Port-back from jspod (lib/start.js), where both behaviours are implemented and proven.
Problem
jss start on a busy port dies with a raw EADDRINUSE — a first-run papercut, especially when a stale instance is still running.
- The startup banner prints the bind host verbatim —
http://0.0.0.0:4443 isn't an openable URL (and bare IPv6 hosts need brackets).
Fix (proven downstream in jspod)
findFreePort — when the requested port is busy, probe upward one port at a time (cap ~10 tries, Vite's behaviour), print what happened, and bind there. Explicitly-passed --port could either still shift with a notice, or fail hard with a clear message (jspod shifts; either is fine if loud).
async function findFreePort(startPort, host, maxTries = 10) {
for (let p = startPort; p < startPort + maxTries; p++) {
const free = await new Promise((resolve) => {
const srv = createServer();
srv.once('error', () => resolve(false));
srv.once('listening', () => srv.close(() => resolve(true)));
srv.listen(p, host);
});
if (free) return p;
}
return null;
}
formatUrl — for the banner only: 0.0.0.0/::/* → localhost, bracket IPv6 literals.
Scope
bin/jss.js start action (+ the banner print). ~30 LoC + tests. No behaviour change when the requested port is free.
Refs
- jspod
lib/start.js — findFreePort + formatUrl, in production downstream
Port-back from jspod (
lib/start.js), where both behaviours are implemented and proven.Problem
jss starton a busy port dies with a rawEADDRINUSE— a first-run papercut, especially when a stale instance is still running.http://0.0.0.0:4443isn't an openable URL (and bare IPv6 hosts need brackets).Fix (proven downstream in jspod)
findFreePort— when the requested port is busy, probe upward one port at a time (cap ~10 tries, Vite's behaviour), print what happened, and bind there. Explicitly-passed--portcould either still shift with a notice, or fail hard with a clear message (jspod shifts; either is fine if loud).formatUrl— for the banner only:0.0.0.0/::/*→localhost, bracket IPv6 literals.Scope
bin/jss.jsstart action (+ the banner print). ~30 LoC + tests. No behaviour change when the requested port is free.Refs
lib/start.js—findFreePort+formatUrl, in production downstream