import { spawn } from "node:child_process";
import { createRequire } from "node:module";
import { dirname } from "node:path";
import { writeManifest } from "./build-manifest.mjs";
const require = createRequire(import.meta.url);
// vite's ./bin subpath isn't exported; resolve via the package directory
const viteBin = new URL("file://" + dirname(require.resolve("vite/package.json")) + "/bin/vite.js").pathname;
/**
* Vite can't emit IIFE for a multi-entry (code-splitting) build, so each
* extension entry (background, content, options) is built as its own
* single-chunk bundle into the same dist/<target> directory.
* Usage: node scripts/build.mjs <chrome|firefox> [--watch]
*/
const target = process.argv[2];
const watch = process.argv.includes("--watch");
if (target !== "chrome" && target !== "firefox") {
console.error("Usage: node scripts/build.mjs <chrome|firefox> [--watch]");
process.exit(1);
}
// order matters: every pass writes assets/style.css (cssCodeSplit:false), so
// the content pass — whose stylesheet is the union of all styles — runs last
const entries = ["background", "options", "popup", "relay", "content"];
function run(entry) {
return new Promise((resolve, reject) => {
const child = spawn(
process.execPath,
[viteBin, "build", "--mode", target, ...(watch ? ["--watch"] : [])],
{
cwd: new URL("..", import.meta.url).pathname,
env: { ...process.env, LTT_ENTRY: entry },
stdio: "inherit",
}
);
child.on("exit", (code) => (code === 0 ? resolve() : reject(new Error(`${target}/${entry} exited with ${code}`))));
});
}
try {
for (const entry of entries) {
if (watch) {
// keep all three watchers alive
run(entry).catch((error) => {
console.error(error.message);
process.exit(1);
});
} else {
await run(entry);
}
}
if (!watch) writeManifest(target);
} catch (error) {
console.error(error.message);
process.exit(1);
}