// GENERATED FILE — DO NOT EDIT BY HAND. // Source of truth: src/cli-exit.cts. Regenerate with: // node scripts/gen-scripts-cli-exit.cjs --write // Byte-compared by `npm run lint:generated-sync` (#3904, ADR-3889 Phase 0). // // Why this copy exists: scripts/ runs straight from the repo checkout and must // work on an unbuilt clone — 64+ scripts require this file, including // check-env.cjs, which runs before any build. gsd-core/bin/lib/cli-exit.cjs is // gitignored tsc output and doubles as the build sentinel, so it cannot be // required from here. Hence one source, two emitted locations. "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; /** * Process-exit primitives (ExitError, runMain) plus the json-error-mode cell. * Must import nothing but `node:fs` — this source is emitted to TWO locations, * gsd-core/bin/lib/cli-exit.cjs (tsc build output) and scripts/lib/cli-exit.cjs * (a generated, committed artifact regenerated by scripts/gen-scripts-cli-exit.cjs), * and the latter must load on an unbuilt clone before anything under ./lib exists. */ const node_fs_1 = __importDefault(require("node:fs")); /** * The wire value `runMain` stamps into its structured envelope. Declared HERE, * not in io.cts, because this module must not import anything (see the module * header): io.cts builds ERROR_REASON.SDK_FAIL_FAST from this constant, so the * two surfaces share ONE definition rather than two literals kept in step by a * parity test. */ const EXIT_ENVELOPE_REASON = 'sdk_fail_fast'; /** * Process-level flag: when true, error paths emit structured JSON to stderr * instead of plain text. Set by gsd-tools.cjs when the CLI is invoked with * `--json-errors`; re-exported by io.cts, which is where most callers reach it. * * Held in a Symbol-keyed cell on globalThis rather than in module scope, and * that is load-bearing: this module is emitted to TWO locations * (gsd-core/bin/lib/cli-exit.cjs and the generated scripts/lib/cli-exit.cjs), * so a process that loads both would get two independent module instances. A * module-level `let` would give them two independent flags — one copy could * think json mode is on while the other thought it was off, which is exactly * the divergence class ADR-3889 exists to remove. One cell, keyed by a * registry Symbol, makes that unrepresentable. */ const JSON_ERROR_MODE_KEY = Symbol.for('gsd.exit.jsonErrorMode'); function setJsonErrorMode(v) { globalThis[JSON_ERROR_MODE_KEY] = !!v; } function getJsonErrorMode() { return globalThis[JSON_ERROR_MODE_KEY] === true; } /** * Error carrying a process exit code. CLI logic throws this instead of calling * process.exit() (banned by n/no-process-exit); runMain() translates it into * process.exitCode at the entrypoint. */ class ExitError extends Error { code; hasUserMessage; constructor(code = 1, message) { super(message === undefined ? `process exit ${code}` : message); this.name = 'ExitError'; this.code = code; this.hasUserMessage = message !== undefined; } } /** * Run a CLI main and translate its outcome into process.exitCode (never * process.exit, so n/no-process-exit stays satisfied; output flushes and * process.on('exit') cleanup still fires). main may be sync or async: * number return -> process.exitCode = it * thrown ExitError -> process.exitCode = err.code (+ stderr err.message if hasUserMessage && code!=0) * other throw -> when json-error mode is active, emits structured { ok:false, reason, message } * to stderr; otherwise writes raw stack trace. exit code = 1 in either case. */ function runMain(main) { Promise.resolve() .then(() => main()) .then((code) => { if (typeof code === 'number') process.exitCode = code; }) .catch((err) => { if (err instanceof ExitError) { if (err.hasUserMessage && err.code !== 0) process.stderr.write(`${err.message}\n`); process.exitCode = err.code; return; } if (getJsonErrorMode()) { const e = err; const payload = JSON.stringify({ ok: false, reason: EXIT_ENVELOPE_REASON, message: (e && e.message) ? e.message : String(err), }) + '\n'; node_fs_1.default.writeSync(2, payload); } else { const e = err; process.stderr.write(`${e && e.stack ? e.stack : String(err)}\n`); } process.exitCode = 1; }); } module.exports = { ExitError, runMain, setJsonErrorMode, getJsonErrorMode, EXIT_ENVELOPE_REASON };