elysia 2.0.0-beta.2 → 2.0.0-beta.4
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/adapter/bun/index.d.ts +1 -1
- package/dist/adapter/bun/index.js +320 -56
- package/dist/adapter/bun/index.mjs +321 -57
- package/dist/adapter/utils.js +51 -30
- package/dist/adapter/utils.mjs +52 -31
- package/dist/adapter/web-standard/handler.js +5 -2
- package/dist/adapter/web-standard/handler.mjs +5 -2
- package/dist/base.d.ts +18 -7
- package/dist/base.js +213 -101
- package/dist/base.mjs +215 -103
- package/dist/compile/aot-capture.js +1 -1
- package/dist/compile/aot-capture.mjs +1 -1
- package/dist/compile/aot.d.ts +5 -4
- package/dist/compile/aot.js +17 -9
- package/dist/compile/aot.mjs +18 -9
- package/dist/compile/handler/descriptor.js +1 -1
- package/dist/compile/handler/descriptor.mjs +1 -1
- package/dist/compile/handler/frozen-validator.d.ts +4 -1
- package/dist/compile/handler/frozen-validator.js +8 -3
- package/dist/compile/handler/frozen-validator.mjs +5 -3
- package/dist/compile/handler/index.d.ts +2 -2
- package/dist/compile/handler/index.js +8 -6
- package/dist/compile/handler/index.mjs +8 -6
- package/dist/compile/handler/reconstruct.d.ts +1 -1
- package/dist/compile/handler/reconstruct.js +4 -3
- package/dist/compile/handler/reconstruct.mjs +4 -3
- package/dist/compile/handler/utils.js +2 -2
- package/dist/compile/handler/utils.mjs +3 -3
- package/dist/compile/jit-probe.d.ts +2 -2
- package/dist/context.d.ts +1 -1
- package/dist/context.js +8 -5
- package/dist/context.mjs +8 -5
- package/dist/cookie/config.d.ts +1 -0
- package/dist/cookie/config.js +3 -2
- package/dist/cookie/config.mjs +3 -2
- package/dist/cookie/cookie.d.ts +1 -0
- package/dist/cookie/cookie.js +6 -5
- package/dist/cookie/cookie.mjs +6 -5
- package/dist/cookie/crypto.d.ts +8 -7
- package/dist/cookie/crypto.js +38 -31
- package/dist/cookie/crypto.mjs +38 -32
- package/dist/cookie/error.js +1 -2
- package/dist/cookie/error.mjs +1 -2
- package/dist/cookie/lib.js +5 -1
- package/dist/cookie/lib.mjs +5 -1
- package/dist/cookie/serialize.js +1 -1
- package/dist/cookie/serialize.mjs +1 -1
- package/dist/cookie/types.d.ts +10 -0
- package/dist/cookie/utils.js +28 -14
- package/dist/cookie/utils.mjs +29 -15
- package/dist/handler/error.d.ts +23 -12
- package/dist/handler/error.js +24 -21
- package/dist/handler/error.mjs +20 -21
- package/dist/handler/fetch.js +6 -7
- package/dist/handler/fetch.mjs +7 -8
- package/dist/handler/utils.js +4 -2
- package/dist/handler/utils.mjs +5 -3
- package/dist/index.js +1 -8
- package/dist/package.js +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin/aot/core.d.ts +33 -6
- package/dist/plugin/aot/core.js +120 -40
- package/dist/plugin/aot/core.mjs +121 -43
- package/dist/plugin/aot/esbuild.js +8 -2
- package/dist/plugin/aot/esbuild.mjs +9 -3
- package/dist/plugin/aot/hooks.d.ts +2 -1
- package/dist/plugin/aot/hooks.js +3 -3
- package/dist/plugin/aot/hooks.mjs +4 -4
- package/dist/plugin/aot/source.d.ts +4 -1
- package/dist/plugin/aot/source.js +21 -14
- package/dist/plugin/aot/source.mjs +21 -14
- package/dist/plugin/aot/worker.js +2 -2
- package/dist/plugin/aot/worker.mjs +2 -2
- package/dist/route-table.d.ts +3 -0
- package/dist/route-table.js +16 -11
- package/dist/route-table.mjs +16 -11
- package/dist/schema-snapshot.js +17 -22
- package/dist/schema-snapshot.mjs +17 -22
- package/dist/type/bridge-live.d.ts +1 -1
- package/dist/type/bridge-live.js +2 -2
- package/dist/type/bridge-live.mjs +2 -2
- package/dist/type/bridge.d.ts +1 -1
- package/dist/type/coerce-plan.js +3 -4
- package/dist/type/coerce-plan.mjs +1 -1
- package/dist/type/coerce.d.ts +1 -1
- package/dist/type/compat.d.ts +3 -0
- package/dist/type/compat.js +32 -14
- package/dist/type/compat.mjs +27 -8
- package/dist/type/constants.d.ts +1 -1
- package/dist/type/elysia/array-buffer.js +2 -3
- package/dist/type/elysia/array-buffer.mjs +1 -1
- package/dist/type/elysia/array-string.js +7 -4
- package/dist/type/elysia/array-string.mjs +9 -5
- package/dist/type/elysia/boolean-string.js +2 -3
- package/dist/type/elysia/boolean-string.mjs +1 -1
- package/dist/type/elysia/boolean.js +4 -3
- package/dist/type/elysia/boolean.mjs +4 -2
- package/dist/type/elysia/cookie.js +2 -1
- package/dist/type/elysia/cookie.mjs +2 -1
- package/dist/type/elysia/date.js +7 -7
- package/dist/type/elysia/date.mjs +3 -2
- package/dist/type/elysia/file-type.d.ts +9 -2
- package/dist/type/elysia/file-type.js +16 -1
- package/dist/type/elysia/file-type.mjs +16 -2
- package/dist/type/elysia/file.js +8 -4
- package/dist/type/elysia/file.mjs +8 -3
- package/dist/type/elysia/files.js +6 -4
- package/dist/type/elysia/files.mjs +5 -2
- package/dist/type/elysia/form.js +2 -3
- package/dist/type/elysia/form.mjs +3 -3
- package/dist/type/elysia/integer-string.js +4 -5
- package/dist/type/elysia/integer-string.mjs +3 -3
- package/dist/type/elysia/integer.js +4 -3
- package/dist/type/elysia/integer.mjs +4 -2
- package/dist/type/elysia/maybe-empty.js +3 -4
- package/dist/type/elysia/maybe-empty.mjs +1 -1
- package/dist/type/elysia/nullable.js +2 -3
- package/dist/type/elysia/nullable.mjs +1 -1
- package/dist/type/elysia/number.js +4 -3
- package/dist/type/elysia/number.mjs +4 -2
- package/dist/type/elysia/numeric-enum.js +2 -3
- package/dist/type/elysia/numeric-enum.mjs +1 -1
- package/dist/type/elysia/numeric.js +5 -5
- package/dist/type/elysia/numeric.mjs +3 -2
- package/dist/type/elysia/object-string.js +7 -4
- package/dist/type/elysia/object-string.mjs +9 -5
- package/dist/type/elysia/string.js +4 -3
- package/dist/type/elysia/string.mjs +4 -2
- package/dist/type/elysia/uint8-array.js +2 -3
- package/dist/type/elysia/uint8-array.mjs +1 -1
- package/dist/type/elysia/union-enum.js +2 -3
- package/dist/type/elysia/union-enum.mjs +1 -1
- package/dist/type/elysia/utils.js +2 -3
- package/dist/type/elysia/utils.mjs +1 -1
- package/dist/type/exports.js +10 -1
- package/dist/type/exports.mjs +7 -0
- package/dist/type/index.d.ts +9 -1
- package/dist/type/index.js +41 -13
- package/dist/type/index.mjs +44 -9
- package/dist/type/typebox-type-live.d.ts +9 -0
- package/dist/type/typebox-type-live.js +31 -0
- package/dist/type/typebox-type-live.mjs +16 -0
- package/dist/type/typebox-type.d.ts +24 -0
- package/dist/type/typebox-type.js +130 -0
- package/dist/type/typebox-type.mjs +66 -0
- package/dist/type/typebox-value-live.d.ts +9 -0
- package/dist/type/typebox-value-live.js +27 -0
- package/dist/type/typebox-value-live.mjs +11 -0
- package/dist/type/typebox-value.d.ts +30 -0
- package/dist/type/typebox-value.js +147 -0
- package/dist/type/typebox-value.mjs +62 -0
- package/dist/type/validator/custom-error.js +4 -5
- package/dist/type/validator/custom-error.mjs +3 -3
- package/dist/type/validator/default-precompute.js +4 -5
- package/dist/type/validator/default-precompute.mjs +1 -1
- package/dist/type/validator/index.d.ts +1 -1
- package/dist/type/validator/index.js +51 -42
- package/dist/type/validator/index.mjs +33 -23
- package/dist/type/validator/validator-cache.d.ts +1 -1
- package/dist/type/validator/validator-cache.js +27 -14
- package/dist/type/validator/validator-cache.mjs +27 -13
- package/dist/universal/constants.d.ts +2 -1
- package/dist/universal/constants.js +3 -1
- package/dist/universal/constants.mjs +2 -1
- package/dist/utils.d.ts +19 -1
- package/dist/utils.js +25 -3
- package/dist/utils.mjs +19 -3
- package/dist/validator/index.js +2 -1
- package/dist/validator/index.mjs +2 -1
- package/dist/ws/context.d.ts +8 -1
- package/dist/ws/context.js +65 -29
- package/dist/ws/context.mjs +64 -29
- package/dist/ws/route.js +176 -28
- package/dist/ws/route.mjs +179 -31
- package/package.json +5 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnyElysia } from "../../base.js";
|
|
2
2
|
import { ElysiaAdapterOptions } from "../types.js";
|
|
3
3
|
//#region src/adapter/bun/index.d.ts
|
|
4
|
-
declare function collectStaticRoutes(app: AnyElysia):
|
|
4
|
+
declare function collectStaticRoutes(app: AnyElysia): Record<string, Record<string, Response>> | undefined;
|
|
5
5
|
declare const BunAdapter: ElysiaAdapterOptions<void>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { BunAdapter, collectStaticRoutes };
|
|
@@ -9,6 +9,77 @@ const require_compile_handler_index = require('../../compile/handler/index.js');
|
|
|
9
9
|
const require_route_table = require('../../route-table.js');
|
|
10
10
|
|
|
11
11
|
//#region src/adapter/bun/index.ts
|
|
12
|
+
function runLifecycle(epoch, callback, ...args) {
|
|
13
|
+
const invoking = epoch.invoking;
|
|
14
|
+
epoch.invoking = true;
|
|
15
|
+
try {
|
|
16
|
+
return callback(...args);
|
|
17
|
+
} finally {
|
|
18
|
+
epoch.invoking = invoking;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const unavailableFetch = () => new Response(null, {
|
|
22
|
+
headers: { connection: "close" },
|
|
23
|
+
status: 503
|
|
24
|
+
});
|
|
25
|
+
function reloadServer(server, serve) {
|
|
26
|
+
try {
|
|
27
|
+
server.reload(serve);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (!serve.routes) throw error;
|
|
30
|
+
delete serve.routes;
|
|
31
|
+
console.warn("[Elysia] Native static promotion was skipped:", error);
|
|
32
|
+
try {
|
|
33
|
+
server.reload(serve);
|
|
34
|
+
} catch (fallbackError) {
|
|
35
|
+
console.error("[Elysia] Failed to reload Bun server:", fallbackError);
|
|
36
|
+
throw fallbackError;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function releaseLifecycle(app, ext, createdExt, stop, registerCleanup) {
|
|
41
|
+
if (ext.stop === stop) delete ext.stop;
|
|
42
|
+
if (ext.cleanupEpoch === registerCleanup) delete ext.cleanupEpoch;
|
|
43
|
+
if (createdExt && app["~ext"] === ext && !Object.keys(ext).length) app["~ext"] = void 0;
|
|
44
|
+
}
|
|
45
|
+
function clearAppServer(app, server) {
|
|
46
|
+
if (app.server === server) app.server = void 0;
|
|
47
|
+
}
|
|
48
|
+
async function waitForServerRequests(server, abandoned) {
|
|
49
|
+
while (server.pendingRequests && !abandoned()) await Bun.sleep(1);
|
|
50
|
+
}
|
|
51
|
+
async function settleServerWebSockets(lifecycle, errors) {
|
|
52
|
+
if (!lifecycle) return true;
|
|
53
|
+
lifecycle.closing = true;
|
|
54
|
+
let failed = false;
|
|
55
|
+
do {
|
|
56
|
+
for (const socket of lifecycle.sockets) if (socket.readyState < 3) try {
|
|
57
|
+
socket.terminate();
|
|
58
|
+
} catch (error) {
|
|
59
|
+
errors.push(error);
|
|
60
|
+
failed = true;
|
|
61
|
+
}
|
|
62
|
+
if (failed) return false;
|
|
63
|
+
await Bun.sleep(1);
|
|
64
|
+
const abandon = lifecycle.abandon === true;
|
|
65
|
+
for (const socket of lifecycle.sockets) if (abandon || require_utils.isSocketQuiet(socket)) {
|
|
66
|
+
delete socket.data["~lifecycleRun"];
|
|
67
|
+
lifecycle.sockets.delete(socket);
|
|
68
|
+
}
|
|
69
|
+
} while (lifecycle.sockets.size);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
const closeServerIdle = (server, errors) => {
|
|
73
|
+
const close = server.closeIdleConnections;
|
|
74
|
+
if (!close) return true;
|
|
75
|
+
try {
|
|
76
|
+
close.call(server);
|
|
77
|
+
return true;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
errors.push(error);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
12
83
|
/**
|
|
13
84
|
* ! This may looks like it would cause race condition, but it is not
|
|
14
85
|
* Bun is single-threaded and synchronous, so the `finally` block will
|
|
@@ -26,15 +97,6 @@ const withOrigin = (fetch) => (request, server) => {
|
|
|
26
97
|
require_adapter_origin.origin.request = void 0;
|
|
27
98
|
}
|
|
28
99
|
};
|
|
29
|
-
const nativeStaticMethods = new Set([
|
|
30
|
-
"GET",
|
|
31
|
-
"POST",
|
|
32
|
-
"PUT",
|
|
33
|
-
"DELETE",
|
|
34
|
-
"PATCH",
|
|
35
|
-
"HEAD",
|
|
36
|
-
"OPTIONS"
|
|
37
|
-
]);
|
|
38
100
|
function collectStaticRoutes(app) {
|
|
39
101
|
if (app["~config"]?.nativeStaticResponse === false) return;
|
|
40
102
|
app.fetch;
|
|
@@ -44,9 +106,16 @@ function collectStaticRoutes(app) {
|
|
|
44
106
|
const table = app["~generation"]?.routeTable ?? app["~routeTable"];
|
|
45
107
|
const length = table?.length ?? 0;
|
|
46
108
|
if (!table || !length) return;
|
|
47
|
-
const methods = table
|
|
48
|
-
const
|
|
49
|
-
|
|
109
|
+
const { method: methods, path: paths, handler: handlers } = table;
|
|
110
|
+
const nativeStaticMethods = new Set([
|
|
111
|
+
"GET",
|
|
112
|
+
"POST",
|
|
113
|
+
"PUT",
|
|
114
|
+
"DELETE",
|
|
115
|
+
"PATCH",
|
|
116
|
+
"HEAD",
|
|
117
|
+
"OPTIONS"
|
|
118
|
+
]);
|
|
50
119
|
let hasCandidate = false;
|
|
51
120
|
for (let i = 0; i < length; i++) {
|
|
52
121
|
const h = handlers[i];
|
|
@@ -85,18 +154,19 @@ function collectStaticRoutes(app) {
|
|
|
85
154
|
const path = paths[i];
|
|
86
155
|
if (seen.get(method + " " + path) !== i) continue;
|
|
87
156
|
if (!nativeStaticMethods.has(method)) continue;
|
|
157
|
+
if (require_constants.isDynamicRegex.test(path)) continue;
|
|
88
158
|
const h = handlers[i];
|
|
89
159
|
if (typeof h === "function" || h instanceof Error || h instanceof Promise) continue;
|
|
90
160
|
const value = require_compile_handler_index.buildNativeStaticResponse(require_route_table.routeRow(table, i), app);
|
|
91
161
|
if (!value) continue;
|
|
92
162
|
add(method, path, value);
|
|
93
|
-
if (!strictPath
|
|
163
|
+
if (!strictPath) {
|
|
94
164
|
const loose = require_utils.getLoosePath(path);
|
|
95
165
|
if (loose !== path && !explicitPaths?.get(method)?.has(loose)) add(method, loose, value);
|
|
96
166
|
}
|
|
97
167
|
}
|
|
98
168
|
if (!Object.keys(ready).length) return;
|
|
99
|
-
return
|
|
169
|
+
return ready;
|
|
100
170
|
}
|
|
101
171
|
const BunAdapter = require_adapter_index.createAdapter({
|
|
102
172
|
name: "bun",
|
|
@@ -105,11 +175,18 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
105
175
|
parse: require_adapter_web_standard_index.WebStandardAdapter.parse,
|
|
106
176
|
response: require_adapter_web_standard_index.WebStandardAdapter.response,
|
|
107
177
|
listen(app, options, callback) {
|
|
178
|
+
if (app.server || app["~ext"]?.stop) throw new Error("[Elysia] Cannot call listen() while a server or teardown is active");
|
|
108
179
|
const _config = app["~config"]?.serve;
|
|
109
180
|
const optionsIsObject = typeof options === "object";
|
|
110
181
|
let live;
|
|
111
|
-
|
|
112
|
-
|
|
182
|
+
let cancelled = false;
|
|
183
|
+
let startupShutdown;
|
|
184
|
+
let shutdownAttempt;
|
|
185
|
+
const gatedFetch = (request, server) => live ? live(request, server) : Promise.resolve(ready).then(async () => {
|
|
186
|
+
if (!live) {
|
|
187
|
+
await startupShutdown;
|
|
188
|
+
throw new Error("[Elysia] Server was stopped before it was ready");
|
|
189
|
+
}
|
|
113
190
|
return live(request, server);
|
|
114
191
|
});
|
|
115
192
|
const _options = optionsIsObject ? { ...options } : {
|
|
@@ -122,6 +199,8 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
122
199
|
..._options
|
|
123
200
|
} : _options;
|
|
124
201
|
let ready;
|
|
202
|
+
let wsLifecycle;
|
|
203
|
+
let modulesReady;
|
|
125
204
|
const build = () => {
|
|
126
205
|
const fetch = app.fetch;
|
|
127
206
|
let routes;
|
|
@@ -134,7 +213,17 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
134
213
|
if (app["~hasWS"]) {
|
|
135
214
|
const resolved = require_generation.resolvedWsOf(app);
|
|
136
215
|
if (!resolved) throw new Error("[Elysia] internal: WebSocket routes are present but no capability provider was resolved");
|
|
137
|
-
|
|
216
|
+
const handler = resolved.provider.buildGlobalWSHandler();
|
|
217
|
+
websocket = resolved.config ? Object.assign(handler, resolved.config) : handler;
|
|
218
|
+
const setter = Object.getOwnPropertyDescriptor(handler, "~lifecycle")?.set;
|
|
219
|
+
if (setter) {
|
|
220
|
+
wsLifecycle = {
|
|
221
|
+
closing: false,
|
|
222
|
+
sockets: /* @__PURE__ */ new Set(),
|
|
223
|
+
run: runLifecycle.bind(null, epoch)
|
|
224
|
+
};
|
|
225
|
+
setter.call(handler, wsLifecycle);
|
|
226
|
+
}
|
|
138
227
|
}
|
|
139
228
|
return {
|
|
140
229
|
fetch,
|
|
@@ -143,74 +232,249 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
143
232
|
};
|
|
144
233
|
};
|
|
145
234
|
let built;
|
|
146
|
-
|
|
147
|
-
const
|
|
235
|
+
let pendingSetups;
|
|
236
|
+
const server = app.server = Bun.serve(serve.routes || serve.error ? {
|
|
237
|
+
...serve,
|
|
238
|
+
error: unavailableFetch,
|
|
239
|
+
routes: {}
|
|
240
|
+
} : serve);
|
|
241
|
+
let startupFailure;
|
|
242
|
+
let forceRequested = false;
|
|
243
|
+
let forceDone = false;
|
|
244
|
+
let nativeStopped = false;
|
|
245
|
+
let abandoned = false;
|
|
246
|
+
let published = false;
|
|
247
|
+
let cleanupCompleted = false;
|
|
248
|
+
let idleRequired = false;
|
|
249
|
+
let cleanupFailures;
|
|
250
|
+
let observedOutcome;
|
|
251
|
+
let persistentCleanup;
|
|
252
|
+
let persistentCleanupLength = -1;
|
|
253
|
+
const epochCleanup = [];
|
|
254
|
+
const createdExt = app["~ext"] === void 0;
|
|
255
|
+
const ext = app["~ext"] ??= require_utils.nullObject();
|
|
256
|
+
const epoch = {
|
|
257
|
+
setup: false,
|
|
258
|
+
invoking: false
|
|
259
|
+
};
|
|
260
|
+
const snapshotCleanup = () => {
|
|
261
|
+
if (persistentCleanupLength !== -1) return;
|
|
262
|
+
persistentCleanup = ext.cleanup;
|
|
263
|
+
persistentCleanupLength = persistentCleanup?.length ?? 0;
|
|
264
|
+
};
|
|
265
|
+
const registerCleanup = (handler) => {
|
|
266
|
+
if (ext.cleanupEpoch !== registerCleanup) return false;
|
|
267
|
+
if (!epoch.setup) throw new Error("[Elysia] .cleanup() called after its setup epoch settled");
|
|
268
|
+
if (Array.isArray(handler)) epochCleanup.push(...handler);
|
|
269
|
+
else epochCleanup.push(handler);
|
|
270
|
+
return true;
|
|
271
|
+
};
|
|
272
|
+
const gate = () => {
|
|
273
|
+
if (!published) return;
|
|
274
|
+
live = void 0;
|
|
275
|
+
if (wsLifecycle) wsLifecycle.closing = true;
|
|
148
276
|
try {
|
|
149
|
-
server.reload(
|
|
277
|
+
server.reload({
|
|
278
|
+
...serve,
|
|
279
|
+
fetch: unavailableFetch,
|
|
280
|
+
error: unavailableFetch,
|
|
281
|
+
routes: {}
|
|
282
|
+
});
|
|
150
283
|
} catch (error) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
284
|
+
return { error };
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const nativeStop = async (closeActiveConnections, errors) => {
|
|
288
|
+
try {
|
|
289
|
+
await server.stop(closeActiveConnections);
|
|
290
|
+
nativeStopped = true;
|
|
291
|
+
if (closeActiveConnections) {
|
|
292
|
+
forceDone = true;
|
|
293
|
+
forceRequested = false;
|
|
159
294
|
}
|
|
295
|
+
return true;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
if (closeActiveConnections) forceRequested = true;
|
|
298
|
+
errors.push(error);
|
|
299
|
+
return false;
|
|
160
300
|
}
|
|
161
301
|
};
|
|
302
|
+
const isAbandoned = () => abandoned;
|
|
303
|
+
const quiesce = async (force) => {
|
|
304
|
+
const errors = [];
|
|
305
|
+
if (!published) return {
|
|
306
|
+
errors,
|
|
307
|
+
releasable: await nativeStop(true, errors),
|
|
308
|
+
safe: true
|
|
309
|
+
};
|
|
310
|
+
if (force && !idleRequired && !wsLifecycle?.closing) {
|
|
311
|
+
const stopped = await nativeStop(true, errors);
|
|
312
|
+
return {
|
|
313
|
+
errors,
|
|
314
|
+
releasable: stopped,
|
|
315
|
+
safe: stopped
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const gateFailure = gate();
|
|
319
|
+
if (gateFailure) errors.push(gateFailure.error);
|
|
320
|
+
let socketsSettled = await settleServerWebSockets(wsLifecycle, errors);
|
|
321
|
+
await Promise.resolve();
|
|
322
|
+
let close = forceRequested || gateFailure !== void 0 || !socketsSettled;
|
|
323
|
+
if (!close && nativeStopped) await waitForServerRequests(server, isAbandoned);
|
|
324
|
+
idleRequired = true;
|
|
325
|
+
let stopped = true;
|
|
326
|
+
while (!nativeStopped || forceRequested && !forceDone) {
|
|
327
|
+
if (nativeStopped) close = true;
|
|
328
|
+
stopped = await nativeStop(close, errors);
|
|
329
|
+
if (stopped) {
|
|
330
|
+
if (socketsSettled) socketsSettled = await settleServerWebSockets(wsLifecycle, errors);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (close) break;
|
|
334
|
+
await waitForServerRequests(server, isAbandoned);
|
|
335
|
+
close = true;
|
|
336
|
+
}
|
|
337
|
+
let idleClosed = true;
|
|
338
|
+
if (idleRequired) {
|
|
339
|
+
idleClosed = closeServerIdle(server, errors);
|
|
340
|
+
if (idleClosed && !gateFailure) idleRequired = false;
|
|
341
|
+
}
|
|
342
|
+
const safe = socketsSettled && stopped && idleClosed && (!gateFailure || forceDone);
|
|
343
|
+
return {
|
|
344
|
+
errors,
|
|
345
|
+
releasable: safe,
|
|
346
|
+
safe
|
|
347
|
+
};
|
|
348
|
+
};
|
|
162
349
|
const setup = () => {
|
|
163
|
-
|
|
350
|
+
snapshotCleanup();
|
|
351
|
+
const onSetup = ext.setup;
|
|
164
352
|
if (!onSetup) return;
|
|
165
|
-
|
|
353
|
+
epoch.setup = true;
|
|
354
|
+
ext.cleanupEpoch = registerCleanup;
|
|
166
355
|
for (let i = 0; i < onSetup.length; i++) {
|
|
167
|
-
|
|
168
|
-
|
|
356
|
+
if (cancelled) break;
|
|
357
|
+
try {
|
|
358
|
+
const result = runLifecycle(epoch, onSetup[i], app);
|
|
359
|
+
if (result && typeof result.then === "function") (pendingSetups ??= []).push(Promise.resolve(result));
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (!pendingSetups) epoch.setup = false;
|
|
362
|
+
stop(true, { error }).catch(() => {});
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
169
365
|
}
|
|
170
|
-
if (pendingSetups) return Promise.all(pendingSetups);
|
|
366
|
+
if (pendingSetups) return Promise.all(pendingSetups).then(() => epoch.setup = false);
|
|
367
|
+
epoch.setup = false;
|
|
171
368
|
};
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
369
|
+
const stop = (closeActiveConnections, failure) => {
|
|
370
|
+
const reentrant = epoch.invoking;
|
|
371
|
+
if (failure) startupFailure ??= failure;
|
|
372
|
+
if (closeActiveConnections === true && !forceDone) forceRequested = true;
|
|
373
|
+
cancelled = true;
|
|
374
|
+
clearAppServer(app, server);
|
|
375
|
+
let outcome;
|
|
376
|
+
if (shutdownAttempt) {
|
|
377
|
+
if (closeActiveConnections === true && !forceDone) {
|
|
378
|
+
abandoned = true;
|
|
379
|
+
if (wsLifecycle) wsLifecycle.abandon = true;
|
|
380
|
+
}
|
|
381
|
+
outcome = shutdownAttempt;
|
|
382
|
+
} else {
|
|
383
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
384
|
+
outcome = shutdownAttempt = promise;
|
|
385
|
+
const quiescence = quiesce(forceRequested || !published);
|
|
386
|
+
let releasable = false;
|
|
387
|
+
(async () => {
|
|
388
|
+
try {
|
|
389
|
+
await Promise.resolve();
|
|
390
|
+
if (modulesReady) try {
|
|
391
|
+
await modulesReady;
|
|
392
|
+
} catch (error) {
|
|
393
|
+
startupFailure ??= { error };
|
|
394
|
+
}
|
|
395
|
+
if (pendingSetups) {
|
|
396
|
+
const setupResults = await Promise.allSettled(pendingSetups);
|
|
397
|
+
if (!startupFailure) for (let i = 0; i < setupResults.length; i++) {
|
|
398
|
+
const result = setupResults[i];
|
|
399
|
+
if (result.status === "rejected") {
|
|
400
|
+
startupFailure = { error: result.reason };
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
epoch.setup = false;
|
|
406
|
+
const errors = [];
|
|
407
|
+
const quiesced = await quiescence;
|
|
408
|
+
if (startupFailure) errors.push(startupFailure.error);
|
|
409
|
+
errors.push(...quiesced.errors);
|
|
410
|
+
releasable = quiesced.releasable;
|
|
411
|
+
if (!quiesced.safe) {
|
|
412
|
+
if (cleanupFailures) errors.push(...cleanupFailures);
|
|
413
|
+
require_utils.throwLifecycleErrors(errors);
|
|
414
|
+
}
|
|
415
|
+
if (!cleanupCompleted) {
|
|
416
|
+
snapshotCleanup();
|
|
417
|
+
if (ext.stop === stop) {
|
|
418
|
+
const length = persistentCleanupLength + epochCleanup.length;
|
|
419
|
+
for (let n = 0; n < length; n++) {
|
|
420
|
+
if (ext.stop !== stop) break;
|
|
421
|
+
const i = startupFailure ? length - 1 - n : n;
|
|
422
|
+
const handler = i < persistentCleanupLength ? persistentCleanup[i] : epochCleanup[i - persistentCleanupLength];
|
|
423
|
+
try {
|
|
424
|
+
await runLifecycle(epoch, handler, app);
|
|
425
|
+
} catch (error) {
|
|
426
|
+
(cleanupFailures ??= []).push(error);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
cleanupCompleted = true;
|
|
431
|
+
epochCleanup.length = 0;
|
|
432
|
+
}
|
|
433
|
+
if (cleanupFailures) errors.push(...cleanupFailures);
|
|
434
|
+
if (releasable) releaseLifecycle(app, ext, createdExt, stop, registerCleanup);
|
|
435
|
+
require_utils.throwLifecycleErrors(errors);
|
|
436
|
+
} finally {
|
|
437
|
+
epoch.setup = false;
|
|
438
|
+
if (!releasable) shutdownAttempt = void 0;
|
|
439
|
+
}
|
|
440
|
+
})().then(resolve, reject);
|
|
180
441
|
}
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
442
|
+
if (!published) startupShutdown ??= outcome;
|
|
443
|
+
if (!reentrant) return outcome;
|
|
444
|
+
if (observedOutcome !== outcome) {
|
|
445
|
+
observedOutcome = outcome;
|
|
446
|
+
outcome.catch((error) => {
|
|
447
|
+
console.error("[Elysia] stop() failed:", error);
|
|
448
|
+
});
|
|
187
449
|
}
|
|
188
|
-
return
|
|
450
|
+
return Promise.resolve();
|
|
189
451
|
};
|
|
452
|
+
ext.stop = stop;
|
|
190
453
|
const publish = () => {
|
|
191
|
-
if (app.server !== server) return;
|
|
454
|
+
if (cancelled || app.server !== server) return;
|
|
192
455
|
built ??= build();
|
|
193
456
|
live = serve.fetch = withOrigin(built.fetch);
|
|
457
|
+
published = true;
|
|
194
458
|
if (built.websocket) serve.websocket = built.websocket;
|
|
195
|
-
if (built.routes) serve.routes = built.routes
|
|
196
|
-
|
|
459
|
+
if (built.routes) serve.routes = built.routes;
|
|
460
|
+
reloadServer(server, serve);
|
|
197
461
|
if (callback) callback(server);
|
|
198
462
|
};
|
|
199
463
|
const start = () => {
|
|
200
|
-
|
|
464
|
+
modulesReady = void 0;
|
|
465
|
+
if (cancelled || app.server !== server) return;
|
|
201
466
|
const setupReady = setup();
|
|
202
467
|
if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
|
|
203
468
|
publish();
|
|
204
469
|
};
|
|
205
470
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
471
|
+
ready = (modulesReady = app.modules).then(start);
|
|
472
|
+
ready = ready.catch((error) => stop(true, { error }));
|
|
208
473
|
ready.catch((error) => {
|
|
209
474
|
console.error("[Elysia] listen() failed:", error);
|
|
210
|
-
return rollback(error);
|
|
211
475
|
});
|
|
212
476
|
} catch (error) {
|
|
213
|
-
|
|
477
|
+
stop(true, { error }).catch(console.error);
|
|
214
478
|
throw error;
|
|
215
479
|
}
|
|
216
480
|
}
|