noninteractive 0.3.21 → 0.3.24

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.
Files changed (2) hide show
  1. package/bin/noninteractive.js +141 -24
  2. package/package.json +1 -1
@@ -35,6 +35,7 @@ var exports_paths = {};
35
35
  __export(exports_paths, {
36
36
  socketPath: () => socketPath,
37
37
  sessionUrlsFile: () => sessionUrlsFile,
38
+ sessionOutputFile: () => sessionOutputFile,
38
39
  sessionDir: () => sessionDir,
39
40
  sessionBinDir: () => sessionBinDir,
40
41
  ensureSessionsDir: () => ensureSessionsDir,
@@ -58,6 +59,9 @@ function sessionBinDir(name) {
58
59
  function sessionUrlsFile(name) {
59
60
  return resolve(SESSIONS_DIR, name, "urls");
60
61
  }
62
+ function sessionOutputFile(name) {
63
+ return resolve(SESSIONS_DIR, `${name}.output`);
64
+ }
61
65
  var SESSIONS_DIR;
62
66
  var init_paths = __esm(() => {
63
67
  SESSIONS_DIR = resolve(homedir(), ".noninteractive", "sessions");
@@ -82,6 +86,9 @@ function sessionBinDir2(name) {
82
86
  function sessionUrlsFile2(name) {
83
87
  return resolve2(SESSIONS_DIR2, name, "urls");
84
88
  }
89
+ function sessionOutputFile2(name) {
90
+ return resolve2(SESSIONS_DIR2, `${name}.output`);
91
+ }
85
92
  var SESSIONS_DIR2;
86
93
  var init_paths2 = __esm(() => {
87
94
  SESSIONS_DIR2 = resolve2(homedir2(), ".noninteractive", "sessions");
@@ -236,6 +243,9 @@ function runDaemon(sessionName, executable, args) {
236
243
  exitCode = code;
237
244
  outputBuffer += `
238
245
  [exited ${code}]`;
246
+ try {
247
+ writeFileSync(sessionOutputFile2(sessionName), outputBuffer);
248
+ } catch {}
239
249
  if (notifyDebounce)
240
250
  clearTimeout(notifyDebounce);
241
251
  notifyDebounce = null;
@@ -329,6 +339,9 @@ function runDaemon(sessionName, executable, args) {
329
339
  break;
330
340
  }
331
341
  case "stop":
342
+ try {
343
+ writeFileSync(sessionOutputFile2(sessionName), outputBuffer);
344
+ } catch {}
332
345
  proc.kill("SIGTERM");
333
346
  socket.end(JSON.stringify({ ok: true }));
334
347
  setTimeout(() => {
@@ -364,7 +377,7 @@ var init_daemon = __esm(() => {
364
377
  var require_package = __commonJS((exports, module) => {
365
378
  module.exports = {
366
379
  name: "noninteractive",
367
- version: "0.3.21",
380
+ version: "0.3.24",
368
381
  type: "module",
369
382
  bin: {
370
383
  noninteractive: "./bin/noninteractive.js"
@@ -394,7 +407,7 @@ var require_package = __commonJS((exports, module) => {
394
407
 
395
408
  // src/index.ts
396
409
  import { execSync, spawn as spawn2 } from "child_process";
397
- import { existsSync as existsSync2 } from "fs";
410
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
398
411
 
399
412
  // src/client.ts
400
413
  import { createConnection } from "node:net";
@@ -474,13 +487,15 @@ flags:
474
487
 
475
488
  the session name is auto-derived from the tool (e.g. "workos" \u2192 session "workos").
476
489
 
477
- text is sent exactly as-is \u2014 no auto-appended enter. use $'\\r' for Enter, $'\\x1b[B' for arrow keys.
490
+ text is sent raw \u2014 no auto-appended enter. escape sequences are parsed:
491
+ \\r = Enter, \\n = newline, \\t = tab, \\x1b = escape (for arrow keys)
478
492
 
479
493
  example workflow:
480
494
  npx noninteractive workos # starts "npx workos", session = "workos"
481
- npx noninteractive send workos $'\\r' # press Enter, returns output
482
- npx noninteractive send workos $'y\\r' # type "y" + Enter, returns output
483
- npx noninteractive send workos $'\\x1b[B\\r' # arrow down + Enter, returns output
495
+ npx noninteractive send workos "" # press Enter (empty string = Enter)
496
+ npx noninteractive send workos "y\\r" # type "y" + Enter
497
+ npx noninteractive send workos "\\x1b[B\\r" # arrow down + Enter
498
+ npx noninteractive send workos "\\x1b[B" # arrow down (no Enter)
484
499
  npx noninteractive read workos --wait # wait for new output (e.g. OAuth callback)
485
500
  npx noninteractive stop workos # done, stop the session
486
501
 
@@ -488,11 +503,85 @@ more examples:
488
503
  npx noninteractive vercel # session "vercel"
489
504
  npx noninteractive supabase init # session "supabase"
490
505
  npx noninteractive start vercel login # explicit start for non-npx commands`;
491
- var stripAnsi = (s) => s.replace(/\x1b\[[012]?K/g, `
492
- `).replace(/\x1b\[[\x20-\x3f]*[\x40-\x7e]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[()][A-Z0-9]|\x1b[\x20-\x2f]*[\x30-\x7e]|\x07/g, "").replace(/\r\n?/g, `
506
+ function stripAnsi(s) {
507
+ s = s.replace(/\x1b\[[012]?K/g, `
508
+ `);
509
+ let result = "";
510
+ let bold = false;
511
+ let boldBuf = "";
512
+ let i = 0;
513
+ while (i < s.length) {
514
+ if (s[i] === "\x1B" && s[i + 1] === "[") {
515
+ const end = s.indexOf("m", i + 2);
516
+ if (end !== -1 && end - i < 16 && /^[\d;]*$/.test(s.slice(i + 2, end))) {
517
+ const codes = s.slice(i + 2, end).split(";").map(Number);
518
+ for (const code of codes) {
519
+ if (code === 1 || code === 4 || code === 7) {
520
+ if (!bold) {
521
+ bold = true;
522
+ boldBuf = "";
523
+ }
524
+ } else if (code === 0 || code === 22 || code === 24 || code === 27) {
525
+ if (bold && boldBuf.trim()) {
526
+ result += `**${boldBuf}**`;
527
+ } else if (bold) {
528
+ result += boldBuf;
529
+ }
530
+ bold = false;
531
+ boldBuf = "";
532
+ }
533
+ }
534
+ i = end + 1;
535
+ continue;
536
+ }
537
+ }
538
+ if (s[i] === "\x1B") {
539
+ if (s[i + 1] === "[") {
540
+ const end = s.slice(i + 2).search(/[\x40-\x7e]/);
541
+ if (end !== -1) {
542
+ i += end + 3;
543
+ continue;
544
+ }
545
+ } else if (s[i + 1] === "]") {
546
+ const end = s.indexOf("\x07", i);
547
+ if (end !== -1) {
548
+ i = end + 1;
549
+ continue;
550
+ }
551
+ const end2 = s.indexOf("\x1B\\", i);
552
+ if (end2 !== -1) {
553
+ i = end2 + 2;
554
+ continue;
555
+ }
556
+ } else if (s[i + 1] === "(" || s[i + 1] === ")") {
557
+ i += 3;
558
+ continue;
559
+ } else {
560
+ i += 2;
561
+ continue;
562
+ }
563
+ }
564
+ if (s[i] === "\x07") {
565
+ i++;
566
+ continue;
567
+ }
568
+ if (bold) {
569
+ boldBuf += s[i];
570
+ } else {
571
+ result += s[i];
572
+ }
573
+ i++;
574
+ }
575
+ if (bold && boldBuf.trim()) {
576
+ result += `**${boldBuf}**`;
577
+ } else if (bold) {
578
+ result += boldBuf;
579
+ }
580
+ return result.replace(/\r\n?/g, `
493
581
  `).replace(/\n{3,}/g, `
494
582
 
495
583
  `);
584
+ }
496
585
  var seenUrls = new Set;
497
586
  function openUrl(url) {
498
587
  try {
@@ -652,29 +741,57 @@ async function read(name, wait, timeout, noOpen = false) {
652
741
  msg.timeout = timeout;
653
742
  }
654
743
  const clientTimeout = wait ? timeout + 5000 : 5000;
655
- const res = await sendMessage(sock, msg, clientTimeout);
656
- if (res.output !== undefined)
657
- process.stdout.write(stripAnsi(res.output));
658
- handleUrls(res, noOpen);
659
- if (res.exited)
660
- console.log(`
744
+ try {
745
+ const res = await sendMessage(sock, msg, clientTimeout);
746
+ if (res.output !== undefined)
747
+ process.stdout.write(stripAnsi(res.output));
748
+ handleUrls(res, noOpen);
749
+ if (res.exited)
750
+ console.log(`
661
751
  [exited ${res.exitCode}]`);
752
+ } catch {
753
+ const outputFile = sessionOutputFile(name);
754
+ if (existsSync2(outputFile)) {
755
+ const output = readFileSync2(outputFile, "utf-8");
756
+ process.stdout.write(stripAnsi(output));
757
+ console.log(`
758
+ [session exited]`);
759
+ } else {
760
+ console.error(`session '${name}' not found`);
761
+ process.exit(1);
762
+ }
763
+ }
662
764
  }
663
765
  async function send(name, text, wait, timeout, noOpen = false) {
664
766
  if (text === "")
665
767
  text = "\r";
768
+ text = text.replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))).replace(/\\r/g, "\r").replace(/\\n/g, `
769
+ `).replace(/\\t/g, "\t");
666
770
  const sock = socketPath(name);
667
- if (wait) {
668
- const res = await sendMessage(sock, { action: "sendread", data: text, timeout }, timeout + 5000);
669
- if (res.output !== undefined)
670
- process.stdout.write(stripAnsi(res.output));
671
- handleUrls(res, noOpen);
672
- if (res.exited)
673
- console.log(`
771
+ try {
772
+ if (wait) {
773
+ const res = await sendMessage(sock, { action: "sendread", data: text, timeout }, timeout + 5000);
774
+ if (res.output !== undefined)
775
+ process.stdout.write(stripAnsi(res.output));
776
+ handleUrls(res, noOpen);
777
+ if (res.exited)
778
+ console.log(`
674
779
  [exited ${res.exitCode}]`);
675
- } else {
676
- await sendMessage(sock, { action: "send", data: text });
677
- console.log(`[sent to '${name}' \u2014 run "npx noninteractive read ${name}" to see the result]`);
780
+ } else {
781
+ await sendMessage(sock, { action: "send", data: text });
782
+ console.log(`[sent to '${name}' \u2014 run "npx noninteractive read ${name}" to see the result]`);
783
+ }
784
+ } catch {
785
+ const outputFile = sessionOutputFile(name);
786
+ if (existsSync2(outputFile)) {
787
+ const output = readFileSync2(outputFile, "utf-8");
788
+ process.stdout.write(stripAnsi(output));
789
+ console.log(`
790
+ [session exited]`);
791
+ } else {
792
+ console.error(`session '${name}' not found`);
793
+ process.exit(1);
794
+ }
678
795
  }
679
796
  }
680
797
  async function stop(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noninteractive",
3
- "version": "0.3.21",
3
+ "version": "0.3.24",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "noninteractive": "./bin/noninteractive.js"