aptunnel 1.0.1 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aptunnel",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Cross-platform Aptible tunnel manager — multi-tunnel, auto-discovery, background process management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,15 +37,16 @@ export async function runInit(args) {
37
37
  console.log('');
38
38
 
39
39
  // 4. Login (interactive — handles 2FA via stdio: inherit)
40
- // Close readline BEFORE spawning aptible so stdin is fully available to the child
40
+ // Do NOT show a spinner here: aptible may prompt for a 2FA OTP code and the
41
+ // spinner output would hide that prompt. Print a plain line instead.
41
42
  closeRL();
42
- const spinner = (await import('ora')).default({ text: 'Logging in to Aptible…' }).start();
43
+ console.log('Logging in to Aptible… (enter 2FA code if prompted)');
43
44
  const ok = await login({ email, password });
44
45
  if (!ok) {
45
- spinner.fail('Login failed. Please check your credentials.');
46
+ logger.error('Login failed. Please check your credentials.');
46
47
  process.exit(1);
47
48
  }
48
- spinner.succeed('Logged in successfully.');
49
+ logger.success('Logged in successfully.');
49
50
  console.log('');
50
51
 
51
52
  // 5. Discover environments
@@ -303,6 +304,9 @@ function askSecret(prompt) {
303
304
  if (char === '\r' || char === '\n') {
304
305
  process.stdin.removeListener('data', onData);
305
306
  if (isTTY) process.stdin.setRawMode(false);
307
+ // Pause so Node.js stops consuming keystrokes that belong to child
308
+ // processes (e.g. aptible login waiting for a 2FA OTP).
309
+ process.stdin.pause();
306
310
  process.stdout.write('\n');
307
311
  resolve(chars.join(''));
308
312
  return;
@@ -120,6 +120,7 @@ function askSecret(prompt) {
120
120
  if (char === '\r' || char === '\n') {
121
121
  process.stdin.removeListener('data', onData);
122
122
  if (isTTY) process.stdin.setRawMode(false);
123
+ process.stdin.pause();
123
124
  process.stdout.write('\n');
124
125
  resolve(chars.join(''));
125
126
  return;
@@ -58,12 +58,10 @@ export function login({ email, password, lifetime = '7d', otp } = {}) {
58
58
  if (password) args.push(`--password=${password}`);
59
59
  if (otp) args.push(`--otp=${otp}`);
60
60
 
61
- // Resume stdin so aptible can receive input (e.g. 2FA OTP prompt).
62
- // readline.close() pauses process.stdin; we must unpause it before handing
63
- // it to a child process, otherwise the child's read() never returns.
64
- process.stdin.resume();
65
-
66
- // stdio: 'inherit' is critical — aptible prompts for 2FA interactively
61
+ // stdio: 'inherit' aptible reads from fd 0 directly at OS level,
62
+ // independent of Node.js stream state. Do NOT call process.stdin.resume()
63
+ // here: flowing mode with no listener would consume the user's 2FA keystrokes
64
+ // before aptible gets them.
67
65
  const child = spawn('aptible', args, { stdio: 'inherit', ...SHELL_OPT });
68
66
 
69
67
  child.on('close', (code) => resolve(code === 0));