#!/usr/bin/env tsx // `archilyzer` — the one command line over the publish layer and the bins. // // pnpm --filter yt-dlp-transcript-common exec tsx bin/archilyzer.ts // (or `tsx ../common/bin/archilyzer.ts …` from export/, as its scripts do) // // Every row imports its implementation LAZILY, so `archilyzer sync tick` never // loads the AWS SDK and `archilyzer settings example` never opens LMDB. The // machinery (parser, lookup, usage) is `_cli.ts`; this file is only the table. import type { Command } from "./_cli"; import { runCli, runIfEntryPoint } from "./_cli"; export const COMMANDS: Command[] = [ { path: ["index"], usage: "rebuild the LMDB transcript index", run: async () => { await (await import("./build-index")).main(); return 0; }, }, { path: ["build", "stats"], usage: "rebuild the stats datasets (reads the index; the data phase's second step)", run: async () => { await (await import("./build-stats")).main(); return 0; }, }, { path: ["build", "templates"], usage: "bake each site's chart templates into its export staging dir (the data phase's third step)", run: async () => { await (await import("./build-chart-templates")).main(); return 0; }, }, { path: ["build", "archives"], usage: "warm the shared archive-zip cache for every enabled site's channels, once", run: async () => { await (await import("./build-archives")).main(); return 0; }, }, { path: ["compose", "site"], usage: " [--allow-missing-media] compose one site's export/public (default: SITE_ID); --allow-missing-media lets a report citation with no prepared media through", flags: { "allow-missing-media": "boolean" }, maxPositionals: 1, run: async ({ positionals, flags, env }) => { const siteId = siteIdFrom(positionals, env, "compose site"); if (!siteId) return 2; await (await import("./compose-site")).main({ siteId, allowMissingMedia: flags["allow-missing-media"] === true, }); return 0; }, }, { path: ["compose", "hub"], usage: "compose the hub's export/public (hub-sites.json, corpus.json, …)", run: async () => { await (await import("./compose-hub")).main(); return 0; }, }, { path: ["compose", "homepage"], usage: "compose homepage/public (whole-pool stats + landing summary)", run: async () => { await (await import("./compose-homepage")).main(); return 0; }, }, // --- publishing as stages (release 18; bin/publish.ts) ---------------------- { path: ["publish", "index"], usage: "update the index: the LMDB index, the stats datasets and the chart templates in one child (8 GB heap), then the index stamp every build reads", run: async () => (await import("./publish")).publishIndex(), }, { path: ["publish", "build"], usage: " [--runner local|docker|auto] [--force] [--skip-archives] [--allow-missing-media] [--out ] build a site (or every stale one) into its bundle //out from the current index; --runner docker builds every site in containers (host only); a fresh site is a no-op without --force; --allow-missing-media lets a report citation with no prepared media through compose; --out then lays the site's bundle out in for a server that is not Pages (hard links where it can, else copies; emptied first and guarded as a local deploy's destination; not a deploy, nothing recorded)", flags: { runner: "string", force: "boolean", "skip-archives": "boolean", "allow-missing-media": "boolean", out: "string", }, maxPositionals: 1, run: async ({ positionals, flags }) => { const [target] = positionals; const runner = flags.runner; if (!target || (runner !== undefined && runner !== "local" && runner !== "docker" && runner !== "auto")) { console.error("publish build: give [--runner local|docker|auto]"); return 2; } if (flags.out !== undefined && (typeof flags.out !== "string" || !flags.out.trim())) { console.error("publish build: --out needs a directory"); return 2; } return (await import("./publish")).publishBuild({ target, runner: runner as "local" | "docker" | "auto" | undefined, force: flags.force === true, skipArchives: flags["skip-archives"] === true, allowMissingMedia: flags["allow-missing-media"] === true, ...(typeof flags.out === "string" ? { out: flags.out } : {}), }); }, }, { path: ["publish", "deploy"], usage: " [--preview ] [--to local] [--force] ship a site's bundle to its Pages project (a preview with --preview), or with --to local into ARCHILYZER_SITE_OUT; a bundle already deployed there is a no-op without --force", flags: { preview: "string", to: "string", force: "boolean" }, maxPositionals: 1, run: async ({ positionals, flags }) => { const [target] = positionals; const to = flags.to; if (!target || (to !== undefined && to !== "pages" && to !== "local")) { console.error("publish deploy: give [--preview ] [--to local]"); return 2; } return (await import("./publish")).publishDeploy({ target, preview: typeof flags.preview === "string" ? flags.preview : undefined, to: to as "pages" | "local" | undefined, force: flags.force === true, }); }, }, { path: ["publish", "hub"], usage: "[--deploy | --deploy-only] [--preview ] [--force] build the hub into its bundle /_hub/out, then (--deploy) ship it; --deploy-only ships the bundle as built", flags: { deploy: "boolean", "deploy-only": "boolean", preview: "string", force: "boolean" }, run: async ({ flags }) => (await import("./publish")).publishHub({ deploy: flags.deploy === true, deployOnly: flags["deploy-only"] === true, preview: typeof flags.preview === "string" ? flags.preview : undefined, force: flags.force === true, }), }, { path: ["publish", "homepage"], usage: "[--deploy | --deploy-only] [--preview ] [--to local] [--force] build homepage/out (source mirror included), then (--deploy) ship it; --deploy-only ships it as built", flags: { deploy: "boolean", "deploy-only": "boolean", preview: "string", to: "string", force: "boolean" }, run: async ({ flags }) => { const to = flags.to; if (to !== undefined && to !== "pages" && to !== "local") { console.error("publish homepage: --to is pages or local"); return 2; } return (await import("./publish")).publishHomepage({ deploy: flags.deploy === true, deployOnly: flags["deploy-only"] === true, preview: typeof flags.preview === "string" ? flags.preview : undefined, to: to as "pages" | "local" | undefined, force: flags.force === true, }); }, }, // `publish status` and `publish now` read the publish state view (release 18 // S3; bin/publishNow.ts). { path: ["publish", "status"], usage: "[--json] the publish status: the index, the lane, and per site / hub / homepage its policy and its built, deployed and live chips, then the plan Publish now would run", flags: { json: "boolean" }, run: async ({ flags }) => (await import("./publishNow")).publishStatusRow({ json: flags.json === true }), }, { path: ["publish", "now"], usage: "run what Publish now runs — the index update when it is stale, then each policy target's build and deploy (site.json publish.auto; settings.json publish.hub / publish.homepage), never forced — one stage at a time IN THIS PROCESS under the publish lock, as the editor's queue would (the CLI has no queue); exit 0 when every stage ran or was a no-op", run: async () => (await import("./publishNow")).publishNow(), }, { path: ["stage"], usage: " --run-id [--preview ] [--to local] [--runner docker] [--force] [--skip-archives] [--allow-missing-media] [--index-after ] [--built-after ] INTERNAL: one publish stage, as the editor's job runs it (exit 0 ran/no-op, 1 failed, 2 usage, 3 precondition not met, 130 cancelled)", // publish/stages.ts STAGE_FLAGS, spelled out so this table stays free of // imports (_cli.test.ts holds the two equal). flags: { "run-id": "string", preview: "string", to: "string", runner: "string", force: "boolean", "skip-archives": "boolean", "allow-missing-media": "boolean", "index-after": "string", "built-after": "string", }, maxPositionals: 2, run: async (ctx) => (await import("./publish")).stageRow(ctx), }, // The rows the stages replaced, kept as printed aliases. { path: ["build", "site"], usage: " [--nodata] [--skip-archives] [--allow-missing-media] alias: publish index (not with --nodata) + publish build --force (default id: SITE_ID)", flags: { nodata: "boolean", "skip-archives": "boolean", "allow-missing-media": "boolean" }, maxPositionals: 1, run: async ({ positionals, flags, env }) => { const siteId = siteIdFrom(positionals, env, "build site"); if (!siteId) return 2; return (await import("./publish")).buildSiteAlias({ siteId, nodata: flags.nodata === true, skipArchives: flags["skip-archives"] === true, allowMissingMedia: flags["allow-missing-media"] === true, }); }, }, { path: ["build", "all"], usage: "[--skip-archives] alias: publish index + publish build all --runner auto (containers when an engine answers, else serially on the host)", flags: { "skip-archives": "boolean" }, run: async ({ flags }) => (await import("./publish")).buildAllAlias({ skipArchives: flags["skip-archives"] === true }), }, { path: ["build", "hub"], // Kept RAW (export's `build:hub`, which e2e:2origin runs — an alias of // `publish index` would index whatever corpus is visible). Unstamped: // `deploy hub` ships the bundle `publish hub` builds, never this. usage: "compose:hub + INSTANCE_MODE=hub next build into export/out — a raw build, unstamped; to deploy the hub build it with `publish hub`", run: async () => { const { buildHub } = await import("../publish/build"); const code = await buildHub({ signal: interrupted() }); if (code !== 0) console.error(`build hub: failed (exit ${code})`); return code; }, }, { path: ["build", "homepage"], usage: "[--no-source] compose + source publish + next build in homepage/ (reads the index as it stands); --no-source removes the published source instead", flags: { "no-source": "boolean" }, run: async ({ flags }) => { const { buildHomepage } = await import("../publish/build"); const code = await buildHomepage({ signal: interrupted(), skipSource: flags["no-source"] === true, }); if (code !== 0) console.error(`build homepage: failed (exit ${code})`); return code; }, }, { path: ["reports", "prepare"], usage: " cut every clip and copy every post capture the site's published reports cite into its report-media cache, before its build, then export the reports as files (reports export) when nothing is missing (exit 1 when a citation lacks media or an export fails; default id: SITE_ID)", maxPositionals: 1, run: async ({ positionals, env }) => { const siteId = siteIdFrom(positionals, env, "reports prepare"); if (!siteId) return 2; return (await import("./reports-prepare")).main({ siteId, signal: interrupted() }); }, }, { path: ["reports", "export"], usage: " [--report ] [--formats html,pdf,md,slides,slides-pdf,zip] [--allow-missing-media] write the site's published reports as files (report.html, report.pdf, report.md, slides.html, slides.pdf, evidence-pack.zip) into its report-exports staging, where compose publishes them from (exit 1 on a problem; a PDF skipped for want of a browser is a note; default id: SITE_ID)", flags: { report: "string", formats: "string", "allow-missing-media": "boolean" }, maxPositionals: 1, run: async ({ positionals, flags, env }) => { const siteId = siteIdFrom(positionals, env, "reports export"); if (!siteId) return 2; const { parseReportExportFormats } = await import("../publish/reportExports"); const formats = typeof flags.formats === "string" ? parseReportExportFormats(flags.formats) : undefined; if (formats === null) { console.error("reports export: --formats is a comma-separated list of html, pdf, md, zip"); return 2; } return (await import("./reports-export")).main({ siteId, signal: interrupted(), ...(typeof flags.report === "string" ? { reportId: flags.report } : {}), ...(formats ? { formats } : {}), allowMissingMedia: flags["allow-missing-media"] === true, }); }, }, { path: ["reports", "check"], usage: " [--reports ] [--allow-missing-media] what compose would say about the site's reports, with no build: each report validated, every cited quote checked against its record, every cited moment's prepared media present and current, the report video under the publish limit (exit 1 with the list; --reports checks those, drafts included; default id: SITE_ID)", flags: { reports: "string", "allow-missing-media": "boolean" }, maxPositionals: 1, run: async ({ positionals, flags, env }) => { const siteId = siteIdFrom(positionals, env, "reports check"); if (!siteId) return 2; const reports = typeof flags.reports === "string" ? flags.reports.split(",").map((r) => r.trim()).filter(Boolean) : undefined; return (await import("./reports-check")).checkMain({ siteId, ...(reports ? { reports } : {}), allowMissingMedia: flags["allow-missing-media"] === true, }); }, }, { path: ["reports", "verify-quotes"], usage: " [--json] every video, audio and post quote of one report against its record with compose's own check: the best score and track, and the en-orig track's score where the record has one — a quote that matches a served `en` rewrite and not en-orig is reported (exit 1 when any quote drifted)", flags: { json: "boolean" }, maxPositionals: 1, run: async ({ positionals, flags }) => { const [file] = positionals; if (!file) { console.error("reports verify-quotes: give "); return 2; } return (await import("./reports-check")).verifyQuotesMain({ file, json: flags.json === true }); }, }, { path: ["reports", "attach-video"], usage: "