




















@@ -2,6 +2,7 @@
22 * Cross-platform pnpm command resolver used by Canvas build scripts.
33 */
44import { accessSync, closeSync, constants, openSync, readSync, statSync } from "node:fs";
5+import path from "node:path";
5667const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>%\r\n]/;
78const PNPM_EXECUTABLE_RE = /^pnpm(?:-cli)?(?:\.(?:[cm]?js|cmd|exe))?$/;
@@ -48,6 +49,49 @@ function isExecutableFile(value) {
4849}
4950}
505152+function isFile(value) {
53+try {
54+return statSync(value).isFile();
55+} catch {
56+return false;
57+}
58+}
59+60+function resolvePathEnvKey(env) {
61+return Object.keys(env).find((key) => key.toLowerCase() === "path") ?? "PATH";
62+}
63+64+function findExecutableOnPath(command, envPath, platform, env, cwd) {
65+if (typeof envPath !== "string" || envPath.length === 0) {
66+return undefined;
67+}
68+const extensions =
69+platform === "win32"
70+ ? (env[Object.keys(env).find((key) => key.toLowerCase() === "pathext") ?? "PATHEXT"] ??
71+".COM;.EXE;.BAT;.CMD")
72+.split(";")
73+.filter(Boolean)
74+.map((extension) => extension.toLowerCase())
75+ : [""];
76+const pathImpl = platform === "win32" ? path.win32 : path;
77+const pathDelimiter = platform === "win32" ? ";" : path.delimiter;
78+for (const directory of envPath.split(pathDelimiter)) {
79+if (!directory) {
80+continue;
81+}
82+const resolvedDirectory = pathImpl.isAbsolute(directory)
83+ ? directory
84+ : pathImpl.resolve(cwd, directory);
85+for (const extension of extensions) {
86+const candidate = pathImpl.join(resolvedDirectory, `${command}${extension}`);
87+if ((platform === "win32" ? isFile(candidate) : isExecutableFile(candidate))) {
88+return candidate;
89+}
90+}
91+}
92+return undefined;
93+}
94+5195function isNodeRunnablePnpmExecPath(value) {
5296if (!isPnpmExecPath(value)) {
5397return false;
@@ -129,6 +173,22 @@ export function resolvePnpmRunner(params = {}) {
129173130174const pnpmArgs = params.pnpmArgs ?? [];
131175const platform = params.platform ?? process.platform;
176+const env = params.env ?? process.env;
177+const envPath = env[platform === "win32" ? resolvePathEnvKey(env) : "PATH"];
178+const cwd = params.cwd ?? process.cwd();
179+const pnpmPath = findExecutableOnPath("pnpm", envPath, platform, env, cwd);
180+if (pnpmPath) {
181+return platform === "win32"
182+ ? windowsCmdSpec(pnpmPath, pnpmArgs, params.comSpec ?? process.env.ComSpec ?? "cmd.exe")
183+ : { args: pnpmArgs, command: pnpmPath, shell: false };
184+}
185+const corepackPath = findExecutableOnPath("corepack", envPath, platform, env, cwd);
186+if (corepackPath) {
187+const args = ["pnpm", ...pnpmArgs];
188+return platform === "win32"
189+ ? windowsCmdSpec(corepackPath, args, params.comSpec ?? process.env.ComSpec ?? "cmd.exe")
190+ : { args, command: corepackPath, shell: false };
191+}
132192if (platform === "win32") {
133193return windowsCmdSpec("pnpm.cmd", pnpmArgs, params.comSpec ?? process.env.ComSpec ?? "cmd.exe");
134194}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。