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

feat: add com.atproto.sync.getRecord endpoint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+35
src
+35
src/pds.js
··· 900 900 '/xrpc/com.atproto.sync.getRepo': { 901 901 handler: (pds, req, url) => pds.handleGetRepo() 902 902 }, 903 + '/xrpc/com.atproto.sync.getRecord': { 904 + handler: (pds, req, url) => pds.handleSyncGetRecord(url) 905 + }, 903 906 '/xrpc/com.atproto.sync.subscribeRepos': { 904 907 handler: (pds, req, url) => pds.handleSubscribeRepos(req, url) 905 908 } ··· 1382 1385 data: new Uint8Array(b.data) 1383 1386 })) 1384 1387 const car = buildCarFile(commits[0].cid, blocksForCar) 1388 + return new Response(car, { 1389 + headers: { 'content-type': 'application/vnd.ipld.car' } 1390 + }) 1391 + } 1392 + 1393 + async handleSyncGetRecord(url) { 1394 + const collection = url.searchParams.get('collection') 1395 + const rkey = url.searchParams.get('rkey') 1396 + if (!collection || !rkey) { 1397 + return Response.json({ error: 'InvalidRequest', message: 'missing collection or rkey' }, { status: 400 }) 1398 + } 1399 + const did = await this.getDid() 1400 + const uri = `at://${did}/${collection}/${rkey}` 1401 + const rows = this.sql.exec( 1402 + `SELECT cid FROM records WHERE uri = ?`, uri 1403 + ).toArray() 1404 + if (rows.length === 0) { 1405 + return Response.json({ error: 'RecordNotFound', message: 'record not found' }, { status: 404 }) 1406 + } 1407 + // Get the record block 1408 + const recordCid = rows[0].cid 1409 + const blockRows = this.sql.exec( 1410 + `SELECT cid, data FROM blocks WHERE cid = ?`, recordCid 1411 + ).toArray() 1412 + if (blockRows.length === 0) { 1413 + return Response.json({ error: 'RecordNotFound', message: 'block not found' }, { status: 404 }) 1414 + } 1415 + const blocks = blockRows.map(b => ({ 1416 + cid: b.cid, 1417 + data: new Uint8Array(b.data) 1418 + })) 1419 + const car = buildCarFile(recordCid, blocks) 1385 1420 return new Response(car, { 1386 1421 headers: { 'content-type': 'application/vnd.ipld.car' } 1387 1422 })