Something went wrong. Try again.
Something went wrong. Try again.
4.4 kB · 124 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125#!/usr/bin/env node// Write dev.at-intent.capability record(s) from a JSON file.//// node write-capability.mjs <record.json> [options]//// The file is a capability record (the dev.at-intent.capability shape); `$type`// and `createdAt` are optional and filled in. It may be one record, an array, or// { "capabilities": [ ... ] }.//// Options:// --dry-run validate and print the createRecord call; write nothing// --json print the built record(s) as JSON and exit// --identifier <h> handle or DID to auth as (env: PDS_IDENTIFIER)// --password <pw> app password (env: PDS_APP_PASSWORD)// --pds <url> PDS endpoint override (env: PDS_URL)// --rkey <key> record key for a single capability (default: server TID)// --force write even if there are warnings (errors always block)//// Capability records are authored by the APP, in the APP's own repo — so// --identifier is the app's account. Example:// PDS_IDENTIFIER=myapp.com PDS_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \// node write-capability.mjs examples/subscribe.capability.json
import { loadRecordFile, capabilitiesFrom } from "./lib/spec.mjs";import { validateCapability, buildCapabilityRecord } from "./lib/capability.mjs";import { CAPABILITY_NSID } from "./lib/nsid.mjs";import { createSession, createRecord } from "./lib/atproto.mjs";import { C, report, printDryRun, authFromArgs } from "./lib/cli.mjs";
function parseArgs(argv) { const a = { _: [] }; for (let i = 0; i < argv.length; i++) { const t = argv[i]; if (t === "--dry-run") a.dryRun = true; else if (t === "--json") a.json = true; else if (t === "--force") a.force = true; else if (t === "--identifier") a.identifier = argv[++i]; else if (t === "--password") a.password = argv[++i]; else if (t === "--pds") a.pds = argv[++i]; else if (t === "--rkey") a.rkey = argv[++i]; else a._.push(t); } return a;}
async function main() { const a = parseArgs(process.argv.slice(2)); const file = a._[0]; if (!file) { console.error("usage: node write-capability.mjs <record.json> [--dry-run] [--identifier h] [--password pw]"); process.exit(1); }
let caps; try { caps = capabilitiesFrom(await loadRecordFile(file)); } catch (err) { console.error(C.red(`\ncould not load ${file}: ${err.message}\n`)); process.exit(1); } if (a.rkey && caps.length > 1) { console.error(C.red("--rkey only works with a single-capability file")); process.exit(1); }
// validate all, build records const now = new Date().toISOString(); let blocked = false; let warned = false; const records = []; caps.forEach((cap, i) => { const label = `${cap.name || "(unnamed)"} [${cap.verb || "?"}]`; const v = validateCapability(cap); if (report(label, v)) blocked = true; if (v.warnings.length) warned = true; records.push(buildCapabilityRecord(cap, now)); });
if (blocked) { console.error(C.red("\nFix the errors above before writing.\n")); process.exit(1); }
if (a.json) { console.log(JSON.stringify(records.length === 1 ? records[0] : records, null, 2)); return; }
if (a.dryRun) { const { identifier, pds } = authFromArgs(a); for (const record of records) { printDryRun({ pds, did: identifier, collection: CAPABILITY_NSID, record }); } console.log(C.dim(`\n${records.length} record(s) validated. Re-run without --dry-run to write.\n`)); return; }
if (warned && !a.force) { console.error(C.yellow("\nThere are warnings. Re-run with --force to write anyway, or --dry-run to inspect.\n")); process.exit(1); }
const { identifier, password, pds } = authFromArgs(a); let session; try { session = await createSession({ identifier, password, pds }); } catch (err) { console.error(C.red(`\nauth failed: ${err.message}\n`)); process.exit(1); } console.error(C.dim(`\nauthed as ${session.handle || session.did} @ ${session.pds}`));
for (const record of records) { try { const res = await createRecord(session, { collection: CAPABILITY_NSID, record, rkey: a.rkey }); console.log(`${C.green("✓ wrote")} ${record.name} ${C.dim(record.verb)} ${C.cyan(res.uri)}`); } catch (err) { console.error(C.red(`✗ ${record.name}: ${err.message}`)); } } console.log();}
main();