Skip to content

Commit 392af2e

Browse files
committed
fix(deps): keep managed overrides in workspace metadata
1 parent b4234d4 commit 392af2e

5 files changed

Lines changed: 50 additions & 60 deletions

File tree

package.json

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,34 +1951,6 @@
19511951
"optionalDependencies": {
19521952
"sqlite-vec": "0.1.9"
19531953
},
1954-
"overrides": {
1955-
"@anthropic-ai/sdk": "0.100.1",
1956-
"@aws-sdk/core": "3.974.13",
1957-
"@aws-sdk/xml-builder": "3.972.25",
1958-
"@hono/node-server": "1.19.14",
1959-
"axios": "1.16.0",
1960-
"basic-ftp": "6.0.1",
1961-
"defu": "6.1.5",
1962-
"fast-uri": "3.1.2",
1963-
"fast-xml-parser": "5.7.0",
1964-
"file-type": "22.0.1",
1965-
"follow-redirects": "1.16.0",
1966-
"form-data": "2.5.4",
1967-
"hono": "4.12.18",
1968-
"ip-address": "10.2.0",
1969-
"minimatch": "10.2.5",
1970-
"node-domexception": "npm:@nolyfill/domexception@1.0.28",
1971-
"path-to-regexp": "8.4.0",
1972-
"protobufjs": "8.4.0",
1973-
"qs": "6.15.2",
1974-
"request": "npm:@cypress/request@3.0.10",
1975-
"request-promise": "npm:@cypress/request-promise@5.0.0",
1976-
"tar": "7.5.15",
1977-
"tough-cookie": "4.1.3",
1978-
"typebox": "1.1.39",
1979-
"uuid": "14.0.0",
1980-
"yauzl": "3.2.1"
1981-
},
19821954
"engines": {
19831955
"node": ">=22.19.0"
19841956
},

src/infra/npm-managed-root.test.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import os from "node:os";
33
import path from "node:path";
44
import { pathToFileURL } from "node:url";
55
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
6+
import YAML from "yaml";
67
import type { CommandOptions } from "../process/exec.js";
78
import { createSuiteTempRootTracker } from "../test-helpers/temp-dir.js";
89
import {
@@ -232,11 +233,11 @@ describe("managed npm root", () => {
232233
});
233234
});
234235

