chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
/**
* Regenerate packages/lexicon-resolver/src/schemas/published.js.
*
* Walks the network resolution chain from every NSID in knownRecords, follows
* each schema's refs, and writes the closure to disk. Run it when Bluesky
* publishes a lexicon change worth shipping early:
*
* node scripts/gen-bundled-lexicons.mjs
*
* The resolver refreshes these from the network on its own TTL, so the file is
* a warm start rather than the authority.
*/
import { execFileSync } from 'node:child_process';
import { writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { LexiconResolver } from '../packages/lexicon-resolver/src/resolver.js';
import { coreSchemas } from '../packages/lexicon-resolver/src/schemas/com-atproto.js';
import { knownRecords } from '../packages/lexicon-resolver/src/schemas/known-records.js';
const OUT = join(
dirname(fileURLToPath(import.meta.url)),
'../packages/lexicon-resolver/src/schemas/published.js',
);
const resolver = new LexiconResolver({
fetch: (url, init) => fetch(url, init),
});
/** @type {string[]} */
const missing = [];
for (const nsid of knownRecords) {
const unresolved = new Set();
await resolver.ensureSchemaWithRefs(nsid, unresolved);
missing.push(...unresolved);
}
if (missing.length) {
console.error(`unresolved: ${[...new Set(missing)].join(', ')}`);
process.exit(1);
}
const bundled = new Set(coreSchemas.map((s) => s.id));
const ids = [...resolver.schemas.keys()]
.filter((id) => !bundled.has(id))
.sort();
const header = `/**
* Lexicons for the record types this PDS enforces, and every schema they
* reference. Generated by scripts/gen-bundled-lexicons.mjs.
*
* The resolver preloads these so the common write path costs no network calls.
* Each one carries the resolver's TTL like any other cache entry, so the
* network answer replaces it once the entry goes stale. Enforcement comes from
* known-records.js, not from this file.
*
* Do not edit by hand.
*/
/** @type {import('@bigmoves/lexicon').Lexicon[]} */
export const publishedSchemas = ${JSON.stringify(
// An authority publishes its lexicon as a record, so the document arrives
// carrying the collection it was stored in. That is not part of a Lexicon.
ids.map((id) => {
const { $type, ...schema } = /** @type {Record<string, unknown>} */ (
resolver.schemas.get(id)
);
return schema;
}),
null,
2,
)};
`;
writeFileSync(OUT, header);
// JSON.stringify does not produce the house style, and `npm run ci` checks it.
execFileSync('npx', ['biome', 'format', '--write', OUT], { stdio: 'inherit' });
console.log(`wrote ${ids.length} schemas to ${OUT}`);