mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-28 18:33:37 +00:00
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
import { buildPluginSdkPackageExports } from "./entrypoints.js";
|
|
|
|
async function collectRuntimeExports(filePath: string, seen = new Set<string>()) {
|
|
const normalizedPath = path.resolve(filePath);
|
|
if (seen.has(normalizedPath)) {
|
|
return new Set<string>();
|
|
}
|
|
seen.add(normalizedPath);
|
|
|
|
const source = await fs.readFile(normalizedPath, "utf8");
|
|
const exportNames = new Set<string>();
|
|
|
|
for (const match of source.matchAll(/export\s+(?!type\b)\{([\s\S]*?)\}\s+from\s+"([^"]+)";/g)) {
|
|
const names = match[1]
|
|
.split(",")
|
|
.map((part) => part.trim())
|
|
.filter(Boolean)
|
|
.map((part) => part.split(/\s+as\s+/).at(-1) ?? part);
|
|
for (const name of names) {
|
|
exportNames.add(name);
|
|
}
|
|
}
|
|
|
|
for (const match of source.matchAll(/export\s+\*\s+from\s+"([^"]+)";/g)) {
|
|
const specifier = match[1];
|
|
if (!specifier.startsWith(".")) {
|
|
continue;
|
|
}
|
|
const nestedPath = path.resolve(
|
|
path.dirname(normalizedPath),
|
|
specifier.replace(/\.js$/, ".ts"),
|
|
);
|
|
const nestedExports = await collectRuntimeExports(nestedPath, seen);
|
|
for (const name of nestedExports) {
|
|
exportNames.add(name);
|
|
}
|
|
}
|
|
|
|
return exportNames;
|
|
}
|
|
|
|
describe("plugin-sdk exports", () => {
|
|
it("does not expose runtime modules", async () => {
|
|
const runtimeExports = await collectRuntimeExports(path.join(import.meta.dirname, "index.ts"));
|
|
const forbidden = [
|
|
"chunkMarkdownText",
|
|
"chunkText",
|
|
"hasControlCommand",
|
|
"isControlCommandMessage",
|
|
"shouldComputeCommandAuthorized",
|
|
"shouldHandleTextCommands",
|
|
"buildMentionRegexes",
|
|
"matchesMentionPatterns",
|
|
"resolveStateDir",
|
|
"writeConfigFile",
|
|
"enqueueSystemEvent",
|
|
"fetchRemoteMedia",
|
|
"saveMediaBuffer",
|
|
"formatAgentEnvelope",
|
|
"buildPairingReply",
|
|
"resolveAgentRoute",
|
|
"dispatchReplyFromConfig",
|
|
"createReplyDispatcherWithTyping",
|
|
"dispatchReplyWithBufferedBlockDispatcher",
|
|
"resolveCommandAuthorizedFromAuthorizers",
|
|
"monitorSlackProvider",
|
|
"monitorTelegramProvider",
|
|
"monitorIMessageProvider",
|
|
"monitorSignalProvider",
|
|
"sendMessageSlack",
|
|
"sendMessageTelegram",
|
|
"sendMessageIMessage",
|
|
"sendMessageSignal",
|
|
"sendMessageWhatsApp",
|
|
"probeSlack",
|
|
"probeTelegram",
|
|
"probeIMessage",
|
|
"probeSignal",
|
|
];
|
|
|
|
for (const key of forbidden) {
|
|
expect(runtimeExports.has(key)).toBe(false);
|
|
}
|
|
});
|
|
|
|
it("keeps the root runtime surface intentionally small", async () => {
|
|
const runtimeExports = await collectRuntimeExports(path.join(import.meta.dirname, "index.ts"));
|
|
expect([...runtimeExports].toSorted()).toEqual([
|
|
"delegateCompactionToRuntime",
|
|
"emptyPluginConfigSchema",
|
|
"onDiagnosticEvent",
|
|
"registerContextEngine",
|
|
]);
|
|
});
|
|
|
|
it("keeps package.json plugin-sdk exports synced with the manifest", async () => {
|
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8")) as {
|
|
exports?: Record<string, unknown>;
|
|
};
|
|
const currentPluginSdkExports = Object.fromEntries(
|
|
Object.entries(packageJson.exports ?? {}).filter(([key]) => key.startsWith("./plugin-sdk")),
|
|
);
|
|
|
|
expect(currentPluginSdkExports).toEqual(buildPluginSdkPackageExports());
|
|
});
|
|
});
|