mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-26 00:21:59 +00:00
fix: use transpiled jiti for source plugin shims
This commit is contained in:
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { createJiti } from "jiti";
|
||||
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { withEnv } from "../test-utils/env.js";
|
||||
async function importFreshPluginTestModules() {
|
||||
@@ -3341,6 +3342,82 @@ module.exports = {
|
||||
expect("alias" in options).toBe(false);
|
||||
});
|
||||
|
||||
it("uses transpiled Jiti loads for source TypeScript plugin entries", () => {
|
||||
expect(__testing.shouldPreferNativeJiti("/repo/dist/plugins/runtime/index.js")).toBe(true);
|
||||
expect(
|
||||
__testing.shouldPreferNativeJiti("/repo/extensions/discord/src/channel.runtime.ts"),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("loads source runtime shims through the non-native Jiti boundary", async () => {
|
||||
const jiti = createJiti(import.meta.url, {
|
||||
...__testing.buildPluginLoaderJitiOptions({}),
|
||||
tryNative: false,
|
||||
});
|
||||
const discordChannelRuntime = path.join(
|
||||
process.cwd(),
|
||||
"extensions",
|
||||
"discord",
|
||||
"src",
|
||||
"channel.runtime.ts",
|
||||
);
|
||||
const discordVoiceRuntime = path.join(
|
||||
process.cwd(),
|
||||
"extensions",
|
||||
"discord",
|
||||
"src",
|
||||
"voice",
|
||||
"manager.runtime.ts",
|
||||
);
|
||||
|
||||
await expect(jiti.import(discordChannelRuntime)).resolves.toMatchObject({
|
||||
discordSetupWizard: expect.any(Object),
|
||||
});
|
||||
await expect(jiti.import(discordVoiceRuntime)).resolves.toMatchObject({
|
||||
DiscordVoiceManager: expect.any(Function),
|
||||
DiscordVoiceReadyListener: expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
it("loads source TypeScript plugins that route through local runtime shims", () => {
|
||||
const plugin = writePlugin({
|
||||
id: "source-runtime-shim",
|
||||
filename: "source-runtime-shim.ts",
|
||||
body: `import "./runtime-shim.ts";
|
||||
|
||||
export default {
|
||||
id: "source-runtime-shim",
|
||||
register() {},
|
||||
};`,
|
||||
});
|
||||
fs.writeFileSync(
|
||||
path.join(plugin.dir, "runtime-shim.ts"),
|
||||
`import { helperValue } from "./helper.js";
|
||||
|
||||
export const runtimeValue = helperValue;`,
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(plugin.dir, "helper.ts"),
|
||||
`export const helperValue = "ok";`,
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
plugins: {
|
||||
load: { paths: [plugin.file] },
|
||||
allow: ["source-runtime-shim"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const record = registry.plugins.find((entry) => entry.id === "source-runtime-shim");
|
||||
expect(record?.status).toBe("loaded");
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "prefers dist plugin runtime module when loader runs from dist",
|
||||
|
||||
@@ -288,6 +288,18 @@ const resolvePluginSdkScopedAliasMap = (): Record<string, string> => {
|
||||
return aliasMap;
|
||||
};
|
||||
|
||||
function shouldPreferNativeJiti(modulePath: string): boolean {
|
||||
switch (path.extname(modulePath).toLowerCase()) {
|
||||
case ".js":
|
||||
case ".mjs":
|
||||
case ".cjs":
|
||||
case ".json":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const __testing = {
|
||||
buildPluginLoaderJitiOptions,
|
||||
listPluginSdkAliasCandidates,
|
||||
@@ -295,6 +307,7 @@ export const __testing = {
|
||||
resolvePluginSdkAliasCandidateOrder,
|
||||
resolvePluginSdkAliasFile,
|
||||
resolvePluginRuntimeModulePath,
|
||||
shouldPreferNativeJiti,
|
||||
maxPluginRegistryCacheEntries: MAX_PLUGIN_REGISTRY_CACHE_ENTRIES,
|
||||
};
|
||||
|
||||
@@ -849,18 +862,28 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
}
|
||||
|
||||
// Lazy: avoid creating the Jiti loader when all plugins are disabled (common in unit tests).
|
||||
let jitiLoader: ReturnType<typeof createJiti> | null = null;
|
||||
const getJiti = () => {
|
||||
if (jitiLoader) {
|
||||
return jitiLoader;
|
||||
const jitiLoaders = new Map<boolean, ReturnType<typeof createJiti>>();
|
||||
const getJiti = (modulePath: string) => {
|
||||
const tryNative = shouldPreferNativeJiti(modulePath);
|
||||
const cached = jitiLoaders.get(tryNative);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const pluginSdkAlias = resolvePluginSdkAlias();
|
||||
const aliasMap = {
|
||||
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
|
||||
...resolvePluginSdkScopedAliasMap(),
|
||||
};
|
||||
jitiLoader = createJiti(import.meta.url, buildPluginLoaderJitiOptions(aliasMap));
|
||||
return jitiLoader;
|
||||
const loader = createJiti(import.meta.url, {
|
||||
...buildPluginLoaderJitiOptions(aliasMap),
|
||||
// Source .ts runtime shims import sibling ".js" specifiers that only exist
|
||||
// after build. Disable native loading for source entries so Jiti rewrites
|
||||
// those imports against the source graph, while keeping native dist/*.js
|
||||
// loading for the canonical built module graph.
|
||||
tryNative,
|
||||
});
|
||||
jitiLoaders.set(tryNative, loader);
|
||||
return loader;
|
||||
};
|
||||
|
||||
let createPluginRuntimeFactory: ((options?: CreatePluginRuntimeOptions) => PluginRuntime) | null =
|
||||
@@ -875,7 +898,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
if (!runtimeModulePath) {
|
||||
throw new Error("Unable to resolve plugin runtime module");
|
||||
}
|
||||
const runtimeModule = getJiti()(runtimeModulePath) as {
|
||||
const runtimeModule = getJiti(runtimeModulePath)(runtimeModulePath) as {
|
||||
createPluginRuntime?: (options?: CreatePluginRuntimeOptions) => PluginRuntime;
|
||||
};
|
||||
if (typeof runtimeModule.createPluginRuntime !== "function") {
|
||||
@@ -1208,7 +1231,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
|
||||
let mod: OpenClawPluginModule | null = null;
|
||||
try {
|
||||
mod = getJiti()(safeSource) as OpenClawPluginModule;
|
||||
mod = getJiti(safeSource)(safeSource) as OpenClawPluginModule;
|
||||
} catch (err) {
|
||||
recordPluginError({
|
||||
logger,
|
||||
|
||||
Reference in New Issue
Block a user