@inditextech/docouture-cli 0.1.0-SNAPSHOT.85.1 → 0.1.0-SNAPSHOT.90.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/bin.js CHANGED
@@ -89,7 +89,9 @@ change to docs/ or antora-playbook.yml. --dir is the repository root
89
89
  (the parent of docs/), same as new/version — not the site directory.
90
90
 
91
91
  Options:
92
- --port <port> Port to listen on (default: 5000)
92
+ --port <port> Port to listen on (default: 5000, falls back to a random
93
+ free port if 5000 is busy — an explicit --port that's busy
94
+ is still a hard error)
93
95
  --dir <path> Repository root (default: cwd, or its enclosing repo)
94
96
  `,
95
97
  },
@@ -26,6 +26,7 @@ const RELOAD_PATH = '/__dev/reload';
26
26
  const CLIENT_PATH = '/__dev/client.js';
27
27
  const DEBOUNCE_MS = 150;
28
28
  const BUILD_TIMEOUT_MS = 120_000;
29
+ const DEFAULT_PORT = 5000;
29
30
  const CLIENT_SCRIPT = `// Injected by docouture dev. Not part of the built site.
30
31
  const es = new EventSource(${JSON.stringify(RELOAD_PATH)})
31
32
  es.addEventListener('message', () => location.reload())
@@ -315,14 +316,36 @@ export async function startDevServer(options) {
315
316
  logError('initial rebuild failed, serving the previous build');
316
317
  }
317
318
  await new Promise((resolvePromise, reject) => {
318
- server.once('error', reject);
319
- server.listen(options.port ?? 5000, () => {
320
- server.off('error', reject);
319
+ // `options.port` set (including 0, which a test uses to pick any free
320
+ // port) means the caller chose this port deliberately — a busy port
321
+ // there is a hard failure, same as always. Nothing set means the
322
+ // *default* port, which is routinely squatted by something the user
323
+ // never asked to avoid (macOS AirPlay Receiver on 5000, most commonly):
324
+ // that case retries with `listen(0)`, an OS-assigned free port, instead
325
+ // of failing the whole dev server over a port nobody actually chose.
326
+ const explicitPort = options.port !== undefined;
327
+ const requestedPort = options.port ?? options.defaultPort ?? DEFAULT_PORT;
328
+ const onListenError = (err) => {
329
+ if (!explicitPort && err.code === 'EADDRINUSE') {
330
+ server.off('error', onListenError);
331
+ logError(`port ${requestedPort} is already in use, falling back to a random free port`);
332
+ server.once('error', reject);
333
+ server.listen(0, () => {
334
+ server.off('error', reject);
335
+ resolvePromise();
336
+ });
337
+ return;
338
+ }
339
+ reject(err);
340
+ };
341
+ server.once('error', onListenError);
342
+ server.listen(requestedPort, () => {
343
+ server.off('error', onListenError);
321
344
  resolvePromise();
322
345
  });
323
346
  });
324
347
  const address = server.address();
325
- const port = typeof address === 'object' && address ? address.port : (options.port ?? 5000);
348
+ const port = typeof address === 'object' && address ? address.port : (options.port ?? DEFAULT_PORT);
326
349
  log(`serving ${root}`);
327
350
  log(` http://localhost:${port}${basePath}/`);
328
351
  const watchers = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inditextech/docouture-cli",
3
- "version": "0.1.0-SNAPSHOT.85.1",
3
+ "version": "0.1.0-SNAPSHOT.90.1",
4
4
  "description": "Command-line tool for docouture documentation sites: scaffold a new site and set its Antora version outside the monorepo",
5
5
  "repository": {
6
6
  "type": "git",