import * as esbuild from "esbuild"; import { cpSync, mkdirSync, existsSync } from "fs"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const isWatch = process.argv.includes("--watch"); const targetBrowser = process.argv.find((a) => a.startsWith("--browser="))?.split("=")[1] || "all"; const browsers = targetBrowser === "all" ? ["chrome", "firefox", "edge", "safari"] : [targetBrowser]; // Browser-specific esbuild targets const browserTargets = { chrome: "chrome120", edge: "chrome120", // Edge is Chromium-based firefox: "firefox109", safari: "safari16", }; const sharedBuildOptions = { entryPoints: [ "src/background/service-worker.ts", "src/popup/popup.ts", "src/options/options.ts", ], bundle: true, format: "esm", sourcemap: true, minify: !isWatch, // Force CJS resolution for libsodium (ESM entry has broken sibling import) alias: { "libsodium-wrappers-sumo": "./node_modules/libsodium-wrappers-sumo/dist/modules-sumo/libsodium-wrappers.js", }, }; /** * Copy static assets (HTML, icons, manifest) to a browser-specific build directory. */ function copyStaticAssets(browser) { const outDir = join(__dirname, "build", browser); mkdirSync(outDir, { recursive: true }); // Copy manifest const manifestSrc = join(__dirname, "manifests", `${browser}.json`); if (existsSync(manifestSrc)) { cpSync(manifestSrc, join(outDir, "manifest.json")); } // Copy src (HTML, icons) const srcDir = join(__dirname, "src"); cpSync(srcDir, join(outDir, "src"), { recursive: true, filter: (src) => !src.endsWith(".ts") }); } async function buildBrowser(browser) { const outDir = join("build", browser, "dist"); const options = { ...sharedBuildOptions, outdir: outDir, target: browserTargets[browser] || "es2020", }; if (isWatch && browsers.length === 1) { const ctx = await esbuild.context(options); await ctx.watch(); console.log(`Watching for changes (${browser})...`); } else { await esbuild.build(options); } copyStaticAssets(browser); console.log(`Build complete: ${browser} → build/${browser}/`); } // Also build the default dist/ for backwards compatibility (Chrome) async function buildDefault() { const options = { ...sharedBuildOptions, outdir: "dist", target: "chrome120", }; if (isWatch) { const ctx = await esbuild.context(options); await ctx.watch(); console.log("Watching for changes (default)..."); } else { await esbuild.build(options); console.log("Build complete (default dist/)."); } } // Build all targets await buildDefault(); for (const browser of browsers) { await buildBrowser(browser); }