@monotykamary/localterm-server 2.74.1 → 2.76.0
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/capture-renderer.d.ts +1 -0
- package/dist/capture-renderer.d.ts.map +1 -1
- package/dist/capture-renderer.js +25 -1
- package/dist/capture-renderer.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -1
- package/dist/hibernate-ledger.d.ts +16 -0
- package/dist/hibernate-ledger.d.ts.map +1 -0
- package/dist/hibernate-ledger.js +37 -0
- package/dist/hibernate-ledger.js.map +1 -0
- package/dist/hibernate-store.d.ts +18 -0
- package/dist/hibernate-store.d.ts.map +1 -0
- package/dist/hibernate-store.js +56 -0
- package/dist/hibernate-store.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +94 -72
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +9 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/schemas.js.map +1 -1
- package/dist/session-client-hub.d.ts.map +1 -1
- package/dist/session-client-hub.js +1 -0
- package/dist/session-client-hub.js.map +1 -1
- package/dist/session-manager.d.ts +4 -1
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +36 -1
- package/dist/session-manager.js.map +1 -1
- package/dist/session-output-coordinator.d.ts.map +1 -1
- package/dist/session-output-coordinator.js +2 -1
- package/dist/session-output-coordinator.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +8 -0
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/append-to-bounded-utf8-ring.d.ts +2 -0
- package/dist/utils/append-to-bounded-utf8-ring.d.ts.map +1 -0
- package/dist/utils/append-to-bounded-utf8-ring.js +32 -0
- package/dist/utils/append-to-bounded-utf8-ring.js.map +1 -0
- package/dist/utils/create-bounded-debounce.d.ts +13 -0
- package/dist/utils/create-bounded-debounce.d.ts.map +1 -0
- package/dist/utils/create-bounded-debounce.js +43 -0
- package/dist/utils/create-bounded-debounce.js.map +1 -0
- package/dist/utils/find-terminal-safe-trim-offset.d.ts +2 -0
- package/dist/utils/find-terminal-safe-trim-offset.d.ts.map +1 -0
- package/dist/utils/find-terminal-safe-trim-offset.js +96 -0
- package/dist/utils/find-terminal-safe-trim-offset.js.map +1 -0
- package/dist/utils/main-screen-output-filter.d.ts +17 -0
- package/dist/utils/main-screen-output-filter.d.ts.map +1 -0
- package/dist/utils/main-screen-output-filter.js +185 -0
- package/dist/utils/main-screen-output-filter.js.map +1 -0
- package/dist/utils/merge-workspace-restore-entries.d.ts +9 -0
- package/dist/utils/merge-workspace-restore-entries.d.ts.map +1 -0
- package/dist/utils/merge-workspace-restore-entries.js +79 -0
- package/dist/utils/merge-workspace-restore-entries.js.map +1 -0
- package/dist/utils/normalize-hibernate-scrollback.d.ts +2 -0
- package/dist/utils/normalize-hibernate-scrollback.d.ts.map +1 -0
- package/dist/utils/normalize-hibernate-scrollback.js +23 -0
- package/dist/utils/normalize-hibernate-scrollback.js.map +1 -0
- package/dist/utils/pending-workspace-restore-tabs.d.ts +4 -0
- package/dist/utils/pending-workspace-restore-tabs.d.ts.map +1 -0
- package/dist/utils/pending-workspace-restore-tabs.js +21 -0
- package/dist/utils/pending-workspace-restore-tabs.js.map +1 -0
- package/dist/utils/plan-workspace-restore.d.ts +14 -0
- package/dist/utils/plan-workspace-restore.d.ts.map +1 -0
- package/dist/utils/plan-workspace-restore.js +12 -0
- package/dist/utils/plan-workspace-restore.js.map +1 -0
- package/dist/utils/render-buffer-line-with-sgr.d.ts +3 -0
- package/dist/utils/render-buffer-line-with-sgr.d.ts.map +1 -0
- package/dist/utils/render-buffer-line-with-sgr.js +100 -0
- package/dist/utils/render-buffer-line-with-sgr.js.map +1 -0
- package/dist/utils/render-legacy-hibernate-scrollback.d.ts +2 -0
- package/dist/utils/render-legacy-hibernate-scrollback.d.ts.map +1 -0
- package/dist/utils/render-legacy-hibernate-scrollback.js +56 -0
- package/dist/utils/render-legacy-hibernate-scrollback.js.map +1 -0
- package/dist/utils/terminal-mode-state.d.ts +0 -1
- package/dist/utils/terminal-mode-state.d.ts.map +1 -1
- package/dist/utils/terminal-mode-state.js +1 -1
- package/dist/utils/terminal-mode-state.js.map +1 -1
- package/dist/utils/workspace-session-ids.d.ts +3 -0
- package/dist/utils/workspace-session-ids.d.ts.map +1 -0
- package/dist/utils/workspace-session-ids.js +11 -0
- package/dist/utils/workspace-session-ids.js.map +1 -0
- package/dist/utils/write-file-atomically.d.ts +2 -0
- package/dist/utils/write-file-atomically.d.ts.map +1 -0
- package/dist/utils/write-file-atomically.js +38 -0
- package/dist/utils/write-file-atomically.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import { detectWithExplicitPort } from "./cdp/discover-explicit-endpoint.js";
|
|
|
22
22
|
import { DaemonConfigStore } from "./daemon-config-store.js";
|
|
23
23
|
import { formatCandidates, resolveCandidates, resolveCompletionContext, } from "./completion/index.js";
|
|
24
24
|
import { z } from "zod";
|
|
25
|
-
import { ACTIVITY_DIRNAME, ACTIVITY_REFRESH_DEBOUNCE_MS, ACTIVITY_WATCHED_PROGRAMS, AUTOMATION_EVENT_DEBOUNCE_MS, AUTOMATION_RECONCILE_MIN_DOWNTIME_MS, AUTOMATION_RUN_QUERY_PARAM, AUTOMATION_WATCH_DEBOUNCE_MS, AUTOMATION_WATCH_POST_RUN_GRACE_MS, AUTOMATION_WEBHOOK_DEBOUNCE_MS, DEFAULT_HOST, DEFAULT_PORT, FRIENDLY_HOSTNAME, GIT_DIRTY_THROTTLE_MS, GIT_MAX_REF_LENGTH, HERDR_THEME_SYNC_DEBOUNCE_MS, HTTP_STATUS_ACCEPTED, HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_CONFLICT, HTTP_STATUS_CREATED, HTTP_STATUS_NOT_FOUND, HTTP_STATUS_PAYLOAD_TOO_LARGE, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, MAX_AUTOMATIONS, MAX_IMAGE_UPLOAD_BYTES, MAX_IMAGE_UPLOAD_REQUEST_BYTES, MAX_PROCESSES, MAX_SECRETS, MS_PER_MINUTE, PROCESSES_FILENAME, SECRETS_FILENAME, THEMES_FILENAME, FONTS_FILENAME, SECRETS_SHIMS_DIRNAME, SECRET_EXPORT_SCRYPT_WORK_FACTOR, AUTOMATION_AGENT_SESSIONS_DIRNAME, SERVER_STOP_GRACE_MS, SESSION_ID_QUERY_PARAM, WORKSPACE_FILENAME, WORKSPACE_RESTORE_SETTLE_MS, WORKSPACE_SNAPSHOT_DEBOUNCE_MS, SESSION_ACTIVITY_WINDOW_MS, WINDOW_ID_QUERY_PARAM, WAIT_DEFAULT_TIMEOUT_MS, WS_BACKPRESSURE_THRESHOLD_BYTES, WS_CLOSE_BACKPRESSURE, WS_CLOSE_CAPACITY_REACHED, WS_CLOSE_POLICY_VIOLATION, WS_HEARTBEAT_GRACE_MS, WS_HEARTBEAT_INTERVAL_MS, WS_HEARTBEAT_TIMEOUT_MS, WS_MAX_INBOUND_PAYLOAD_BYTES, WS_READY_STATE_OPEN, AUTH_SECRET_FILENAME, AUTH_COOKIE_NAME, UPDATE_CHECK_FILENAME, } from "./constants.js";
|
|
25
|
+
import { ACTIVITY_DIRNAME, ACTIVITY_REFRESH_DEBOUNCE_MS, ACTIVITY_WATCHED_PROGRAMS, AUTOMATION_EVENT_DEBOUNCE_MS, AUTOMATION_RECONCILE_MIN_DOWNTIME_MS, AUTOMATION_RUN_QUERY_PARAM, AUTOMATION_WATCH_DEBOUNCE_MS, AUTOMATION_WATCH_POST_RUN_GRACE_MS, AUTOMATION_WEBHOOK_DEBOUNCE_MS, DEFAULT_HOST, DEFAULT_PORT, FRIENDLY_HOSTNAME, GIT_DIRTY_THROTTLE_MS, GIT_MAX_REF_LENGTH, HERDR_THEME_SYNC_DEBOUNCE_MS, HIBERNATE_FILENAME, HTTP_STATUS_ACCEPTED, HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_CONFLICT, HTTP_STATUS_CREATED, HTTP_STATUS_NOT_FOUND, HTTP_STATUS_PAYLOAD_TOO_LARGE, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, MAX_AUTOMATIONS, MAX_IMAGE_UPLOAD_BYTES, MAX_IMAGE_UPLOAD_REQUEST_BYTES, MAX_PROCESSES, MAX_SECRETS, MS_PER_MINUTE, PROCESSES_FILENAME, SECRETS_FILENAME, THEMES_FILENAME, FONTS_FILENAME, SECRETS_SHIMS_DIRNAME, SECRET_EXPORT_SCRYPT_WORK_FACTOR, AUTOMATION_AGENT_SESSIONS_DIRNAME, SERVER_STOP_GRACE_MS, SESSION_ID_QUERY_PARAM, WORKSPACE_FILENAME, WORKSPACE_RESTORE_SETTLE_MS, WORKSPACE_SNAPSHOT_DEBOUNCE_MS, SESSION_ACTIVITY_WINDOW_MS, WINDOW_ID_QUERY_PARAM, WAIT_DEFAULT_TIMEOUT_MS, WS_BACKPRESSURE_THRESHOLD_BYTES, WS_CLOSE_BACKPRESSURE, WS_CLOSE_CAPACITY_REACHED, WS_CLOSE_POLICY_VIOLATION, WS_HEARTBEAT_GRACE_MS, WS_HEARTBEAT_INTERVAL_MS, WS_HEARTBEAT_TIMEOUT_MS, WS_MAX_INBOUND_PAYLOAD_BYTES, WS_READY_STATE_OPEN, AUTH_SECRET_FILENAME, AUTH_COOKIE_NAME, UPDATE_CHECK_FILENAME, } from "./constants.js";
|
|
26
26
|
import { getDefaultShell, listKnownShells, resolveShellOverride } from "./default-shell.js";
|
|
27
27
|
import { resolveWindowId } from "./utils/resolve-window-id.js";
|
|
28
28
|
import { resolveTermBackspaceSequence } from "./utils/resolve-term-backspace-sequence.js";
|
|
@@ -39,6 +39,7 @@ import { SessionEventManager } from "./session-event-manager.js";
|
|
|
39
39
|
import { WebhookTriggerManager } from "./webhook-trigger-manager.js";
|
|
40
40
|
import { getGitBranchInfo, getGitBranchPr, getGitDiff, getGitDiffFileContents, getGitDiffFilePatch, getGitDiffFiles, getGitDiffSummary, } from "./git-diff.js";
|
|
41
41
|
import { HeartbeatStore } from "./heartbeat-store.js";
|
|
42
|
+
import { HibernateStore } from "./hibernate-store.js";
|
|
42
43
|
import { WorkspaceStore } from "./workspace-store.js";
|
|
43
44
|
import { createDefaultSecretBackend } from "./secret-backend.js";
|
|
44
45
|
import { SecretStore } from "./secret-store.js";
|
|
@@ -1770,6 +1771,10 @@ export const createServer = async (options = {}) => {
|
|
|
1770
1771
|
const caffeinatePreferencesStore = new CaffeinatePreferencesStore(path.join(stateDirectory, "caffeinate.json"));
|
|
1771
1772
|
const worktreeConfigStore = new WorktreeConfigStore(stateDirectory);
|
|
1772
1773
|
const workspaceStore = new WorkspaceStore(path.join(stateDirectory, WORKSPACE_FILENAME));
|
|
1774
|
+
const hibernateStore = new HibernateStore(path.join(stateDirectory, HIBERNATE_FILENAME));
|
|
1775
|
+
// Immutable shutdown snapshot for this daemon lifetime. Exact old session ids
|
|
1776
|
+
// let surviving or CDP-restored browser tabs recover only their own text.
|
|
1777
|
+
const startupHibernateEntries = hibernateStore.read();
|
|
1773
1778
|
// Per-process secret injection: a backend (macOS Keychain on darwin) holds
|
|
1774
1779
|
// secret values; a secret is an identity + the env var it exports
|
|
1775
1780
|
// (~/.localterm/secrets.json, names + env var only — never values), and a
|
|
@@ -2355,14 +2360,23 @@ export const createServer = async (options = {}) => {
|
|
|
2355
2360
|
}
|
|
2356
2361
|
workspaceStore.write(registry.workspaceEntries());
|
|
2357
2362
|
};
|
|
2358
|
-
const buildSpawnTabUrl = (cwd, shell) => {
|
|
2363
|
+
const buildSpawnTabUrl = (cwd, shell, sessionId) => {
|
|
2359
2364
|
const url = new URL(localOrigin ?? publicOrigin ?? `http://${FRIENDLY_HOSTNAME}:${actualPort}`);
|
|
2360
2365
|
if (cwd)
|
|
2361
2366
|
url.searchParams.set("cwd", cwd);
|
|
2362
2367
|
if (shell)
|
|
2363
2368
|
url.searchParams.set("shell", shell);
|
|
2369
|
+
if (sessionId)
|
|
2370
|
+
url.searchParams.set(SESSION_ID_QUERY_PARAM, sessionId);
|
|
2364
2371
|
return url.toString();
|
|
2365
2372
|
};
|
|
2373
|
+
const hibernatedTabFor = (owner, windowId, sessionId) => {
|
|
2374
|
+
if (!windowId || !sessionId)
|
|
2375
|
+
return undefined;
|
|
2376
|
+
return startupHibernateEntries
|
|
2377
|
+
.find((entry) => entry.owner === owner && entry.windowId === windowId)
|
|
2378
|
+
?.tabs.find((tab) => tab.sessionId === sessionId);
|
|
2379
|
+
};
|
|
2366
2380
|
const restoredWorkspaceKeys = new Set();
|
|
2367
2381
|
const workspaceRestoreTimers = new Map();
|
|
2368
2382
|
const scheduleWorkspaceRestore = (owner, windowId) => {
|
|
@@ -2389,45 +2403,42 @@ export const createServer = async (options = {}) => {
|
|
|
2389
2403
|
return;
|
|
2390
2404
|
if (!cdpClient || !cdpClient.isConnected())
|
|
2391
2405
|
return;
|
|
2392
|
-
const
|
|
2406
|
+
const hibernatedEntry = startupHibernateEntries.find((candidate) => candidate.owner === owner && candidate.windowId === windowId);
|
|
2407
|
+
const workspaceEntry = workspaceStore
|
|
2393
2408
|
.read()
|
|
2394
2409
|
.find((candidate) => candidate.owner === owner && candidate.windowId === windowId);
|
|
2395
|
-
|
|
2410
|
+
const manifest = hibernatedEntry?.tabs ?? workspaceEntry?.tabs ?? [];
|
|
2411
|
+
if (manifest.length === 0)
|
|
2396
2412
|
return;
|
|
2397
|
-
const
|
|
2413
|
+
const urlFor = (index) => {
|
|
2414
|
+
const tab = manifest[index];
|
|
2415
|
+
const sessionId = "sessionId" in tab && typeof tab.sessionId === "string" ? tab.sessionId : undefined;
|
|
2416
|
+
return buildSpawnTabUrl(tab.cwd, tab.shell, sessionId);
|
|
2417
|
+
};
|
|
2398
2418
|
const openCount = registry.attachedClientCount(owner, windowId);
|
|
2399
2419
|
if (openCount >= manifest.length)
|
|
2400
2420
|
return;
|
|
2401
2421
|
if (openCount === 0) {
|
|
2402
|
-
for (
|
|
2403
|
-
await cdpClient.openBackgroundTab(
|
|
2422
|
+
for (let index = 0; index < manifest.length; index += 1) {
|
|
2423
|
+
await cdpClient.openBackgroundTab(urlFor(index));
|
|
2404
2424
|
}
|
|
2405
2425
|
return;
|
|
2406
2426
|
}
|
|
2407
2427
|
if (openCount === 1) {
|
|
2408
|
-
// Browser was fully closed; the lone bootstrap
|
|
2409
|
-
// first restored shell (navigate-the-bootstrap) so the reopen lands
|
|
2410
|
-
// exactly N tabs in the manifest's cwds instead of N−1 + one stray in
|
|
2411
|
-
// the default directory.
|
|
2428
|
+
// Browser was fully closed; repoint the lone bootstrap to the first tab.
|
|
2412
2429
|
const firstTargetId = [...wsToTargetId.entries()].find(([ws]) => {
|
|
2413
2430
|
const profile = registry.clientProfile(ws);
|
|
2414
2431
|
return profile !== null && profile.owner === owner && profile.windowId === windowId;
|
|
2415
2432
|
})?.[1];
|
|
2416
|
-
if (firstTargetId)
|
|
2417
|
-
await cdpClient.navigateTab(firstTargetId,
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
await cdpClient.openBackgroundTab(buildSpawnTabUrl(manifest[index].cwd, manifest[index].shell));
|
|
2433
|
+
if (firstTargetId)
|
|
2434
|
+
await cdpClient.navigateTab(firstTargetId, urlFor(0));
|
|
2435
|
+
for (let index = 1; index < manifest.length; index += 1) {
|
|
2436
|
+
await cdpClient.openBackgroundTab(urlFor(index));
|
|
2421
2437
|
}
|
|
2422
2438
|
return;
|
|
2423
2439
|
}
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
// manifest cwds the survivors cover can't be matched (their URLs carry the
|
|
2427
|
-
// spawn cwd, stale after a `cd`), so the tail is opened as a best-effort
|
|
2428
|
-
// placement — the count is exact, the cwd placement is approximate.
|
|
2429
|
-
for (let index = openCount; index < manifest.length; index++) {
|
|
2430
|
-
await cdpClient.openBackgroundTab(buildSpawnTabUrl(manifest[index].cwd, manifest[index].shell));
|
|
2440
|
+
for (let index = openCount; index < manifest.length; index += 1) {
|
|
2441
|
+
await cdpClient.openBackgroundTab(urlFor(index));
|
|
2431
2442
|
}
|
|
2432
2443
|
};
|
|
2433
2444
|
const updateCheckStore = new UpdateCheckStore({
|
|
@@ -2603,6 +2614,9 @@ export const createServer = async (options = {}) => {
|
|
|
2603
2614
|
/* automation cwd vanished since creation; fall back to default */
|
|
2604
2615
|
}
|
|
2605
2616
|
}
|
|
2617
|
+
const hibernatedTab = claimedRun || requestedInitialCommand
|
|
2618
|
+
? undefined
|
|
2619
|
+
: hibernatedTabFor(owner, requestedWindowId, requestedSid);
|
|
2606
2620
|
const automation = claimedRun
|
|
2607
2621
|
? {
|
|
2608
2622
|
automationId: claimedRun.automationId,
|
|
@@ -2611,8 +2625,9 @@ export const createServer = async (options = {}) => {
|
|
|
2611
2625
|
}
|
|
2612
2626
|
: undefined;
|
|
2613
2627
|
const spawned = registry.spawnAndAttach(ws, {
|
|
2614
|
-
cwd: sessionCwd,
|
|
2615
|
-
shell: requestedShell,
|
|
2628
|
+
cwd: hibernatedTab?.cwd ?? sessionCwd,
|
|
2629
|
+
shell: hibernatedTab?.shell ?? requestedShell,
|
|
2630
|
+
replaySeed: hibernatedTab?.scrollback,
|
|
2616
2631
|
initialCommand: claimedRun && claimedRun.runner.kind === "shell"
|
|
2617
2632
|
? claimedRun.runner.command
|
|
2618
2633
|
: requestedInitialCommand,
|
|
@@ -2905,58 +2920,65 @@ export const createServer = async (options = {}) => {
|
|
|
2905
2920
|
// No debug-enabled Chromium browser reachable — runs use `open -g`.
|
|
2906
2921
|
});
|
|
2907
2922
|
}
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2923
|
+
let stopPromise = null;
|
|
2924
|
+
const stop = () => {
|
|
2925
|
+
if (stopPromise)
|
|
2926
|
+
return stopPromise;
|
|
2927
|
+
stopPromise = (async () => {
|
|
2928
|
+
flushWorkspaceSnapshot();
|
|
2929
|
+
hibernateStore.write(await registry.hibernateEntries());
|
|
2930
|
+
automationScheduler.dispose();
|
|
2931
|
+
folderWatchManager.dispose();
|
|
2932
|
+
automationGitWatcher.dispose();
|
|
2933
|
+
updateCheckStore.dispose();
|
|
2934
|
+
webhookTriggerManager.dispose();
|
|
2935
|
+
caffeinateManager.dispose();
|
|
2936
|
+
processActivityWatcher?.dispose();
|
|
2937
|
+
herdrThemeSync?.dispose();
|
|
2938
|
+
cdpClient?.close();
|
|
2939
|
+
registry.disposeAll();
|
|
2940
|
+
// Forcibly tear down every WS first. node-pty + ws upgraded sockets
|
|
2941
|
+
// aren't tracked in http.Server's keep-alive set, so target.close() would
|
|
2942
|
+
// otherwise wait forever for them and the CLI's force-exit fallback would
|
|
2943
|
+
// fire on every shutdown.
|
|
2944
|
+
for (const client of wss.clients) {
|
|
2945
|
+
try {
|
|
2946
|
+
client.terminate();
|
|
2947
|
+
}
|
|
2948
|
+
catch {
|
|
2949
|
+
/* socket already torn down */
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2925
2952
|
try {
|
|
2926
|
-
|
|
2953
|
+
wss.close();
|
|
2927
2954
|
}
|
|
2928
2955
|
catch {
|
|
2929
|
-
/*
|
|
2956
|
+
/* idempotent close — wss may already be closed */
|
|
2930
2957
|
}
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
};
|
|
2953
|
-
const grace = setTimeout(settle, SERVER_STOP_GRACE_MS);
|
|
2954
|
-
grace.unref?.();
|
|
2955
|
-
target.close(() => {
|
|
2956
|
-
clearTimeout(grace);
|
|
2957
|
-
settle();
|
|
2958
|
+
if (!httpServer)
|
|
2959
|
+
return;
|
|
2960
|
+
const target = httpServer;
|
|
2961
|
+
const closeAllConnections = Reflect.get(target, "closeAllConnections");
|
|
2962
|
+
if (typeof closeAllConnections === "function") {
|
|
2963
|
+
closeAllConnections.call(target);
|
|
2964
|
+
}
|
|
2965
|
+
await new Promise((resolve) => {
|
|
2966
|
+
let settled = false;
|
|
2967
|
+
const settle = () => {
|
|
2968
|
+
if (settled)
|
|
2969
|
+
return;
|
|
2970
|
+
settled = true;
|
|
2971
|
+
resolve();
|
|
2972
|
+
};
|
|
2973
|
+
const grace = setTimeout(settle, SERVER_STOP_GRACE_MS);
|
|
2974
|
+
grace.unref?.();
|
|
2975
|
+
target.close(() => {
|
|
2976
|
+
clearTimeout(grace);
|
|
2977
|
+
settle();
|
|
2978
|
+
});
|
|
2958
2979
|
});
|
|
2959
|
-
});
|
|
2980
|
+
})();
|
|
2981
|
+
return stopPromise;
|
|
2960
2982
|
};
|
|
2961
2983
|
return { port: actualPort, host, registry, automationStore, setPublicUrl, setLocalUrl, stop };
|
|
2962
2984
|
};
|