Files
seedit/scripts/dev-server-utils.mjs
Tommaso Casaburi 6159ee1ede fix(dev server): avoid portless route collisions
Adopt branch-aware Portless app naming with numeric suffixes for repeated worktree runs, add a shared direct-Vite port resolver for PORTLESS=0, and keep the Electron bypass pinned to PORT=3000 so existing localhost-based dev flows still work.
2026-03-31 19:41:27 +07:00

96 lines
2.2 KiB
JavaScript

#!/usr/bin/env node
import { spawn } from 'node:child_process';
import net from 'node:net';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export const repoRoot = path.resolve(__dirname, '..');
export const isWindows = process.platform === 'win32';
function checkPort(host, port) {
return new Promise((resolve) => {
const server = net.createServer();
server.once('error', () => resolve(false));
server.once('listening', () => {
server.close(() => resolve(true));
});
server.listen(port, host);
});
}
export async function resolvePort(requestedPort, host = '127.0.0.1') {
let port = requestedPort;
while (!(await checkPort(host, port))) {
port += 1;
}
return port;
}
export async function waitForPort(host, port, timeoutMs = 30_000) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeoutMs) {
const ready = await new Promise((resolve) => {
const socket = net.connect({ host, port });
socket.once('connect', () => {
socket.destroy();
resolve(true);
});
socket.once('error', () => resolve(false));
});
if (ready) {
return;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
throw new Error(`Timed out waiting for dev server on http://${host}:${port}`);
}
export function startVite(host, port) {
const child = spawn('corepack', ['yarn', 'exec', 'vite', '--host', host, '--port', String(port), '--strictPort'], {
cwd: repoRoot,
env: {
...process.env,
PORTLESS: '0',
},
stdio: 'inherit',
});
const forwardSignal = (signal) => {
if (!child.killed) {
child.kill(signal);
}
};
const onSigint = () => forwardSignal('SIGINT');
const onSigterm = () => forwardSignal('SIGTERM');
process.on('SIGINT', onSigint);
process.on('SIGTERM', onSigterm);
child.on('exit', (code, signal) => {
process.off('SIGINT', onSigint);
process.off('SIGTERM', onSigterm);
if (signal) {
process.kill(process.pid, signal);
return;
}
process.exit(code ?? 0);
});
return child;
}