

























@@ -0,0 +1,115 @@
1+import { closeSync, openSync, readSync } from "node:fs";
2+import path from "node:path";
3+4+const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>%\r\n]/;
5+6+function getPortableBasename(value) {
7+return value.split(/[/\\]/).at(-1) ?? value;
8+}
9+10+function getPortableExtension(value) {
11+return path.posix.extname(getPortableBasename(value)).toLowerCase();
12+}
13+14+function isPnpmExecPath(value) {
15+return /^pnpm(?:-cli)?(?:\.(?:[cm]?js|cmd|exe))?$/.test(getPortableBasename(value).toLowerCase());
16+}
17+18+function hasScriptShebang(value) {
19+let fd;
20+try {
21+fd = openSync(value, "r");
22+const header = Buffer.alloc(2);
23+return (
24+readSync(fd, header, 0, header.length, 0) === header.length &&
25+header[0] === 0x23 &&
26+header[1] === 0x21
27+);
28+} catch {
29+return false;
30+} finally {
31+if (fd !== undefined) {
32+closeSync(fd);
33+}
34+}
35+}
36+37+function isNodeRunnablePnpmExecPath(value) {
38+if (!isPnpmExecPath(value)) {
39+return false;
40+}
41+const extension = getPortableExtension(value);
42+if (extension === ".js" || extension === ".cjs" || extension === ".mjs") {
43+return true;
44+}
45+if (extension.length > 0) {
46+return false;
47+}
48+return hasScriptShebang(value);
49+}
50+51+function escapeForCmdExe(arg) {
52+if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(arg)) {
53+throw new Error(`unsafe Windows cmd.exe argument detected: ${JSON.stringify(arg)}`);
54+}
55+const escaped = arg.replace(/\^/g, "^^");
56+if (!escaped.includes(" ") && !escaped.includes('"')) {
57+return escaped;
58+}
59+return `"${escaped.replace(/"/g, '""')}"`;
60+}
61+62+function buildCmdExeCommandLine(command, args) {
63+return [escapeForCmdExe(command), ...args.map(escapeForCmdExe)].join(" ");
64+}
65+66+export function resolvePnpmRunner(params = {}) {
67+const pnpmArgs = params.pnpmArgs ?? [];
68+const nodeArgs = params.nodeArgs ?? [];
69+const npmExecPath = params.npmExecPath ?? process.env.npm_execpath;
70+const nodeExecPath = params.nodeExecPath ?? process.execPath;
71+const platform = params.platform ?? process.platform;
72+const comSpec = params.comSpec ?? process.env.ComSpec ?? "cmd.exe";
73+74+if (typeof npmExecPath === "string" && npmExecPath.length > 0 && isPnpmExecPath(npmExecPath)) {
75+if (isNodeRunnablePnpmExecPath(npmExecPath)) {
76+return {
77+command: nodeExecPath,
78+args: [...nodeArgs, npmExecPath, ...pnpmArgs],
79+shell: false,
80+};
81+}
82+83+const npmExecExtension = getPortableExtension(npmExecPath);
84+if (platform === "win32" && npmExecExtension === ".exe") {
85+return {
86+command: npmExecPath,
87+args: pnpmArgs,
88+shell: false,
89+};
90+}
91+if (platform === "win32" && npmExecExtension === ".cmd") {
92+return {
93+command: comSpec,
94+args: ["/d", "/s", "/c", buildCmdExeCommandLine(npmExecPath, pnpmArgs)],
95+shell: false,
96+windowsVerbatimArguments: true,
97+};
98+}
99+}
100+101+if (platform === "win32") {
102+return {
103+command: comSpec,
104+args: ["/d", "/s", "/c", buildCmdExeCommandLine("pnpm.cmd", pnpmArgs)],
105+shell: false,
106+windowsVerbatimArguments: true,
107+};
108+}
109+110+return {
111+command: "pnpm",
112+args: pnpmArgs,
113+shell: false,
114+};
115+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。