mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(deps): keep managed overrides in workspace metadata
This commit is contained in:
28
package.json
28
package.json
@@ -1951,34 +1951,6 @@
|
||||
"optionalDependencies": {
|
||||
"sqlite-vec": "0.1.9"
|
||||
},
|
||||
"overrides": {
|
||||
"@anthropic-ai/sdk": "0.100.1",
|
||||
"@aws-sdk/core": "3.974.13",
|
||||
"@aws-sdk/xml-builder": "3.972.25",
|
||||
"@hono/node-server": "1.19.14",
|
||||
"axios": "1.16.0",
|
||||
"basic-ftp": "6.0.1",
|
||||
"defu": "6.1.5",
|
||||
"fast-uri": "3.1.2",
|
||||
"fast-xml-parser": "5.7.0",
|
||||
"file-type": "22.0.1",
|
||||
"follow-redirects": "1.16.0",
|
||||
"form-data": "2.5.4",
|
||||
"hono": "4.12.18",
|
||||
"ip-address": "10.2.0",
|
||||
"minimatch": "10.2.5",
|
||||
"node-domexception": "npm:@nolyfill/domexception@1.0.28",
|
||||
"path-to-regexp": "8.4.0",
|
||||
"protobufjs": "8.4.0",
|
||||
"qs": "6.15.2",
|
||||
"request": "npm:@cypress/request@3.0.10",
|
||||
"request-promise": "npm:@cypress/request-promise@5.0.0",
|
||||
"tar": "7.5.15",
|
||||
"tough-cookie": "4.1.3",
|
||||
"typebox": "1.1.39",
|
||||
"uuid": "14.0.0",
|
||||
"yauzl": "3.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import YAML from "yaml";
|
||||
import type { CommandOptions } from "../process/exec.js";
|
||||
import { createSuiteTempRootTracker } from "../test-helpers/temp-dir.js";
|
||||
import {
|
||||
@@ -232,11 +233,11 @@ describe("managed npm root", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reads package-level npm overrides for managed plugin installs", async () => {
|
||||
const manifest = JSON.parse(
|
||||
await fs.readFile(path.resolve(process.cwd(), "package.json"), "utf8"),
|
||||
it("reads workspace pnpm overrides for managed plugin installs", async () => {
|
||||
const workspace = YAML.parse(
|
||||
await fs.readFile(path.resolve(process.cwd(), "pnpm-workspace.yaml"), "utf8"),
|
||||
) as { overrides?: Record<string, unknown> };
|
||||
const expectedOverrides = manifest.overrides ?? {};
|
||||
const expectedOverrides = workspace.overrides ?? {};
|
||||
|
||||
expect(expectedOverrides).toMatchObject({
|
||||
axios: "1.16.0",
|
||||
@@ -245,7 +246,7 @@ describe("managed npm root", () => {
|
||||
await expect(readOpenClawManagedNpmRootOverrides()).resolves.toEqual(expectedOverrides);
|
||||
});
|
||||
|
||||
it("resolves package-level npm overrides from packaged dist chunks", async () => {
|
||||
it("resolves workspace pnpm overrides from packaged dist chunks", async () => {
|
||||
const packageRoot = await makeTempRoot();
|
||||
await fs.mkdir(path.join(packageRoot, "dist"), { recursive: true });
|
||||
await fs.writeFile(
|
||||
@@ -253,14 +254,15 @@ describe("managed npm root", () => {
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: "openclaw",
|
||||
overrides: {
|
||||
axios: "1.16.0",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(packageRoot, "pnpm-workspace.yaml"),
|
||||
"overrides:\n axios: 1.16.0\n",
|
||||
);
|
||||
|
||||
await expect(
|
||||
readOpenClawManagedNpmRootOverrides({
|
||||
@@ -286,20 +288,24 @@ describe("managed npm root", () => {
|
||||
optionalDependencies: {
|
||||
"optional-runtime": "2.0.0",
|
||||
},
|
||||
overrides: {
|
||||
"managed-runtime": "$managed-runtime",
|
||||
nested: {
|
||||
"optional-runtime": "$optional-runtime",
|
||||
alias: "$node-domexception",
|
||||
},
|
||||
axios: "1.16.0",
|
||||
"node-domexception": "$node-domexception",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(packageRoot, "pnpm-workspace.yaml"),
|
||||
[
|
||||
"overrides:",
|
||||
' managed-runtime: "$managed-runtime"',
|
||||
" nested:",
|
||||
' optional-runtime: "$optional-runtime"',
|
||||
' alias: "$node-domexception"',
|
||||
" axios: 1.16.0",
|
||||
' node-domexception: "$node-domexception"',
|
||||
"",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
await expect(readOpenClawManagedNpmRootOverrides({ packageRoot })).resolves.toEqual({
|
||||
"managed-runtime": "3.1024.0",
|
||||
|
||||
@@ -4,6 +4,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { isRecord } from "@openclaw/normalization-core/record-coerce";
|
||||
import { normalizeOptionalString as readOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { parse as parseYaml } from "yaml";
|
||||
import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import { hasErrnoCode } from "./errors.js";
|
||||
import type { NpmSpecResolution } from "./install-source-utils.js";
|
||||
@@ -145,6 +146,13 @@ async function readManagedNpmRootManifest(filePath: string): Promise<ManagedNpmR
|
||||
return isRecord(parsed) ? { ...parsed } : {};
|
||||
}
|
||||
|
||||
async function readHostWorkspaceOverrides(packageRoot: string): Promise<Record<string, unknown>> {
|
||||
const workspace = parseYaml(
|
||||
await fs.readFile(path.join(packageRoot, "pnpm-workspace.yaml"), "utf8"),
|
||||
) as unknown;
|
||||
return isRecord(workspace) ? readOverrideRecord(workspace.overrides) : {};
|
||||
}
|
||||
|
||||
function readHostDependencySpec(
|
||||
manifest: HostPackageManifest,
|
||||
packageName: string,
|
||||
@@ -194,7 +202,7 @@ function filterUnsupportedManagedNpmRootOverrides(value: unknown): Record<string
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/** Read host OpenClaw package overrides for reuse inside a managed npm root. */
|
||||
/** Read host OpenClaw pnpm overrides for reuse inside a managed npm root. */
|
||||
export async function readOpenClawManagedNpmRootOverrides(params?: {
|
||||
argv1?: string;
|
||||
cwd?: string;
|
||||
@@ -219,7 +227,7 @@ export async function readOpenClawManagedNpmRootOverrides(params?: {
|
||||
return {};
|
||||
}
|
||||
const hostManifest = manifest as HostPackageManifest;
|
||||
const overrides = readOverrideRecord(hostManifest.overrides);
|
||||
const overrides = await readHostWorkspaceOverrides(packageRoot);
|
||||
return Object.fromEntries(
|
||||
Object.entries(overrides).map(([key, value]) => [
|
||||
key,
|
||||
|
||||
@@ -2122,20 +2122,25 @@ describe("installPluginFromNpmSpec", () => {
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: "openclaw",
|
||||
overrides: {
|
||||
axios: "1.16.0",
|
||||
"node-domexception": "npm:@nolyfill/domexception@1.0.28",
|
||||
nested: {
|
||||
alias: "npm:@scope/alias@1.0.0",
|
||||
semver: "1.2.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(hostRoot, "pnpm-workspace.yaml"),
|
||||
[
|
||||
"overrides:",
|
||||
" axios: 1.16.0",
|
||||
' node-domexception: "npm:@nolyfill/domexception@1.0.28"',
|
||||
" nested:",
|
||||
' alias: "npm:@scope/alias@1.0.0"',
|
||||
" semver: 1.2.3",
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
resolveOpenClawPackageRootSyncMock.mockReturnValue(hostRoot);
|
||||
mockNpmViewAndInstall({
|
||||
spec: "@openclaw/voice-call@0.0.1",
|
||||
|
||||
@@ -52,22 +52,21 @@ describe("root package override guardrails", () => {
|
||||
expect(pnpmWorkspace.overrides).not.toHaveProperty(packageName);
|
||||
});
|
||||
|
||||
it("pins the node-domexception alias exactly in npm and pnpm overrides", () => {
|
||||
it("pins the node-domexception alias exactly in pnpm override metadata", () => {
|
||||
const manifest = readRootManifest();
|
||||
const pnpmWorkspace = readPnpmWorkspaceConfig();
|
||||
const pnpmOverride = pnpmWorkspace.overrides?.["node-domexception"];
|
||||
const npmOverride = manifest.overrides?.["node-domexception"];
|
||||
|
||||
expect(pnpmOverride).toBe("npm:@nolyfill/domexception@1.0.28");
|
||||
expect(npmOverride).toBe(pnpmOverride);
|
||||
expect(manifest.overrides).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps npm, pnpm, and lockfile override metadata aligned", () => {
|
||||
it("keeps pnpm and lockfile override metadata aligned without duplicating root package policy", () => {
|
||||
const manifest = readRootManifest();
|
||||
const pnpmWorkspace = readPnpmWorkspaceConfig();
|
||||
const pnpmLockfile = readPnpmLockfileConfig();
|
||||
|
||||
expect(manifest.overrides).toEqual(pnpmWorkspace.overrides);
|
||||
expect(manifest.overrides).toBeUndefined();
|
||||
expect(pnpmLockfile.overrides).toEqual(pnpmWorkspace.overrides);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user