You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
51 lines
1.4 KiB
51 lines
1.4 KiB
/**
|
|
* Local stack: Next.js web + IMAP worker in one process group.
|
|
* Usage: pnpm dev / pnpm dev:stack
|
|
*/
|
|
import { spawn } from "node:child_process";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
const children = [];
|
|
|
|
function start(label, args) {
|
|
const child = spawn("pnpm", args, {
|
|
cwd: root,
|
|
stdio: "inherit",
|
|
shell: true,
|
|
env: process.env,
|
|
});
|
|
child.on("exit", (code, signal) => {
|
|
console.error(`[dev-stack] ${label} exited code=${code} signal=${signal}`);
|
|
shutdown(code ?? 1);
|
|
});
|
|
children.push(child);
|
|
return child;
|
|
}
|
|
|
|
let shuttingDown = false;
|
|
function shutdown(code = 0) {
|
|
if (shuttingDown) return;
|
|
shuttingDown = true;
|
|
for (const child of children) {
|
|
if (!child.killed) {
|
|
try {
|
|
child.kill("SIGTERM");
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
}
|
|
// Give children a moment, then force-exit so orphaned cmd.exe on Windows dies with parent intent
|
|
setTimeout(() => process.exit(code), 500).unref();
|
|
}
|
|
|
|
process.on("SIGINT", () => shutdown(0));
|
|
process.on("SIGTERM", () => shutdown(0));
|
|
|
|
console.log("[dev-stack] starting web (next) + worker …");
|
|
// Use dev:web so this is never recursive with package.json "dev" = this script
|
|
start("web", ["run", "dev:web"]);
|
|
start("worker", ["run", "worker"]);
|