cli-tunnel 1.2.0-beta.4 → 1.2.0-beta.6
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/dist/index.js +112 -48
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -475,42 +475,36 @@ async function main() {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
if (devtunnelInstalled) {
|
|
478
|
+
// Check if logged in before attempting tunnel creation
|
|
478
479
|
try {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
if (userInfo.includes('not logged in') || userInfo.includes('No user') || userInfo.includes('Anonymous')) {
|
|
483
|
-
throw new Error('not logged in');
|
|
484
|
-
}
|
|
480
|
+
const userInfo = execFileSync('devtunnel', ['user', 'show'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
481
|
+
if (userInfo.includes('not logged in') || userInfo.includes('No user') || userInfo.includes('Anonymous')) {
|
|
482
|
+
throw new Error('not logged in');
|
|
485
483
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
catch {
|
|
499
|
-
console.log(`\n ${YELLOW}⚠${RESET} Login failed. Run manually: ${GREEN}devtunnel user login${RESET}\n`);
|
|
500
|
-
console.log(` ${DIM}Continuing without tunnel (local only)...${RESET}\n`);
|
|
501
|
-
devtunnelInstalled = false;
|
|
502
|
-
}
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
console.log(`\n ${YELLOW}⚠ devtunnel not authenticated.${RESET}\n`);
|
|
487
|
+
const loginAnswer = await askUser(` Would you like to log in now? [Y/n] `);
|
|
488
|
+
if (loginAnswer === '' || loginAnswer === 'y' || loginAnswer === 'yes') {
|
|
489
|
+
try {
|
|
490
|
+
const loginProc = spawn('devtunnel', ['user', 'login'], { stdio: 'inherit' });
|
|
491
|
+
await new Promise((resolve, reject) => {
|
|
492
|
+
loginProc.on('close', (code) => code === 0 ? resolve() : reject(new Error(`Login exited with code ${code}`)));
|
|
493
|
+
loginProc.on('error', reject);
|
|
494
|
+
});
|
|
495
|
+
console.log(`\n ${GREEN}✓${RESET} Logged in successfully!\n`);
|
|
503
496
|
}
|
|
504
|
-
|
|
505
|
-
console.log(`\n ${
|
|
497
|
+
catch {
|
|
498
|
+
console.log(`\n ${YELLOW}⚠${RESET} Login failed. Run manually: ${GREEN}devtunnel user login${RESET}\n`);
|
|
506
499
|
console.log(` ${DIM}Continuing without tunnel (local only)...${RESET}\n`);
|
|
507
500
|
devtunnelInstalled = false;
|
|
508
501
|
}
|
|
509
502
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
503
|
+
else {
|
|
504
|
+
console.log(`\n ${DIM}Run this once to log in: ${GREEN}devtunnel user login${RESET}`);
|
|
505
|
+
console.log(` ${DIM}Continuing without tunnel (local only)...${RESET}\n`);
|
|
506
|
+
devtunnelInstalled = false;
|
|
507
|
+
}
|
|
514
508
|
}
|
|
515
509
|
}
|
|
516
510
|
if (devtunnelInstalled) {
|
|
@@ -553,7 +547,28 @@ async function main() {
|
|
|
553
547
|
catch { } });
|
|
554
548
|
}
|
|
555
549
|
catch (err) {
|
|
556
|
-
|
|
550
|
+
const errMsg = err.message || '';
|
|
551
|
+
// Detect auth failure at create time (expired token, anonymous, etc.)
|
|
552
|
+
if (errMsg.includes('Anonymous') || errMsg.includes('Unauthorized') || errMsg.includes('not permitted')) {
|
|
553
|
+
console.log(`\n ${YELLOW}⚠ devtunnel session expired or not authenticated.${RESET}\n`);
|
|
554
|
+
const loginAnswer = await askUser(` Would you like to log in now? [Y/n] `);
|
|
555
|
+
if (loginAnswer === '' || loginAnswer === 'y' || loginAnswer === 'yes') {
|
|
556
|
+
try {
|
|
557
|
+
const loginProc = spawn('devtunnel', ['user', 'login'], { stdio: 'inherit' });
|
|
558
|
+
await new Promise((resolve, reject) => {
|
|
559
|
+
loginProc.on('close', (code) => code === 0 ? resolve() : reject(new Error(`Login exited with code ${code}`)));
|
|
560
|
+
loginProc.on('error', reject);
|
|
561
|
+
});
|
|
562
|
+
console.log(`\n ${GREEN}✓${RESET} Logged in! Please run cli-tunnel again to create the tunnel.\n`);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
console.log(`\n ${YELLOW}⚠${RESET} Login failed. Run manually: ${GREEN}devtunnel user login${RESET}\n`);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
console.log(` ${YELLOW}⚠${RESET} Tunnel failed: ${errMsg}\n`);
|
|
571
|
+
}
|
|
557
572
|
}
|
|
558
573
|
} // end if (devtunnelInstalled)
|
|
559
574
|
}
|
|
@@ -617,44 +632,93 @@ async function main() {
|
|
|
617
632
|
cols, rows, cwd,
|
|
618
633
|
env: safeEnv,
|
|
619
634
|
});
|
|
620
|
-
// Detect CSPRNG crash (Node.js 23 + node-pty issue) and retry
|
|
635
|
+
// Detect CSPRNG crash (Node.js 23 + node-pty issue) and retry with fallbacks
|
|
621
636
|
let ptyExitedEarly = false;
|
|
622
637
|
const earlyExitCheck = new Promise((resolve) => {
|
|
623
638
|
ptyProcess.onExit(({ exitCode }) => {
|
|
624
|
-
if (exitCode === 134 || exitCode === 3221226505) {
|
|
639
|
+
if (exitCode === 134 || exitCode === 3221226505) {
|
|
625
640
|
ptyExitedEarly = true;
|
|
626
641
|
resolve();
|
|
627
642
|
}
|
|
628
643
|
});
|
|
629
|
-
setTimeout(resolve, 2000);
|
|
644
|
+
setTimeout(resolve, 2000);
|
|
630
645
|
});
|
|
631
646
|
await earlyExitCheck;
|
|
632
647
|
if (ptyExitedEarly && process.platform === 'win32') {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
648
|
+
// Retry 1: Use full environment — CSPRNG may need env vars we filtered out
|
|
649
|
+
console.log(` ${YELLOW}⚠${RESET} Process crashed, retrying with full environment...\n`);
|
|
650
|
+
// Blocklist approach: pass everything EXCEPT known dangerous vars
|
|
651
|
+
const DANGEROUS_VARS = new Set(['NODE_OPTIONS', 'NODE_REPL_HISTORY', 'NODE_EXTRA_CA_CERTS',
|
|
652
|
+
'NODE_PATH', 'NODE_REDIRECT_WARNINGS', 'NODE_PENDING_DEPRECATION',
|
|
653
|
+
'UV_THREADPOOL_SIZE', 'LD_PRELOAD', 'DYLD_INSERT_LIBRARIES']);
|
|
654
|
+
const fullSafeEnv = {};
|
|
655
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
656
|
+
if (!DANGEROUS_VARS.has(k) && v !== undefined)
|
|
657
|
+
fullSafeEnv[k] = v;
|
|
658
|
+
}
|
|
659
|
+
ptyProcess = nodePty.spawn(resolvedCmd, commandArgs, {
|
|
637
660
|
name: 'xterm-256color',
|
|
638
661
|
cols, rows, cwd,
|
|
639
|
-
env:
|
|
662
|
+
env: fullSafeEnv,
|
|
640
663
|
});
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
const retryCheck = new Promise((resolve) => {
|
|
664
|
+
let retry1Failed = false;
|
|
665
|
+
const retry1Check = new Promise((resolve) => {
|
|
644
666
|
ptyProcess.onExit(({ exitCode }) => {
|
|
645
667
|
if (exitCode === 134 || exitCode === 3221226505) {
|
|
646
|
-
|
|
668
|
+
retry1Failed = true;
|
|
647
669
|
resolve();
|
|
648
670
|
}
|
|
649
671
|
});
|
|
650
672
|
setTimeout(resolve, 2000);
|
|
651
673
|
});
|
|
652
|
-
await
|
|
653
|
-
if (
|
|
654
|
-
|
|
655
|
-
console.log(` ${YELLOW}⚠${RESET}
|
|
656
|
-
|
|
657
|
-
|
|
674
|
+
await retry1Check;
|
|
675
|
+
if (retry1Failed) {
|
|
676
|
+
// Retry 2: cmd.exe wrapper with full env
|
|
677
|
+
console.log(` ${YELLOW}⚠${RESET} Still crashing, retrying via cmd.exe wrapper...\n`);
|
|
678
|
+
const cmdLine = [resolvedCmd, ...commandArgs].map(a => a.includes(' ') ? `"${a}"` : a).join(' ');
|
|
679
|
+
ptyProcess = nodePty.spawn('cmd.exe', ['/c', cmdLine], {
|
|
680
|
+
name: 'xterm-256color',
|
|
681
|
+
cols, rows, cwd,
|
|
682
|
+
env: fullSafeEnv,
|
|
683
|
+
});
|
|
684
|
+
let retry2Failed = false;
|
|
685
|
+
const retry2Check = new Promise((resolve) => {
|
|
686
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
687
|
+
if (exitCode === 134 || exitCode === 3221226505) {
|
|
688
|
+
retry2Failed = true;
|
|
689
|
+
resolve();
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
setTimeout(resolve, 2000);
|
|
693
|
+
});
|
|
694
|
+
await retry2Check;
|
|
695
|
+
if (retry2Failed) {
|
|
696
|
+
// Retry 3: useConpty: false with full env
|
|
697
|
+
console.log(` ${YELLOW}⚠${RESET} Still crashing, retrying with legacy PTY backend...\n`);
|
|
698
|
+
ptyProcess = nodePty.spawn(resolvedCmd, commandArgs, {
|
|
699
|
+
name: 'xterm-256color',
|
|
700
|
+
cols, rows, cwd,
|
|
701
|
+
env: fullSafeEnv,
|
|
702
|
+
useConpty: false,
|
|
703
|
+
});
|
|
704
|
+
let retry3Failed = false;
|
|
705
|
+
const retry3Check = new Promise((resolve) => {
|
|
706
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
707
|
+
if (exitCode === 134 || exitCode === 3221226505) {
|
|
708
|
+
retry3Failed = true;
|
|
709
|
+
resolve();
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
setTimeout(resolve, 2000);
|
|
713
|
+
});
|
|
714
|
+
await retry3Check;
|
|
715
|
+
if (retry3Failed) {
|
|
716
|
+
const nodeVer = process.version;
|
|
717
|
+
console.log(` ${YELLOW}⚠${RESET} The command crashed due to a known Node.js ${nodeVer} + PTY compatibility issue.`);
|
|
718
|
+
console.log(` ${BOLD}Fix:${RESET} Install Node.js 22 LTS: ${GREEN}nvm install 22${RESET} or ${GREEN}winget install OpenJS.NodeJS.LTS${RESET}\n`);
|
|
719
|
+
process.exit(1);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
658
722
|
}
|
|
659
723
|
}
|
|
660
724
|
ptyProcess.onData((data) => {
|