@threadbase-sh/streamer 1.31.2 → 1.31.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/cli.cjs +98 -8
- package/dist/cli.cjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -147757,7 +147757,81 @@ async function stopService(opts = {}) {
|
|
|
147757
147757
|
const { stdout: stdout2, stderr } = await execFileP("schtasks.exe", ["/End", "/TN", label]).catch(
|
|
147758
147758
|
(err) => ({ stdout: "", stderr: String(err) })
|
|
147759
147759
|
);
|
|
147760
|
-
|
|
147760
|
+
const listenerResult = await stopWindowsListener(opts.port ?? 8766);
|
|
147761
|
+
return {
|
|
147762
|
+
method: "schtasks-end",
|
|
147763
|
+
stdout: `${stdout2}
|
|
147764
|
+
${listenerResult.stdout}`,
|
|
147765
|
+
stderr: `${stderr}
|
|
147766
|
+
${listenerResult.stderr}`
|
|
147767
|
+
};
|
|
147768
|
+
}
|
|
147769
|
+
async function stopWindowsListener(port) {
|
|
147770
|
+
let netstat;
|
|
147771
|
+
try {
|
|
147772
|
+
netstat = await execFileP("netstat.exe", ["-ano", "-p", "tcp"]);
|
|
147773
|
+
} catch (err) {
|
|
147774
|
+
return { stdout: "", stderr: `Could not inspect port ${port}: ${String(err)}` };
|
|
147775
|
+
}
|
|
147776
|
+
const pids = /* @__PURE__ */ new Set();
|
|
147777
|
+
for (const line of netstat.stdout.split(/\r?\n/)) {
|
|
147778
|
+
const columns = line.trim().split(/\s+/);
|
|
147779
|
+
if (columns.length < 5 || columns[0]?.toUpperCase() !== "TCP") continue;
|
|
147780
|
+
const [localAddress, state, pid] = [columns[1], columns[3], columns[4]];
|
|
147781
|
+
if (state?.toUpperCase() !== "LISTENING" || !pid || pid === "0") continue;
|
|
147782
|
+
if (localAddress?.endsWith(`:${port}`)) pids.add(pid);
|
|
147783
|
+
}
|
|
147784
|
+
const output = [];
|
|
147785
|
+
const errors = [];
|
|
147786
|
+
for (const pid of pids) {
|
|
147787
|
+
try {
|
|
147788
|
+
const result = await execFileP("taskkill.exe", ["/PID", pid, "/T", "/F"]);
|
|
147789
|
+
output.push(result.stdout);
|
|
147790
|
+
if (result.stderr) errors.push(result.stderr);
|
|
147791
|
+
} catch (err) {
|
|
147792
|
+
errors.push(`Could not stop PID ${pid} on port ${port}: ${String(err)}`);
|
|
147793
|
+
}
|
|
147794
|
+
}
|
|
147795
|
+
return { stdout: output.join("\n"), stderr: errors.join("\n") };
|
|
147796
|
+
}
|
|
147797
|
+
|
|
147798
|
+
// src/updater/restart-health.ts
|
|
147799
|
+
function isExpectedVersion(actual, expected) {
|
|
147800
|
+
return actual === expected || actual.startsWith(`${expected}+`);
|
|
147801
|
+
}
|
|
147802
|
+
async function waitForRestartHealth(opts) {
|
|
147803
|
+
const timeoutMs = opts.timeoutMs ?? 15e3;
|
|
147804
|
+
const pollIntervalMs = opts.pollIntervalMs ?? 250;
|
|
147805
|
+
const deadline = Date.now() + timeoutMs;
|
|
147806
|
+
let lastFailure = "server did not respond";
|
|
147807
|
+
while (Date.now() <= deadline) {
|
|
147808
|
+
const controller = new AbortController();
|
|
147809
|
+
const requestTimer = setTimeout(() => controller.abort(), Math.min(2e3, timeoutMs));
|
|
147810
|
+
try {
|
|
147811
|
+
const response = await fetch(`http://127.0.0.1:${opts.port}/healthz`, {
|
|
147812
|
+
signal: controller.signal
|
|
147813
|
+
});
|
|
147814
|
+
if (response.ok) {
|
|
147815
|
+
const body = await response.json();
|
|
147816
|
+
if (body.ok === true && typeof body.version === "string") {
|
|
147817
|
+
if (isExpectedVersion(body.version, opts.expectedVersion)) return;
|
|
147818
|
+
lastFailure = `running version is ${body.version}, expected ${opts.expectedVersion}`;
|
|
147819
|
+
} else {
|
|
147820
|
+
lastFailure = "health response is missing ok/version";
|
|
147821
|
+
}
|
|
147822
|
+
} else {
|
|
147823
|
+
lastFailure = `health endpoint returned ${response.status}`;
|
|
147824
|
+
}
|
|
147825
|
+
} catch (err) {
|
|
147826
|
+
lastFailure = err instanceof Error ? err.message : String(err);
|
|
147827
|
+
} finally {
|
|
147828
|
+
clearTimeout(requestTimer);
|
|
147829
|
+
}
|
|
147830
|
+
const remaining = deadline - Date.now();
|
|
147831
|
+
if (remaining <= 0) break;
|
|
147832
|
+
await new Promise((resolve6) => setTimeout(resolve6, Math.min(pollIntervalMs, remaining)));
|
|
147833
|
+
}
|
|
147834
|
+
throw new Error(`restart verification failed: ${lastFailure}`);
|
|
147761
147835
|
}
|
|
147762
147836
|
|
|
147763
147837
|
// src/updater/stamp-version.ts
|
|
@@ -150899,7 +150973,7 @@ async function runInstall(opts) {
|
|
|
150899
150973
|
await unpackTarball({ tarballPath, destDir });
|
|
150900
150974
|
stampVersionTxt(destDir, targetVersion);
|
|
150901
150975
|
if (process.platform === "win32") {
|
|
150902
|
-
await stopService().catch(() => {
|
|
150976
|
+
await stopService({ port: opts.runningServer?.port }).catch(() => {
|
|
150903
150977
|
});
|
|
150904
150978
|
}
|
|
150905
150979
|
swapCurrent(targetVersion);
|
|
@@ -150908,6 +150982,12 @@ async function runInstall(opts) {
|
|
|
150908
150982
|
try {
|
|
150909
150983
|
const r = await restartService();
|
|
150910
150984
|
restartMethod = r.method;
|
|
150985
|
+
if (opts.runningServer && r.method !== "none") {
|
|
150986
|
+
await waitForRestartHealth({
|
|
150987
|
+
port: opts.runningServer.port,
|
|
150988
|
+
expectedVersion: targetVersion
|
|
150989
|
+
});
|
|
150990
|
+
}
|
|
150911
150991
|
} catch (err) {
|
|
150912
150992
|
restartMethod = `failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
150913
150993
|
}
|
|
@@ -150918,8 +150998,9 @@ async function runInstall(opts) {
|
|
|
150918
150998
|
pruned,
|
|
150919
150999
|
restart: { method: restartMethod }
|
|
150920
151000
|
};
|
|
151001
|
+
const outcome = restartMethod.startsWith("failed:") ? "failed" : "installed";
|
|
150921
151002
|
appendUpdateLog(
|
|
150922
|
-
`[
|
|
151003
|
+
`[${outcome}] ${installed.previous} \u2192 ${installed.installed} restart=${installed.restart.method}${pruned.length > 0 ? ` pruned=${pruned.length}` : ""}`
|
|
150923
151004
|
);
|
|
150924
151005
|
return installed;
|
|
150925
151006
|
}
|
|
@@ -151378,11 +151459,20 @@ program2.command("update").description("Check for streamer updates from GitHub R
|
|
|
151378
151459
|
);
|
|
151379
151460
|
break;
|
|
151380
151461
|
case "installed":
|
|
151381
|
-
|
|
151382
|
-
|
|
151383
|
-
|
|
151384
|
-
|
|
151385
|
-
|
|
151462
|
+
if (result.restart.method.startsWith("failed:")) {
|
|
151463
|
+
log7.error(
|
|
151464
|
+
`Installed ${result.installed} on disk, but the running service was not updated. Restart: ${result.restart.method}.`,
|
|
151465
|
+
void 0,
|
|
151466
|
+
"console"
|
|
151467
|
+
);
|
|
151468
|
+
process.exitCode = 1;
|
|
151469
|
+
} else {
|
|
151470
|
+
log7.info(
|
|
151471
|
+
`Installed ${result.installed} (was ${result.previous}). Restart: ${result.restart.method}.`,
|
|
151472
|
+
void 0,
|
|
151473
|
+
"console"
|
|
151474
|
+
);
|
|
151475
|
+
}
|
|
151386
151476
|
if (result.pruned.length > 0) {
|
|
151387
151477
|
log7.info(`Pruned old releases: ${result.pruned.join(", ")}`, void 0, "console");
|
|
151388
151478
|
}
|