Files
2026-06-05 17:55:51 +07:00

95 lines
2.1 KiB
JavaScript

import { spawn } from 'node:child_process';
export function createDevProcessSpecs({
nodeCommand = process.execPath,
env = process.env,
} = {}) {
return {
roda: {
command: nodeCommand,
args: ['groups/RODA/server.js'],
options: {
env: {
...env,
HOST: env.RODA_HOST || '127.0.0.1',
PORT: env.RODA_PORT || '3000',
},
stdio: ['ignore', 'ignore', 'pipe'],
},
},
vite: {
command: nodeCommand,
args: ['node_modules/vite/bin/vite.js'],
options: {
env: { ...env },
stdio: 'inherit',
},
},
};
}
export function startDevServers({
spawnProcess = spawn,
specs = createDevProcessSpecs(),
} = {}) {
const roda = spawnProcess(specs.roda.command, specs.roda.args, specs.roda.options);
const vite = spawnProcess(specs.vite.command, specs.vite.args, specs.vite.options);
let shuttingDown = false;
let rodaErrorOutput = '';
roda.stderr?.on('data', (chunk) => {
const message = String(chunk);
rodaErrorOutput += message;
if (!message.includes('EADDRINUSE')) {
process.stderr.write(`[roda] ${message}`);
}
});
function stopChildren() {
shuttingDown = true;
if (!roda.killed) {
roda.kill();
}
if (!vite.killed) {
vite.kill();
}
}
vite.on('exit', (code, signal) => {
shuttingDown = true;
if (!roda.killed) {
roda.kill();
}
if (signal) {
process.exitCode = 1;
return;
}
process.exitCode = code ?? 0;
});
roda.on('exit', (code, signal) => {
if (shuttingDown) {
return;
}
if (rodaErrorOutput.includes('EADDRINUSE')) {
process.stderr.write('[roda] Port 3000 is already in use; continuing with the existing RODA server.\n');
return;
}
const reason = signal ? `signal ${signal}` : `exit code ${code}`;
process.stderr.write(`[roda] server stopped unexpectedly (${reason})\n`);
if (!vite.killed) {
vite.kill();
}
process.exitCode = code || 1;
});
process.once('SIGINT', stopChildren);
process.once('SIGTERM', stopChildren);
return { roda, vite };
}