diff --git a/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs b/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs index 907098609a4..c4c0cef46a2 100644 --- a/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs +++ b/scripts/lib/bundled-plugin-root-runtime-mirrors.mjs @@ -2,11 +2,6 @@ import fs from "node:fs"; import path from "node:path"; const JS_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]); -const CURATED_ROOT_RUNTIME_MIRRORS = new Set([ - "@matrix-org/matrix-sdk-crypto-nodejs", - "@matrix-org/matrix-sdk-crypto-wasm", -]); - export function collectRuntimeDependencySpecs(packageJson = {}) { return new Map( [ @@ -151,8 +146,12 @@ function extractModuleSpecifiers(source) { return specifiers; } -function isPluginOwnedDistImporter(relativePath, pluginIds) { - return pluginIds.some((pluginId) => relativePath.startsWith(`extensions/${pluginId}/`)); +function isPluginOwnedDistImporter(relativePath, source, pluginIds) { + return pluginIds.some( + (pluginId) => + relativePath.startsWith(`extensions/${pluginId}/`) || + source.includes(`//#region extensions/${pluginId}/`), + ); } export function collectRootDistBundledRuntimeMirrors(params) { @@ -160,18 +159,6 @@ export function collectRootDistBundledRuntimeMirrors(params) { const bundledSpecs = params.bundledRuntimeDependencySpecs; const mirrors = new Map(); - for (const dependencyName of CURATED_ROOT_RUNTIME_MIRRORS) { - const bundledSpec = bundledSpecs.get(dependencyName); - if (!bundledSpec) { - continue; - } - mirrors.set(dependencyName, { - importers: new Set([""]), - pluginIds: bundledSpec.pluginIds, - spec: bundledSpec.spec, - }); - } - for (const filePath of walkJavaScriptFiles(distDir)) { const source = fs.readFileSync(filePath, "utf8"); const relativePath = path.relative(distDir, filePath).replaceAll(path.sep, "/"); @@ -181,7 +168,7 @@ export function collectRootDistBundledRuntimeMirrors(params) { continue; } const bundledSpec = bundledSpecs.get(dependencyName); - if (isPluginOwnedDistImporter(relativePath, bundledSpec.pluginIds)) { + if (isPluginOwnedDistImporter(relativePath, source, bundledSpec.pluginIds)) { continue; } const existing = mirrors.get(dependencyName); diff --git a/test/openclaw-npm-postpublish-verify.test.ts b/test/openclaw-npm-postpublish-verify.test.ts index 75444904187..3844be14e3a 100644 --- a/test/openclaw-npm-postpublish-verify.test.ts +++ b/test/openclaw-npm-postpublish-verify.test.ts @@ -168,6 +168,7 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => { function writeSlackWebApiProbePackage(params: { root: string; + importerSource?: string; importerPath?: string; rootDependencies?: Record; rootOptionalDependencies?: Record; @@ -184,7 +185,11 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => { }); const importerPath = params.importerPath ?? "dist/probe-Cz2PiFtC.js"; mkdirSync(join(params.root, "dist"), { recursive: true }); - writeFileSync(join(params.root, importerPath), 'import("@slack/web-api");\n', "utf8"); + writeFileSync( + join(params.root, importerPath), + params.importerSource ?? 'import("@slack/web-api");\n', + "utf8", + ); } it("flags bundled plugin deps imported by root dist when root mirrors are missing", () => { @@ -216,6 +221,47 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => { } }); + it("allows bundled plugin deps imported from root chunks sourced from their extension", () => { + const packageRoot = makeInstalledPackageRoot(); + + try { + writeSlackWebApiProbePackage({ + root: packageRoot, + importerSource: '//#region extensions/slack/client.ts\nimport("@slack/web-api");\n', + }); + + expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([]); + } finally { + rmSync(packageRoot, { recursive: true, force: true }); + } + }); + + it("does not require root mirrors for extension-only Matrix crypto deps", () => { + const packageRoot = makeInstalledPackageRoot(); + + try { + writePackageFile(packageRoot, "package.json", { + version: "2026.4.10", + dependencies: {}, + }); + writePackageFile(packageRoot, "dist/extensions/matrix/package.json", { + dependencies: { + "@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0", + "@matrix-org/matrix-sdk-crypto-wasm": "18.1.0", + }, + }); + writeFileSync( + join(packageRoot, "dist/extensions/matrix/crypto-node.runtime.js"), + 'require("@matrix-org/matrix-sdk-crypto-nodejs");\n', + "utf8", + ); + + expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([]); + } finally { + rmSync(packageRoot, { recursive: true, force: true }); + } + }); + it("accepts mirrored root dependencies declared in package optionalDependencies", () => { const packageRoot = makeInstalledPackageRoot();