




















@@ -1,4 +1,3 @@
1-import { execFileSync } from "node:child_process";
21import fsSync from "node:fs";
32import os from "node:os";
43import path from "node:path";
@@ -16,31 +15,6 @@ const EXPECTED_FRESHNESS_ENV = {
1615npm_config_min_release_age: "0",
1716};
181719-function readNpmConfigList(env: NodeJS.ProcessEnv): Record<string, unknown> {
20-const raw = execFileSync("npm", ["config", "list", "--json"], {
21-encoding: "utf-8",
22-env: {
23- ...process.env,
24- ...env,
25-},
26-stdio: ["ignore", "pipe", "pipe"],
27-timeout: 5_000,
28-});
29-return JSON.parse(raw) as Record<string, unknown>;
30-}
31-32-function expectUnsetNpmJsonConfig(value: unknown): void {
33-expect(value == null).toBe(true);
34-}
35-36-function expectZeroNpmJsonConfig(value: unknown): void {
37-expect(value === 0 || value === "0").toBe(true);
38-}
39-40-function expectUnsetOrZeroNpmJsonConfig(value: unknown): void {
41-expect(value == null || value === false || value === 0 || value === "0").toBe(true);
42-}
43-4418function createIsolatedNpmConfigEnv(dir: string): NodeJS.ProcessEnv {
4519const home = path.join(dir, "home");
4620const globalconfig = path.join(dir, "global-npmrc");
@@ -344,6 +318,36 @@ describe("npm project install env", () => {
344318}
345319});
346320321+it("prefers scoped npm prefix policy over parent npm prefix policy", () => {
322+const dir = fsSync.mkdtempSync(path.join(os.tmpdir(), "openclaw-prefix-npmrc-"));
323+try {
324+const baseEnv = createIsolatedNpmConfigEnv(dir);
325+const scopedPrefix = path.join(dir, "scoped-prefix");
326+const parentPrefix = path.join(dir, "parent-prefix");
327+fsSync.mkdirSync(path.join(scopedPrefix, "etc"), { recursive: true });
328+fsSync.mkdirSync(path.join(parentPrefix, "etc"), { recursive: true });
329+fsSync.writeFileSync(
330+path.join(scopedPrefix, "etc", "npmrc"),
331+"before=2026-01-01T00:00:00.000Z\n",
332+"utf-8",
333+);
334+fsSync.writeFileSync(path.join(parentPrefix, "etc", "npmrc"), "min-release-age=7\n", "utf-8");
335+336+expect(
337+createNpmFreshnessBypassArgs(
338+{
339+ ...baseEnv,
340+NPM_CONFIG_PREFIX: parentPrefix,
341+},
342+FROZEN_NOW,
343+{ npmConfigPrefix: scopedPrefix },
344+),
345+).toEqual([`--before=${FROZEN_NOW.toISOString()}`]);
346+} finally {
347+fsSync.rmSync(dir, { recursive: true, force: true });
348+}
349+});
350+347351it("overrides stale npmrc before config without emitting release-age config", () => {
348352const dir = fsSync.mkdtempSync(path.join(os.tmpdir(), "openclaw-npmrc-"));
349353try {
@@ -359,9 +363,9 @@ describe("npm project install env", () => {
359363FROZEN_NOW,
360364);
361365362-const npmConfig = readNpmConfigList(env);
363-expect(npmConfig.before).toBe(FROZEN_NOW.toISOString());
364-expectUnsetNpmJsonConfig(npmConfig["min-release-age"]);
366+expect(env.npm_config_before).toBe(FROZEN_NOW.toISOString());
367+expect(env.npm_config_min_release_age).toBe("");
368+expect(env["npm_config_min-release-age"]).toBe("");
365369} finally {
366370fsSync.rmSync(dir, { recursive: true, force: true });
367371}
@@ -370,12 +374,14 @@ describe("npm project install env", () => {
370374it("uses release-age args for npmrc release-age policies", () => {
371375const dir = fsSync.mkdtempSync(path.join(os.tmpdir(), "openclaw-npmrc-"));
372376try {
377+const baseEnv = createIsolatedNpmConfigEnv(dir);
373378const npmrc = path.join(dir, "npmrc");
374379fsSync.writeFileSync(npmrc, "min-release-age=7\n", "utf-8");
375380376381expect(
377382createNpmFreshnessBypassArgs(
378383{
384+ ...baseEnv,
379385NPM_CONFIG_USERCONFIG: npmrc,
380386},
381387FROZEN_NOW,
@@ -389,10 +395,12 @@ describe("npm project install env", () => {
389395it("overrides npmrc release-age config without emitting before config", () => {
390396const dir = fsSync.mkdtempSync(path.join(os.tmpdir(), "openclaw-npmrc-"));
391397try {
398+const baseEnv = createIsolatedNpmConfigEnv(dir);
392399const npmrc = path.join(dir, "npmrc");
393400fsSync.writeFileSync(npmrc, "min-release-age=7\n", "utf-8");
394401const env = createNpmProjectInstallEnv(
395402{
403+ ...baseEnv,
396404NPM_CONFIG_USERCONFIG: npmrc,
397405},
398406{},
@@ -401,13 +409,8 @@ describe("npm project install env", () => {
401409402410expect(env.npm_config_before).toBe("");
403411expect(env.npm_config_min_release_age).toBe("0");
404-const npmConfig = readNpmConfigList(env);
405-expect(
406-npmConfig.before == null ||
407-npmConfig.before === false ||
408-typeof npmConfig.before === "string",
409-).toBe(true);
410-expectUnsetOrZeroNpmJsonConfig(npmConfig["min-release-age"]);
412+expect(env.NPM_CONFIG_BEFORE).toBe("");
413+expect(env["npm_config_min-release-age"]).toBe("");
411414} finally {
412415fsSync.rmSync(dir, { recursive: true, force: true });
413416}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。