chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// The issue statements as the server reads them: every listed voice from
// their own server, and whoever the discovery port names from theirs.
import { describe, expect, it } from 'vitest';
import { createIssueReader } from '../src/issue-reader.js';
const ALICE = 'did:plc:alice';
const BOB = 'did:plc:bob';
const DAN = 'did:plc:dan';
const REPO = 'demo';
const SUBJECT = `at://${ALICE}/dev.pdsjs.git.repo/${REPO}`;
/** @type {Record<string, {did: string, handle: string, pds: string}>} */
const PEOPLE = {
[ALICE]: { did: ALICE, handle: 'alice.test', pds: 'https://alice.test' },
[BOB]: { did: BOB, handle: 'bob.test', pds: 'https://bob.test' },
[DAN]: { did: DAN, handle: 'dan.test', pds: 'https://dan.test' },
};
/**
* @param {string} did @param {string} rkey @param {Record<string, unknown>} value
*/
const row = (did, rkey, value) => ({
uri: `at://${did}/dev.pdsjs.git.issue/${rkey}`,
cid: `cid-${rkey}`,
value: {
subject: { uri: SUBJECT },
createdAt: '2026-08-01T00:00:00Z',
...value,
},
});
/**
* @param {Object} [options]
* @param {Array<{did: string, collection: string, rkey: string}>} [options.about]
* @param {string[]} [options.unreachable]
*/
function world({ about = [], unreachable = [] } = {}) {
/** @type {Record<string, unknown[]>} */
const records = {
[ALICE]: [row(ALICE, 'a1', { body: 'Resolved.', disposition: 'resolved' })],
[BOB]: [
row(BOB, 'b1', { title: 'It breaks', body: 'Steps.' }),
// About another repository, which a voice's listing carries too.
{
...row(BOB, 'b2', { title: 'Elsewhere' }),
value: {
subject: { uri: `at://${ALICE}/dev.pdsjs.git.repo/other` },
title: 'Elsewhere',
},
},
],
[DAN]: [
row(DAN, 'd1', { title: 'From a stranger' }),
{
...row(DAN, 'd2', { title: 'Lied about' }),
value: {
subject: { uri: `at://${ALICE}/dev.pdsjs.git.repo/other` },
title: 'Lied about',
},
},
],
};
/** @type {typeof fetch} */
const send = async (input) => {
const url = new URL(String(input));
const who = Object.values(PEOPLE).find((one) => one.pds === url.origin);
if (!who || unreachable.includes(who.did)) {
throw new TypeError('fetch failed');
}
const held = /** @type {{uri: string}[]} */ (records[who.did] ?? []);
if (url.pathname.endsWith('listRecords')) {
return Response.json({ records: held, cursor: null });
}
const rkey = url.searchParams.get('rkey');
const found = held.find((one) => one.uri.endsWith(`/${rkey}`));
return found ? Response.json(found) : new Response('no', { status: 404 });
};
const reader = createIssueReader({
resolveContributor: async (did) => PEOPLE[did] ?? null,
readRecord: async (_did, collection, rkey) => {
if (rkey !== REPO) return null;
return collection === 'dev.pdsjs.git.repo'
? { defaultBranch: 'main' }
: { collaborators: [BOB] };
},
discovery: {
about: async (_subject, collection) =>
about.filter((entry) => entry.collection === collection),
},
fetch: send,
});
return reader;
}
describe('createIssueReader', () => {
it('lists every voice the config names, about this repository only', async () => {
const answer = await world().listIssues(ALICE, REPO);
const statements = answer?.statements ?? [];
expect(statements.map((one) => one.uri)).toEqual([
`at://${ALICE}/dev.pdsjs.git.issue/a1`,
`at://${BOB}/dev.pdsjs.git.issue/b1`,
]);
expect(statements[0].by).toEqual(PEOPLE[ALICE]);
expect(statements[0].disposition).toBe('resolved');
expect(statements[1].indexed).toBeUndefined();
});
it('reads a stranger the port names from their own server, and takes the record over the index', async () => {
const answer = await world({
about: [
{ did: DAN, collection: 'dev.pdsjs.git.issue', rkey: 'd1' },
{ did: DAN, collection: 'dev.pdsjs.git.issue', rkey: 'd2' },
{ did: DAN, collection: 'dev.pdsjs.git.issue', rkey: 'missing' },
// A listed voice's record, read directly already.
{ did: BOB, collection: 'dev.pdsjs.git.issue', rkey: 'b1' },
],
}).listIssues(ALICE, REPO);
const statements = answer?.statements ?? [];
const fromDan = statements.filter((one) => one.by.did === DAN);
expect(fromDan.map((one) => one.uri)).toEqual([
`at://${DAN}/dev.pdsjs.git.issue/d1`,
]);
expect(fromDan[0]).toMatchObject({
title: 'From a stranger',
indexed: true,
});
// Bob's word appears once.
expect(statements.filter((one) => one.uri.endsWith('/b1'))).toHaveLength(1);
});
it('costs an unreachable voice their words and nothing else', async () => {
const answer = await world({ unreachable: [BOB] }).listIssues(ALICE, REPO);
expect(answer?.statements.map((one) => one.by.did)).toEqual([ALICE]);
});
it('answers null for a repository this account does not hold', async () => {
expect(await world().listIssues(ALICE, 'nothing')).toBeNull();
});
});