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