mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
88 lines
2.7 KiB
JavaScript
88 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
// Launcher for `pnpm run dev:all`.
|
|
//
|
|
// Probes for free ports for the daemon (OD_PORT, default 7456) and the
|
|
// Next.js dev server (NEXT_PORT, default 3000) before spawning the workspace
|
|
// apps, so a stray process holding either port doesn't kill the
|
|
// whole boot. The resolved ports are exported into the child env, which
|
|
// means:
|
|
// * the daemon's cli.ts sees the new OD_PORT and binds to it
|
|
// * apps/web/next.config.ts reads the same OD_PORT and proxies /api, /artifacts,
|
|
// /frames to the daemon's actual port
|
|
// * Next.js binds to NEXT_PORT (we pass `-p $NEXT_PORT` to the web package
|
|
// dev script so it can stay parameter-free for the common single-process
|
|
// case where the user runs just `pnpm dev`)
|
|
//
|
|
// If a port is busy we walk forward up to PORT_SEARCH_RANGE steps and log
|
|
// the switch so the user notices.
|
|
|
|
import { spawn } from 'node:child_process';
|
|
import { findFreePort } from './resolve-dev-ports.ts';
|
|
|
|
const desiredDaemon = Number(process.env.OD_PORT) || 7456;
|
|
const desiredNext = Number(process.env.NEXT_PORT) || 3000;
|
|
const strictDaemonPort = process.env.OD_PORT_STRICT === '1';
|
|
const strictNextPort = process.env.NEXT_PORT_STRICT === '1';
|
|
|
|
const daemonPort = strictDaemonPort
|
|
? desiredDaemon
|
|
: await findFreePort(desiredDaemon, 'daemon');
|
|
const nextPort = strictNextPort
|
|
? desiredNext
|
|
: await findFreePort(desiredNext, 'next');
|
|
|
|
if (daemonPort !== desiredDaemon) {
|
|
console.log(
|
|
`[dev:all] daemon port ${desiredDaemon} is busy, switching to ${daemonPort}`,
|
|
);
|
|
}
|
|
if (nextPort !== desiredNext) {
|
|
console.log(
|
|
`[dev:all] next port ${desiredNext} is busy, switching to ${nextPort}`,
|
|
);
|
|
}
|
|
|
|
const env = {
|
|
...process.env,
|
|
OD_PORT: String(daemonPort),
|
|
NEXT_PORT: String(nextPort),
|
|
PORT: String(nextPort),
|
|
};
|
|
|
|
const packageManager = process.platform === 'win32' ? 'corepack.cmd' : 'corepack';
|
|
|
|
const children = [
|
|
spawn(packageManager, ['pnpm', '--filter', '@open-design/daemon', 'daemon'], {
|
|
env,
|
|
stdio: 'inherit',
|
|
}),
|
|
spawn(packageManager, ['pnpm', '--filter', '@open-design/web', 'dev', '-p', String(nextPort)], {
|
|
env,
|
|
stdio: 'inherit',
|
|
}),
|
|
];
|
|
|
|
let shuttingDown = false;
|
|
|
|
function stopChildren(signal: NodeJS.Signals = 'SIGTERM'): void {
|
|
for (const child of children) {
|
|
if (!child.killed) child.kill(signal);
|
|
}
|
|
}
|
|
|
|
for (const child of children) {
|
|
child.on('exit', (code, signal) => {
|
|
if (shuttingDown) return;
|
|
shuttingDown = true;
|
|
stopChildren(signal || 'SIGTERM');
|
|
if (signal) process.kill(process.pid, signal);
|
|
else process.exit(code ?? 0);
|
|
});
|
|
}
|
|
|
|
for (const sig of ['SIGINT', 'SIGTERM'] as const) {
|
|
process.on(sig, () => {
|
|
shuttingDown = true;
|
|
stopChildren(sig);
|
|
});
|
|
}
|