Files
HiveGrid-Wireframes/hivegrid-cloud/scripts/vitest-cli-compat.mjs
T

82 lines
3.6 KiB
JavaScript

// Invoked as `node scripts/vitest-cli-compat.mjs ...` (see package.json `test`); no shebang so the
// module also imports cleanly under Vite/Rollup in vitest-cli-compat.test.mjs. The CLI body below is
// gated behind `isCliEntrypoint`, so importing this file never spawns vitest.
import { spawn } from "node:child_process";
import { chmod, copyFile, mkdtemp, rm } from "node:fs/promises";
import { delimiter, join } from "node:path";
import { tmpdir } from "node:os";
import { fileURLToPath, pathToFileURL } from "node:url";
const defaultAppTestRoot = "apps/web/app/";
const isCliEntrypoint = process.argv[1] ? import.meta.url === pathToFileURL(process.argv[1]).href : false;
export function normalizeVitestArgs(vitestArgs) {
const brokenTenantArg = vitestArgs.find((arg) => arg.includes("app./"));
if (brokenTenantArg) {
throw new Error(`Refusing to repair shell-expanded tenant route path "${brokenTenantArg}". Quote paths containing $tenant or use apps/web/app/... explicitly.`);
}
const repairedArgs = vitestArgs;
const hasDefaultAppTestRoot = repairedArgs.includes(defaultAppTestRoot);
const hasExplicitTestPath = repairedArgs.some((arg, index) => index > 0 && arg !== defaultAppTestRoot && /^(?:app|apps\/web\/app)\/.*\.test\.[cm]?[jt]sx?$/.test(arg));
if (!hasDefaultAppTestRoot || !hasExplicitTestPath) return repairedArgs;
return repairedArgs.filter((arg, index) => {
if (arg === defaultAppTestRoot) return false;
return !(arg === "--" && repairedArgs[index - 1] === defaultAppTestRoot);
});
}
export function appendNodeOption(nodeOptions, option) {
return [nodeOptions, option].filter(Boolean).join(" ");
}
async function createPnpmExecCompatShimDir() {
const shimDir = await mkdtemp(join(tmpdir(), "toolctrl-vitest-compat-"));
await Promise.all(["eslint", "vitest"].map((name) => copyPnpmExecCompatShim(shimDir, name)));
return shimDir;
}
async function copyPnpmExecCompatShim(shimDir, name) {
const shimSource = fileURLToPath(new URL(`./${name}-pnpm-exec-shim.cjs`, import.meta.url));
const shimDestination = join(shimDir, name);
await copyFile(shimSource, shimDestination);
await chmod(shimDestination, 0o755);
}
if (isCliEntrypoint) {
// Computed here (not at module top level) so importing this file for unit tests never touches
// `import.meta.url` under Vite, where it is not a file: URL and `fileURLToPath` would throw.
const vitestEntry = fileURLToPath(new URL("../node_modules/vitest/vitest.mjs", import.meta.url));
const repoRoot = fileURLToPath(new URL("..", import.meta.url));
const rawArgs = process.argv.slice(2);
const args = rawArgs.flatMap((arg) => (arg === "--runInBand" ? ["--single-thread"] : [arg]));
const normalizedArgs = normalizeVitestArgs(args);
let shimDir;
const storageDir = await mkdtemp(join(tmpdir(), "toolctrl-vitest-storage-"));
let childEnv = { ...process.env, VITEST_PNPM_EXEC_COMPAT_READY: "1", TOOLCTRL_REPO_ROOT: repoRoot };
if (!process.env.VITEST_PNPM_EXEC_COMPAT_READY) {
shimDir = await createPnpmExecCompatShimDir();
childEnv = { ...childEnv, PATH: `${shimDir}${delimiter}${process.env.PATH ?? ""}` };
}
childEnv.NODE_OPTIONS = appendNodeOption(childEnv.NODE_OPTIONS, `--localstorage-file=${join(storageDir, "localstorage.json")}`);
const child = spawn(process.execPath, [vitestEntry, ...normalizedArgs], {
cwd: repoRoot,
stdio: "inherit",
env: childEnv,
});
child.on("exit", async (code, signal) => {
await Promise.all([shimDir ? rm(shimDir, { recursive: true, force: true }) : Promise.resolve(), rm(storageDir, { recursive: true, force: true })]);
if (signal) {
process.kill(process.pid, signal);
return;
}
process.exit(code ?? 1);
});
}