diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..37320b0 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": ["es2020", "dom"], + "noEmit": true, + "module": "esnext", + "strict": false, + "moduleResolution": "bundler", + "resolveJsonModule": true + }, + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/src/pds.js b/src/pds.js index 01bdd5c..3adefc1 100644 --- a/src/pds.js +++ b/src/pds.js @@ -1,3 +1,4 @@ +// @ts-check /** * Minimal AT Protocol Personal Data Server (PDS) * @@ -290,7 +291,7 @@ export function cborDecode(bytes) { /** * Create a CIDv1 (dag-cbor + sha-256) from raw bytes - * @param {Uint8Array} bytes - Content to hash + * @param {Uint8Array} bytes - Content to hash * @returns {Promise} CID bytes (36 bytes: version + codec + multihash) */ export async function createCid(bytes) { @@ -449,7 +450,7 @@ function bigIntToBytes(n, length) { /** * Sign data with ECDSA P-256, returning low-S normalized signature * @param {CryptoKey} privateKey - Web Crypto key from importPrivateKey - * @param {Uint8Array} data - Data to sign + * @param {Uint8Array} data - Data to sign * @returns {Promise} 64-byte signature (r || s) */ export async function sign(privateKey, data) { @@ -1001,7 +1002,7 @@ export function base32Decode(str) { * Build a CAR (Content Addressable aRchive) file * @param {string} rootCid - Root CID string * @param {Array<{cid: string, data: Uint8Array}>} blocks - Blocks to include - * @returns {Uint8Array} CAR file bytes + * @returns {Uint8Array} CAR file bytes */ export function buildCarFile(rootCid, blocks) { const parts = []; @@ -1086,7 +1087,7 @@ const pdsRoutes = { handler: (pds, _req, _url) => pds.handleRepoInfo(), }, '/xrpc/com.atproto.server.describeServer': { - handler: (pds, req, _url) => pds.handleDescribeServer(req), + handler: async (pds, req, _url) => pds.handleDescribeServer(req), }, '/xrpc/com.atproto.server.createSession': { method: 'POST', @@ -1135,19 +1136,19 @@ const pdsRoutes = { handler: (pds, _req, url) => pds.handleListRecords(url), }, '/xrpc/com.atproto.sync.getLatestCommit': { - handler: (pds, _req, _url) => pds.handleGetLatestCommit(), + handler: async (pds, _req, _url) => pds.handleGetLatestCommit(), }, '/xrpc/com.atproto.sync.getRepoStatus': { handler: (pds, _req, _url) => pds.handleGetRepoStatus(), }, '/xrpc/com.atproto.sync.getRepo': { - handler: (pds, _req, _url) => pds.handleGetRepo(), + handler: async (pds, _req, _url) => pds.handleGetRepo(), }, '/xrpc/com.atproto.sync.getRecord': { handler: (pds, _req, url) => pds.handleSyncGetRecord(url), }, '/xrpc/com.atproto.sync.subscribeRepos': { - handler: (pds, req, url) => pds.handleSubscribeRepos(req, url), + handler: async (pds, req, url) => pds.handleSubscribeRepos(req, url), }, }; @@ -2386,12 +2387,13 @@ function getSubdomain(hostname) { * Verify auth and return DID from token * @param {Request} request - HTTP request with Authorization header * @param {Object} env - Environment with JWT_SECRET - * @returns {Promise<{did: string} | {error: Response}>} DID or error response + * @returns {Promise<{did:string|null, error:Response|null}>} DID or error response */ -async function requireAuth(request, env) { +async function requireAuth (request, env) { const authHeader = request.headers.get('Authorization'); if (!authHeader || !authHeader.startsWith('Bearer ')) { return { + did: null, error: Response.json( { error: 'AuthRequired', @@ -2406,6 +2408,7 @@ async function requireAuth(request, env) { const jwtSecret = env?.JWT_SECRET; if (!jwtSecret) { return { + did: null, error: Response.json( { error: 'InternalServerError', @@ -2418,9 +2421,10 @@ async function requireAuth(request, env) { try { const payload = await verifyAccessJwt(token, jwtSecret); - return { did: payload.sub }; + return { did: payload.sub, error: null }; } catch (err) { return { + did: null, error: Response.json( { error: 'InvalidToken',