235-
it("reads package-level npm overrides for managed plugin installs", async () => {
236-
const manifest = JSON.parse(
237-
await fs.readFile(path.resolve(process.cwd(), "package.json"), "utf8"),
236+
it("reads workspace pnpm overrides for managed plugin installs", async () => {
237+
const workspace = YAML.parse(
238+
await fs.readFile(path.resolve(process.cwd(), "pnpm-workspace.yaml"), "utf8"),
238239
) as { overrides?: Record<string, unknown> };
239-
const expectedOverrides = manifest.overrides ?? {};
240+
const expectedOverrides = workspace.overrides ?? {};
240241

241242
expect(expectedOverrides).toMatchObject({
242243
axios: "1.16.0",
@@ -245,22 +246,23 @@ describe("managed npm root", () => {
245246
await expect(readOpenClawManagedNpmRootOverrides()).resolves.toEqual(expectedOverrides);
246247
});
247248

248-
it("resolves package-level npm overrides from packaged dist chunks", async () => {
249+
it("resolves workspace pnpm overrides from packaged dist chunks", async () => {
249250
const packageRoot = await makeTempRoot();
250251
await fs.mkdir(path.join(packageRoot, "dist"), { recursive: true });
251252
await fs.writeFile(
252253
path.join(packageRoot, "package.json"),
253254
`${JSON.stringify(
254255
{
255256
name: "openclaw",
256-
overrides: {
257-
axios: "1.16.0",
258-
},
259257
},
260258
null,
261259
2,
262260
)}\n`,
263261
);
262+
await fs.writeFile(
263+
path.join(packageRoot, "pnpm-workspace.yaml"),
264+
"overrides:\n axios: 1.16.0\n",
265+
);
264266

265267
await expect(
266268
readOpenClawManagedNpmRootOverrides({
@@ -286,20 +288,24 @@ describe("managed npm root", () => {
286288
optionalDependencies: {
287289
"optional-runtime": "2.0.0",
288290
},
289-
overrides: {
290-
"managed-runtime": "$managed-runtime",
291-
nested: {
292-
"optional-runtime": "$optional-runtime",
293-
alias: "$node-domexception",
294-
},
295-
axios: "1.16.0",
296-
"node-domexception": "$node-domexception",
297-
},
298291
},
299292
null,
300293
2,
301294
)}\n`,
302295
);
296+
await fs.writeFile(
297+
path.join(packageRoot, "pnpm-workspace.yaml"),
298+
[
299+
"overrides:",
300+
' managed-runtime: "$managed-runtime"',
301+
" nested:",
302+
' optional-runtime: "$optional-runtime"',
303+
' alias: "$node-domexception"',
304+
" axios: 1.16.0",
305+
' node-domexception: "$node-domexception"',
306+
"",
307+
].join("\n"),
308+
);
303309

304310
await expect(readOpenClawManagedNpmRootOverrides({ packageRoot })).resolves.toEqual({
305311
"managed-runtime": "3.1024.0",

src/infra/npm-managed-root.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import os from "node:os";
44
import path from "node:path";
55
import { isRecord } from "@openclaw/normalization-core/record-coerce";
66
import { normalizeOptionalString as readOptionalString } from "@openclaw/normalization-core/string-coerce";
7+
import { parse as parseYaml } from "yaml";
78
import { runCommandWithTimeout } from "../process/exec.js";
89
import { hasErrnoCode } from "./errors.js";
910
import type { NpmSpecResolution } from "./install-source-utils.js";
@@ -145,6 +146,13 @@ async function readManagedNpmRootManifest(filePath: string): Promise<ManagedNpmR
145146
return isRecord(parsed) ? { ...parsed } : {};
146147
}
147148

149+
async function readHostWorkspaceOverrides(packageRoot: string): Promise<Record<string, unknown>> {
150+
const workspace = parseYaml(
151+
await fs.readFile(path.join(packageRoot, "pnpm-workspace.yaml"), "utf8"),
152+
) as unknown;
153+
return isRecord(workspace) ? readOverrideRecord(workspace.overrides) : {};
154+
}
155+
148156
function readHostDependencySpec(
149157
manifest: HostPackageManifest,
150158
packageName: string,
@@ -194,7 +202,7 @@ function filterUnsupportedManagedNpmRootOverrides(value: unknown): Record<string
194202
return filtered;
195203
}
196204

197-
/** Read host OpenClaw package overrides for reuse inside a managed npm root. */
205+
/** Read host OpenClaw pnpm overrides for reuse inside a managed npm root. */
198206
export async function readOpenClawManagedNpmRootOverrides(params?: {
199207
argv1?: string;
200208
cwd?: string;
@@ -219,7 +227,7 @@ export async function readOpenClawManagedNpmRootOverrides(params?: {
219227
return {};
220228
}
221229
const hostManifest = manifest as HostPackageManifest;
222-
const overrides = readOverrideRecord(hostManifest.overrides);
230+
const overrides = await readHostWorkspaceOverrides(packageRoot);
223231
return Object.fromEntries(
224232
Object.entries(overrides).map(([key, value]) => [
225233
key,

src/plugins/install.npm-spec.test.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,20 +2122,25 @@ describe("installPluginFromNpmSpec", () => {
21222122
`${JSON.stringify(
21232123
{
21242124
name: "openclaw",
2125-
overrides: {
2126-
axios: "1.16.0",
2127-
"node-domexception": "npm:@nolyfill/domexception@1.0.28",
2128-
nested: {
2129-
alias: "npm:@scope/alias@1.0.0",
2130-
semver: "1.2.3",
2131-
},
2132-
},
21332125
},
21342126
null,
21352127
2,
21362128
)}\n`,
21372129
"utf8",
21382130
);
2131+
fs.writeFileSync(
2132+
path.join(hostRoot, "pnpm-workspace.yaml"),
2133+
[
2134+
"overrides:",
2135+
" axios: 1.16.0",
2136+
' node-domexception: "npm:@nolyfill/domexception@1.0.28"',
2137+
" nested:",
2138+
' alias: "npm:@scope/alias@1.0.0"',
2139+
" semver: 1.2.3",
2140+
"",
2141+
].join("\n"),
2142+
"utf8",
2143+
);
21392144
resolveOpenClawPackageRootSyncMock.mockReturnValue(hostRoot);
21402145
mockNpmViewAndInstall({
21412146
spec: "@openclaw/voice-call@0.0.1",

test/scripts/root-package-overrides.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,21 @@ describe("root package override guardrails", () => {
5252
expect(pnpmWorkspace.overrides).not.toHaveProperty(packageName);
5353
});
5454

55-
it("pins the node-domexception alias exactly in npm and pnpm overrides", () => {
55+
it("pins the node-domexception alias exactly in pnpm override metadata", () => {
5656
const manifest = readRootManifest();
5757
const pnpmWorkspace = readPnpmWorkspaceConfig();
5858
const pnpmOverride = pnpmWorkspace.overrides?.["node-domexception"];
59-
const npmOverride = manifest.overrides?.["node-domexception"];
6059

6160
expect(pnpmOverride).toBe("npm:@nolyfill/domexception@1.0.28");
62-
expect(npmOverride).toBe(pnpmOverride);
61+
expect(manifest.overrides).toBeUndefined();
6362
});
6463

65-
it("keeps npm, pnpm, and lockfile override metadata aligned", () => {
64+
it("keeps pnpm and lockfile override metadata aligned without duplicating root package policy", () => {
6665
const manifest = readRootManifest();
6766
const pnpmWorkspace = readPnpmWorkspaceConfig();
6867
const pnpmLockfile = readPnpmLockfileConfig();
6968

70-
expect(manifest.overrides).toEqual(pnpmWorkspace.overrides);
69+
expect(manifest.overrides).toBeUndefined();
7170
expect(pnpmLockfile.overrides).toEqual(pnpmWorkspace.overrides);
7271
});
7372
});

0 commit comments

Comments
 (0)