// @pdsjs/spaces/routes - the space route table. // // @pdsjs/core never imports this package. Instead a platform package builds the // table and passes it to the PDS as `spaceRoutes`, which merges it into its own // route map. With the feature off, the routes are simply absent and requests // fall through to the normal 404 — see spec section 3. import { createAuthRoutes } from './handlers/auth.js'; import { createManageRoutes } from './handlers/manage.js'; import { createReadRoutes } from './handlers/read.js'; import { createWriteRoutes } from './handlers/write.js'; import { createNotifyOutbox } from './outbox.js'; /** * @param {Object} ctx * @param {import('@pdsjs/core/ports').SpaceStoragePort} ctx.spaceStorage * @param {import('@pdsjs/core/ports').BlobPort} ctx.blobs - blobs referenced * from space records live in the account's ordinary blob store * @param {(blobCid: string, recordUri: string, recordTime: number|null) => Promise} ctx.linkBlob * @param {(recordUri: string) => Promise} ctx.unlinkBlobs * @param {() => Promise} ctx.getDid - the hosted account's DID * @param {() => Promise} ctx.getSigner * - the account's atproto signing key, which signs space tokens and * service auth * @param {() => Promise<{privateKey: Uint8Array, didKey: string}|null>} ctx.getKemKey * - the account's `#atproto_kem` key, which MACs its repos' responses * @param {import('@pdsjs/core/ports').DidResolverPort} ctx.resolveDid - DID document lookup, * injected so this package stays dependency-free * @param {import('@pdsjs/core/ports').SignatureVerifierPort} ctx.verifier * @param {import('@pdsjs/core/ports').RecordWriteGuardPort} [ctx.recordGuard] * - a veto over writes in its named collections, e.g. git branch protection * @param {typeof fetch} [ctx.fetch] - injected for the outbound notification * calls, so tests can observe them without a network * @param {(work: Promise) => void} [ctx.background] - runs write * notices after the response; absent, they run before it * @param {ReturnType} [ctx.outbox] * - notices owed to other services; built from ctx when absent * @returns {import('@pdsjs/core/pds').Routes} */ export function createSpaceRoutes(ctx) { if (!ctx?.spaceStorage) { throw new Error('createSpaceRoutes requires a spaceStorage port'); } if (!ctx.getDid || !ctx.getSigner || !ctx.getKemKey) { throw new Error( 'createSpaceRoutes requires getDid, getSigner and getKemKey', ); } if (!ctx.resolveDid || !ctx.verifier) { throw new Error('createSpaceRoutes requires resolveDid and a verifier'); } // Refused rather than defaulted: without the link callbacks a space record's // blobs look unreferenced, and orphan cleanup deletes them. if (!ctx.blobs || !ctx.linkBlob || !ctx.unlinkBlobs) { throw new Error( 'createSpaceRoutes requires blobs, linkBlob and unlinkBlobs', ); } // One outbox, so write notices and deletion notices share a schedule. const shared = { ...ctx, outbox: ctx.outbox ?? createNotifyOutbox(ctx) }; return { ...createWriteRoutes(shared), ...createReadRoutes(shared), ...createAuthRoutes(shared), ...createManageRoutes(shared), }; }