diff --git a/packages/cli/test/artifact-flag-precedence.integration.test.ts b/packages/cli/test/artifact-flag-precedence.integration.test.ts index f01a6b1d96f..67128510686 100644 --- a/packages/cli/test/artifact-flag-precedence.integration.test.ts +++ b/packages/cli/test/artifact-flag-precedence.integration.test.ts @@ -85,7 +85,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; import { defineStackSourceFromLiteral, linkSpec, writeDefineStackConfig } from './helpers/define-stack-fixture.js'; @@ -127,7 +126,7 @@ interface Live { function boot(argv: string[], cwd: string, env: Record): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, ...argv], { + const child = spawn(process.execPath, [CLI, ...argv], { cwd, // `childEnv`, never a bare `...process.env` — see its header. Neither // artifact variable leaks in from the runner: each case states its own. diff --git a/packages/cli/test/build-json-advisory-parity.e2e.test.ts b/packages/cli/test/build-json-advisory-parity.e2e.test.ts index cf9f7517c93..8a382d60c74 100644 --- a/packages/cli/test/build-json-advisory-parity.e2e.test.ts +++ b/packages/cli/test/build-json-advisory-parity.e2e.test.ts @@ -82,7 +82,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -93,7 +92,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-json-failure-conversions.e2e.test.ts b/packages/cli/test/build-json-failure-conversions.e2e.test.ts index cb14fdd1eed..b903b643cbd 100644 --- a/packages/cli/test/build-json-failure-conversions.e2e.test.ts +++ b/packages/cli/test/build-json-failure-conversions.e2e.test.ts @@ -88,7 +88,6 @@ import { LIVE_PROBE, liveProbeNodeOptions } from './helpers/live-conversion-prob const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const COMPILE_TS = resolve(HERE, '../src/commands/compile.ts'); /** @@ -111,7 +110,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1', NODE_OPTIONS: liveProbeNodeOptions() }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-json-failure-warnings.e2e.test.ts b/packages/cli/test/build-json-failure-warnings.e2e.test.ts index 7dfddae7a5c..f9e215a3abc 100644 --- a/packages/cli/test/build-json-failure-warnings.e2e.test.ts +++ b/packages/cli/test/build-json-failure-warnings.e2e.test.ts @@ -93,7 +93,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const COMPILE_TS = resolve(HERE, '../src/commands/compile.ts'); interface Run { @@ -105,7 +104,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-json-undeclared-key-parity.e2e.test.ts b/packages/cli/test/build-json-undeclared-key-parity.e2e.test.ts index 722d21e38a9..728e8bebf33 100644 --- a/packages/cli/test/build-json-undeclared-key-parity.e2e.test.ts +++ b/packages/cli/test/build-json-undeclared-key-parity.e2e.test.ts @@ -75,7 +75,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -86,7 +85,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-multi-package-artifact.e2e.test.ts b/packages/cli/test/build-multi-package-artifact.e2e.test.ts index b3ea43f7118..9b01e1c6377 100644 --- a/packages/cli/test/build-multi-package-artifact.e2e.test.ts +++ b/packages/cli/test/build-multi-package-artifact.e2e.test.ts @@ -48,14 +48,13 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; stdout: string; stderr: string } function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-package-docs-attachment.e2e.test.ts b/packages/cli/test/build-package-docs-attachment.e2e.test.ts index d5036f5339e..e0ab1d5cb9e 100644 --- a/packages/cli/test/build-package-docs-attachment.e2e.test.ts +++ b/packages/cli/test/build-package-docs-attachment.e2e.test.ts @@ -48,14 +48,13 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; stdout: string; stderr: string } function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/build-text-face-advisory-count.test.ts b/packages/cli/test/build-text-face-advisory-count.test.ts index 349b708a2ac..cf6f0a99d9d 100644 --- a/packages/cli/test/build-text-face-advisory-count.test.ts +++ b/packages/cli/test/build-text-face-advisory-count.test.ts @@ -82,7 +82,7 @@ import { execFile } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { linkSpec } from './helpers/define-stack-fixture.js'; interface Run { @@ -94,7 +94,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/cloud-login-json-ndjson.e2e.test.ts b/packages/cli/test/cloud-login-json-ndjson.e2e.test.ts index 1c8cf80d177..24f64632f45 100644 --- a/packages/cli/test/cloud-login-json-ndjson.e2e.test.ts +++ b/packages/cli/test/cloud-login-json-ndjson.e2e.test.ts @@ -75,7 +75,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const CLOUD_LOGIN_SRC = resolve(HERE, '../src/commands/cloud/login.ts'); const REPO_ROOT = resolve(HERE, '../../..'); const CLI_DOCS = resolve(REPO_ROOT, 'content/docs/deployment/cli.mdx'); @@ -270,7 +269,7 @@ async function runCloudDeviceLogin(opts: { }); const shell = [ - `'${TSX}' '${CLI}' cloud login${opts.json ? ' --json' : ''} --no-browser`, + `'${process.execPath}' '${CLI}' cloud login${opts.json ? ' --json' : ''} --no-browser`, `--url 'http://127.0.0.1:${port}'`, `> '${outFile}' 2> '${errFile}'`, ].join(' '); diff --git a/packages/cli/test/compile-artifact-packages.e2e.test.ts b/packages/cli/test/compile-artifact-packages.e2e.test.ts index ffd37bf54e6..dd0143c3125 100644 --- a/packages/cli/test/compile-artifact-packages.e2e.test.ts +++ b/packages/cli/test/compile-artifact-packages.e2e.test.ts @@ -38,7 +38,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -49,7 +48,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/config-miss-stdout-purity.e2e.test.ts b/packages/cli/test/config-miss-stdout-purity.e2e.test.ts index 99a7f22b7ae..4cba5a00642 100644 --- a/packages/cli/test/config-miss-stdout-purity.e2e.test.ts +++ b/packages/cli/test/config-miss-stdout-purity.e2e.test.ts @@ -68,7 +68,6 @@ import { const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { key: string; @@ -80,7 +79,7 @@ interface Run { function runCli(argv: string[], cwd: string): Promise> { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...argv], { cwd, maxBuffer: 32 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -121,7 +120,7 @@ beforeAll(async () => { // branch misses and the explicit branch resolves against a real cwd. dir = mkdtempSync(join(tmpdir(), 'os-config-miss-e2e-')); - // Sequential: nineteen `tsx` starts at once is the kind of load that makes a + // Sequential: nineteen CLI starts at once is the kind of load that makes a // shared box report timeouts instead of verdicts. BOTH faces are driven — // the `--json` half is the contract this card repaired, the text half is the // one it had to leave untouched, and only driving the second proves it. diff --git a/packages/cli/test/create-example-retired.e2e.test.ts b/packages/cli/test/create-example-retired.e2e.test.ts index ce9a0935e1f..4f56597cd30 100644 --- a/packages/cli/test/create-example-retired.e2e.test.ts +++ b/packages/cli/test/create-example-retired.e2e.test.ts @@ -42,8 +42,8 @@ * `RETIRED_TEMPLATES` is asserted as DATA next door in `create.test.ts`. That * is worth nothing on its own: a registry nothing reads prints nothing. What is * measured here is a real child process — the exit status a CI script judges by - * `$?`, and the bytes that reach a terminal. Spawned through `bin/run-dev.js` + - * tsx so the suite does not depend on `packages/cli/dist` having been built + * `$?`, and the bytes that reach a terminal. Spawned through `bin/run-dev.js` + * so the suite does not depend on `packages/cli/dist` having been built * (`@objectstack/cli#test` depends on `^build` only), the same way * `create-refuses-invalid-project-name.e2e.test.ts` and * `generate-agent-retired.e2e.test.ts` spawn. @@ -52,7 +52,7 @@ * * `*.e2e.test.*` is a NAME-decided tier (`scripts/nightly-tiers.mjs`, #16455): * these files are excluded from the per-PR and merge-queue population and run - * in the nightly job. That is the right lane for four cold `tsx` spawns, and it + * in the nightly job. That is the right lane for four cold CLI spawns, and it * is where both of this pin's closest siblings already live * (`create-refuses-invalid-project-name.e2e.test.ts`, * `generate-agent-retired.e2e.test.ts`). @@ -75,7 +75,6 @@ import { RETIRED_TEMPLATES, templates } from '../src/commands/create.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold start with every command module loaded; ~2-10 s when healthy. */ const RUN_TIMEOUT_MS = 180_000; @@ -93,7 +92,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -122,7 +121,7 @@ let survivor: Run; beforeAll(async () => { dir = mkdtempSync(join(tmpdir(), 'os-create-example-retired-')); - // Sequential on purpose: four cold tsx starts, each loading every command + // Sequential on purpose: four cold CLI starts, each loading every command // module, in a container several agents share. retired = await runCli(['create', 'example', PROJECT], dir); retiredNoName = await runCli(['create', 'example'], dir); diff --git a/packages/cli/test/diff-usage-error-stream.e2e.test.ts b/packages/cli/test/diff-usage-error-stream.e2e.test.ts index bda0ece82bd..6d6f9109e08 100644 --- a/packages/cli/test/diff-usage-error-stream.e2e.test.ts +++ b/packages/cli/test/diff-usage-error-stream.e2e.test.ts @@ -68,7 +68,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const COMMANDS_DIR = resolve(HERE, '../src/commands'); /** The refusal and its two hint lines — what must be on stderr, never stdout. */ @@ -84,7 +83,7 @@ interface Run { function runCli(argv: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...argv], { cwd, maxBuffer: 32 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -137,7 +136,7 @@ beforeAll(async () => { // assumed, by making sure no stray `objectstack.config.*` is in reach. dir = mkdtempSync(join(tmpdir(), 'os-diff-usage-e2e-')); - // Sequential: concurrent `tsx` starts are the kind of load that makes a + // Sequential: concurrent CLI starts are the kind of load that makes a // shared box report timeouts instead of verdicts. control = await runCli(['diff', '--help'], dir); runs = {}; @@ -156,7 +155,7 @@ describe('control — the reading below is worthless without this', () => { // negative: empty streams, non-zero exit. Rule it out before reading // anything off the runs. expect(existsSync(CLI)).toBe(true); - expect(existsSync(TSX)).toBe(true); + expect(existsSync(process.execPath)).toBe(true); }); it('actually reaches `os diff` with this argv', () => { diff --git a/packages/cli/test/flow-credential-literal-doors.e2e.test.ts b/packages/cli/test/flow-credential-literal-doors.e2e.test.ts index 4bf05b48faf..d510c5c01c1 100644 --- a/packages/cli/test/flow-credential-literal-doors.e2e.test.ts +++ b/packages/cli/test/flow-credential-literal-doors.e2e.test.ts @@ -34,7 +34,6 @@ import { writeDefineStackConfig } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const SENTINELS = ['cli-header-sentinel', 'cli-url-sentinel', 'cli-input-sentinel'] as const; @@ -119,7 +118,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/generate-refuses-namespace-prefix.test.ts b/packages/cli/test/generate-refuses-namespace-prefix.test.ts index 2d303220202..585fce6b147 100644 --- a/packages/cli/test/generate-refuses-namespace-prefix.test.ts +++ b/packages/cli/test/generate-refuses-namespace-prefix.test.ts @@ -62,7 +62,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold starts, five of them, sequential. */ const RUN_TIMEOUT_MS = 240_000; @@ -75,10 +74,10 @@ interface Run { stderr: string; } -function runTsx(args: string[], cwd: string): Promise { +function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, args, { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -165,12 +164,12 @@ beforeAll(async () => { brokenBarrel = barrelOf(broken); brokenFiles = objectFilesIn(broken); - // Sequential on purpose: cold tsx starts in a container several agents share. + // Sequential on purpose: cold CLI starts in a container several agents share. // Every refusal runs BEFORE its project's control, so the barrel and file // snapshots above are what each refusal was measured against. - residual = await runTsx([CLI, 'generate', 'object', 'order__line'], namespaced); - residualDryRun = await runTsx([CLI, 'generate', 'view', 'order__line', '--dry-run'], namespaced); - loadFailed = await runTsx([CLI, 'generate', 'object', 'customer'], broken); + residual = await runCli([CLI, 'generate', 'object', 'order__line'], namespaced); + residualDryRun = await runCli([CLI, 'generate', 'view', 'order__line', '--dry-run'], namespaced); + loadFailed = await runCli([CLI, 'generate', 'object', 'customer'], broken); residualAfter = { barrel: barrelOf(namespaced), @@ -179,8 +178,8 @@ beforeAll(async () => { }; loadFailedAfter = { barrel: barrelOf(broken), files: objectFilesIn(broken) }; - namespacedControl = await runTsx([CLI, 'generate', 'object', 'order_line'], namespaced); - brokenControl = await runTsx([CLI, 'generate', 'dashboard', 'sales'], broken); + namespacedControl = await runCli([CLI, 'generate', 'object', 'order_line'], namespaced); + brokenControl = await runCli([CLI, 'generate', 'dashboard', 'sales'], broken); }, RUN_TIMEOUT_MS); afterAll(() => { diff --git a/packages/cli/test/generate-refuses-retired-generator.test.ts b/packages/cli/test/generate-refuses-retired-generator.test.ts index 84c2b45831e..c3457b872c0 100644 --- a/packages/cli/test/generate-refuses-retired-generator.test.ts +++ b/packages/cli/test/generate-refuses-retired-generator.test.ts @@ -54,7 +54,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold starts, four of them, sequential. */ const RUN_TIMEOUT_MS = 240_000; @@ -65,10 +64,10 @@ interface Run { stderr: string; } -function runTsx(args: string[], cwd: string): Promise { +function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, args, { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -103,15 +102,15 @@ let afterInherited: string[]; beforeAll(async () => { dir = mkdtempSync(join(tmpdir(), 'os-g-refuses-retired-')); - // Sequential on purpose: cold tsx starts in a container several agents share. + // Sequential on purpose: cold CLI starts in a container several agents share. // Every refusal runs BEFORE the control, so the listings below are what each // refusal was measured against. - schema = await runTsx([CLI, 'generate', 'schema'], dir); - schemaAlias = await runTsx([CLI, 'g', 'schema', '-o', 'custom.schema.json'], dir); + schema = await runCli([CLI, 'generate', 'schema'], dir); + schemaAlias = await runCli([CLI, 'g', 'schema', '-o', 'custom.schema.json'], dir); afterSchemaRuns = readdirSync(dir); - inherited = await runTsx([CLI, 'g', 'constructor', 'thing'], dir); + inherited = await runCli([CLI, 'g', 'constructor', 'thing'], dir); afterInherited = readdirSync(dir); - control = await runTsx([CLI, 'g', 'object', 'customer', '--dry-run'], dir); + control = await runCli([CLI, 'g', 'object', 'customer', '--dry-run'], dir); }, RUN_TIMEOUT_MS); afterAll(() => { diff --git a/packages/cli/test/generate-scaffold-gates.e2e.test.ts b/packages/cli/test/generate-scaffold-gates.e2e.test.ts index 03b7fa2999c..e004b736aab 100644 --- a/packages/cli/test/generate-scaffold-gates.e2e.test.ts +++ b/packages/cli/test/generate-scaffold-gates.e2e.test.ts @@ -79,7 +79,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); // One `resolve(HERE, …)` call per line: `check:cross-package-test-inputs` // reconstructs this read by SOURCE SCAN. @@ -135,7 +134,7 @@ function run(file: string, args: string[], cwd: string): Promise { }); } -const os = (args: string[], cwd: string) => run(TSX, [CLI, ...args], cwd); +const os = (args: string[], cwd: string) => run(process.execPath, [CLI, ...args], cwd); const out = (r: Run) => r.stdout + r.stderr; const target = (type: string) => { diff --git a/packages/cli/test/generate-scaffolds-reach-stack.e2e.test.ts b/packages/cli/test/generate-scaffolds-reach-stack.e2e.test.ts index d13273bec1e..43025d3f99b 100644 --- a/packages/cli/test/generate-scaffolds-reach-stack.e2e.test.ts +++ b/packages/cli/test/generate-scaffolds-reach-stack.e2e.test.ts @@ -52,7 +52,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = dirname(fileURLToPath(import.meta.url)); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold starts, ten of them, sequential. */ const RUN_TIMEOUT_MS = 480_000; @@ -69,7 +68,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/generate-schema-retired.e2e.test.ts b/packages/cli/test/generate-schema-retired.e2e.test.ts index 8722e58da34..c39199af381 100644 --- a/packages/cli/test/generate-schema-retired.e2e.test.ts +++ b/packages/cli/test/generate-schema-retired.e2e.test.ts @@ -23,8 +23,8 @@ * leaves the author hunting for a spelling of something that no longer * exists. They run on a REAL CHILD PROCESS and read stdout, for the reasons * that file gives (`process.exitCode` in a vitest worker is not an exit - * status; `printError` writes to stdout), spawned through `bin/run-dev.js` + - * tsx so the suite does not depend on `packages/cli/dist`. + * status; `printError` writes to stdout), spawned through `bin/run-dev.js` + * so the suite does not depend on `packages/cli/dist`. * * ## Why the DOOR is pinned, not only the ledger entry * @@ -52,7 +52,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold start, with every command module loaded; ~2-10 s when healthy. */ const RUN_TIMEOUT_MS = 240_000; @@ -63,10 +62,10 @@ interface Run { stderr: string; } -function runTsx(args: string[], cwd: string): Promise { +function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, args, { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -97,16 +96,16 @@ let survivor: Run; beforeAll(async () => { dir = mkdtempSync(join(tmpdir(), 'os-g-schema-retired-')); - // Sequential on purpose: five cold tsx starts, each loading every command + // Sequential on purpose: five cold CLI starts, each loading every command // module, in a container several agents share. - retired = await runTsx([CLI, 'generate', 'schema'], dir); - retiredAlias = await runTsx([CLI, 'g', 'schema', '-o', 'custom.schema.json'], dir); + retired = await runCli([CLI, 'generate', 'schema'], dir); + retiredAlias = await runCli([CLI, 'g', 'schema', '-o', 'custom.schema.json'], dir); // Listed right after the two schema runs and before anything else runs in // this directory: the default target and the `-o` target must both be absent. writtenBySchemaRuns = readdirSync(dir); - agentNoName = await runTsx([CLI, 'g', 'agent'], dir); - inherited = await runTsx([CLI, 'g', 'constructor', 'thing'], dir); - survivor = await runTsx([CLI, 'g', 'object', 'customer', '--dry-run'], dir); + agentNoName = await runCli([CLI, 'g', 'agent'], dir); + inherited = await runCli([CLI, 'g', 'constructor', 'thing'], dir); + survivor = await runCli([CLI, 'g', 'object', 'customer', '--dry-run'], dir); }, RUN_TIMEOUT_MS); afterAll(() => { diff --git a/packages/cli/test/i18n-check-platform-bucket.e2e.test.ts b/packages/cli/test/i18n-check-platform-bucket.e2e.test.ts index a3b85faf7e9..444d7da7226 100644 --- a/packages/cli/test/i18n-check-platform-bucket.e2e.test.ts +++ b/packages/cli/test/i18n-check-platform-bucket.e2e.test.ts @@ -38,7 +38,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const CLI_PACKAGE_ROOT = resolve(HERE, '..'); /** An app that translates everything it owns and ships no platform bundle. */ @@ -106,7 +105,7 @@ interface Run { } function runCheck(args: readonly string[]): Run { - const child = spawnSync(TSX, [CLI, 'i18n', 'check', ...args], { + const child = spawnSync(process.execPath, [CLI, 'i18n', 'check', ...args], { cwd: CLI_PACKAGE_ROOT, encoding: 'utf8', env: childEnv(), diff --git a/packages/cli/test/i18n-extract-check-hint.e2e.test.ts b/packages/cli/test/i18n-extract-check-hint.e2e.test.ts index d1978a240ef..7cd5179995c 100644 --- a/packages/cli/test/i18n-extract-check-hint.e2e.test.ts +++ b/packages/cli/test/i18n-extract-check-hint.e2e.test.ts @@ -77,7 +77,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const CLI_PACKAGE_ROOT = resolve(HERE, '..'); /** @@ -117,7 +116,7 @@ beforeAll(() => { // entry point in first would edit the very bytes under test. shimRoot = mkdtempSync(join(tmpdir(), 'os-i18n-14895-bin-')); const shim = join(shimRoot, 'os'); - writeFileSync(shim, `#!/bin/sh\nexec ${JSON.stringify(TSX)} ${JSON.stringify(CLI)} "$@"\n`, 'utf8'); + writeFileSync(shim, `#!/bin/sh\nexec ${JSON.stringify(process.execPath)} ${JSON.stringify(CLI)} "$@"\n`, 'utf8'); chmodSync(shim, 0o755); }); @@ -142,7 +141,7 @@ interface Run { /** The CLI, from source, with `--check`'s non-zero exit treated as data. */ function runCli(args: readonly string[], cwd: string = CLI_PACKAGE_ROOT): Run { - const child = spawnSync(TSX, [CLI, 'i18n', 'extract', ...args], { + const child = spawnSync(process.execPath, [CLI, 'i18n', 'extract', ...args], { cwd, encoding: 'utf8', env: childEnv(), @@ -273,7 +272,7 @@ describe('os i18n extract --check — the hint is the invocation, not a reconstr expect(run.status).toBe(1); expect(driftPaths(run.stdout)).toEqual([join('bundles', 'zh-CN.objects.generated.ts')]); }); - // Every case spawns the CLI through `tsx`, and the healing cases spawn it + // Every case spawns the CLI's source entry, and the healing cases spawn it // three times; measured at ~6 s per run on a shared box, well over vitest's // 5 s default. Same instrument and the same generous ceiling as the sibling // CLI-spawning pins in this directory. diff --git a/packages/cli/test/i18n-extract-key-count.e2e.test.ts b/packages/cli/test/i18n-extract-key-count.e2e.test.ts index e1114128af6..db251572c3b 100644 --- a/packages/cli/test/i18n-extract-key-count.e2e.test.ts +++ b/packages/cli/test/i18n-extract-key-count.e2e.test.ts @@ -59,7 +59,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const CLI_PACKAGE_ROOT = resolve(HERE, '..'); /** One object (2 leaves) + one app (1 leaf); the registry baseline rides along. */ @@ -116,7 +115,7 @@ function plain(text: string): string { function runExtract(name: string, config: string, flags: readonly string[]): { stdout: string; dir: string; files: string[] } { const dir = join(outRoot, name); - const stdout = execFileSync(TSX, [CLI, 'i18n', 'extract', config, '--locales=zh-CN', ...flags, `--out=${dir}`], { + const stdout = execFileSync(process.execPath, [CLI, 'i18n', 'extract', config, '--locales=zh-CN', ...flags, `--out=${dir}`], { encoding: 'utf8', env: childEnv(), timeout: 180_000, @@ -238,7 +237,7 @@ describe('os i18n extract — the number printed is the number written (#16121)' */ it('--json counts describe the payload printed beside them, in both sub-tree modes', () => { const runJson = (flags: readonly string[]) => { - const stdout = execFileSync(TSX, [CLI, 'i18n', 'extract', CONFIG, '--locales=zh-CN', '--json', ...flags], { + const stdout = execFileSync(process.execPath, [CLI, 'i18n', 'extract', CONFIG, '--locales=zh-CN', '--json', ...flags], { encoding: 'utf8', env: childEnv(), timeout: 180_000, @@ -335,7 +334,7 @@ describe('os i18n extract — the number printed is the number written (#16121)' ); expect(summaryRow(wide.stdout).emitted).toBe(1); }); - // Each case spawns the CLI through `tsx`; measured at ~6 s per run on a + // Each case spawns the CLI's source entry; measured at ~6 s per run on a // shared box, well over vitest's 5 s default. Same instrument and the same // generous ceiling as the sibling CLI-spawning pins in this directory. }, 900_000); diff --git a/packages/cli/test/i18n-extract-metadata-forms-flag.e2e.test.ts b/packages/cli/test/i18n-extract-metadata-forms-flag.e2e.test.ts index c9fdbb1c7c4..5b2c023d2ca 100644 --- a/packages/cli/test/i18n-extract-metadata-forms-flag.e2e.test.ts +++ b/packages/cli/test/i18n-extract-metadata-forms-flag.e2e.test.ts @@ -55,7 +55,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** * The fixture goes under this package's git-ignored `tmp/`; the `--out` root @@ -120,7 +119,7 @@ afterAll(() => { /** Run the real command; returns stdout and the files it left in `--out`. */ function extract(name: string, flags: string[]): { stdout: string; files: string[]; dir: string } { const dir = join(outRoot, name); - const stdout = execFileSync(TSX, [CLI, 'i18n', 'extract', CONFIG, '--locales=zh-CN', ...flags, `--out=${dir}`], { + const stdout = execFileSync(process.execPath, [CLI, 'i18n', 'extract', CONFIG, '--locales=zh-CN', ...flags, `--out=${dir}`], { encoding: 'utf8', env: childEnv(), timeout: 180_000, @@ -200,7 +199,7 @@ describe('os i18n extract — the metadata-form baseline has exactly one home (# it('--json mirrors the file set in BOTH flag states', () => { const runJson = (flags: string[]) => { const stdout = execFileSync( - TSX, + process.execPath, [CLI, 'i18n', 'extract', CONFIG, '--locales=zh-CN', '--json', '--no-objects-only', ...flags], { encoding: 'utf8', env: childEnv(), timeout: 180_000 }, ); @@ -246,7 +245,7 @@ describe('os i18n extract — the metadata-form baseline has exactly one home (# withoutDuration(off as unknown as Record), ); }); - // Each case spawns the CLI through `tsx`; measured at ~6 s per run on a + // Each case spawns the CLI's source entry; measured at ~6 s per run on a // shared box, well over vitest's 5 s default. Same instrument and same // generous ceiling as the sibling CLI-spawning pins in this directory. }, 900_000); diff --git a/packages/cli/test/init-created-files-summary.e2e.test.ts b/packages/cli/test/init-created-files-summary.e2e.test.ts index ca31019d16a..fcbe11aa94d 100644 --- a/packages/cli/test/init-created-files-summary.e2e.test.ts +++ b/packages/cli/test/init-created-files-summary.e2e.test.ts @@ -62,7 +62,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); const REPO_ROOT = resolve(HERE, '../../..'); -const TSX = resolve(REPO_ROOT, 'node_modules/.bin/tsx'); const SPEC_PKG = resolve(REPO_ROOT, 'packages/spec'); interface Run { @@ -74,7 +73,7 @@ interface Run { function runCli(args: string[], cwd: string, env: Record): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1', ...env }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/json-stdout-purity.e2e.test.ts b/packages/cli/test/json-stdout-purity.e2e.test.ts index cea60762339..a22344bae82 100644 --- a/packages/cli/test/json-stdout-purity.e2e.test.ts +++ b/packages/cli/test/json-stdout-purity.e2e.test.ts @@ -71,7 +71,6 @@ import { CONFIG_MISS_FAMILY, discoverConfigMissFamily } from './helpers/config-m const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const COMMANDS_DIR = resolve(HERE, '../src/commands'); const UTILS_DIR = resolve(HERE, '../src/utils'); @@ -307,7 +306,7 @@ interface Run { function runCli(argv: string[], cwd: string, env: Record): Promise> { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...argv], { cwd, maxBuffer: 32 * 1024 * 1024, env: childEnv({ NO_COLOR: '1', ...env }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/jsx-gate-manifest-notice.e2e.test.ts b/packages/cli/test/jsx-gate-manifest-notice.e2e.test.ts index 45306ee08e2..ed865b23096 100644 --- a/packages/cli/test/jsx-gate-manifest-notice.e2e.test.ts +++ b/packages/cli/test/jsx-gate-manifest-notice.e2e.test.ts @@ -58,7 +58,6 @@ import { consoleSduiManifestPath } from '../src/utils/sdui-manifest.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** * Whether the manifest-less path is reachable in THIS checkout (#19922). With @@ -88,7 +87,7 @@ interface Run { function runCli(args: readonly string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-conversion-notices.e2e.test.ts b/packages/cli/test/lint-conversion-notices.e2e.test.ts index b5693c7423e..be796b54b1d 100644 --- a/packages/cli/test/lint-conversion-notices.e2e.test.ts +++ b/packages/cli/test/lint-conversion-notices.e2e.test.ts @@ -82,7 +82,6 @@ import { LIVE_PROBE, liveProbeNodeOptions } from './helpers/live-conversion-prob const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** * The live ADR-0087 D2 conversion these fixtures drive: a TEST-ONLY probe the @@ -102,7 +101,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1', NODE_OPTIONS: liveProbeNodeOptions() }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-eval-empty-generator-refusal.e2e.test.ts b/packages/cli/test/lint-eval-empty-generator-refusal.e2e.test.ts index c2386c972c1..4fcbc1085b9 100644 --- a/packages/cli/test/lint-eval-empty-generator-refusal.e2e.test.ts +++ b/packages/cli/test/lint-eval-empty-generator-refusal.e2e.test.ts @@ -78,7 +78,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -126,7 +125,7 @@ function clearMarker(): void { function runLint(args: string[]): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, 'lint', ...args], { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-eval-generator-load-envelope.e2e.test.ts b/packages/cli/test/lint-eval-generator-load-envelope.e2e.test.ts index a0c93ac44c8..d1e852033aa 100644 --- a/packages/cli/test/lint-eval-generator-load-envelope.e2e.test.ts +++ b/packages/cli/test/lint-eval-generator-load-envelope.e2e.test.ts @@ -98,7 +98,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -117,7 +116,7 @@ function generator(name: string, source: string): string { function runLint(args: string[]): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, 'lint', '--eval', ...args], { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-eval-json-unscorable-stack.e2e.test.ts b/packages/cli/test/lint-eval-json-unscorable-stack.e2e.test.ts index 54512eba16f..2ec7e8c1d19 100644 --- a/packages/cli/test/lint-eval-json-unscorable-stack.e2e.test.ts +++ b/packages/cli/test/lint-eval-json-unscorable-stack.e2e.test.ts @@ -72,7 +72,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -92,7 +91,7 @@ function runEval(generatorPath?: string): Promise { const args = [CLI, 'lint', '--eval', '--json', ...(generatorPath ? ['--generator', generatorPath] : [])]; return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, args, { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-generator-requires-eval.e2e.test.ts b/packages/cli/test/lint-generator-requires-eval.e2e.test.ts index 61de6e667be..21aad68491a 100644 --- a/packages/cli/test/lint-generator-requires-eval.e2e.test.ts +++ b/packages/cli/test/lint-generator-requires-eval.e2e.test.ts @@ -62,7 +62,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -110,7 +109,7 @@ function clearMarker(): void { function runLint(args: string[]): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, 'lint', ...args], { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-hook-rules-reach-handler-hooks.e2e.test.ts b/packages/cli/test/lint-hook-rules-reach-handler-hooks.e2e.test.ts index 52c616cb500..b15e1722dbb 100644 --- a/packages/cli/test/lint-hook-rules-reach-handler-hooks.e2e.test.ts +++ b/packages/cli/test/lint-hook-rules-reach-handler-hooks.e2e.test.ts @@ -47,7 +47,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const READONLY_RULE = 'hook-api-update-readonly-field'; @@ -60,7 +59,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/lint-per-package-authoring-parity.test.ts b/packages/cli/test/lint-per-package-authoring-parity.test.ts index fcfdccb4cfe..ba958dfbd5b 100644 --- a/packages/cli/test/lint-per-package-authoring-parity.test.ts +++ b/packages/cli/test/lint-per-package-authoring-parity.test.ts @@ -55,7 +55,7 @@ import { execFile } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { linkSpec } from './helpers/define-stack-fixture.js'; interface Run { @@ -67,7 +67,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -212,7 +212,7 @@ export default defineStack({ const dirs = { flip: '', single: '' }; -/** A cold `tsx` spawn of the CLI source entry, the per-case allowance this file always gave one. */ +/** A cold spawn of the CLI source entry, the per-case allowance this file always gave one. */ const SPAWN_TIMEOUT_MS = 180_000; /** diff --git a/packages/cli/test/lint-strict-warnings.e2e.test.ts b/packages/cli/test/lint-strict-warnings.e2e.test.ts index 60ff03b4c32..8ae72703048 100644 --- a/packages/cli/test/lint-strict-warnings.e2e.test.ts +++ b/packages/cli/test/lint-strict-warnings.e2e.test.ts @@ -68,7 +68,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** The console sentence a strict-only failure must print — count, then flag. */ const STRICT_REASON = /(\d+) warning\(s\) fail this run under --strict/; @@ -82,7 +81,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/login-json-ndjson.e2e.test.ts b/packages/cli/test/login-json-ndjson.e2e.test.ts index 5713a8ec363..43d47fb618f 100644 --- a/packages/cli/test/login-json-ndjson.e2e.test.ts +++ b/packages/cli/test/login-json-ndjson.e2e.test.ts @@ -71,7 +71,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const LOGIN_SRC = resolve(HERE, '../src/commands/login.ts'); const REPO_ROOT = resolve(HERE, '../../..'); const CLI_DOCS = resolve(REPO_ROOT, 'content/docs/deployment/cli.mdx'); @@ -259,7 +258,7 @@ async function runDeviceLogin(outcome: 'token' | 'access_denied'): Promise '${outFile}' 2> '${errFile}'`, ].join(' '); diff --git a/packages/cli/test/login-json-noninteractive.e2e.test.ts b/packages/cli/test/login-json-noninteractive.e2e.test.ts index 13c4090d8b7..7ec6ee526ef 100644 --- a/packages/cli/test/login-json-noninteractive.e2e.test.ts +++ b/packages/cli/test/login-json-noninteractive.e2e.test.ts @@ -61,7 +61,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const LOGIN_SRC = resolve(HERE, '../src/commands/login.ts'); const CLI_DOCS = resolve(HERE, '../../..', 'content/docs/deployment/cli.mdx'); @@ -99,7 +98,7 @@ function runLogin(args: string[], answer: Array<{ when: RegExp; send: string }> const home = join(dir, 'home'); return new Promise((done) => { - const child = spawn(TSX, [CLI, 'login', ...args], { + const child = spawn(process.execPath, [CLI, 'login', ...args], { stdio: ['pipe', 'pipe', 'pipe'], env: childEnv({ HOME: home, NO_COLOR: '1' }), }); diff --git a/packages/cli/test/migrate-meta.e2e.test.ts b/packages/cli/test/migrate-meta.e2e.test.ts index b0bf89a148b..ef78599a02b 100644 --- a/packages/cli/test/migrate-meta.e2e.test.ts +++ b/packages/cli/test/migrate-meta.e2e.test.ts @@ -30,7 +30,6 @@ import { childEnv } from './helpers/serve-process.js'; const execFileP = promisify(execFile); const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** * A stack authored against protocol 16: every line marked `// 16:` is a shape @@ -137,7 +136,7 @@ let dir: string; let out: { stdout: string; parsed: any }; async function runMeta(args: string[], cwd: string) { - const { stdout } = await execFileP(TSX, [CLI, 'migrate', 'meta', ...args], { + const { stdout } = await execFileP(process.execPath, [CLI, 'migrate', 'meta', ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }), @@ -455,7 +454,7 @@ export default defineStack({ it('still refuses the same source everywhere else — `os validate` keeps the prescription', async () => { let refused = false; try { - await execFileP(TSX, [CLI, 'validate'], { + await execFileP(process.execPath, [CLI, 'validate'], { cwd: rkDir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/package-install-local-boot-steps.integration.test.ts b/packages/cli/test/package-install-local-boot-steps.integration.test.ts index 84808bc4ddf..bcbd2d9e66a 100644 --- a/packages/cli/test/package-install-local-boot-steps.integration.test.ts +++ b/packages/cli/test/package-install-local-boot-steps.integration.test.ts @@ -59,7 +59,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -155,7 +154,7 @@ interface LiveStart { function bootStart(cwd: string, home: string, extra: string[] = []): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { cwd, // `childEnv`, never a bare `...process.env` — see its header. env: childEnv({ NO_COLOR: '1', OS_CLOUD_URL: 'off', OS_LOG_LEVEL: 'warn', OS_SECRET_KEY: E2E_SECRET_KEY }), @@ -247,7 +246,7 @@ async function authenticate(live: LiveStart): Promise { */ function packageInstall(appDir: string, live: LiveStart): Promise<{ exit: number | null; output: string }> { return new Promise((done) => { - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-install-local-hooks.integration.test.ts b/packages/cli/test/package-install-local-hooks.integration.test.ts index 3245570ae5d..6a1638fa0b8 100644 --- a/packages/cli/test/package-install-local-hooks.integration.test.ts +++ b/packages/cli/test/package-install-local-hooks.integration.test.ts @@ -56,7 +56,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -215,7 +214,7 @@ interface LiveStart { function bootStart(cwd: string, home: string, extra: string[] = []): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { cwd, // `childEnv`, never a bare `...process.env` — see its header. Package // scheduled work is OFF by default in every posture (#17396); this @@ -315,7 +314,7 @@ async function authenticate(live: LiveStart): Promise { */ function packageInstall(appDir: string, live: LiveStart): Promise<{ exit: number | null; output: string }> { return new Promise((done) => { - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-install-local-jobs-pull.integration.test.ts b/packages/cli/test/package-install-local-jobs-pull.integration.test.ts index fcab92ed5d1..99418f23dff 100644 --- a/packages/cli/test/package-install-local-jobs-pull.integration.test.ts +++ b/packages/cli/test/package-install-local-jobs-pull.integration.test.ts @@ -61,7 +61,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -182,7 +181,7 @@ interface LiveStart { function bootStart(cwd: string, home: string, extra: string[] = []): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { cwd, // `childEnv`, never a bare `...process.env` — see its header. Package // scheduled work is OFF by default in every posture (#17396); this @@ -282,7 +281,7 @@ async function authenticate(live: LiveStart): Promise { */ function packageInstall(appDir: string, live: LiveStart): Promise<{ exit: number | null; output: string }> { return new Promise((done) => { - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts b/packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts index f25adea7df2..ad6f98f0a6a 100644 --- a/packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts +++ b/packages/cli/test/package-install-local-jobs-shared-name.integration.test.ts @@ -57,7 +57,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -142,7 +141,7 @@ interface LiveStart { function bootStart(cwd: string, home: string, extra: string[] = []): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { cwd, // `childEnv`, never a bare `...process.env` — see its header. Package // scheduled work is OFF by default in every posture (#17396); this @@ -267,8 +266,8 @@ interface InstallRun { exit: number | null; output: string; elapsedMs: number } * process draining the server's pipes for the whole install. * * The child runs until `deadline` (see `SETUP_BUDGET_MS`). It gets its own - * process group, so the kill reaches the node process `tsx` starts as well. - * That process holds the pipes, and `close` would wait for it. A kill REJECTS, + * process group, so the kill reaches every process the install started. + * The CLI process holds the pipes, and `close` would wait for it. A kill REJECTS, * naming the install, the wall time and the budget: the rest of the hook could * only run into vitest's hook timeout. An install that exits by itself * resolves, whatever its code, and the first `it` judges it. @@ -276,7 +275,7 @@ interface InstallRun { exit: number | null; output: string; elapsedMs: number } function packageInstall(appDir: string, live: LiveStart, deadline: number): Promise { return new Promise((done, fail) => { const started = Date.now(); - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-install-local-jobs.integration.test.ts b/packages/cli/test/package-install-local-jobs.integration.test.ts index 07c2998219c..2cb1f6e7866 100644 --- a/packages/cli/test/package-install-local-jobs.integration.test.ts +++ b/packages/cli/test/package-install-local-jobs.integration.test.ts @@ -58,7 +58,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -201,7 +200,7 @@ interface LiveStart { function bootStart(cwd: string, home: string, extra: string[] = []): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui', ...extra], { cwd, // `childEnv`, never a bare `...process.env` — see its header. Package // scheduled work is OFF by default in every posture (#17396); this @@ -301,7 +300,7 @@ async function authenticate(live: LiveStart): Promise { */ function packageInstall(appDir: string, live: LiveStart): Promise<{ exit: number | null; output: string }> { return new Promise((done) => { - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-install-local-uninstall-cleanups.integration.test.ts b/packages/cli/test/package-install-local-uninstall-cleanups.integration.test.ts index 362323c7771..cff225fff07 100644 --- a/packages/cli/test/package-install-local-uninstall-cleanups.integration.test.ts +++ b/packages/cli/test/package-install-local-uninstall-cleanups.integration.test.ts @@ -74,7 +74,6 @@ import { KERNEL_ASSIGNED_PORT, probeThroughChild, readKernelAssignedPort, - TSX, } from './helpers/serve-process.js'; /** The banner's tail — every row above it has printed. */ @@ -132,7 +131,7 @@ interface LiveStart { function bootStart(cwd: string, home: string): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui'], { + const child = spawn(process.execPath, [CLI, 'start', '-p', KERNEL_ASSIGNED_PORT, '--home', home, '--auth-secret', E2E_SECRET_KEY, '--no-ui'], { cwd, // `childEnv`, never a bare `...process.env` — see its header. env: childEnv({ NO_COLOR: '1', OS_CLOUD_URL: 'off', OS_LOG_LEVEL: 'warn', OS_SECRET_KEY: E2E_SECRET_KEY }), @@ -227,7 +226,7 @@ async function authenticate(live: LiveStart): Promise { */ function packageInstall(appDir: string, live: LiveStart): Promise<{ exit: number | null; output: string }> { return new Promise((done) => { - const child = spawn(TSX, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { + const child = spawn(process.execPath, [CLI, 'package', 'install', './dist/objectstack.json', '--runtime', live.base, '--email', EMAIL, '--password', PASSWORD], { cwd: appDir, env: childEnv({ NO_COLOR: '1' }), stdio: ['ignore', 'pipe', 'pipe'], diff --git a/packages/cli/test/package-union-readers.test.ts b/packages/cli/test/package-union-readers.test.ts index f7b3928ddd5..9518fab4796 100644 --- a/packages/cli/test/package-union-readers.test.ts +++ b/packages/cli/test/package-union-readers.test.ts @@ -42,7 +42,7 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { linkSpec } from './helpers/define-stack-fixture.js'; interface Run { code: number; stdout: string; stderr: string } @@ -50,7 +50,7 @@ interface Run { code: number; stdout: string; stderr: string } function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/picklist-reference-doors.test.ts b/packages/cli/test/picklist-reference-doors.test.ts index e202ea0d695..05c2ea7da65 100644 --- a/packages/cli/test/picklist-reference-doors.test.ts +++ b/packages/cli/test/picklist-reference-doors.test.ts @@ -37,7 +37,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** oclif + tsx cold start, with every command module loaded. */ const RUN_TIMEOUT_MS = 180_000; @@ -51,7 +50,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/qa-empty-glob-exit-code.e2e.test.ts b/packages/cli/test/qa-empty-glob-exit-code.e2e.test.ts index 87658e56ae3..eeaeee646a7 100644 --- a/packages/cli/test/qa-empty-glob-exit-code.e2e.test.ts +++ b/packages/cli/test/qa-empty-glob-exit-code.e2e.test.ts @@ -25,8 +25,8 @@ * * It has to be a real child process. `process.exit(1)` inside a vitest worker * is not an exit status — the number a shell, a `set -e` script or a CI step - * reads only exists once Node has exited. Spawned through `bin/run-dev.js` + - * tsx (the pattern `migrate-exit-code.e2e.test.ts` and `emit-json-pipe.test.ts` + * reads only exists once Node has exited. Spawned through `bin/run-dev.js` + * (the pattern `migrate-exit-code.e2e.test.ts` and `emit-json-pipe.test.ts` * already use) so the suite does not depend on `packages/cli/dist` having been * built. No server is contacted on this path — the command resolves the glob * before it sends anything — so the run needs neither a boot nor a config. @@ -42,7 +42,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); /** Matches nothing, in a temp dir that contains nothing. */ const EMPTY_PATTERN = 'qa/nothing-matches-*.test.json'; @@ -59,7 +58,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 8 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/requires-retired-capability.e2e.test.ts b/packages/cli/test/requires-retired-capability.e2e.test.ts index e932220e0b5..d5ba46aba54 100644 --- a/packages/cli/test/requires-retired-capability.e2e.test.ts +++ b/packages/cli/test/requires-retired-capability.e2e.test.ts @@ -33,7 +33,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -44,7 +43,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/serve-app-anchored-optional-import.e2e.test.ts b/packages/cli/test/serve-app-anchored-optional-import.e2e.test.ts index 5cc52742428..01e724c1150 100644 --- a/packages/cli/test/serve-app-anchored-optional-import.e2e.test.ts +++ b/packages/cli/test/serve-app-anchored-optional-import.e2e.test.ts @@ -153,8 +153,6 @@ const HERE = dirname(fileURLToPath(import.meta.url)); /** `bin/run-dev.js` — this package's own entrypoint, run from TS source. */ const CLI = resolve(HERE, '../bin/run-dev.js'); -/** The workspace `tsx` binary (an installed dependency, not a repo source input). */ -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const CONFIG = ` export default { @@ -370,7 +368,7 @@ function runServeFrom( return new Promise((resolveRun, rejectRun) => { // A kernel-assigned port (#24342): no number is drawn here, so none can be // taken between a pick and the child's bind. - const child = spawn(TSX, [CLI, 'serve', configArg, '--port', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', configArg, '--port', KERNEL_ASSIGNED_PORT], { cwd, env: childEnv({ NO_COLOR: '1', diff --git a/packages/cli/test/serve-app-runtime-hooks.e2e.test.ts b/packages/cli/test/serve-app-runtime-hooks.e2e.test.ts index 045a0fe79dd..ceaf83bc718 100644 --- a/packages/cli/test/serve-app-runtime-hooks.e2e.test.ts +++ b/packages/cli/test/serve-app-runtime-hooks.e2e.test.ts @@ -27,7 +27,7 @@ import { promisify } from 'node:util'; import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { childEnv, runServe, CLI, TSX } from './helpers/serve-process.js'; +import { childEnv, runServe, CLI } from './helpers/serve-process.js'; import { linkSpec } from './helpers/define-stack-fixture.js'; const execFileP = promisify(execFile); @@ -82,7 +82,7 @@ beforeAll(async () => { // regression is about. Without it serve wraps the config directly (#4085/#4110 // made that path boot), `onEnable` runs for the trivial reason, and the test // would pass while exercising nothing. - await execFileP(TSX, [CLI, 'compile'], { + await execFileP(process.execPath, [CLI, 'compile'], { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/serve-config-boot-flat-docs.integration.test.ts b/packages/cli/test/serve-config-boot-flat-docs.integration.test.ts index 4243aad2672..43a32d2e165 100644 --- a/packages/cli/test/serve-config-boot-flat-docs.integration.test.ts +++ b/packages/cli/test/serve-config-boot-flat-docs.integration.test.ts @@ -59,7 +59,6 @@ import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, - TSX, childEnv, probeThroughChild, readKernelAssignedPort, @@ -146,7 +145,7 @@ interface LiveServe { /** Boot `os serve objectstack.config.ts --dev` and keep it running; `--dev` seeds the admin. */ function bootServe(dir: string): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). diff --git a/packages/cli/test/serve-config-boot-residual.integration.test.ts b/packages/cli/test/serve-config-boot-residual.integration.test.ts index 25f41ffd48b..f7aabb5016b 100644 --- a/packages/cli/test/serve-config-boot-residual.integration.test.ts +++ b/packages/cli/test/serve-config-boot-residual.integration.test.ts @@ -63,7 +63,6 @@ import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, - TSX, childEnv, probeThroughChild, readKernelAssignedPort, @@ -204,7 +203,7 @@ function build(dir: string): Promise { function runCli(dir: string, args: string[]): Promise { return new Promise((done) => { execFile( - TSX, + process.execPath, [CLI, ...args], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, @@ -236,7 +235,7 @@ interface LiveServe { /** Boot `os serve` in `dir` with `args`; the source entry seeds the dev admin either way. */ function bootServe(dir: string, args: string[]): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). @@ -395,7 +394,7 @@ async function read(dir: string, args: string[]): Promise { */ function bootRefused(dir: string, args: string[]): Promise<{ code: number | null; output: string }> { return new Promise((resolveRefusal, rejectRefusal) => { - const child = spawn(TSX, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). diff --git a/packages/cli/test/serve-config-boot-seed-files.e2e.test.ts b/packages/cli/test/serve-config-boot-seed-files.e2e.test.ts index de04eeaae68..87b5ac858d4 100644 --- a/packages/cli/test/serve-config-boot-seed-files.e2e.test.ts +++ b/packages/cli/test/serve-config-boot-seed-files.e2e.test.ts @@ -31,7 +31,6 @@ import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, - TSX, childEnv, probeThroughChild, readKernelAssignedPort, @@ -101,7 +100,7 @@ afterAll(async () => { /** Boot `os serve objectstack.config.ts --dev`; `--dev` seeds the admin. Answers the port it bound. */ function bootServe(): Promise { return new Promise((resolveBoot, rejectBoot) => { - child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { + child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], env: childEnv({ diff --git a/packages/cli/test/serve-installed-plugins.integration.test.ts b/packages/cli/test/serve-installed-plugins.integration.test.ts index 4b7b79d5c6f..836f57fb4b0 100644 --- a/packages/cli/test/serve-installed-plugins.integration.test.ts +++ b/packages/cli/test/serve-installed-plugins.integration.test.ts @@ -49,7 +49,7 @@ import PluginDisable from '../src/commands/plugin/disable.js'; import PluginEnable from '../src/commands/plugin/enable.js'; import PluginUninstall from '../src/commands/plugin/uninstall.js'; import PluginTrustAdd from '../src/commands/plugin/trust/add.js'; -import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, childEnv } from './helpers/serve-process.js'; const CLI_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const ENV_KEYS = ['OS_HOME', 'OS_DATABASE_URL', 'DATABASE_URL', 'TURSO_DATABASE_URL', 'OS_DATABASE_DRIVER', 'OS_ARTIFACT_PATH', 'OS_ENVIRONMENT_ID'] as const; @@ -185,7 +185,7 @@ interface Boot { /** `os serve --no-server` with `OS_MIGRATE_AND_EXIT=1` from the app directory; waits for its own exit. */ function boot(): Promise { return new Promise((done, fail) => { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '--no-server', '--port', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '--no-server', '--port', KERNEL_ASSIGNED_PORT], { cwd: app, env: childEnv({ NO_COLOR: '1', diff --git a/packages/cli/test/serve-migrate-exit-schema-parity.integration.test.ts b/packages/cli/test/serve-migrate-exit-schema-parity.integration.test.ts index 4063ee846e8..5eda7255b1e 100644 --- a/packages/cli/test/serve-migrate-exit-schema-parity.integration.test.ts +++ b/packages/cli/test/serve-migrate-exit-schema-parity.integration.test.ts @@ -50,7 +50,7 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import Database from 'better-sqlite3'; -import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, childEnv } from './helpers/serve-process.js'; /** The fixture app's own object; its table proves the config was loaded. */ const FIXTURE_OBJECT = 'parity_task'; @@ -93,7 +93,7 @@ function migrateAndExit(label: string, extraArgs: string[]): Promise return new Promise((resolveRun, rejectRun) => { const child = spawn( - TSX, + process.execPath, [CLI, 'serve', 'objectstack.config.ts', '--port', KERNEL_ASSIGNED_PORT, ...extraArgs], { cwd: fixtureDir, diff --git a/packages/cli/test/serve-organization-record-page.e2e.test.ts b/packages/cli/test/serve-organization-record-page.e2e.test.ts index 8b8b56d568b..f840121844f 100644 --- a/packages/cli/test/serve-organization-record-page.e2e.test.ts +++ b/packages/cli/test/serve-organization-record-page.e2e.test.ts @@ -40,7 +40,6 @@ import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, - TSX, childEnv, probeThroughChild, readKernelAssignedPort, @@ -80,7 +79,7 @@ interface LiveServe { function bootServe(dir: string): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). diff --git a/packages/cli/test/serve-package-registry-always-on.e2e.test.ts b/packages/cli/test/serve-package-registry-always-on.e2e.test.ts index 527bbd6a4b2..c75faf09f32 100644 --- a/packages/cli/test/serve-package-registry-always-on.e2e.test.ts +++ b/packages/cli/test/serve-package-registry-always-on.e2e.test.ts @@ -43,7 +43,6 @@ import { join } from 'node:path'; import { CLI, E2E_SECRET_KEY, - TSX, childEnv, KERNEL_ASSIGNED_PORT, probeThroughChild, @@ -126,7 +125,7 @@ const dirs: string[] = []; */ function bootServe(dir: string, db: string): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '-p', KERNEL_ASSIGNED_PORT, '--dev'], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). diff --git a/packages/cli/test/serve-port-drift-notice.e2e.test.ts b/packages/cli/test/serve-port-drift-notice.e2e.test.ts index cda2eb96e0d..3ceb9318c82 100644 --- a/packages/cli/test/serve-port-drift-notice.e2e.test.ts +++ b/packages/cli/test/serve-port-drift-notice.e2e.test.ts @@ -78,7 +78,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, E2E_SECRET_KEY, childEnv, randomPort } from './helpers/serve-process.js'; +import { CLI, E2E_SECRET_KEY, childEnv, randomPort } from './helpers/serve-process.js'; /** * The notice, as ONE regex shared by both cases. @@ -112,13 +112,13 @@ afterAll(async () => { * Stop a spawned child and WAIT for it to be gone — SIGTERM first, SIGKILL only * as a fallback, which is the shape every other spawner in this directory uses. * - * ⚠️ ⛔ Not a bare `child.kill('SIGKILL')`. The child here is the `tsx` shim, - * and the `os serve` process is its own child: SIGKILL cannot be forwarded, so - * killing the shim outright leaves the server running, re-parented to init and - * still holding this process's stdio pipes — measured while writing this file, - * where it kept the runner alive after the assertions had all passed. SIGTERM - * reaches the server through the shim; the 10s SIGKILL is the fallback for a - * child that ignores it. + * ⚠️ ⛔ Not a bare `child.kill('SIGKILL')`. When this file spawned through the + * `tsx` shim, `os serve` was the shim's own child and a SIGKILL could not be + * forwarded: the server kept running, re-parented to init and still holding + * this process's stdio pipes, which kept the runner alive after the assertions + * had all passed (measured while writing this file). The child is `os serve` + * itself now, and SIGTERM first still lets it shut down and release those + * pipes; the 10s SIGKILL is the fallback for a child that ignores it. */ async function stop(child: ChildProcessWithoutNullStreams): Promise { if (child.exitCode !== null || child.signalCode !== null) return; @@ -186,7 +186,7 @@ interface Booted { */ function boot(port: number | string, timeoutMs = 180_000): Promise { return new Promise((resolveBoot) => { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '--port', String(port)], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '--port', String(port)], { cwd: dir, // The shared child environment, never a bare `...process.env` (commit 1ddda1d00). // diff --git a/packages/cli/test/serve-process-child-env.e2e.test.ts b/packages/cli/test/serve-process-child-env.e2e.test.ts index e8a6d7e86b6..997af40db45 100644 --- a/packages/cli/test/serve-process-child-env.e2e.test.ts +++ b/packages/cli/test/serve-process-child-env.e2e.test.ts @@ -115,7 +115,6 @@ import { join } from 'node:path'; import type { Readable } from 'node:stream'; import { CLI, - TSX, E2E_SECRET_KEY, boundPortFromBanner, childEnv, @@ -266,7 +265,7 @@ async function probeOrigin( env: Record, requestedPort: string = KERNEL_ASSIGNED_PORT, ): Promise<{ status: number; code: unknown }> { - const child = spawn(TSX, [CLI, 'serve', 'objectstack.config.ts', '--port', requestedPort], { + const child = spawn(process.execPath, [CLI, 'serve', 'objectstack.config.ts', '--port', requestedPort], { cwd: dir, stdio: ['ignore', 'pipe', 'pipe'], env, diff --git a/packages/cli/test/serve-publishes-bound-port.e2e.test.ts b/packages/cli/test/serve-publishes-bound-port.e2e.test.ts index 3c6dd06135b..d3375bd0281 100644 --- a/packages/cli/test/serve-publishes-bound-port.e2e.test.ts +++ b/packages/cli/test/serve-publishes-bound-port.e2e.test.ts @@ -75,7 +75,7 @@ * * ## Cost, stated rather than hidden * - * THREE real boots, each a `tsx` spawn (this package's measured floor is ~6s) + * THREE real boots, each a source-entry spawn (this package's measured floor is ~6s) * plus a kernel boot. They buy the three arms of the acceptance criterion — * `--port 0`, a free non-zero port, and a port taken out from under the boot — * and none of them substitutes for another. The cheap half of the same @@ -103,7 +103,6 @@ import { join } from 'node:path'; import { runtimeStateFileName } from '../src/commands/serve.js'; import { CLI, - TSX, boundPortFromBanner, childEnv, E2E_SECRET_KEY, @@ -216,13 +215,13 @@ interface Booted { * three channels plus a teardown. * * The child is `detached` so it leads its own process group, and `stop()` kills - * that GROUP: `tsx` runs the CLI in a grandchild, so signalling the direct - * child alone is what leaves orphans behind (see the header). + * that GROUP, so no process the boot started can outlive the teardown (see + * the header). */ function bootServe(cwd: string, args: string[], home: string): Promise { return new Promise((resolveBoot, rejectBoot) => { const child: ChildProcess = spawn( - TSX, + process.execPath, [CLI, 'serve', 'objectstack.config.ts', ...args], { cwd, @@ -266,8 +265,8 @@ function bootServe(cwd: string, args: string[], home: string): Promise { } child.on('exit', () => done()); try { - // NEGATIVE pid = the whole process group. `tsx` runs the CLI in a - // grandchild; killing `child.pid` alone leaves it running. + // NEGATIVE pid = the whole process group, so no process the boot + // started outlives `child.pid`. process.kill(-(child.pid as number), 'SIGTERM'); } catch { try { child.kill('SIGTERM'); } catch { /* already gone */ } @@ -424,9 +423,9 @@ describe('#13062 `os serve --port 0` — the request that can never be the answe } // ⚠️ Teardown really tore down — the same probe, the other way. This is - // the orphan check too: `tsx` runs the CLI in a GRANDCHILD, so a teardown - // that signalled only the direct child would leave a server still - // answering here (13 such orphans took this container to 14.4GB once). + // the orphan check too: a teardown that left any process of the boot + // running would leave a server still answering here (13 such orphans + // took this container to 14.4GB once). expect(await reachable(announced)).toBe(false); }, 240_000, @@ -490,8 +489,7 @@ describe('#13062 the non-zero half — nothing an ordinary boot publishes may mo // the child is gone, so the port THIS server held is gone with it. A boot // that published the port it was ASKED for while binding another would // leave that number still answering here, held by whatever took it; and a - // surviving grandchild (`tsx` runs the CLI one level down) would leave the - // real one answering. + // surviving process of the boot would leave the real one answering. expect(await reachable(published)).toBe(false); }, 240_000, diff --git a/packages/cli/test/serve-runtime-assets-branding-warning.e2e.test.ts b/packages/cli/test/serve-runtime-assets-branding-warning.e2e.test.ts index 5622a183d14..ed8bc7eb68f 100644 --- a/packages/cli/test/serve-runtime-assets-branding-warning.e2e.test.ts +++ b/packages/cli/test/serve-runtime-assets-branding-warning.e2e.test.ts @@ -46,7 +46,6 @@ import type { Readable } from 'node:stream'; import { PROTOCOL_MAJOR } from '@objectstack/spec/kernel'; import { CLI, - TSX, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, childEnv, @@ -148,7 +147,7 @@ async function bootAndFetchLogo(layout: 'no-assets' | 'cwd-assets' | 'env-assets // only for the `assets/` control, that directory — nothing else. expect(readdirSync(cwd).sort()).toEqual(layout === 'cwd-assets' ? ['assets', 'objectstack.json'] : ['objectstack.json']); - const child = spawn(TSX, [CLI, 'serve', '-p', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', '-p', KERNEL_ASSIGNED_PORT], { cwd, stdio: ['ignore', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` (`check:cli-test-child-env`). diff --git a/packages/cli/test/serve-view-container-read.integration.test.ts b/packages/cli/test/serve-view-container-read.integration.test.ts index 280e1b7914a..9204faab47b 100644 --- a/packages/cli/test/serve-view-container-read.integration.test.ts +++ b/packages/cli/test/serve-view-container-read.integration.test.ts @@ -47,7 +47,6 @@ import { CLI, E2E_SECRET_KEY, KERNEL_ASSIGNED_PORT, - TSX, childEnv, probeThroughChild, readKernelAssignedPort, @@ -90,7 +89,7 @@ interface Run { code: number; stdout: string; stderr: string } function build(dir: string): Promise { return new Promise((done) => { execFile( - TSX, + process.execPath, [CLI, 'build'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). { cwd: dir, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, @@ -122,7 +121,7 @@ interface LiveServe { /** Boot `os serve` in `dir` with `args`; the source entry seeds the dev admin either way. */ function bootServe(dir: string, args: string[]): Promise { return new Promise((resolveBoot, rejectBoot) => { - const child = spawn(TSX, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { + const child = spawn(process.execPath, [CLI, 'serve', ...args, '-p', KERNEL_ASSIGNED_PORT], { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'], // `childEnv`, never a bare `...process.env` — see its header (commit 1ddda1d00). diff --git a/packages/cli/test/stack-conversion-record-door.test.ts b/packages/cli/test/stack-conversion-record-door.test.ts index 1df1e5f8886..65e0fb9bbd8 100644 --- a/packages/cli/test/stack-conversion-record-door.test.ts +++ b/packages/cli/test/stack-conversion-record-door.test.ts @@ -87,7 +87,6 @@ import { LIVE_PROBE, liveProbeNodeOptions } from './helpers/live-conversion-prob const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -98,7 +97,7 @@ interface Run { function runCli(args: string[], cwd: string, probe = true): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, diff --git a/packages/cli/test/stack-provenance-door.test.ts b/packages/cli/test/stack-provenance-door.test.ts index 7f19af5b340..c27a15f64e3 100644 --- a/packages/cli/test/stack-provenance-door.test.ts +++ b/packages/cli/test/stack-provenance-door.test.ts @@ -45,7 +45,6 @@ import { defineStackSourceFromLiteral, linkSpec } from './helpers/define-stack-f const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); interface Run { code: number; @@ -56,7 +55,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/start-port-banner-agreement.e2e.test.ts b/packages/cli/test/start-port-banner-agreement.e2e.test.ts index a29d36cbcda..0dff3b50820 100644 --- a/packages/cli/test/start-port-banner-agreement.e2e.test.ts +++ b/packages/cli/test/start-port-banner-agreement.e2e.test.ts @@ -80,7 +80,6 @@ import { requireBuiltCli, holdPort, KERNEL_ASSIGNED_PORT, - TSX, RUN_JS_RESOLVES_FROM_DIST, } from './helpers/serve-process.js'; @@ -299,7 +298,7 @@ describe('`os start` — every address it prints is the port it bound', () => { const output = await bootStart( {}, ['--port', String(held.port)], - { exec: TSX, argv: [RUN_DEV_JS] }, + { exec: process.execPath, argv: [RUN_DEV_JS] }, ); const readback = boundPortFromBanner(output); diff --git a/packages/cli/test/starter-field-consumers.e2e.test.ts b/packages/cli/test/starter-field-consumers.e2e.test.ts index d9485739f3a..10d08ec920b 100644 --- a/packages/cli/test/starter-field-consumers.e2e.test.ts +++ b/packages/cli/test/starter-field-consumers.e2e.test.ts @@ -68,7 +68,6 @@ import { childEnv } from './helpers/serve-process.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); // One `resolve(HERE, …)` call per line: `check:cross-package-test-inputs` // reconstructs these reads by SOURCE SCAN. @@ -129,7 +128,7 @@ function run(file: string, args: string[], cwd: string): Promise { }); } -const os = (args: string[], cwd: string) => run(TSX, [CLI, ...args], cwd); +const os = (args: string[], cwd: string) => run(process.execPath, [CLI, ...args], cwd); const out = (r: Run) => r.stdout + r.stderr; /** The `field-no-consumers` paths a gate's `--json` reports; `null` when it printed no JSON. */ diff --git a/packages/cli/test/validate-json-failure-conversions.e2e.test.ts b/packages/cli/test/validate-json-failure-conversions.e2e.test.ts index c1a6f7e554c..e7ab01e4f5c 100644 --- a/packages/cli/test/validate-json-failure-conversions.e2e.test.ts +++ b/packages/cli/test/validate-json-failure-conversions.e2e.test.ts @@ -115,7 +115,6 @@ import { LIVE_PROBE, liveProbeNodeOptions } from './helpers/live-conversion-prob const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const VALIDATE_TS = resolve(HERE, '../src/commands/validate.ts'); /** @@ -139,7 +138,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1', NODE_OPTIONS: liveProbeNodeOptions() }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/validate-json-failure-warnings.e2e.test.ts b/packages/cli/test/validate-json-failure-warnings.e2e.test.ts index 130379c2391..d3ade599f7f 100644 --- a/packages/cli/test/validate-json-failure-warnings.e2e.test.ts +++ b/packages/cli/test/validate-json-failure-warnings.e2e.test.ts @@ -119,7 +119,6 @@ import { linkSpec } from './helpers/define-stack-fixture.js'; const HERE = resolve(fileURLToPath(import.meta.url), '..'); const CLI = resolve(HERE, '../bin/run-dev.js'); -const TSX = resolve(HERE, '../../../node_modules/.bin/tsx'); const VALIDATE_TS = resolve(HERE, '../src/commands/validate.ts'); /** The planted capability token — classified `unknown`, i.e. an ADVISORY. */ @@ -143,7 +142,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { diff --git a/packages/cli/test/validate-per-package-authoring-parity.test.ts b/packages/cli/test/validate-per-package-authoring-parity.test.ts index e6445116d11..276b5f07645 100644 --- a/packages/cli/test/validate-per-package-authoring-parity.test.ts +++ b/packages/cli/test/validate-per-package-authoring-parity.test.ts @@ -74,7 +74,7 @@ import { execFile } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { linkSpec } from './helpers/define-stack-fixture.js'; interface Run { @@ -86,7 +86,7 @@ interface Run { function runCli(args: string[], cwd: string): Promise { return new Promise((resolvePromise) => { execFile( - TSX, + process.execPath, [CLI, ...args], { cwd, maxBuffer: 16 * 1024 * 1024, env: childEnv({ NO_COLOR: '1' }) }, (err, stdout, stderr) => { @@ -231,7 +231,7 @@ export default defineStack({ const dirs = { multi: '', single: '' }; -/** A cold `tsx` spawn of the CLI source entry, the per-case allowance this file always gave one. */ +/** A cold spawn of the CLI source entry, the per-case allowance this file always gave one. */ const SPAWN_TIMEOUT_MS = 180_000; /** diff --git a/packages/cli/test/verify-author-time-stage.test.ts b/packages/cli/test/verify-author-time-stage.test.ts index 0cf36653bde..1b0efdb987f 100644 --- a/packages/cli/test/verify-author-time-stage.test.ts +++ b/packages/cli/test/verify-author-time-stage.test.ts @@ -41,7 +41,7 @@ import { spawnSync } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, linkSpec } from './helpers/define-stack-fixture.js'; /** The three rules the card's planted mistakes trip, in the order the registry reports them. */ @@ -115,10 +115,10 @@ interface Run { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/` — under plain node - // oclif resolves the command from `dist/`, and the pin would measure - // whatever was last built. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` pins `NODE_ENV=development`, so @oclif/core maps the + // command tree to `src/` and registers tsx in-process: the child runs this + // checkout's `src/`, never whatever was last built into `dist/`. + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', // Every spawned child under this directory declares its environment at the diff --git a/packages/cli/test/verify-dashboard-windows.test.ts b/packages/cli/test/verify-dashboard-windows.test.ts index 774a9b8f8ff..131d8b91e23 100644 --- a/packages/cli/test/verify-dashboard-windows.test.ts +++ b/packages/cli/test/verify-dashboard-windows.test.ts @@ -27,7 +27,7 @@ import { spawnSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, defineStackSourceFromLiteral, linkSpec } from './helpers/define-stack-fixture.js'; const MANIFEST = { @@ -110,8 +110,8 @@ interface Doc { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/`. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` runs this checkout's `src/` (oclif maps its command tree there). + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/verify-delete-behaviors.test.ts b/packages/cli/test/verify-delete-behaviors.test.ts index 951314fac81..18f5ee6d0ae 100644 --- a/packages/cli/test/verify-delete-behaviors.test.ts +++ b/packages/cli/test/verify-delete-behaviors.test.ts @@ -26,7 +26,7 @@ import { spawnSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, defineStackSourceFromLiteral, linkSpec } from './helpers/define-stack-fixture.js'; const MANIFEST = { @@ -112,8 +112,8 @@ interface Doc { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/`. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` runs this checkout's `src/` (oclif maps its command tree there). + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/verify-host-root.test.ts b/packages/cli/test/verify-host-root.test.ts index 4e4fc5df8ad..4c0165dbfa6 100644 --- a/packages/cli/test/verify-host-root.test.ts +++ b/packages/cli/test/verify-host-root.test.ts @@ -39,7 +39,7 @@ import { spawnSync } from 'node:child_process'; import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, linkSpec } from './helpers/define-stack-fixture.js'; /** A package only the app's own directory declares and installs. */ @@ -115,8 +115,8 @@ describe('os verify anchors the app at its own directory, not the process cwd (# linkSpec(appDir); pluginDir = installAppOnlyPlugin(appDir); - // Through tsx, so the child runs this checkout's `src/` (see verify-json-stdout.test.ts). - const r = spawnSync(TSX, [CLI, 'verify', '--app', join(appDir, 'objectstack.config.mjs')], { + // `bin/run-dev.js` runs this checkout's `src/` (see verify-json-stdout.test.ts). + const r = spawnSync(process.execPath, [CLI, 'verify', '--app', join(appDir, 'objectstack.config.mjs')], { cwd: elsewhere, encoding: 'utf8', env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/verify-json-stdout.test.ts b/packages/cli/test/verify-json-stdout.test.ts index cdfe5fef6e1..dd0c75d9e67 100644 --- a/packages/cli/test/verify-json-stdout.test.ts +++ b/packages/cli/test/verify-json-stdout.test.ts @@ -47,7 +47,7 @@ import { spawnSync } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, linkSpec } from './helpers/define-stack-fixture.js'; /** A stack the author-time rules pass, so `os verify` reaches the runtime stage. */ @@ -88,10 +88,10 @@ interface Run { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/` — under plain node - // oclif resolves the command from `dist/`, and the pin would measure - // whatever was last built. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` pins `NODE_ENV=development`, so @oclif/core maps the + // command tree to `src/` and registers tsx in-process: the child runs this + // checkout's `src/`, never whatever was last built into `dist/`. + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', // Every spawned child under this directory declares its environment at the diff --git a/packages/cli/test/verify-parent-write-reach.test.ts b/packages/cli/test/verify-parent-write-reach.test.ts index d8e4e793e9e..b078bd2d8a5 100644 --- a/packages/cli/test/verify-parent-write-reach.test.ts +++ b/packages/cli/test/verify-parent-write-reach.test.ts @@ -29,7 +29,7 @@ import { spawnSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, defineStackSourceFromLiteral, linkSpec } from './helpers/define-stack-fixture.js'; const MANIFEST = { @@ -119,8 +119,8 @@ interface Doc { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/`. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` runs this checkout's `src/` (oclif maps its command tree there). + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', env: childEnv({ NO_COLOR: '1' }), diff --git a/packages/cli/test/verify-reference-shapes.test.ts b/packages/cli/test/verify-reference-shapes.test.ts index 86130cb5612..db0a394b879 100644 --- a/packages/cli/test/verify-reference-shapes.test.ts +++ b/packages/cli/test/verify-reference-shapes.test.ts @@ -26,7 +26,7 @@ import { spawnSync } from 'node:child_process'; import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, linkSpec } from './helpers/define-stack-fixture.js'; const STACK = { @@ -74,8 +74,8 @@ interface Doc { } function runCli(dir: string, args: string[], env: Record = {}): Run { - // Through tsx, so the child runs this checkout's `src/`. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` runs this checkout's `src/` (oclif maps its command tree there). + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', env: childEnv({ NO_COLOR: '1', OS_ALLOW_LAX_VALUE_SHAPES: undefined, ...env }), diff --git a/packages/cli/test/verify-unique-scopes.test.ts b/packages/cli/test/verify-unique-scopes.test.ts index 0a7547aadd2..7d81bbf228b 100644 --- a/packages/cli/test/verify-unique-scopes.test.ts +++ b/packages/cli/test/verify-unique-scopes.test.ts @@ -35,7 +35,7 @@ import { spawnSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { CLI, TSX, childEnv } from './helpers/serve-process.js'; +import { CLI, childEnv } from './helpers/serve-process.js'; import { defineStackSource, defineStackSourceFromLiteral, linkSpec } from './helpers/define-stack-fixture.js'; const MANIFEST = { @@ -96,8 +96,8 @@ interface Doc { } function runCli(dir: string, args: string[]): Run { - // Through tsx, so the child runs this checkout's `src/`. - const r = spawnSync(TSX, [CLI, ...args], { + // `bin/run-dev.js` runs this checkout's `src/` (oclif maps its command tree there). + const r = spawnSync(process.execPath, [CLI, ...args], { cwd: dir, encoding: 'utf8', env: childEnv({ NO_COLOR: '1' }),