~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
100 lines · 6.1 KB Raw History
// 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 {};