scripter-x 1.0.36 → 1.0.38

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/package.json +1 -1
  2. package/src/update.js +30 -28
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scripter-x",
3
- "version": "1.0.36",
3
+ "version": "1.0.38",
4
4
  "description": "ScripterX — local Flipkart session extractor (runs on your residential IP, syncs to marthunt)",
5
5
  "type": "module",
6
6
  "bin": {
package/src/update.js CHANGED
@@ -121,53 +121,55 @@ function resetTerminal() {
121
121
  } catch { /* */ }
122
122
  }
123
123
 
124
- // Re-exec the CLI so the just-installed version takes over. Spawns a fresh, DETACHED
125
- // process that inherits this terminal, then exits the current one. The caller MUST have
126
- // already torn down the ink/alt-screen UI before calling this.
124
+ // Re-exec the CLI so the just-installed version takes over, keeping the SAME controlling
125
+ // terminal so input goes to the new process not back to the shell.
127
126
  //
128
- // We re-run the CURRENT entry file with node (`process.argv[1]`): after `npm install -g`,
129
- // the global bin symlink points at the new version, so this loads the updated code. If
130
- // that entry path is somehow missing, we fall back to the `scripterx` bin on PATH.
127
+ // THE BUG this fixes: the old code spawned the child with `detached:true` + `child.unref()`,
128
+ // which puts the child in its OWN session and RELINQUISHES the controlling TTY. The child
129
+ // then can't be the foreground job, so the user's shell (zsh) stays in the foreground and
130
+ // echoes every keystroke at the bottom of the screen, while the orphaned child renders the
131
+ // banner in the background. That's exactly the "typing shows at the bottom" symptom.
131
132
  //
132
- // ORDERING is what makes the restart clean: we resetTerminal() FIRST (cooked TTY, mouse off,
133
- // stdin drained), THEN spawn the child, THEN exit immediately on the next tick. The child
134
- // only sets up raw mode / mouse tracking after it boots by which point the parent is gone,
135
- // so the two never fight over the TTY. No more leaked keystrokes.
133
+ // Correct pattern for a TTY hand-off: spawn the child ATTACHED (not detached, no unref) with
134
+ // inherited stdio, and keep THIS process alive as its parent until it exits, then mirror its
135
+ // exit code. The child is a normal foreground job sharing our controlling terminal, so it
136
+ // owns stdin and raw mode works. We reset the terminal first so it boots onto a clean screen.
136
137
  //
137
- // NOTE: on success it exits the process and never returns. Returns false only if BOTH
138
- // spawn attempts throw synchronously, so the caller can show "restart manually".
138
+ // We re-run the CURRENT entry file with node (`process.argv[1]`): after `npm install -g`, the
139
+ // global bin symlink points at the new version, so this loads the updated code; if that entry
140
+ // path is missing we fall back to the `scripterx` bin on PATH.
141
+ //
142
+ // NOTE: on success this never returns (it waits, then process.exit mirrors the child). Returns
143
+ // false only if BOTH spawn attempts throw synchronously.
139
144
  export function restartCli({ binName = 'scripterx' } = {}) {
140
- // Re-run with the SAME args the user launched with (drop node + the script path), so
141
- // `scripterx` → interactive shell, `scripterx zepto` → zepto, etc.
142
145
  const argv = process.argv.slice(2);
143
146
  const entry = process.argv[1];
144
147
 
145
- // Clean the terminal BEFORE spawning so the child never inherits raw mode / mouse mode.
148
+ // Clean the terminal BEFORE spawning so the child boots onto a clean, cooked screen.
146
149
  resetTerminal();
147
150
 
148
- const trySpawn = (cmd, args) => {
149
- const child = spawn(cmd, args, { stdio: 'inherit', detached: true, shell: false });
150
- child.unref();
151
- return child;
152
- };
151
+ // ATTACHED spawn: child shares our controlling TTY and becomes the foreground job. We keep
152
+ // running as its parent and exit with its code when it finishes — so the shell prompt only
153
+ // returns after the (new) CLI actually quits.
154
+ const trySpawn = (cmd, args) => spawn(cmd, args, { stdio: 'inherit', shell: false });
153
155
 
154
- const exitSoon = () => {
155
- // Exit on the next tick (not after a long timer) so we don't linger on the TTY. The
156
- // detached child has already inherited the (now clean) fds and takes over.
157
- setImmediate(() => process.exit(0));
156
+ const supervise = (child) => {
157
+ child.on('exit', (code, signal) => {
158
+ if (signal) { try { process.kill(process.pid, signal); } catch { process.exit(1); } }
159
+ else process.exit(code == null ? 0 : code);
160
+ });
158
161
  };
159
162
 
160
163
  try {
161
164
  const primary = trySpawn(process.execPath, [entry, ...argv]);
162
165
  primary.on('error', () => {
163
- try { trySpawn(binName, argv); } catch { /* nothing more we can do */ }
166
+ try { supervise(trySpawn(binName, argv)); } catch { process.exit(1); }
164
167
  });
165
- exitSoon();
168
+ supervise(primary);
166
169
  return true;
167
170
  } catch {
168
171
  try {
169
- trySpawn(binName, argv);
170
- exitSoon();
172
+ supervise(trySpawn(binName, argv));
171
173
  return true;
172
174
  } catch {
173
175
  return false;