A zero-dependency AT Protocol Personal Data Server written in JavaScript

Add jsconfig.json, fix type checking

Changed files
+26 -10
src
+12
jsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "target": "es2020", 4 + "lib": ["es2020", "dom"], 5 + "noEmit": true, 6 + "module": "esnext", 7 + "strict": false, 8 + "moduleResolution": "bundler", 9 + "resolveJsonModule": true 10 + }, 11 + "exclude": ["node_modules"] 12 + }
+14 -10
src/pds.js
··· 1 + // @ts-check 1 2 /** 2 3 * Minimal AT Protocol Personal Data Server (PDS) 3 4 * ··· 290 291 291 292 /** 292 293 * Create a CIDv1 (dag-cbor + sha-256) from raw bytes 293 - * @param {Uint8Array} bytes - Content to hash 294 + * @param {Uint8Array<ArrayBuffer>} bytes - Content to hash 294 295 * @returns {Promise<Uint8Array>} CID bytes (36 bytes: version + codec + multihash) 295 296 */ 296 297 export async function createCid(bytes) { ··· 449 450 /** 450 451 * Sign data with ECDSA P-256, returning low-S normalized signature 451 452 * @param {CryptoKey} privateKey - Web Crypto key from importPrivateKey 452 - * @param {Uint8Array} data - Data to sign 453 + * @param {Uint8Array<ArrayBuffer>} data - Data to sign 453 454 * @returns {Promise<Uint8Array>} 64-byte signature (r || s) 454 455 */ 455 456 export async function sign(privateKey, data) { ··· 1001 1002 * Build a CAR (Content Addressable aRchive) file 1002 1003 * @param {string} rootCid - Root CID string 1003 1004 * @param {Array<{cid: string, data: Uint8Array}>} blocks - Blocks to include 1004 - * @returns {Uint8Array} CAR file bytes 1005 + * @returns {Uint8Array<ArrayBuffer>} CAR file bytes 1005 1006 */ 1006 1007 export function buildCarFile(rootCid, blocks) { 1007 1008 const parts = []; ··· 1086 1087 handler: (pds, _req, _url) => pds.handleRepoInfo(), 1087 1088 }, 1088 1089 '/xrpc/com.atproto.server.describeServer': { 1089 - handler: (pds, req, _url) => pds.handleDescribeServer(req), 1090 + handler: async (pds, req, _url) => pds.handleDescribeServer(req), 1090 1091 }, 1091 1092 '/xrpc/com.atproto.server.createSession': { 1092 1093 method: 'POST', ··· 1135 1136 handler: (pds, _req, url) => pds.handleListRecords(url), 1136 1137 }, 1137 1138 '/xrpc/com.atproto.sync.getLatestCommit': { 1138 - handler: (pds, _req, _url) => pds.handleGetLatestCommit(), 1139 + handler: async (pds, _req, _url) => pds.handleGetLatestCommit(), 1139 1140 }, 1140 1141 '/xrpc/com.atproto.sync.getRepoStatus': { 1141 1142 handler: (pds, _req, _url) => pds.handleGetRepoStatus(), 1142 1143 }, 1143 1144 '/xrpc/com.atproto.sync.getRepo': { 1144 - handler: (pds, _req, _url) => pds.handleGetRepo(), 1145 + handler: async (pds, _req, _url) => pds.handleGetRepo(), 1145 1146 }, 1146 1147 '/xrpc/com.atproto.sync.getRecord': { 1147 1148 handler: (pds, _req, url) => pds.handleSyncGetRecord(url), 1148 1149 }, 1149 1150 '/xrpc/com.atproto.sync.subscribeRepos': { 1150 - handler: (pds, req, url) => pds.handleSubscribeRepos(req, url), 1151 + handler: async (pds, req, url) => pds.handleSubscribeRepos(req, url), 1151 1152 }, 1152 1153 }; 1153 1154 ··· 2386 2387 * Verify auth and return DID from token 2387 2388 * @param {Request} request - HTTP request with Authorization header 2388 2389 * @param {Object} env - Environment with JWT_SECRET 2389 - * @returns {Promise<{did: string} | {error: Response}>} DID or error response 2390 + * @returns {Promise<{did:string|null, error:Response|null}>} DID or error response 2390 2391 */ 2391 - async function requireAuth(request, env) { 2392 + async function requireAuth (request, env) { 2392 2393 const authHeader = request.headers.get('Authorization'); 2393 2394 if (!authHeader || !authHeader.startsWith('Bearer ')) { 2394 2395 return { 2396 + did: null, 2395 2397 error: Response.json( 2396 2398 { 2397 2399 error: 'AuthRequired', ··· 2406 2408 const jwtSecret = env?.JWT_SECRET; 2407 2409 if (!jwtSecret) { 2408 2410 return { 2411 + did: null, 2409 2412 error: Response.json( 2410 2413 { 2411 2414 error: 'InternalServerError', ··· 2418 2421 2419 2422 try { 2420 2423 const payload = await verifyAccessJwt(token, jwtSecret); 2421 - return { did: payload.sub }; 2424 + return { did: payload.sub, error: null }; 2422 2425 } catch (err) { 2423 2426 return { 2427 + did: null, 2424 2428 error: Response.json( 2425 2429 { 2426 2430 error: 'InvalidToken',