




















@@ -1,3 +1,4 @@
1+import { spawnSync } from "node:child_process";
12import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
23import { dirname, join } from "node:path";
34import { afterEach, describe, expect, it } from "vitest";
@@ -49,6 +50,28 @@ function writeFileText(filePath: string, text: string): void {
4950writeFileSync(filePath, text, "utf8");
5051}
515253+function listNpmPackDryRunFiles(packageDir: string): string[] {
54+const result = spawnSync("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], {
55+cwd: packageDir,
56+encoding: "utf8",
57+stdio: ["ignore", "pipe", "pipe"],
58+});
59+if (result.error) {
60+throw result.error;
61+}
62+if (result.status !== 0) {
63+throw new Error(result.stderr.trim() || `npm pack failed with exit ${result.status}`);
64+}
65+const [packResult] = JSON.parse(result.stdout) as [
66+{
67+files?: { path?: string }[];
68+},
69+];
70+return (packResult?.files ?? []).flatMap((entry) =>
71+typeof entry.path === "string" ? [entry.path] : [],
72+);
73+}
74+5275function writePublishablePluginPackage(repoDir: string): string {
5376const packageDir = join(repoDir, "extensions", "diffs");
5477mkdirSync(packageDir, { recursive: true });
@@ -194,4 +217,40 @@ describe("plugin npm package manifest staging", () => {
194217"package-local plugin runtime is missing for diffs: ./dist/index.js, ./dist/setup-entry.js",
195218);
196219});
220+221+it("refuses package file rules that omit advertised package-local runtime files", () => {
222+const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-package-runtime-excluded-");
223+const packageDir = writePublishablePluginPackage(repoDir);
224+writeFileText(join(packageDir, "dist", "index.js"), "export {};\n");
225+writeFileText(join(packageDir, "dist", "setup-entry.js"), "export {};\n");
226+writeJsonFile(join(packageDir, "package.json"), {
227+name: "@openclaw/diffs",
228+version: "2026.5.3",
229+type: "module",
230+files: ["dist/**", "!dist/setup-entry.js"],
231+openclaw: {
232+extensions: ["./index.ts"],
233+setupEntry: "./setup-entry.ts",
234+compat: {
235+pluginApi: ">=2026.4.30",
236+},
237+release: {
238+publishToNpm: true,
239+},
240+},
241+});
242+243+const packedFiles = listNpmPackDryRunFiles(packageDir);
244+expect(packedFiles).toContain("dist/index.js");
245+expect(packedFiles).not.toContain("dist/setup-entry.js");
246+247+expect(() =>
248+resolveAugmentedPluginNpmPackageJson({
249+repoRoot: repoDir,
250+ packageDir,
251+}),
252+).toThrow(
253+"package file rule '!dist/setup-entry.js' excludes required package-local runtime file './dist/setup-entry.js' for diffs",
254+);
255+});
197256});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。