mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
test(plugins): lock package boundary bridges
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
95362e415e8400ab74d81938d0c6b57ba82ba1447826fe02bd9a62de932f0b7b plugin-sdk-api-baseline.json
|
||||
fefd2248a26be6f563bb777aeb9cf73ae6a479f1ed16c74be93eef7b9e35356e plugin-sdk-api-baseline.jsonl
|
||||
282897f1e044b79bd444e164646e492602f987fa0fefb20a3336aa0b2445e6b7 plugin-sdk-api-baseline.json
|
||||
49cc5b3330e19a86a4884c71d08070034a39463d7e25ab8eca124f65028f1114 plugin-sdk-api-baseline.jsonl
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import { normalizeOptionalString } from "../../../src/shared/string-coerce.js";
|
||||
import { isRecord } from "../../../src/utils.js";
|
||||
|
||||
export type JsonObject = Record<string, unknown>;
|
||||
|
||||
export type ExternalPluginCompatibility = {
|
||||
@@ -25,6 +22,18 @@ export const EXTERNAL_CODE_PLUGIN_REQUIRED_FIELD_PATHS = [
|
||||
"openclaw.build.openclawVersion",
|
||||
] as const;
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function normalizeOptionalString(value: unknown): string | undefined {
|
||||
if (typeof value !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function readOpenClawBlock(packageJson: unknown) {
|
||||
const root = isRecord(packageJson) ? packageJson : undefined;
|
||||
const openclaw = isRecord(root?.openclaw) ? root.openclaw : undefined;
|
||||
|
||||
@@ -1,13 +1 @@
|
||||
export { collectProviderDangerousNameMatchingScopes } from "../../../src/config/dangerous-name-matching.js";
|
||||
export {
|
||||
asObjectRecord,
|
||||
hasLegacyAccountStreamingAliases,
|
||||
hasLegacyStreamingAliases,
|
||||
normalizeLegacyDmAliases,
|
||||
normalizeLegacyStreamingAliases,
|
||||
} from "../../../src/config/channel-compat-normalization.js";
|
||||
export {
|
||||
detectPluginInstallPathIssue,
|
||||
formatPluginInstallPathIssue,
|
||||
} from "../../../src/infra/plugin-install-path-warnings.js";
|
||||
export { removePluginFromConfig } from "../../../src/plugins/uninstall.js";
|
||||
export * from "../../../src/plugin-sdk/runtime-doctor.js";
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
export {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
readStringValue,
|
||||
} from "../../../src/shared/string-coerce.js";
|
||||
export * from "../../../src/plugin-sdk/text-runtime.js";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { relative, resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
collectExtensionsWithTsconfig,
|
||||
@@ -55,12 +55,38 @@ const MEMORY_HOST_SDK_EXPORTS = [
|
||||
"./secret",
|
||||
"./status",
|
||||
] as const;
|
||||
const MEMORY_HOST_SDK_ALLOWED_CORE_BRIDGE_FILES = [
|
||||
"packages/memory-host-sdk/src/host/openclaw-runtime.ts",
|
||||
] as const;
|
||||
|
||||
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- Test helper lets assertions ascribe JSON file shape.
|
||||
function readJsonFile<T>(relativePath: string): T {
|
||||
return JSON.parse(readFileSync(resolve(REPO_ROOT, relativePath), "utf8")) as T;
|
||||
}
|
||||
|
||||
function collectCodeFiles(relativeDir: string): string[] {
|
||||
const dir = resolve(REPO_ROOT, relativeDir);
|
||||
const files: string[] = [];
|
||||
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
||||
const nextPath = resolve(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
files.push(...collectCodeFiles(relative(REPO_ROOT, nextPath).replaceAll("\\", "/")));
|
||||
continue;
|
||||
}
|
||||
if (entry.isFile() && /\.(?:[cm]?ts|tsx|mts|cts)$/u.test(entry.name)) {
|
||||
files.push(relative(REPO_ROOT, nextPath).replaceAll("\\", "/"));
|
||||
}
|
||||
}
|
||||
return files.toSorted();
|
||||
}
|
||||
|
||||
function collectCoreReferenceFiles(relativeDir: string): string[] {
|
||||
return collectCodeFiles(relativeDir).filter((file) => {
|
||||
const source = readFileSync(resolve(REPO_ROOT, file), "utf8");
|
||||
return source.includes("../../../../src/") || source.includes("../../../src/");
|
||||
});
|
||||
}
|
||||
|
||||
describe("opt-in extension package boundaries", () => {
|
||||
it("keeps path aliases in a dedicated shared config", () => {
|
||||
const pathsConfig = readJsonFile<TsConfigJson>(EXTENSION_PACKAGE_BOUNDARY_PATHS_CONFIG);
|
||||
@@ -209,5 +235,13 @@ describe("opt-in extension package boundaries", () => {
|
||||
const source = readFileSync(resolve(REPO_ROOT, "packages/memory-host-sdk", target), "utf8");
|
||||
expect(source, target).not.toContain("src/memory-host-sdk/");
|
||||
}
|
||||
|
||||
expect(collectCoreReferenceFiles("packages/memory-host-sdk/src")).toEqual([
|
||||
...MEMORY_HOST_SDK_ALLOWED_CORE_BRIDGE_FILES,
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps plugin-package-contract independent from core internals", () => {
|
||||
expect(collectCoreReferenceFiles("packages/plugin-package-contract/src")).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user