diff --git a/billing/data/allocations.js b/billing/data/allocations.js index 52d07624..86b3de4a 100644 --- a/billing/data/allocations.js +++ b/billing/data/allocations.js @@ -2,14 +2,14 @@ import * as Link from 'multiformats/link' import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').Allocation} Allocation - * @typedef {import('../lib/api').AllocationSpaceInsertedAtIndex} AllocationSpaceInsertedAtIndex - * @typedef {import('../types').InferStoreRecord} AllocationStoreRecord - * @typedef {import('../lib/api').AllocationKey} AllocationKey - * @typedef {import('../lib/api').AllocationListKey} AllocationListKey - * @typedef {import('../types').InferStoreRecord} AllocationKeyStoreRecord + * @typedef {import('../lib/api.js').Allocation} Allocation + * @typedef {import('../lib/api.js').AllocationSpaceInsertedAtIndex} AllocationSpaceInsertedAtIndex + * @typedef {import('../types.js').InferStoreRecord} AllocationStoreRecord + * @typedef {import('../lib/api.js').AllocationKey} AllocationKey + * @typedef {import('../lib/api.js').AllocationListKey} AllocationListKey + * @typedef {import('../types.js').InferStoreRecord} AllocationKeyStoreRecord * @typedef {{ space: string, insertedAt?: string }} AllocationListStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord */ const schema = Schema.struct({ @@ -20,13 +20,13 @@ const schema = Schema.struct({ size: Schema.bigint().greaterThanEqualTo(0n), }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = (input) => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeKey = (input) => ({ ok: { multihash: input.multihash } }) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = (input) => { try { return { @@ -47,7 +47,7 @@ export const encode = (input) => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = (input) => { try { return { @@ -69,7 +69,7 @@ export const decode = (input) => { } export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: (input) => { /** @type AllocationListStoreRecord */ const conditions = { space: input.space.toString() } @@ -82,7 +82,7 @@ export const lister = { }, } }, - /** @type {import('../lib/api').Decoder} */ + /** @type {import('../lib/api.js').Decoder} */ decode: (input) => { try { return { diff --git a/billing/data/consumer.js b/billing/data/consumer.js index a64db192..2b890dc3 100644 --- a/billing/data/consumer.js +++ b/billing/data/consumer.js @@ -2,13 +2,13 @@ import * as Link from 'multiformats/link' import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').Consumer} Consumer - * @typedef {import('../types').InferStoreRecord} ConsumerStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord - * @typedef {import('../lib/api').ConsumerKey} ConsumerKey - * @typedef {import('../types').InferStoreRecord} ConsumerKeyStoreRecord - * @typedef {import('../lib/api').ConsumerListKey} ConsumerListKey - * @typedef {import('../types').InferStoreRecord} ConsumerListKeyStoreRecord + * @typedef {import('../lib/api.js').Consumer} Consumer + * @typedef {import('../types.js').InferStoreRecord} ConsumerStoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord + * @typedef {import('../lib/api.js').ConsumerKey} ConsumerKey + * @typedef {import('../types.js').InferStoreRecord} ConsumerKeyStoreRecord + * @typedef {import('../lib/api.js').ConsumerListKey} ConsumerListKey + * @typedef {import('../types.js').InferStoreRecord} ConsumerListKeyStoreRecord * @typedef {Pick} ConsumerList */ @@ -22,10 +22,10 @@ const schema = Schema.struct({ updatedAt: Schema.date().optional() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -46,7 +46,7 @@ export const encode = input => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { @@ -67,7 +67,7 @@ export const decode = input => { } } -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeKey = input => ({ ok: { subscription: input.subscription, @@ -77,9 +77,9 @@ export const encodeKey = input => ({ /** Encoders/decoders for listings. */ export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: input => ({ ok: { consumer: input.consumer } }), - /** @type {import('../lib/api').Decoder} */ + /** @type {import('../lib/api.js').Decoder} */ decode: input => { try { return { diff --git a/billing/data/customer-billing-instruction.js b/billing/data/customer-billing-instruction.js index 620d5138..10d5b88b 100644 --- a/billing/data/customer-billing-instruction.js +++ b/billing/data/customer-billing-instruction.js @@ -2,7 +2,7 @@ import * as dagJSON from '@ipld/dag-json' import { EncodeFailure, DecodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').CustomerBillingInstruction} CustomerBillingInstruction + * @typedef {import('../lib/api.js').CustomerBillingInstruction} CustomerBillingInstruction */ export const schema = Schema.struct({ @@ -13,10 +13,10 @@ export const schema = Schema.struct({ to: Schema.date() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = message => { try { const data = { @@ -32,7 +32,7 @@ export const encode = message => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = str => { try { const data = dagJSON.parse(str) diff --git a/billing/data/customer.js b/billing/data/customer.js index 4ff7242e..11f65d0f 100644 --- a/billing/data/customer.js +++ b/billing/data/customer.js @@ -1,11 +1,11 @@ import { EncodeFailure, DecodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').Customer} Customer - * @typedef {import('../types').InferStoreRecord} CustomerStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord - * @typedef {import('../lib/api').CustomerKey} CustomerKey - * @typedef {import('../types').InferStoreRecord} CustomerKeyStoreRecord + * @typedef {import('../lib/api.js').Customer} Customer + * @typedef {import('../types.js').InferStoreRecord} CustomerStoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord + * @typedef {import('../lib/api.js').CustomerKey} CustomerKey + * @typedef {import('../types.js').InferStoreRecord} CustomerKeyStoreRecord */ const schema = Schema.struct({ @@ -16,10 +16,10 @@ const schema = Schema.struct({ updatedAt: Schema.date().optional() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -38,10 +38,10 @@ export const encode = input => { } } -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeKey = input => ({ ok: { customer: input.customer } }) -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { diff --git a/billing/data/egress.js b/billing/data/egress.js index 094b3e47..ae866bed 100644 --- a/billing/data/egress.js +++ b/billing/data/egress.js @@ -2,8 +2,8 @@ import { Link } from '@ucanto/server' import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef { import('../lib/api').EgressTrafficData } EgressTrafficData - * @typedef { import('../types').InferStoreRecord & { pk: string, sk: string } } EgressTrafficStoreRecord + * @typedef { import('../lib/api.js').EgressTrafficData } EgressTrafficData + * @typedef { import('../types.js').InferStoreRecord & { pk: string, sk: string } } EgressTrafficStoreRecord * @typedef {{ pk: string, sk: string }} EgressTrafficKeyStoreRecord */ @@ -16,10 +16,10 @@ export const egressSchema = Schema.struct({ cause: Schema.link(), }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => egressSchema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -41,7 +41,7 @@ export const encode = input => { } } -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeStr = input => { try { const data = encode(input) @@ -54,7 +54,7 @@ export const encodeStr = input => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { @@ -74,7 +74,7 @@ export const decode = input => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decodeStr = input => { try { return decode(JSON.parse(input)) @@ -86,14 +86,14 @@ export const decodeStr = input => { } export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: input => ({ ok: { pk: `${input.space.toString()}#${input.resource.toString()}`, sk: `${input.servedAt.toISOString()}#${input.cause.toString()}`, } }), - /** @type {import('../lib/api').Decoder} */ + /** @type {import('../lib/api.js').Decoder} */ decodeKey: input => { try { const [space, resource] = input.pk.split('#') diff --git a/billing/data/space-billing-instruction.js b/billing/data/space-billing-instruction.js index 944655a8..f38da011 100644 --- a/billing/data/space-billing-instruction.js +++ b/billing/data/space-billing-instruction.js @@ -2,7 +2,7 @@ import * as dagJSON from '@ipld/dag-json' import { EncodeFailure, DecodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').SpaceBillingInstruction} SpaceBillingInstruction + * @typedef {import('../lib/api.js').SpaceBillingInstruction} SpaceBillingInstruction */ export const schema = Schema.struct({ @@ -15,10 +15,10 @@ export const schema = Schema.struct({ to: Schema.date() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = message => { try { const data = { @@ -36,7 +36,7 @@ export const encode = message => { } } -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = str => { try { const data = dagJSON.parse(str) diff --git a/billing/data/space-diff.js b/billing/data/space-diff.js index 06bbad53..1a15800f 100644 --- a/billing/data/space-diff.js +++ b/billing/data/space-diff.js @@ -2,11 +2,11 @@ import * as Link from 'multiformats/link' import { EncodeFailure, DecodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').SpaceDiff} SpaceDiff - * @typedef {import('../types').InferStoreRecord & { pk: string, sk: string }} SpaceDiffStoreRecord - * @typedef {import('../lib/api').SpaceDiffListKey} SpaceDiffListKey + * @typedef {import('../lib/api.js').SpaceDiff} SpaceDiff + * @typedef {import('../types.js').InferStoreRecord & { pk: string, sk: string }} SpaceDiffStoreRecord + * @typedef {import('../lib/api.js').SpaceDiffListKey} SpaceDiffListKey * @typedef {{ pk: string, sk: string }} SpaceDiffListStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord */ export const schema = Schema.struct({ @@ -19,10 +19,10 @@ export const schema = Schema.struct({ insertedAt: Schema.date() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -47,7 +47,7 @@ export const encode = input => { -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { @@ -69,7 +69,7 @@ export const decode = input => { } export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: input => ({ ok: { pk: `${input.provider}#${input.space}`, diff --git a/billing/data/space-snapshot.js b/billing/data/space-snapshot.js index 0d9f4828..4270f045 100644 --- a/billing/data/space-snapshot.js +++ b/billing/data/space-snapshot.js @@ -1,11 +1,11 @@ import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').SpaceSnapshot} SpaceSnapshot - * @typedef {import('../types').InferStoreRecord & { pk: string }} SpaceSnapshotStoreRecord - * @typedef {import('../lib/api').SpaceSnapshotKey} SpaceSnapshotKey - * @typedef {Omit, 'provider'|'space'> & { pk: string }} SpaceSnapshotKeyStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord + * @typedef {import('../lib/api.js').SpaceSnapshot} SpaceSnapshot + * @typedef {import('../types.js').InferStoreRecord & { pk: string }} SpaceSnapshotStoreRecord + * @typedef {import('../lib/api.js').SpaceSnapshotKey} SpaceSnapshotKey + * @typedef {Omit, 'provider'|'space'> & { pk: string }} SpaceSnapshotKeyStoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord */ export const schema = Schema.struct({ @@ -16,10 +16,10 @@ export const schema = Schema.struct({ insertedAt: Schema.date() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -39,7 +39,7 @@ export const encode = input => { } } -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeKey = input => ({ ok: { pk: `${input.provider}#${input.space}`, @@ -47,7 +47,7 @@ export const encodeKey = input => ({ } }) -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { diff --git a/billing/data/store.js b/billing/data/store.js index e1b411b5..4c57534d 100644 --- a/billing/data/store.js +++ b/billing/data/store.js @@ -3,7 +3,7 @@ import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** * @typedef {import('../lib/api.js').StoreTable} StoreTable - * @typedef {import('../lib/api').StoreTableSpaceInsertedAtIndex} StoreTableSpaceInsertedAtIndex + * @typedef {import('../lib/api.js').StoreTableSpaceInsertedAtIndex} StoreTableSpaceInsertedAtIndex * @typedef {import('../types.js').InferStoreRecord} StoreTableStoreRecord * @typedef {import('../lib/api.js').StoreTableKey} StoreTableKey * @typedef {import('../lib/api.js').StoreTableListKey} StoreTableListKey diff --git a/billing/data/subscription.js b/billing/data/subscription.js index 361f4bd4..e5c7dc47 100644 --- a/billing/data/subscription.js +++ b/billing/data/subscription.js @@ -2,13 +2,13 @@ import * as Link from 'multiformats/link' import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').Subscription} Subscription - * @typedef {import('../types').InferStoreRecord} SubscriptionStoreRecord - * @typedef {import('../lib/api').SubscriptionKey} SubscriptionKey - * @typedef {import('../types').InferStoreRecord} SubscriptionKeyStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord - * @typedef {import('../lib/api').SubscriptionListKey} SubscriptionListKey - * @typedef {import('../types').InferStoreRecord} SubscriptionListKeyStoreRecord + * @typedef {import('../lib/api.js').Subscription} Subscription + * @typedef {import('../types.js').InferStoreRecord} SubscriptionStoreRecord + * @typedef {import('../lib/api.js').SubscriptionKey} SubscriptionKey + * @typedef {import('../types.js').InferStoreRecord} SubscriptionKeyStoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord + * @typedef {import('../lib/api.js').SubscriptionListKey} SubscriptionListKey + * @typedef {import('../types.js').InferStoreRecord} SubscriptionListKeyStoreRecord * @typedef {Pick} SubscriptionList */ @@ -21,10 +21,10 @@ const schema = Schema.struct({ updatedAt: Schema.date().optional() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -44,7 +44,7 @@ export const encode = input => { } } -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encodeKey = input => ({ ok: { provider: input.provider, @@ -52,7 +52,7 @@ export const encodeKey = input => ({ } }) -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { @@ -74,9 +74,9 @@ export const decode = input => { /** Encoders/decoders for listings. */ export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: input => ({ ok: { customer: input.customer } }), - /** @type {import('../lib/api').Decoder} */ + /** @type {import('../lib/api.js').Decoder} */ decode: input => { try { return { diff --git a/billing/data/usage.js b/billing/data/usage.js index bdbb2fe6..b7b1d518 100644 --- a/billing/data/usage.js +++ b/billing/data/usage.js @@ -1,11 +1,11 @@ import { DecodeFailure, EncodeFailure, Schema } from './lib.js' /** - * @typedef {import('../lib/api').Usage} Usage - * @typedef {import('../types').InferStoreRecord & { sk: string }} UsageStoreRecord - * @typedef {import('../lib/api').UsageListKey} UsageListKey - * @typedef {Omit, 'from'> & { sk: string }} UsageListKeyStoreRecord - * @typedef {import('../types').StoreRecord} StoreRecord + * @typedef {import('../lib/api.js').Usage} Usage + * @typedef {import('../types.js').InferStoreRecord & { sk: string }} UsageStoreRecord + * @typedef {import('../lib/api.js').UsageListKey} UsageListKey + * @typedef {Omit, 'from'> & { sk: string }} UsageListKeyStoreRecord + * @typedef {import('../types.js').StoreRecord} StoreRecord */ export const schema = Schema.struct({ @@ -20,10 +20,10 @@ export const schema = Schema.struct({ insertedAt: Schema.date() }) -/** @type {import('../lib/api').Validator} */ +/** @type {import('../lib/api.js').Validator} */ export const validate = input => schema.read(input) -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { @@ -48,7 +48,7 @@ export const encode = input => { } export const lister = { - /** @type {import('../lib/api').Encoder} */ + /** @type {import('../lib/api.js').Encoder} */ encodeKey: input => ({ ok: { customer: input.customer, @@ -59,7 +59,7 @@ export const lister = { -/** @type {import('../lib/api').Decoder} */ +/** @type {import('../lib/api.js').Decoder} */ export const decode = input => { try { return { diff --git a/billing/functions/ucan-stream.js b/billing/functions/ucan-stream.js index 342f507d..d0f30160 100644 --- a/billing/functions/ucan-stream.js +++ b/billing/functions/ucan-stream.js @@ -51,7 +51,7 @@ export const handler = Sentry.AWSLambda.wrapHandler( /** * @param {import('aws-lambda').KinesisStreamEvent} event - * @returns {import('../lib/api').UcanStreamMessage[]} + * @returns {import('../lib/api.js').UcanStreamMessage[]} */ const parseUcanStreamEvent = event => { const batch = event.Records.map(r => fromString(r.kinesis.data, 'base64')) @@ -91,11 +91,11 @@ const CONSUMER_LIST_CACHE_TTL = 1000 * 60 * 5 const CONSUMER_LIST_CACHE_MAX = 10_000 /** - * @param {import('../lib/api').ConsumerStore} consumerStore - * @returns {import('../lib/api').ConsumerStore} + * @param {import('../lib/api.js').ConsumerStore} consumerStore + * @returns {import('../lib/api.js').ConsumerStore} */ const withConsumerListCache = (consumerStore) => { - /** @type {LRUCache>>} */ + /** @type {LRUCache>>} */ const cache = new LRUCache({ max: CONSUMER_LIST_CACHE_MAX, ttl: CONSUMER_LIST_CACHE_TTL diff --git a/billing/lib/api.ts b/billing/lib/api.ts index 418a82ec..0b07b5c9 100644 --- a/billing/lib/api.ts +++ b/billing/lib/api.ts @@ -1,5 +1,5 @@ import { DID, Link, URI, LinkJSON, Result, Capabilities, Unit, Failure, UnknownLink } from '@ucanto/interface' -import { StoreRecord } from '../types' +import { StoreRecord } from '../types.js' // Billing stores ///////////////////////////////////////////////////////////// diff --git a/billing/lib/customer-billing-queue.js b/billing/lib/customer-billing-queue.js index dd2a36eb..e35da59f 100644 --- a/billing/lib/customer-billing-queue.js +++ b/billing/lib/customer-billing-queue.js @@ -2,11 +2,11 @@ * Discovers spaces that should be billed for a given customer and enqueues * a space billing instruction for each. * - * @param {import('./api').CustomerBillingInstruction} instruction + * @param {import('./api.js').CustomerBillingInstruction} instruction * @param {{ - * subscriptionStore: import('./api').SubscriptionStore - * consumerStore: import('./api').ConsumerStore - * spaceBillingQueue: import('./api').SpaceBillingQueue + * subscriptionStore: import('./api.js').SubscriptionStore + * consumerStore: import('./api.js').ConsumerStore + * spaceBillingQueue: import('./api.js').SpaceBillingQueue * }} ctx * @returns {Promise>} */ diff --git a/billing/lib/space-billing-queue.js b/billing/lib/space-billing-queue.js index 73831068..9bf5e114 100644 --- a/billing/lib/space-billing-queue.js +++ b/billing/lib/space-billing-queue.js @@ -2,9 +2,9 @@ import Big from 'big.js' import {GB} from './util.js' /** - * @param {import('./api').SpaceDiffListKey & { to: Date }} params - * @param {{ spaceDiffStore: import('./api').SpaceDiffStore }} ctx - * @returns {AsyncIterable>} + * @param {import('./api.js').SpaceDiffListKey & { to: Date }} params + * @param {{ spaceDiffStore: import('./api.js').SpaceDiffStore }} ctx + * @returns {AsyncIterable>} */ export const iterateSpaceDiffs = async function * ({ provider, space, from, to }, ctx) { /** @type {string|undefined} */ @@ -39,10 +39,10 @@ export const iterateSpaceDiffs = async function * ({ provider, space, from, to } * The usage value for the period and the space size at the end of the period * are returned to the caller. * - * @param {import('./api').SpaceBillingInstruction} instruction + * @param {import('./api.js').SpaceBillingInstruction} instruction * @param {{ - * spaceDiffStore: import('./api').SpaceDiffStore - * spaceSnapshotStore: import('./api').SpaceSnapshotStore + * spaceDiffStore: import('./api.js').SpaceDiffStore + * spaceSnapshotStore: import('./api.js').SpaceSnapshotStore * }} ctx * @returns {Promise>} */ @@ -87,11 +87,11 @@ export const calculatePeriodUsage = async (instruction, ctx) => { * period. The _next_ billing period is expected to start on the `to` date of * the current period, so that the snapshot will be used in the next cycle. * - * @param {import('./api').SpaceBillingInstruction} instruction + * @param {import('./api.js').SpaceBillingInstruction} instruction * @param {{ usage: bigint, size: bigint }} calculation * @param {{ - * spaceSnapshotStore: import('./api').SpaceSnapshotStore - * usageStore: import('./api').UsageStore + * spaceSnapshotStore: import('./api.js').SpaceSnapshotStore + * usageStore: import('./api.js').UsageStore * }} ctx * @returns {Promise>} */ @@ -122,13 +122,13 @@ export const storeSpaceUsage = async (instruction, { size, usage }, ctx) => { * Additionally, it estimates the usage for the space based on the allocation/store values. * Note: This value is approximate as it doesn’t account for deleted files. * - * @typedef {import('./api').AllocationStore} AllocationStore - * @typedef {import('./api').StoreTableStore} StoreTableStore + * @typedef {import('./api.js').AllocationStore} AllocationStore + * @typedef {import('./api.js').StoreTableStore} StoreTableStore * @typedef {{allocationStore: AllocationStore}} AllocationStoreCtx * @typedef {{storeTableStore: StoreTableStore}} StoreTableStoreCtx * * @param {"allocationStore" | "storeTableStore"} store - * @param {import('./api').SpaceBillingInstruction} instruction + * @param {import('./api.js').SpaceBillingInstruction} instruction * @param { AllocationStoreCtx | StoreTableStoreCtx} ctx * @returns {Promise>} */ diff --git a/billing/lib/ucan-stream.js b/billing/lib/ucan-stream.js index 027d4709..37629aed 100644 --- a/billing/lib/ucan-stream.js +++ b/billing/lib/ucan-stream.js @@ -67,8 +67,8 @@ export const findSpaceUsageDeltas = messages => { * * @param {import('./api.js').UsageDelta[]} deltas * @param {{ - * spaceDiffStore: import('./api').SpaceDiffStore - * consumerStore: import('./api').ConsumerStore + * spaceDiffStore: import('./api.js').SpaceDiffStore + * consumerStore: import('./api.js').ConsumerStore * }} ctx */ export const storeSpaceUsageDeltas = async (deltas, ctx) => { @@ -118,8 +118,8 @@ export const storeSpaceUsageDeltas = async (deltas, ctx) => { } /** - * @param {import('./api').UcanStreamMessage} m - * @returns {m is import('./api').UcanReceiptMessage} + * @param {import('./api.js').UcanStreamMessage} m + * @returns {m is import('./api.js').UcanReceiptMessage} */ const isReceipt = m => m.type === 'receipt' @@ -169,8 +169,8 @@ const isStoreRemoveSuccess = r => /** * @template {import('@ucanto/interface').Ability} Can * @template {import('@ucanto/interface').Unit} Caveats - * @param {import('./api').UcanReceiptMessage} m + * @param {import('./api.js').UcanReceiptMessage} m * @param {import('@ucanto/interface').TheCapabilityParser>} cap - * @returns {m is import('./api').UcanReceiptMessage<[import('@ucanto/interface').Capability]>} + * @returns {m is import('./api.js').UcanReceiptMessage<[import('@ucanto/interface').Capability]>} */ const isReceiptForCapability = (m, cap) => m.value.att.some(c => c.can === cap.can) diff --git a/billing/queues/client.js b/billing/queues/client.js index 4c1930d5..10e64622 100644 --- a/billing/queues/client.js +++ b/billing/queues/client.js @@ -14,9 +14,9 @@ export const connectQueue = target => * @param {{ region: string } | import('@aws-sdk/client-sqs').SQSClient} conf * @param {object} context * @param {URL} context.url - * @param {import('../lib/api').Validator} context.validate - * @param {import('../lib/api').Encoder} context.encode - * @returns {import('../lib/api').QueueAdder} + * @param {import('../lib/api.js').Validator} context.validate + * @param {import('../lib/api.js').Encoder} context.encode + * @returns {import('../lib/api.js').QueueAdder} */ export function createQueueAdderClient (conf, context) { const client = connectQueue(conf) diff --git a/billing/scripts/space-allocations-snapshot/index.js b/billing/scripts/space-allocations-snapshot/index.js index 23bb349c..592a8efd 100644 --- a/billing/scripts/space-allocations-snapshot/index.js +++ b/billing/scripts/space-allocations-snapshot/index.js @@ -309,12 +309,12 @@ async function exportSnapshotToCSV() { /** @type {Array<[string, string, bigint, string, string]>} */ const snapshot = [] - for (const customer of /** @type {Array} */ ( + for (const customer of /** @type {Array} */ ( Object.keys(result) )) { for (const spaceAllocation of result[customer].spaceAllocations) { const [space, { size }] = - /** @type [import('../../lib/api').ConsumerDID, {size:bigint, usage:bigint}] */ ( + /** @type [import('../../lib/api.js').ConsumerDID, {size:bigint, usage:bigint}] */ ( Object.entries(spaceAllocation)[0] ) @@ -340,7 +340,7 @@ async function calculateAndExportUsageSummary() { const usageSummary = [] const duration = to.getTime() - from.getTime() - for (const customer of /** @type {Array} */ ( + for (const customer of /** @type {Array} */ ( Object.keys(result) )) { if (!result[customer].product) { diff --git a/billing/tables/allocations.js b/billing/tables/allocations.js index d4ba043a..88c494c3 100644 --- a/billing/tables/allocations.js +++ b/billing/tables/allocations.js @@ -41,7 +41,7 @@ const indexName = 'space-insertedAt-index' /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').AllocationStore} + * @returns {import('../lib/api.js').AllocationStore} */ export const createAllocationStore = (conf, { tableName }) => ({ ...createStoreGetterClient(conf, { tableName, encodeKey, decode }), @@ -73,12 +73,12 @@ export const createAllocationStore = (conf, { tableName }) => ({ * conf: { region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient, * tableName: string, * indexName: string, - * decode: import('../lib/api').Decoder }} listBetweenConfig + * decode: import('../lib/api.js').Decoder }} listBetweenConfig * @param {{ - * space: import('../lib/api').ConsumerDID, + * space: import('../lib/api.js').ConsumerDID, * from: Date, * to: Date, - * options?: import('../lib/api').Pageable }} listBetweenParams + * options?: import('../lib/api.js').Pageable }} listBetweenParams */ export async function listBetweenWithConfig( listBetweenConfig, diff --git a/billing/tables/client.js b/billing/tables/client.js index efd2612a..c1e26345 100644 --- a/billing/tables/client.js +++ b/billing/tables/client.js @@ -15,9 +15,9 @@ export const connectTable = target => * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {object} context * @param {string} context.tableName - * @param {import('../lib/api').Validator} context.validate - * @param {import('../lib/api').Encoder} context.encode - * @returns {import('../lib/api').StorePutter} + * @param {import('../lib/api.js').Validator} context.validate + * @param {import('../lib/api.js').Encoder} context.encode + * @returns {import('../lib/api.js').StorePutter} */ export const createStorePutterClient = (conf, context) => { const client = connectTable(conf) @@ -59,9 +59,9 @@ export const createStorePutterClient = (conf, context) => { * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {object} context * @param {string} context.tableName - * @param {import('../lib/api').Validator} context.validate - * @param {import('../lib/api').Encoder} context.encode - * @returns {import('../lib/api').StoreBatchPutter} + * @param {import('../lib/api.js').Validator} context.validate + * @param {import('../lib/api.js').Encoder} context.encode + * @returns {import('../lib/api.js').StoreBatchPutter} */ export const createStoreBatchPutterClient = (conf, context) => { const client = connectTable(conf) @@ -107,9 +107,9 @@ export const createStoreBatchPutterClient = (conf, context) => { * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {object} context * @param {string} context.tableName - * @param {import('../lib/api').Encoder} context.encodeKey - * @param {import('../lib/api').Decoder} context.decode - * @returns {import('../lib/api').StoreGetter} + * @param {import('../lib/api.js').Encoder} context.encodeKey + * @param {import('../lib/api.js').Decoder} context.decode + * @returns {import('../lib/api.js').StoreGetter} */ export const createStoreGetterClient = (conf, context) => { const client = connectTable(conf) @@ -154,8 +154,8 @@ export const createStoreGetterClient = (conf, context) => { * @template {object} K * @template V * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf - * @param {import('../lib/api').CreateStoreListerContext} context - * @returns {import('../lib/api').StoreLister} + * @param {import('../lib/api.js').CreateStoreListerContext} context + * @returns {import('../lib/api.js').StoreLister} */ export const createStoreListerClient = (conf, context) => { const client = connectTable(conf) diff --git a/billing/tables/consumer.js b/billing/tables/consumer.js index fc4d1e02..fc883b7a 100644 --- a/billing/tables/consumer.js +++ b/billing/tables/consumer.js @@ -4,7 +4,7 @@ import { encodeKey, decode, lister } from '../data/consumer.js' /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').ConsumerStore} + * @returns {import('../lib/api.js').ConsumerStore} */ export const createConsumerStore = (conf, { tableName }) => ({ ...createStoreGetterClient(conf, { tableName, encodeKey, decode }), diff --git a/billing/tables/customer.js b/billing/tables/customer.js index aca10ca3..f82b45e3 100644 --- a/billing/tables/customer.js +++ b/billing/tables/customer.js @@ -37,7 +37,7 @@ export const customerTableProps = { /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').CustomerStore} + * @returns {import('../lib/api.js').CustomerStore} */ export const createCustomerStore = (conf, { tableName }) => ({ ...createStoreGetterClient(conf, { tableName, encodeKey, decode }), diff --git a/billing/tables/space-diff.js b/billing/tables/space-diff.js index 247b8090..69e9bf18 100644 --- a/billing/tables/space-diff.js +++ b/billing/tables/space-diff.js @@ -33,7 +33,7 @@ export const spaceDiffTableProps = { /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').SpaceDiffStore} + * @returns {import('../lib/api.js').SpaceDiffStore} */ export const createSpaceDiffStore = (conf, { tableName }) => ({ ...createStoreBatchPutterClient(conf, { tableName, validate, encode }), diff --git a/billing/tables/space-snapshot.js b/billing/tables/space-snapshot.js index 3437a9ce..839dde45 100644 --- a/billing/tables/space-snapshot.js +++ b/billing/tables/space-snapshot.js @@ -31,7 +31,7 @@ export const spaceSnapshotTableProps = { /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').SpaceSnapshotStore} + * @returns {import('../lib/api.js').SpaceSnapshotStore} */ export const createSpaceSnapshotStore = (conf, { tableName }) => ({ ...createStorePutterClient(conf, { tableName, validate, encode }), diff --git a/billing/tables/subscription.js b/billing/tables/subscription.js index 597010f9..42ae962d 100644 --- a/billing/tables/subscription.js +++ b/billing/tables/subscription.js @@ -4,7 +4,7 @@ import { decode, encodeKey, lister } from '../data/subscription.js' /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').SubscriptionStore} + * @returns {import('../lib/api.js').SubscriptionStore} */ export const createSubscriptionStore = (conf, { tableName }) => ({ ...createStoreGetterClient(conf, { tableName, encodeKey, decode }), diff --git a/billing/tables/usage.js b/billing/tables/usage.js index 87298d2f..59fcc719 100644 --- a/billing/tables/usage.js +++ b/billing/tables/usage.js @@ -39,7 +39,7 @@ export const usageTableProps = { /** * @param {{ region: string } | import('@aws-sdk/client-dynamodb').DynamoDBClient} conf * @param {{ tableName: string }} context - * @returns {import('../lib/api').UsageStore} + * @returns {import('../lib/api.js').UsageStore} */ export const createUsageStore = (conf, { tableName }) => createStorePutterClient(conf, { tableName, validate, encode }) diff --git a/billing/test/helpers/consumer.js b/billing/test/helpers/consumer.js index ab87c7dc..20a999e9 100644 --- a/billing/test/helpers/consumer.js +++ b/billing/test/helpers/consumer.js @@ -5,8 +5,8 @@ import { randomDID } from './did.js' import { randomInteger } from './math.js' /** - * @param {Partial} [base] - * @returns {Promise} + * @param {Partial} [base] + * @returns {Promise} */ export const randomConsumer = async (base = {}) => ({ consumer: await randomDID(), diff --git a/billing/test/helpers/context.js b/billing/test/helpers/context.js index bbf41bcc..476a3463 100644 --- a/billing/test/helpers/context.js +++ b/billing/test/helpers/context.js @@ -167,7 +167,7 @@ export const createUCANStreamTestContext = async () => { } /** - * @returns {Promise} + * @returns {Promise} */ export const createEgressTrafficTestContext = async () => { await createAWSServices() @@ -223,11 +223,11 @@ export const createEgressTrafficTestContext = async () => { /** * @template C - * @param {import('../lib/api').TestSuite} suite + * @param {import('../lib/api.js').TestSuite} suite * @param {() => Promise} createContext */ export const bindTestContext = (suite, createContext) => { - /** @type {import('../lib/api').TestSuite} */ + /** @type {import('../lib/api.js').TestSuite} */ const test = {} for (const [name, impl] of Object.entries(suite)) { test[name] = async (assert) => impl(assert, await createContext()) diff --git a/billing/test/helpers/customer.js b/billing/test/helpers/customer.js index b789bb3d..da247165 100644 --- a/billing/test/helpers/customer.js +++ b/billing/test/helpers/customer.js @@ -4,8 +4,8 @@ import { randomDIDMailto } from './did.js' import { randomInteger } from './math.js' /** - * @param {Partial} [base] - * @returns {import('../../lib/api').Customer} + * @param {Partial} [base] + * @returns {import('../../lib/api.js').Customer} */ export const randomCustomer = (base = {}) => ({ customer: randomDIDMailto(), diff --git a/billing/test/helpers/egress.js b/billing/test/helpers/egress.js index 7b9b87ba..138c5f1c 100644 --- a/billing/test/helpers/egress.js +++ b/billing/test/helpers/egress.js @@ -2,8 +2,8 @@ import { randomLink } from './dag.js' import { randomDID } from './did.js' /** - * @param {import('../../lib/api').Customer} customer - * @returns {Promise} + * @param {import('../../lib/api.js').Customer} customer + * @returns {Promise} */ export const randomEgressEvent = async (customer) => ({ space: await randomDID(), diff --git a/billing/test/helpers/queue.js b/billing/test/helpers/queue.js index 08242e69..c38e87b9 100644 --- a/billing/test/helpers/queue.js +++ b/billing/test/helpers/queue.js @@ -5,7 +5,7 @@ import { Failure } from '@ucanto/server' /** * @template T - * @param {import("../lib/api").QueueRemover} q + * @param {import('../lib/api.js').QueueRemover} q */ export const collectQueueMessages = async q => { /** @type {T[]} */ @@ -32,8 +32,8 @@ export const connectQueue = target => * @param {{ region: string } | import('@aws-sdk/client-sqs').SQSClient} conf * @param {object} context * @param {URL} context.url - * @param {import('../../lib/api').Decoder} context.decode - * @returns {import('../lib/api').QueueRemover} + * @param {import('../../lib/api.js').Decoder} context.decode + * @returns {import('../lib/api.js').QueueRemover} */ export function createQueueRemoverClient (conf, context) { const client = connectQueue(conf) diff --git a/billing/test/helpers/subscription.js b/billing/test/helpers/subscription.js index 3cb3b485..4e2ed32e 100644 --- a/billing/test/helpers/subscription.js +++ b/billing/test/helpers/subscription.js @@ -4,8 +4,8 @@ import { randomDIDMailto } from './did.js' import { randomInteger } from './math.js' /** - * @param {Partial} [base] - * @returns {Promise} + * @param {Partial} [base] + * @returns {Promise} */ export const randomSubscription = async (base = {}) => ({ customer: randomDIDMailto(), diff --git a/billing/test/lib/billing-cron.js b/billing/test/lib/billing-cron.js index 03b52b39..962aac5a 100644 --- a/billing/test/lib/billing-cron.js +++ b/billing/test/lib/billing-cron.js @@ -3,7 +3,7 @@ import { enqueueCustomerBillingInstructions } from '../../lib/billing-cron.js' import { randomCustomer } from '../helpers/customer.js' import { collectQueueMessages } from '../helpers/queue.js' -/** @type {import('./api').TestSuite} */ +/** @type {import('./api.js').TestSuite} */ export const test = { 'should queue all the customers': async (/** @type {import('entail').assert} */ assert, ctx) => { const customers = [] diff --git a/billing/test/lib/customer-billing-queue.js b/billing/test/lib/customer-billing-queue.js index f7b5179c..ecf4dc17 100644 --- a/billing/test/lib/customer-billing-queue.js +++ b/billing/test/lib/customer-billing-queue.js @@ -5,7 +5,7 @@ import { randomCustomer } from '../helpers/customer.js' import { collectQueueMessages } from '../helpers/queue.js' import { randomSubscription } from '../helpers/subscription.js' -/** @type {import('./api').TestSuite} */ +/** @type {import('./api.js').TestSuite} */ export const test = { 'should queue all spaces for a customer': async (/** @type {import('entail').assert} */ assert, ctx) => { const customer = randomCustomer() diff --git a/billing/test/lib/egress-traffic.js b/billing/test/lib/egress-traffic.js index cc0b0e93..24d3922f 100644 --- a/billing/test/lib/egress-traffic.js +++ b/billing/test/lib/egress-traffic.js @@ -4,11 +4,11 @@ import { randomEgressEvent } from '../helpers/egress.js' import retry from 'p-retry' import * as DidMailto from '@storacha/did-mailto' -/** @type {import('./api').TestSuite} */ +/** @type {import('./api.js').TestSuite} */ export const test = { /** * @param {import('entail').assert} assert - * @param {import('./api').EgressTrafficTestContext} ctx + * @param {import('./api.js').EgressTrafficTestContext} ctx */ 'should process all the egress traffic events from the queue': async (assert, ctx) => { /** @type {string | null} */ @@ -31,7 +31,7 @@ export const test = { // 1. Add egress events to the queue to simulate egress traffic from the Freeway worker const maxEvents = 5 - /** @type {import('../../lib/api').EgressTrafficData[]} */ + /** @type {import('../../lib/api.js').EgressTrafficData[]} */ const events = await Promise.all( Array.from( { length: maxEvents }, diff --git a/billing/test/lib/space-billing-queue.js b/billing/test/lib/space-billing-queue.js index c336c415..be56c5c2 100644 --- a/billing/test/lib/space-billing-queue.js +++ b/billing/test/lib/space-billing-queue.js @@ -4,7 +4,7 @@ import { randomConsumer } from '../helpers/consumer.js' import { randomCustomer } from '../helpers/customer.js' import { randomLink } from '../helpers/dag.js' -/** @type {import('./api').TestSuite} */ +/** @type {import('./api.js').TestSuite} */ export const test = { 'should do basic usage calculation for new space with single item added at snapshot time': async (/** @type {import('entail').assert} */ assert, ctx) => { const customer = randomCustomer() diff --git a/billing/test/lib/ucan-stream.js b/billing/test/lib/ucan-stream.js index 0609bbca..dcbaade5 100644 --- a/billing/test/lib/ucan-stream.js +++ b/billing/test/lib/ucan-stream.js @@ -7,7 +7,7 @@ import { randomConsumer } from '../helpers/consumer.js' import { randomLink } from '../helpers/dag.js' import { randomDID, randomDIDKey } from '../helpers/did.js' -/** @type {import('./api').TestSuite} */ +/** @type {import('./api.js').TestSuite} */ export const test = { 'should filter UCANs': async (/** @type {import('entail').assert} */ assert, ctx) => { /** @type {import('../../lib/api.js').UcanStreamMessage[]} */ diff --git a/filecoin/functions/handle-piece-insert-to-content-claim.js b/filecoin/functions/handle-piece-insert-to-content-claim.js index 52709f0c..9fbd8b76 100644 --- a/filecoin/functions/handle-piece-insert-to-content-claim.js +++ b/filecoin/functions/handle-piece-insert-to-content-claim.js @@ -16,7 +16,7 @@ Sentry.AWSLambda.init({ }) /** - * @typedef {import('../types').PieceStoreRecord} PieceStoreRecord + * @typedef {import('../types.js').PieceStoreRecord} PieceStoreRecord */ /** diff --git a/filecoin/functions/handle-piece-insert-to-filecoin-submit.js b/filecoin/functions/handle-piece-insert-to-filecoin-submit.js index 411fdf63..cb46881d 100644 --- a/filecoin/functions/handle-piece-insert-to-filecoin-submit.js +++ b/filecoin/functions/handle-piece-insert-to-filecoin-submit.js @@ -18,7 +18,7 @@ Sentry.AWSLambda.init({ }) /** - * @typedef {import('../types').PieceStoreRecord} PieceStoreRecord + * @typedef {import('../types.js').PieceStoreRecord} PieceStoreRecord */ /** diff --git a/filecoin/functions/handle-piece-status-update.js b/filecoin/functions/handle-piece-status-update.js index 22d8f71b..ac374f95 100644 --- a/filecoin/functions/handle-piece-status-update.js +++ b/filecoin/functions/handle-piece-status-update.js @@ -18,7 +18,7 @@ Sentry.AWSLambda.init({ }) /** - * @typedef {import('../types').PieceStoreRecord} PieceStoreRecord + * @typedef {import('../types.js').PieceStoreRecord} PieceStoreRecord */ /** diff --git a/filecoin/metrics.js b/filecoin/metrics.js index 599a6cd7..4e4d660f 100644 --- a/filecoin/metrics.js +++ b/filecoin/metrics.js @@ -25,7 +25,7 @@ import { DecodeBlockOperationError, NotFoundWorkflowError } from './errors.js' * - AGGREGATE_ACCEPT_TOTAL: increment number of `aggregate/accept` success receipts * * @param {import('@storacha/upload-service-infra-upload-api/types.js').UcanStreamInvocation[]} ucanInvocations - * @param {import('./types').FilecoinMetricsCtx} ctx + * @param {import('./types.js').FilecoinMetricsCtx} ctx */ export async function updateAggregateAcceptTotal (ucanInvocations, ctx) { const aggregateAcceptInvocations = ucanInvocations @@ -51,7 +51,7 @@ export async function updateAggregateAcceptTotal (ucanInvocations, ctx) { * - AGGREGATE_OFFER_PIECES_SIZE_TOTAL: increment size of pieces included of `aggregate/offer` success receipts * * @param {import('@storacha/upload-service-infra-upload-api/types.js').UcanStreamInvocation[]} ucanInvocations - * @param {import('./types').FilecoinAggregateOfferMetricsCtx} ctx + * @param {import('./types.js').FilecoinAggregateOfferMetricsCtx} ctx */ export async function updateAggregateOfferTotal (ucanInvocations, ctx) { // Get a Map of workflows that include aggregate offer receipts @@ -106,7 +106,7 @@ export async function updateAggregateOfferTotal (ucanInvocations, ctx) { * * @param {import('@storacha/upload-service-infra-upload-api/types.js').UcanStreamInvocation[]} ucanInvocations * @param {string} capability - * @param {import('./types').FilecoinAggregateOfferMetricsCtx} ctx + * @param {import('./types.js').FilecoinAggregateOfferMetricsCtx} ctx */ function getWorkflowsWithReceiptForCapability (ucanInvocations, capability, ctx) { return ucanInvocations @@ -138,7 +138,7 @@ function getWorkflowsWithReceiptForCapability (ucanInvocations, capability, ctx) /** * @param {string} taskCid - * @param {import('./types').FilecoinAggregateOfferMetricsCtx} ctx + * @param {import('./types.js').FilecoinAggregateOfferMetricsCtx} ctx */ async function getAgentMessage (taskCid, ctx) { // TODO: When we distinct between TaskCid and InvocationCid, we also need to see this mapping. diff --git a/filecoin/store/invocation.js b/filecoin/store/invocation.js index 4df71375..02a4ed50 100644 --- a/filecoin/store/invocation.js +++ b/filecoin/store/invocation.js @@ -21,7 +21,7 @@ export function createInvocationStore(region, bucketName, options = {}) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3client * @param {string} bucketName - * @returns {import('../types').InvocationBucket} + * @returns {import('../types.js').InvocationBucket} */ export const useInvocationStore = (s3client, bucketName) => { const store = Store.open({ diff --git a/filecoin/store/metrics.js b/filecoin/store/metrics.js index 8f5a985c..021a0cfa 100644 --- a/filecoin/store/metrics.js +++ b/filecoin/store/metrics.js @@ -25,7 +25,7 @@ export function createFilecoinMetricsTable (region, tableName, options = {}) { /** * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName - * @returns {import('../types').FilecoinMetricsStore} + * @returns {import('../types.js').FilecoinMetricsStore} */ export function useFilecoinMetricsTable (dynamoDb, tableName) { return { diff --git a/filecoin/store/piece.js b/filecoin/store/piece.js index 52156be0..09d5ef66 100644 --- a/filecoin/store/piece.js +++ b/filecoin/store/piece.js @@ -15,9 +15,9 @@ import { getDynamoClient } from '../../lib/aws/dynamo.js' * @typedef {import('@storacha/filecoin-api/storefront/api').PieceRecord} PieceRecord * @typedef {import('@storacha/filecoin-api/storefront/api').PieceRecordKey} PieceRecordKey * @typedef {{ status: PieceStatus }} PieceRecordQuery - * @typedef {import('../types').PieceStoreRecord} PieceStoreRecord - * @typedef {import('../types').PieceStoreRecordKey} PieceStoreRecordKey - * @typedef {import('../types').PieceStoreRecordStatus} PieceStoreRecordStatus + * @typedef {import('../types.js').PieceStoreRecord} PieceStoreRecord + * @typedef {import('../types.js').PieceStoreRecordKey} PieceStoreRecordKey + * @typedef {import('../types.js').PieceStoreRecordStatus} PieceStoreRecordStatus */ /** diff --git a/filecoin/store/workflow.js b/filecoin/store/workflow.js index 52b5b867..7a83f947 100644 --- a/filecoin/store/workflow.js +++ b/filecoin/store/workflow.js @@ -20,7 +20,7 @@ export function createWorkflowStore(region, bucketName, options = {}) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3client * @param {string} bucketName - * @returns {import('../types').WorkflowBucket} + * @returns {import('../types.js').WorkflowBucket} */ export const useWorkflowStore = (s3client, bucketName) => { return { diff --git a/indexer/data/blocks-cars-position.js b/indexer/data/blocks-cars-position.js index 20c07539..4116789d 100644 --- a/indexer/data/blocks-cars-position.js +++ b/indexer/data/blocks-cars-position.js @@ -6,7 +6,7 @@ import { EncodeFailure } from './lib.js' * @typedef {import('../types.js').InferStoreRecord} BlocksCarsPositionStoreRecord */ -/** @type {import('../lib/api').Encoder} */ +/** @type {import('../lib/api.js').Encoder} */ export const encode = input => { try { return { diff --git a/indexer/test/helpers/table.js b/indexer/test/helpers/table.js index 5cdafdff..796e397f 100644 --- a/indexer/test/helpers/table.js +++ b/indexer/test/helpers/table.js @@ -10,8 +10,8 @@ import { connectTable } from '../../tables/client.js' * @param {object} context * @param {string} context.tableName * @param {import('../../lib/api.js').Encoder} context.encodeKey - * @param {import('../lib/api').Decoder} context.decode - * @returns {import('../lib/api').StoreLister} + * @param {import('../lib/api.js').Decoder} context.decode + * @returns {import('../lib/api.js').StoreLister} */ export const createStoreListerClient = (conf, context) => { const client = connectTable(conf) diff --git a/package-lock.json b/package-lock.json index 09e73b65..ac71b55f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30515,6 +30515,7 @@ "@storacha/access": "^1.0.0", "@storacha/capabilities": "^1.2.0", "@storacha/did-mailto": "^1.0.1", + "@storacha/indexing-service-client": "^2.0.0", "@storacha/upload-api": "^1.2.0", "@ucanto/client": "^9.0.1", "@ucanto/core": "^10.0.1", diff --git a/test/helpers/up-client.js b/test/helpers/up-client.js index e8f15f54..74dc5bda 100644 --- a/test/helpers/up-client.js +++ b/test/helpers/up-client.js @@ -19,7 +19,7 @@ dotenv.config({ path: fileURLToPath(new URL('../../.env', import.meta.url)) }) */ function getAuthLinkFromEmail (email, accessServiceUrl) { // forgive me for I have s̵i̵n̴n̴e̵d̴ ̸a̸n̵d̷ ̷p̶a̵r̵s̵e̸d̷ Ȟ̷̞T̷̢̈́M̸̼̿L̴̎ͅ ̵̗̍ẅ̵̝́ï̸ͅt̴̬̅ḫ̸̔ ̵͚̔ŗ̵͊e̸͍͐g̶̜͒ė̷͖x̴̱̌ - // TODO we should update the email and add an ID to this element to make this more robust - tracked in https://github.com/web3-storage/w3infra/issues/208 + // TODO we should update the email and add an ID to this element to make this more robust - tracked in https://github.com/storacha/w3infra/issues/208 const link = email.match(/ ({ can, with: resource })) ), - audience: DID.parse('did:web:staging.web3.storage') + audience: DID.parse('did:web:staging.upload.storacha.network') } } } @@ -111,7 +111,7 @@ export function getServiceProps (client, serviceUrl, capability) { */ function getAccessServiceConnection(serviceUrl) { const accessServiceURL = new URL(serviceUrl) - const accessServicePrincipal = DID.parse('did:web:staging.web3.storage') + const accessServicePrincipal = DID.parse('did:web:staging.upload.storacha.network') return connect({ id: accessServicePrincipal, @@ -128,7 +128,7 @@ function getAccessServiceConnection(serviceUrl) { */ function getUploadServiceConnection(serviceUrl) { const uploadServiceURL = new URL(serviceUrl) - const uploadServicePrincipal = DID.parse('did:web:staging.web3.storage') + const uploadServicePrincipal = DID.parse('did:web:staging.upload.storacha.network') return connect({ id: uploadServicePrincipal, diff --git a/tools/follow-filecoin-receipt-chain.js b/tools/follow-filecoin-receipt-chain.js index 3c4ebc5f..96e427f0 100644 --- a/tools/follow-filecoin-receipt-chain.js +++ b/tools/follow-filecoin-receipt-chain.js @@ -17,8 +17,8 @@ export async function followFilecoinReceiptChain () { const AWS_REGION = getRegion(ENV) const pieceTableName = getPieceTableName(ENV) - const invocationBucketName = getInvocationBucketName(ENV) - const workflowBucketName = getWorkflowBucketName(ENV) + const agentIndexBucketName = getAgentIndexBucketName(ENV) + const agentMessageBucketName = getAgentMessageBucketName(ENV) const did = getDid(ENV) let id = getServiceSigner({ @@ -27,7 +27,7 @@ export async function followFilecoinReceiptChain () { id = id.withDID(DID.parse(did).did()) const pieceInfo = Piece.fromString(PIECE_CID) - const receiptStore = createFilecoinReceiptStore(AWS_REGION, invocationBucketName, workflowBucketName) + const receiptStore = createFilecoinReceiptStore(AWS_REGION, agentIndexBucketName, agentMessageBucketName) const pieceStore = createPieceTable(AWS_REGION, pieceTableName) // Get piece in store @@ -146,7 +146,7 @@ function getPieceTableName (env) { /** * @param {string} env */ -function getInvocationBucketName (env) { +function getAgentIndexBucketName (env) { if (env === 'staging') { return 'invocation-store-staging-0' } @@ -157,7 +157,7 @@ function getInvocationBucketName (env) { /** * @param {string} env */ -function getWorkflowBucketName (env) { +function getAgentMessageBucketName (env) { if (env === 'staging') { return 'workflow-store-staging-0' } @@ -170,8 +170,8 @@ function getWorkflowBucketName (env) { */ function getDid (env) { if (env === 'staging') { - return 'did:web:staging.web3.storage' + return 'did:web:staging.upload.storacha.network' } - return 'did:web:web3.storage' + return 'did:web:upload.storacha.network' } diff --git a/tsconfig.json b/tsconfig.json index 82d01aa1..128e8313 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "jsx": "react-jsx", "jsxImportSource": "preact", "target": "ES2022", - "module": "ES2022", + "module": "NodeNext", "lib": ["ES2022", "DOM", "DOM.Iterable"], "noEmit": false, "noEmitOnError": true, @@ -22,7 +22,7 @@ "removeComments": false, // module resolution "esModuleInterop": true, - "moduleResolution": "Node", + "moduleResolution": "NodeNext", // linter checks "noImplicitReturns": false, "noFallthroughCasesInSwitch": true, diff --git a/upload-api/bridge/types.ts b/upload-api/bridge/types.ts index 9f821962..156bbee7 100644 --- a/upload-api/bridge/types.ts +++ b/upload-api/bridge/types.ts @@ -1,4 +1,4 @@ -import { PrincipalView } from "@ipld/dag-ucan/." +import { PrincipalView } from '@ipld/dag-ucan' import { Ability, DID, Delegation, Failure, Principal, Result, Receipt, OutcomeModel, Signature } from "@ucanto/interface" import { ed25519 } from '@ucanto/principal' diff --git a/upload-api/buckets/car-store.js b/upload-api/buckets/car-store.js index f569c9c5..ecbcfd4f 100644 --- a/upload-api/buckets/car-store.js +++ b/upload-api/buckets/car-store.js @@ -21,7 +21,7 @@ export function createCarStore(region, bucketName, options) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3 * @param {string} bucketName - * @returns {import('../types').CarStore} + * @returns {import('../types.js').CarStore} */ export function useCarStore(s3, bucketName) { return { diff --git a/upload-api/buckets/delegations-store.js b/upload-api/buckets/delegations-store.js index 588cac5a..01d43c4c 100644 --- a/upload-api/buckets/delegations-store.js +++ b/upload-api/buckets/delegations-store.js @@ -38,7 +38,7 @@ function createDelegationsBucketKey (cid) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3client * @param {string} bucketName - * @returns {import('../types').DelegationsBucket} + * @returns {import('../types.js').DelegationsBucket} */ export const useDelegationsStore = (s3client, bucketName) => { return { diff --git a/upload-api/buckets/invocation-store.js b/upload-api/buckets/invocation-store.js index 23bc9e15..e19bd43a 100644 --- a/upload-api/buckets/invocation-store.js +++ b/upload-api/buckets/invocation-store.js @@ -21,7 +21,7 @@ export function createInvocationStore(region, bucketName, options = {}) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3client * @param {string} bucketName - * @returns {import('../types').InvocationBucket} + * @returns {import('../types.js').InvocationBucket} */ export const useInvocationStore = (s3client, bucketName) => { return { diff --git a/upload-api/buckets/workflow-store.js b/upload-api/buckets/workflow-store.js index 31c689ed..86585b79 100644 --- a/upload-api/buckets/workflow-store.js +++ b/upload-api/buckets/workflow-store.js @@ -21,7 +21,7 @@ export function createWorkflowStore(region, bucketName, options = {}) { /** * @param {import('@aws-sdk/client-s3').S3Client} s3client * @param {string} bucketName - * @returns {import('../types').WorkflowBucket} + * @returns {import('../types.js').WorkflowBucket} */ export const useWorkflowStore = (s3client, bucketName) => { return { diff --git a/upload-api/config.js b/upload-api/config.js index d70f572e..67e0a5cd 100644 --- a/upload-api/config.js +++ b/upload-api/config.js @@ -44,8 +44,8 @@ export function parseServiceDids(serviceDids) { * @returns */ export function getServiceConnection (config) { - const servicePrincipal = DID.parse(config.did) // 'did:web:web3.storage' - const serviceURL = new URL(config.url) // 'https://tracker.web3.storage' + const servicePrincipal = DID.parse(config.did) // 'did:web:upload.storacha.network' + const serviceURL = new URL(config.url) // 'https://upload.storacha.network' const serviceConnection = connect({ id: servicePrincipal, diff --git a/upload-api/external-services/blob-retriever.js b/upload-api/external-services/blob-retriever.js new file mode 100644 index 00000000..3373f75d --- /dev/null +++ b/upload-api/external-services/blob-retriever.js @@ -0,0 +1,53 @@ +import { ok, error } from '@ucanto/core' +import { BlobNotFound } from '@storacha/upload-api/blob' +import * as Digest from 'multiformats/hashes/digest' +import { equals } from 'multiformats/bytes' + +/** + * @import * as API from '@storacha/upload-api' + * @typedef {API.Link | { digest: Uint8Array }} LinkOrDigest + * @typedef {{ + * content: LinkOrDigest + * location: string[] + * range?: { offset: number, length?: number } + * }} LocationCaveats + */ + +/** + * @param {import('@storacha/indexing-service-client/api').IndexingServiceClient} client + * @returns {API.BlobRetriever} + */ +export const create = (client) => { + return { + /** @type {API.BlobRetriever['stream']} */ + async stream(digest) { + const result = await client.queryClaims({ hashes: [digest] }) + if (result.error) { + // @ts-expect-error need to align blob retriever error types + return result + } + + for (const claim of result.ok.claims.values()) { + const cap = claim.capabilities[0] + if (cap.can === 'assert/location') { + const caveats = /** @type {LocationCaveats} */ (cap.nb) + const contentDigest = toDigest(caveats.content) + if (equals(contentDigest.bytes, digest.bytes)) { + const headers = new Headers() + if (caveats.range) { + headers.set('Range', `bytes=${caveats.range.offset}-${caveats.range.length || ''}`) + } + const res = await fetch(caveats.location[0], { headers }) + if (!res.body) throw new Error('missing response body') + return ok(res.body) + } + } + } + return error(new BlobNotFound(digest)) + }, + } +} + +/** @param {LinkOrDigest} input */ +const toDigest = input => + 'digest' in input ? Digest.decode(input.digest) : input.multihash diff --git a/upload-api/external-services/ipni-service.js b/upload-api/external-services/ipni-service.js index 29b42f8c..bc55fd83 100644 --- a/upload-api/external-services/ipni-service.js +++ b/upload-api/external-services/ipni-service.js @@ -13,9 +13,10 @@ import { getSQSClient } from '../../lib/aws/sqs.js' const CONCURRENCY = 10 /** + * @deprecated * @param {{ url: URL, region: string }} blockAdvertisementPublisherQueueConfig * @param {{ url: URL, region: string }} blockIndexWriterQueueConfig - * @param {import('@storacha/upload-api').BlobsStorage} blobsStorage + * @param {import('@web3-storage/upload-api').BlobsStorage} blobsStorage */ export const createIPNIService = (blockAdvertisementPublisherQueueConfig, blockIndexWriterQueueConfig, blobsStorage) => { const blockAdvertPublisherQueue = new BlockAdvertisementPublisherQueue({ @@ -30,10 +31,11 @@ export const createIPNIService = (blockAdvertisementPublisherQueueConfig, blockI } /** + * @deprecated * @param {BlockAdvertisementPublisherQueue} blockAdvertPublisherQueue * @param {BlockIndexWriterQueue} blockIndexWriterQueue - * @param {import('@storacha/upload-api').BlobsStorage} blobsStorage - * @returns {import('@storacha/upload-api').IPNIService} + * @param {import('@web3-storage/upload-api').BlobsStorage} blobsStorage + * @returns {import('@web3-storage/upload-api').IPNIService} */ export const useIPNIService = (blockAdvertPublisherQueue, blockIndexWriterQueue, blobsStorage) => ({ /** @param {import('@storacha/upload-api').ShardedDAGIndex} index */ diff --git a/upload-api/external-services/router.js b/upload-api/external-services/router.js new file mode 100644 index 00000000..e00d5daa --- /dev/null +++ b/upload-api/external-services/router.js @@ -0,0 +1,97 @@ +import { ok, error, Failure, Invocation } from '@ucanto/core' +import { parse } from '@ipld/dag-ucan/did' +import { CAR, HTTP } from '@ucanto/transport' +import { connect } from '@ucanto/client' + +/** + * @import * as API from '../types.js' + * @import { BlobAPI } from '@storacha/upload-api/types' + */ + +/** + * @param {API.StorageProviderTable} storageProviderTable + * @param {import('@ucanto/interface').Signer} serviceID + * @returns {BlobAPI.RoutingService} + */ +export const create = (storageProviderTable, serviceID) => ({ + selectStorageProvider: async () => { + const ids = await storageProviderTable.list() + if (!ids.length) return error(new CandidateUnavailableError()) + const provider = parse(ids[getWeightedRandomInt(ids.map(id => id.weight))].provider) + return ok(provider) + }, + configureInvocation: async (provider, capability, options) => { + const record = await storageProviderTable.get(provider.did()) + if (!record) { + return error(new ProofUnavailableError(`provider not found: ${provider.did()}`)) + } + const { endpoint, proof } = record + + const invocation = Invocation.invoke({ + ...options, + issuer: serviceID, + audience: provider, + capability, + proofs: [proof], + }) + const channel = HTTP.open({ url: endpoint, method: 'POST' }) + const connection = connect({ id: provider, codec: CAR.outbound, channel }) + + return ok({ invocation, connection }) + }, +}) + +/** + * Generates a weighted random index based on the provided weights. + * + * @param {number[]} weights - An array of weights. + * @returns {number} - The index of the selected weight. + */ +const getWeightedRandomInt = (weights) => { + const totalWeight = weights.reduce((sum, weight) => sum + weight, 0) + let random = Math.random() * totalWeight + + for (let i = 0; i < weights.length; i++) { + random -= weights[i] + if (random <= 0) { + return i + } + } + throw new Error("did not find a weight - should never reach here") +} + +export class ProofUnavailableError extends Failure { + static name = /** @type {const} */ ('ProofUnavailable') + + get name() { + return ProofUnavailableError.name + } + + /** @param {string} [reason] */ + constructor(reason) { + super() + this.reason = reason + } + + describe() { + return this.reason ?? 'proof unavailable' + } +} + +export class CandidateUnavailableError extends Failure { + static name = /** @type {const} */ ('CandidateUnavailable') + + get name() { + return CandidateUnavailableError.name + } + + /** @param {string} [reason] */ + constructor(reason) { + super() + this.reason = reason + } + + describe() { + return this.reason ?? 'no candidates available for blob allocation' + } +} diff --git a/upload-api/functions/bridge.js b/upload-api/functions/bridge.js index 60401d5c..554b6420 100644 --- a/upload-api/functions/bridge.js +++ b/upload-api/functions/bridge.js @@ -18,7 +18,7 @@ Sentry.AWSLambda.init({ /** * - * @type {import('../bridge/types').AuthSecretHeaderParser} + * @type {import('../bridge/types.js').AuthSecretHeaderParser} */ async function parseAuthSecretHeader(headerValue) { const secret = base64url.decode(headerValue) @@ -27,7 +27,7 @@ async function parseAuthSecretHeader(headerValue) { } /** - * @type {import('../bridge/types').AuthorizationHeaderParser} + * @type {import('../bridge/types.js').AuthorizationHeaderParser} */ async function parseAuthorizationHeader(headerValue) { const result = await Delegation.extract(base64url.decode(headerValue)) @@ -41,14 +41,14 @@ async function parseAuthorizationHeader(headerValue) { } /** - * @type {import('../bridge/types').TaskParser} + * @type {import('../bridge/types.js').TaskParser} */ async function parseTask(maybeTask) { if (Array.isArray(maybeTask)) { return (maybeTask[0] && maybeTask[1] && maybeTask[2]) ? { // TODO: should we do more verification of the format of these arguments? // weird to have to cast twice, but TypeScript complains unless I cast back to unknown first - ok: /** @type {import('../bridge/types').Task} */(/** @type {unknown} */(maybeTask)) + ok: /** @type {import('../bridge/types.js').Task} */(/** @type {unknown} */(maybeTask)) } : { error: { name: 'InvalidTask', @@ -67,12 +67,12 @@ async function parseTask(maybeTask) { /** * - * @type {import('../bridge/types').TasksParser} + * @type {import('../bridge/types.js').TasksParser} */ async function parseTasks(maybeTasks) { if (Array.isArray(maybeTasks)) { /** - * @type {import('../bridge/types').Task[]} + * @type {import('../bridge/types.js').Task[]} */ const tasks = [] for (const maybeTask of maybeTasks) { @@ -97,7 +97,7 @@ async function parseTasks(maybeTasks) { } /** - * @type {import('../bridge/types').BodyParser} + * @type {import('../bridge/types.js').BodyParser} */ async function parseBody(body, contentType) { const bodyBytes = await streamToArrayBuffer(body) @@ -133,7 +133,7 @@ async function parseBody(body, contentType) { /** * @param {import('aws-lambda').APIGatewayProxyEventV2} request - * @returns {import('../bridge/types').ParsedRequest} + * @returns {import('../bridge/types.js').ParsedRequest} */ function parseAwsLambdaRequest(request) { const authSecretHeader = request.headers['x-auth-secret'] @@ -178,7 +178,7 @@ function serializeBridgeReceipts(receipts) { /** * - * @type {import('../bridge/types').TasksExecutor} + * @type {import('../bridge/types.js').TasksExecutor} */ export async function invokeAndExecuteTasks( issuer, servicePrincipal, serviceURL, tasks, delegation @@ -220,7 +220,7 @@ export async function invokeAndExecuteTasks( * see: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format * * @param {import('aws-lambda').APIGatewayProxyEventV2} request - * @param {import('../bridge/types').BridgeRequestContext} context + * @param {import('../bridge/types.js').BridgeRequestContext} context */ export async function handleBridgeRequest(request, context) { try { @@ -321,7 +321,7 @@ function createBridgeHandler() { } const serviceURL = new URL(ACCESS_SERVICE_URL) /** - * @type {import('../bridge/types').BridgeRequestContext} + * @type {import('../bridge/types.js').BridgeRequestContext} */ const context = { serviceDID, diff --git a/upload-api/functions/ucan-invocation-router.js b/upload-api/functions/ucan-invocation-router.js index d763b57a..355d0bd2 100644 --- a/upload-api/functions/ucan-invocation-router.js +++ b/upload-api/functions/ucan-invocation-router.js @@ -53,7 +53,7 @@ Sentry.AWSLambda.init({ export { API } /** - * @typedef {import('../types').Receipt} Receipt + * @typedef {import('../types.js').Receipt} Receipt * @typedef {import('@ucanto/interface').Block} BlockReceipt * @typedef {object} ExecuteCtx * @property {import('@ucanto/interface').Signer} signer diff --git a/upload-api/functions/validate-email.jsx b/upload-api/functions/validate-email.jsx index 75262c39..716bb22e 100644 --- a/upload-api/functions/validate-email.jsx +++ b/upload-api/functions/validate-email.jsx @@ -14,13 +14,15 @@ import { createRevocationsTable } from '../stores/revocations.js' import { createReferralStore } from '../stores/referrals.js' import * as AgentStore from '../stores/agent.js' import { useProvisionStore } from '../stores/provisions.js' +// @ts-expect-error // eslint-disable-next-line import/extensions import * as htmlStoracha from '../html-storacha' +// @ts-expect-error // eslint-disable-next-line import/extensions import * as htmlW3s from '../html-w3s' import { createRateLimitTable } from '../tables/rate-limit.js' import { createSpaceMetricsTable } from '../tables/space-metrics.js' -import { createCustomerStore } from '@storacha/upload-service-infra-billing/tables/customer' +import { createCustomerStore } from '../../billing/tables/customer.js' const html = process.env.HOSTED_ZONE === 'upload.storacha.network' ? htmlW3s : htmlStoracha @@ -82,8 +84,8 @@ function createAuthorizeContext() { R2_ACCESS_KEY_ID = '', R2_SECRET_ACCESS_KEY = '', R2_DELEGATION_BUCKET_NAME = '', - INVOCATION_BUCKET_NAME = '', - WORKFLOW_BUCKET_NAME = '', + AGENT_INDEX_BUCKET_NAME = '', + AGENT_MESSAGE_BUCKET_NAME = '', POSTMARK_TOKEN = '', SUBSCRIPTION_TABLE_NAME = '', CONSUMER_TABLE_NAME = '', @@ -102,9 +104,9 @@ function createAuthorizeContext() { const { PRIVATE_KEY } = Config const invocationBucket = createInvocationStore( AWS_REGION, - INVOCATION_BUCKET_NAME + AGENT_INDEX_BUCKET_NAME ) - const workflowBucket = createWorkflowStore(AWS_REGION, WORKFLOW_BUCKET_NAME) + const workflowBucket = createWorkflowStore(AWS_REGION, AGENT_MESSAGE_BUCKET_NAME) const delegationBucket = createDelegationsStore( R2_ENDPOINT, R2_ACCESS_KEY_ID, @@ -140,8 +142,8 @@ function createAuthorizeContext() { }, region: AWS_REGION, buckets: { - message: { name: WORKFLOW_BUCKET_NAME }, - index: { name: INVOCATION_BUCKET_NAME }, + message: { name: AGENT_MESSAGE_BUCKET_NAME }, + index: { name: AGENT_INDEX_BUCKET_NAME }, }, }, stream: { diff --git a/upload-api/metrics.js b/upload-api/metrics.js index 35b2795b..349a439a 100644 --- a/upload-api/metrics.js +++ b/upload-api/metrics.js @@ -14,7 +14,7 @@ import { /** * @typedef {import('@ucanto/interface').Capability} Capability * @typedef {import('@storacha/upload-api').StoreRemoveSuccess} StoreRemoveSuccess - * @typedef {import('@storacha/upload-api').BlobRemoveSuccess} BlobRemoveSuccess + * @typedef {import('@storacha/upload-api').SpaceBlobRemoveSuccess} SpaceBlobRemoveSuccess */ /** @@ -32,7 +32,7 @@ import { * - UPLOAD_REMOVE_TOTAL: increment number of `upload/remove` success receipts * * @param {import('./types.js').UcanStreamInvocation[]} ucanInvocations - * @param {import('./types').MetricsCtx} ctx + * @param {import('./types.js').MetricsCtx} ctx */ export async function updateAdminMetrics (ucanInvocations, ctx) { const receipts = getReceiptPerCapability(ucanInvocations) @@ -53,7 +53,7 @@ export async function updateAdminMetrics (ucanInvocations, ctx) { // Append size for `blob/remove` receipts const blobRemoveReceipts = await Promise.all((receipts.get(BLOB_REMOVE) || []).map(async r => { - const blobRemoveSuccess = /** @type {BlobRemoveSuccess} */ (r.out.ok) + const blobRemoveSuccess = /** @type {SpaceBlobRemoveSuccess} */ (r.out.ok) r.nb.size = blobRemoveSuccess?.size return r })) @@ -91,7 +91,7 @@ export async function updateAdminMetrics (ucanInvocations, ctx) { * - UPLOAD_REMOVE_TOTAL: increment number of `upload/remove` success receipts for a space * * @param {import('./types.js').UcanStreamInvocation[]} ucanInvocations - * @param {import('./types').SpaceMetricsCtx} ctx + * @param {import('./types.js').SpaceMetricsCtx} ctx */ export async function updateSpaceMetrics (ucanInvocations, ctx) { const receipts = getReceiptPerCapability(ucanInvocations) @@ -112,7 +112,7 @@ export async function updateSpaceMetrics (ucanInvocations, ctx) { // Append size for `blob/remove` receipts const blobRemoveReceipts = await Promise.all((receipts.get(BLOB_REMOVE) || []).map(async r => { - const blobRemoveSuccess = /** @type {BlobRemoveSuccess} */ (r.out.ok) + const blobRemoveSuccess = /** @type {SpaceBlobRemoveSuccess} */ (r.out.ok) r.nb.size = blobRemoveSuccess?.size return r })) @@ -149,7 +149,7 @@ function normalizeCapsPerSpaceTotal (capabilities) { }) } return acc - }, /** @type {import('./types').SpaceMetricsItem[]} */ ([])) + }, /** @type {import('./types.js').SpaceMetricsItem[]} */ ([])) return res } @@ -171,7 +171,7 @@ function normalizeCapsPerSpaceSize (capabilities) { acc.push({ space: c.with, value: size }) } return acc - }, /** @type {import('./types').SpaceMetricsItem[]} */ ([])) + }, /** @type {import('./types.js').SpaceMetricsItem[]} */ ([])) return res } @@ -180,7 +180,7 @@ function normalizeCapsPerSpaceSize (capabilities) { * Get a map of receipts per capability. * * @param {import('./types.js').UcanStreamInvocation[]} ucanInvocations - * @returns {Map>} + * @returns {Map>} */ function getReceiptPerCapability (ucanInvocations) { return ucanInvocations diff --git a/upload-api/package.json b/upload-api/package.json index ffacd4e8..6eab93a1 100644 --- a/upload-api/package.json +++ b/upload-api/package.json @@ -18,6 +18,7 @@ "@storacha/access": "^1.0.0", "@storacha/capabilities": "^1.2.0", "@storacha/did-mailto": "^1.0.1", + "@storacha/indexing-service-client": "^2.0.0", "@storacha/upload-api": "^1.2.0", "@ucanto/client": "^9.0.1", "@ucanto/core": "^10.0.1", diff --git a/upload-api/stores/blob-registry.js b/upload-api/stores/blob-registry.js index 2c46bcc6..fbfee1ec 100644 --- a/upload-api/stores/blob-registry.js +++ b/upload-api/stores/blob-registry.js @@ -47,6 +47,7 @@ export const useBlobRegistry = (dynamoDb, tableName, metrics) => ({ const cmd = new GetItemCommand({ TableName: tableName, Key: key, + ConsistentRead: true, }) const response = await dynamoDb.send(cmd) diff --git a/upload-api/stores/metrics.js b/upload-api/stores/metrics.js index 4176dc67..4b0fdb58 100644 --- a/upload-api/stores/metrics.js +++ b/upload-api/stores/metrics.js @@ -22,7 +22,7 @@ export function createMetricsTable (region, tableName, options = {}) { /** * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName - * @returns {import('../types').MetricsStore} + * @returns {import('../types.js').MetricsStore} */ export function useMetricsTable (dynamoDb, tableName) { return { diff --git a/upload-api/stores/provisions.js b/upload-api/stores/provisions.js index 7c9bd114..48f73581 100644 --- a/upload-api/stores/provisions.js +++ b/upload-api/stores/provisions.js @@ -14,9 +14,9 @@ export const createProvisionSubscriptionId = async ({ customer, consumer }) => (await CBOR.write({ consumer })).cid.toString() /** - * @param {import('../types').SubscriptionTable} subscriptionTable - * @param {import('../types').ConsumerTable} consumerTable - * @param {import('../types').SpaceMetricsTable} spaceMetricsTable + * @param {import('../types.js').SubscriptionTable} subscriptionTable + * @param {import('../types.js').ConsumerTable} consumerTable + * @param {import('../types.js').SpaceMetricsTable} spaceMetricsTable * @param {import('@ucanto/interface').DID<'web'>[]} services * @returns {import('@storacha/upload-api').ProvisionsStorage} */ diff --git a/upload-api/stores/space-metrics.js b/upload-api/stores/space-metrics.js index 957f8da9..263f982d 100644 --- a/upload-api/stores/space-metrics.js +++ b/upload-api/stores/space-metrics.js @@ -22,14 +22,14 @@ export function createMetricsTable (region, tableName, options = {}) { /** * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName - * @returns {import('../types').SpaceMetricsStore} + * @returns {import('../types.js').SpaceMetricsStore} */ export function useMetricsTable (dynamoDb, tableName) { return { /** * Increment total values of the given metrics. * - * @param {Record} metricsToUpdate + * @param {Record} metricsToUpdate */ incrementTotals: async (metricsToUpdate) => { const transactItems = Object.entries(metricsToUpdate).map(([name, items]) => items.map((item) => ({ diff --git a/upload-api/tables/consumer.js b/upload-api/tables/consumer.js index 336d44d9..9d7636f4 100644 --- a/upload-api/tables/consumer.js +++ b/upload-api/tables/consumer.js @@ -11,8 +11,8 @@ import { marshall, unmarshall } from '@aws-sdk/util-dynamodb' import { getDynamoClient } from '../../lib/aws/dynamo.js' /** - * @typedef {import('../types').ConsumerTable} ConsumerTable - * @typedef {import('../types').ConsumerInput} ConsumerInput + * @typedef {import('../types.js').ConsumerTable} ConsumerTable + * @typedef {import('../types.js').ConsumerInput} ConsumerInput */ /** diff --git a/upload-api/tables/delegations.js b/upload-api/tables/delegations.js index 90b4245e..6f277a67 100644 --- a/upload-api/tables/delegations.js +++ b/upload-api/tables/delegations.js @@ -41,9 +41,9 @@ const DELEGATIONS_FIND_DEFAULT_LIMIT = 1000 * @param {string} region * @param {string} tableName * @param {object} deps - * @param {import('../types').DelegationsBucket} deps.bucket - * @param {import('../types').InvocationBucket} deps.invocationBucket - * @param {import('../types').WorkflowBucket} deps.workflowBucket + * @param {import('../types.js').DelegationsBucket} deps.bucket + * @param {import('../types.js').InvocationBucket} deps.invocationBucket + * @param {import('../types.js').WorkflowBucket} deps.workflowBucket * @param {object} [options] * @param {string} [options.endpoint] */ @@ -60,9 +60,9 @@ export function createDelegationsTable (region, tableName, { bucket, invocationB * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName * @param {object} deps - * @param {import('../types').DelegationsBucket} deps.bucket - * @param {import('../types').InvocationBucket} deps.invocationBucket - * @param {import('../types').WorkflowBucket} deps.workflowBucket + * @param {import('../types.js').DelegationsBucket} deps.bucket + * @param {import('../types.js').InvocationBucket} deps.invocationBucket + * @param {import('../types.js').WorkflowBucket} deps.workflowBucket * @returns {import('@storacha/upload-api').DelegationsStorage} */ export function useDelegationsTable (dynamoDb, tableName, { bucket, invocationBucket, workflowBucket }) { @@ -173,7 +173,7 @@ export function useDelegationsTable (dynamoDb, tableName, { bucket, invocationBu /** * - * @param {import('../types').DelegationsBucket} bucket + * @param {import('../types.js').DelegationsBucket} bucket * @param {Ucanto.Delegation>[]} delegations */ async function writeDelegations (bucket, delegations) { @@ -189,7 +189,7 @@ async function writeDelegations (bucket, delegations) { /** * - * @param {import('../types').DelegationsBucket} bucket + * @param {import('../types.js').DelegationsBucket} bucket * @param {Iterable} entries */ async function writeEntries (bucket, entries) { @@ -212,7 +212,7 @@ function createDelegationItem (d, cause) { } /** - * @param {import('../types').DelegationsBucket} bucket + * @param {import('../types.js').DelegationsBucket} bucket * @param {Ucanto.Link} cid * @returns {Promise>} */ @@ -232,8 +232,8 @@ async function cidToDelegation (bucket, cid) { /** * @typedef {NoInvocationFoundForGivenCidError | NoDelegationFoundForGivenCidError | FailedToDecodeDelegationForGivenCidError} FindDelegationError * @param {object} opts - * @param {import('../types').InvocationBucket} opts.invocationBucket - * @param {import('../types').WorkflowBucket} opts.workflowBucket + * @param {import('../types.js').InvocationBucket} opts.invocationBucket + * @param {import('../types.js').WorkflowBucket} opts.workflowBucket * @param {Ucanto.UCANLink} opts.invocationCid * @param {Ucanto.Link} opts.delegationCid * @returns {Promise>} diff --git a/upload-api/tables/metrics.js b/upload-api/tables/metrics.js index a7a0efaf..d5899345 100644 --- a/upload-api/tables/metrics.js +++ b/upload-api/tables/metrics.js @@ -22,7 +22,7 @@ export function createMetricsTable(region, tableName, options = {}) { /** * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName - * @returns {import('../types').MetricsTable} + * @returns {import('../types.js').MetricsTable} */ export function useMetricsTable(dynamoDb, tableName) { return { diff --git a/upload-api/tables/space-metrics.js b/upload-api/tables/space-metrics.js index 98056d89..79ce91b0 100644 --- a/upload-api/tables/space-metrics.js +++ b/upload-api/tables/space-metrics.js @@ -24,7 +24,7 @@ export function createSpaceMetricsTable(region, tableName, options = {}) { /** * @param {import('@aws-sdk/client-dynamodb').DynamoDBClient} dynamoDb * @param {string} tableName - * @returns {import('../types').SpaceMetricsTable} + * @returns {import('../types.js').SpaceMetricsTable} */ export function useSpaceMetricsTable(dynamoDb, tableName) { return { diff --git a/upload-api/tables/subscription.js b/upload-api/tables/subscription.js index 93488be5..235496d4 100644 --- a/upload-api/tables/subscription.js +++ b/upload-api/tables/subscription.js @@ -9,8 +9,8 @@ import { marshall, unmarshall } from '@aws-sdk/util-dynamodb' import { getDynamoClient } from '../../lib/aws/dynamo.js' /** - * @typedef {import('../types').SubscriptionTable} SubscriptionTable - * @typedef {import('../types').SubscriptionInput} SubscriptionInput + * @typedef {import('../types.js').SubscriptionTable} SubscriptionTable + * @typedef {import('../types.js').SubscriptionInput} SubscriptionInput */ export class ConflictError extends Failure { diff --git a/upload-api/test/helpers/context.js b/upload-api/test/helpers/context.js index 167696a1..a7337aeb 100644 --- a/upload-api/test/helpers/context.js +++ b/upload-api/test/helpers/context.js @@ -9,14 +9,14 @@ import anyTest from 'ava' * @typedef {object} ServiceContext * @property {Signer} service * @typedef {object} GetMetricsContext - * @property {import('../../types').MetricsTable} metricsTable + * @property {import('../../types.js').MetricsTable} metricsTable * @property {string} tableName * @typedef {object} MetricsContext - * @property {import('../../types').MetricsStore} adminMetricsStore + * @property {import('../../types.js').MetricsStore} adminMetricsStore * @property {string} adminMetricsTableName - * @property {import('../../types').SpaceMetricsStore} spaceMetricsStore + * @property {import('../../types.js').SpaceMetricsStore} spaceMetricsStore * @property {string} spaceMetricsTableName - * @property {import('../../types').CarStore} carStore + * @property {import('../../types.js').CarStore} carStore * @property {string} carStoreBucketName * @property {import('@storacha/upload-api').AllocationsStorage} allocationsStorage * @property {string} allocationsTableName diff --git a/upload-api/types.ts b/upload-api/types.ts index 03040d05..92412f66 100644 --- a/upload-api/types.ts +++ b/upload-api/types.ts @@ -1,10 +1,9 @@ import * as UCAN from '@ipld/dag-ucan' -import { DID, Delegation, Block, UCANLink, ByteView, ReceiptModel, DIDKey, Result, Failure, Unit } from '@ucanto/interface' +import { DID, Delegation, UCANLink, ByteView, DIDKey, Result, Failure, Unit } from '@ucanto/interface' import { UnknownLink } from 'multiformats' import { CID } from 'multiformats/cid' -import { Kinesis } from '@aws-sdk/client-kinesis' import { CarStoreBucket, AllocationsStorage } from '@web3-storage/upload-api' // TODO: is CarStoreBucket needed? -import { AccountDID, ProviderDID, Service, SpaceDID, PlanCreateAdminSessionSuccess, PlanCreateAdminSessionFailure, AgentStore } from '@storacha/upload-api' +import { AccountDID, ProviderDID, Service, SpaceDID, BlobAPI, PlanCreateAdminSessionSuccess, PlanCreateAdminSessionFailure, AgentStore } from '@storacha/upload-api' export type { UnknownLink, @@ -37,22 +36,6 @@ export interface UcanLogCtx { agentStore: AgentStore } -export interface UcanStreamCtx { - streamName: string - kinesisClient?: Kinesis -} - -export interface WorkflowCtx extends UcanStreamCtx { - invocationBucket: InvocationBucket - workflowBucket: WorkflowBucket -} - -export interface ReceiptBlockCtx extends UcanStreamCtx { - invocationBucket: InvocationBucket - taskBucket: TaskBucket - workflowBucket: WorkflowBucket -} - export interface MetricsStore { incrementTotals: (metricsToUpdate: Record) => Promise } @@ -60,7 +43,7 @@ export interface MetricsStore { export interface MetricsCtx { metricsStore: MetricsStore carStore: CarStore - allocationsStorage: AllocationsStorage + blobRegistry: BlobAPI.Registry } export interface SpaceMetricsItem { @@ -123,9 +106,6 @@ export interface SpaceMetricsTable { getAllocated: (consumer: DIDKey) => Promise } -/** - * - */ export interface SubscriptionInput { /** DID of the customer who maintains this subscription */ customer: DID, @@ -250,7 +230,7 @@ export interface UcanStreamInvocation { value: UcanInvocation ts: number type: UcanStreamInvocationType - out?: ReceiptResult + out?: Result } export interface UcanInvocation { @@ -260,25 +240,6 @@ export interface UcanInvocation { cid: string } -export interface Workflow { - cid: UnknownLink - bytes: Uint8Array - invocations: UcanInvocation[] -} - - -export interface ReceiptBlock extends Block { - data: ReceiptModel -} -// TODO: Remove once in ucanto -/** - * Defines result type as per invocation spec - * - * @see https://github.com/ucan-wg/invocation/#6-result - */ -export type ReceiptResult = Result - - // would be generated by sst, but requires `sst build` to be run, which calls out to aws; not great for CI declare module 'sst/node/config' { export interface SecretResources { diff --git a/upload-api/ucan-invocation.js b/upload-api/ucan-invocation.js index 37229ce2..8e6bc6a1 100644 --- a/upload-api/ucan-invocation.js +++ b/upload-api/ucan-invocation.js @@ -12,13 +12,7 @@ import { export const CONTENT_TYPE = CAR.contentType -/** - * @typedef {import('./types').UcanLogCtx} UcanLogCtx - * @typedef {import('./types').WorkflowCtx} WorkflowCtx - * @typedef {import('./types').ReceiptBlockCtx} ReceiptBlockCtx - * @typedef {import('./types').Workflow} Workflow - * @typedef {import('./types').ReceiptBlock} ReceiptBlock - */ +/** @typedef {import('./types.js').UcanLogCtx} UcanLogCtx */ /** * @param {import('aws-lambda').APIGatewayProxyEventV2} request diff --git a/upload-api/utils.js b/upload-api/utils.js index 84613238..e42c3b7f 100644 --- a/upload-api/utils.js +++ b/upload-api/utils.js @@ -4,8 +4,7 @@ const STREAM_TYPE = { } /** - * - * @param {import('./types').UcanStreamInvocation} ucanInvocation + * @param {import('./types.js').UcanStreamInvocation} ucanInvocation */ export function hasOkReceipt (ucanInvocation) { return ucanInvocation.type === STREAM_TYPE.RECEIPT && Boolean(ucanInvocation.out?.ok)