





















@@ -1,10 +1,11 @@
11import { spawnSync } from "node:child_process";
22import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3-import { dirname, join } from "node:path";
3+import { dirname, join, win32 } from "node:path";
44import { afterEach, describe, expect, it } from "vitest";
55import {
66resolveAugmentedPluginNpmPackageJson,
77resolveAugmentedPluginNpmManifest,
8+resolvePluginNpmCommand,
89withAugmentedPluginNpmManifestForPackage,
910} from "../scripts/lib/plugin-npm-package-manifest.mjs";
1011import { cleanupTempDirs, makeTempRepoRoot, writeJsonFile } from "./helpers/temp-repo.js";
@@ -51,10 +52,16 @@ function writeFileText(filePath: string, text: string): void {
5152}
52535354function listNpmPackDryRunFiles(packageDir: string): string[] {
54-const result = spawnSync("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], {
55+const invocation = resolvePluginNpmCommand(["pack", "--dry-run", "--json", "--ignore-scripts"]);
56+const result = spawnSync(invocation.command, invocation.args, {
5557cwd: packageDir,
5658encoding: "utf8",
59+ ...(invocation.env ? { env: invocation.env } : {}),
60+ ...(invocation.shell !== undefined ? { shell: invocation.shell } : {}),
5761stdio: ["ignore", "pipe", "pipe"],
62+ ...(invocation.windowsVerbatimArguments !== undefined
63+ ? { windowsVerbatimArguments: invocation.windowsVerbatimArguments }
64+ : {}),
5865});
5966if (result.error) {
6067throw result.error;
@@ -132,6 +139,41 @@ function writeOptionalPlatformDependencyPackage(packageDir: string): string {
132139}
133140134141describe("plugin npm package manifest staging", () => {
142+it("wraps Windows npm.cmd staging through cmd.exe without shell mode", () => {
143+const nodeDir = "C:\\Program Files\\nodejs";
144+const npmCmdPath = win32.resolve(nodeDir, "npm.cmd");
145+146+expect(
147+resolvePluginNpmCommand(["install", "--package-lock-only"], {
148+comSpec: "C:\\Windows\\System32\\cmd.exe",
149+env: { PATH: "C:\\bin" },
150+execPath: win32.join(nodeDir, "node.exe"),
151+existsSync: (candidate: string) => candidate === npmCmdPath,
152+platform: "win32",
153+}),
154+).toEqual({
155+command: "C:\\Windows\\System32\\cmd.exe",
156+args: [
157+"/d",
158+"/s",
159+"/c",
160+'""C:\\Program Files\\nodejs\\npm.cmd" install --package-lock-only"',
161+],
162+shell: false,
163+windowsVerbatimArguments: true,
164+});
165+});
166+167+it("rejects bare npm fallback on Windows plugin package staging", () => {
168+expect(() =>
169+resolvePluginNpmCommand(["install"], {
170+execPath: "C:\\nodejs\\node.exe",
171+existsSync: () => false,
172+platform: "win32",
173+}),
174+).toThrow("OpenClaw refuses to shell out to bare npm on Windows");
175+});
176+135177it("overlays generated channel configs while packing and restores source manifest", () => {
136178const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-package-manifest-");
137179const packageDir = join(repoDir, "extensions", "twitch");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。