stitchkit 0.49.0 → 0.49.1
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/{index-fjfzsq6y.js → index-z992nfbx.js} +47 -24
- package/dist/node.js +1 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/index.js +20 -18
- package/dist/server/shutdown.d.ts +1 -0
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/server/websocket.d.ts +1 -1
- package/llms-full.txt +16 -7
- package/package.json +1 -1
|
@@ -1409,6 +1409,7 @@ var ShutdownStateSchema = z.enum([
|
|
|
1409
1409
|
]);
|
|
1410
1410
|
var ShutdownOptionsSchema = z.object({
|
|
1411
1411
|
gracePeriodMs: z.number().int().nonnegative().default(30000),
|
|
1412
|
+
forceTimeoutMs: z.number().int().nonnegative().default(5000),
|
|
1412
1413
|
retryAfterSeconds: z.number().int().nonnegative().default(5),
|
|
1413
1414
|
signal: z.custom((value) => typeof value === "object" && value !== null && ("aborted" in value) && ("addEventListener" in value), "Expected an AbortSignal").optional()
|
|
1414
1415
|
});
|
|
@@ -1461,6 +1462,18 @@ function untilAbort(signal) {
|
|
|
1461
1462
|
return Promise.resolve();
|
|
1462
1463
|
return new Promise((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
1463
1464
|
}
|
|
1465
|
+
function withTimeout(promise, timeoutMs, message) {
|
|
1466
|
+
return new Promise((resolve, reject) => {
|
|
1467
|
+
const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
1468
|
+
promise.then((value) => {
|
|
1469
|
+
clearTimeout(timer);
|
|
1470
|
+
resolve(value);
|
|
1471
|
+
}, (error) => {
|
|
1472
|
+
clearTimeout(timer);
|
|
1473
|
+
reject(error);
|
|
1474
|
+
});
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1464
1477
|
function createServerLifecycle(getAdapter) {
|
|
1465
1478
|
let state = "running";
|
|
1466
1479
|
let acceptedRequests = 0;
|
|
@@ -1504,6 +1517,7 @@ function createServerLifecycle(getAdapter) {
|
|
|
1504
1517
|
shutdownPromise = new Promise((resolve, reject) => {
|
|
1505
1518
|
const phaseAbort = new AbortController;
|
|
1506
1519
|
let forcedReason;
|
|
1520
|
+
let phaseError;
|
|
1507
1521
|
const force = (reason) => {
|
|
1508
1522
|
if (forcedReason)
|
|
1509
1523
|
return;
|
|
@@ -1520,28 +1534,21 @@ function createServerLifecycle(getAdapter) {
|
|
|
1520
1534
|
parsed.signal?.removeEventListener("abort", onExternalAbort);
|
|
1521
1535
|
};
|
|
1522
1536
|
(async () => {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
await Promise.race([
|
|
1539
|
-
stopGracefully.catch((error) => {
|
|
1540
|
-
if (!forcedReason)
|
|
1541
|
-
throw error;
|
|
1542
|
-
}),
|
|
1543
|
-
untilAbort(phaseAbort.signal)
|
|
1544
|
-
]);
|
|
1537
|
+
try {
|
|
1538
|
+
await waitForZero(() => pendingApplicationRequests, phaseAbort.signal);
|
|
1539
|
+
if (!forcedReason) {
|
|
1540
|
+
state = "closing-realtime";
|
|
1541
|
+
await Promise.race([adapter.closeRealtime(), untilAbort(phaseAbort.signal)]);
|
|
1542
|
+
}
|
|
1543
|
+
if (!forcedReason) {
|
|
1544
|
+
state = "stopping-runtime";
|
|
1545
|
+
await Promise.race([adapter.stopGracefully(), untilAbort(phaseAbort.signal)]);
|
|
1546
|
+
}
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
if (!forcedReason) {
|
|
1549
|
+
phaseError = error;
|
|
1550
|
+
force("error");
|
|
1551
|
+
}
|
|
1545
1552
|
}
|
|
1546
1553
|
let pendingRequestsAtForce = 0;
|
|
1547
1554
|
let pendingWebSocketsAtForce = 0;
|
|
@@ -1549,8 +1556,24 @@ function createServerLifecycle(getAdapter) {
|
|
|
1549
1556
|
state = "stopping-runtime";
|
|
1550
1557
|
pendingRequestsAtForce = adapter.pendingRequests();
|
|
1551
1558
|
pendingWebSocketsAtForce = adapter.pendingWebSockets();
|
|
1552
|
-
|
|
1553
|
-
|
|
1559
|
+
let forceError;
|
|
1560
|
+
let forceFailed = false;
|
|
1561
|
+
try {
|
|
1562
|
+
await withTimeout(adapter.forceStop(), parsed.forceTimeoutMs, `[stitchkit] forced shutdown did not complete within ${parsed.forceTimeoutMs}ms`);
|
|
1563
|
+
} catch (error) {
|
|
1564
|
+
forceFailed = true;
|
|
1565
|
+
forceError = error;
|
|
1566
|
+
} finally {
|
|
1567
|
+
state = "forced";
|
|
1568
|
+
}
|
|
1569
|
+
if (forcedReason === "error") {
|
|
1570
|
+
if (forceFailed) {
|
|
1571
|
+
throw new AggregateError([phaseError, forceError], "[stitchkit] graceful shutdown failed and forced cleanup also failed", { cause: phaseError });
|
|
1572
|
+
}
|
|
1573
|
+
throw phaseError;
|
|
1574
|
+
}
|
|
1575
|
+
if (forceFailed)
|
|
1576
|
+
throw forceError;
|
|
1554
1577
|
} else {
|
|
1555
1578
|
state = "clean";
|
|
1556
1579
|
}
|
package/dist/node.js
CHANGED
package/dist/server/bun.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/server/bun.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAC5D,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAExD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,oBAAoB,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1D,KAAK,qBAAqB,GAAG,eAAe,SAAS;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3F,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAChF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,mBAAmB;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,iGAAiG;IACjG,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;AAE7D,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/server/bun.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAC5D,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAExD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,oBAAoB,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1D,KAAK,qBAAqB,GAAG,eAAe,SAAS;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3F,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAChF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,mBAAmB;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,iGAAiG;IACjG,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;AAE7D,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAyIrE"}
|
package/dist/server/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
parseMultipart,
|
|
17
17
|
socketIoLane,
|
|
18
18
|
webSocketLane
|
|
19
|
-
} from "../index-
|
|
19
|
+
} from "../index-z992nfbx.js";
|
|
20
20
|
import {
|
|
21
21
|
createAuthHook,
|
|
22
22
|
createBearerResolver,
|
|
@@ -83,7 +83,20 @@ function createServer(config) {
|
|
|
83
83
|
const socketRoutePrefix = socket?.route.path.replace(/\*socketPath$/, "");
|
|
84
84
|
const websocket = configuredWebSocket ?? socket?.websocket;
|
|
85
85
|
const openSockets = new Set;
|
|
86
|
+
const socketDrainWaiters = new Set;
|
|
86
87
|
let hadWebSockets = false;
|
|
88
|
+
const resolveSocketDrain = () => {
|
|
89
|
+
if (openSockets.size !== 0)
|
|
90
|
+
return;
|
|
91
|
+
for (const resolve of socketDrainWaiters)
|
|
92
|
+
resolve();
|
|
93
|
+
socketDrainWaiters.clear();
|
|
94
|
+
};
|
|
95
|
+
const waitForSocketDrain = () => {
|
|
96
|
+
if (openSockets.size === 0)
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
return new Promise((resolve) => socketDrainWaiters.add(resolve));
|
|
99
|
+
};
|
|
87
100
|
const trackedWebSocket = websocket ? {
|
|
88
101
|
...websocket,
|
|
89
102
|
open(ws) {
|
|
@@ -93,6 +106,7 @@ function createServer(config) {
|
|
|
93
106
|
},
|
|
94
107
|
close(ws, code, reason) {
|
|
95
108
|
openSockets.delete(ws);
|
|
109
|
+
resolveSocketDrain();
|
|
96
110
|
websocket.close?.(ws, code, reason);
|
|
97
111
|
}
|
|
98
112
|
} : undefined;
|
|
@@ -110,21 +124,7 @@ function createServer(config) {
|
|
|
110
124
|
const logicalClose = socket?.close();
|
|
111
125
|
for (const ws of openSockets)
|
|
112
126
|
ws.close(1001, "Server shutting down");
|
|
113
|
-
await Promise.all([
|
|
114
|
-
logicalClose,
|
|
115
|
-
new Promise((resolve) => {
|
|
116
|
-
if (openSockets.size === 0) {
|
|
117
|
-
resolve();
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const timer = setInterval(() => {
|
|
121
|
-
if (openSockets.size === 0) {
|
|
122
|
-
clearInterval(timer);
|
|
123
|
-
resolve();
|
|
124
|
-
}
|
|
125
|
-
}, 5);
|
|
126
|
-
})
|
|
127
|
-
]);
|
|
127
|
+
await Promise.all([logicalClose, waitForSocketDrain()]);
|
|
128
128
|
},
|
|
129
129
|
async stopGracefully() {
|
|
130
130
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -142,9 +142,10 @@ function createServer(config) {
|
|
|
142
142
|
await server2.stop(false);
|
|
143
143
|
},
|
|
144
144
|
async forceStop() {
|
|
145
|
-
|
|
145
|
+
const logicalClose = socket?.close();
|
|
146
|
+
const physicalClose = waitForSocketDrain();
|
|
147
|
+
for (const ws of [...openSockets])
|
|
146
148
|
ws.terminate();
|
|
147
|
-
openSockets.clear();
|
|
148
149
|
const stopping = requireRuntime().stop(true);
|
|
149
150
|
if (!hadWebSockets)
|
|
150
151
|
await stopping;
|
|
@@ -152,6 +153,7 @@ function createServer(config) {
|
|
|
152
153
|
stopping.catch(() => {
|
|
153
154
|
return;
|
|
154
155
|
});
|
|
156
|
+
await Promise.all([logicalClose, physicalClose]);
|
|
155
157
|
}
|
|
156
158
|
};
|
|
157
159
|
const lifecycle = createServerLifecycle(() => adapter);
|
|
@@ -11,6 +11,7 @@ export declare const ShutdownStateSchema: z.ZodEnum<{
|
|
|
11
11
|
export type ShutdownState = z.infer<typeof ShutdownStateSchema>;
|
|
12
12
|
export declare const ShutdownOptionsSchema: z.ZodObject<{
|
|
13
13
|
gracePeriodMs: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
forceTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
14
15
|
retryAfterSeconds: z.ZodDefault<z.ZodNumber>;
|
|
15
16
|
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
16
17
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/server/shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,mBAAmB;;;;;;;EAO9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/server/shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,mBAAmB;;;;;;;EAO9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,qBAAqB;;;;;iBAchC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;iBAM/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;iBAY/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB,CAAC,QAAQ;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,eAAe,IAAI,MAAM,CAAC;IAC1B,iBAAiB,IAAI,MAAM,CAAC;IAC5B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,UAAU,eAAe;IACvB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9D;AAqDD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,eAAe,GAAG,eAAe,CAiJxF"}
|
|
@@ -66,7 +66,7 @@ export declare function webSocketLane<TData>(lane: WebSocketLane<TData>): Compos
|
|
|
66
66
|
* [webSocketLane({ match: isPcmSocket, handlers: pcmHandlers }), socketIoLane(socket.websocket)],
|
|
67
67
|
* { maxPayloadLength: 16 * 1024 * 1024 },
|
|
68
68
|
* )
|
|
69
|
-
* createServer({ websocket: ws, rawRoutes: [
|
|
69
|
+
* createServer({ socket, websocket: ws, rawRoutes: [pcmUpgradeRoute] })
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
72
|
export declare function composeWebSocketHandlers(lanes: ComposedLane[], config?: WebSocketComposeConfig): WebSocketHandler<unknown>;
|
package/llms-full.txt
CHANGED
|
@@ -762,19 +762,24 @@ const server = createServer({ services, socket })
|
|
|
762
762
|
|
|
763
763
|
const result = await server.shutdown({
|
|
764
764
|
gracePeriodMs: 30_000,
|
|
765
|
+
forceTimeoutMs: 5_000,
|
|
765
766
|
retryAfterSeconds: 5,
|
|
766
767
|
signal: shutdownController.signal,
|
|
767
768
|
})
|
|
768
769
|
```
|
|
769
770
|
|
|
770
|
-
The first call closes HTTP and Socket.IO admission,
|
|
771
|
-
|
|
772
|
-
budget
|
|
771
|
+
The first call closes HTTP and Socket.IO admission, then gives the complete
|
|
772
|
+
graceful request/realtime/runtime chain one `gracePeriodMs` budget. If that
|
|
773
|
+
budget or the external signal forces destructive teardown, `forceTimeoutMs`
|
|
774
|
+
bounds physical completion separately. Repeated calls return the same Promise;
|
|
775
|
+
the first options win. New
|
|
773
776
|
ordinary HTTP work receives `503`, `Retry-After` and `Connection: close` outside
|
|
774
777
|
`wrapFetch`. `result.outcome` is `clean` or `forced`; a forced result preserves
|
|
775
778
|
the pending snapshot and reason while final pending counters describe the
|
|
776
|
-
post-close transport state.
|
|
777
|
-
|
|
779
|
+
post-close transport state. A graceful phase error still runs forced cleanup and
|
|
780
|
+
then rejects with the original error; a forced transport that cannot confirm
|
|
781
|
+
completion before `forceTimeoutMs` rejects instead of reporting a false zero.
|
|
782
|
+
`runtime` is a diagnostics escape hatch, not a second canonical stop path.
|
|
778
783
|
|
|
779
784
|
### Trusted HTTPS in development
|
|
780
785
|
|
|
@@ -4643,7 +4648,11 @@ function shutdown() {
|
|
|
4643
4648
|
force.abort() // a later signal shortens the same shutdown, not a second chain
|
|
4644
4649
|
return closing
|
|
4645
4650
|
}
|
|
4646
|
-
closing = server.shutdown({
|
|
4651
|
+
closing = server.shutdown({
|
|
4652
|
+
gracePeriodMs: 30_000,
|
|
4653
|
+
forceTimeoutMs: 5_000,
|
|
4654
|
+
signal: force.signal,
|
|
4655
|
+
}).then(async result => {
|
|
4647
4656
|
await mcp.close()
|
|
4648
4657
|
await prisma.$disconnect()
|
|
4649
4658
|
console.log(result)
|
|
@@ -6025,7 +6034,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
6025
6034
|
| `BunServerConfig` | _type_ | config for `createServer` (Bun) |
|
|
6026
6035
|
| `BunServerHandle` | _type_ | managed Bun handle (`url`, `port`, `runtime`, `status`, `shutdown`) |
|
|
6027
6036
|
| `ManagedServerHandle` | _type_ | shared lifecycle shape generic over the runtime escape hatch |
|
|
6028
|
-
| `ShutdownOptionsSchema` / `ShutdownOptions` | schema / _type_ | one
|
|
6037
|
+
| `ShutdownOptionsSchema` / `ShutdownOptions` | schema / _type_ | one graceful budget, bounded forced-completion timeout, retry hint and optional external abort signal |
|
|
6029
6038
|
| `ShutdownStatusSchema` / `ShutdownStatus` | schema / _type_ | live state and request/WebSocket counters |
|
|
6030
6039
|
| `ShutdownResultSchema` / `ShutdownResult` | schema / _type_ | clean/forced result with final counters and at-force snapshots |
|
|
6031
6040
|
| `ShutdownStateSchema` / `ShutdownState` | schema / _type_ | managed lifecycle state machine |
|
package/package.json
CHANGED