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)`);