chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// The port shapes the drive package builds and its account routes read.
/**
* Read-only view of the files this account stores in its own repo, for the
* account page.
*
* @typedef {Object} DriveBrowserPort
* @property {(folder: string|null, space?: string|null) => Promise<DriveFolderListing|null>} listFolder - one folder's contents, or null when no such folder exists
* @property {(rkey: string, space?: string|null) => Promise<{name: string, mimeType: string, size: number, bytes: Uint8Array}|null>} readFile - the joined bytes, or null when the record or any part is missing
* @property {(rkey: string, space?: string|null) => Promise<{name: string, mimeType: string, size: number}|null>} statFile - name, type and length without reading a single part
* @property {(rkey: string, start: number, end: number, space?: string|null) => Promise<{name: string, mimeType: string, start: number, end: number, total: number, bytes: Uint8Array}|null>} readRange - only the parts a byte range touches, so a large file is never held whole
* @property {(space?: string|null) => Promise<DriveTrashListing|null>} listTrash - what is in the trash, newest first
*/
/**
* @typedef {Object} DriveTrashListing
* @property {string|null} space
* @property {DriveTrashRow[]} items
* @property {number} totalSize - bytes the trash still holds, which storage still counts
*/
/**
* @typedef {Object} DriveTrashRow
* @property {string} rkey
* @property {string} uri
* @property {string} name
* @property {boolean} isFolder
* @property {string|null} mimeType
* @property {number} size
* @property {string} deletedAt
*/
/**
* Direct storage access for a drive held in a permissioned space. The account
* page is the owner's own surface, so the extension reads space storage here
* rather than going through the authenticated space endpoints.
*
* @typedef {Object} DriveSpaceReader
* @property {(space: string, collection: string, limit: number) => Promise<{records: Array<{rkey: string, cid: string, value: unknown}>}>} listRecords
* @property {(space: string, rkey: string) => Promise<{cid: string, value: unknown}|null>} getRecord
* @property {(cid: string) => Promise<Uint8Array|null>} getBlob
*/
/**
* Writing one file into the drive. Kept apart from DriveBrowserPort so a
* read-only deployment can compose the listing without the write path.
*
* @typedef {Object} DriveWriterPort
* @property {(file: {name: string, folder: string|null, mimeType: string, body: ReadableStream<Uint8Array>|null, space?: string|null}) => Promise<DriveFileRow>} createFile - stores the bytes as blob parts and commits the record
* @property {(rkey: string, space?: string|null) => Promise<boolean>} deleteFile - puts one file in the trash, answering false when no such record exists
* @property {(rkey: string, space?: string|null) => Promise<number>} restore - takes an item back out of the trash, with everything a folder covered; answers how many records changed
* @property {(rkey: string, space?: string|null) => Promise<number>} purge - removes a trashed item for good and unlinks its parts, so the orphan sweep frees the bytes
* @property {(folder: {name: string, parent: string|null, space?: string|null}) => Promise<DriveFolderRow>} createFolder - a folder exists in its own right, so an empty one stays
* @property {(folder: {rkey: string, name?: string, parent?: string|null, space?: string|null}) => Promise<DriveFolderRow>} renameFolder - renames or moves one folder, leaving every file's identity alone
* @property {(rkey: string, space?: string|null) => Promise<boolean>} deleteFolder - puts one folder in the trash with everything under it, the way every drive does it
* @property {number} [uploadPartSize] - how many bytes a client sends per request of a multi-request upload; present with the session methods below
* @property {(file: {name: string, folder: string|null, mimeType: string, space?: string|null}) => Promise<{id: string}>} [createUpload] - opens a multi-request upload, so one file can arrive across several requests each under the platform's per-request body cap and still land as one blob
* @property {(id: string, body: ReadableStream<Uint8Array>) => Promise<{received: number}>} [appendUpload] - takes the next run of bytes, whole and in order; a failed part abandons the session
* @property {(id: string) => Promise<DriveFileRow>} [finishUpload] - files the blob under its hash and commits the record
* @property {(id: string) => Promise<void>} [abortUpload] - abandons the session and its staged bytes
*/
/**
* @typedef {Object} DriveFolderRow
* @property {string} rkey
* @property {string} uri
* @property {string} cid
* @property {string} name
* @property {string} parent - record key of the folder above, empty at the top level
* @property {string} createdAt
*/
/**
* @typedef {Object} DriveFolderListing
* @property {string} folder - record key of the folder this listing describes, empty at the top level
* @property {string} path - the folder's display path, like `photos/2026`
* @property {Array<{rkey: string, name: string}>} ancestry - every folder from the top level down to this one
* @property {string|null} space - the space this drive lives in, null for the public repo
* @property {Array<{rkey: string, name: string, files: number, size: number, createdAt: string|null}>} folders - folders directly under it, with what they hold at any depth
* @property {DriveFileRow[]} files - files directly in it
* @property {number} totalFiles - files in the whole drive
* @property {number} totalSize - bytes in the whole drive
*/
/**
* @typedef {Object} DriveFileRow
* @property {string} rkey
* @property {string} uri
* @property {string} cid - the record CID
* @property {string} name
* @property {string} folder - record key of the folder it sits in, empty at the top level
* @property {string} mimeType
* @property {number} size - bytes, summed from the part refs
* @property {number} partCount
* @property {string|null} [blobCid] - the one part's blob CID when the file is a single blob, so a record in any app can reference it; null for a split file
* @property {string|null} createdAt
* @property {string|null} updatedAt
*/
export {};