elysia 2.0.0-beta.11 → 2.0.0-beta.13
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.js +36 -21
- package/dist/adapter/bun/index.mjs +36 -21
- package/dist/adapter/utils.js +1 -0
- package/dist/adapter/utils.mjs +1 -0
- package/dist/adapter/web-standard/handler.js +8 -2
- package/dist/adapter/web-standard/handler.mjs +8 -2
- package/dist/base.d.ts +5 -0
- package/dist/base.js +109 -4
- package/dist/base.mjs +111 -6
- package/dist/compile/aot-capture.d.ts +2 -13
- package/dist/compile/aot-capture.js +5 -27
- package/dist/compile/aot-capture.mjs +6 -24
- package/dist/compile/aot-emit.js +1 -1
- package/dist/compile/aot-emit.mjs +1 -1
- package/dist/compile/aot.d.ts +1 -1
- package/dist/compile/aot.js +2 -2
- package/dist/compile/aot.mjs +2 -2
- package/dist/compile/handler/descriptor.d.ts +4 -8
- package/dist/compile/handler/descriptor.js +8 -21
- package/dist/compile/handler/descriptor.mjs +9 -21
- package/dist/compile/handler/index.d.ts +4 -3
- package/dist/compile/handler/index.js +16 -6
- package/dist/compile/handler/index.mjs +16 -7
- package/dist/compile/handler/jit.js +82 -76
- package/dist/compile/handler/jit.mjs +83 -77
- package/dist/compile/handler/params.d.ts +1 -4
- package/dist/compile/handler/params.js +3 -4
- package/dist/compile/handler/params.mjs +5 -5
- package/dist/compile/handler/reconstruct.d.ts +1 -1
- package/dist/compile/handler/static-clone-resolver.d.ts +6 -0
- package/dist/compile/handler/static-clone-resolver.js +8 -0
- package/dist/compile/handler/static-clone-resolver.mjs +7 -0
- package/dist/compile/handler/utils.d.ts +7 -7
- package/dist/compile/handler/utils.js +24 -20
- package/dist/compile/handler/utils.mjs +24 -20
- package/dist/compile/utils.js +7 -4
- package/dist/compile/utils.mjs +7 -4
- package/dist/context.js +3 -21
- package/dist/context.mjs +4 -22
- package/dist/cookie/index.d.ts +1 -2
- package/dist/cookie/index.js +0 -2
- package/dist/cookie/index.mjs +1 -2
- package/dist/cookie/lib.js +2 -1
- package/dist/cookie/lib.mjs +2 -1
- package/dist/cookie/utils.d.ts +3 -7
- package/dist/cookie/utils.js +9 -28
- package/dist/cookie/utils.mjs +11 -29
- package/dist/error.d.ts +40 -83
- package/dist/error.js +18 -19
- package/dist/error.mjs +18 -20
- package/dist/handler/error.js +4 -5
- package/dist/handler/error.mjs +4 -5
- package/dist/handler/fetch.js +31 -17
- package/dist/handler/fetch.mjs +32 -18
- package/dist/handler/utils.d.ts +3 -3
- package/dist/handler/utils.js +28 -17
- package/dist/handler/utils.mjs +28 -17
- package/dist/index.d.ts +3 -3
- package/dist/package.js +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin/aot/core.d.ts +3 -7
- package/dist/plugin/aot/core.js +8 -18
- package/dist/plugin/aot/core.mjs +9 -17
- package/dist/plugin/aot/hooks.js +5 -1
- package/dist/plugin/aot/hooks.mjs +5 -1
- package/dist/trace.js +23 -10
- package/dist/trace.mjs +23 -10
- package/dist/type/bridge-live.d.ts +3 -2
- package/dist/type/bridge-live.js +4 -2
- package/dist/type/bridge-live.mjs +3 -2
- package/dist/type/bridge.d.ts +6 -4
- package/dist/type/bridge.js +9 -1
- package/dist/type/bridge.mjs +3 -1
- package/dist/type/coerce-plan.d.ts +2 -2
- package/dist/type/coerce-plan.js +0 -1
- package/dist/type/coerce-plan.mjs +2 -2
- package/dist/type/compat.js +2 -1
- package/dist/type/compat.mjs +3 -2
- package/dist/type/constants.d.ts +1 -1
- package/dist/type/shared.d.ts +1 -3
- package/dist/type/shared.js +0 -3
- package/dist/type/shared.mjs +1 -3
- package/dist/type/typebox-value-live.d.ts +4 -3
- package/dist/type/typebox-value-live.js +5 -3
- package/dist/type/typebox-value-live.mjs +4 -3
- package/dist/type/typebox-value.d.ts +11 -7
- package/dist/type/typebox-value.js +2 -1
- package/dist/type/typebox-value.mjs +1 -1
- package/dist/type/validator/index.d.ts +1 -1
- package/dist/type/validator/validator-cache.d.ts +1 -1
- package/dist/types.d.ts +10 -17
- package/dist/universal/file.d.ts +1 -3
- package/dist/universal/file.js +0 -2
- package/dist/universal/file.mjs +1 -2
- package/dist/universal/is-production.d.ts +1 -2
- package/dist/universal/is-production.js +1 -3
- package/dist/universal/is-production.mjs +2 -3
- package/dist/utils.d.ts +0 -1
- package/package.json +13 -6
|
@@ -167,12 +167,10 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
167
167
|
response: require_adapter_web_standard_index.WebStandardAdapter.response,
|
|
168
168
|
listen(app, options, callback) {
|
|
169
169
|
if (app.server || app["~ext"]?.stop) throw new Error("[Elysia] Cannot call listen() while a server or teardown is active");
|
|
170
|
+
const requestReady = Promise.withResolvers();
|
|
170
171
|
function gatedFetch(request, server) {
|
|
171
|
-
return live ? live(request, server) :
|
|
172
|
-
if (!live)
|
|
173
|
-
await startupShutdown;
|
|
174
|
-
throw new Error("[Elysia] Server was stopped before it was ready");
|
|
175
|
-
}
|
|
172
|
+
return live && !cancelled ? live(request, server) : requestReady.promise.then(() => {
|
|
173
|
+
if (cancelled || !live) return unavailableFetch();
|
|
176
174
|
return live(request, server);
|
|
177
175
|
});
|
|
178
176
|
}
|
|
@@ -194,7 +192,6 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
194
192
|
} : serve);
|
|
195
193
|
let live;
|
|
196
194
|
let cancelled = false;
|
|
197
|
-
let startupShutdown;
|
|
198
195
|
let shutdownAttempt;
|
|
199
196
|
let ready;
|
|
200
197
|
let wsLifecycle;
|
|
@@ -233,6 +230,7 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
233
230
|
};
|
|
234
231
|
let startupFailure;
|
|
235
232
|
let forceRequested = false;
|
|
233
|
+
const force = Promise.withResolvers();
|
|
236
234
|
let forceDone = false;
|
|
237
235
|
let nativeStopped = false;
|
|
238
236
|
let abandoned = false;
|
|
@@ -279,7 +277,9 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
279
277
|
};
|
|
280
278
|
const nativeStop = async (closeActiveConnections, errors) => {
|
|
281
279
|
try {
|
|
282
|
-
|
|
280
|
+
const stopping = server.stop(closeActiveConnections);
|
|
281
|
+
await (closeActiveConnections ? stopping : Promise.race([stopping, force.promise]));
|
|
282
|
+
if (!closeActiveConnections && forceRequested && !forceDone) return false;
|
|
283
283
|
nativeStopped = true;
|
|
284
284
|
if (closeActiveConnections) {
|
|
285
285
|
forceDone = true;
|
|
@@ -362,8 +362,12 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
362
362
|
const stop = (closeActiveConnections, failure) => {
|
|
363
363
|
const reentrant = epoch.invoking;
|
|
364
364
|
if (failure) startupFailure ??= failure;
|
|
365
|
-
if (closeActiveConnections === true
|
|
365
|
+
if (closeActiveConnections === true) {
|
|
366
|
+
force.resolve();
|
|
367
|
+
if (!forceDone) forceRequested = true;
|
|
368
|
+
}
|
|
366
369
|
cancelled = true;
|
|
370
|
+
requestReady.resolve();
|
|
367
371
|
clearAppServer(app, server);
|
|
368
372
|
let outcome;
|
|
369
373
|
if (shutdownAttempt) {
|
|
@@ -381,7 +385,7 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
381
385
|
try {
|
|
382
386
|
await Promise.resolve();
|
|
383
387
|
if (modulesReady) try {
|
|
384
|
-
await modulesReady;
|
|
388
|
+
await Promise.race([modulesReady, force.promise]);
|
|
385
389
|
} catch (error) {
|
|
386
390
|
startupFailure ??= { error };
|
|
387
391
|
}
|
|
@@ -432,7 +436,6 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
432
436
|
}
|
|
433
437
|
})().then(resolve, reject);
|
|
434
438
|
}
|
|
435
|
-
if (!published) startupShutdown ??= outcome;
|
|
436
439
|
if (!reentrant) return outcome;
|
|
437
440
|
if (observedOutcome !== outcome) {
|
|
438
441
|
observedOutcome = outcome;
|
|
@@ -444,27 +447,39 @@ const BunAdapter = require_adapter_index.createAdapter({
|
|
|
444
447
|
};
|
|
445
448
|
ext.stop = stop;
|
|
446
449
|
const publish = () => {
|
|
447
|
-
if (cancelled || app.server !== server)
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
450
|
+
if (cancelled || app.server !== server) {
|
|
451
|
+
requestReady.resolve();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
try {
|
|
455
|
+
built ??= build();
|
|
456
|
+
live = serve.fetch = withOrigin(built.fetch);
|
|
457
|
+
published = true;
|
|
458
|
+
if (built.websocket) serve.websocket = built.websocket;
|
|
459
|
+
if (built.routes) serve.routes = built.routes;
|
|
460
|
+
reloadServer(server, serve);
|
|
461
|
+
if (callback) callback(server);
|
|
462
|
+
} catch (error) {
|
|
463
|
+
startupFailure ??= { error };
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
466
|
+
requestReady.resolve();
|
|
455
467
|
};
|
|
456
468
|
const start = () => {
|
|
457
469
|
modulesReady = void 0;
|
|
458
|
-
if (cancelled || app.server !== server)
|
|
470
|
+
if (cancelled || app.server !== server) {
|
|
471
|
+
requestReady.resolve();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
459
474
|
const setupReady = setup();
|
|
460
475
|
if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
|
|
461
476
|
publish();
|
|
462
477
|
};
|
|
463
478
|
try {
|
|
464
|
-
ready = (modulesReady = app.modules).then(start);
|
|
465
|
-
ready = ready.catch((error) => stop(true, { error }));
|
|
479
|
+
ready = (modulesReady = app.modules).then(start).catch((error) => stop(true, { error }));
|
|
466
480
|
ready.catch((error) => {
|
|
467
481
|
console.error("[Elysia] listen() failed:", error);
|
|
482
|
+
if (typeof process !== "undefined") process.exitCode = 1;
|
|
468
483
|
});
|
|
469
484
|
} catch (error) {
|
|
470
485
|
stop(true, { error }).catch(console.error);
|
|
@@ -166,12 +166,10 @@ const BunAdapter = createAdapter({
|
|
|
166
166
|
response: WebStandardAdapter.response,
|
|
167
167
|
listen(app, options, callback) {
|
|
168
168
|
if (app.server || app["~ext"]?.stop) throw new Error("[Elysia] Cannot call listen() while a server or teardown is active");
|
|
169
|
+
const requestReady = Promise.withResolvers();
|
|
169
170
|
function gatedFetch(request, server) {
|
|
170
|
-
return live ? live(request, server) :
|
|
171
|
-
if (!live)
|
|
172
|
-
await startupShutdown;
|
|
173
|
-
throw new Error("[Elysia] Server was stopped before it was ready");
|
|
174
|
-
}
|
|
171
|
+
return live && !cancelled ? live(request, server) : requestReady.promise.then(() => {
|
|
172
|
+
if (cancelled || !live) return unavailableFetch();
|
|
175
173
|
return live(request, server);
|
|
176
174
|
});
|
|
177
175
|
}
|
|
@@ -193,7 +191,6 @@ const BunAdapter = createAdapter({
|
|
|
193
191
|
} : serve);
|
|
194
192
|
let live;
|
|
195
193
|
let cancelled = false;
|
|
196
|
-
let startupShutdown;
|
|
197
194
|
let shutdownAttempt;
|
|
198
195
|
let ready;
|
|
199
196
|
let wsLifecycle;
|
|
@@ -232,6 +229,7 @@ const BunAdapter = createAdapter({
|
|
|
232
229
|
};
|
|
233
230
|
let startupFailure;
|
|
234
231
|
let forceRequested = false;
|
|
232
|
+
const force = Promise.withResolvers();
|
|
235
233
|
let forceDone = false;
|
|
236
234
|
let nativeStopped = false;
|
|
237
235
|
let abandoned = false;
|
|
@@ -278,7 +276,9 @@ const BunAdapter = createAdapter({
|
|
|
278
276
|
};
|
|
279
277
|
const nativeStop = async (closeActiveConnections, errors) => {
|
|
280
278
|
try {
|
|
281
|
-
|
|
279
|
+
const stopping = server.stop(closeActiveConnections);
|
|
280
|
+
await (closeActiveConnections ? stopping : Promise.race([stopping, force.promise]));
|
|
281
|
+
if (!closeActiveConnections && forceRequested && !forceDone) return false;
|
|
282
282
|
nativeStopped = true;
|
|
283
283
|
if (closeActiveConnections) {
|
|
284
284
|
forceDone = true;
|
|
@@ -361,8 +361,12 @@ const BunAdapter = createAdapter({
|
|
|
361
361
|
const stop = (closeActiveConnections, failure) => {
|
|
362
362
|
const reentrant = epoch.invoking;
|
|
363
363
|
if (failure) startupFailure ??= failure;
|
|
364
|
-
if (closeActiveConnections === true
|
|
364
|
+
if (closeActiveConnections === true) {
|
|
365
|
+
force.resolve();
|
|
366
|
+
if (!forceDone) forceRequested = true;
|
|
367
|
+
}
|
|
365
368
|
cancelled = true;
|
|
369
|
+
requestReady.resolve();
|
|
366
370
|
clearAppServer(app, server);
|
|
367
371
|
let outcome;
|
|
368
372
|
if (shutdownAttempt) {
|
|
@@ -380,7 +384,7 @@ const BunAdapter = createAdapter({
|
|
|
380
384
|
try {
|
|
381
385
|
await Promise.resolve();
|
|
382
386
|
if (modulesReady) try {
|
|
383
|
-
await modulesReady;
|
|
387
|
+
await Promise.race([modulesReady, force.promise]);
|
|
384
388
|
} catch (error) {
|
|
385
389
|
startupFailure ??= { error };
|
|
386
390
|
}
|
|
@@ -431,7 +435,6 @@ const BunAdapter = createAdapter({
|
|
|
431
435
|
}
|
|
432
436
|
})().then(resolve, reject);
|
|
433
437
|
}
|
|
434
|
-
if (!published) startupShutdown ??= outcome;
|
|
435
438
|
if (!reentrant) return outcome;
|
|
436
439
|
if (observedOutcome !== outcome) {
|
|
437
440
|
observedOutcome = outcome;
|
|
@@ -443,27 +446,39 @@ const BunAdapter = createAdapter({
|
|
|
443
446
|
};
|
|
444
447
|
ext.stop = stop;
|
|
445
448
|
const publish = () => {
|
|
446
|
-
if (cancelled || app.server !== server)
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
449
|
+
if (cancelled || app.server !== server) {
|
|
450
|
+
requestReady.resolve();
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
try {
|
|
454
|
+
built ??= build();
|
|
455
|
+
live = serve.fetch = withOrigin(built.fetch);
|
|
456
|
+
published = true;
|
|
457
|
+
if (built.websocket) serve.websocket = built.websocket;
|
|
458
|
+
if (built.routes) serve.routes = built.routes;
|
|
459
|
+
reloadServer(server, serve);
|
|
460
|
+
if (callback) callback(server);
|
|
461
|
+
} catch (error) {
|
|
462
|
+
startupFailure ??= { error };
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
requestReady.resolve();
|
|
454
466
|
};
|
|
455
467
|
const start = () => {
|
|
456
468
|
modulesReady = void 0;
|
|
457
|
-
if (cancelled || app.server !== server)
|
|
469
|
+
if (cancelled || app.server !== server) {
|
|
470
|
+
requestReady.resolve();
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
458
473
|
const setupReady = setup();
|
|
459
474
|
if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
|
|
460
475
|
publish();
|
|
461
476
|
};
|
|
462
477
|
try {
|
|
463
|
-
ready = (modulesReady = app.modules).then(start);
|
|
464
|
-
ready = ready.catch((error) => stop(true, { error }));
|
|
478
|
+
ready = (modulesReady = app.modules).then(start).catch((error) => stop(true, { error }));
|
|
465
479
|
ready.catch((error) => {
|
|
466
480
|
console.error("[Elysia] listen() failed:", error);
|
|
481
|
+
if (typeof process !== "undefined") process.exitCode = 1;
|
|
467
482
|
});
|
|
468
483
|
} catch (error) {
|
|
469
484
|
stop(true, { error }).catch(console.error);
|
package/dist/adapter/utils.js
CHANGED
|
@@ -145,6 +145,7 @@ function enqueueBinaryChunk(controller, chunk) {
|
|
|
145
145
|
}
|
|
146
146
|
function createStreamHandler({ mapResponse, mapCompactResponse }) {
|
|
147
147
|
return async (generator, set, request, skipFormat, owned = false) => {
|
|
148
|
+
if (request === null) return void 0;
|
|
148
149
|
if (require_utils.isByteStream(generator)) {
|
|
149
150
|
if (generator.locked) throw new TypeError("Cannot transfer a locked or consumed byte stream");
|
|
150
151
|
if (set) {
|
package/dist/adapter/utils.mjs
CHANGED
|
@@ -144,6 +144,7 @@ function enqueueBinaryChunk(controller, chunk) {
|
|
|
144
144
|
}
|
|
145
145
|
function createStreamHandler({ mapResponse, mapCompactResponse }) {
|
|
146
146
|
return async (generator, set, request, skipFormat, owned = false) => {
|
|
147
|
+
if (request === null) return void 0;
|
|
147
148
|
if (isByteStream(generator)) {
|
|
148
149
|
if (generator.locked) throw new TypeError("Cannot transfer a locked or consumed byte stream");
|
|
149
150
|
if (set) {
|
|
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
const require_universal_constants = require('../../universal/constants.js');
|
|
3
3
|
const require_universal_file = require('../../universal/file.js');
|
|
4
4
|
const require_utils = require('../../utils.js');
|
|
5
|
+
const require_universal_is_production = require('../../universal/is-production.js');
|
|
5
6
|
const require_error = require('../../error.js');
|
|
6
7
|
const require_adapter_default_headers = require('../default-headers.js');
|
|
7
8
|
const require_adapter_utils = require('../utils.js');
|
|
@@ -58,7 +59,12 @@ function mapResponseWithSet(response, set, request, owned) {
|
|
|
58
59
|
default: return mapFallback(response, set, request, owned);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
62
|
+
const checkRemovedSetRedirect = !require_universal_is_production.isProduction();
|
|
61
63
|
function mapResponse(response, set, request, owned) {
|
|
64
|
+
if (checkRemovedSetRedirect && Object.hasOwn(set, "redirect") && !require_universal_is_production.isProduction()) {
|
|
65
|
+
delete set.redirect;
|
|
66
|
+
throw new Error("[Elysia] set.redirect was removed in 2.0 — return redirect(url) instead");
|
|
67
|
+
}
|
|
62
68
|
const headers = set.headers;
|
|
63
69
|
if (set.status !== void 0 || set.cookie || headers["\0"] === headers || require_utils.isNotEmpty(headers)) return mapResponseWithSet(response, set, request, owned);
|
|
64
70
|
if (response instanceof require_error.ElysiaStatus) {
|
|
@@ -131,11 +137,11 @@ function mapFallback(response, set, request, owned = false) {
|
|
|
131
137
|
status: response.status,
|
|
132
138
|
headers: response.headers ? { ...response.headers } : {}
|
|
133
139
|
}, request, owned);
|
|
134
|
-
if (response instanceof require_universal_file.ElysiaFile) return handleElysiaFile(response,
|
|
140
|
+
if (response instanceof require_universal_file.ElysiaFile) return handleElysiaFile(response, set, request);
|
|
135
141
|
if (require_utils.isElysiaForm(response)) return new Response(require_utils.formToFormData(response), set);
|
|
136
142
|
if (typeof response?.next === "function" || response instanceof ReadableStream) return handleStream(response, set, request, void 0, owned);
|
|
137
143
|
if (typeof response?.then === "function") return response.then((x) => set ? mapResponse(x, set, request, owned) : mapCompactResponse(x, request, owned));
|
|
138
|
-
if (Array.isArray(response)) return Response.json(response);
|
|
144
|
+
if (Array.isArray(response)) return Response.json(response, set);
|
|
139
145
|
if (typeof response?.toResponse === "function") return set ? mapResponse(response.toResponse(), set, request, owned) : mapCompactResponse(response.toResponse(), request, owned);
|
|
140
146
|
if (responseTag(response) === "Cookie" && require_cookie_cookie.Cookie.isCookie(response)) return set ? mapResponse(response.value, set, request, owned) : mapCompactResponse(response.value, request, owned);
|
|
141
147
|
return new Response(response, set);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isBun } from "../../universal/constants.mjs";
|
|
2
2
|
import { ElysiaFile, mime } from "../../universal/file.mjs";
|
|
3
3
|
import { formToFormData, isElysiaForm, isNotEmpty, nullObject } from "../../utils.mjs";
|
|
4
|
+
import { isProduction } from "../../universal/is-production.mjs";
|
|
4
5
|
import { ElysiaStatus, PROBLEM_JSON, internalServerErrorBody } from "../../error.mjs";
|
|
5
6
|
import { defaultHeaders } from "../default-headers.mjs";
|
|
6
7
|
import { createResponseHandler, createStreamHandler, handleFile, handleSet, materializeSetHeaders } from "../utils.mjs";
|
|
@@ -57,7 +58,12 @@ function mapResponseWithSet(response, set, request, owned) {
|
|
|
57
58
|
default: return mapFallback(response, set, request, owned);
|
|
58
59
|
}
|
|
59
60
|
}
|
|
61
|
+
const checkRemovedSetRedirect = !isProduction();
|
|
60
62
|
function mapResponse(response, set, request, owned) {
|
|
63
|
+
if (checkRemovedSetRedirect && Object.hasOwn(set, "redirect") && !isProduction()) {
|
|
64
|
+
delete set.redirect;
|
|
65
|
+
throw new Error("[Elysia] set.redirect was removed in 2.0 — return redirect(url) instead");
|
|
66
|
+
}
|
|
61
67
|
const headers = set.headers;
|
|
62
68
|
if (set.status !== void 0 || set.cookie || headers["\0"] === headers || isNotEmpty(headers)) return mapResponseWithSet(response, set, request, owned);
|
|
63
69
|
if (response instanceof ElysiaStatus) {
|
|
@@ -130,11 +136,11 @@ function mapFallback(response, set, request, owned = false) {
|
|
|
130
136
|
status: response.status,
|
|
131
137
|
headers: response.headers ? { ...response.headers } : {}
|
|
132
138
|
}, request, owned);
|
|
133
|
-
if (response instanceof ElysiaFile) return handleElysiaFile(response,
|
|
139
|
+
if (response instanceof ElysiaFile) return handleElysiaFile(response, set, request);
|
|
134
140
|
if (isElysiaForm(response)) return new Response(formToFormData(response), set);
|
|
135
141
|
if (typeof response?.next === "function" || response instanceof ReadableStream) return handleStream(response, set, request, void 0, owned);
|
|
136
142
|
if (typeof response?.then === "function") return response.then((x) => set ? mapResponse(x, set, request, owned) : mapCompactResponse(x, request, owned));
|
|
137
|
-
if (Array.isArray(response)) return Response.json(response);
|
|
143
|
+
if (Array.isArray(response)) return Response.json(response, set);
|
|
138
144
|
if (typeof response?.toResponse === "function") return set ? mapResponse(response.toResponse(), set, request, owned) : mapCompactResponse(response.toResponse(), request, owned);
|
|
139
145
|
if (responseTag(response) === "Cookie" && Cookie.isCookie(response)) return set ? mapResponse(response.value, set, request, owned) : mapCompactResponse(response.value, request, owned);
|
|
140
146
|
return new Response(response, set);
|
package/dist/base.d.ts
CHANGED
|
@@ -101,6 +101,11 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
|
|
|
101
101
|
'~scopeChild'?: boolean;
|
|
102
102
|
'~scopeChildren'?: AnyElysia[];
|
|
103
103
|
constructor(config?: ElysiaConfig<BasePath, Scope>);
|
|
104
|
+
/**
|
|
105
|
+
* Every registered route with its merged hooks.
|
|
106
|
+
* Development shares a frozen cache. Production rebuilds the list so its
|
|
107
|
+
* metadata can be released after startup.
|
|
108
|
+
*/
|
|
104
109
|
get routes(): PublicRoute[];
|
|
105
110
|
/**
|
|
106
111
|
* ### decorate
|
package/dist/base.js
CHANGED
|
@@ -45,6 +45,42 @@ const mergeExtCallbacks = (target, incoming) => {
|
|
|
45
45
|
index.indexedLength = target.length;
|
|
46
46
|
};
|
|
47
47
|
const canRegisterLoose = (path, isDynamic) => !isDynamic && (path.length === 0 || path.charCodeAt(path.length - 1) === 47);
|
|
48
|
+
const isSchemaValue = (value) => {
|
|
49
|
+
if (value == null || typeof value === "string") return true;
|
|
50
|
+
if (typeof value !== "object" && typeof value !== "function") return false;
|
|
51
|
+
return "~kind" in value || "~standard" in value || "~elyAcl" in value || typeof value.Check === "function";
|
|
52
|
+
};
|
|
53
|
+
const hookKeys = new Set([
|
|
54
|
+
...require_utils.schemaProperties,
|
|
55
|
+
...require_utils.eventProperties,
|
|
56
|
+
"detail",
|
|
57
|
+
"tags"
|
|
58
|
+
]);
|
|
59
|
+
const hasHookKeys = (value) => {
|
|
60
|
+
for (const key in value) if (hookKeys.has(key)) return true;
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
63
|
+
const isPlainObject = (value) => {
|
|
64
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
65
|
+
const proto = Object.getPrototypeOf(value);
|
|
66
|
+
return proto === Object.prototype || proto === null;
|
|
67
|
+
};
|
|
68
|
+
const assertSchemaShape = (hook, where) => {
|
|
69
|
+
for (const key in hook) {
|
|
70
|
+
if (!require_utils.schemaProperties.has(key)) continue;
|
|
71
|
+
const value = hook[key];
|
|
72
|
+
if (isSchemaValue(value)) continue;
|
|
73
|
+
if (key === "response" && isPlainObject(value)) {
|
|
74
|
+
let isStatusMap = true;
|
|
75
|
+
for (const status in value) if (status !== "default" && isNaN(+status) || !isSchemaValue(value[status])) {
|
|
76
|
+
isStatusMap = false;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
if (isStatusMap) continue;
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`[Elysia] ${where}: "${key}" is not a schema — use t.Object({ ... })`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
48
84
|
/**
|
|
49
85
|
* Every key a single route must answer to, in registration order.
|
|
50
86
|
*
|
|
@@ -173,6 +209,11 @@ var Elysia = class Elysia {
|
|
|
173
209
|
if (adapter?.setup) this.#useFn(adapter.setup);
|
|
174
210
|
} else this["~Prefix"] = void 0;
|
|
175
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Every registered route with its merged hooks.
|
|
214
|
+
* Development shares a frozen cache. Production rebuilds the list so its
|
|
215
|
+
* metadata can be released after startup.
|
|
216
|
+
*/
|
|
176
217
|
get routes() {
|
|
177
218
|
const generation = this["~generation"];
|
|
178
219
|
if (this.#isCacheable && this.cachedGeneration === generation && this.cachedEpoch === mutationEpoch && this.cachedRoutes !== void 0) return this.cachedRoutes;
|
|
@@ -192,7 +233,8 @@ var Elysia = class Elysia {
|
|
|
192
233
|
hooks: merged
|
|
193
234
|
};
|
|
194
235
|
});
|
|
195
|
-
if (this.#isCacheable) {
|
|
236
|
+
if (this.#isCacheable && !require_universal_is_production.isProduction()) {
|
|
237
|
+
Object.freeze(routes);
|
|
196
238
|
this.#cacheRoutes(generation);
|
|
197
239
|
this.cachedRoutes = routes;
|
|
198
240
|
}
|
|
@@ -428,6 +470,7 @@ var Elysia = class Elysia {
|
|
|
428
470
|
return this;
|
|
429
471
|
}
|
|
430
472
|
#guard(scope, hook) {
|
|
473
|
+
if (hook) assertSchemaShape(hook, ".guard()");
|
|
431
474
|
hook = require_schema_snapshot.snapshotHookSchemas(hook);
|
|
432
475
|
require_utils.hookToGuard(hook);
|
|
433
476
|
const trackFn = (fn) => {
|
|
@@ -540,13 +583,17 @@ var Elysia = class Elysia {
|
|
|
540
583
|
};
|
|
541
584
|
return this;
|
|
542
585
|
}
|
|
543
|
-
macro(macro) {
|
|
586
|
+
macro(macro, definition) {
|
|
544
587
|
this.#assertMutable("macro");
|
|
545
588
|
if (typeof macro === "function") throw new Error("use `.macro({ name: fn })` instead of `.macro(fn)`");
|
|
589
|
+
if (definition != null || typeof macro === "string") throw new Error("[Elysia] .macro(name, definition) was removed in 2.0 — use .macro({ [name]: definition })");
|
|
546
590
|
const m = this.#ensureMacroTable();
|
|
547
591
|
const baseline = this.macroBaseline;
|
|
548
592
|
for (const key in macro) {
|
|
549
|
-
if (typeof macro[key] === "object")
|
|
593
|
+
if (typeof macro[key] === "object") {
|
|
594
|
+
if (macro[key]) assertSchemaShape(macro[key], `.macro(${key})`);
|
|
595
|
+
macro[key] = require_utils.hookToGuard(macro[key]);
|
|
596
|
+
}
|
|
550
597
|
if (this.hash !== void 0 && !require_utils.macroOrigin.has(macro[key])) require_utils.macroOrigin.set(macro[key], this.hash);
|
|
551
598
|
if (baseline?.has(key) && key in m && m[key] !== macro[key]) throw new Error(`[Elysia] Macro "${key}" can be only define once`);
|
|
552
599
|
}
|
|
@@ -1047,6 +1094,8 @@ var Elysia = class Elysia {
|
|
|
1047
1094
|
#add(method, path, hookOrFn, fn, hasHook = fn !== void 0) {
|
|
1048
1095
|
if (this["~Prefix"]) path = require_utils.joinPath(this["~Prefix"], path);
|
|
1049
1096
|
else if (path && path.charCodeAt(0) !== 47) path = "/" + path;
|
|
1097
|
+
if (typeof hookOrFn === "function" && !hasHookKeys(hookOrFn) && isPlainObject(fn) && hasHookKeys(fn)) throw new Error(`[Elysia] .${method === "*" ? "all" : method.toLowerCase()}('${path}', handler, hook) is the 1.x order; Elysia 2 takes (path, hook, handler) — see the 2.0 migration guide`);
|
|
1098
|
+
if (hasHook && hookOrFn) assertSchemaShape(hookOrFn, `${method} ${path}`);
|
|
1050
1099
|
const handler = hasHook ? fn : hookOrFn;
|
|
1051
1100
|
const hook = hasHook ? require_schema_snapshot.snapshotHookSchemas(hookOrFn) : void 0;
|
|
1052
1101
|
const appHook = this["~hookChain"];
|
|
@@ -1398,6 +1447,56 @@ var Elysia = class Elysia {
|
|
|
1398
1447
|
}
|
|
1399
1448
|
return false;
|
|
1400
1449
|
}
|
|
1450
|
+
static #slotHasTypeBox(value, models, record) {
|
|
1451
|
+
if (typeof value === "string") value = models?.[value];
|
|
1452
|
+
if (!value || typeof value !== "object") return false;
|
|
1453
|
+
if ("~kind" in value || "~elyAcl" in value) return true;
|
|
1454
|
+
if (!record || "~standard" in value) return false;
|
|
1455
|
+
for (const status in value) if (Elysia.#slotHasTypeBox(value[status], models)) return true;
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
static #hookHasTypeBox(h, models) {
|
|
1459
|
+
if (!h || typeof h !== "object") return false;
|
|
1460
|
+
for (const key in h) {
|
|
1461
|
+
if (key === "schemas") {
|
|
1462
|
+
const schemas = h[key];
|
|
1463
|
+
if (Array.isArray(schemas)) {
|
|
1464
|
+
for (let s = 0; s < schemas.length; s++) if (Elysia.#hookHasTypeBox(schemas[s], models)) return true;
|
|
1465
|
+
}
|
|
1466
|
+
continue;
|
|
1467
|
+
}
|
|
1468
|
+
if (require_utils.schemaProperties.has(key) && Elysia.#slotHasTypeBox(h[key], models, key === "response")) return true;
|
|
1469
|
+
}
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
static #chainHasTypeBox(node, models, seen, resolve) {
|
|
1473
|
+
while (node) {
|
|
1474
|
+
if (seen.has(node)) return false;
|
|
1475
|
+
seen.add(node);
|
|
1476
|
+
if ("added" in node) {
|
|
1477
|
+
if (Elysia.#hookHasTypeBox(resolve ? resolve(node) : node.added, models)) return true;
|
|
1478
|
+
node = node.parent;
|
|
1479
|
+
} else {
|
|
1480
|
+
if (Elysia.#chainHasTypeBox(node.combine, models, seen, resolve)) return true;
|
|
1481
|
+
node = node.over;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
return false;
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Scan each route and its inherited hooks for TypeBox schemas.
|
|
1488
|
+
* This may warm TypeBox after a closer schema overrides it, avoiding a full
|
|
1489
|
+
* hook merge during build.
|
|
1490
|
+
*/
|
|
1491
|
+
#hasTypeBoxSchema(table) {
|
|
1492
|
+
const models = this["~ext"]?.models;
|
|
1493
|
+
const resolve = require_compile_handler_index.chainResolver(this);
|
|
1494
|
+
const rootChain = this["~hookChain"];
|
|
1495
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1496
|
+
const { localHook, appHook, inheritedChain, owner } = table;
|
|
1497
|
+
for (let i = 0; i < table.length; i++) if (Elysia.#hookHasTypeBox(localHook[i], models) || Elysia.#chainHasTypeBox(appHook[i], models, seen, resolve) || Elysia.#chainHasTypeBox(inheritedChain[i], models, seen, resolve) || owner[i] !== this && Elysia.#chainHasTypeBox(rootChain, models, seen, resolve)) return true;
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1401
1500
|
#routeMayHaveModelRef(table, i) {
|
|
1402
1501
|
const macroScope = table.macroScope?.get(i);
|
|
1403
1502
|
const owner = table.owner[i];
|
|
@@ -1551,6 +1650,9 @@ var Elysia = class Elysia {
|
|
|
1551
1650
|
const appChain = this["~hookChain"];
|
|
1552
1651
|
if (this["~ext"]?.macro || this["~scopeChildren"] || appChain !== void 0 && appChain.refs) for (let i = 0; i < length; i++) this.#assertRouteModelRefs(require_route_table.routeRow(table, i), method[i]);
|
|
1553
1652
|
else for (let i = 0; i < length; i++) if (this.#routeMayHaveModelRef(table, i)) this.#assertRouteModelRefs(require_route_table.routeRow(table, i), method[i]);
|
|
1653
|
+
if (length && this.#hasTypeBoxSchema(table)) try {
|
|
1654
|
+
require_type_bridge.warmTypebox();
|
|
1655
|
+
} catch {}
|
|
1554
1656
|
let markDuplicates = false;
|
|
1555
1657
|
if (length) {
|
|
1556
1658
|
const programId = this["~programId"];
|
|
@@ -1640,7 +1742,10 @@ var Elysia = class Elysia {
|
|
|
1640
1742
|
}
|
|
1641
1743
|
listen(options, callback) {
|
|
1642
1744
|
const listen = (this["~config"]?.adapter ?? (require_universal_constants.isBun ? require_adapter_bun_index.BunAdapter : void 0))?.listen;
|
|
1643
|
-
if (!listen)
|
|
1745
|
+
if (!listen) {
|
|
1746
|
+
const deno = typeof Deno !== "undefined";
|
|
1747
|
+
throw new Error(`[Elysia] listen() requires an adapter on ${deno ? "Deno" : typeof process === "undefined" ? "this runtime" : "Node.js"} — https://elysiajs.com/integrations/${deno ? "deno" : "node"}`);
|
|
1748
|
+
}
|
|
1644
1749
|
if (!require_compile_aot.Capture.isAotBuildEnv()) listen(this, options, callback);
|
|
1645
1750
|
return this;
|
|
1646
1751
|
}
|