chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// The git extension against a fake host: the write guard reads the config
// record from the public repo or a space, and smart HTTP mounts only when
// asked for.
import { cborEncodeDagCbor } from '@pdsjs/core/repo';
import { describe, expect, it, vi } from 'vitest';
import {
createGitExtension,
createGitGuardExtension,
} from '../src/extension.js';
const DID = 'did:plc:gitextension';
const SPACE = 'at://did:plc:gitextension/dev.pdsjs.space/abc';
const CONFIG = 'dev.pdsjs.git.config';
/**
* @param {Object} [options]
* @param {boolean} [options.withSpaces]
*/
function createHost({ withSpaces = false } = {}) {
const records = new Map([
[
`at://${DID}/${CONFIG}/repo`,
cborEncodeDagCbor({ protectedBranches: ['main'] }),
],
]);
const spaceRecords = new Map([
[`${CONFIG}/repo`, cborEncodeDagCbor({ protectedBranches: ['release'] })],
]);
const host = {
actorStorage: {
getRecord: vi.fn(async (/** @type {string} */ uri) => {
const value = records.get(uri);
return value ? { value } : null;
}),
},
blobs: { get: vi.fn(async () => null) },
spaceStorage: withSpaces
? {
getSpaceRecord: vi.fn(
async (
/** @type {string} */ _space,
/** @type {string} */ collection,
/** @type {string} */ rkey,
) => {
const value = spaceRecords.get(`${collection}/${rkey}`);
return value ? { cid: 'bafy', value } : null;
},
),
}
: undefined,
readOnly: false,
getDid: async () => DID,
xrpc: vi.fn(async () => new Response('{}')),
createCommit: vi.fn(),
accountApi: vi.fn(),
};
return /** @type {import('@pdsjs/core/ports').ExtensionHost} */ (
/** @type {unknown} */ (host)
);
}
/** @param {string} branch @param {string} sha */
const repo = (branch, sha) => ({
name: 'repo',
createdAt: '2026-01-01T00:00:00.000Z',
refs: [{ name: `refs/heads/${branch}`, sha }],
bundles: [],
});
const emptyRepo = {
name: 'repo',
createdAt: '2026-01-01T00:00:00.000Z',
refs: [],
bundles: [],
};
describe('createGitExtension', () => {
it('guards repo and config writes without any option', () => {
const extension = createGitExtension()(createHost());
expect(extension.name).toBe('git');
expect(extension.writeGuard?.collections).toEqual([
'dev.pdsjs.git.repo',
CONFIG,
]);
expect(extension.handle).toBeUndefined();
expect(extension.prefixes).toBeUndefined();
});
it('registers the XRPC methods, the bundle-chain reads with a browser', () => {
const routes = Object.keys(createGitExtension()(createHost()).routes ?? {});
expect(routes).toContain('/xrpc/dev.pdsjs.git.listRepos');
expect(routes).toContain('/xrpc/dev.pdsjs.git.getTree');
const noBrowse = Object.keys(
createGitExtension({ browse: false })(createHost()).routes ?? {},
);
expect(noBrowse).toContain('/xrpc/dev.pdsjs.git.listRepos');
expect(noBrowse).not.toContain('/xrpc/dev.pdsjs.git.getTree');
});
it('serves smart HTTP under /git when asked', async () => {
const host = createHost();
const extension = createGitExtension({ http: true })(host);
expect(extension.prefixes).toEqual(['/git']);
const miss = await extension.handle?.(
new Request('https://pds.example.com/other'),
new URL('https://pds.example.com/other'),
);
expect(miss).toBeNull();
});
it('reads the public config record to refuse a protected ref deletion', async () => {
const host = createHost();
const guard = createGitExtension()(host).writeGuard;
await expect(
guard?.check({
space: null,
collection: 'dev.pdsjs.git.repo',
rkey: 'repo',
prevValue: repo('main', 'a'.repeat(40)),
nextValue: emptyRepo,
}),
).rejects.toThrow(/protected/);
expect(host.actorStorage.getRecord).toHaveBeenCalledWith(
`at://${DID}/${CONFIG}/repo`,
);
});
it('reads a space config record through the host space storage', async () => {
const host = createHost({ withSpaces: true });
const guard = createGitExtension()(host).writeGuard;
await expect(
guard?.check({
space: SPACE,
collection: 'dev.pdsjs.git.repo',
rkey: 'repo',
prevValue: repo('release', 'a'.repeat(40)),
nextValue: emptyRepo,
}),
).rejects.toThrow(/protected/);
expect(host.spaceStorage?.getSpaceRecord).toHaveBeenCalledWith(
SPACE,
CONFIG,
'repo',
);
});
it('holds no rules for a space write when spaces are off', async () => {
const guard = createGitExtension()(createHost()).writeGuard;
await expect(
guard?.check({
space: SPACE,
collection: 'dev.pdsjs.git.repo',
rkey: 'repo',
prevValue: repo('release', 'a'.repeat(40)),
nextValue: emptyRepo,
}),
).resolves.toBeUndefined();
});
});
describe('createGitGuardExtension', () => {
it('carries the write guard and nothing else', () => {
const host = createHost();
const extension = createGitGuardExtension()(host);
expect(extension.name).toBe('git');
expect(extension.writeGuard).toBeDefined();
expect(extension.routes).toBeUndefined();
expect(extension.handle).toBeUndefined();
expect(extension.prefixes).toBeUndefined();
expect(extension.collections).toContain('dev.pdsjs.git.repo');
});
it('enforces branch protection at the record write', async () => {
const host = createHost();
const guard = createGitGuardExtension()(host).writeGuard;
await expect(
guard?.check({
space: null,
collection: 'dev.pdsjs.git.repo',
rkey: 'repo',
prevValue: repo('main', 'a'.repeat(40)),
nextValue: emptyRepo,
}),
).rejects.toThrow(/protected/);
expect(host.actorStorage.getRecord).toHaveBeenCalledWith(
`at://${DID}/${CONFIG}/repo`,
);
});
});