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.
- package/bin/noninteractive.js +141 -24
- package/package.json +1 -1
package/bin/noninteractive.js
CHANGED
|
@@ -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.
|
|
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
|
|
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
|
|
482
|
-
npx noninteractive send workos
|
|
483
|
-
npx noninteractive send workos
|
|
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
|
-
|
|
492
|
-
|
|
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
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
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
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
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
|
-
|
|
676
|
-
|
|
677
|
-
|
|
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) {
|