kandown 0.3.3 → 0.3.5

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/bin/kandown.js CHANGED
@@ -57,6 +57,8 @@ const PKG_ROOT = resolve(__dirname, '..');
57
57
  // 📖 Default localhost range for the zero-config `kandown` web UI server.
58
58
  const DEFAULT_SERVE_PORT = 2048;
59
59
  const MAX_SERVE_PORT = 2060;
60
+ const START_PORT_RANGE = 2048;
61
+ const END_PORT_RANGE = 2060;
60
62
 
61
63
  // 📖 Get current CLI version from package.json at PKG_ROOT
62
64
  function getCurrentVersion() {
@@ -626,8 +628,8 @@ function listen(server, port) {
626
628
  }
627
629
 
628
630
  async function listenOnAvailablePort(kandownDir, preferredPort) {
629
- const startPort = preferredPort ?? DEFAULT_SERVE_PORT;
630
- const endPort = preferredPort ?? MAX_SERVE_PORT;
631
+ const startPort = preferredPort ?? START_PORT_RANGE;
632
+ const endPort = preferredPort ?? END_PORT_RANGE;
631
633
 
632
634
  for (let port = startPort; port <= endPort; port++) {
633
635
  const server = createServeServer(kandownDir);
@@ -640,7 +642,7 @@ async function listenOnAvailablePort(kandownDir, preferredPort) {
640
642
  }
641
643
 
642
644
  const range = preferredPort === null
643
- ? `${DEFAULT_SERVE_PORT}-${MAX_SERVE_PORT}`
645
+ ? `${START_PORT_RANGE}-${END_PORT_RANGE}`
644
646
  : String(preferredPort);
645
647
  err(`No free port available in ${c.bold}${range}${c.reset}.`);
646
648
  process.exit(1);
@@ -690,17 +692,27 @@ async function cmdServe(rawArgs) {
690
692
  }
691
693
 
692
694
  /**
693
- * 📖 Opens a file path in the system default browser/app.
695
+ * 📖 Opens a URL in the system default browser after confirming the server is ready.
694
696
  * Non-blocking — spawns the opener and returns immediately.
695
697
  * macOS: open, Linux: xdg-open, Windows: start (via cmd.exe).
696
698
  */
697
- function openInBrowser(filePath) {
699
+ async function openInBrowser(url) {
700
+ // 📖 Wait for server to be truly ready (up to 2s) before opening browser.
701
+ // This prevents ERR_UNSAFE_PORT and similar race conditions.
702
+ for (let i = 0; i < 10; i++) {
703
+ try {
704
+ const res = await fetch(url, { method: 'HEAD', signal: AbortSignal.timeout(500) });
705
+ if (res.ok || res.status === 404) break; // server is up (404 means serving HTML)
706
+ } catch { /* server not ready yet */ }
707
+ await new Promise(r => setTimeout(r, 200));
708
+ }
709
+
698
710
  const opener = process.platform === 'darwin'
699
711
  ? 'open'
700
712
  : process.platform === 'win32'
701
713
  ? 'cmd'
702
714
  : 'xdg-open';
703
- const args = process.platform === 'win32' ? ['/c', 'start', '', filePath] : [filePath];
715
+ const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
704
716
  const child = spawn(opener, args, { detached: true, stdio: 'ignore' });
705
717
  child.on('error', (e) => warn(`Could not open browser automatically: ${e.message}`));
706
718
  child.unref();