mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-14 04:26:04 +00:00
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { isJavaScriptModulePath } from "../../plugins/native-module-require.js";
|
|
import { resolveExistingPluginModulePath } from "./module-loader.js";
|
|
|
|
const tempDirs: string[] = [];
|
|
|
|
afterEach(() => {
|
|
for (const tempDir of tempDirs.splice(0)) {
|
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
}
|
|
vi.resetModules();
|
|
});
|
|
|
|
function createTempDir(): string {
|
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-channel-module-loader-"));
|
|
tempDirs.push(tempDir);
|
|
return tempDir;
|
|
}
|
|
|
|
describe("channel plugin module loader helpers", () => {
|
|
it("resolves extensionless plugin module specifiers to the first existing extension", () => {
|
|
const rootDir = createTempDir();
|
|
const expectedPath = path.join(rootDir, "src", "checker.mts");
|
|
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
|
|
fs.writeFileSync(expectedPath, "export const ok = true;\n", "utf8");
|
|
|
|
expect(resolveExistingPluginModulePath(rootDir, "./src/checker")).toBe(expectedPath);
|
|
});
|
|
|
|
it("detects JavaScript module paths case-insensitively", () => {
|
|
expect(isJavaScriptModulePath("/tmp/entry.js")).toBe(true);
|
|
expect(isJavaScriptModulePath("/tmp/entry.MJS")).toBe(true);
|
|
expect(isJavaScriptModulePath("/tmp/entry.ts")).toBe(false);
|
|
});
|
|
|
|
it("uses native require for eligible JavaScript modules without creating Jiti", async () => {
|
|
const createJiti = vi.fn(() => vi.fn(() => ({ ok: false })));
|
|
vi.resetModules();
|
|
vi.doMock("jiti", () => ({
|
|
createJiti,
|
|
}));
|
|
const loaderModule = await importFreshModule<typeof import("./module-loader.js")>(
|
|
import.meta.url,
|
|
"./module-loader.js?scope=native-require",
|
|
);
|
|
const rootDir = createTempDir();
|
|
const modulePath = path.join(rootDir, "dist", "extensions", "demo", "index.cjs");
|
|
fs.mkdirSync(path.dirname(modulePath), { recursive: true });
|
|
fs.writeFileSync(modulePath, "module.exports = { ok: true };\n", "utf8");
|
|
|
|
expect(
|
|
loaderModule.loadChannelPluginModule({
|
|
modulePath,
|
|
rootDir,
|
|
}),
|
|
).toEqual({ ok: true });
|
|
expect(createJiti).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("rejects TypeScript modules without creating Jiti", async () => {
|
|
const createJiti = vi.fn(() => {
|
|
throw new Error("channel module loader must not create jiti");
|
|
});
|
|
vi.resetModules();
|
|
vi.doMock("jiti", () => ({
|
|
createJiti,
|
|
}));
|
|
const loaderModule = await importFreshModule<typeof import("./module-loader.js")>(
|
|
import.meta.url,
|
|
"./module-loader.js?scope=source-ts-native-hook",
|
|
);
|
|
const rootDir = createTempDir();
|
|
const modulePath = path.join(rootDir, "extensions", "demo", "index.ts");
|
|
fs.mkdirSync(path.dirname(modulePath), { recursive: true });
|
|
fs.writeFileSync(modulePath, "export const ok = true;\n", "utf8");
|
|
|
|
expect(() =>
|
|
loaderModule.loadChannelPluginModule({
|
|
modulePath,
|
|
rootDir,
|
|
}),
|
|
).toThrow(/must be built JavaScript/u);
|
|
expect(createJiti).not.toHaveBeenCalled();
|
|
});
|
|
});
|