Files
openclaw/src/infra/tsdown-config.test.ts
Vincent Koc e174d96cc0 refactor(media): move sharp image ops into media runtime (#71519)
* refactor(media): move sharp image ops into plugin

* fix(media): pass image pixel budget to sharp plugin

* refactor(media): reuse media understanding sharp runtime

* test(build): allow staged runtime core graphs
2026-04-25 04:31:10 -07:00

161 lines
5.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { bundledPluginRoot } from "../../test/helpers/bundled-plugin-paths.js";
import tsdownConfig from "../../tsdown.config.ts";
type TsdownConfigEntry = {
deps?: {
neverBundle?: string[] | ((id: string) => boolean);
};
entry?: Record<string, string> | string[];
inputOptions?: TsdownInputOptions;
outDir?: string;
};
type TsdownLog = {
code?: string;
message?: string;
id?: string;
importer?: string;
};
type TsdownOnLog = (
level: string,
log: TsdownLog,
defaultHandler: (level: string, log: TsdownLog) => void,
) => void;
type TsdownInputOptions = (
options: { onLog?: TsdownOnLog },
format?: unknown,
context?: unknown,
) => { onLog?: TsdownOnLog } | undefined;
function asConfigArray(config: unknown): TsdownConfigEntry[] {
return Array.isArray(config) ? (config as TsdownConfigEntry[]) : [config as TsdownConfigEntry];
}
function entryKeys(config: TsdownConfigEntry): string[] {
if (!config.entry || Array.isArray(config.entry)) {
return [];
}
return Object.keys(config.entry);
}
function hasBundledPluginRuntimeEntry(config: TsdownConfigEntry): boolean {
const keys = entryKeys(config);
return keys.includes("index") || keys.includes("runtime-api");
}
function bundledEntry(pluginId: string): string {
return `${bundledPluginRoot(pluginId)}/index`;
}
function unifiedDistGraph(): TsdownConfigEntry | undefined {
return asConfigArray(tsdownConfig).find((config) =>
entryKeys(config).includes("plugins/runtime/index"),
);
}
describe("tsdown config", () => {
it("keeps core, plugin runtime, plugin-sdk, bundled root plugins, and bundled hooks in one dist graph", () => {
const distGraph = unifiedDistGraph();
expect(distGraph).toBeDefined();
expect(entryKeys(distGraph as TsdownConfigEntry)).toEqual(
expect.arrayContaining([
"agents/auth-profiles.runtime",
"agents/model-catalog.runtime",
"agents/models-config.runtime",
"subagent-registry.runtime",
"agents/pi-model-discovery-runtime",
"index",
"commands/status.summary.runtime",
"plugins/provider-discovery.runtime",
"plugins/provider-runtime.runtime",
"plugins/runtime/index",
"plugin-sdk/compat",
"plugin-sdk/index",
bundledEntry("openai"),
"bundled/boot-md/handler",
]),
);
});
it("emits staged bundled plugins as separate extension graphs", () => {
const stagedGraphs = asConfigArray(tsdownConfig).filter(
(config) => typeof config.outDir === "string" && config.outDir.startsWith("dist/extensions/"),
);
expect(stagedGraphs.length).toBeGreaterThan(0);
expect(stagedGraphs.every(hasBundledPluginRuntimeEntry)).toBe(true);
expect(stagedGraphs.every((config) => !entryKeys(config).includes("plugin-sdk/index"))).toBe(
true,
);
expect(stagedGraphs.some((config) => config.outDir === "dist/extensions/discord")).toBe(true);
expect(stagedGraphs.some((config) => config.outDir === "dist/extensions/msteams")).toBe(true);
expect(
stagedGraphs.some(
(config) =>
config.outDir === "dist/extensions/media-understanding-core" &&
entryKeys(config).includes("image-ops"),
),
).toBe(true);
});
it("does not emit plugin-sdk or hooks from a separate dist graph", () => {
const configs = asConfigArray(tsdownConfig);
expect(configs.some((config) => config.outDir === "dist/plugin-sdk")).toBe(false);
expect(
configs.some((config) =>
Array.isArray(config.entry)
? config.entry.some((entry) => entry.includes("src/hooks/"))
: false,
),
).toBe(false);
});
it("externalizes staged bundled plugin runtime dependencies", () => {
const unifiedGraph = unifiedDistGraph();
const neverBundle = unifiedGraph?.deps?.neverBundle;
if (typeof neverBundle === "function") {
expect(neverBundle("silk-wasm")).toBe(true);
expect(neverBundle("ws")).toBe(true);
expect(neverBundle("ws/lib/websocket.js")).toBe(true);
expect(neverBundle("not-a-runtime-dependency")).toBe(false);
} else {
expect(neverBundle).toEqual(expect.arrayContaining(["silk-wasm", "ws"]));
}
});
it("suppresses unresolved imports from extension source", () => {
const configured = unifiedDistGraph()?.inputOptions?.({})?.onLog;
const handled: TsdownLog[] = [];
configured?.(
"warn",
{
code: "UNRESOLVED_IMPORT",
message: "Could not resolve '@azure/identity' in extensions/msteams/src/sdk.ts",
},
(_level, log) => handled.push(log),
);
expect(handled).toEqual([]);
});
it("keeps unresolved imports outside extension source visible", () => {
const configured = unifiedDistGraph()?.inputOptions?.({})?.onLog;
const handled: TsdownLog[] = [];
const log = {
code: "UNRESOLVED_IMPORT",
message: "Could not resolve 'missing-dependency' in src/index.ts",
};
configured?.("warn", log, (_level, forwardedLog) => handled.push(forwardedLog));
expect(handled).toEqual([log]);
});
});