runRegistry
uses node:path
Runs tcm registry, without opening a codebase: the registry tcm ships (registry), copied into --dir (again when tcm's
changes) and run there by tcm start, its jobs with it, until it's stopped.
import { routeRegistry } from "#codebase/tcmts/cli/commands"; import { execute } from "#codebase/tcmts/cli/main"; import { SHIPPED_APP } from "#codebase/tcmts/cli/pack"; import { registryEnv } from "#codebase/tcmts/cli/run"; import type { Started } from "#codebase/tcmts/cli/run"; import { shippedApp } from "#codebase/tcmts/cli/sync"; import { UsageError } from "#codebase/tcmts/cli/ui"; import { parse } from "@bomb.sh/router"; import { spawn } from "node:child_process"; import { createHash } from "node:crypto"; import fs from "node:fs"; import path_1 from "node:path"; export async function runRegistry({ cmd, rest, cwd }: Started): Promise<number> { const m = execute(cmd, parse(routeRegistry(), { argv: rest })).model; const shipped = shippedApp("registry"); if (!shipped) throw new UsageError( "this tcm doesn't ship the registry: a tcm installed from its package does", ); const base = m.base?.replace(/\/+$/, ""); if (base !== undefined && !/^\/[^\s?#]+$/.test(base)) throw new UsageError(`--base ${m.base}: the path it's served under, as /registry`); const dir = path_1.resolve(cwd, m.dir); const from = path_1.join(shipped, "codebase.sqlite"); const to = path_1.join(dir, ".tcm", "codebase.sqlite"); const digest = createHash("sha256").update(fs.readFileSync(from)).digest("hex"); const mark = path_1.join(dir, ".tcm", "shipped"); if (fs.existsSync(path_1.join(dir, ".tcm")) && !fs.existsSync(mark)) throw new UsageError(`${dir} holds a codebase that isn't a registry: give another --dir`); if (!fs.existsSync(to) || fs.readFileSync(mark, "utf8") !== digest) { fs.mkdirSync(path_1.dirname(to), { recursive: true }); for (const f of [to, `${to}-wal`, `${to}-shm`]) fs.rmSync(f, { force: true }); fs.copyFileSync(from, to); fs.writeFileSync(mark, digest); } // (it stops when this does, however this ends) const env = registryEnv(process.env); const child = spawn( process.execPath, // (and its HTTP routes, under /api: its OAuth client metadata, for visitors signing in on a domain, and search; // all of it under the base, if it has one) [ process.argv[1]!, "start", SHIPPED_APP, "--port", String(m.port), "--host", m.host, "--http", "http=/api", ...(base ? ["--base", base] : []), ], { cwd: dir, env, stdio: "inherit" }, ); const stop = () => child.kill(); process.once("SIGINT", stop); process.once("SIGTERM", stop); return new Promise((resolve) => child.on("exit", (code) => resolve(code ?? 0))); }
uses
- tcmts.cli.commands.routeRegistry
- tcmts.cli.main.execute
- tcmts.cli.pack.SHIPPED_APP
- tcmts.cli.run.Started
- tcmts.cli.run.registryEnv
- tcmts.cli.sync.shippedApp
- tcmts.cli.ui.UsageError