stitchkit 0.59.1 → 0.59.2
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/README.md +44 -4
- package/dist/application/activity.d.ts +70 -0
- package/dist/application/activity.d.ts.map +1 -0
- package/dist/application/events.d.ts +65 -0
- package/dist/application/events.d.ts.map +1 -0
- package/dist/application/grammy.d.ts +35 -0
- package/dist/application/grammy.d.ts.map +1 -0
- package/dist/application/graph.d.ts +11 -0
- package/dist/application/graph.d.ts.map +1 -0
- package/dist/application/health.d.ts +13 -0
- package/dist/application/health.d.ts.map +1 -0
- package/dist/application/kernel.d.ts +31 -0
- package/dist/application/kernel.d.ts.map +1 -0
- package/dist/application/latest-sink.d.ts +39 -0
- package/dist/application/latest-sink.d.ts.map +1 -0
- package/dist/application/resource.d.ts +30 -0
- package/dist/application/resource.d.ts.map +1 -0
- package/dist/application/schedule.d.ts +112 -0
- package/dist/application/schedule.d.ts.map +1 -0
- package/dist/application/schemas.d.ts +160 -0
- package/dist/application/schemas.d.ts.map +1 -0
- package/dist/application/server-resource.d.ts +12 -0
- package/dist/application/server-resource.d.ts.map +1 -0
- package/dist/application-grammy.d.ts +2 -0
- package/dist/application-grammy.d.ts.map +1 -0
- package/dist/application-grammy.js +165 -0
- package/dist/application.d.ts +10 -0
- package/dist/application.d.ts.map +1 -0
- package/dist/application.js +1370 -0
- package/dist/index-dk6e56g0.js +211 -0
- package/dist/{index-9zn9fb4e.js → index-he4psyve.js} +6 -213
- package/dist/index-yr276yz0.js +6 -0
- package/dist/internal/fetch-port.d.ts +2 -0
- package/dist/internal/fetch-port.d.ts.map +1 -0
- package/dist/node.js +115 -13
- package/dist/server/index.js +8 -6
- package/dist/server/node.d.ts.map +1 -1
- package/dist/server/process-signals.d.ts +10 -8
- package/dist/server/process-signals.d.ts.map +1 -1
- package/llms-full.txt +379 -0
- package/llms.txt +1 -0
- package/package.json +15 -2
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// src/server/shutdown.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var ShutdownStateSchema = z.enum([
|
|
4
|
+
"running",
|
|
5
|
+
"draining-http",
|
|
6
|
+
"closing-realtime",
|
|
7
|
+
"stopping-runtime",
|
|
8
|
+
"clean",
|
|
9
|
+
"forced"
|
|
10
|
+
]);
|
|
11
|
+
var ShutdownOptionsSchema = z.object({
|
|
12
|
+
gracePeriodMs: z.number().int().nonnegative().default(30000),
|
|
13
|
+
forceTimeoutMs: z.number().int().nonnegative().default(5000),
|
|
14
|
+
retryAfterSeconds: z.number().int().nonnegative().default(5),
|
|
15
|
+
signal: z.custom((value) => typeof value === "object" && value !== null && ("aborted" in value) && ("addEventListener" in value), "Expected an AbortSignal").optional()
|
|
16
|
+
});
|
|
17
|
+
var ShutdownStatusSchema = z.object({
|
|
18
|
+
state: ShutdownStateSchema,
|
|
19
|
+
acceptedRequests: z.number().int().nonnegative(),
|
|
20
|
+
completedRequests: z.number().int().nonnegative(),
|
|
21
|
+
pendingRequests: z.number().int().nonnegative(),
|
|
22
|
+
pendingWebSockets: z.number().int().nonnegative()
|
|
23
|
+
});
|
|
24
|
+
var ShutdownResultSchema = z.object({
|
|
25
|
+
outcome: z.enum(["clean", "forced"]),
|
|
26
|
+
reason: z.enum(["deadline", "signal"]).optional(),
|
|
27
|
+
acceptedRequests: z.number().int().nonnegative(),
|
|
28
|
+
completedRequests: z.number().int().nonnegative(),
|
|
29
|
+
pendingRequests: z.number().int().nonnegative(),
|
|
30
|
+
pendingWebSockets: z.number().int().nonnegative(),
|
|
31
|
+
pendingRequestsAtForce: z.number().int().nonnegative(),
|
|
32
|
+
pendingWebSocketsAtForce: z.number().int().nonnegative(),
|
|
33
|
+
abortedRequests: z.number().int().nonnegative(),
|
|
34
|
+
forcedWebSockets: z.number().int().nonnegative(),
|
|
35
|
+
durationMs: z.number().nonnegative()
|
|
36
|
+
});
|
|
37
|
+
function rejectedResponse(retryAfterSeconds) {
|
|
38
|
+
return Response.json({ error: { code: "SERVER_SHUTTING_DOWN", message: "Server is shutting down" } }, {
|
|
39
|
+
status: 503,
|
|
40
|
+
headers: {
|
|
41
|
+
Connection: "close",
|
|
42
|
+
"Retry-After": String(retryAfterSeconds)
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function waitForZero(read, signal) {
|
|
47
|
+
if (read() === 0)
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
const check = () => {
|
|
51
|
+
if (read() === 0 || signal.aborted) {
|
|
52
|
+
clearInterval(timer);
|
|
53
|
+
signal.removeEventListener("abort", check);
|
|
54
|
+
resolve();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const timer = setInterval(check, 5);
|
|
58
|
+
signal.addEventListener("abort", check, { once: true });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function untilAbort(signal) {
|
|
62
|
+
if (signal.aborted)
|
|
63
|
+
return Promise.resolve();
|
|
64
|
+
return new Promise((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
65
|
+
}
|
|
66
|
+
function withTimeout(promise, timeoutMs, message) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
69
|
+
promise.then((value) => {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
resolve(value);
|
|
72
|
+
}, (error) => {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
reject(error);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function createServerLifecycle(getAdapter) {
|
|
79
|
+
let state = "running";
|
|
80
|
+
let acceptedRequests = 0;
|
|
81
|
+
let completedRequests = 0;
|
|
82
|
+
let pendingApplicationRequests = 0;
|
|
83
|
+
let retryAfterSeconds = 5;
|
|
84
|
+
let shutdownPromise;
|
|
85
|
+
const status = () => {
|
|
86
|
+
const adapter = getAdapter();
|
|
87
|
+
return ShutdownStatusSchema.parse({
|
|
88
|
+
state,
|
|
89
|
+
acceptedRequests,
|
|
90
|
+
completedRequests,
|
|
91
|
+
pendingRequests: adapter.pendingRequests(),
|
|
92
|
+
pendingWebSockets: adapter.pendingWebSockets()
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const wrapFetch = (handler) => {
|
|
96
|
+
return async (request, server) => {
|
|
97
|
+
if (state !== "running")
|
|
98
|
+
return rejectedResponse(retryAfterSeconds);
|
|
99
|
+
acceptedRequests += 1;
|
|
100
|
+
pendingApplicationRequests += 1;
|
|
101
|
+
try {
|
|
102
|
+
return await handler(request, server);
|
|
103
|
+
} finally {
|
|
104
|
+
pendingApplicationRequests -= 1;
|
|
105
|
+
completedRequests += 1;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
const shutdown = (options) => {
|
|
110
|
+
if (shutdownPromise)
|
|
111
|
+
return shutdownPromise;
|
|
112
|
+
const parsed = ShutdownOptionsSchema.parse(options ?? {});
|
|
113
|
+
retryAfterSeconds = parsed.retryAfterSeconds;
|
|
114
|
+
const startedAt = performance.now();
|
|
115
|
+
const adapter = getAdapter();
|
|
116
|
+
state = "draining-http";
|
|
117
|
+
adapter.beginShutdown(retryAfterSeconds);
|
|
118
|
+
shutdownPromise = new Promise((resolve, reject) => {
|
|
119
|
+
const phaseAbort = new AbortController;
|
|
120
|
+
let forcedReason;
|
|
121
|
+
let phaseError;
|
|
122
|
+
const force = (reason) => {
|
|
123
|
+
if (forcedReason)
|
|
124
|
+
return;
|
|
125
|
+
forcedReason = reason;
|
|
126
|
+
phaseAbort.abort();
|
|
127
|
+
};
|
|
128
|
+
const timer = setTimeout(() => force("deadline"), parsed.gracePeriodMs);
|
|
129
|
+
const onExternalAbort = () => force("signal");
|
|
130
|
+
parsed.signal?.addEventListener("abort", onExternalAbort, { once: true });
|
|
131
|
+
if (parsed.signal?.aborted)
|
|
132
|
+
force("signal");
|
|
133
|
+
const cleanup = () => {
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
parsed.signal?.removeEventListener("abort", onExternalAbort);
|
|
136
|
+
};
|
|
137
|
+
(async () => {
|
|
138
|
+
try {
|
|
139
|
+
await waitForZero(() => pendingApplicationRequests, phaseAbort.signal);
|
|
140
|
+
if (!forcedReason) {
|
|
141
|
+
state = "closing-realtime";
|
|
142
|
+
await Promise.race([adapter.closeRealtime(), untilAbort(phaseAbort.signal)]);
|
|
143
|
+
}
|
|
144
|
+
if (!forcedReason) {
|
|
145
|
+
state = "stopping-runtime";
|
|
146
|
+
await Promise.race([adapter.stopGracefully(), untilAbort(phaseAbort.signal)]);
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (!forcedReason) {
|
|
150
|
+
phaseError = error;
|
|
151
|
+
force("error");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let pendingRequestsAtForce = 0;
|
|
155
|
+
let pendingWebSocketsAtForce = 0;
|
|
156
|
+
if (forcedReason) {
|
|
157
|
+
state = "stopping-runtime";
|
|
158
|
+
pendingRequestsAtForce = adapter.pendingRequests();
|
|
159
|
+
pendingWebSocketsAtForce = adapter.pendingWebSockets();
|
|
160
|
+
let forceError;
|
|
161
|
+
let forceFailed = false;
|
|
162
|
+
try {
|
|
163
|
+
await withTimeout(adapter.forceStop(), parsed.forceTimeoutMs, `[stitchkit] forced shutdown did not complete within ${parsed.forceTimeoutMs}ms`);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
forceFailed = true;
|
|
166
|
+
forceError = error;
|
|
167
|
+
} finally {
|
|
168
|
+
state = "forced";
|
|
169
|
+
}
|
|
170
|
+
if (forcedReason === "error") {
|
|
171
|
+
if (forceFailed) {
|
|
172
|
+
throw new AggregateError([phaseError, forceError], "[stitchkit] graceful shutdown failed and forced cleanup also failed", { cause: phaseError });
|
|
173
|
+
}
|
|
174
|
+
throw phaseError;
|
|
175
|
+
}
|
|
176
|
+
if (forceFailed)
|
|
177
|
+
throw forceError;
|
|
178
|
+
} else {
|
|
179
|
+
state = "clean";
|
|
180
|
+
}
|
|
181
|
+
cleanup();
|
|
182
|
+
resolve(ShutdownResultSchema.parse({
|
|
183
|
+
outcome: forcedReason ? "forced" : "clean",
|
|
184
|
+
...forcedReason && { reason: forcedReason },
|
|
185
|
+
acceptedRequests,
|
|
186
|
+
completedRequests,
|
|
187
|
+
pendingRequests: adapter.pendingRequests(),
|
|
188
|
+
pendingWebSockets: adapter.pendingWebSockets(),
|
|
189
|
+
pendingRequestsAtForce,
|
|
190
|
+
pendingWebSocketsAtForce,
|
|
191
|
+
abortedRequests: pendingRequestsAtForce,
|
|
192
|
+
forcedWebSockets: pendingWebSocketsAtForce,
|
|
193
|
+
durationMs: performance.now() - startedAt
|
|
194
|
+
}));
|
|
195
|
+
})().catch((error) => {
|
|
196
|
+
cleanup();
|
|
197
|
+
reject(error);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
return shutdownPromise;
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
wrapFetch,
|
|
204
|
+
get status() {
|
|
205
|
+
return status();
|
|
206
|
+
},
|
|
207
|
+
shutdown
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { ShutdownStateSchema, ShutdownOptionsSchema, ShutdownStatusSchema, ShutdownResultSchema, createServerLifecycle };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ShutdownOptionsSchema
|
|
3
|
+
} from "./index-dk6e56g0.js";
|
|
1
4
|
import {
|
|
2
5
|
DEFAULT_PROCESS_SIGNALS,
|
|
3
6
|
RUNTIME_CONTEXT_RESERVED_KEYS,
|
|
@@ -1457,216 +1460,6 @@ function json(data, status, cors, req) {
|
|
|
1457
1460
|
return Response.json(data, { status, headers: corsHeaders2(cors, req) });
|
|
1458
1461
|
}
|
|
1459
1462
|
|
|
1460
|
-
// src/server/shutdown.ts
|
|
1461
|
-
import { z } from "zod";
|
|
1462
|
-
var ShutdownStateSchema = z.enum([
|
|
1463
|
-
"running",
|
|
1464
|
-
"draining-http",
|
|
1465
|
-
"closing-realtime",
|
|
1466
|
-
"stopping-runtime",
|
|
1467
|
-
"clean",
|
|
1468
|
-
"forced"
|
|
1469
|
-
]);
|
|
1470
|
-
var ShutdownOptionsSchema = z.object({
|
|
1471
|
-
gracePeriodMs: z.number().int().nonnegative().default(30000),
|
|
1472
|
-
forceTimeoutMs: z.number().int().nonnegative().default(5000),
|
|
1473
|
-
retryAfterSeconds: z.number().int().nonnegative().default(5),
|
|
1474
|
-
signal: z.custom((value) => typeof value === "object" && value !== null && ("aborted" in value) && ("addEventListener" in value), "Expected an AbortSignal").optional()
|
|
1475
|
-
});
|
|
1476
|
-
var ShutdownStatusSchema = z.object({
|
|
1477
|
-
state: ShutdownStateSchema,
|
|
1478
|
-
acceptedRequests: z.number().int().nonnegative(),
|
|
1479
|
-
completedRequests: z.number().int().nonnegative(),
|
|
1480
|
-
pendingRequests: z.number().int().nonnegative(),
|
|
1481
|
-
pendingWebSockets: z.number().int().nonnegative()
|
|
1482
|
-
});
|
|
1483
|
-
var ShutdownResultSchema = z.object({
|
|
1484
|
-
outcome: z.enum(["clean", "forced"]),
|
|
1485
|
-
reason: z.enum(["deadline", "signal"]).optional(),
|
|
1486
|
-
acceptedRequests: z.number().int().nonnegative(),
|
|
1487
|
-
completedRequests: z.number().int().nonnegative(),
|
|
1488
|
-
pendingRequests: z.number().int().nonnegative(),
|
|
1489
|
-
pendingWebSockets: z.number().int().nonnegative(),
|
|
1490
|
-
pendingRequestsAtForce: z.number().int().nonnegative(),
|
|
1491
|
-
pendingWebSocketsAtForce: z.number().int().nonnegative(),
|
|
1492
|
-
abortedRequests: z.number().int().nonnegative(),
|
|
1493
|
-
forcedWebSockets: z.number().int().nonnegative(),
|
|
1494
|
-
durationMs: z.number().nonnegative()
|
|
1495
|
-
});
|
|
1496
|
-
function rejectedResponse(retryAfterSeconds) {
|
|
1497
|
-
return Response.json({ error: { code: "SERVER_SHUTTING_DOWN", message: "Server is shutting down" } }, {
|
|
1498
|
-
status: 503,
|
|
1499
|
-
headers: {
|
|
1500
|
-
Connection: "close",
|
|
1501
|
-
"Retry-After": String(retryAfterSeconds)
|
|
1502
|
-
}
|
|
1503
|
-
});
|
|
1504
|
-
}
|
|
1505
|
-
function waitForZero(read, signal) {
|
|
1506
|
-
if (read() === 0)
|
|
1507
|
-
return Promise.resolve();
|
|
1508
|
-
return new Promise((resolve) => {
|
|
1509
|
-
const check = () => {
|
|
1510
|
-
if (read() === 0 || signal.aborted) {
|
|
1511
|
-
clearInterval(timer);
|
|
1512
|
-
signal.removeEventListener("abort", check);
|
|
1513
|
-
resolve();
|
|
1514
|
-
}
|
|
1515
|
-
};
|
|
1516
|
-
const timer = setInterval(check, 5);
|
|
1517
|
-
signal.addEventListener("abort", check, { once: true });
|
|
1518
|
-
});
|
|
1519
|
-
}
|
|
1520
|
-
function untilAbort(signal) {
|
|
1521
|
-
if (signal.aborted)
|
|
1522
|
-
return Promise.resolve();
|
|
1523
|
-
return new Promise((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
1524
|
-
}
|
|
1525
|
-
function withTimeout(promise, timeoutMs, message) {
|
|
1526
|
-
return new Promise((resolve, reject) => {
|
|
1527
|
-
const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
1528
|
-
promise.then((value) => {
|
|
1529
|
-
clearTimeout(timer);
|
|
1530
|
-
resolve(value);
|
|
1531
|
-
}, (error) => {
|
|
1532
|
-
clearTimeout(timer);
|
|
1533
|
-
reject(error);
|
|
1534
|
-
});
|
|
1535
|
-
});
|
|
1536
|
-
}
|
|
1537
|
-
function createServerLifecycle(getAdapter) {
|
|
1538
|
-
let state = "running";
|
|
1539
|
-
let acceptedRequests = 0;
|
|
1540
|
-
let completedRequests = 0;
|
|
1541
|
-
let pendingApplicationRequests = 0;
|
|
1542
|
-
let retryAfterSeconds = 5;
|
|
1543
|
-
let shutdownPromise;
|
|
1544
|
-
const status = () => {
|
|
1545
|
-
const adapter = getAdapter();
|
|
1546
|
-
return ShutdownStatusSchema.parse({
|
|
1547
|
-
state,
|
|
1548
|
-
acceptedRequests,
|
|
1549
|
-
completedRequests,
|
|
1550
|
-
pendingRequests: adapter.pendingRequests(),
|
|
1551
|
-
pendingWebSockets: adapter.pendingWebSockets()
|
|
1552
|
-
});
|
|
1553
|
-
};
|
|
1554
|
-
const wrapFetch = (handler) => {
|
|
1555
|
-
return async (request, server) => {
|
|
1556
|
-
if (state !== "running")
|
|
1557
|
-
return rejectedResponse(retryAfterSeconds);
|
|
1558
|
-
acceptedRequests += 1;
|
|
1559
|
-
pendingApplicationRequests += 1;
|
|
1560
|
-
try {
|
|
1561
|
-
return await handler(request, server);
|
|
1562
|
-
} finally {
|
|
1563
|
-
pendingApplicationRequests -= 1;
|
|
1564
|
-
completedRequests += 1;
|
|
1565
|
-
}
|
|
1566
|
-
};
|
|
1567
|
-
};
|
|
1568
|
-
const shutdown = (options) => {
|
|
1569
|
-
if (shutdownPromise)
|
|
1570
|
-
return shutdownPromise;
|
|
1571
|
-
const parsed = ShutdownOptionsSchema.parse(options ?? {});
|
|
1572
|
-
retryAfterSeconds = parsed.retryAfterSeconds;
|
|
1573
|
-
const startedAt = performance.now();
|
|
1574
|
-
const adapter = getAdapter();
|
|
1575
|
-
state = "draining-http";
|
|
1576
|
-
adapter.beginShutdown(retryAfterSeconds);
|
|
1577
|
-
shutdownPromise = new Promise((resolve, reject) => {
|
|
1578
|
-
const phaseAbort = new AbortController;
|
|
1579
|
-
let forcedReason;
|
|
1580
|
-
let phaseError;
|
|
1581
|
-
const force = (reason) => {
|
|
1582
|
-
if (forcedReason)
|
|
1583
|
-
return;
|
|
1584
|
-
forcedReason = reason;
|
|
1585
|
-
phaseAbort.abort();
|
|
1586
|
-
};
|
|
1587
|
-
const timer = setTimeout(() => force("deadline"), parsed.gracePeriodMs);
|
|
1588
|
-
const onExternalAbort = () => force("signal");
|
|
1589
|
-
parsed.signal?.addEventListener("abort", onExternalAbort, { once: true });
|
|
1590
|
-
if (parsed.signal?.aborted)
|
|
1591
|
-
force("signal");
|
|
1592
|
-
const cleanup = () => {
|
|
1593
|
-
clearTimeout(timer);
|
|
1594
|
-
parsed.signal?.removeEventListener("abort", onExternalAbort);
|
|
1595
|
-
};
|
|
1596
|
-
(async () => {
|
|
1597
|
-
try {
|
|
1598
|
-
await waitForZero(() => pendingApplicationRequests, phaseAbort.signal);
|
|
1599
|
-
if (!forcedReason) {
|
|
1600
|
-
state = "closing-realtime";
|
|
1601
|
-
await Promise.race([adapter.closeRealtime(), untilAbort(phaseAbort.signal)]);
|
|
1602
|
-
}
|
|
1603
|
-
if (!forcedReason) {
|
|
1604
|
-
state = "stopping-runtime";
|
|
1605
|
-
await Promise.race([adapter.stopGracefully(), untilAbort(phaseAbort.signal)]);
|
|
1606
|
-
}
|
|
1607
|
-
} catch (error) {
|
|
1608
|
-
if (!forcedReason) {
|
|
1609
|
-
phaseError = error;
|
|
1610
|
-
force("error");
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
let pendingRequestsAtForce = 0;
|
|
1614
|
-
let pendingWebSocketsAtForce = 0;
|
|
1615
|
-
if (forcedReason) {
|
|
1616
|
-
state = "stopping-runtime";
|
|
1617
|
-
pendingRequestsAtForce = adapter.pendingRequests();
|
|
1618
|
-
pendingWebSocketsAtForce = adapter.pendingWebSockets();
|
|
1619
|
-
let forceError;
|
|
1620
|
-
let forceFailed = false;
|
|
1621
|
-
try {
|
|
1622
|
-
await withTimeout(adapter.forceStop(), parsed.forceTimeoutMs, `[stitchkit] forced shutdown did not complete within ${parsed.forceTimeoutMs}ms`);
|
|
1623
|
-
} catch (error) {
|
|
1624
|
-
forceFailed = true;
|
|
1625
|
-
forceError = error;
|
|
1626
|
-
} finally {
|
|
1627
|
-
state = "forced";
|
|
1628
|
-
}
|
|
1629
|
-
if (forcedReason === "error") {
|
|
1630
|
-
if (forceFailed) {
|
|
1631
|
-
throw new AggregateError([phaseError, forceError], "[stitchkit] graceful shutdown failed and forced cleanup also failed", { cause: phaseError });
|
|
1632
|
-
}
|
|
1633
|
-
throw phaseError;
|
|
1634
|
-
}
|
|
1635
|
-
if (forceFailed)
|
|
1636
|
-
throw forceError;
|
|
1637
|
-
} else {
|
|
1638
|
-
state = "clean";
|
|
1639
|
-
}
|
|
1640
|
-
cleanup();
|
|
1641
|
-
resolve(ShutdownResultSchema.parse({
|
|
1642
|
-
outcome: forcedReason ? "forced" : "clean",
|
|
1643
|
-
...forcedReason && { reason: forcedReason },
|
|
1644
|
-
acceptedRequests,
|
|
1645
|
-
completedRequests,
|
|
1646
|
-
pendingRequests: adapter.pendingRequests(),
|
|
1647
|
-
pendingWebSockets: adapter.pendingWebSockets(),
|
|
1648
|
-
pendingRequestsAtForce,
|
|
1649
|
-
pendingWebSocketsAtForce,
|
|
1650
|
-
abortedRequests: pendingRequestsAtForce,
|
|
1651
|
-
forcedWebSockets: pendingWebSocketsAtForce,
|
|
1652
|
-
durationMs: performance.now() - startedAt
|
|
1653
|
-
}));
|
|
1654
|
-
})().catch((error) => {
|
|
1655
|
-
cleanup();
|
|
1656
|
-
reject(error);
|
|
1657
|
-
});
|
|
1658
|
-
});
|
|
1659
|
-
return shutdownPromise;
|
|
1660
|
-
};
|
|
1661
|
-
return {
|
|
1662
|
-
wrapFetch,
|
|
1663
|
-
get status() {
|
|
1664
|
-
return status();
|
|
1665
|
-
},
|
|
1666
|
-
shutdown
|
|
1667
|
-
};
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
1463
|
// src/server/process-signals.ts
|
|
1671
1464
|
var bound = new WeakSet;
|
|
1672
1465
|
function bindProcessSignals(handle, options = {}) {
|
|
@@ -1775,9 +1568,9 @@ function bindProcessSignals(handle, options = {}) {
|
|
|
1775
1568
|
}
|
|
1776
1569
|
|
|
1777
1570
|
// src/realtime/rejection.ts
|
|
1778
|
-
import { z
|
|
1571
|
+
import { z } from "zod";
|
|
1779
1572
|
function realtimeContractViolation(options) {
|
|
1780
|
-
const issues = options.cause instanceof
|
|
1573
|
+
const issues = options.cause instanceof z.ZodError ? zodIssues(options.cause) : undefined;
|
|
1781
1574
|
const reason = options.reason.replaceAll("-", " ");
|
|
1782
1575
|
const error = new AppError("REALTIME_CONTRACT_VIOLATION", `Realtime event "${options.event}" (${options.direction}, ${options.phase}): ${reason}`, 500, {
|
|
1783
1576
|
event: options.event,
|
|
@@ -2227,4 +2020,4 @@ function socketIoLane(websocket) {
|
|
|
2227
2020
|
});
|
|
2228
2021
|
}
|
|
2229
2022
|
|
|
2230
|
-
export { parseMultipart, createHandler,
|
|
2023
|
+
export { parseMultipart, createHandler, bindProcessSignals, bindRealtimeServer, webSocketLane, composeWebSocketHandlers, createSocketIOServer, socketIoLane };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-port.d.ts","sourceRoot":"","sources":["../../src/internal/fetch-port.ts"],"names":[],"mappings":"AAaA,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD"}
|
package/dist/node.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ShutdownOptionsSchema,
|
|
3
|
-
ShutdownResultSchema,
|
|
4
|
-
ShutdownStateSchema,
|
|
5
|
-
ShutdownStatusSchema,
|
|
6
2
|
bindProcessSignals,
|
|
7
3
|
bindRealtimeServer,
|
|
8
4
|
createHandler,
|
|
9
|
-
createServerLifecycle,
|
|
10
5
|
createSocketIOServer
|
|
11
|
-
} from "./index-
|
|
6
|
+
} from "./index-he4psyve.js";
|
|
7
|
+
import {
|
|
8
|
+
ShutdownOptionsSchema,
|
|
9
|
+
ShutdownResultSchema,
|
|
10
|
+
ShutdownStateSchema,
|
|
11
|
+
ShutdownStatusSchema,
|
|
12
|
+
createServerLifecycle
|
|
13
|
+
} from "./index-dk6e56g0.js";
|
|
12
14
|
import {
|
|
13
15
|
createImplement,
|
|
14
16
|
createImplementRegistry,
|
|
@@ -36,6 +38,97 @@ import"./index-smpbdg6k.js";
|
|
|
36
38
|
import"./index-1bx83sw4.js";
|
|
37
39
|
// src/server/node.ts
|
|
38
40
|
import { serve } from "srvx/node";
|
|
41
|
+
|
|
42
|
+
// src/internal/fetch-port.ts
|
|
43
|
+
var FETCH_BLOCKED_PORTS = new Set([
|
|
44
|
+
1,
|
|
45
|
+
7,
|
|
46
|
+
9,
|
|
47
|
+
11,
|
|
48
|
+
13,
|
|
49
|
+
15,
|
|
50
|
+
17,
|
|
51
|
+
19,
|
|
52
|
+
20,
|
|
53
|
+
21,
|
|
54
|
+
22,
|
|
55
|
+
23,
|
|
56
|
+
25,
|
|
57
|
+
37,
|
|
58
|
+
42,
|
|
59
|
+
43,
|
|
60
|
+
53,
|
|
61
|
+
69,
|
|
62
|
+
77,
|
|
63
|
+
79,
|
|
64
|
+
87,
|
|
65
|
+
95,
|
|
66
|
+
101,
|
|
67
|
+
102,
|
|
68
|
+
103,
|
|
69
|
+
104,
|
|
70
|
+
109,
|
|
71
|
+
110,
|
|
72
|
+
111,
|
|
73
|
+
113,
|
|
74
|
+
115,
|
|
75
|
+
117,
|
|
76
|
+
119,
|
|
77
|
+
123,
|
|
78
|
+
135,
|
|
79
|
+
137,
|
|
80
|
+
139,
|
|
81
|
+
143,
|
|
82
|
+
161,
|
|
83
|
+
179,
|
|
84
|
+
389,
|
|
85
|
+
427,
|
|
86
|
+
465,
|
|
87
|
+
512,
|
|
88
|
+
513,
|
|
89
|
+
514,
|
|
90
|
+
515,
|
|
91
|
+
526,
|
|
92
|
+
530,
|
|
93
|
+
531,
|
|
94
|
+
532,
|
|
95
|
+
540,
|
|
96
|
+
548,
|
|
97
|
+
554,
|
|
98
|
+
556,
|
|
99
|
+
563,
|
|
100
|
+
587,
|
|
101
|
+
601,
|
|
102
|
+
636,
|
|
103
|
+
989,
|
|
104
|
+
990,
|
|
105
|
+
993,
|
|
106
|
+
995,
|
|
107
|
+
1719,
|
|
108
|
+
1720,
|
|
109
|
+
1723,
|
|
110
|
+
2049,
|
|
111
|
+
3659,
|
|
112
|
+
4045,
|
|
113
|
+
4190,
|
|
114
|
+
5060,
|
|
115
|
+
5061,
|
|
116
|
+
6000,
|
|
117
|
+
6566,
|
|
118
|
+
6665,
|
|
119
|
+
6666,
|
|
120
|
+
6667,
|
|
121
|
+
6668,
|
|
122
|
+
6669,
|
|
123
|
+
6679,
|
|
124
|
+
6697,
|
|
125
|
+
10080
|
|
126
|
+
]);
|
|
127
|
+
function isFetchBlockedPort(port) {
|
|
128
|
+
return FETCH_BLOCKED_PORTS.has(port);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/server/node.ts
|
|
39
132
|
async function serveNode(config) {
|
|
40
133
|
const { port = 3000, hostname, socket, wrapFetch, ...handlerConfig } = config;
|
|
41
134
|
const handler = createHandler(handlerConfig);
|
|
@@ -101,14 +194,23 @@ async function serveNode(config) {
|
|
|
101
194
|
const lifecycle = createServerLifecycle(() => adapter);
|
|
102
195
|
const consumerFetch = wrapFetch ? wrapFetch(handler) : handler;
|
|
103
196
|
const fetch = lifecycle.wrapFetch(consumerFetch);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
197
|
+
for (;; ) {
|
|
198
|
+
runtime = serve({ port, hostname, fetch, gracefulShutdown: false });
|
|
199
|
+
await runtime.ready();
|
|
200
|
+
const candidate = runtime.node?.server;
|
|
201
|
+
if (!candidate || !("maxRequestsPerSocket" in candidate)) {
|
|
202
|
+
await runtime.close(true);
|
|
203
|
+
throw new Error("[stitchkit] serveNode: expected a node:http.Server for the managed lifecycle.");
|
|
204
|
+
}
|
|
205
|
+
const candidateUrl = runtime.url ?? `http://${hostname ?? "localhost"}:${port}`;
|
|
206
|
+
const candidatePort = Number(new URL(candidateUrl).port) || port;
|
|
207
|
+
if (port === 0 && isFetchBlockedPort(candidatePort)) {
|
|
208
|
+
await runtime.close(true);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
nodeServer = candidate;
|
|
212
|
+
break;
|
|
110
213
|
}
|
|
111
|
-
nodeServer = candidate;
|
|
112
214
|
nodeServer.on("connection", (activeSocket) => {
|
|
113
215
|
sockets.add(activeSocket);
|
|
114
216
|
activeSocket.once("close", () => {
|
package/dist/server/index.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ShutdownOptionsSchema,
|
|
3
|
-
ShutdownResultSchema,
|
|
4
|
-
ShutdownStateSchema,
|
|
5
|
-
ShutdownStatusSchema,
|
|
6
2
|
bindProcessSignals,
|
|
7
3
|
bindRealtimeServer,
|
|
8
4
|
composeWebSocketHandlers,
|
|
9
5
|
createHandler,
|
|
10
|
-
createServerLifecycle,
|
|
11
6
|
createSocketIOServer,
|
|
12
7
|
parseMultipart,
|
|
13
8
|
socketIoLane,
|
|
14
9
|
webSocketLane
|
|
15
|
-
} from "../index-
|
|
10
|
+
} from "../index-he4psyve.js";
|
|
11
|
+
import {
|
|
12
|
+
ShutdownOptionsSchema,
|
|
13
|
+
ShutdownResultSchema,
|
|
14
|
+
ShutdownStateSchema,
|
|
15
|
+
ShutdownStatusSchema,
|
|
16
|
+
createServerLifecycle
|
|
17
|
+
} from "../index-dk6e56g0.js";
|
|
16
18
|
import {
|
|
17
19
|
composeAuthHooks,
|
|
18
20
|
createAuthHook,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/server/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAkB,MAAM,WAAW,CAAC;AAEtE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/server/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAkB,MAAM,WAAW,CAAC;AAEtE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGlC,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,aAAa,IAAI,IAAI,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,WAAW,IAAI,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAiB,SAAQ,aAAa,EAAE,gBAAgB;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACzD,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAEtE,wBAAsB,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmInF"}
|