@helping-ai-workflow/md2doc 3.2.1 → 3.4.0

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/lib/editor/cli.js CHANGED
@@ -5,11 +5,28 @@ const { createEditorServer } = require('./server.js');
5
5
 
6
6
  const CLIENT_SRC = fs.readFileSync(path.join(__dirname, 'client.js'), 'utf8');
7
7
 
8
- async function startEditSession({ files, port = null, open = true, quiet = false }) {
8
+ // F13: each exit path prints its own line. The tab-closed (idle) and
9
+ // never-opened lines come from a listener on server.js's
10
+ // 'md2doc-auto-close' event, since that side is what decides why the
11
+ // server is closing. The SIGINT line is printed here instead, because the
12
+ // signal lands on the process itself — server.js has no way to observe it.
13
+ const AUTO_CLOSE_MESSAGES = {
14
+ idle: 'md2doc: no browser activity for a while — closing this editor session.\n',
15
+ 'never-opened': 'md2doc: the editor link was never opened — closing this editor session.\n',
16
+ };
17
+
18
+ async function startEditSession({
19
+ files, port = null, open = true, quiet = false, idleTimeoutMs, neverOpenedGraceMs,
20
+ }) {
9
21
  const srv = await createEditorServer({
10
22
  files,
11
23
  clientJs: CLIENT_SRC,
12
24
  listenPort: port === null ? 0 : port,
25
+ // Included when the caller supplies a value; otherwise omitted so
26
+ // createEditorServer's own default applies, rather than a duplicated
27
+ // default here that could drift out of sync with it.
28
+ ...(idleTimeoutMs === undefined ? {} : { idleTimeoutMs }),
29
+ ...(neverOpenedGraceMs === undefined ? {} : { neverOpenedGraceMs }),
13
30
  });
14
31
  const urls = files.map((f) => srv.urlFor(f));
15
32
  for (const u of urls) process.stdout.write(u + '\n');
@@ -17,6 +34,38 @@ async function startEditSession({ files, port = null, open = true, quiet = false
17
34
  const { openViewer } = require('./open.js');
18
35
  for (const u of urls) openViewer(u);
19
36
  }
37
+ srv.server.on('md2doc-auto-close', (reason) => {
38
+ const msg = AUTO_CLOSE_MESSAGES[reason];
39
+ if (msg) process.stdout.write(msg);
40
+ });
41
+ // SIGINT previously had no handler: Node's default action kills the
42
+ // process before srv.server's 'close' listener below ever runs. Driven
43
+ // directly by spawning a child and sending it SIGINT before this fix:
44
+ // it exited with signal=SIGINT, code=null, and stdout held only the
45
+ // earlier URL line — no closing message. Printing here and driving the
46
+ // close through srv.close() (rather than letting the signal's default
47
+ // action finish the job) routes this exit through the same 'close'
48
+ // listener that already handles the idle and never-opened exits.
49
+ //
50
+ // T21 item 3: this handler REPLACES Node's default action, and the default
51
+ // action was the escape route — with a handler installed, a Ctrl+C that
52
+ // does not lead to an exit leaves the user with no way out but another
53
+ // terminal. Two things answer that here. srv.close() now lands the open
54
+ // sockets rather than waiting on them (see shutdownServer() in server.js
55
+ // for the preconnect measurement that made the default invocation hang
56
+ // where --no-open did not), and a SECOND SIGINT exits on the spot. The
57
+ // second one does not reprint the line: driven before this guard existed,
58
+ // two Ctrl+C's printed 'interrupted' twice and the process was still alive
59
+ // 12 s after the first. 130 is the conventional code for a process ending
60
+ // on SIGINT; the ordinary path still exits 0 through the 'close' listener
61
+ // below.
62
+ let interrupted = false;
63
+ process.on('SIGINT', () => {
64
+ if (interrupted) process.exit(130);
65
+ interrupted = true;
66
+ process.stdout.write('md2doc: interrupted — closing this editor session.\n');
67
+ srv.close();
68
+ });
20
69
  srv.server.on('close', () => process.exit(0));
21
70
  return srv;
22
71
  }