runRun
uses node:path
Runs tcm run.
import { routeRun } from "#codebase/tcmts/cli/commands"; import { execute, words } from "#codebase/tcmts/cli/main"; import { packagesIn } from "#codebase/tcmts/cli/manifests"; import type { Context } from "#codebase/tcmts/cli/run"; import { dim } from "#codebase/tcmts/cli/style"; import { commandsIn } from "#codebase/tcmts/cli/suites"; import { runOn } from "#codebase/tcmts/cli/sync"; import { chooseName, UsageError } from "#codebase/tcmts/cli/ui"; import { run } from "#codebase/tcmts/loader"; import { parse } from "@bomb.sh/router"; import path_1 from "node:path"; export async function runRun({ cb, cmd, rest }: Context): Promise<number> { const r = execute(cmd, parse(routeRun(), { argv: rest })); // a command of the codebase's packages, by its name: what its bin runs, with every argument const bin = r.model.bin; const target = bin ? packagesIn(cb, cb.store.names()).flatMap((p) => p.manifest.bin[bin] ? [`${p.namespace ? `${p.namespace}.` : ""}${p.manifest.bin[bin]}`] : [], )[0] : undefined; if (bin && !target) throw new UsageError(`no package here has a command called ${bin}`); const name = target ?? r.model.name ?? (await chooseName(cb, "run <name> [args...] [--on <remote>]", "Run what?", "value")); // (with --bin, a word before `--` is the command's first argument, not a definition's name) const args = [ ...(target && r.model.name !== undefined ? [r.model.name] : []), ...r.model.args, ...words(r.literals), ]; const h = cb.lookupOne(name, "value"); if (cb.store.getDef(h)!.kind === "type") throw new UsageError(`${name} is a type`); if (r.model.on !== undefined) return runOn(cb, r.model.on, h, args); // what it starts can run the codebase's commands, as <CMD>_BIN (a script running tcm, say). One the caller set is // kept, and said (an end-to-end test run against another tcm); one a tcm run further out set (TCM_COMMANDS // records them) is the codebase's build as it was then, so it's replaced, as is one of its runners (a `tcm run` // further out made it: a tcm from before TCM_COMMANDS doesn't record it) const before = JSON.parse(process.env.TCM_COMMANDS || "{}") as Record<string, string>; const set: Record<string, string> = {}; const runnerHere = (file: string) => path_1.dirname(path_1.resolve(file)) === path_1.resolve(cb.lay.cacheDir) && /^run_[a-z2-7]+\.ts$/.test(path_1.basename(file)); for (const [variable, runner] of Object.entries(commandsIn(cb))) { const given = process.env[variable]; if (given && given !== before[variable] && !runnerHere(given)) console.error(dim(`${variable} is set: ${given}, not this codebase's build`)); else process.env[variable] = set[variable] = runner; } process.env.TCM_COMMANDS = JSON.stringify({ ...before, ...set }); return run(h, args, cb.source(), cb.lay); }
uses
- tcmts.cli.commands.routeRun
- tcmts.cli.main.execute
- tcmts.cli.main.words
- tcmts.cli.manifests.packagesIn
- tcmts.cli.run.Context
- tcmts.cli.style.dim
- tcmts.cli.suites.commandsIn
- tcmts.cli.sync.runOn
- tcmts.cli.ui.UsageError
- tcmts.cli.ui.chooseName
- tcmts.loader.run