mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(opencode-plugin): drop CJS bundle to fix OpenCode plugin loader (#3883)
Integrated into release/v3.8.26 (scoped to the ESM-only loader fix)
This commit is contained in:
committed by
GitHub
parent
6c1c055a20
commit
a475389b98
@@ -3,19 +3,16 @@
|
||||
"version": "0.1.0",
|
||||
"description": "OpenCode plugin for the OmniRoute AI Gateway. Drives dynamic model discovery, /connect auth flow, and multi-instance OmniRoute providers via the official @opencode-ai/plugin contract.",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/index.d.cts",
|
||||
"default": "./dist/index.cjs"
|
||||
}
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
},
|
||||
"./runtime": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineConfig } from "tsup";
|
||||
|
||||
export default defineConfig({
|
||||
entry: ["src/index.ts"],
|
||||
format: ["esm", "cjs"],
|
||||
format: ["esm"],
|
||||
dts: true,
|
||||
clean: true,
|
||||
sourcemap: false,
|
||||
@@ -11,7 +11,7 @@ export default defineConfig({
|
||||
target: "node22",
|
||||
outDir: "dist",
|
||||
minify: false,
|
||||
cjsInterop: true,
|
||||
cjsInterop: false,
|
||||
// Bundle runtime deps so the .tgz / npm install is self-contained.
|
||||
// `zod` is required at runtime by the options schema and would otherwise
|
||||
// need a peer install when the plugin is loaded directly from a file path
|
||||
|
||||
65
tests/unit/build/opencode-plugin-esm-only.test.ts
Normal file
65
tests/unit/build/opencode-plugin-esm-only.test.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
// Regression guard for #3883: the @omniroute/opencode-plugin must ship an
|
||||
// ESM-only bundle. OpenCode's Bun-based plugin loader resolves the package
|
||||
// `main`/`exports` and applies CJS-to-ESM interop on a dual CJS bundle, which
|
||||
// turns `mod.default` into the whole exports namespace, fails V1 plugin
|
||||
// detection, and makes the loader throw "Plugin export is not a function".
|
||||
// Shipping ESM-only (with a `./runtime` subpath) keeps `mod.default` the V1
|
||||
// plugin object so the loader registers it. Do NOT re-introduce a CJS bundle.
|
||||
|
||||
const PKG_URL = new URL("../../../@omniroute/opencode-plugin/package.json", import.meta.url);
|
||||
const TSUP_URL = new URL("../../../@omniroute/opencode-plugin/tsup.config.ts", import.meta.url);
|
||||
|
||||
function readJson(url: URL): Record<string, unknown> {
|
||||
return JSON.parse(readFileSync(fileURLToPath(url), "utf8"));
|
||||
}
|
||||
|
||||
test("opencode-plugin package.json ships ESM-only (no CJS bundle)", () => {
|
||||
const pkg = readJson(PKG_URL);
|
||||
|
||||
// main must point at the ESM build, never the .cjs bundle.
|
||||
assert.equal(pkg.main, "./dist/index.js", "main must be the ESM build");
|
||||
assert.equal(
|
||||
typeof pkg.main === "string" && pkg.main.endsWith(".cjs"),
|
||||
false,
|
||||
"main must not be a .cjs bundle"
|
||||
);
|
||||
// The legacy dual-bundle `module` field should be gone.
|
||||
assert.equal("module" in pkg, false, "the dual-bundle `module` field must be removed");
|
||||
|
||||
const exports = pkg.exports as Record<string, unknown> | undefined;
|
||||
assert.ok(exports && typeof exports === "object", "exports map must exist");
|
||||
|
||||
const root = exports["."] as Record<string, unknown>;
|
||||
assert.ok(root && typeof root === "object", 'exports["."] must exist');
|
||||
assert.equal(root.import, "./dist/index.js", 'exports["."].import must be the ESM build');
|
||||
// A `require` condition would re-introduce the CJS path the loader chokes on.
|
||||
assert.equal("require" in root, false, 'exports["."] must not declare a `require` condition');
|
||||
|
||||
// The `./runtime` subpath used by the OpenCode loader must resolve to ESM.
|
||||
const runtime = exports["./runtime"] as Record<string, unknown>;
|
||||
assert.ok(runtime && typeof runtime === "object", 'exports["./runtime"] must exist');
|
||||
assert.equal(runtime.import, "./dist/index.js", 'exports["./runtime"].import must be ESM');
|
||||
});
|
||||
|
||||
test("opencode-plugin tsup config builds ESM-only with cjsInterop disabled", () => {
|
||||
const tsup = readFileSync(fileURLToPath(TSUP_URL), "utf8");
|
||||
|
||||
const formatMatch = tsup.match(/format:\s*\[([^\]]*)\]/);
|
||||
assert.ok(formatMatch, "tsup config must declare a format array");
|
||||
const formats = formatMatch[1]
|
||||
.split(",")
|
||||
.map((s) => s.trim().replace(/['"]/g, ""))
|
||||
.filter(Boolean);
|
||||
assert.deepEqual(formats, ["esm"], "tsup must build esm only (no cjs)");
|
||||
|
||||
assert.equal(
|
||||
/cjsInterop:\s*true/.test(tsup),
|
||||
false,
|
||||
"cjsInterop must not be true for an ESM-only build"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user