fix(runtime): anchor bundled plugin npm staging to active node

This commit is contained in:
Vincent Koc
2026-03-23 20:31:31 -07:00
parent 483dc90f05
commit 6142fc1d94
2 changed files with 77 additions and 2 deletions

View File

@@ -82,11 +82,33 @@ function sanitizeBundledManifestForRuntimeInstall(pluginDir) {
}
}
export function resolveNpmRunner(params = {}) {
const execPath = params.execPath ?? process.execPath;
const existsSync = params.existsSync ?? fs.existsSync;
const platform = params.platform ?? process.platform;
const nodeDir = path.dirname(execPath);
const npmCliPath = path.resolve(nodeDir, "../lib/node_modules/npm/bin/npm-cli.js");
if (existsSync(npmCliPath)) {
return {
command: execPath,
args: [npmCliPath],
shell: false,
};
}
return {
command: "npm",
args: [],
shell: platform === "win32",
};
}
function installPluginRuntimeDeps(pluginDir, pluginId) {
sanitizeBundledManifestForRuntimeInstall(pluginDir);
const npmRunner = resolveNpmRunner();
const result = spawnSync(
"npm",
npmRunner.command,
[
...npmRunner.args,
"install",
"--omit=dev",
"--silent",
@@ -98,7 +120,7 @@ function installPluginRuntimeDeps(pluginDir, pluginId) {
cwd: pluginDir,
encoding: "utf8",
stdio: "pipe",
shell: process.platform === "win32",
shell: npmRunner.shell,
},
);
if (result.status === 0) {

View File

@@ -0,0 +1,53 @@
import path from "node:path";
import { describe, expect, it } from "vitest";
import { resolveNpmRunner } from "../../scripts/stage-bundled-plugin-runtime-deps.mjs";
describe("resolveNpmRunner", () => {
it("anchors npm staging to the active node toolchain when npm-cli.js exists", () => {
const execPath = "/Users/test/.nodenv/versions/24.13.0/bin/node";
const expectedNpmCliPath = path.resolve(
path.dirname(execPath),
"../lib/node_modules/npm/bin/npm-cli.js",
);
const runner = resolveNpmRunner({
execPath,
existsSync: (candidate: string) => candidate === expectedNpmCliPath,
platform: "darwin",
});
expect(runner).toEqual({
command: execPath,
args: [expectedNpmCliPath],
shell: false,
});
});
it("falls back to bare npm when npm-cli.js is unavailable", () => {
expect(
resolveNpmRunner({
execPath: "/tmp/node",
existsSync: () => false,
platform: "linux",
}),
).toEqual({
command: "npm",
args: [],
shell: false,
});
});
it("keeps shell mode for bare npm fallback on Windows", () => {
expect(
resolveNpmRunner({
execPath: "C:\\node\\node.exe",
existsSync: () => false,
platform: "win32",
}),
).toEqual({
command: "npm",
args: [],
shell: true,
});
});
});