mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-25 16:42:16 +03:00
Merged via consolidated batch validation. Fixes omniroute update on Windows (npm.cmd cannot be execFile'd without a shell on Node >=24, nodejs/node#52554). Extracts a shared bin/cli/npm-exec.mjs (also handles Bun, windowsHide) mirroring the existing server-side pattern in src/lib/services/installers/utils.ts. Own tests pass. Note: #11336 fixed the same underlying bug (#11335) with a narrower inline change; closed as duplicate crediting this more complete fix.
35 lines
1.6 KiB
JavaScript
35 lines
1.6 KiB
JavaScript
// Spawning npm from the CLI, on every platform.
|
|
//
|
|
// On Windows npm is `npm.cmd`, a batch wrapper. Node ≥ 24 refuses to spawn a
|
|
// `.cmd` without a shell (nodejs/node#52554), and a bare `npm` can additionally
|
|
// resolve to an extensionless shim that `CreateProcess` cannot execute — so the
|
|
// call fails with `EINVAL` or `ENOENT` while npm works fine in the same terminal.
|
|
// `src/lib/services/installers/utils.ts` already solves this for the server; this
|
|
// is the same rule for the `bin/cli` entry points, which cannot import TypeScript.
|
|
//
|
|
// SECURITY (Hard Rule #13): enabling the shell means the SHELL splits the command
|
|
// line, not `execFile`. Every argv element passed alongside these options must be
|
|
// a literal — never a runtime value — or it must be validated first. Callers that
|
|
// need to pass a user-supplied name have to guard it themselves.
|
|
|
|
/** The npm binary to spawn on this platform. */
|
|
export function npmBin(platform = process.platform) {
|
|
const isBun = Boolean(process.versions.bun);
|
|
if (platform === "win32") return isBun ? "bun.exe" : "npm.cmd";
|
|
return isBun ? "bun" : "npm";
|
|
}
|
|
|
|
/**
|
|
* `execFile` / `spawnSync` options for an npm call.
|
|
*
|
|
* @param {NodeJS.Platform} platform
|
|
* @param {{ timeoutMs?: number, stdio?: string }} [options]
|
|
*/
|
|
export function npmExecOptions(platform = process.platform, options = {}) {
|
|
const base = {};
|
|
if (options.timeoutMs !== undefined) base.timeout = options.timeoutMs;
|
|
if (options.stdio !== undefined) base.stdio = options.stdio;
|
|
if (platform !== "win32") return { ...base, shell: false };
|
|
return { ...base, shell: true, windowsHide: true };
|
|
}
|