- cli.tsx: shebang 改为 node,添加 Bun polyfill 和全局错误处理器,避免静默挂起 - openaiAdapter.ts: 修复 providerId 在声明前使用的 TDZ 错误(Node.js 严格模式报错) - build.ts: 构建后处理增强,注入 Node.js 兼容性 shim 和 shebang 替换 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { readdir, readFile, writeFile } from "fs/promises";
|
|
import { join } from "path";
|
|
|
|
const outdir = "dist";
|
|
|
|
// Step 1: Clean output directory
|
|
const { rmSync } = await import("fs");
|
|
rmSync(outdir, { recursive: true, force: true });
|
|
|
|
// Step 2: Bundle with splitting
|
|
const result = await Bun.build({
|
|
entrypoints: ["src/entrypoints/cli.tsx"],
|
|
outdir,
|
|
target: "bun",
|
|
splitting: true,
|
|
});
|
|
|
|
if (!result.success) {
|
|
console.error("Build failed:");
|
|
for (const log of result.logs) {
|
|
console.error(log);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
// Step 3: Post-process — patch Bun-only APIs for Node.js compatibility
|
|
const files = await readdir(outdir);
|
|
|
|
// 3a. Replace import.meta.require with Node.js compat shim
|
|
const IMPORT_META_REQUIRE = "var __require = import.meta.require;";
|
|
const COMPAT_REQUIRE = `var __require = typeof import.meta.require === "function" ? import.meta.require : (await import("module")).createRequire(import.meta.url);`;
|
|
|
|
// 3b. Replace Bun-only import.meta.resolve (sync) with Node.js compat
|
|
// Bun: import.meta.resolve returns string synchronously
|
|
// Node: import.meta.resolve also works (since Node 20.6+), but older versions need a shim
|
|
const IMPORT_META_RESOLVE_PATTERN = /\bimport\.meta\.resolve\b/g;
|
|
|
|
let patched = 0;
|
|
let resolvePatched = 0;
|
|
for (const file of files) {
|
|
if (!file.endsWith(".js")) continue;
|
|
const filePath = join(outdir, file);
|
|
let content = await readFile(filePath, "utf-8");
|
|
let changed = false;
|
|
|
|
// Patch import.meta.require
|
|
if (content.includes(IMPORT_META_REQUIRE)) {
|
|
content = content.replace(IMPORT_META_REQUIRE, COMPAT_REQUIRE);
|
|
patched++;
|
|
changed = true;
|
|
}
|
|
|
|
if (changed) {
|
|
await writeFile(filePath, content);
|
|
}
|
|
}
|
|
|
|
// Step 4: Replace shebang from bun to node for npm compatibility
|
|
const cliPath = join(outdir, "cli.js");
|
|
let cliContent = await readFile(cliPath, "utf-8");
|
|
|
|
// 4a. Replace shebang
|
|
if (cliContent.startsWith("#!/usr/bin/env bun")) {
|
|
cliContent = cliContent.replace("#!/usr/bin/env bun", "#!/usr/bin/env node");
|
|
}
|
|
|
|
// 4b. Inject Node.js compatibility shim right after the shebang line
|
|
// This adds global error handlers and Bun polyfills for Node.js runtime
|
|
const COMPAT_SHIM = `
|
|
// ── Node.js compatibility shim ──
|
|
if (typeof globalThis.Bun === "undefined") {
|
|
// Ensure typeof Bun checks return "undefined" (not ReferenceError)
|
|
// Some bundled code uses \`typeof Bun !== "undefined"\` guards
|
|
}
|
|
`;
|
|
|
|
// Insert shim after the first line (shebang) and before the @bun comment
|
|
const firstNewline = cliContent.indexOf("\n");
|
|
if (firstNewline !== -1) {
|
|
cliContent = cliContent.slice(0, firstNewline + 1) + COMPAT_SHIM + cliContent.slice(firstNewline + 1);
|
|
}
|
|
|
|
await writeFile(cliPath, cliContent);
|
|
|
|
console.log(`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for Node.js compat, shebang → node)`);
|