From e9af60b986179f8fd72f836d59ee40ce41b37c03 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Wed, 4 Oct 2023 12:40:10 +0100 Subject: [PATCH 01/12] feat: add `store/get` and `upload/get` capabilities License: MIT Signed-off-by: Oli Evans --- packages/capabilities/src/store.js | 22 ++++++++++++++++++++ packages/capabilities/src/upload.js | 32 +++++++++++++++++++++++++++++ packages/capabilities/src/utils.js | 2 +- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packages/capabilities/src/store.js b/packages/capabilities/src/store.js index 8995467d0..8ce823a93 100644 --- a/packages/capabilities/src/store.js +++ b/packages/capabilities/src/store.js @@ -77,6 +77,28 @@ export const add = capability({ }, }) +/** + * Capability to get store metadata by shard CID. + * Use to check for inclusion, or get shard size and origin + * + * `nb.link` is optional to allow delegation of `store/get` + * capability for any shard cid. If link is specified, then the + * capability only allows a get for that single cid. + * + * When used as as an invocation, `nb.link` should be specified. + */ +export const get = capability({ + can: 'store/get', + with: SpaceDID, + nb: Schema.struct({ + /** + * shard CID to fetch info about. + */ + link: Link.optional() + }), + derives: equalLink +}) + /** * Capability can be used to remove the stored CAR file from the (memory) * space identified by `with` field. diff --git a/packages/capabilities/src/upload.js b/packages/capabilities/src/upload.js index 794b04fdd..cbcf5c142 100644 --- a/packages/capabilities/src/upload.js +++ b/packages/capabilities/src/upload.js @@ -77,6 +77,38 @@ export const add = capability({ }, }) +/** + * Capability to get upload metadata by root CID. + * Use to check for inclusion, or find the shards for a root. + * + * `nb.root` is optional to allow delegation of `upload/get` + * capability for any root. If root is specified, then the + * capability only allows a get for that single cid. + * + * When used as as an invocation, `nb.root` should be specified. + */ +export const get = capability({ + can: 'upload/get', + with: SpaceDID, + nb: Schema.struct({ + /** + * Root CID of the DAG to fetch upload info about. + */ + root: Link.optional() + }), + derives: (self, from) => { + const res = equalWith(self, from) + if (res.error) { + return res + } + if (!from.nb.root) { + return res + } + // root must match if specified in the proof + return equal(self.nb.root, from.nb.root, 'root') + } +}) + /** * Capability removes an upload (identified by it's root CID) from the upload * list. Please note that removing an upload does not delete corresponding shards diff --git a/packages/capabilities/src/utils.js b/packages/capabilities/src/utils.js index 3b12142fb..c149c6cfb 100644 --- a/packages/capabilities/src/utils.js +++ b/packages/capabilities/src/utils.js @@ -60,7 +60,7 @@ export function equal(child, parent, constraint) { } /** - * @template {Types.ParsedCapability<"store/add"|"store/remove", Types.URI<'did:'>, {link?: Types.Link}>} T + * @template {Types.ParsedCapability<"store/add"|"store/get"|"store/remove", Types.URI<'did:'>, {link?: Types.Link}>} T * @param {T} claimed * @param {T} delegated * @returns {Types.Result<{}, Types.Failure>} From 87a4c74cd0b9948bfcc9712062eeff8664aba975 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Wed, 4 Oct 2023 13:46:42 +0100 Subject: [PATCH 02/12] chore: format License: MIT Signed-off-by: Oli Evans --- packages/capabilities/src/store.js | 10 +++++----- packages/capabilities/src/upload.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/capabilities/src/store.js b/packages/capabilities/src/store.js index 8ce823a93..442f1984b 100644 --- a/packages/capabilities/src/store.js +++ b/packages/capabilities/src/store.js @@ -80,11 +80,11 @@ export const add = capability({ /** * Capability to get store metadata by shard CID. * Use to check for inclusion, or get shard size and origin - * - * `nb.link` is optional to allow delegation of `store/get` + * + * `nb.link` is optional to allow delegation of `store/get` * capability for any shard cid. If link is specified, then the * capability only allows a get for that single cid. - * + * * When used as as an invocation, `nb.link` should be specified. */ export const get = capability({ @@ -94,9 +94,9 @@ export const get = capability({ /** * shard CID to fetch info about. */ - link: Link.optional() + link: Link.optional(), }), - derives: equalLink + derives: equalLink, }) /** diff --git a/packages/capabilities/src/upload.js b/packages/capabilities/src/upload.js index cbcf5c142..d1ce85d50 100644 --- a/packages/capabilities/src/upload.js +++ b/packages/capabilities/src/upload.js @@ -80,11 +80,11 @@ export const add = capability({ /** * Capability to get upload metadata by root CID. * Use to check for inclusion, or find the shards for a root. - * - * `nb.root` is optional to allow delegation of `upload/get` + * + * `nb.root` is optional to allow delegation of `upload/get` * capability for any root. If root is specified, then the * capability only allows a get for that single cid. - * + * * When used as as an invocation, `nb.root` should be specified. */ export const get = capability({ @@ -94,7 +94,7 @@ export const get = capability({ /** * Root CID of the DAG to fetch upload info about. */ - root: Link.optional() + root: Link.optional(), }), derives: (self, from) => { const res = equalWith(self, from) @@ -106,7 +106,7 @@ export const get = capability({ } // root must match if specified in the proof return equal(self.nb.root, from.nb.root, 'root') - } + }, }) /** From 8e6459c9dc80f36d07bd13e26f05c254fad9cdf2 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Fri, 13 Oct 2023 16:02:27 +0100 Subject: [PATCH 03/12] feat: `store/get` & `upload/get` capabilities License: MIT Signed-off-by: Oli Evans --- packages/capabilities/src/store.js | 2 +- packages/capabilities/src/types.ts | 26 ++++-- packages/capabilities/src/upload.js | 2 +- packages/upload-api/src/store.js | 2 + packages/upload-api/src/store/get.js | 29 ++++++ packages/upload-api/src/types.ts | 56 +++++++----- packages/upload-api/src/upload.js | 2 + packages/upload-api/src/upload/get.js | 29 ++++++ packages/upload-api/test/handlers/store.js | 90 ++++++++++++++++++- packages/upload-api/test/handlers/upload.js | 75 ++++++++++++++++ .../upload-api/test/storage/store-table.js | 10 +-- .../upload-api/test/storage/upload-table.js | 2 +- 12 files changed, 289 insertions(+), 36 deletions(-) create mode 100644 packages/upload-api/src/store/get.js create mode 100644 packages/upload-api/src/upload/get.js diff --git a/packages/capabilities/src/store.js b/packages/capabilities/src/store.js index 442f1984b..1c85cafa2 100644 --- a/packages/capabilities/src/store.js +++ b/packages/capabilities/src/store.js @@ -85,7 +85,7 @@ export const add = capability({ * capability for any shard cid. If link is specified, then the * capability only allows a get for that single cid. * - * When used as as an invocation, `nb.link` should be specified. + * When used as as an invocation, `nb.link` must be specified. */ export const get = capability({ can: 'store/get', diff --git a/packages/capabilities/src/types.ts b/packages/capabilities/src/types.ts index 7d737bd2e..928d4f62e 100644 --- a/packages/capabilities/src/types.ts +++ b/packages/capabilities/src/types.ts @@ -6,7 +6,7 @@ import type { PieceLink } from '@web3-storage/data-segment' import { space, info } from './space.js' import * as provider from './provider.js' import { top } from './top.js' -import { add, list, remove, store } from './store.js' +import * as StoreCaps from './store.js' import * as UploadCaps from './upload.js' import * as AccessCaps from './access.js' import * as CustomerCaps from './customer.js' @@ -206,13 +206,27 @@ export interface ChainTrackerInfoFailure extends Ucanto.Failure { // Upload export type Upload = InferInvokedCapability export type UploadAdd = InferInvokedCapability +export type UploadGet = InferInvokedCapability export type UploadRemove = InferInvokedCapability export type UploadList = InferInvokedCapability + +export interface UploadNotFound extends Ucanto.Failure { + name: 'UploadNotFound' +} +export type UploadGetFailure = UploadNotFound | Ucanto.Failure + // Store -export type Store = InferInvokedCapability -export type StoreAdd = InferInvokedCapability -export type StoreRemove = InferInvokedCapability -export type StoreList = InferInvokedCapability +export type Store = InferInvokedCapability +export type StoreAdd = InferInvokedCapability +export type StoreGet = InferInvokedCapability +export type StoreRemove = InferInvokedCapability +export type StoreList = InferInvokedCapability + +export interface ShardNotFound extends Ucanto.Failure { + name: 'ShardNotFound' +} +export type StoreGetFailure = ShardNotFound | Ucanto.Failure + // Admin export type Admin = InferInvokedCapability export type AdminUploadInspect = InferInvokedCapability< @@ -263,10 +277,12 @@ export type AbilitiesArray = [ SpaceInfo['can'], Upload['can'], UploadAdd['can'], + UploadGet['can'], UploadRemove['can'], UploadList['can'], Store['can'], StoreAdd['can'], + StoreGet['can'], StoreRemove['can'], StoreList['can'], Access['can'], diff --git a/packages/capabilities/src/upload.js b/packages/capabilities/src/upload.js index d1ce85d50..e35b5c631 100644 --- a/packages/capabilities/src/upload.js +++ b/packages/capabilities/src/upload.js @@ -85,7 +85,7 @@ export const add = capability({ * capability for any root. If root is specified, then the * capability only allows a get for that single cid. * - * When used as as an invocation, `nb.root` should be specified. + * When used as as an invocation, `nb.root` must be specified. */ export const get = capability({ can: 'upload/get', diff --git a/packages/upload-api/src/store.js b/packages/upload-api/src/store.js index 0461fde34..146bcf09c 100644 --- a/packages/upload-api/src/store.js +++ b/packages/upload-api/src/store.js @@ -1,4 +1,5 @@ import { storeAddProvider } from './store/add.js' +import { storeGetProvider } from './store/get.js' import { storeListProvider } from './store/list.js' import { storeRemoveProvider } from './store/remove.js' import * as API from './types.js' @@ -9,6 +10,7 @@ import * as API from './types.js' export function createService(context) { return { add: storeAddProvider(context), + get: storeGetProvider(context), list: storeListProvider(context), remove: storeRemoveProvider(context), } diff --git a/packages/upload-api/src/store/get.js b/packages/upload-api/src/store/get.js new file mode 100644 index 000000000..2fddbd246 --- /dev/null +++ b/packages/upload-api/src/store/get.js @@ -0,0 +1,29 @@ +import * as Server from '@ucanto/server' +import * as Store from '@web3-storage/capabilities/store' +import * as API from '../types.js' + +/** + * @param {API.StoreServiceContext} context + * @returns {API.ServiceMethod} + */ +export function storeGetProvider(context) { + return Server.provide(Store.get, async ({ capability }) => { + const { link } = capability.nb + if (!link) { + return Server.fail('nb.link must be set') + } + const space = Server.DID.parse(capability.with).did() + const res = await context.storeTable.get(space, link) + if (!res) { + return { + error: { + name: 'ShardNotFound', + message: 'Shard not found' + } + } + } + return { + ok: res + } + }) +} diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 9604f29d2..0ed877f76 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -51,9 +51,11 @@ export interface DebugEmail extends Email { import { StoreAdd, + StoreGet, StoreRemove, StoreList, UploadAdd, + UploadGet, UploadRemove, UploadList, AccessAuthorize, @@ -99,6 +101,8 @@ import { ProviderAddFailure, SpaceInfo, ProviderDID, + StoreGetFailure, + UploadGetFailure, } from '@web3-storage/capabilities/types' import * as Capabilities from '@web3-storage/capabilities' @@ -115,12 +119,14 @@ export type { RateLimitsStorage, RateLimit } from './types/rate-limits' export interface Service { store: { add: ServiceMethod + get: ServiceMethod remove: ServiceMethod list: ServiceMethod } upload: { add: ServiceMethod - remove: ServiceMethod + get: ServiceMethod + remove: ServiceMethod list: ServiceMethod } console: { @@ -292,9 +298,7 @@ export interface UcantoServerTestContext fetch: typeof fetch } -export interface StoreTestContext { - testStoreTable: TestStoreTable -} +export interface StoreTestContext {} export interface UploadTestContext {} @@ -334,7 +338,7 @@ export interface DudewhereBucket { } export interface StoreTable { - inspect: (link: UnknownLink) => Promise + inspect: (link: UnknownLink) => Promise exists: (space: DID, link: UnknownLink) => Promise insert: (item: StoreAddInput) => Promise remove: (space: DID, link: UnknownLink) => Promise @@ -342,17 +346,14 @@ export interface StoreTable { space: DID, options?: ListOptions ) => Promise> -} - -export interface TestStoreTable { get( space: DID, link: UnknownLink - ): Promise<(StoreAddInput & StoreListItem) | undefined> + ): Promise<(StoreGetItem) | undefined> } export interface UploadTable { - inspect: (link: UnknownLink) => Promise + inspect: (link: UnknownLink) => Promise exists: (space: DID, root: UnknownLink) => Promise insert: (item: UploadAddInput) => Promise remove: (space: DID, root: UnknownLink) => Promise @@ -360,6 +361,10 @@ export interface UploadTable { space: DID, options?: ListOptions ) => Promise> + get( + space: DID, + link: UnknownLink + ): Promise<(UploadGetItem) | undefined> } export type SpaceInfoSuccess = { @@ -394,19 +399,25 @@ export interface StoreAddInput { invocation: UCANLink } +export interface StoreMetadata { + insertedAt: string +} + export interface StoreAddOutput extends Omit {} -export interface StoreGetOk { +export interface StoreInspectOk { spaces: Array<{ did: DID; insertedAt: string }> } -export interface StoreListItem extends StoreAddOutput { - insertedAt: string -} +export type StoreListItem = StoreAddOutput & StoreMetadata + +export type StoreGetItem = StoreAddInput & StoreMetadata export interface StoreListOk extends ListResponse {} +export type StoreGetOk = StoreGetItem + export type StoreAddOk = StoreAddDone | StoreAddUpload export interface StoreAddDone { @@ -433,27 +444,32 @@ export interface UploadAddInput { invocation: UCANLink } +export interface UploadMetadata { + insertedAt: string + updatedAt: string +} + export interface UploadAddOk extends Omit {} export type UploadRemoveOk = UploadDIDRemove | UploadDidNotRemove +export type UploadListItem = UploadAddOk & UploadMetadata +export type UploadGetItem = UploadAddInput & UploadMetadata + export interface UploadDIDRemove extends UploadAddOk {} export interface UploadDidNotRemove { root?: undefined shards?: undefined } -export interface UploadGetOk { +export interface UploadInspectOk { spaces: Array<{ did: DID; insertedAt: string }> } -export interface UploadListItem extends UploadAddOk { - insertedAt: string - updatedAt: string -} - export interface UploadListOk extends ListResponse {} +export interface UploadGetOk extends UploadGetItem {} + export interface ListOptions { size?: number cursor?: string diff --git a/packages/upload-api/src/upload.js b/packages/upload-api/src/upload.js index cbb6be515..693fa0644 100644 --- a/packages/upload-api/src/upload.js +++ b/packages/upload-api/src/upload.js @@ -1,4 +1,5 @@ import { uploadAddProvider } from './upload/add.js' +import { uploadGetProvider } from './upload/get.js' import { uploadListProvider } from './upload/list.js' import { uploadRemoveProvider } from './upload/remove.js' import * as API from './types.js' @@ -9,6 +10,7 @@ import * as API from './types.js' export function createService(context) { return { add: uploadAddProvider(context), + get: uploadGetProvider(context), list: uploadListProvider(context), remove: uploadRemoveProvider(context), } diff --git a/packages/upload-api/src/upload/get.js b/packages/upload-api/src/upload/get.js new file mode 100644 index 000000000..0a5537e25 --- /dev/null +++ b/packages/upload-api/src/upload/get.js @@ -0,0 +1,29 @@ +import * as Server from '@ucanto/server' +import * as Upload from '@web3-storage/capabilities/upload' +import * as API from '../types.js' + +/** + * @param {API.UploadServiceContext} context + * @returns {API.ServiceMethod} + */ +export function uploadGetProvider(context) { + return Server.provide(Upload.get, async ({ capability }) => { + const { root } = capability.nb + if (!root) { + return Server.fail('nb.root must be set') + } + const space = Server.DID.parse(capability.with).did() + const res = await context.uploadTable.get(space, root) + if (!res) { + return { + error: { + name: 'UploadNotFound', + message: 'Upload not found' + } + } + } + return { + ok: res + } + }) +} diff --git a/packages/upload-api/test/handlers/store.js b/packages/upload-api/test/handlers/store.js index d3dcd9672..77482e432 100644 --- a/packages/upload-api/test/handlers/store.js +++ b/packages/upload-api/test/handlers/store.js @@ -73,7 +73,7 @@ export const test = { assert.equal(goodPut.status, 200, await goodPut.text()) - const item = await context.testStoreTable.get(spaceDid, link) + const item = await context.storeTable.get(spaceDid, link) if (!item) { return assert.equal(item != null, true) @@ -298,7 +298,7 @@ export const test = { assert.deepEqual(storeAdd.out.ok.link.toString(), link.toString()) assert.equal(storeAdd.out.ok.url == null, true) - const item = await context.testStoreTable.get(spaceDid, link) + const item = await context.storeTable.get(spaceDid, link) if (!item) { throw assert.equal(item != null, true, 'should have stored item') } @@ -706,4 +706,88 @@ export const test = { assert.deepEqual(prevListResponse.out.ok.before, listResponse.out.ok.before) assert.deepEqual(prevListResponse.out.ok.after, listResponse.out.ok.after) }, -} + + 'store/get returns shard info': async ( + assert, + context + ) => { + const { proof, spaceDid } = await registerSpace(alice, context) + const connection = connect({ + id: context.id, + channel: createServer(context), + }) + + const data = [ + new Uint8Array([11, 22, 34, 44, 55]), + new Uint8Array([22, 34, 44, 55, 66]), + ] + const links = [] + for (const datum of data) { + const storeAdd = await StoreCapabilities.add + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + nb: { link: await CAR.codec.link(datum), size: datum.byteLength }, + proofs: [proof], + }) + .execute(connection) + + if (storeAdd.out.error) { + throw new Error('invocation failed', { cause: storeAdd }) + } + + assert.equal(storeAdd.out.ok.status, 'upload') + links.push(storeAdd.out.ok.link) + } + + const storeGet = await StoreCapabilities.get + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + proofs: [proof], + nb: { + link: links[0] + }, + }) + .execute(connection) + + if (storeGet.out.error) { + throw new Error('invocation failed', { cause: storeGet }) + } + + assert.deepEqual(storeGet.out.ok.link, links[0]) + assert.equal(storeGet.out.ok.size, data[0].byteLength) + assert.equal(storeGet.out.ok.space, spaceDid) + assert.ok(storeGet.out.ok.insertedAt) + }, + + 'store/get returns ShardNotFound Failure': async ( + assert, + context + ) => { + const { proof, spaceDid } = await registerSpace(alice, context) + const connection = connect({ + id: context.id, + channel: createServer(context), + }) + + const link = await CAR.codec.link(new Uint8Array([11, 22, 34, 44, 55])) + + const storeGet = await StoreCapabilities.get + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + proofs: [proof], + nb: { + link + }, + }) + .execute(connection) + + assert.ok(storeGet.out.error) + assert.equal(storeGet.out.error?.name, 'ShardNotFound') + }, +} \ No newline at end of file diff --git a/packages/upload-api/test/handlers/upload.js b/packages/upload-api/test/handlers/upload.js index 7a11e94ae..5e8055435 100644 --- a/packages/upload-api/test/handlers/upload.js +++ b/packages/upload-api/test/handlers/upload.js @@ -9,6 +9,7 @@ import { } from '../util.js' import { createServer, connect } from '../../src/lib.js' import { Upload } from '@web3-storage/capabilities' +import { uploadListProvider } from '../../src/upload/list.js' // https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/batchwriteitemcommand.html const BATCH_MAX_SAFE_LIMIT = 25 @@ -859,4 +860,78 @@ export const test = { 'mentions passed audience' ) }, + + 'upload/get returns info for one upload': async ( + assert, + context + ) => { + const { proof, spaceDid } = await registerSpace(alice, context) + const connection = connect({ + id: context.id, + channel: createServer(context), + }) + + // invoke multiple upload/add with proof + const cars = [await randomCAR(128), await randomCAR(128)] + + for (const car of cars) { + await Upload.add + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + nb: { root: car.roots[0], shards: [car.cid] }, + proofs: [proof], + }) + .execute(connection) + } + + const uploadGet = await Upload.get + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + proofs: [proof], + nb: { + root: cars[0].roots[0] + }, + }) + .execute(connection) + + if (!uploadGet.out.ok) { + throw new Error('invocation failed', { cause: uploadGet }) + } + + assert.equal(uploadGet.out.ok.issuer, alice.toDIDKey()) + assert.equal(uploadGet.out.ok.space, spaceDid) + assert.equal(uploadGet.out.ok.shards?.[0].toString(), cars[0].cid.toString()) + assert.equal(uploadGet.out.ok.root.toString(), cars[0].roots[0].toString()) + }, + + 'upload/get returns UploadNotFound when root is not in uploads': async ( + assert, + context + ) => { + const { proof, spaceDid } = await registerSpace(alice, context) + const connection = connect({ + id: context.id, + channel: createServer(context), + }) + + const car = await randomCAR(128) + + const uploadGet = await Upload.get + .invoke({ + issuer: alice, + audience: connection.id, + with: spaceDid, + proofs: [proof], + nb: { + root: car.roots[0] + }, + }) + .execute(connection) + + assert.equal(uploadGet.out.error?.name, 'UploadNotFound') + }, } diff --git a/packages/upload-api/test/storage/store-table.js b/packages/upload-api/test/storage/store-table.js index 9dcc62fe5..09fc0728c 100644 --- a/packages/upload-api/test/storage/store-table.js +++ b/packages/upload-api/test/storage/store-table.js @@ -2,17 +2,16 @@ import * as API from '../../src/types.js' /** * @implements {API.StoreTable} - * @implements {API.TestStoreTable} */ export class StoreTable { constructor() { - /** @type {(API.StoreAddInput & API.StoreListItem)[]} */ + /** @type {(API.StoreGetItem)[]} */ this.items = [] } /** * @param {API.StoreAddInput} input - * @returns + * @returns {Promise} */ async insert({ space, issuer, invocation, ...output }) { this.items.unshift({ @@ -28,7 +27,7 @@ export class StoreTable { /** * * @param {API.UnknownLink} link - * @returns {Promise} + * @returns {Promise} */ async inspect(link) { const items = @@ -43,9 +42,10 @@ export class StoreTable { } /** - * + * Get info for a single shard or undefined if it doesn't exist * @param {API.DID} space * @param {API.UnknownLink} link + * @returns {Promise} */ async get(space, link) { return this.items.find( diff --git a/packages/upload-api/test/storage/upload-table.js b/packages/upload-api/test/storage/upload-table.js index 79a46ded9..fabcc0072 100644 --- a/packages/upload-api/test/storage/upload-table.js +++ b/packages/upload-api/test/storage/upload-table.js @@ -13,7 +13,7 @@ export class UploadTable { /** * * @param {API.UnknownLink} link - * @returns {Promise} + * @returns {Promise} */ async inspect(link) { const items = From abb005850b08a92d24048eabf48519bd3a06e931 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 17 Oct 2023 11:02:52 +0100 Subject: [PATCH 04/12] chore: add new caps to abilitiesAsStrings License: MIT Signed-off-by: Oli Evans --- packages/capabilities/src/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/capabilities/src/index.js b/packages/capabilities/src/index.js index 92222702a..a18071e59 100644 --- a/packages/capabilities/src/index.js +++ b/packages/capabilities/src/index.js @@ -40,10 +40,12 @@ export const abilitiesAsStrings = [ Space.info.can, Upload.upload.can, Upload.add.can, + Upload.get.can, Upload.remove.can, Upload.list.can, Store.store.can, Store.add.can, + Store.get.can, Store.remove.can, Store.list.can, Access.access.can, From 17a093a4668d37df4ccc5ec8ff54350581552638 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 17 Oct 2023 14:48:02 +0100 Subject: [PATCH 05/12] chore: fix tests License: MIT Signed-off-by: Oli Evans --- packages/capabilities/src/types.ts | 14 +++- packages/upload-api/src/store/get.js | 2 +- packages/upload-api/src/types.ts | 72 +++---------------- packages/upload-api/src/upload/get.js | 2 +- packages/upload-api/test/handlers/store.js | 7 -- packages/upload-api/test/handlers/upload.js | 3 - packages/upload-api/test/helpers/context.js | 1 - .../upload-api/test/storage/store-table.js | 4 +- packages/upload-client/src/types.ts | 8 +++ packages/upload-client/test/helpers/mocks.js | 2 + packages/upload-client/test/store.test.js | 3 + packages/upload-client/test/upload.test.js | 6 ++ .../w3up-client/test/capability/store.test.js | 1 + .../test/capability/upload.test.js | 2 + 14 files changed, 45 insertions(+), 82 deletions(-) diff --git a/packages/capabilities/src/types.ts b/packages/capabilities/src/types.ts index 73b3b5c20..0eaf329b2 100644 --- a/packages/capabilities/src/types.ts +++ b/packages/capabilities/src/types.ts @@ -265,6 +265,8 @@ export interface StoreItemNotFound extends Ucanto.Failure { export type StoreRemoveFailure = StoreItemNotFound | Ucanto.Failure +export type StoreGetSuccess = StoreListItem + export type StoreGetFailure = StoreItemNotFound | Ucanto.Failure export interface StoreListSuccess extends ListResponse {} @@ -281,13 +283,21 @@ export interface StoreListItem { link: UnknownLink size: number origin?: UnknownLink + insertedAt: string } -export interface UploadAddSuccess { +export interface UploadListItem { root: UnknownLink shards?: CARLink[] + insertedAt: string + updatedAt: string } +// TODO: (olizilla) make this an UploadListItem too? +export type UploadAddSuccess = Omit + +export type UploadGetSuccess = UploadListItem + export type UploadRemoveSuccess = UploadDidRemove | UploadDidNotRemove export interface UploadDidRemove extends UploadAddSuccess {} @@ -299,8 +309,6 @@ export interface UploadDidNotRemove { export interface UploadListSuccess extends ListResponse {} -export interface UploadListItem extends UploadAddSuccess {} - // UCAN core events export type UCANRevoke = InferInvokedCapability diff --git a/packages/upload-api/src/store/get.js b/packages/upload-api/src/store/get.js index 2fddbd246..6ea8baca4 100644 --- a/packages/upload-api/src/store/get.js +++ b/packages/upload-api/src/store/get.js @@ -4,7 +4,7 @@ import * as API from '../types.js' /** * @param {API.StoreServiceContext} context - * @returns {API.ServiceMethod} + * @returns {API.ServiceMethod} */ export function storeGetProvider(context) { return Server.provide(Store.get, async ({ capability }) => { diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 776de8737..7d23c7750 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -123,6 +123,8 @@ import { UCANRevoke, ListResponse, CARLink, + StoreGetSuccess, + UploadGetSuccess, } from '@web3-storage/capabilities/types' import * as Capabilities from '@web3-storage/capabilities' import { RevocationsStorage } from './types/revocations' @@ -146,13 +148,13 @@ export type { RateLimitsStorage, RateLimit } from './types/rate-limits' export interface Service { store: { add: ServiceMethod - get: ServiceMethod + get: ServiceMethod remove: ServiceMethod list: ServiceMethod } upload: { add: ServiceMethod - get: ServiceMethod + get: ServiceMethod remove: ServiceMethod list: ServiceMethod } @@ -383,13 +385,8 @@ export interface StoreTable { list: ( space: DID, options?: ListOptions - ) => Promise< - (StoreAddInput & StoreListItem & { insertedAt: string }) | undefined - > - get( - space: DID, - link: UnknownLink - ): Promise<(StoreGetItem) | undefined> + ) => Promise> + get: (space: DID,link: UnknownLink) => Promise<(StoreListItem) | undefined> } export interface UploadTable { @@ -400,13 +397,8 @@ export interface UploadTable { list: ( space: DID, options?: ListOptions - ) => Promise< - ListResponse - > - get( - space: DID, - link: UnknownLink - ): Promise<(UploadGetItem) | undefined> + ) => Promise> + get: (space: DID,link: UnknownLink) => Promise<(UploadListItem) | undefined> } export type SpaceInfoSuccess = { @@ -452,32 +444,6 @@ export interface StoreInspectOk { spaces: Array<{ did: DID; insertedAt: string }> } -export type StoreListItem = StoreAddOutput & StoreMetadata - -export type StoreGetItem = StoreAddInput & StoreMetadata - -export interface StoreListOk extends ListResponse {} - -export type StoreGetOk = StoreGetItem - -export type StoreAddOk = StoreAddDone | StoreAddUpload - -export interface StoreAddDone { - status: 'done' - with: DID - link: UnknownLink - url?: undefined - headers?: undefined -} - -export interface StoreAddUpload { - status: 'upload' - with: DID - link: UnknownLink - url: URL - headers: Record -} - export interface UploadAddInput { space: DID root: UnknownLink @@ -486,32 +452,10 @@ export interface UploadAddInput { invocation: UCANLink } -export interface UploadMetadata { - insertedAt: string - updatedAt: string -} - -export interface UploadAddOk - extends Omit {} -export type UploadRemoveOk = UploadDIDRemove | UploadDidNotRemove - -export type UploadListItem = UploadAddOk & UploadMetadata -export type UploadGetItem = UploadAddInput & UploadMetadata - -export interface UploadDIDRemove extends UploadAddOk {} -export interface UploadDidNotRemove { - root?: undefined - shards?: undefined -} - export interface UploadInspectOk { spaces: Array<{ did: DID; insertedAt: string }> } -export interface UploadListOk extends ListResponse {} - -export interface UploadGetOk extends UploadGetItem {} - export interface ListOptions { size?: number cursor?: string diff --git a/packages/upload-api/src/upload/get.js b/packages/upload-api/src/upload/get.js index 0a5537e25..e113f0358 100644 --- a/packages/upload-api/src/upload/get.js +++ b/packages/upload-api/src/upload/get.js @@ -4,7 +4,7 @@ import * as API from '../types.js' /** * @param {API.UploadServiceContext} context - * @returns {API.ServiceMethod} + * @returns {API.ServiceMethod} */ export function uploadGetProvider(context) { return Server.provide(Upload.get, async ({ capability }) => { diff --git a/packages/upload-api/test/handlers/store.js b/packages/upload-api/test/handlers/store.js index 43ce5a08f..24534f446 100644 --- a/packages/upload-api/test/handlers/store.js +++ b/packages/upload-api/test/handlers/store.js @@ -1,6 +1,5 @@ import { createServer, connect } from '../../src/lib.js' import * as API from '../../src/types.js' -import { CID } from 'multiformats' import * as CAR from '@ucanto/transport/car' import { base64pad } from 'multiformats/bases/base64' import * as StoreCapabilities from '@web3-storage/capabilities/store' @@ -80,10 +79,8 @@ export const test = { assert.deepEqual( { - space: item.space, link: item.link.toString(), size: item.size, - issuer: item.issuer, }, { space: spaceDid, @@ -93,7 +90,6 @@ export const test = { } ) - assert.equal(CID.parse(item.invocation.toString()) != null, true) assert.equal( Date.now() - new Date(item?.insertedAt).getTime() < 60_000, true @@ -304,10 +300,8 @@ export const test = { assert.deepEqual( { - space: item.space, link: item.link.toString(), size: item.size, - issuer: item.issuer, }, { space: spaceDid, @@ -739,7 +733,6 @@ export const test = { assert.deepEqual(storeGet.out.ok.link, links[0]) assert.equal(storeGet.out.ok.size, data[0].byteLength) - assert.equal(storeGet.out.ok.space, spaceDid) assert.ok(storeGet.out.ok.insertedAt) }, diff --git a/packages/upload-api/test/handlers/upload.js b/packages/upload-api/test/handlers/upload.js index 842096958..34f764be6 100644 --- a/packages/upload-api/test/handlers/upload.js +++ b/packages/upload-api/test/handlers/upload.js @@ -9,7 +9,6 @@ import { } from '../util.js' import { createServer, connect } from '../../src/lib.js' import { Upload } from '@web3-storage/capabilities' -import { uploadListProvider } from '../../src/upload/list.js' // https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/batchwriteitemcommand.html const BATCH_MAX_SAFE_LIMIT = 25 @@ -901,8 +900,6 @@ export const test = { throw new Error('invocation failed', { cause: uploadGet }) } - assert.equal(uploadGet.out.ok.issuer, alice.toDIDKey()) - assert.equal(uploadGet.out.ok.space, spaceDid) assert.equal(uploadGet.out.ok.shards?.[0].toString(), cars[0].cid.toString()) assert.equal(uploadGet.out.ok.root.toString(), cars[0].roots[0].toString()) }, diff --git a/packages/upload-api/test/helpers/context.js b/packages/upload-api/test/helpers/context.js index e2d9790bc..209efe887 100644 --- a/packages/upload-api/test/helpers/context.js +++ b/packages/upload-api/test/helpers/context.js @@ -61,7 +61,6 @@ export const createContext = async (options = {}) => { mail: /** @type {TestTypes.DebugEmail} */ (serviceContext.email), service: /** @type {TestTypes.ServiceSigner} */ (serviceContext.id), connection, - testStoreTable: storeTable, fetch, } } diff --git a/packages/upload-api/test/storage/store-table.js b/packages/upload-api/test/storage/store-table.js index 09fc0728c..576f6802f 100644 --- a/packages/upload-api/test/storage/store-table.js +++ b/packages/upload-api/test/storage/store-table.js @@ -5,7 +5,7 @@ import * as API from '../../src/types.js' */ export class StoreTable { constructor() { - /** @type {(API.StoreGetItem)[]} */ + /** @type {(API.StoreAddInput & API.StoreListItem)[]} */ this.items = [] } @@ -45,7 +45,7 @@ export class StoreTable { * Get info for a single shard or undefined if it doesn't exist * @param {API.DID} space * @param {API.UnknownLink} link - * @returns {Promise} + * @returns {Promise<(API.StoreAddInput & API.StoreListItem) | undefined>} */ async get(space, link) { return this.items.find( diff --git a/packages/upload-client/src/types.ts b/packages/upload-client/src/types.ts index 648caeda2..b1390f265 100644 --- a/packages/upload-client/src/types.ts +++ b/packages/upload-client/src/types.ts @@ -18,6 +18,8 @@ import { StoreAddSuccess, StoreAddSuccessUpload, StoreAddSuccessDone, + StoreGet, + StoreGetFailure, StoreList, StoreListSuccess, StoreListItem, @@ -34,6 +36,10 @@ import { ListResponse, CARLink, PieceLink, + StoreGetSuccess, + UploadGet, + UploadGetSuccess, + UploadGetFailure, } from '@web3-storage/capabilities/types' import * as UnixFS from '@ipld/unixfs/src/unixfs' @@ -70,11 +76,13 @@ export type ProgressFn = (status: ProgressStatus) => void export interface Service { store: { add: ServiceMethod + get: ServiceMethod remove: ServiceMethod list: ServiceMethod } upload: { add: ServiceMethod + get: ServiceMethod remove: ServiceMethod list: ServiceMethod } diff --git a/packages/upload-client/test/helpers/mocks.js b/packages/upload-client/test/helpers/mocks.js index 4d1386aae..937914bf6 100644 --- a/packages/upload-client/test/helpers/mocks.js +++ b/packages/upload-client/test/helpers/mocks.js @@ -14,11 +14,13 @@ export function mockService(impl) { return { store: { add: withCallCount(impl.store?.add ?? notImplemented), + get: withCallCount(impl.store?.get ?? notImplemented), list: withCallCount(impl.store?.list ?? notImplemented), remove: withCallCount(impl.store?.remove ?? notImplemented), }, upload: { add: withCallCount(impl.upload?.add ?? notImplemented), + get: withCallCount(impl.upload?.get ?? notImplemented), list: withCallCount(impl.upload?.list ?? notImplemented), remove: withCallCount(impl.upload?.remove ?? notImplemented), }, diff --git a/packages/upload-client/test/store.test.js b/packages/upload-client/test/store.test.js index deaccca34..35a0ca12e 100644 --- a/packages/upload-client/test/store.test.js +++ b/packages/upload-client/test/store.test.js @@ -354,6 +354,7 @@ describe('Store.list', () => { { link: car.cid, size: 123, + insertedAt: 'foo' }, ], } @@ -422,6 +423,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, + insertedAt: 'time1' }, ], } @@ -431,6 +433,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, + insertedAt: 'time1' }, ], } diff --git a/packages/upload-client/test/upload.test.js b/packages/upload-client/test/upload.test.js index 878d157b6..e9360dbcd 100644 --- a/packages/upload-client/test/upload.test.js +++ b/packages/upload-client/test/upload.test.js @@ -137,6 +137,8 @@ describe('Upload.list', () => { { root: car.roots[0], shards: [car.cid], + insertedAt: 'foo', + updatedAt: 'bar' }, ], } @@ -208,6 +210,8 @@ describe('Upload.list', () => { { root: car0.roots[0], shards: [car0.cid], + insertedAt: 'foo', + updatedAt: 'bar' }, ], } @@ -218,6 +222,8 @@ describe('Upload.list', () => { { root: car1.roots[0], shards: [car1.cid], + insertedAt: 'foo', + updatedAt: 'bar' }, ], } diff --git a/packages/w3up-client/test/capability/store.test.js b/packages/w3up-client/test/capability/store.test.js index 348f33834..fab39a5b1 100644 --- a/packages/w3up-client/test/capability/store.test.js +++ b/packages/w3up-client/test/capability/store.test.js @@ -68,6 +68,7 @@ describe('StoreClient', () => { { link: (await randomCAR(128)).cid, size: 123, + insertedAt: 'foo' }, ], } diff --git a/packages/w3up-client/test/capability/upload.test.js b/packages/w3up-client/test/capability/upload.test.js index e20acec29..11785ff8f 100644 --- a/packages/w3up-client/test/capability/upload.test.js +++ b/packages/w3up-client/test/capability/upload.test.js @@ -68,6 +68,8 @@ describe('StoreClient', () => { { root: car.roots[0], shards: [car.cid], + insertedAt: 'foo', + updatedAt: 'bar' }, ], } From 5eb25f369908da2ad869a743db11e8ba222af98b Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 17 Oct 2023 14:57:47 +0100 Subject: [PATCH 06/12] chore: make diff less noisy License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 7d23c7750..8ccb3d399 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -380,25 +380,25 @@ export interface DudewhereBucket { export interface StoreTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, link: UnknownLink) => Promise + get: (space: DID,link: UnknownLink) => Promise<(StoreListItem) | undefined> insert: (item: StoreAddInput) => Promise remove: (space: DID, link: UnknownLink) => Promise list: ( space: DID, options?: ListOptions ) => Promise> - get: (space: DID,link: UnknownLink) => Promise<(StoreListItem) | undefined> } export interface UploadTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, root: UnknownLink) => Promise + get: (space: DID,link: UnknownLink) => Promise<(UploadListItem) | undefined> insert: (item: UploadAddInput) => Promise remove: (space: DID, root: UnknownLink) => Promise list: ( space: DID, options?: ListOptions ) => Promise> - get: (space: DID,link: UnknownLink) => Promise<(UploadListItem) | undefined> } export type SpaceInfoSuccess = { From a47a11854aee1614eb09e4850dce1b4111dae858 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 17 Oct 2023 14:59:51 +0100 Subject: [PATCH 07/12] chore: make diff less noisy License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 8ccb3d399..ef4495fbb 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -380,7 +380,7 @@ export interface DudewhereBucket { export interface StoreTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, link: UnknownLink) => Promise - get: (space: DID,link: UnknownLink) => Promise<(StoreListItem) | undefined> + get: (space: DID,link: UnknownLink) => Promise insert: (item: StoreAddInput) => Promise remove: (space: DID, link: UnknownLink) => Promise list: ( @@ -392,7 +392,7 @@ export interface StoreTable { export interface UploadTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, root: UnknownLink) => Promise - get: (space: DID,link: UnknownLink) => Promise<(UploadListItem) | undefined> + get: (space: DID,link: UnknownLink) => Promise insert: (item: UploadAddInput) => Promise remove: (space: DID, root: UnknownLink) => Promise list: ( From df55473f8f778954cdb03380f738d380f3c7e4d9 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Tue, 17 Oct 2023 15:14:05 +0100 Subject: [PATCH 08/12] chore: make diff nice License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/types.ts | 8 ++------ packages/upload-api/test/handlers/store.js | 10 +++------- packages/upload-client/test/store.test.js | 6 +++--- packages/upload-client/test/upload.test.js | 12 ++++++------ packages/w3up-client/test/capability/store.test.js | 2 +- packages/w3up-client/test/capability/upload.test.js | 4 ++-- 6 files changed, 17 insertions(+), 25 deletions(-) diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index ef4495fbb..418e14105 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -380,7 +380,7 @@ export interface DudewhereBucket { export interface StoreTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, link: UnknownLink) => Promise - get: (space: DID,link: UnknownLink) => Promise + get: (space: DID, link: UnknownLink) => Promise insert: (item: StoreAddInput) => Promise remove: (space: DID, link: UnknownLink) => Promise list: ( @@ -392,7 +392,7 @@ export interface StoreTable { export interface UploadTable { inspect: (link: UnknownLink) => Promise exists: (space: DID, root: UnknownLink) => Promise - get: (space: DID,link: UnknownLink) => Promise + get: (space: DID, link: UnknownLink) => Promise insert: (item: UploadAddInput) => Promise remove: (space: DID, root: UnknownLink) => Promise list: ( @@ -433,10 +433,6 @@ export interface StoreAddInput { invocation: UCANLink } -export interface StoreMetadata { - insertedAt: string -} - export interface StoreAddOutput extends Omit {} diff --git a/packages/upload-api/test/handlers/store.js b/packages/upload-api/test/handlers/store.js index 24534f446..67cb2657f 100644 --- a/packages/upload-api/test/handlers/store.js +++ b/packages/upload-api/test/handlers/store.js @@ -83,10 +83,8 @@ export const test = { size: item.size, }, { - space: spaceDid, link: link.toString(), size: data.byteLength, - issuer: alice.did(), } ) @@ -301,13 +299,11 @@ export const test = { assert.deepEqual( { link: item.link.toString(), - size: item.size, + size: item.size }, { - space: spaceDid, link: link.toString(), - size: data.byteLength, - issuer: alice.did(), + size: data.byteLength } ) @@ -763,4 +759,4 @@ export const test = { assert.ok(storeGet.out.error) assert.equal(storeGet.out.error?.name, 'ShardNotFound') }, -} \ No newline at end of file +} diff --git a/packages/upload-client/test/store.test.js b/packages/upload-client/test/store.test.js index 35a0ca12e..dbb99481b 100644 --- a/packages/upload-client/test/store.test.js +++ b/packages/upload-client/test/store.test.js @@ -354,7 +354,7 @@ describe('Store.list', () => { { link: car.cid, size: 123, - insertedAt: 'foo' + insertedAt: '1970-01-01T00:00:00.000Z' }, ], } @@ -423,7 +423,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: 'time1' + insertedAt: '1970-01-01T00:00:00.000Z' }, ], } @@ -433,7 +433,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: 'time1' + insertedAt: '1970-01-01T00:00:00.000Z' }, ], } diff --git a/packages/upload-client/test/upload.test.js b/packages/upload-client/test/upload.test.js index e9360dbcd..a97cb6b50 100644 --- a/packages/upload-client/test/upload.test.js +++ b/packages/upload-client/test/upload.test.js @@ -137,8 +137,8 @@ describe('Upload.list', () => { { root: car.roots[0], shards: [car.cid], - insertedAt: 'foo', - updatedAt: 'bar' + insertedAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z' }, ], } @@ -210,8 +210,8 @@ describe('Upload.list', () => { { root: car0.roots[0], shards: [car0.cid], - insertedAt: 'foo', - updatedAt: 'bar' + insertedAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z' }, ], } @@ -222,8 +222,8 @@ describe('Upload.list', () => { { root: car1.roots[0], shards: [car1.cid], - insertedAt: 'foo', - updatedAt: 'bar' + insertedAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z' }, ], } diff --git a/packages/w3up-client/test/capability/store.test.js b/packages/w3up-client/test/capability/store.test.js index fab39a5b1..f46497c20 100644 --- a/packages/w3up-client/test/capability/store.test.js +++ b/packages/w3up-client/test/capability/store.test.js @@ -68,7 +68,7 @@ describe('StoreClient', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: 'foo' + insertedAt: '1970-01-01T00:00:00.000Z' }, ], } diff --git a/packages/w3up-client/test/capability/upload.test.js b/packages/w3up-client/test/capability/upload.test.js index 11785ff8f..f8fedbed4 100644 --- a/packages/w3up-client/test/capability/upload.test.js +++ b/packages/w3up-client/test/capability/upload.test.js @@ -68,8 +68,8 @@ describe('StoreClient', () => { { root: car.roots[0], shards: [car.cid], - insertedAt: 'foo', - updatedAt: 'bar' + insertedAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z' }, ], } From 9d8fece2d0bcd1c2c42dc4e9d12c605013ade280 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Wed, 18 Oct 2023 09:57:44 +0100 Subject: [PATCH 09/12] chore: apply suggestions from code review Co-authored-by: Alan Shaw --- packages/capabilities/src/store.js | 4 ++-- packages/upload-api/src/store/get.js | 2 +- packages/upload-api/src/upload/get.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/capabilities/src/store.js b/packages/capabilities/src/store.js index 1c85cafa2..6582b50f0 100644 --- a/packages/capabilities/src/store.js +++ b/packages/capabilities/src/store.js @@ -82,8 +82,8 @@ export const add = capability({ * Use to check for inclusion, or get shard size and origin * * `nb.link` is optional to allow delegation of `store/get` - * capability for any shard cid. If link is specified, then the - * capability only allows a get for that single cid. + * capability for any shard CID. If link is specified, then the + * capability only allows a get for that specific CID. * * When used as as an invocation, `nb.link` must be specified. */ diff --git a/packages/upload-api/src/store/get.js b/packages/upload-api/src/store/get.js index 6ea8baca4..0c0da0ef0 100644 --- a/packages/upload-api/src/store/get.js +++ b/packages/upload-api/src/store/get.js @@ -4,7 +4,7 @@ import * as API from '../types.js' /** * @param {API.StoreServiceContext} context - * @returns {API.ServiceMethod} + * @returns {API.ServiceMethod} */ export function storeGetProvider(context) { return Server.provide(Store.get, async ({ capability }) => { diff --git a/packages/upload-api/src/upload/get.js b/packages/upload-api/src/upload/get.js index e113f0358..9d87575e1 100644 --- a/packages/upload-api/src/upload/get.js +++ b/packages/upload-api/src/upload/get.js @@ -4,7 +4,7 @@ import * as API from '../types.js' /** * @param {API.UploadServiceContext} context - * @returns {API.ServiceMethod} + * @returns {API.ServiceMethod} */ export function uploadGetProvider(context) { return Server.provide(Upload.get, async ({ capability }) => { From c268076755fac1d0d191a050b693d560537fa641 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Wed, 18 Oct 2023 13:19:56 +0100 Subject: [PATCH 10/12] chore: rename *inpect success types and fix error name for StoreItemNotFound License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/store/get.js | 4 ++-- packages/upload-api/src/types.ts | 8 ++++---- packages/upload-api/test/handlers/store.js | 4 ++-- packages/upload-api/test/storage/store-table.js | 2 +- packages/upload-api/test/storage/upload-table.js | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/upload-api/src/store/get.js b/packages/upload-api/src/store/get.js index 0c0da0ef0..5fddcc921 100644 --- a/packages/upload-api/src/store/get.js +++ b/packages/upload-api/src/store/get.js @@ -17,8 +17,8 @@ export function storeGetProvider(context) { if (!res) { return { error: { - name: 'ShardNotFound', - message: 'Shard not found' + name: 'StoreItemNotFound', + message: 'Store item not found' } } } diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 418e14105..786bf1ca7 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -378,7 +378,7 @@ export interface DudewhereBucket { } export interface StoreTable { - inspect: (link: UnknownLink) => Promise + inspect: (link: UnknownLink) => Promise exists: (space: DID, link: UnknownLink) => Promise get: (space: DID, link: UnknownLink) => Promise insert: (item: StoreAddInput) => Promise @@ -390,7 +390,7 @@ export interface StoreTable { } export interface UploadTable { - inspect: (link: UnknownLink) => Promise + inspect: (link: UnknownLink) => Promise exists: (space: DID, root: UnknownLink) => Promise get: (space: DID, link: UnknownLink) => Promise insert: (item: UploadAddInput) => Promise @@ -436,7 +436,7 @@ export interface StoreAddInput { export interface StoreAddOutput extends Omit {} -export interface StoreInspectOk { +export interface StoreInspectSuccess { spaces: Array<{ did: DID; insertedAt: string }> } @@ -448,7 +448,7 @@ export interface UploadAddInput { invocation: UCANLink } -export interface UploadInspectOk { +export interface UploadInspectSuccess { spaces: Array<{ did: DID; insertedAt: string }> } diff --git a/packages/upload-api/test/handlers/store.js b/packages/upload-api/test/handlers/store.js index 67cb2657f..b78a5358b 100644 --- a/packages/upload-api/test/handlers/store.js +++ b/packages/upload-api/test/handlers/store.js @@ -732,7 +732,7 @@ export const test = { assert.ok(storeGet.out.ok.insertedAt) }, - 'store/get returns ShardNotFound Failure': async ( + 'store/get returns StoreItemNotFound Failure': async ( assert, context ) => { @@ -757,6 +757,6 @@ export const test = { .execute(connection) assert.ok(storeGet.out.error) - assert.equal(storeGet.out.error?.name, 'ShardNotFound') + assert.equal(storeGet.out.error?.name, 'StoreItemNotFound') }, } diff --git a/packages/upload-api/test/storage/store-table.js b/packages/upload-api/test/storage/store-table.js index 576f6802f..31907e4c2 100644 --- a/packages/upload-api/test/storage/store-table.js +++ b/packages/upload-api/test/storage/store-table.js @@ -27,7 +27,7 @@ export class StoreTable { /** * * @param {API.UnknownLink} link - * @returns {Promise} + * @returns {Promise} */ async inspect(link) { const items = diff --git a/packages/upload-api/test/storage/upload-table.js b/packages/upload-api/test/storage/upload-table.js index 2b14ee9ed..d6dcf597c 100644 --- a/packages/upload-api/test/storage/upload-table.js +++ b/packages/upload-api/test/storage/upload-table.js @@ -13,7 +13,7 @@ export class UploadTable { /** * * @param {API.UnknownLink} link - * @returns {Promise} + * @returns {Promise} */ async inspect(link) { const items = From 6927e81ee7f63473d6393eaa0889c4f39fb43eb0 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Wed, 18 Oct 2023 15:14:12 +0100 Subject: [PATCH 11/12] chore: am i not pretty enough? License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/store/get.js | 8 +++---- packages/upload-api/src/types.ts | 4 ++-- packages/upload-api/src/upload/get.js | 8 +++---- packages/upload-api/test/handlers/store.js | 22 +++++++------------ packages/upload-api/test/handlers/upload.js | 14 ++++++------ packages/upload-client/test/store.test.js | 6 ++--- packages/upload-client/test/upload.test.js | 6 ++--- .../w3up-client/test/capability/store.test.js | 2 +- .../test/capability/upload.test.js | 2 +- 9 files changed, 33 insertions(+), 39 deletions(-) diff --git a/packages/upload-api/src/store/get.js b/packages/upload-api/src/store/get.js index 5fddcc921..e8a3c1983 100644 --- a/packages/upload-api/src/store/get.js +++ b/packages/upload-api/src/store/get.js @@ -15,15 +15,15 @@ export function storeGetProvider(context) { const space = Server.DID.parse(capability.with).did() const res = await context.storeTable.get(space, link) if (!res) { - return { + return { error: { name: 'StoreItemNotFound', - message: 'Store item not found' - } + message: 'Store item not found', + }, } } return { - ok: res + ok: res, } }) } diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 786bf1ca7..0023b990b 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -386,7 +386,7 @@ export interface StoreTable { list: ( space: DID, options?: ListOptions - ) => Promise> + ) => Promise> } export interface UploadTable { @@ -398,7 +398,7 @@ export interface UploadTable { list: ( space: DID, options?: ListOptions - ) => Promise> + ) => Promise> } export type SpaceInfoSuccess = { diff --git a/packages/upload-api/src/upload/get.js b/packages/upload-api/src/upload/get.js index 9d87575e1..d15547c51 100644 --- a/packages/upload-api/src/upload/get.js +++ b/packages/upload-api/src/upload/get.js @@ -15,15 +15,15 @@ export function uploadGetProvider(context) { const space = Server.DID.parse(capability.with).did() const res = await context.uploadTable.get(space, root) if (!res) { - return { + return { error: { name: 'UploadNotFound', - message: 'Upload not found' - } + message: 'Upload not found', + }, } } return { - ok: res + ok: res, } }) } diff --git a/packages/upload-api/test/handlers/store.js b/packages/upload-api/test/handlers/store.js index b78a5358b..0d51ef246 100644 --- a/packages/upload-api/test/handlers/store.js +++ b/packages/upload-api/test/handlers/store.js @@ -299,11 +299,11 @@ export const test = { assert.deepEqual( { link: item.link.toString(), - size: item.size + size: item.size, }, { link: link.toString(), - size: data.byteLength + size: data.byteLength, } ) @@ -677,10 +677,7 @@ export const test = { assert.deepEqual(prevListResponse.out.ok.after, listResponse.out.ok.after) }, - 'store/get returns shard info': async ( - assert, - context - ) => { + 'store/get returns shard info': async (assert, context) => { const { proof, spaceDid } = await registerSpace(alice, context) const connection = connect({ id: context.id, @@ -718,7 +715,7 @@ export const test = { with: spaceDid, proofs: [proof], nb: { - link: links[0] + link: links[0], }, }) .execute(connection) @@ -727,15 +724,12 @@ export const test = { throw new Error('invocation failed', { cause: storeGet }) } - assert.deepEqual(storeGet.out.ok.link, links[0]) - assert.equal(storeGet.out.ok.size, data[0].byteLength) + assert.deepEqual(storeGet.out.ok.link, links[0]) + assert.equal(storeGet.out.ok.size, data[0].byteLength) assert.ok(storeGet.out.ok.insertedAt) }, - 'store/get returns StoreItemNotFound Failure': async ( - assert, - context - ) => { + 'store/get returns StoreItemNotFound Failure': async (assert, context) => { const { proof, spaceDid } = await registerSpace(alice, context) const connection = connect({ id: context.id, @@ -751,7 +745,7 @@ export const test = { with: spaceDid, proofs: [proof], nb: { - link + link, }, }) .execute(connection) diff --git a/packages/upload-api/test/handlers/upload.js b/packages/upload-api/test/handlers/upload.js index 34f764be6..8e957064d 100644 --- a/packages/upload-api/test/handlers/upload.js +++ b/packages/upload-api/test/handlers/upload.js @@ -859,10 +859,7 @@ export const test = { ) }, - 'upload/get returns info for one upload': async ( - assert, - context - ) => { + 'upload/get returns info for one upload': async (assert, context) => { const { proof, spaceDid } = await registerSpace(alice, context) const connection = connect({ id: context.id, @@ -891,7 +888,7 @@ export const test = { with: spaceDid, proofs: [proof], nb: { - root: cars[0].roots[0] + root: cars[0].roots[0], }, }) .execute(connection) @@ -900,7 +897,10 @@ export const test = { throw new Error('invocation failed', { cause: uploadGet }) } - assert.equal(uploadGet.out.ok.shards?.[0].toString(), cars[0].cid.toString()) + assert.equal( + uploadGet.out.ok.shards?.[0].toString(), + cars[0].cid.toString() + ) assert.equal(uploadGet.out.ok.root.toString(), cars[0].roots[0].toString()) }, @@ -923,7 +923,7 @@ export const test = { with: spaceDid, proofs: [proof], nb: { - root: car.roots[0] + root: car.roots[0], }, }) .execute(connection) diff --git a/packages/upload-client/test/store.test.js b/packages/upload-client/test/store.test.js index dbb99481b..c6e81f84b 100644 --- a/packages/upload-client/test/store.test.js +++ b/packages/upload-client/test/store.test.js @@ -354,7 +354,7 @@ describe('Store.list', () => { { link: car.cid, size: 123, - insertedAt: '1970-01-01T00:00:00.000Z' + insertedAt: '1970-01-01T00:00:00.000Z', }, ], } @@ -423,7 +423,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: '1970-01-01T00:00:00.000Z' + insertedAt: '1970-01-01T00:00:00.000Z', }, ], } @@ -433,7 +433,7 @@ describe('Store.list', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: '1970-01-01T00:00:00.000Z' + insertedAt: '1970-01-01T00:00:00.000Z', }, ], } diff --git a/packages/upload-client/test/upload.test.js b/packages/upload-client/test/upload.test.js index a97cb6b50..a22b10848 100644 --- a/packages/upload-client/test/upload.test.js +++ b/packages/upload-client/test/upload.test.js @@ -138,7 +138,7 @@ describe('Upload.list', () => { root: car.roots[0], shards: [car.cid], insertedAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z' + updatedAt: '1970-01-01T00:00:00.000Z', }, ], } @@ -211,7 +211,7 @@ describe('Upload.list', () => { root: car0.roots[0], shards: [car0.cid], insertedAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z' + updatedAt: '1970-01-01T00:00:00.000Z', }, ], } @@ -223,7 +223,7 @@ describe('Upload.list', () => { root: car1.roots[0], shards: [car1.cid], insertedAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z' + updatedAt: '1970-01-01T00:00:00.000Z', }, ], } diff --git a/packages/w3up-client/test/capability/store.test.js b/packages/w3up-client/test/capability/store.test.js index f46497c20..3c5d60754 100644 --- a/packages/w3up-client/test/capability/store.test.js +++ b/packages/w3up-client/test/capability/store.test.js @@ -68,7 +68,7 @@ describe('StoreClient', () => { { link: (await randomCAR(128)).cid, size: 123, - insertedAt: '1970-01-01T00:00:00.000Z' + insertedAt: '1970-01-01T00:00:00.000Z', }, ], } diff --git a/packages/w3up-client/test/capability/upload.test.js b/packages/w3up-client/test/capability/upload.test.js index f8fedbed4..bc8ed0956 100644 --- a/packages/w3up-client/test/capability/upload.test.js +++ b/packages/w3up-client/test/capability/upload.test.js @@ -69,7 +69,7 @@ describe('StoreClient', () => { root: car.roots[0], shards: [car.cid], insertedAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z' + updatedAt: '1970-01-01T00:00:00.000Z', }, ], } From 654449684b17c4f98d2adf93be0c408119bcfd92 Mon Sep 17 00:00:00 2001 From: Oli Evans Date: Thu, 19 Oct 2023 11:08:03 +0100 Subject: [PATCH 12/12] chore: simplify return type from store table License: MIT Signed-off-by: Oli Evans --- packages/upload-api/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/upload-api/src/types.ts b/packages/upload-api/src/types.ts index 0023b990b..4fd6f72cc 100644 --- a/packages/upload-api/src/types.ts +++ b/packages/upload-api/src/types.ts @@ -386,7 +386,7 @@ export interface StoreTable { list: ( space: DID, options?: ListOptions - ) => Promise> + ) => Promise> } export interface UploadTable {