@floless/app 0.6.1 → 0.6.3
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/floless-server.cjs +1373 -1364
- package/launch.mjs +23 -3
- package/package.json +1 -1
package/launch.mjs
CHANGED
|
@@ -123,7 +123,11 @@ function startServerDetached() {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
function openBrowser(url) {
|
|
126
|
-
|
|
126
|
+
// NO `detached` on Windows: Node #21825 makes `detached` defeat `windowsHide` for a CUI
|
|
127
|
+
// child (cmd.exe), flashing a console window. Without it, windowsHide hides cmd; `start`
|
|
128
|
+
// hands the URL to the browser via ShellExecute (independent of cmd's tree), so the browser
|
|
129
|
+
// still survives this launcher exiting. unref() keeps it from holding the event loop.
|
|
130
|
+
if (isWin) spawn('cmd', ['/c', 'start', '', url], { windowsHide: true }).unref();
|
|
127
131
|
else spawn(process.platform === 'darwin' ? 'open' : 'xdg-open', [url], { detached: true }).unref();
|
|
128
132
|
}
|
|
129
133
|
|
|
@@ -312,16 +316,32 @@ function enumerateProcesses() {
|
|
|
312
316
|
}
|
|
313
317
|
}
|
|
314
318
|
|
|
319
|
+
// Build the `taskkill` argv for one pid. `tree` (default true) adds /T to also kill the
|
|
320
|
+
// target's whole child-process tree — correct for teardown/uninstall, where the
|
|
321
|
+
// supervisor's spawned --serve child must die WITH it. The update-apply path running
|
|
322
|
+
// inside the SERVE passes tree:false: there the caller IS the supervisor's --serve child
|
|
323
|
+
// (and the process that must survive to launch Update.exe), so a /T tree-kill of the
|
|
324
|
+
// supervisor would also kill the caller itself. tree:false kills ONLY the supervisor and
|
|
325
|
+
// lets the serve exit on its own. Pure + exported so the /T decision is unit-tested.
|
|
326
|
+
export function taskkillArgs(pid, { tree = true } = {}) {
|
|
327
|
+
return tree ? ['/PID', String(pid), '/T', '/F'] : ['/PID', String(pid), '/F'];
|
|
328
|
+
}
|
|
329
|
+
|
|
315
330
|
// Kill the --supervise watchdog FIRST (Codex B1) so it can't respawn the server in
|
|
316
331
|
// the gap before stopServer(). Matches THIS app's exe + the supervise action, never
|
|
317
332
|
// process.pid (self-kill guard lives in supervisorPidsToKill). Idempotent; win32-only.
|
|
318
333
|
//
|
|
334
|
+
// `tree` (default true) tree-kills (/T) — teardown/uninstall, where the supervisor's
|
|
335
|
+
// --serve child must die too. The update-apply path INSIDE the serve passes {tree:false}
|
|
336
|
+
// (the serve is itself the supervisor's child and must survive to launch Update.exe, then
|
|
337
|
+
// exit on its own) — see taskkillArgs above and index.ts /api/update/apply.
|
|
338
|
+
//
|
|
319
339
|
// SAFETY (review #1): in the npm channel process.execPath is the GENERIC node.exe, so
|
|
320
340
|
// matching on it alone could kill ANY `node … supervise` process (e.g. a third-party
|
|
321
341
|
// watchdog). When we detect that channel, also require the launcher script (this
|
|
322
342
|
// launch.mjs) in the command line — our supervisor runs `node … launch.mjs supervise`.
|
|
323
343
|
// The packaged exe (unique FlolessApp.exe) passes no scriptMatch — its match is exact.
|
|
324
|
-
function killSupervisor() {
|
|
344
|
+
export function killSupervisor({ tree = true } = {}) {
|
|
325
345
|
if (!isWin) return;
|
|
326
346
|
const isNpmChannel = /^node(\.exe)?$/i.test(basename(process.execPath));
|
|
327
347
|
const scriptMatch = isNpmChannel ? basename(fileURLToPath(import.meta.url)) : undefined; // 'launch.mjs'
|
|
@@ -339,7 +359,7 @@ function killSupervisor() {
|
|
|
339
359
|
log(`stopping supervisor (pid ${pid})…`);
|
|
340
360
|
// execFileSync (no shell) with an argv array — pid is already Number()-coerced in
|
|
341
361
|
// parseProcessList, and avoiding the shell rules out any injection entirely.
|
|
342
|
-
try { execFileSync('taskkill',
|
|
362
|
+
try { execFileSync('taskkill', taskkillArgs(pid, { tree }), { stdio: 'ignore', windowsHide: true }); } catch { /* already gone */ }
|
|
343
363
|
}
|
|
344
364
|
}
|
|
345
365
|
|