Skip to content

Commit

Permalink
fix: rename blob and index client capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed May 23, 2024
1 parent 604d300 commit addfb05
Show file tree
Hide file tree
Showing 22 changed files with 513 additions and 460 deletions.
12 changes: 6 additions & 6 deletions packages/capabilities/src/blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import { equalBlob, equalWith, SpaceDID } from './utils.js'

/**
* Capability can only be delegated (but not invoked) allowing audience to
* derived any `blob/` prefixed capability for the (memory) space identified
* derived any `space/blob/` prefixed capability for the (memory) space identified
* by DID in the `with` field.
*/
export const blob = capability({
can: 'blob/*',
can: 'space/blob/*',
/**
* DID of the (memory) space where Blob is intended to
* be stored.
Expand All @@ -50,13 +50,13 @@ export const content = Schema.struct({
})

/**
* `blob/add` capability allows agent to store a Blob into a (memory) space
* `space/blob/add` capability allows agent to store a Blob into a (memory) space
* identified by did:key in the `with` field. Agent should compute blob multihash
* and size and provide it under `nb.blob` field, allowing a service to provision
* a write location for the agent to PUT desired Blob into.
*/
export const add = capability({
can: 'blob/add',
can: 'space/blob/add',
/**
* DID of the (memory) space where Blob is intended to
* be stored.
Expand All @@ -76,7 +76,7 @@ export const add = capability({
* space identified by `with` field.
*/
export const remove = capability({
can: 'blob/remove',
can: 'space/blob/remove',
/**
* DID of the (memory) space where Blob is stored.
*/
Expand Down Expand Up @@ -111,7 +111,7 @@ export const remove = capability({
* (memory) space identified by `with` field.
*/
export const list = capability({
can: 'blob/list',
can: 'space/blob/list',
/**
* DID of the (memory) space where Blobs to be listed are stored.
*/
Expand Down
8 changes: 4 additions & 4 deletions packages/capabilities/src/index/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ import { equalWith, SpaceDID, and, equal } from '../utils.js'

/**
* Capability can only be delegated (but not invoked) allowing audience to
* derive any `index/` prefixed capability for the space identified by the DID
* derive any `space/index/` prefixed capability for the space identified by the DID
* in the `with` field.
*/
export const index = capability({
can: 'index/*',
can: 'space/index/*',
/** DID of the space where indexed data is stored. */
with: SpaceDID,
derives: equalWith,
})

/**
* `index/add` capability allows an agent to submit verifiable claims
* `space/index/add` capability allows an agent to submit verifiable claims
* about content-addressed data to be published on the InterPlanetary Network
* Indexer (IPNI), making it publicly queryable.
*/
export const add = capability({
can: 'index/add',
can: 'space/index/add',
/** DID of the space where indexed data is stored. */
with: SpaceDID,
nb: Schema.struct({
Expand Down
2 changes: 1 addition & 1 deletion packages/capabilities/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const equalLink = (claimed, delegated) => {
}

/**
* @template {Types.ParsedCapability<"blob/add"|"blob/remove"|"web3.storage/blob/allocate"|"web3.storage/blob/accept", Types.URI<'did:'>, {blob: { digest: Uint8Array, size: number }}>} T
* @template {Types.ParsedCapability<"space/blob/add"|"space/blob/remove"|"web3.storage/blob/allocate"|"web3.storage/blob/accept", Types.URI<'did:'>, {blob: { digest: Uint8Array, size: number }}>} T
* @param {T} claimed
* @param {T} delegated
* @returns {Types.Result<{}, Types.Failure>}
Expand Down
4 changes: 3 additions & 1 deletion packages/filecoin-api/src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ export class UnexpectedPiece extends Error {
}
}

export const UnsupportedCapabilityErrorName = /** @type {const} */ ('UnsupportedCapability')
export const UnsupportedCapabilityErrorName = /** @type {const} */ (
'UnsupportedCapability'
)
export class UnsupportedCapability extends Server.Failure {
/**
* @param {object} source
Expand Down
5 changes: 3 additions & 2 deletions packages/filecoin-api/test/context/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,10 @@ export function getMockService() {
return Server.ok({
piece: invCap.nb.piece,
aggregates: [],
deals: []
deals: [],
})
}})
},
}),
},
deal: {
info: Server.provideAdvanced({
Expand Down
12 changes: 6 additions & 6 deletions packages/filecoin-api/test/context/store-implementations.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ export const getStoreImplementations = (
return undefined
}
return new ReadableStream({
start(controller) {
// Push the data into the stream
controller.enqueue(item)
// Close the stream
controller.close()
}
start(controller) {
// Push the data into the stream
controller.enqueue(item)
// Close the stream
controller.close()
},
})
},
}),
Expand Down
5 changes: 1 addition & 4 deletions packages/filecoin-api/test/services/aggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,7 @@ export const test = {
pieceQueue: new FailingQueue(),
})
),
'piece/accept must be invoked on service did': async (
assert,
context
) => {
'piece/accept must be invoked on service did': async (assert, context) => {
const { agent, storefront } = await getServiceContext(context.id)
const connection = connect({
id: context.id,
Expand Down
95 changes: 48 additions & 47 deletions packages/filecoin-api/test/services/storefront.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { createServer, connect } from '../../src/storefront/service.js'
import {
QueueOperationErrorName,
StoreOperationErrorName,
UnsupportedCapabilityErrorName
UnsupportedCapabilityErrorName,
} from '../../src/errors.js'
import { randomCargo, randomAggregate } from '../utils.js'
import { createInvocationsAndReceiptsForDealDataProofChain } from '../context/receipts.js'
Expand Down Expand Up @@ -242,30 +242,29 @@ export const test = {
pieceStore: getStoreImplementations(FailingStore).storefront.pieceStore,
})
),
'filecoin/submit must be invoked on service did':
async (assert, context) => {
const { agent } = await getServiceContext(context.id)
const connection = connect({
id: context.id,
channel: createServer(context),
})
'filecoin/submit must be invoked on service did': async (assert, context) => {
const { agent } = await getServiceContext(context.id)
const connection = connect({
id: context.id,
channel: createServer(context),
})

// Generate piece for test
const [cargo] = await randomCargo(1, 128)
const filecoinSubmitInv = Filecoin.submit.invoke({
issuer: agent,
audience: connection.id,
with: agent.did(),
nb: {
piece: cargo.link.link(),
content: cargo.content.link(),
},
})
// Generate piece for test
const [cargo] = await randomCargo(1, 128)
const filecoinSubmitInv = Filecoin.submit.invoke({
issuer: agent,
audience: connection.id,
with: agent.did(),
nb: {
piece: cargo.link.link(),
content: cargo.content.link(),
},
})

const response = await filecoinSubmitInv.execute(connection)
assert.ok(response.out.error)
assert.equal(response.out.error?.name, UnsupportedCapabilityErrorName)
},
const response = await filecoinSubmitInv.execute(connection)
assert.ok(response.out.error)
assert.equal(response.out.error?.name, UnsupportedCapabilityErrorName)
},
'filecoin/submit inserts piece into piece offer queue and returns effect':
async (assert, context) => {
const { storefront } = await getServiceContext(context.id)
Expand Down Expand Up @@ -344,7 +343,9 @@ export const test = {
assert,
context
) => {
const { storefront, aggregator, dealer } = await getServiceContext(context.id)
const { storefront, aggregator, dealer } = await getServiceContext(
context.id
)
const group = context.id.did()
const connection = connect({
id: context.id,
Expand Down Expand Up @@ -452,30 +453,29 @@ export const test = {
BigInt(dealMetadata.dataSource.dealID)
)
},
'filecoin/accept must be invoked on service did':
async (assert, context) => {
const { agent } = await getServiceContext(context.id)
const connection = connect({
id: context.id,
channel: createServer(context),
})
'filecoin/accept must be invoked on service did': async (assert, context) => {
const { agent } = await getServiceContext(context.id)
const connection = connect({
id: context.id,
channel: createServer(context),
})

// Generate piece for test
const [cargo] = await randomCargo(1, 128)
const filecoinSubmitInv = Filecoin.accept.invoke({
issuer: agent,
audience: connection.id,
with: agent.did(),
nb: {
piece: cargo.link.link(),
content: cargo.content.link(),
},
})
// Generate piece for test
const [cargo] = await randomCargo(1, 128)
const filecoinSubmitInv = Filecoin.accept.invoke({
issuer: agent,
audience: connection.id,
with: agent.did(),
nb: {
piece: cargo.link.link(),
content: cargo.content.link(),
},
})

const response = await filecoinSubmitInv.execute(connection)
assert.ok(response.out.error)
assert.equal(response.out.error?.name, UnsupportedCapabilityErrorName)
},
const response = await filecoinSubmitInv.execute(connection)
assert.ok(response.out.error)
assert.equal(response.out.error?.name, UnsupportedCapabilityErrorName)
},
'filecoin/accept fails if fails to read from piece store':
wichMockableContext(
async (assert, context) => {
Expand Down Expand Up @@ -509,7 +509,8 @@ export const test = {
'filecoin/info gets aggregate where piece was included together with deals and inclusion proof':
wichMockableContext(
async (assert, context) => {
const { agent, storefront, aggregator, dealer } = await getServiceContext(context.id)
const { agent, storefront, aggregator, dealer } =
await getServiceContext(context.id)
const group = context.id.did()
const connection = connect({
id: context.id,
Expand Down
12 changes: 4 additions & 8 deletions packages/filecoin-api/test/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import type {
Signer,
Result,
Unit,
UnknownLink
} from '@ucanto/interface'
import type { Signer, Result, Unit, UnknownLink } from '@ucanto/interface'
import * as AggregatorInterface from '../src/aggregator/api.js'
import * as DealerInterface from '../src/dealer/api.js'
import * as StorefrontInterface from '../src/storefront/api.js'
Expand Down Expand Up @@ -61,9 +56,10 @@ export interface StorefrontTestEventsContext
}>
}

export interface TestContentStore<RecKey, Rec> extends StorefrontInterface.ContentStore<RecKey, Rec> {
export interface TestContentStore<RecKey, Rec>
extends StorefrontInterface.ContentStore<RecKey, Rec> {
/**
* Puts a record in the store.
*/
put: (record: Rec) => Promise<Result<Unit, StorePutError>>
}
}
4 changes: 0 additions & 4 deletions packages/upload-api/src/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import * as Types from './types.js'
import * as Legacy from '@ucanto/transport/legacy'
import * as CAR from '@ucanto/transport/car'
import { create as createRevocationChecker } from './utils/revocation.js'
import { createService as createBlobService } from './blob.js'
import { createService as createStoreService } from './store.js'
import { createService as createUploadService } from './upload.js'
import { createService as createConsoleService } from './console.js'
import { createService as createAccessService } from './access.js'
import { createService as createConsumerService } from './consumer.js'
import { createService as createCustomerService } from './customer.js'
import { createService as createSpaceService } from './space.js'
import { createService as createIndexService } from './index.js'
import { createService as createProviderService } from './provider.js'
import { createService as createSubscriptionService } from './subscription.js'
import { createService as createAdminService } from './admin.js'
Expand Down Expand Up @@ -160,11 +158,9 @@ export const run = async (agent, invocation) => {
*/
export const createService = (context) => ({
access: createAccessService(context),
blob: createBlobService(context),
console: createConsoleService(context),
consumer: createConsumerService(context),
customer: createCustomerService(context),
index: createIndexService(context),
provider: createProviderService(context),
'rate-limit': createRateLimitService(context),
admin: createAdminService(context),
Expand Down
48 changes: 6 additions & 42 deletions packages/upload-api/src/space.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,16 @@
import { Space } from '@web3-storage/capabilities'
import { DID } from '@ucanto/validator'
import * as Provider from '@ucanto/server'
import * as API from './types.js'

/**
* @param {API.Input<Space.info>} input
* @param {API.SpaceServiceContext} ctx
* @returns {Promise<API.Result<API.SpaceInfoSuccess, API.SpaceInfoFailure>>}
*/
export const info = async ({ capability }, ctx) => {
const { provisionsStorage: provisions } = ctx

const spaceDid = capability.with
if (!DID.match({ method: 'key' }).is(spaceDid)) {
/** @type {API.SpaceUnknown} */
const unexpectedSpaceDidFailure = {
name: 'SpaceUnknown',
message: `can only get info for did:key spaces`,
}
return {
error: unexpectedSpaceDidFailure,
}
}

const result = await provisions.getStorageProviders(spaceDid)
const providers = result.ok
if (providers && providers.length > 0) {
return {
ok: {
did: spaceDid,
providers,
},
}
}

/** @type {import('@web3-storage/access/types').SpaceUnknown} */
const spaceUnknownFailure = {
name: 'SpaceUnknown',
message: `Space not found.`,
}
return {
error: spaceUnknownFailure,
}
}
import { info } from './space/info.js'
import { createService as createBlobService } from './blob.js'
import { createService as createIndexService } from './index.js'

/**
* @param {API.SpaceServiceContext} ctx
* @param {API.SpaceServiceContext & API.BlobServiceContext & API.IndexServiceContext} ctx
*/
export const createService = (ctx) => ({
info: Provider.provide(Space.info, (input) => info(input, ctx)),
blob: createBlobService(ctx),
index: createIndexService(ctx),
})
Loading

0 comments on commit addfb05

Please sign in to comment.