elysia 2.0.0-beta.2 → 2.0.0-beta.21
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 +18 -2
- package/dist/adapter/bun/index.js +467 -110
- package/dist/adapter/bun/index.mjs +467 -112
- package/dist/adapter/types.d.ts +2 -21
- package/dist/adapter/utils.d.ts +14 -3
- package/dist/adapter/utils.js +146 -87
- package/dist/adapter/utils.mjs +148 -90
- package/dist/adapter/web-standard/handler.d.ts +1 -1
- package/dist/adapter/web-standard/handler.js +47 -36
- package/dist/adapter/web-standard/handler.mjs +48 -37
- package/dist/adapter/web-standard/index.js +2 -30
- package/dist/adapter/web-standard/index.mjs +2 -30
- package/dist/adapter/web-standard/utils.js +5 -18
- package/dist/adapter/web-standard/utils.mjs +5 -18
- package/dist/base.d.ts +99 -67
- package/dist/base.js +678 -510
- package/dist/base.mjs +682 -514
- package/dist/compile/aot-capture.d.ts +2 -13
- package/dist/compile/aot-capture.js +26 -69
- package/dist/compile/aot-capture.mjs +28 -67
- package/dist/compile/aot-emit.d.ts +9 -7
- package/dist/compile/aot-emit.js +42 -19
- package/dist/compile/aot-emit.mjs +42 -20
- package/dist/compile/aot.d.ts +17 -19
- package/dist/compile/aot.js +41 -51
- package/dist/compile/aot.mjs +39 -49
- package/dist/compile/handler/descriptor.d.ts +9 -12
- package/dist/compile/handler/descriptor.js +19 -44
- package/dist/compile/handler/descriptor.mjs +20 -42
- package/dist/compile/handler/frozen-validator.d.ts +5 -10
- package/dist/compile/handler/frozen-validator.js +55 -105
- package/dist/compile/handler/frozen-validator.mjs +53 -105
- package/dist/compile/handler/index.d.ts +7 -5
- package/dist/compile/handler/index.js +270 -111
- package/dist/compile/handler/index.mjs +270 -113
- package/dist/compile/handler/jit.d.ts +19 -17
- package/dist/compile/handler/jit.js +222 -149
- package/dist/compile/handler/jit.mjs +224 -152
- package/dist/compile/handler/params.d.ts +1 -4
- package/dist/compile/handler/params.js +10 -5
- package/dist/compile/handler/params.mjs +14 -8
- package/dist/compile/handler/reconstruct.d.ts +2 -2
- package/dist/compile/handler/reconstruct.js +6 -4
- package/dist/compile/handler/reconstruct.mjs +6 -4
- 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 +22 -11
- package/dist/compile/handler/utils.js +159 -253
- package/dist/compile/handler/utils.mjs +155 -252
- package/dist/compile/jit-probe.d.ts +2 -2
- package/dist/compile/jit-probe.js +2 -3
- package/dist/compile/jit-probe.mjs +2 -3
- package/dist/compile/lexer.d.ts +7 -4
- package/dist/compile/lexer.js +268 -6
- package/dist/compile/lexer.mjs +268 -4
- package/dist/compile/utils.js +7 -4
- package/dist/compile/utils.mjs +7 -4
- package/dist/compiled.d.ts +0 -1
- package/dist/compiled.js +0 -1
- package/dist/compiled.mjs +0 -1
- package/dist/context.d.ts +14 -4
- package/dist/context.js +17 -32
- package/dist/context.mjs +19 -34
- package/dist/cookie/config.d.ts +7 -2
- package/dist/cookie/config.js +76 -16
- package/dist/cookie/config.mjs +77 -18
- package/dist/cookie/cookie.d.ts +1 -1
- package/dist/cookie/cookie.js +8 -10
- package/dist/cookie/cookie.mjs +8 -10
- package/dist/cookie/crypto.d.ts +8 -7
- package/dist/cookie/crypto.js +51 -40
- package/dist/cookie/crypto.mjs +51 -41
- package/dist/cookie/error.d.ts +1 -2
- package/dist/cookie/error.js +6 -4
- package/dist/cookie/error.mjs +6 -4
- package/dist/cookie/lib.js +7 -2
- package/dist/cookie/lib.mjs +7 -2
- 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.d.ts +4 -8
- package/dist/cookie/utils.js +86 -52
- package/dist/cookie/utils.mjs +89 -54
- package/dist/error.d.ts +113 -103
- package/dist/error.js +181 -117
- package/dist/error.mjs +179 -118
- package/dist/generation.d.ts +2 -2
- package/dist/handler/error.d.ts +26 -15
- package/dist/handler/error.js +77 -96
- package/dist/handler/error.mjs +74 -97
- package/dist/handler/fetch.js +87 -108
- package/dist/handler/fetch.mjs +89 -110
- package/dist/handler/utils.d.ts +12 -6
- package/dist/handler/utils.js +84 -28
- package/dist/handler/utils.mjs +80 -28
- package/dist/index.d.ts +12 -12
- package/dist/index.js +2 -9
- package/dist/index.mjs +1 -1
- package/dist/memory.js +1 -1
- package/dist/memory.mjs +1 -1
- package/dist/package.js +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin/aot/bun.d.ts +8 -1
- package/dist/plugin/aot/bun.js +16 -9
- package/dist/plugin/aot/bun.mjs +17 -10
- package/dist/plugin/aot/core.d.ts +52 -60
- package/dist/plugin/aot/core.js +208 -109
- package/dist/plugin/aot/core.mjs +205 -111
- package/dist/plugin/aot/esbuild.js +8 -5
- package/dist/plugin/aot/esbuild.mjs +9 -6
- package/dist/plugin/aot/hooks.d.ts +6 -17
- package/dist/plugin/aot/hooks.js +36 -14
- package/dist/plugin/aot/hooks.mjs +37 -16
- package/dist/plugin/aot/rspack-loader.d.ts +1 -5
- package/dist/plugin/aot/rspack-loader.js +1 -10
- package/dist/plugin/aot/rspack-loader.mjs +1 -10
- package/dist/plugin/aot/rspack.js +2 -5
- package/dist/plugin/aot/rspack.mjs +3 -6
- package/dist/plugin/aot/source.d.ts +6 -42
- package/dist/plugin/aot/source.js +71 -71
- package/dist/plugin/aot/source.mjs +72 -72
- package/dist/plugin/aot/treeshake.js +2 -6
- package/dist/plugin/aot/treeshake.mjs +2 -6
- package/dist/plugin/aot/unplugin.d.ts +1 -4
- package/dist/plugin/aot/unplugin.js +4 -13
- package/dist/plugin/aot/unplugin.mjs +4 -13
- package/dist/plugin/aot/vite.d.ts +2 -6
- package/dist/plugin/aot/worker.js +2 -2
- package/dist/plugin/aot/worker.mjs +2 -2
- package/dist/plugin/auto-head.js +1 -10
- package/dist/plugin/auto-head.mjs +1 -10
- package/dist/plugin/trace.d.ts +2 -1
- 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.d.ts +0 -4
- package/dist/schema-snapshot.js +32 -49
- package/dist/schema-snapshot.mjs +32 -49
- package/dist/sucrose.d.ts +6 -55
- package/dist/sucrose.js +103 -731
- package/dist/sucrose.mjs +102 -724
- package/dist/trace.d.ts +5 -8
- package/dist/trace.js +23 -134
- package/dist/trace.mjs +24 -135
- package/dist/type/bridge-live.d.ts +4 -2
- package/dist/type/bridge-live.js +6 -3
- package/dist/type/bridge-live.mjs +4 -2
- package/dist/type/bridge.d.ts +6 -4
- package/dist/type/bridge.js +17 -9
- package/dist/type/bridge.mjs +5 -3
- package/dist/type/coerce-plan.d.ts +5 -5
- package/dist/type/coerce-plan.js +41 -39
- package/dist/type/coerce-plan.mjs +43 -39
- package/dist/type/coerce.d.ts +3 -7
- package/dist/type/coerce.js +18 -75
- package/dist/type/coerce.mjs +19 -76
- package/dist/type/compat.d.ts +3 -0
- package/dist/type/compat.js +23 -14
- package/dist/type/compat.mjs +20 -10
- package/dist/type/elysia/array-buffer.d.ts +4 -1
- package/dist/type/elysia/array-buffer.js +17 -17
- package/dist/type/elysia/array-buffer.mjs +17 -17
- package/dist/type/elysia/array-string.js +2 -40
- package/dist/type/elysia/array-string.mjs +2 -39
- package/dist/type/elysia/array.js +5 -9
- package/dist/type/elysia/array.mjs +5 -9
- package/dist/type/elysia/boolean-string.js +2 -3
- package/dist/type/elysia/boolean-string.mjs +1 -1
- package/dist/type/elysia/boolean.js +3 -12
- package/dist/type/elysia/boolean.mjs +3 -11
- package/dist/type/elysia/cookie.d.ts +3 -4
- package/dist/type/elysia/cookie.js +5 -15
- package/dist/type/elysia/cookie.mjs +5 -15
- package/dist/type/elysia/date.js +13 -20
- package/dist/type/elysia/date.mjs +10 -16
- package/dist/type/elysia/file-type.d.ts +11 -4
- package/dist/type/elysia/file-type.js +17 -2
- package/dist/type/elysia/file-type.mjs +17 -3
- package/dist/type/elysia/file.d.ts +1 -3
- package/dist/type/elysia/file.js +11 -27
- package/dist/type/elysia/file.mjs +11 -12
- package/dist/type/elysia/files.js +7 -11
- package/dist/type/elysia/files.mjs +7 -10
- package/dist/type/elysia/form.js +2 -3
- package/dist/type/elysia/form.mjs +3 -3
- package/dist/type/elysia/integer-string.d.ts +1 -1
- package/dist/type/elysia/integer-string.js +4 -30
- package/dist/type/elysia/integer-string.mjs +5 -30
- package/dist/type/elysia/integer.js +3 -12
- package/dist/type/elysia/integer.mjs +3 -11
- package/dist/type/elysia/intersect.js +0 -5
- package/dist/type/elysia/intersect.mjs +0 -5
- package/dist/type/elysia/json-string.d.ts +7 -0
- package/dist/type/elysia/json-string.js +47 -0
- package/dist/type/elysia/json-string.mjs +46 -0
- package/dist/type/elysia/keep-config.d.ts +14 -0
- package/dist/type/elysia/keep-config.js +62 -0
- package/dist/type/elysia/keep-config.mjs +53 -0
- 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.d.ts +2 -1
- package/dist/type/elysia/number.js +19 -11
- package/dist/type/elysia/number.mjs +18 -10
- package/dist/type/elysia/numeric-enum.d.ts +1 -1
- package/dist/type/elysia/numeric-enum.js +4 -5
- package/dist/type/elysia/numeric-enum.mjs +3 -3
- package/dist/type/elysia/numeric.d.ts +4 -2
- package/dist/type/elysia/numeric.js +20 -17
- package/dist/type/elysia/numeric.mjs +19 -16
- package/dist/type/elysia/object-string.js +2 -37
- package/dist/type/elysia/object-string.mjs +2 -36
- package/dist/type/elysia/object.js +5 -9
- package/dist/type/elysia/object.mjs +5 -9
- package/dist/type/elysia/optional.js +8 -8
- package/dist/type/elysia/optional.mjs +7 -7
- package/dist/type/elysia/problem.d.ts +20 -0
- package/dist/type/elysia/problem.js +25 -0
- package/dist/type/elysia/problem.mjs +24 -0
- package/dist/type/elysia/string.js +4 -3
- package/dist/type/elysia/string.mjs +4 -2
- package/dist/type/elysia/uint8-array.d.ts +1 -1
- package/dist/type/elysia/uint8-array.js +5 -20
- package/dist/type/elysia/uint8-array.mjs +5 -19
- package/dist/type/elysia/union-enum.js +7 -8
- package/dist/type/elysia/union-enum.mjs +6 -6
- package/dist/type/elysia/union.js +0 -5
- package/dist/type/elysia/union.mjs +0 -5
- package/dist/type/elysia/utils.d.ts +2 -4
- package/dist/type/elysia/utils.js +10 -21
- package/dist/type/elysia/utils.mjs +7 -15
- package/dist/type/exports.d.ts +4 -2
- package/dist/type/exports.js +23 -2
- package/dist/type/exports.mjs +11 -2
- package/dist/type/index.d.ts +10 -2
- package/dist/type/index.js +62 -15
- package/dist/type/index.mjs +65 -11
- package/dist/type/shared.d.ts +3 -9
- package/dist/type/shared.js +44 -97
- package/dist/type/shared.mjs +43 -97
- package/dist/type/sync-require.d.ts +11 -0
- package/dist/type/sync-require.js +14 -0
- package/dist/type/sync-require.mjs +12 -0
- package/dist/type/typebox-system-lite.d.ts +2 -0
- package/dist/type/typebox-system-lite.js +34 -0
- package/dist/type/typebox-system-lite.mjs +3 -0
- package/dist/type/typebox-system-require.d.ts +7 -0
- package/dist/type/typebox-system-require.js +24 -0
- package/dist/type/typebox-system-require.mjs +23 -0
- package/dist/type/typebox-type-live.d.ts +11 -0
- package/dist/type/typebox-type-live.js +45 -0
- package/dist/type/typebox-type-live.mjs +20 -0
- package/dist/type/typebox-type.d.ts +34 -0
- package/dist/type/typebox-type.js +199 -0
- package/dist/type/typebox-type.mjs +86 -0
- package/dist/type/typebox-value-live.d.ts +11 -0
- package/dist/type/typebox-value-live.js +31 -0
- package/dist/type/typebox-value-live.mjs +13 -0
- package/dist/type/typebox-value-ops.d.ts +4 -0
- package/dist/type/typebox-value-ops.js +90 -0
- package/dist/type/typebox-value-ops.mjs +5 -0
- package/dist/type/typebox-value-require.d.ts +8 -0
- package/dist/type/typebox-value-require.js +28 -0
- package/dist/type/typebox-value-require.mjs +25 -0
- package/dist/type/typebox-value.d.ts +35 -0
- package/dist/type/typebox-value.js +161 -0
- package/dist/type/typebox-value.mjs +74 -0
- package/dist/type/utils.js +1 -10
- package/dist/type/utils.mjs +1 -10
- package/dist/type/validator/clean-safe.d.ts +2 -4
- package/dist/type/validator/clean-safe.js +15 -11
- package/dist/type/validator/clean-safe.mjs +16 -10
- package/dist/type/validator/custom-error.js +12 -16
- package/dist/type/validator/custom-error.mjs +11 -14
- package/dist/type/validator/default-precompute.d.ts +9 -1
- package/dist/type/validator/default-precompute.js +40 -77
- package/dist/type/validator/default-precompute.mjs +37 -74
- package/dist/type/validator/exact-mirror-live.d.ts +8 -0
- package/dist/type/validator/exact-mirror-live.js +22 -0
- package/dist/type/validator/exact-mirror-live.mjs +17 -0
- package/dist/type/validator/exact-mirror-require.d.ts +4 -0
- package/dist/type/validator/exact-mirror-require.js +11 -0
- package/dist/type/validator/exact-mirror-require.mjs +9 -0
- package/dist/type/validator/exact-mirror.js +8 -8
- package/dist/type/validator/exact-mirror.mjs +9 -8
- package/dist/type/validator/frozen-check.js +5 -6
- package/dist/type/validator/frozen-check.mjs +6 -7
- package/dist/type/validator/index.d.ts +1 -0
- package/dist/type/validator/index.js +169 -166
- package/dist/type/validator/index.mjs +162 -158
- package/dist/type/validator/string-codec-aot.d.ts +2 -1
- package/dist/type/validator/string-codec-aot.js +8 -2
- package/dist/type/validator/string-codec-aot.mjs +7 -2
- package/dist/type/validator/validator-cache.d.ts +5 -4
- package/dist/type/validator/validator-cache.js +41 -24
- package/dist/type/validator/validator-cache.mjs +40 -22
- package/dist/types.d.ts +263 -95
- package/dist/universal/constants.d.ts +2 -1
- package/dist/universal/constants.js +3 -1
- package/dist/universal/constants.mjs +2 -1
- package/dist/universal/env.js +2 -3
- package/dist/universal/env.mjs +2 -3
- package/dist/universal/file.d.ts +6 -4
- package/dist/universal/file.js +11 -16
- package/dist/universal/file.mjs +12 -16
- package/dist/universal/index.d.ts +2 -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/universal/server.d.ts +0 -272
- package/dist/utils.d.ts +43 -7
- package/dist/utils.js +181 -126
- package/dist/utils.mjs +168 -126
- package/dist/validator/index.d.ts +1 -1
- package/dist/validator/index.js +17 -30
- package/dist/validator/index.mjs +18 -31
- package/dist/validator/route.js +2 -1
- package/dist/validator/route.mjs +2 -1
- package/dist/ws/context.d.ts +8 -1
- package/dist/ws/context.js +68 -44
- package/dist/ws/context.mjs +67 -44
- package/dist/ws/parser.js +10 -20
- package/dist/ws/parser.mjs +10 -20
- package/dist/ws/route.d.ts +2 -2
- package/dist/ws/route.js +249 -141
- package/dist/ws/route.mjs +254 -146
- package/dist/ws/types.d.ts +2 -2
- package/package.json +23 -49
- package/dist/compile/analysis-cache.d.ts +0 -6
- package/dist/compile/analysis-cache.js +0 -12
- package/dist/compile/analysis-cache.mjs +0 -11
- package/dist/cookie/index.d.ts +0 -7
- package/dist/cookie/index.js +0 -13
- package/dist/cookie/index.mjs +0 -7
- package/dist/handler/index.d.ts +0 -2
- package/dist/handler/index.js +0 -5
- package/dist/handler/index.mjs +0 -3
package/dist/base.mjs
CHANGED
|
@@ -1,41 +1,119 @@
|
|
|
1
1
|
import { isBun } from "./universal/constants.mjs";
|
|
2
|
-
import { clonePlainDecorators, clonePlainDeep, coalesceSchemas, createErrorEventHandler, eventProperties, fnOrigin, fnv1a, getLoosePath, guardNonPlainLeaves, hookToGuard, invalidateMacroEpoch, isEmpty, isNotEmpty, isRecordNumber, joinPath, macroOrigin, mapDeriveEntry, mergeDeep, mergeResponse, nullObject, pushField, schemaProperties, serializeMacroSeed } from "./utils.mjs";
|
|
3
|
-
import { Ref } from "./type/bridge.mjs";
|
|
2
|
+
import { clearFlattenChainMemo, clonePlainDecorators, clonePlainDeep, coalesceSchemas, createErrorEventHandler, eventProperties, fnOrigin, fnv1a, getLoosePath, guardNonPlainLeaves, hookToGuard, invalidateMacroEpoch, isEmpty, isHTMLBundle, isLocalScope, isNotEmpty, isPlainObject, isRecordNumber, joinPath, macroOrigin, mapDeriveEntry, markSingletons, mergeDeep, mergeResponse, nullObject, pushField, rootSnapshot, schemaProperties, serializeMacroSeed, throwLifecycleErrors } from "./utils.mjs";
|
|
3
|
+
import { Ref, warmTypebox } from "./type/bridge.mjs";
|
|
4
4
|
import { isProduction } from "./universal/is-production.mjs";
|
|
5
|
-
import { Capture, Compiled, beginCompilerSession, createAotFingerprint,
|
|
5
|
+
import { Capture, Compiled, beginCompilerSession, createAotFingerprint, endCompilerSession } from "./compile/aot.mjs";
|
|
6
6
|
import { traceCapabilityRequired, wsCapabilityRequired } from "./generation.mjs";
|
|
7
|
-
import { compileHandler, composeRouteHook, localMacroRoot, resolveLocalHook } from "./compile/handler/index.mjs";
|
|
7
|
+
import { chainResolver, clearHandlerAnalysisCaches, compileHandler, composeRouteHook, localMacroRoot, resolveLocalHook } from "./compile/handler/index.mjs";
|
|
8
8
|
import { RouteFlag, buildRouteTable, routeRow } from "./route-table.mjs";
|
|
9
9
|
import { BunAdapter } from "./adapter/bun/index.mjs";
|
|
10
|
+
import { clearContextCache } from "./context.mjs";
|
|
10
11
|
import { applyHoc, createFetchHandler } from "./handler/fetch.mjs";
|
|
11
|
-
import { clearAuthoringAnalysisCaches } from "./compile/analysis-cache.mjs";
|
|
12
12
|
import { snapshotHookSchemas, snapshotSchema } from "./schema-snapshot.mjs";
|
|
13
13
|
import Memoirist from "memoirist";
|
|
14
14
|
|
|
15
15
|
//#region src/base.ts
|
|
16
16
|
const useNodesBuffer = [];
|
|
17
17
|
const emptyHistory = Object.freeze([]);
|
|
18
|
+
let mutationEpoch = 0;
|
|
19
|
+
const extCallbackIndexes = /* @__PURE__ */ new WeakMap();
|
|
20
|
+
const mergeExtCallbacks = (target, incoming) => {
|
|
21
|
+
if (!target) return incoming.slice();
|
|
22
|
+
let index = extCallbackIndexes.get(target);
|
|
23
|
+
if (!index) {
|
|
24
|
+
index = {
|
|
25
|
+
indexedLength: target.length,
|
|
26
|
+
seen: new Set(target)
|
|
27
|
+
};
|
|
28
|
+
extCallbackIndexes.set(target, index);
|
|
29
|
+
} else for (let i = index.indexedLength; i < target.length; i++) index.seen.add(target[i]);
|
|
30
|
+
for (const fn of incoming) {
|
|
31
|
+
if (index.seen.has(fn)) continue;
|
|
32
|
+
target.push(fn);
|
|
33
|
+
index.seen.add(fn);
|
|
34
|
+
}
|
|
35
|
+
index.indexedLength = target.length;
|
|
36
|
+
return target;
|
|
37
|
+
};
|
|
38
|
+
const markStoredSingletons = (table, source) => {
|
|
39
|
+
if (!table) return;
|
|
40
|
+
for (const key in source) markSingletons(table[key]);
|
|
41
|
+
};
|
|
18
42
|
const canRegisterLoose = (path, isDynamic) => !isDynamic && (path.length === 0 || path.charCodeAt(path.length - 1) === 47);
|
|
43
|
+
const isSingleSchema = (value) => "~kind" in value || "~elyAcl" in value || "~standard" in value;
|
|
44
|
+
const isSchemaValue = (value) => {
|
|
45
|
+
if (value == null || typeof value === "string") return true;
|
|
46
|
+
if (typeof value !== "object" && typeof value !== "function") return false;
|
|
47
|
+
return isSingleSchema(value) || typeof value.Check === "function";
|
|
48
|
+
};
|
|
49
|
+
const toModel = (key, value) => {
|
|
50
|
+
if ("~standard" in value) return value;
|
|
51
|
+
value = snapshotSchema(value);
|
|
52
|
+
value.$id ??= key;
|
|
53
|
+
return value;
|
|
54
|
+
};
|
|
55
|
+
const hookKeys = new Set([
|
|
56
|
+
...schemaProperties,
|
|
57
|
+
...eventProperties,
|
|
58
|
+
"detail",
|
|
59
|
+
"tags"
|
|
60
|
+
]);
|
|
61
|
+
const assertScope = (scope) => {
|
|
62
|
+
if (scope !== void 0 && scope !== "local" && scope !== "plugin" && scope !== "global") throw new Error(`[Elysia] Invalid hook scope ${JSON.stringify(scope)}, expected 'local', 'plugin' or 'global' (1.x 'scoped' is 'plugin')`);
|
|
63
|
+
};
|
|
64
|
+
const hasHookKeys = (value) => {
|
|
65
|
+
for (const key in value) if (hookKeys.has(key)) return true;
|
|
66
|
+
return false;
|
|
67
|
+
};
|
|
68
|
+
function assertSchemaShape(hook, where) {
|
|
69
|
+
for (const key in hook) {
|
|
70
|
+
if (!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
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Every key a single route must answer to, in registration order.
|
|
86
|
+
*
|
|
87
|
+
* `registerLoose` is the caller's call, not this helper's: HTTP gates it on
|
|
88
|
+
* `canRegisterLoose` because its lookup retries the trailing slash, while WS
|
|
89
|
+
* has no such retry and must own both directions outright
|
|
90
|
+
*/
|
|
91
|
+
function expandPaths(path, needsEncode, registerLoose, explicit) {
|
|
92
|
+
const variants = [path];
|
|
93
|
+
if (needsEncode) {
|
|
94
|
+
const encoded = encodeURI(path);
|
|
95
|
+
if (encoded !== path) variants.push(encoded);
|
|
96
|
+
}
|
|
97
|
+
if (!registerLoose) return variants;
|
|
98
|
+
const paths = [];
|
|
99
|
+
for (let v = 0; v < variants.length; v++) {
|
|
100
|
+
const p = variants[v];
|
|
101
|
+
paths.push(p);
|
|
102
|
+
const loose = getLoosePath(p);
|
|
103
|
+
if (loose !== p && !explicit?.has(loose)) paths.push(loose);
|
|
104
|
+
}
|
|
105
|
+
return paths;
|
|
106
|
+
}
|
|
19
107
|
var Elysia = class Elysia {
|
|
20
|
-
#hasPlugin;
|
|
21
|
-
#hasGlobal;
|
|
22
|
-
#ready;
|
|
23
|
-
#pending = 0;
|
|
24
|
-
#error;
|
|
25
|
-
#hash;
|
|
26
|
-
#childrenHash;
|
|
27
|
-
#scopeParent;
|
|
28
|
-
#pluginMacros;
|
|
29
|
-
#macroBaseline;
|
|
30
|
-
#declaredRoutes;
|
|
31
|
-
#routeSources;
|
|
32
108
|
get history() {
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
109
|
+
const generation = this["~generation"];
|
|
110
|
+
if (this.#isCacheable && this.cachedGeneration === generation && this.cachedEpoch === mutationEpoch && this.cachedHistory !== void 0) return this.cachedHistory;
|
|
111
|
+
if (this.declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
|
|
112
|
+
if (!this.declaredRoutes?.length) return emptyHistory;
|
|
113
|
+
const history = new Array(this.declaredRoutes.length);
|
|
114
|
+
for (let sequence = 0; sequence < this.declaredRoutes.length; sequence++) {
|
|
115
|
+
const route = this.declaredRoutes[sequence];
|
|
116
|
+
const source = this.routeSources?.[sequence];
|
|
39
117
|
history[sequence] = Object.freeze({
|
|
40
118
|
sequence,
|
|
41
119
|
method: route[0],
|
|
@@ -43,12 +121,17 @@ var Elysia = class Elysia {
|
|
|
43
121
|
...source === void 0 ? {} : { source }
|
|
44
122
|
});
|
|
45
123
|
}
|
|
46
|
-
|
|
124
|
+
Object.freeze(history);
|
|
125
|
+
if (this.#isCacheable) {
|
|
126
|
+
this.#cacheRoutes(generation);
|
|
127
|
+
this.cachedHistory = history;
|
|
128
|
+
}
|
|
129
|
+
return history;
|
|
47
130
|
}
|
|
48
131
|
get ["~routes"]() {
|
|
49
|
-
if (this
|
|
50
|
-
if (!this
|
|
51
|
-
const routes = this
|
|
132
|
+
if (this.declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
|
|
133
|
+
if (!this.declaredRoutes?.length) return [];
|
|
134
|
+
const routes = this.declaredRoutes;
|
|
52
135
|
if (!this["~ext"]?.macro && !this["~scopeChildren"]) return routes;
|
|
53
136
|
return routes.map((r) => {
|
|
54
137
|
const localHook = r[4];
|
|
@@ -71,17 +154,16 @@ var Elysia = class Elysia {
|
|
|
71
154
|
this.#registerRoute(route);
|
|
72
155
|
return this;
|
|
73
156
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
#jitRoute;
|
|
78
|
-
#jitStatic;
|
|
79
|
-
#jitAliases;
|
|
157
|
+
get ["~programId"]() {
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
80
160
|
constructor(config) {
|
|
161
|
+
this._pending = 0;
|
|
162
|
+
this.routerBuilt = false;
|
|
81
163
|
/**
|
|
82
164
|
* ! Don't tune
|
|
83
165
|
*
|
|
84
|
-
* Interesting JSC internal: These `= undefined`
|
|
166
|
+
* Interesting JSC internal: These `= undefined` shouldn't be removed
|
|
85
167
|
*
|
|
86
168
|
* Inline slots live inside the object cell, so JSC must pick their
|
|
87
169
|
* count at allocation before any initializer runs
|
|
@@ -99,7 +181,8 @@ var Elysia = class Elysia {
|
|
|
99
181
|
* Don't omitted field either for monomorphic access
|
|
100
182
|
*
|
|
101
183
|
* @see test/memory/instance-footprint.test.ts
|
|
102
|
-
* Est.
|
|
184
|
+
* Est. overflow 37 -> 21 = butterfly 64 -> 32 slots = 738B -> 450B;
|
|
185
|
+
* reusing the app as its program identity brings the current cell to ~386B.
|
|
103
186
|
**/
|
|
104
187
|
this["~config"] = config;
|
|
105
188
|
this["~ext"] = void 0;
|
|
@@ -119,18 +202,24 @@ var Elysia = class Elysia {
|
|
|
119
202
|
this["~introspect"] = void 0;
|
|
120
203
|
this["~scopeChild"] = void 0;
|
|
121
204
|
this["~scopeChildren"] = void 0;
|
|
122
|
-
this["~programId"] = createProgramId();
|
|
123
205
|
if (config) {
|
|
124
206
|
const { prefix, name, seed, adapter } = config;
|
|
125
207
|
this["~Prefix"] = prefix ? prefix.charCodeAt(0) === 47 ? prefix : `/${prefix}` : void 0;
|
|
126
|
-
if (name) this
|
|
208
|
+
if (name) this.hash = fnv1a(seed ? `${name}_${typeof seed === "object" ? JSON.stringify(seed, serializeMacroSeed) : seed}` : name);
|
|
127
209
|
if (adapter?.setup) this.#useFn(adapter.setup);
|
|
128
210
|
} else this["~Prefix"] = void 0;
|
|
129
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
|
+
*/
|
|
130
217
|
get routes() {
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
218
|
+
const generation = this["~generation"];
|
|
219
|
+
if (this.#isCacheable && this.cachedGeneration === generation && this.cachedEpoch === mutationEpoch && this.cachedRoutes !== void 0) return this.cachedRoutes;
|
|
220
|
+
if (this.declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
|
|
221
|
+
if (!this.declaredRoutes?.length) return [];
|
|
222
|
+
const routes = this["~routes"].map(([method, path, handler, instance, hook, appHook, inheritedChain, macroScope]) => {
|
|
134
223
|
const merged = composeRouteHook(instance, hook, appHook, inheritedChain, this, macroScope);
|
|
135
224
|
if (merged?.schemas?.length) for (const entry of merged.schemas) {
|
|
136
225
|
if (!entry?.response) continue;
|
|
@@ -144,20 +233,36 @@ var Elysia = class Elysia {
|
|
|
144
233
|
hooks: merged
|
|
145
234
|
};
|
|
146
235
|
});
|
|
236
|
+
if (this.#isCacheable && !isProduction()) {
|
|
237
|
+
Object.freeze(routes);
|
|
238
|
+
this.#cacheRoutes(generation);
|
|
239
|
+
this.cachedRoutes = routes;
|
|
240
|
+
}
|
|
241
|
+
return routes;
|
|
147
242
|
}
|
|
148
243
|
decorate(typeOrNameOrDecorators, nameOrDecorators, value) {
|
|
149
|
-
|
|
150
|
-
|
|
244
|
+
return this.#setField("decorator", arguments.length, typeOrNameOrDecorators, nameOrDecorators, value);
|
|
245
|
+
}
|
|
246
|
+
#setField(field, length, typeOrName, nameOrValue, value) {
|
|
247
|
+
let as = "append";
|
|
248
|
+
let name = "";
|
|
249
|
+
switch (length) {
|
|
250
|
+
case 1:
|
|
251
|
+
value = typeOrName;
|
|
252
|
+
break;
|
|
151
253
|
case 2:
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
254
|
+
if (typeOrName === "append" || typeOrName === "override") as = typeOrName;
|
|
255
|
+
else name = typeOrName;
|
|
256
|
+
value = nameOrValue;
|
|
257
|
+
break;
|
|
258
|
+
case 3:
|
|
259
|
+
as = typeOrName;
|
|
260
|
+
name = nameOrValue;
|
|
261
|
+
break;
|
|
262
|
+
default: return this;
|
|
155
263
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
#setField(field, as, name, value) {
|
|
159
|
-
if (this["~generation"] !== void 0) this.#assertMutable(field === "store" ? "state" : "decorate");
|
|
160
|
-
const ext = this.#ext;
|
|
264
|
+
this.#assertMutable(field === "store" ? "state" : "decorate");
|
|
265
|
+
const ext = this.ext;
|
|
161
266
|
const fresh = !ext[field];
|
|
162
267
|
const target = ext[field] ??= nullObject();
|
|
163
268
|
switch (typeof value) {
|
|
@@ -166,69 +271,71 @@ var Elysia = class Elysia {
|
|
|
166
271
|
if (!name && isEmpty(value)) return this;
|
|
167
272
|
if (name) {
|
|
168
273
|
const existing = target[name];
|
|
169
|
-
if (
|
|
274
|
+
if (existing && typeof existing === "object" && !Array.isArray(existing) && !Array.isArray(value)) target[name] = mergeDeep(target[name], value, void 0, as === "override");
|
|
170
275
|
else target[name] = value;
|
|
276
|
+
markSingletons(target[name]);
|
|
171
277
|
return this;
|
|
172
278
|
}
|
|
173
279
|
if (fresh) Object.assign(target, value);
|
|
174
280
|
else ext[field] = mergeDeep(target, value, void 0, as === "override");
|
|
281
|
+
markStoredSingletons(ext[field], value);
|
|
175
282
|
return this;
|
|
176
283
|
case "function":
|
|
177
284
|
if (name) {
|
|
178
|
-
if (as === "override" || !(name in target))
|
|
179
|
-
|
|
285
|
+
if (as === "override" || !(name in target)) {
|
|
286
|
+
target[name] = value;
|
|
287
|
+
markSingletons(value);
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
ext[field] = value(target);
|
|
291
|
+
markStoredSingletons(ext[field], ext[field]);
|
|
292
|
+
}
|
|
180
293
|
return this;
|
|
181
294
|
default:
|
|
182
295
|
if (as === "override" || !(name in target)) target[name] = value;
|
|
183
296
|
return this;
|
|
184
297
|
}
|
|
185
298
|
}
|
|
186
|
-
#decorate(as, name, value) {
|
|
187
|
-
return this.#setField("decorator", as, name, value);
|
|
188
|
-
}
|
|
189
299
|
state(typeOrNameOrStore, nameOrStore, value) {
|
|
190
|
-
|
|
191
|
-
case 1: return this.#state("append", "", typeOrNameOrStore);
|
|
192
|
-
case 2:
|
|
193
|
-
if (typeOrNameOrStore === "append" || typeOrNameOrStore === "override") return this.#state(typeOrNameOrStore, "", nameOrStore);
|
|
194
|
-
return this.#state("append", typeOrNameOrStore, nameOrStore);
|
|
195
|
-
case 3: return this.#state(typeOrNameOrStore, nameOrStore, value);
|
|
196
|
-
}
|
|
197
|
-
return this;
|
|
198
|
-
}
|
|
199
|
-
#state(as, name, value) {
|
|
200
|
-
return this.#setField("store", as, name, value);
|
|
300
|
+
return this.#setField("store", arguments.length, typeOrNameOrStore, nameOrStore, value);
|
|
201
301
|
}
|
|
202
302
|
headers(headers) {
|
|
203
303
|
this.#assertMutable("headers");
|
|
204
|
-
const ext = this
|
|
205
|
-
|
|
206
|
-
else ext.headers = Object.assign(nullObject(), headers);
|
|
304
|
+
const ext = this.ext;
|
|
305
|
+
ext.headers = Object.assign(ext.headers ?? nullObject(), headers);
|
|
207
306
|
return this;
|
|
208
307
|
}
|
|
209
308
|
#on(type, fn, scope = this["~config"]?.as) {
|
|
210
|
-
|
|
309
|
+
this.#assertMutable(type);
|
|
310
|
+
assertScope(scope);
|
|
211
311
|
const added = nullObject();
|
|
212
312
|
added[type] = fn;
|
|
213
313
|
if (type === "trace") this["~hasTrace"] = true;
|
|
314
|
+
this.#link(added, scope, this);
|
|
315
|
+
this.#tagOrigin(fn);
|
|
316
|
+
return this;
|
|
317
|
+
}
|
|
318
|
+
#link(added, scope, owner, mayRef = true, propagated) {
|
|
214
319
|
const parent = this["~hookChain"];
|
|
215
|
-
|
|
320
|
+
const refs = parent !== void 0 && parent.refs || mayRef && Elysia.#hookHasString(added);
|
|
321
|
+
this["~hookChain"] = propagated ? {
|
|
322
|
+
added,
|
|
323
|
+
parent,
|
|
324
|
+
refs,
|
|
325
|
+
scope,
|
|
326
|
+
propagated,
|
|
327
|
+
owner
|
|
328
|
+
} : {
|
|
216
329
|
added,
|
|
217
330
|
parent,
|
|
218
|
-
refs
|
|
331
|
+
refs,
|
|
219
332
|
scope,
|
|
220
|
-
owner
|
|
333
|
+
owner
|
|
221
334
|
};
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (this
|
|
225
|
-
|
|
226
|
-
if (typeof f === "function" && !fnOrigin.has(f)) fnOrigin.set(f, this.#hash);
|
|
227
|
-
};
|
|
228
|
-
if (Array.isArray(fn)) for (const f of fn) tag(f);
|
|
229
|
-
else tag(fn);
|
|
230
|
-
}
|
|
231
|
-
return this;
|
|
335
|
+
}
|
|
336
|
+
#tagOrigin(value) {
|
|
337
|
+
if (this.hash === void 0) return;
|
|
338
|
+
for (const fn of Array.isArray(value) ? value : [value]) if (typeof fn === "function" && !fnOrigin.has(fn)) fnOrigin.set(fn, this.hash);
|
|
232
339
|
}
|
|
233
340
|
#onBranch(type, scopeOrFn, fn) {
|
|
234
341
|
return fn ? this.#on(type, fn, scopeOrFn) : this.#on(type, scopeOrFn);
|
|
@@ -245,7 +352,7 @@ var Elysia = class Elysia {
|
|
|
245
352
|
}
|
|
246
353
|
parser(name, fn) {
|
|
247
354
|
this.#assertMutable("parser");
|
|
248
|
-
const ext = this
|
|
355
|
+
const ext = this.ext;
|
|
249
356
|
const parsers = ext.parser ??= nullObject();
|
|
250
357
|
parsers[name] = fn;
|
|
251
358
|
return this;
|
|
@@ -266,9 +373,7 @@ var Elysia = class Elysia {
|
|
|
266
373
|
*/
|
|
267
374
|
setup(handler) {
|
|
268
375
|
this.#assertMutable("setup");
|
|
269
|
-
|
|
270
|
-
if (Array.isArray(handler)) arr.push(...handler);
|
|
271
|
-
else arr.push(handler);
|
|
376
|
+
(this.ext.setup ??= []).push(...[].concat(handler));
|
|
272
377
|
return this;
|
|
273
378
|
}
|
|
274
379
|
transform(scopeOrFn, fn) {
|
|
@@ -278,26 +383,18 @@ var Elysia = class Elysia {
|
|
|
278
383
|
return this.#onBranch("beforeHandle", scopeOrFn, fn);
|
|
279
384
|
}
|
|
280
385
|
derive(scopeOrFn, fn) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
return
|
|
386
|
+
return this.#derive(scopeOrFn, fn);
|
|
387
|
+
}
|
|
388
|
+
#derive(scopeOrFn, fn, map) {
|
|
389
|
+
this.#onBranch("beforeHandle", scopeOrFn, fn);
|
|
390
|
+
const d = fn ?? scopeOrFn;
|
|
391
|
+
const entries = this["~hookChain"].added["~deriveEntries"] ??= [];
|
|
392
|
+
if (Array.isArray(d)) for (const f of d) entries.push(map ? map(f) : f);
|
|
393
|
+
else entries.push(map ? map(d) : d);
|
|
394
|
+
return this;
|
|
290
395
|
}
|
|
291
396
|
mapDerive(scopeOrFn, fn) {
|
|
292
|
-
|
|
293
|
-
const node = this["~hookChain"];
|
|
294
|
-
if (node?.added) {
|
|
295
|
-
const d = fn ?? scopeOrFn;
|
|
296
|
-
const entries = node.added["~deriveEntries"] ??= [];
|
|
297
|
-
if (Array.isArray(d)) for (const f of d) entries.push(mapDeriveEntry(f));
|
|
298
|
-
else entries.push(mapDeriveEntry(d));
|
|
299
|
-
}
|
|
300
|
-
return result;
|
|
397
|
+
return this.#derive(scopeOrFn, fn, mapDeriveEntry);
|
|
301
398
|
}
|
|
302
399
|
afterHandle(scopeOrFn, fn) {
|
|
303
400
|
return this.#onBranch("afterHandle", scopeOrFn, fn);
|
|
@@ -312,26 +409,19 @@ var Elysia = class Elysia {
|
|
|
312
409
|
this.#assertMutable("error");
|
|
313
410
|
switch (arguments.length) {
|
|
314
411
|
case 1:
|
|
315
|
-
if (scopeOrFnOrError && typeof scopeOrFnOrError === "object")
|
|
316
|
-
for (const [code, ErrorClass] of Object.entries(scopeOrFnOrError)) if (typeof ErrorClass === "function") (this.#ext.error ??= /* @__PURE__ */ new Map()).set(ErrorClass, code);
|
|
317
|
-
return this;
|
|
318
|
-
}
|
|
412
|
+
if (scopeOrFnOrError && typeof scopeOrFnOrError === "object") return this;
|
|
319
413
|
return this.#onBranch("error", scopeOrFnOrError);
|
|
320
414
|
case 2:
|
|
321
|
-
if (typeof scopeOrFnOrError === "function" &&
|
|
322
|
-
const run = typeof fnOrError === "function" ? fnOrError : () => fnOrError;
|
|
323
|
-
(this.#ext.error ??= /* @__PURE__ */ new Map()).set(scopeOrFnOrError, scopeOrFnOrError.name);
|
|
324
|
-
return this.#onBranch("error", createErrorEventHandler(run, scopeOrFnOrError));
|
|
325
|
-
}
|
|
415
|
+
if (typeof scopeOrFnOrError === "function" && scopeOrFnOrError.prototype instanceof Object) return this.#errorClass(scopeOrFnOrError, fnOrError);
|
|
326
416
|
return this.#onBranch("error", scopeOrFnOrError, fnOrError);
|
|
327
|
-
case 3:
|
|
328
|
-
const run = typeof fn === "function" ? fn : () => fn;
|
|
329
|
-
(this.#ext.error ??= /* @__PURE__ */ new Map()).set(fnOrError, fnOrError.name);
|
|
330
|
-
return this.#onBranch("error", scopeOrFnOrError, createErrorEventHandler(run, fnOrError));
|
|
331
|
-
}
|
|
417
|
+
case 3: return this.#errorClass(fnOrError, fn, scopeOrFnOrError);
|
|
332
418
|
}
|
|
333
419
|
return this;
|
|
334
420
|
}
|
|
421
|
+
#errorClass(ErrorClass, fn, scope) {
|
|
422
|
+
const run = typeof fn === "function" ? fn : () => fn;
|
|
423
|
+
return this.#on("error", createErrorEventHandler(run, ErrorClass), scope);
|
|
424
|
+
}
|
|
335
425
|
trace(scopeOrFn, fn) {
|
|
336
426
|
return this.#onBranch("trace", scopeOrFn, fn);
|
|
337
427
|
}
|
|
@@ -350,21 +440,13 @@ var Elysia = class Elysia {
|
|
|
350
440
|
if (node.scope !== "global") {
|
|
351
441
|
node.scope = scope;
|
|
352
442
|
node.propagated = false;
|
|
353
|
-
for (const key in node.added) {
|
|
354
|
-
if (!eventProperties.has(key)) continue;
|
|
355
|
-
const v = node.added[key];
|
|
356
|
-
const fns = Array.isArray(v) ? v : [v];
|
|
357
|
-
for (const fn of fns) {
|
|
358
|
-
if (typeof fn !== "function") continue;
|
|
359
|
-
if (scope === "plugin") this.#hasPlugin = true;
|
|
360
|
-
else this.#hasGlobal = true;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
443
|
}
|
|
364
444
|
node = node.parent;
|
|
365
445
|
}
|
|
366
446
|
}
|
|
367
447
|
guard() {
|
|
448
|
+
const maybeHook = typeof arguments[0] === "string" ? arguments[1] : arguments[0];
|
|
449
|
+
if (maybeHook && typeof maybeHook === "object" && "as" in maybeHook && maybeHook.as !== void 0) throw new Error(`[elysia] guard({ as: '${maybeHook.as}' }) was removed in 2.0. Pass the scope as the first argument instead: guard('${maybeHook.as === "scoped" ? "plugin" : maybeHook.as}', { ... }). To combine a guard schema with a route's own schema for the same slot, add schema: 'merge'.`);
|
|
368
450
|
if (arguments.length === 1) return this.#guard("local", arguments[0]);
|
|
369
451
|
if (arguments.length === 2) {
|
|
370
452
|
if (typeof arguments[1] === "function") return this.group("", arguments[0], arguments[1]);
|
|
@@ -373,21 +455,12 @@ var Elysia = class Elysia {
|
|
|
373
455
|
return this;
|
|
374
456
|
}
|
|
375
457
|
#guard(scope, hook) {
|
|
458
|
+
assertScope(scope);
|
|
459
|
+
if (hook) assertSchemaShape(hook, ".guard()");
|
|
376
460
|
hook = snapshotHookSchemas(hook);
|
|
377
461
|
hookToGuard(hook);
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
if (this.#hash !== void 0 && !fnOrigin.has(fn)) fnOrigin.set(fn, this.#hash);
|
|
381
|
-
};
|
|
382
|
-
for (const key in hook) {
|
|
383
|
-
if (!eventProperties.has(key)) continue;
|
|
384
|
-
const raw = hook[key];
|
|
385
|
-
if (raw === null) continue;
|
|
386
|
-
if (Array.isArray(raw)) for (const fn of raw) trackFn(fn);
|
|
387
|
-
else trackFn(raw);
|
|
388
|
-
}
|
|
389
|
-
if (hook.derive) if (Array.isArray(hook.derive)) for (const fn of hook.derive) trackFn(fn);
|
|
390
|
-
else trackFn(hook.derive);
|
|
462
|
+
for (const key in hook) if (eventProperties.has(key)) this.#tagOrigin(hook[key]);
|
|
463
|
+
this.#tagOrigin(hook.derive);
|
|
391
464
|
this.#pushHook(hook, scope);
|
|
392
465
|
return this;
|
|
393
466
|
}
|
|
@@ -406,7 +479,7 @@ var Elysia = class Elysia {
|
|
|
406
479
|
prefix
|
|
407
480
|
} : void 0);
|
|
408
481
|
child["~scopeChild"] = true;
|
|
409
|
-
child
|
|
482
|
+
child.scopeParent = this;
|
|
410
483
|
(this["~scopeChildren"] ??= []).push(child);
|
|
411
484
|
const src = this["~ext"];
|
|
412
485
|
if (src) {
|
|
@@ -429,7 +502,7 @@ var Elysia = class Elysia {
|
|
|
429
502
|
this.#use(child);
|
|
430
503
|
return this;
|
|
431
504
|
}
|
|
432
|
-
get
|
|
505
|
+
get ext() {
|
|
433
506
|
return this["~ext"] ??= nullObject();
|
|
434
507
|
}
|
|
435
508
|
["~resolvedCapability"](kind) {
|
|
@@ -448,9 +521,9 @@ var Elysia = class Elysia {
|
|
|
448
521
|
return provider;
|
|
449
522
|
}
|
|
450
523
|
#ensureMacroTable() {
|
|
451
|
-
const ext = this
|
|
524
|
+
const ext = this.ext;
|
|
452
525
|
if (ext.macro) return ext.macro;
|
|
453
|
-
const parent = this["~scopeChild"] ? this
|
|
526
|
+
const parent = this["~scopeChild"] ? this.scopeParent : void 0;
|
|
454
527
|
ext.macro = parent ? Object.create(parent.#ensureMacroTable()) : nullObject();
|
|
455
528
|
return ext.macro;
|
|
456
529
|
}
|
|
@@ -458,41 +531,30 @@ var Elysia = class Elysia {
|
|
|
458
531
|
this.#assertMutable("guard");
|
|
459
532
|
let hook = _hook;
|
|
460
533
|
if (hook.derive) {
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
promoted[key] = hook[key];
|
|
465
|
-
}
|
|
466
|
-
const extras = [];
|
|
467
|
-
if (hook.derive) if (Array.isArray(hook.derive)) extras.push(...hook.derive);
|
|
468
|
-
else extras.push(hook.derive);
|
|
534
|
+
const { derive, ...rest } = hook;
|
|
535
|
+
const extras = [].concat(derive);
|
|
536
|
+
hook = Object.assign(nullObject(), rest);
|
|
469
537
|
if (extras.length) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
else promoted.beforeHandle = extras;
|
|
473
|
-
(promoted["~deriveEntries"] ??= []).push(...extras);
|
|
538
|
+
hook.beforeHandle = extras.concat(hook.beforeHandle || []);
|
|
539
|
+
(hook["~deriveEntries"] ??= []).push(...extras);
|
|
474
540
|
}
|
|
475
|
-
hook = promoted;
|
|
476
541
|
}
|
|
477
542
|
if (hook.trace) this["~hasTrace"] = true;
|
|
478
|
-
|
|
479
|
-
this["~hookChain"] = {
|
|
480
|
-
added: hook,
|
|
481
|
-
parent,
|
|
482
|
-
refs: parent !== void 0 && parent.refs || Elysia.#hookHasString(hook),
|
|
483
|
-
scope,
|
|
484
|
-
owner: this
|
|
485
|
-
};
|
|
543
|
+
this.#link(hook, scope, this);
|
|
486
544
|
return this;
|
|
487
545
|
}
|
|
488
|
-
macro(macro) {
|
|
546
|
+
macro(macro, definition) {
|
|
489
547
|
this.#assertMutable("macro");
|
|
490
548
|
if (typeof macro === "function") throw new Error("use `.macro({ name: fn })` instead of `.macro(fn)`");
|
|
549
|
+
if (definition != null || typeof macro === "string") throw new Error("[Elysia] .macro(name, definition) was removed in 2.0 — use .macro({ [name]: definition })");
|
|
491
550
|
const m = this.#ensureMacroTable();
|
|
492
|
-
const baseline = this
|
|
551
|
+
const baseline = this.macroBaseline;
|
|
493
552
|
for (const key in macro) {
|
|
494
|
-
if (typeof macro[key] === "object")
|
|
495
|
-
|
|
553
|
+
if (typeof macro[key] === "object") {
|
|
554
|
+
if (macro[key]) assertSchemaShape(macro[key], `.macro(${key})`);
|
|
555
|
+
macro[key] = hookToGuard(macro[key]);
|
|
556
|
+
}
|
|
557
|
+
if (this.hash !== void 0 && !macroOrigin.has(macro[key])) macroOrigin.set(macro[key], this.hash);
|
|
496
558
|
if (baseline?.has(key) && key in m && m[key] !== macro[key]) throw new Error(`[Elysia] Macro "${key}" can be only define once`);
|
|
497
559
|
}
|
|
498
560
|
Object.assign(m, macro);
|
|
@@ -515,7 +577,7 @@ var Elysia = class Elysia {
|
|
|
515
577
|
const seedSource = hook.seed ?? value;
|
|
516
578
|
const seedType = typeof seedSource;
|
|
517
579
|
let seedKey;
|
|
518
|
-
if (seedSource === null ||
|
|
580
|
+
if (seedSource === null || seedType !== "object") seedKey = key + "\0" + seedType + "\0" + String(seedSource);
|
|
519
581
|
else try {
|
|
520
582
|
seedKey = key + "\0object\0" + JSON.stringify(seedSource, serializeMacroSeed);
|
|
521
583
|
} catch {
|
|
@@ -530,7 +592,7 @@ var Elysia = class Elysia {
|
|
|
530
592
|
}
|
|
531
593
|
for (const k in hook) {
|
|
532
594
|
const v = hook[k];
|
|
533
|
-
if (k === "seed") continue;
|
|
595
|
+
if (k === "seed" || k === "meta" || k === "$type") continue;
|
|
534
596
|
if (k === "introspect") {
|
|
535
597
|
v?.(input);
|
|
536
598
|
delete input[key];
|
|
@@ -579,11 +641,9 @@ var Elysia = class Elysia {
|
|
|
579
641
|
insertions.set(k, at + added.length);
|
|
580
642
|
} else if (k in input) {
|
|
581
643
|
if (Array.isArray(input[k])) {
|
|
582
|
-
|
|
583
|
-
for (const item of v) if (!input[k].some((e) => e === item)) input[k].unshift(item);
|
|
584
|
-
} else if (!input[k].some((item) => item === v)) input[k].unshift(v);
|
|
644
|
+
for (const item of Array.isArray(v) ? v : [v]) if (!input[k].includes(item)) input[k].unshift(item);
|
|
585
645
|
} else if (input[k] !== v) input[k] = [v, input[k]];
|
|
586
|
-
} else input[k] =
|
|
646
|
+
} else input[k] = Array.isArray(v) ? v.slice() : v;
|
|
587
647
|
delete input[key];
|
|
588
648
|
}
|
|
589
649
|
}
|
|
@@ -591,7 +651,7 @@ var Elysia = class Elysia {
|
|
|
591
651
|
}
|
|
592
652
|
use(app) {
|
|
593
653
|
if (!app) return this;
|
|
594
|
-
|
|
654
|
+
this.#assertMutable("use");
|
|
595
655
|
if (typeof app === "function") return this.#useFn(app);
|
|
596
656
|
if (typeof app.then === "function") return this.#useAsync(app);
|
|
597
657
|
if (Array.isArray(app)) {
|
|
@@ -605,21 +665,37 @@ var Elysia = class Elysia {
|
|
|
605
665
|
return this;
|
|
606
666
|
}
|
|
607
667
|
#useFn(app) {
|
|
608
|
-
const prevBaseline = this
|
|
668
|
+
const prevBaseline = this.macroBaseline;
|
|
609
669
|
const baseline = /* @__PURE__ */ new Set();
|
|
610
670
|
const existingMacro = this["~ext"]?.macro;
|
|
611
671
|
if (existingMacro) for (const k in existingMacro) baseline.add(k);
|
|
612
|
-
this
|
|
672
|
+
this.macroBaseline = baseline;
|
|
673
|
+
let wantSnapshot = false;
|
|
674
|
+
let settled = false;
|
|
675
|
+
let beforeMacro;
|
|
676
|
+
queueMicrotask(() => {
|
|
677
|
+
if (wantSnapshot && !settled) {
|
|
678
|
+
beforeMacro = new Map(Object.entries(this["~ext"]?.macro ?? nullObject()));
|
|
679
|
+
(this.macroSnapshots ??= /* @__PURE__ */ new Set()).add(beforeMacro);
|
|
680
|
+
}
|
|
681
|
+
});
|
|
613
682
|
const result = app(this);
|
|
614
|
-
this
|
|
683
|
+
this.macroBaseline = prevBaseline;
|
|
615
684
|
if (result && typeof result.then === "function") {
|
|
616
|
-
|
|
617
|
-
return this.#useAsync(result.then((value) => {
|
|
685
|
+
wantSnapshot = true;
|
|
686
|
+
return this.#useAsync(Promise.resolve(result).then((value) => {
|
|
687
|
+
settled = true;
|
|
688
|
+
if (!beforeMacro) return value;
|
|
689
|
+
this.macroSnapshots?.delete(beforeMacro);
|
|
618
690
|
const after = this["~ext"]?.macro;
|
|
619
691
|
if (after) {
|
|
620
692
|
for (const [k, def] of Object.entries(after)) if (beforeMacro.get(k) !== def) throw new Error(`Macro ${k} can only run in sync plugin`);
|
|
621
693
|
}
|
|
622
694
|
return value;
|
|
695
|
+
}, (err) => {
|
|
696
|
+
settled = true;
|
|
697
|
+
if (beforeMacro) this.macroSnapshots?.delete(beforeMacro);
|
|
698
|
+
throw err;
|
|
623
699
|
}));
|
|
624
700
|
}
|
|
625
701
|
return this;
|
|
@@ -630,17 +706,17 @@ var Elysia = class Elysia {
|
|
|
630
706
|
if (app["~introspect"] || config?.introspect) this["~introspect"] = true;
|
|
631
707
|
const name = config?.name;
|
|
632
708
|
if (name) {
|
|
633
|
-
const hash = app
|
|
634
|
-
if (this
|
|
635
|
-
this
|
|
636
|
-
this
|
|
709
|
+
const hash = app.hash;
|
|
710
|
+
if (this.childrenHash?.has(hash)) return;
|
|
711
|
+
this.childrenHash ??= /* @__PURE__ */ new Set();
|
|
712
|
+
this.childrenHash.add(hash);
|
|
637
713
|
(addedByThisCall ??= /* @__PURE__ */ new Set()).add(hash);
|
|
638
714
|
}
|
|
639
|
-
if (app
|
|
715
|
+
if (app.childrenHash) addedByThisCall = this.#absorbChildrenHash(app, addedByThisCall);
|
|
640
716
|
if (app["~ext"]) this.#assertMacroUnique(app, addedByThisCall);
|
|
641
717
|
if (app["~hasTrace"]) this["~hasTrace"] = true;
|
|
642
|
-
if (app
|
|
643
|
-
if (app
|
|
718
|
+
if (app.declaredRoutes === void 0 && app["~routeTable"]?.length) app.#materializeDeclaredRoutes();
|
|
719
|
+
if (app.declaredRoutes?.length) {
|
|
644
720
|
if (app["~hasWS"]) this["~hasWS"] = true;
|
|
645
721
|
this.#emitChildRoutes(app, this["~hookChain"], name);
|
|
646
722
|
}
|
|
@@ -650,17 +726,17 @@ var Elysia = class Elysia {
|
|
|
650
726
|
}
|
|
651
727
|
const hookChain = app["~hookChain"];
|
|
652
728
|
if (app["~ext"]) this.#absorbExt(app);
|
|
653
|
-
if (
|
|
729
|
+
if (hookChain) this.#propagateHooks(app, hookChain, addedByThisCall);
|
|
654
730
|
}
|
|
655
731
|
#absorbChildrenHash(app, addedByThisCall) {
|
|
656
|
-
const incoming = app
|
|
657
|
-
if (this
|
|
658
|
-
if (this
|
|
659
|
-
this
|
|
732
|
+
const incoming = app.childrenHash;
|
|
733
|
+
if (this.childrenHash) for (const h of incoming) {
|
|
734
|
+
if (this.childrenHash.has(h)) continue;
|
|
735
|
+
this.childrenHash.add(h);
|
|
660
736
|
(addedByThisCall ??= /* @__PURE__ */ new Set()).add(h);
|
|
661
737
|
}
|
|
662
738
|
else {
|
|
663
|
-
this
|
|
739
|
+
this.childrenHash = new Set(incoming);
|
|
664
740
|
addedByThisCall = new Set(incoming);
|
|
665
741
|
}
|
|
666
742
|
return addedByThisCall;
|
|
@@ -679,7 +755,7 @@ var Elysia = class Elysia {
|
|
|
679
755
|
if (existing === incoming) continue;
|
|
680
756
|
const origin = macroOrigin.get(existing);
|
|
681
757
|
if (origin !== void 0 && origin === macroOrigin.get(incoming)) continue;
|
|
682
|
-
if (addedByThisCall) for (const h of addedByThisCall) this
|
|
758
|
+
if (addedByThisCall) for (const h of addedByThisCall) this.childrenHash.delete(h);
|
|
683
759
|
throw new Error(`[Elysia] Macro "${macroName}" can be only define once`);
|
|
684
760
|
}
|
|
685
761
|
}
|
|
@@ -692,80 +768,54 @@ var Elysia = class Elysia {
|
|
|
692
768
|
* Keep the cold blocks in their own frames.
|
|
693
769
|
*/
|
|
694
770
|
#absorbExt(app) {
|
|
695
|
-
const { decorator, store, headers, models, parser, macro,
|
|
771
|
+
const { decorator, store, headers, models, parser, macro, hoc, setup, cleanup, capability } = app["~ext"];
|
|
696
772
|
const ext = this["~ext"] ??= nullObject();
|
|
697
|
-
if (decorator)
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
773
|
+
if (decorator) {
|
|
774
|
+
if (ext.decorator) mergeDeep(ext.decorator, decorator, void 0, true, false, void 0, { map: void 0 });
|
|
775
|
+
else ext.decorator = clonePlainDecorators(decorator);
|
|
776
|
+
markStoredSingletons(ext.decorator, decorator);
|
|
777
|
+
}
|
|
778
|
+
if (store) {
|
|
779
|
+
if (ext.store) mergeDeep(ext.store, store);
|
|
780
|
+
else ext.store = Object.assign(nullObject(), store);
|
|
781
|
+
markStoredSingletons(ext.store, store);
|
|
782
|
+
}
|
|
783
|
+
if (headers) ext.headers = Object.assign(ext.headers ?? nullObject(), headers);
|
|
784
|
+
if (models) ext.models = Object.assign(ext.models ?? nullObject(), models);
|
|
785
|
+
if (parser) ext.parser = Object.assign(ext.parser ?? nullObject(), parser);
|
|
707
786
|
if (macro) if (app["~scopeChild"]) {
|
|
708
|
-
const pluginMacros = app
|
|
787
|
+
const pluginMacros = app.pluginMacros;
|
|
709
788
|
let changed = false;
|
|
710
789
|
if (pluginMacros?.size) {
|
|
711
790
|
const target = this.#ensureMacroTable();
|
|
712
791
|
for (const [name, def] of pluginMacros) if (!(name in target)) {
|
|
713
792
|
target[name] = def;
|
|
714
793
|
changed = true;
|
|
715
|
-
if (this["~scopeChild"]) (this
|
|
794
|
+
if (this["~scopeChild"]) (this.pluginMacros ??= /* @__PURE__ */ new Map()).set(name, def);
|
|
716
795
|
}
|
|
717
796
|
}
|
|
718
797
|
if (changed) invalidateMacroEpoch();
|
|
719
798
|
} else {
|
|
720
799
|
Object.assign(this.#ensureMacroTable(), macro);
|
|
721
800
|
if (this["~scopeChild"]) {
|
|
722
|
-
const pluginMacros = this
|
|
801
|
+
const pluginMacros = this.pluginMacros ??= /* @__PURE__ */ new Map();
|
|
723
802
|
for (const name in macro) pluginMacros.set(name, macro[name]);
|
|
724
803
|
}
|
|
725
804
|
invalidateMacroEpoch();
|
|
726
805
|
}
|
|
727
|
-
if (
|
|
728
|
-
|
|
729
|
-
if (
|
|
730
|
-
const seen = new Set(ext.hoc);
|
|
731
|
-
for (const fn of hoc) if (!seen.has(fn)) {
|
|
732
|
-
seen.add(fn);
|
|
733
|
-
ext.hoc.push(fn);
|
|
734
|
-
}
|
|
735
|
-
} else ext.hoc = hoc.slice();
|
|
736
|
-
if (setup) if (ext.setup) {
|
|
737
|
-
const seen = new Set(ext.setup);
|
|
738
|
-
for (const fn of setup) if (!seen.has(fn)) {
|
|
739
|
-
seen.add(fn);
|
|
740
|
-
ext.setup.push(fn);
|
|
741
|
-
}
|
|
742
|
-
} else ext.setup = setup.slice();
|
|
743
|
-
if (cleanup) if (ext.cleanup) {
|
|
744
|
-
const seen = new Set(ext.cleanup);
|
|
745
|
-
for (const fn of cleanup) if (!seen.has(fn)) {
|
|
746
|
-
seen.add(fn);
|
|
747
|
-
ext.cleanup.push(fn);
|
|
748
|
-
}
|
|
749
|
-
} else ext.cleanup = cleanup.slice();
|
|
806
|
+
if (hoc) ext.hoc = mergeExtCallbacks(ext.hoc, hoc);
|
|
807
|
+
if (setup) ext.setup = mergeExtCallbacks(ext.setup, setup);
|
|
808
|
+
if (cleanup) ext.cleanup = mergeExtCallbacks(ext.cleanup, cleanup);
|
|
750
809
|
if (capability) {
|
|
751
810
|
const target = ext.capability ??= nullObject();
|
|
752
|
-
if (capability.trace) {
|
|
753
|
-
const incoming = capability.trace.provider;
|
|
754
|
-
if (!target.trace) target.trace = { provider: incoming };
|
|
755
|
-
}
|
|
811
|
+
if (capability.trace) target.trace ??= { provider: capability.trace.provider };
|
|
756
812
|
if (capability.ws) {
|
|
757
|
-
const incoming = capability.ws.provider;
|
|
758
|
-
const existing = target.ws;
|
|
759
813
|
const incomingOptions = capability.ws.options;
|
|
760
|
-
|
|
761
|
-
provider:
|
|
762
|
-
options:
|
|
763
|
-
depth: entry.depth + 1,
|
|
764
|
-
value: entry.value,
|
|
765
|
-
origin: entry.origin
|
|
766
|
-
})) : void 0
|
|
814
|
+
const existing = target.ws ??= {
|
|
815
|
+
provider: capability.ws.provider,
|
|
816
|
+
options: void 0
|
|
767
817
|
};
|
|
768
|
-
|
|
818
|
+
if (incomingOptions?.length) {
|
|
769
819
|
const base = existing.options ?? [];
|
|
770
820
|
const seen = new Set(base.map((e) => e.origin));
|
|
771
821
|
let next;
|
|
@@ -795,7 +845,6 @@ var Elysia = class Elysia {
|
|
|
795
845
|
let globalEvents;
|
|
796
846
|
let pluginMayRef = false;
|
|
797
847
|
let globalMayRef = false;
|
|
798
|
-
if (app.#hasGlobal) this.#hasGlobal = true;
|
|
799
848
|
const nodes = useNodesBuffer;
|
|
800
849
|
nodes.length = 0;
|
|
801
850
|
let current = hookChain;
|
|
@@ -823,10 +872,7 @@ var Elysia = class Elysia {
|
|
|
823
872
|
const target = isGlobal ? globalEvents ??= nullObject() : pluginEvents ??= nullObject();
|
|
824
873
|
if (isGlobal) globalMayRef = true;
|
|
825
874
|
else pluginMayRef = true;
|
|
826
|
-
for (const s of schemas)
|
|
827
|
-
(target.schemas ??= []).push(s);
|
|
828
|
-
if (isGlobal) this.#hasGlobal = true;
|
|
829
|
-
}
|
|
875
|
+
for (const s of schemas) (target.schemas ??= []).push(s);
|
|
830
876
|
continue;
|
|
831
877
|
}
|
|
832
878
|
if (key === "schema") continue;
|
|
@@ -836,13 +882,12 @@ var Elysia = class Elysia {
|
|
|
836
882
|
const count = many ? raw.length : 1;
|
|
837
883
|
for (let f = 0; f < count; f++) {
|
|
838
884
|
const fn = many ? raw[f] : raw;
|
|
839
|
-
const childrenHash = this
|
|
885
|
+
const childrenHash = this.childrenHash;
|
|
840
886
|
if (childrenHash !== void 0) {
|
|
841
887
|
const origin = fnOrigin.get(fn);
|
|
842
888
|
if (origin !== void 0 && childrenHash.has(origin) && !addedByThisCall?.has(origin)) continue;
|
|
843
889
|
}
|
|
844
890
|
pushField(isGlobal ? globalEvents ??= nullObject() : pluginEvents ??= nullObject(), key, fn);
|
|
845
|
-
if (isGlobal) this.#hasGlobal = true;
|
|
846
891
|
}
|
|
847
892
|
continue;
|
|
848
893
|
}
|
|
@@ -861,40 +906,46 @@ var Elysia = class Elysia {
|
|
|
861
906
|
}
|
|
862
907
|
}
|
|
863
908
|
nodes.length = 0;
|
|
864
|
-
if (globalEvents)
|
|
865
|
-
|
|
866
|
-
this["~hookChain"] = {
|
|
867
|
-
added: globalEvents,
|
|
868
|
-
parent,
|
|
869
|
-
refs: parent !== void 0 && parent.refs || globalMayRef && Elysia.#hookHasString(globalEvents),
|
|
870
|
-
scope: "global",
|
|
871
|
-
propagated: true,
|
|
872
|
-
owner: app
|
|
873
|
-
};
|
|
874
|
-
}
|
|
875
|
-
if (pluginEvents) {
|
|
876
|
-
const parent = this["~hookChain"];
|
|
877
|
-
this["~hookChain"] = {
|
|
878
|
-
added: pluginEvents,
|
|
879
|
-
parent,
|
|
880
|
-
refs: parent !== void 0 && parent.refs || pluginMayRef && Elysia.#hookHasString(pluginEvents),
|
|
881
|
-
scope: "plugin",
|
|
882
|
-
propagated: true,
|
|
883
|
-
owner: app
|
|
884
|
-
};
|
|
885
|
-
}
|
|
909
|
+
if (globalEvents) this.#link(globalEvents, "global", app, globalMayRef, true);
|
|
910
|
+
if (pluginEvents) this.#link(pluginEvents, "plugin", app, pluginMayRef, true);
|
|
886
911
|
}
|
|
887
912
|
#emitChildRoutes(app, preChain, name) {
|
|
888
|
-
const declared = app
|
|
889
|
-
if (!declared?.length) return;
|
|
913
|
+
const declared = app.declaredRoutes;
|
|
890
914
|
const limit = declared.length;
|
|
915
|
+
const tail = app["~hookChain"];
|
|
916
|
+
let recent;
|
|
917
|
+
let hasLocal = false;
|
|
891
918
|
let lastChildChain;
|
|
892
919
|
let lastCombined;
|
|
920
|
+
let lastTailChild = null;
|
|
921
|
+
let lastTailCombined;
|
|
893
922
|
for (let i = 0; i < limit; i++) {
|
|
894
923
|
const route = declared[i];
|
|
895
924
|
const childChain = route[6];
|
|
925
|
+
const absorbed = tail !== void 0 && route[3] !== app;
|
|
926
|
+
if (absorbed && recent === void 0) {
|
|
927
|
+
recent = /* @__PURE__ */ new Set();
|
|
928
|
+
for (let node = tail; node && "added" in node; node = node.parent) {
|
|
929
|
+
recent.add(node);
|
|
930
|
+
if (isLocalScope(node.scope)) {
|
|
931
|
+
hasLocal = true;
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
896
936
|
let inheritedChain;
|
|
897
|
-
if (
|
|
937
|
+
if (absorbed && hasLocal && !recent.has(rootSnapshot(childChain))) {
|
|
938
|
+
if (childChain !== lastTailChild) {
|
|
939
|
+
lastTailChild = childChain;
|
|
940
|
+
lastTailCombined = {
|
|
941
|
+
combine: childChain,
|
|
942
|
+
over: preChain,
|
|
943
|
+
tail,
|
|
944
|
+
refs: !!(childChain?.refs || preChain?.refs || tail.refs)
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
inheritedChain = lastTailCombined;
|
|
948
|
+
} else if (childChain === void 0) inheritedChain = preChain;
|
|
898
949
|
else if (preChain === void 0) inheritedChain = childChain;
|
|
899
950
|
else if (childChain === lastChildChain) inheritedChain = lastCombined;
|
|
900
951
|
else {
|
|
@@ -923,55 +974,91 @@ var Elysia = class Elysia {
|
|
|
923
974
|
], source);
|
|
924
975
|
}
|
|
925
976
|
get modules() {
|
|
926
|
-
const ready = this
|
|
977
|
+
const ready = this.ready;
|
|
927
978
|
if (!ready) {
|
|
928
|
-
if (this
|
|
979
|
+
if (this._error !== void 0) return Promise.reject(this._error.error);
|
|
929
980
|
return Promise.resolve();
|
|
930
981
|
}
|
|
931
982
|
return ready.then(() => {
|
|
932
|
-
if (this
|
|
933
|
-
if (this
|
|
983
|
+
if (this._error !== void 0) throw this._error.error;
|
|
984
|
+
if (this.ready && this.ready !== ready) return this.modules;
|
|
934
985
|
});
|
|
935
986
|
}
|
|
936
987
|
get pending() {
|
|
937
|
-
return this
|
|
988
|
+
return this._pending > 0;
|
|
938
989
|
}
|
|
939
990
|
#useAsync(promise) {
|
|
940
|
-
if (!this
|
|
941
|
-
this
|
|
942
|
-
const next = (this
|
|
991
|
+
if (!this.ready) this._error = void 0;
|
|
992
|
+
this._pending++;
|
|
993
|
+
const next = (this.ready ?? Promise.resolve()).then(() => promise).then((value) => {
|
|
943
994
|
const plugin = value && typeof value === "object" && "default" in value && value.default ? value.default : value;
|
|
995
|
+
const snapshots = this.macroSnapshots;
|
|
996
|
+
let before;
|
|
997
|
+
if (snapshots?.size) {
|
|
998
|
+
const macro = this["~ext"]?.macro;
|
|
999
|
+
before = macro ? new Map(Object.entries(macro)) : /* @__PURE__ */ new Map();
|
|
1000
|
+
}
|
|
944
1001
|
if (plugin) try {
|
|
945
1002
|
this.use(plugin);
|
|
946
1003
|
} catch (err) {
|
|
947
|
-
this
|
|
1004
|
+
this._error ??= { error: err };
|
|
948
1005
|
console.error(err);
|
|
949
1006
|
}
|
|
1007
|
+
if (before) {
|
|
1008
|
+
const after = this["~ext"]?.macro;
|
|
1009
|
+
if (after) {
|
|
1010
|
+
for (const [k, def] of Object.entries(after)) if (before.get(k) !== def) {
|
|
1011
|
+
for (const snap of snapshots) if (snap.has(k) === before.has(k) && snap.get(k) === before.get(k)) snap.set(k, def);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
950
1015
|
}).finally(() => {
|
|
951
|
-
this
|
|
1016
|
+
this._pending--;
|
|
952
1017
|
}).then(() => {}, (err) => {
|
|
953
|
-
this
|
|
1018
|
+
this._error ??= { error: err };
|
|
954
1019
|
console.error(err);
|
|
955
|
-
}).finally(() =>
|
|
956
|
-
|
|
1020
|
+
}).finally(() => {
|
|
1021
|
+
if (this._pending > 0) return;
|
|
1022
|
+
if (this.ready !== next) return;
|
|
1023
|
+
const previousCompiled = this.compiled;
|
|
1024
|
+
const previousJitColdRemaining = this.jitColdRemaining;
|
|
1025
|
+
this.ready = void 0;
|
|
1026
|
+
this.compiled = void 0;
|
|
1027
|
+
this.fetchFn = void 0;
|
|
1028
|
+
this.routerBuilt = false;
|
|
1029
|
+
clearContextCache(this);
|
|
1030
|
+
try {
|
|
1031
|
+
this.#buildRouter(false);
|
|
1032
|
+
} catch (error) {
|
|
1033
|
+
this.compiled = previousCompiled;
|
|
1034
|
+
this.jitColdRemaining = previousJitColdRemaining;
|
|
1035
|
+
this._error ??= { error };
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
this.ready = next;
|
|
957
1039
|
return this;
|
|
958
1040
|
}
|
|
959
|
-
#tryDrain(sentinel) {
|
|
960
|
-
if (this.#pending > 0) return;
|
|
961
|
-
if (this.#ready !== sentinel) return;
|
|
962
|
-
this.#ready = void 0;
|
|
963
|
-
this.#fetchFn = void 0;
|
|
964
|
-
this.#routerBuilt = false;
|
|
965
|
-
this.#buildRouter(false);
|
|
966
|
-
}
|
|
967
1041
|
#add(method, path, hookOrFn, fn, hasHook = fn !== void 0) {
|
|
968
1042
|
if (this["~Prefix"]) path = joinPath(this["~Prefix"], path);
|
|
969
1043
|
else if (path && path.charCodeAt(0) !== 47) path = "/" + path;
|
|
1044
|
+
if (typeof hookOrFn === "function" && isPlainObject(fn) && !hasHookKeys(hookOrFn)) {
|
|
1045
|
+
let isHook = hasHookKeys(fn);
|
|
1046
|
+
const macro = this["~ext"]?.macro;
|
|
1047
|
+
if (!isHook && macro) {
|
|
1048
|
+
for (const key in fn) if (key in macro) {
|
|
1049
|
+
isHook = true;
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
if (isHook) 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`);
|
|
1054
|
+
}
|
|
1055
|
+
if (hasHook && hookOrFn) assertSchemaShape(hookOrFn, `${method} ${path}`);
|
|
970
1056
|
const handler = hasHook ? fn : hookOrFn;
|
|
971
1057
|
const hook = hasHook ? snapshotHookSchemas(hookOrFn) : void 0;
|
|
972
1058
|
const appHook = this["~hookChain"];
|
|
973
|
-
|
|
974
|
-
|
|
1059
|
+
const verb = this["~generation"] === void 0 ? "method" : method === "*" ? "all" : method.toLowerCase();
|
|
1060
|
+
this.#assertMutable(verb in this ? verb : "method");
|
|
1061
|
+
(this.declaredRoutes ?? this.#materializeDeclaredRoutes()).push(appHook ? [
|
|
975
1062
|
method,
|
|
976
1063
|
path,
|
|
977
1064
|
handler,
|
|
@@ -990,76 +1077,61 @@ var Elysia = class Elysia {
|
|
|
990
1077
|
handler,
|
|
991
1078
|
this
|
|
992
1079
|
]);
|
|
993
|
-
if (this
|
|
994
|
-
this.#compiled = void 0;
|
|
995
|
-
this.#jitColdRemaining = void 0;
|
|
996
|
-
this.#jitTable = void 0;
|
|
997
|
-
this.#jitRoute = void 0;
|
|
998
|
-
this.#jitStatic = void 0;
|
|
999
|
-
this.#jitAliases = void 0;
|
|
1000
|
-
this.#fetchFn = void 0;
|
|
1001
|
-
this.#routerBuilt = false;
|
|
1002
|
-
}
|
|
1080
|
+
if (this.routerBuilt || this.compiled !== void 0) this.#invalidate();
|
|
1003
1081
|
return this;
|
|
1004
1082
|
}
|
|
1005
1083
|
#assertMutable(api) {
|
|
1084
|
+
mutationEpoch++;
|
|
1006
1085
|
if (this["~generation"] === void 0) return;
|
|
1007
|
-
throw new Error(`[Elysia] .${api}() called after the app was sealed`);
|
|
1086
|
+
throw new Error(`[Elysia] .${api}() called after the app was sealed by its first request, listen or compile`);
|
|
1087
|
+
}
|
|
1088
|
+
get #isCacheable() {
|
|
1089
|
+
return this["~generation"] !== void 0 && this.routerBuilt && !Capture.isCapturing();
|
|
1090
|
+
}
|
|
1091
|
+
#cacheRoutes(generation) {
|
|
1092
|
+
if (this.cachedGeneration === generation && this.cachedEpoch === mutationEpoch) return;
|
|
1093
|
+
this.cachedGeneration = generation;
|
|
1094
|
+
this.cachedEpoch = mutationEpoch;
|
|
1095
|
+
this.cachedRoutes = void 0;
|
|
1096
|
+
this.cachedHistory = void 0;
|
|
1008
1097
|
}
|
|
1009
1098
|
#materializeDeclaredRoutes() {
|
|
1010
|
-
if (this
|
|
1099
|
+
if (this.declaredRoutes !== void 0) return this.declaredRoutes;
|
|
1011
1100
|
const table = this["~routeTable"];
|
|
1012
|
-
if (!table) return this
|
|
1101
|
+
if (!table) return this.declaredRoutes = [];
|
|
1013
1102
|
const routes = new Array(table.length);
|
|
1014
1103
|
for (let i = 0; i < table.length; i++) routes[i] = routeRow(table, i);
|
|
1015
|
-
return this
|
|
1104
|
+
return this.declaredRoutes = routes;
|
|
1016
1105
|
}
|
|
1017
1106
|
#registerRoute(route, source) {
|
|
1018
|
-
|
|
1019
|
-
const routes = this
|
|
1107
|
+
this.#assertMutable("route");
|
|
1108
|
+
const routes = this.declaredRoutes ?? this.#materializeDeclaredRoutes();
|
|
1020
1109
|
const sequence = routes.length;
|
|
1021
1110
|
routes.push(route);
|
|
1022
|
-
if (source) (this
|
|
1023
|
-
if (this
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1111
|
+
if (source) (this.routeSources ??= [])[sequence] = source;
|
|
1112
|
+
if (this.routerBuilt || this.compiled !== void 0) this.#invalidate();
|
|
1113
|
+
}
|
|
1114
|
+
#invalidate() {
|
|
1115
|
+
this.compiled = void 0;
|
|
1116
|
+
this.jitColdRemaining = void 0;
|
|
1117
|
+
this.jitTable = void 0;
|
|
1118
|
+
this.jitRoute = void 0;
|
|
1119
|
+
this.jitAliases = void 0;
|
|
1120
|
+
this.fetchFn = void 0;
|
|
1121
|
+
this.routerBuilt = false;
|
|
1033
1122
|
}
|
|
1034
1123
|
model(name, model) {
|
|
1035
1124
|
this.#assertMutable("model");
|
|
1036
|
-
const models = this
|
|
1125
|
+
const models = this.ext.models ??= nullObject();
|
|
1037
1126
|
switch (typeof name) {
|
|
1038
1127
|
case "object":
|
|
1039
|
-
const
|
|
1040
|
-
if (entries.length) for (let [key, value] of entries) {
|
|
1041
|
-
if (key in models) continue;
|
|
1042
|
-
if ("~standard" in value) models[key] = value;
|
|
1043
|
-
else {
|
|
1044
|
-
value = snapshotSchema(value);
|
|
1045
|
-
value.$id ??= key;
|
|
1046
|
-
models[key] = value;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1128
|
+
for (const [key, value] of Object.entries(name)) if (!(key in models)) models[key] = toModel(key, value);
|
|
1049
1129
|
return this;
|
|
1050
1130
|
case "function": {
|
|
1051
|
-
const remapped = name(models
|
|
1131
|
+
const remapped = name(models);
|
|
1052
1132
|
const next = nullObject();
|
|
1053
|
-
for (const key in remapped)
|
|
1054
|
-
|
|
1055
|
-
if ("~standard" in value) next[key] = value;
|
|
1056
|
-
else {
|
|
1057
|
-
value = snapshotSchema(value);
|
|
1058
|
-
value.$id ??= key;
|
|
1059
|
-
next[key] = value;
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
this.#ext.models = next;
|
|
1133
|
+
for (const key in remapped) next[key] = toModel(key, remapped[key]);
|
|
1134
|
+
this.ext.models = next;
|
|
1063
1135
|
return this;
|
|
1064
1136
|
}
|
|
1065
1137
|
case "string":
|
|
@@ -1094,6 +1166,9 @@ var Elysia = class Elysia {
|
|
|
1094
1166
|
options(path, hookOrFn, fn) {
|
|
1095
1167
|
return this.#add("OPTIONS", path, hookOrFn, fn);
|
|
1096
1168
|
}
|
|
1169
|
+
query(path, hookOrFn, fn) {
|
|
1170
|
+
return this.#add("QUERY", path, hookOrFn, fn);
|
|
1171
|
+
}
|
|
1097
1172
|
head(path, hookOrFn, fn) {
|
|
1098
1173
|
return this.#add("HEAD", path, hookOrFn, fn);
|
|
1099
1174
|
}
|
|
@@ -1118,22 +1193,18 @@ var Elysia = class Elysia {
|
|
|
1118
1193
|
this.#add("WS", path, opts, void 0, true);
|
|
1119
1194
|
return this;
|
|
1120
1195
|
}
|
|
1121
|
-
mount(path,
|
|
1196
|
+
mount(path, handler) {
|
|
1122
1197
|
const options = {
|
|
1123
|
-
...config,
|
|
1124
1198
|
parse: "none",
|
|
1125
|
-
detail: {
|
|
1126
|
-
...config?.detail,
|
|
1127
|
-
hide: true
|
|
1128
|
-
}
|
|
1199
|
+
detail: { hide: true }
|
|
1129
1200
|
};
|
|
1130
1201
|
if (typeof path === "function" || path === "" || path === "/") {
|
|
1131
|
-
const run = typeof path === "function" ? path : typeof
|
|
1202
|
+
const run = typeof path === "function" ? path : typeof handler === "function" ? handler : null;
|
|
1132
1203
|
if (!run) throw new Error("Invalid handler");
|
|
1133
1204
|
this.all("/*", options, Elysia.#mountHandler(run, 2));
|
|
1134
1205
|
return this;
|
|
1135
1206
|
}
|
|
1136
|
-
const handle = typeof
|
|
1207
|
+
const handle = typeof handler === "function" ? handler : null;
|
|
1137
1208
|
if (!handle) throw new Error("Invalid handler");
|
|
1138
1209
|
const endsStar = path.endsWith("*") ? 1 : 0;
|
|
1139
1210
|
const wildcardSuffix = path.endsWith("/") ? "*" : "/*";
|
|
@@ -1169,75 +1240,102 @@ var Elysia = class Elysia {
|
|
|
1169
1240
|
compile() {
|
|
1170
1241
|
this["~config"] ??= nullObject();
|
|
1171
1242
|
this["~config"].precompile = true;
|
|
1172
|
-
this.#
|
|
1173
|
-
this.#compiled = void 0;
|
|
1174
|
-
this.#jitColdRemaining = void 0;
|
|
1175
|
-
this.#jitTable = void 0;
|
|
1176
|
-
this.#jitRoute = void 0;
|
|
1177
|
-
this.#jitStatic = void 0;
|
|
1178
|
-
this.#jitAliases = void 0;
|
|
1179
|
-
this.#fetchFn = void 0;
|
|
1243
|
+
this.#invalidate();
|
|
1180
1244
|
this.fetch;
|
|
1181
1245
|
return this;
|
|
1182
1246
|
}
|
|
1183
|
-
handler(index, immediate
|
|
1184
|
-
if (this
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1247
|
+
handler(index, immediate, route, aliases, table) {
|
|
1248
|
+
if (this.compiled?.[index]) return this.compiled[index];
|
|
1249
|
+
const indexedTable = table ?? (this.routerBuilt ? this["~routeTable"] : void 0);
|
|
1250
|
+
const compiled = this.compiled ??= new Array(indexedTable?.length ?? this["~routes"].length);
|
|
1251
|
+
if (immediate ?? this["~config"]?.precompile) {
|
|
1252
|
+
const row = route ?? (indexedTable ? routeRow(indexedTable, index) : this["~routes"][index]);
|
|
1253
|
+
const exactDuplicate = ((indexedTable?.flags[index] ?? 0) & RouteFlag.ExactDuplicate) !== 0;
|
|
1188
1254
|
let handler;
|
|
1189
1255
|
try {
|
|
1190
|
-
handler = compileHandler(row, this,
|
|
1256
|
+
handler = compileHandler(row, this, exactDuplicate && Compiled.hasProgram(this["~programId"]));
|
|
1191
1257
|
} catch (error) {
|
|
1192
1258
|
throw new Error(`[Elysia] Failed to compile route ${row[0]} ${row[1]}: ${error?.message ?? error}`, { cause: error });
|
|
1193
1259
|
}
|
|
1194
1260
|
compiled[index] = handler;
|
|
1195
|
-
this.#
|
|
1261
|
+
if (indexedTable) this.#satisfyJit(indexedTable, index);
|
|
1196
1262
|
return handler;
|
|
1197
1263
|
}
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
if (
|
|
1202
|
-
if (route !== void 0) (this.#jitRoute ??= [])[index] = route;
|
|
1203
|
-
if (precomputedStatic !== void 0) (this.#jitStatic ??= [])[index] = precomputedStatic;
|
|
1204
|
-
if (aliases !== void 0) (this.#jitAliases ??= [])[index] = aliases;
|
|
1264
|
+
const jitRoute = route ?? (indexedTable ? void 0 : this["~routes"][index]);
|
|
1265
|
+
if (indexedTable !== void 0) this.jitTable = indexedTable;
|
|
1266
|
+
if (jitRoute !== void 0) (this.jitRoute ??= [])[index] = jitRoute;
|
|
1267
|
+
if (aliases !== void 0) (this.jitAliases ??= [])[index] = aliases;
|
|
1205
1268
|
return (context) => this.#jitDispatch(index, context);
|
|
1206
1269
|
}
|
|
1270
|
+
#staticAliases(table, index) {
|
|
1271
|
+
const flags = table.flags[index];
|
|
1272
|
+
if ((flags & (RouteFlag.WS | RouteFlag.Dynamic)) !== 0) return;
|
|
1273
|
+
const path = table.path[index];
|
|
1274
|
+
const method = table.method[index];
|
|
1275
|
+
const needsEncode = (flags & RouteFlag.Encode) !== 0;
|
|
1276
|
+
const registerLoose = this["~config"]?.strictPath !== true && canRegisterLoose(path, false);
|
|
1277
|
+
if (!needsEncode && !registerLoose) return;
|
|
1278
|
+
let explicit;
|
|
1279
|
+
if (registerLoose) {
|
|
1280
|
+
explicit = /* @__PURE__ */ new Set();
|
|
1281
|
+
for (let i = 0; i < table.length; i++) {
|
|
1282
|
+
if (table.method[i] !== method) continue;
|
|
1283
|
+
const declared = table.path[i];
|
|
1284
|
+
explicit.add(declared);
|
|
1285
|
+
if ((table.flags[i] & RouteFlag.Encode) !== 0) explicit.add(encodeURI(declared));
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
return {
|
|
1289
|
+
method,
|
|
1290
|
+
paths: expandPaths(path, needsEncode, registerLoose, explicit)
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
#releaseJit() {
|
|
1294
|
+
Compiled.release(this["~programId"]);
|
|
1295
|
+
this.jitColdRemaining = void 0;
|
|
1296
|
+
this.jitRoute = void 0;
|
|
1297
|
+
this.jitAliases = void 0;
|
|
1298
|
+
this.jitTable = void 0;
|
|
1299
|
+
}
|
|
1300
|
+
#satisfyJit(table, index) {
|
|
1301
|
+
if ((table.flags[index] & RouteFlag.ExactDuplicate) !== 0) return false;
|
|
1302
|
+
if (this.jitColdRemaining === void 0) {
|
|
1303
|
+
if (this["~generation"] === void 0 && this["~config"]?.precompile !== true && isProduction() && !Capture.isAotBuildEnv()) table.flags[index] |= RouteFlag.JITSatisfied;
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
if ((table.flags[index] & RouteFlag.JITCold) === 0) return false;
|
|
1307
|
+
table.flags[index] &= ~RouteFlag.JITCold;
|
|
1308
|
+
if (--this.jitColdRemaining > 0) return false;
|
|
1309
|
+
this.#releaseJit();
|
|
1310
|
+
return true;
|
|
1311
|
+
}
|
|
1207
1312
|
#jitDispatch(index, context) {
|
|
1208
|
-
if (this
|
|
1209
|
-
const
|
|
1313
|
+
if (this.compiled[index]) return this.compiled[index](context);
|
|
1314
|
+
const route = this.jitRoute?.[index];
|
|
1315
|
+
const table = this.jitTable ?? this["~routeTable"];
|
|
1316
|
+
const materialized = route ?? routeRow(table, index);
|
|
1317
|
+
const exactDuplicate = ((table?.flags[index] ?? 0) & RouteFlag.ExactDuplicate) !== 0;
|
|
1210
1318
|
let handler;
|
|
1211
1319
|
try {
|
|
1212
|
-
handler = compileHandler(materialized, this, this
|
|
1320
|
+
handler = compileHandler(materialized, this, exactDuplicate && Compiled.hasProgram(this["~programId"]));
|
|
1213
1321
|
} catch (error) {
|
|
1214
1322
|
const routeError = new Error(`[Elysia] Failed to compile route ${materialized[0]} ${materialized[1]}: ${error?.message ?? error}`, { cause: error });
|
|
1215
1323
|
const finalize = this["~finalizeError"];
|
|
1216
1324
|
if (finalize) return finalize(context, routeError);
|
|
1217
1325
|
throw routeError;
|
|
1218
1326
|
}
|
|
1219
|
-
this
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1327
|
+
this.compiled[index] = handler;
|
|
1328
|
+
if (!exactDuplicate) {
|
|
1329
|
+
const aliases = this.jitAliases?.[index] ?? (table ? this.#staticAliases(table, index) : void 0);
|
|
1330
|
+
if (aliases) {
|
|
1331
|
+
this.#initMap();
|
|
1332
|
+
const map = this["~map"][aliases.method] ??= nullObject();
|
|
1333
|
+
for (let p = 0; p < aliases.paths.length; p++) map[aliases.paths[p]] = handler;
|
|
1334
|
+
} else this.#saveHandler(materialized[0], materialized[1], handler);
|
|
1225
1335
|
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
this
|
|
1229
|
-
const map = this["~map"][aliases.method] ??= nullObject();
|
|
1230
|
-
for (let p = 0; p < aliases.paths.length; p++) map[aliases.paths[p]] = handler;
|
|
1231
|
-
} else this.#saveHandler(materialized[0], materialized[1], handler);
|
|
1232
|
-
if (releasedNow) {
|
|
1233
|
-
this.#jitRoute = void 0;
|
|
1234
|
-
this.#jitStatic = void 0;
|
|
1235
|
-
this.#jitAliases = void 0;
|
|
1236
|
-
this.#jitTable = void 0;
|
|
1237
|
-
} else {
|
|
1238
|
-
if (this.#jitRoute) this.#jitRoute[index] = void 0;
|
|
1239
|
-
if (this.#jitStatic) this.#jitStatic[index] = void 0;
|
|
1240
|
-
if (this.#jitAliases) this.#jitAliases[index] = void 0;
|
|
1336
|
+
if (!(table ? this.#satisfyJit(table, index) : false)) {
|
|
1337
|
+
if (this.jitRoute) this.jitRoute[index] = void 0;
|
|
1338
|
+
if (this.jitAliases) this.jitAliases[index] = void 0;
|
|
1241
1339
|
}
|
|
1242
1340
|
return handler(context);
|
|
1243
1341
|
}
|
|
@@ -1254,7 +1352,7 @@ var Elysia = class Elysia {
|
|
|
1254
1352
|
if (typeof response === "string") return true;
|
|
1255
1353
|
if (response && typeof response === "object") {
|
|
1256
1354
|
const record = response;
|
|
1257
|
-
if (!(
|
|
1355
|
+
if (!isSingleSchema(record)) {
|
|
1258
1356
|
for (const status in record) if (typeof record[status] === "string") return true;
|
|
1259
1357
|
}
|
|
1260
1358
|
}
|
|
@@ -1268,16 +1366,41 @@ var Elysia = class Elysia {
|
|
|
1268
1366
|
}
|
|
1269
1367
|
return false;
|
|
1270
1368
|
}
|
|
1271
|
-
#
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
if (
|
|
1276
|
-
if (Elysia.#
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1369
|
+
static #slotHasTypeBox(value, models, record) {
|
|
1370
|
+
if (typeof value === "string") value = models?.[value];
|
|
1371
|
+
if (!value || typeof value !== "object") return false;
|
|
1372
|
+
if ("~kind" in value || "~elyAcl" in value) return true;
|
|
1373
|
+
if (!record || "~standard" in value) return false;
|
|
1374
|
+
for (const status in value) if (Elysia.#slotHasTypeBox(value[status], models)) return true;
|
|
1375
|
+
return false;
|
|
1376
|
+
}
|
|
1377
|
+
static #hookHasTypeBox(h, models) {
|
|
1378
|
+
if (!h || typeof h !== "object") return false;
|
|
1379
|
+
for (const key in h) {
|
|
1380
|
+
if (key === "schemas") {
|
|
1381
|
+
const schemas = h[key];
|
|
1382
|
+
if (Array.isArray(schemas)) {
|
|
1383
|
+
for (let s = 0; s < schemas.length; s++) if (Elysia.#hookHasTypeBox(schemas[s], models)) return true;
|
|
1384
|
+
}
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
if (schemaProperties.has(key) && Elysia.#slotHasTypeBox(h[key], models, key === "response")) return true;
|
|
1388
|
+
}
|
|
1389
|
+
return false;
|
|
1390
|
+
}
|
|
1391
|
+
static #chainHasTypeBox(node, models, seen, resolve) {
|
|
1392
|
+
while (node) {
|
|
1393
|
+
if (seen.has(node)) return false;
|
|
1394
|
+
seen.add(node);
|
|
1395
|
+
if ("added" in node) {
|
|
1396
|
+
if (Elysia.#hookHasTypeBox(resolve ? resolve(node) : node.added, models)) return true;
|
|
1397
|
+
node = node.parent;
|
|
1398
|
+
} else {
|
|
1399
|
+
if (Elysia.#chainHasTypeBox(node.combine, models, seen, resolve) || Elysia.#chainHasTypeBox(node.tail, models, seen, resolve)) return true;
|
|
1400
|
+
node = node.over;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
return false;
|
|
1281
1404
|
}
|
|
1282
1405
|
#assertRouteModelRefs(route, method) {
|
|
1283
1406
|
const models = this["~ext"]?.models;
|
|
@@ -1291,7 +1414,7 @@ var Elysia = class Elysia {
|
|
|
1291
1414
|
if (!models || !(v in models)) throw new Error(`[Elysia] Unknown model reference "${v}" for ${key} on route ${method} ${path}.`);
|
|
1292
1415
|
} else if (key === "response" && v && typeof v === "object") {
|
|
1293
1416
|
const record = v;
|
|
1294
|
-
if (
|
|
1417
|
+
if (isSingleSchema(record)) continue;
|
|
1295
1418
|
for (const status in record) {
|
|
1296
1419
|
const r = record[status];
|
|
1297
1420
|
if (typeof r === "string" && (!models || !(r in models))) throw new Error(`[Elysia] Unknown model reference "${r}" for response ${status} on route ${method} ${path}.`);
|
|
@@ -1304,30 +1427,27 @@ var Elysia = class Elysia {
|
|
|
1304
1427
|
const schemas = hook?.schemas;
|
|
1305
1428
|
if (Array.isArray(schemas)) for (let s = 0; s < schemas.length; s++) checkSlots(schemas[s]);
|
|
1306
1429
|
}
|
|
1307
|
-
#routerBuilt = false;
|
|
1308
1430
|
#buildRouter(seal = false) {
|
|
1309
|
-
if (this
|
|
1431
|
+
if (this.routerBuilt) {
|
|
1310
1432
|
if (seal && this["~generation"] === void 0) this.#publishGeneration();
|
|
1311
1433
|
return;
|
|
1312
1434
|
}
|
|
1313
1435
|
const compilerSession = beginCompilerSession(this);
|
|
1314
1436
|
const previousMap = this["~map"];
|
|
1315
1437
|
const previousRouter = this["~router"];
|
|
1316
|
-
const previousCompiled = this
|
|
1317
|
-
const previousJitTable = this
|
|
1318
|
-
const previousJitRoute = this
|
|
1319
|
-
const
|
|
1320
|
-
const previousJitAliases = this.#jitAliases;
|
|
1438
|
+
const previousCompiled = this.compiled;
|
|
1439
|
+
const previousJitTable = this.jitTable;
|
|
1440
|
+
const previousJitRoute = this.jitRoute;
|
|
1441
|
+
const previousJitAliases = this.jitAliases;
|
|
1321
1442
|
const previousHasDynamicWS = this["~hasDynamicWS"];
|
|
1322
1443
|
const previousGeneration = this["~generation"];
|
|
1323
1444
|
this["~map"] = void 0;
|
|
1324
1445
|
this["~router"] = void 0;
|
|
1325
|
-
this
|
|
1326
|
-
this
|
|
1327
|
-
this
|
|
1328
|
-
this
|
|
1329
|
-
this
|
|
1330
|
-
this.#jitAliases = void 0;
|
|
1446
|
+
this.compiled = previousCompiled?.slice();
|
|
1447
|
+
this.jitColdRemaining = void 0;
|
|
1448
|
+
this.jitTable = void 0;
|
|
1449
|
+
this.jitRoute = void 0;
|
|
1450
|
+
this.jitAliases = void 0;
|
|
1331
1451
|
this["~hasDynamicWS"] = void 0;
|
|
1332
1452
|
this["~generation"] = void 0;
|
|
1333
1453
|
let buildSucceeded = false;
|
|
@@ -1343,18 +1463,17 @@ var Elysia = class Elysia {
|
|
|
1343
1463
|
Object.assign(previousRouter, nextRouter);
|
|
1344
1464
|
this["~router"] = previousRouter;
|
|
1345
1465
|
}
|
|
1346
|
-
this
|
|
1466
|
+
this.routerBuilt = true;
|
|
1347
1467
|
if (seal) this.#publishGeneration();
|
|
1348
1468
|
buildSucceeded = true;
|
|
1349
1469
|
} catch (error) {
|
|
1350
1470
|
this["~map"] = previousMap;
|
|
1351
1471
|
this["~router"] = previousRouter;
|
|
1352
|
-
this
|
|
1353
|
-
this
|
|
1354
|
-
this
|
|
1355
|
-
this
|
|
1356
|
-
this
|
|
1357
|
-
this.#jitAliases = previousJitAliases;
|
|
1472
|
+
this.compiled = previousCompiled;
|
|
1473
|
+
this.jitColdRemaining = void 0;
|
|
1474
|
+
this.jitTable = previousJitTable;
|
|
1475
|
+
this.jitRoute = previousJitRoute;
|
|
1476
|
+
this.jitAliases = previousJitAliases;
|
|
1358
1477
|
this["~hasDynamicWS"] = previousHasDynamicWS;
|
|
1359
1478
|
this["~generation"] = previousGeneration;
|
|
1360
1479
|
throw error;
|
|
@@ -1375,26 +1494,31 @@ var Elysia = class Elysia {
|
|
|
1375
1494
|
"~wsConfig": this["~wsConfig"]
|
|
1376
1495
|
};
|
|
1377
1496
|
if (isProduction() && !Capture.isAotBuildEnv()) {
|
|
1378
|
-
if (this["~config"]?.precompile)
|
|
1497
|
+
if (this["~config"]?.precompile) this.#releaseJit();
|
|
1379
1498
|
else {
|
|
1380
1499
|
const table = this["~routeTable"];
|
|
1381
|
-
const routeCount = table
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
for (let i = 0; i < routeCount; i++)
|
|
1385
|
-
|
|
1386
|
-
|
|
1500
|
+
const routeCount = table.length;
|
|
1501
|
+
const compiled = this.compiled;
|
|
1502
|
+
let cold = 0;
|
|
1503
|
+
for (let i = 0; i < routeCount; i++) {
|
|
1504
|
+
const satisfied = (table.flags[i] & RouteFlag.JITSatisfied) !== 0;
|
|
1505
|
+
table.flags[i] &= ~(RouteFlag.JITCold | RouteFlag.JITSatisfied);
|
|
1506
|
+
const flags = table.flags[i];
|
|
1507
|
+
if (satisfied || (flags & (RouteFlag.WS | RouteFlag.ExactDuplicate)) !== 0 || compiled?.[i] !== void 0) continue;
|
|
1508
|
+
table.flags[i] |= RouteFlag.JITCold;
|
|
1509
|
+
cold++;
|
|
1510
|
+
}
|
|
1511
|
+
if (cold === 0) this.#releaseJit();
|
|
1512
|
+
else this.jitColdRemaining = cold;
|
|
1387
1513
|
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1514
|
+
clearHandlerAnalysisCaches(this);
|
|
1515
|
+
clearFlattenChainMemo(this);
|
|
1516
|
+
if (!this["~ext"]?.macro && !this["~scopeChildren"]) this.declaredRoutes = void 0;
|
|
1390
1517
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
this["~generation"] = void 0;
|
|
1396
|
-
this.#buildRouter(true);
|
|
1397
|
-
return this;
|
|
1518
|
+
const ext = this["~ext"];
|
|
1519
|
+
if (ext?.hoc) extCallbackIndexes.delete(ext.hoc);
|
|
1520
|
+
if (ext?.setup) extCallbackIndexes.delete(ext.setup);
|
|
1521
|
+
if (ext?.cleanup) extCallbackIndexes.delete(ext.cleanup);
|
|
1398
1522
|
}
|
|
1399
1523
|
#buildRouterUnsafe() {
|
|
1400
1524
|
const precompile = this["~config"]?.precompile;
|
|
@@ -1410,21 +1534,52 @@ var Elysia = class Elysia {
|
|
|
1410
1534
|
const length = table.length;
|
|
1411
1535
|
const appChain = this["~hookChain"];
|
|
1412
1536
|
if (this["~ext"]?.macro || this["~scopeChildren"] || appChain !== void 0 && appChain.refs) for (let i = 0; i < length; i++) this.#assertRouteModelRefs(routeRow(table, i), method[i]);
|
|
1413
|
-
else for (let i = 0; i < length; i++)
|
|
1414
|
-
|
|
1537
|
+
else for (let i = 0; i < length; i++) {
|
|
1538
|
+
const macroScope = table.macroScope?.get(i);
|
|
1539
|
+
const owner = table.owner[i];
|
|
1540
|
+
const candidate = macroScope ?? owner ?? this;
|
|
1541
|
+
if ((candidate === this ? this : localMacroRoot(candidate, this))["~ext"]?.macro || Elysia.#hookHasString(table.localHook[i]) || table.appHook[i]?.refs || table.inheritedChain[i]?.refs) this.#assertRouteModelRefs(routeRow(table, i), method[i]);
|
|
1542
|
+
}
|
|
1543
|
+
let hasTypeBoxSchema = false;
|
|
1544
|
+
if (length) {
|
|
1545
|
+
const models = this["~ext"]?.models;
|
|
1546
|
+
const resolve = chainResolver(this);
|
|
1547
|
+
const rootChain = this["~hookChain"];
|
|
1548
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1549
|
+
const { localHook, appHook, inheritedChain, owner } = table;
|
|
1550
|
+
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)) {
|
|
1551
|
+
hasTypeBoxSchema = true;
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
if (hasTypeBoxSchema) try {
|
|
1556
|
+
warmTypebox();
|
|
1557
|
+
} catch {}
|
|
1558
|
+
let markDuplicates = false;
|
|
1559
|
+
if (length) {
|
|
1560
|
+
const programId = this["~programId"];
|
|
1561
|
+
if (!Compiled.claim(programId, this["~aotFingerprint"] = createAotFingerprint())) Compiled.assertUncontested(programId);
|
|
1562
|
+
markDuplicates = Compiled.hasProgram(programId) || precompile !== true && isProduction() && !Capture.isAotBuildEnv();
|
|
1563
|
+
}
|
|
1415
1564
|
const isLoose = this["~config"]?.strictPath !== true;
|
|
1565
|
+
const collectExplicit = isLoose && table.hasLoose;
|
|
1416
1566
|
let explicitPaths;
|
|
1417
|
-
if (
|
|
1418
|
-
|
|
1567
|
+
if (markDuplicates || collectExplicit) {
|
|
1568
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1569
|
+
if (collectExplicit) explicitPaths = seen;
|
|
1419
1570
|
for (let i = 0; i < length; i++) {
|
|
1420
1571
|
const m = method[i];
|
|
1421
1572
|
const p = path[i];
|
|
1422
|
-
let
|
|
1423
|
-
if (!
|
|
1424
|
-
|
|
1425
|
-
|
|
1573
|
+
let paths = seen.get(m);
|
|
1574
|
+
if (!paths) seen.set(m, paths = /* @__PURE__ */ new Map());
|
|
1575
|
+
if (markDuplicates && (flags[i] & RouteFlag.WS) === 0) {
|
|
1576
|
+
const displaced = paths.get(p);
|
|
1577
|
+
if (displaced !== void 0 && displaced >= 0) flags[displaced] |= RouteFlag.ExactDuplicate;
|
|
1578
|
+
paths.set(p, i);
|
|
1579
|
+
} else paths.set(p, -1);
|
|
1580
|
+
if (collectExplicit && (flags[i] & RouteFlag.Encode) !== 0) {
|
|
1426
1581
|
const encoded = encodeURI(p);
|
|
1427
|
-
if (encoded !== p) set
|
|
1582
|
+
if (encoded !== p && !paths.has(encoded)) paths.set(encoded, -1);
|
|
1428
1583
|
}
|
|
1429
1584
|
}
|
|
1430
1585
|
}
|
|
@@ -1437,54 +1592,40 @@ var Elysia = class Elysia {
|
|
|
1437
1592
|
const handler = ws[0];
|
|
1438
1593
|
const options = ws[1];
|
|
1439
1594
|
if (wsConfig === void 0 && wsCap.options) wsConfig = wsCap.options;
|
|
1595
|
+
const wsNeedsEncode = (routeFlags & RouteFlag.Encode) !== 0;
|
|
1440
1596
|
if ((routeFlags & RouteFlag.Dynamic) !== 0) {
|
|
1441
|
-
|
|
1597
|
+
const wsRouter = this["~router"] ??= new Memoirist({ loosePath: isLoose });
|
|
1598
|
+
const wsPaths = expandPaths(routePath, wsNeedsEncode, false, void 0);
|
|
1599
|
+
for (let v = 0; v < wsPaths.length; v++) wsRouter.add("WS", wsPaths[v], handler);
|
|
1442
1600
|
this["~hasDynamicWS"] = true;
|
|
1443
1601
|
} else {
|
|
1444
|
-
this.#initMap();
|
|
1445
1602
|
const wsMap = this["~map"]["WS"] ??= nullObject();
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
const loose = getLoosePath(routePath);
|
|
1449
|
-
if (loose !== routePath && !explicitPaths?.get("WS")?.has(loose)) wsMap[loose] = handler;
|
|
1450
|
-
}
|
|
1603
|
+
const wsPaths = expandPaths(routePath, wsNeedsEncode, isLoose, isLoose ? explicitPaths?.get("WS") : void 0);
|
|
1604
|
+
for (let v = 0; v < wsPaths.length; v++) wsMap[wsPaths[v]] = handler;
|
|
1451
1605
|
}
|
|
1452
1606
|
if (options && isNotEmpty(options)) {
|
|
1453
1607
|
wsConfig ??= nullObject();
|
|
1454
|
-
wsCap.provider.accumulateOptions(wsConfig, options
|
|
1608
|
+
wsCap.provider.accumulateOptions(wsConfig, options);
|
|
1455
1609
|
}
|
|
1456
1610
|
continue;
|
|
1457
1611
|
}
|
|
1458
1612
|
const isDynamic = (routeFlags & RouteFlag.Dynamic) !== 0;
|
|
1459
1613
|
const needsEncode = (routeFlags & RouteFlag.Encode) !== 0;
|
|
1460
1614
|
const registerLoose = isLoose && canRegisterLoose(routePath, isDynamic);
|
|
1461
|
-
const explicitMain = registerLoose ? explicitPaths?.get(routeMethod) : void 0;
|
|
1462
1615
|
if (!isDynamic && !needsEncode && !registerLoose) {
|
|
1463
1616
|
const map = methods[routeMethod] ??= nullObject();
|
|
1464
|
-
map[routePath] = this.handler(i, precompile, void 0, void 0,
|
|
1617
|
+
map[routePath] = this.handler(i, precompile, void 0, void 0, table);
|
|
1465
1618
|
continue;
|
|
1466
1619
|
}
|
|
1467
|
-
const
|
|
1468
|
-
if (needsEncode) {
|
|
1469
|
-
const encoded = encodeURI(routePath);
|
|
1470
|
-
if (encoded !== routePath) variants.push(encoded);
|
|
1471
|
-
}
|
|
1472
|
-
const paths = [];
|
|
1473
|
-
for (let v = 0; v < variants.length; v++) {
|
|
1474
|
-
const p = variants[v];
|
|
1475
|
-
paths.push(p);
|
|
1476
|
-
if (registerLoose) {
|
|
1477
|
-
const loose = getLoosePath(p);
|
|
1478
|
-
if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1620
|
+
const paths = expandPaths(routePath, needsEncode, registerLoose, registerLoose ? explicitPaths?.get(routeMethod) : void 0);
|
|
1481
1621
|
if (isDynamic) {
|
|
1622
|
+
if (isHTMLBundle(table.handler[i])) continue;
|
|
1482
1623
|
const router = this["~router"] ??= new Memoirist({ loosePath: isLoose });
|
|
1483
|
-
const handler = this.handler(i, precompile, void 0, void 0,
|
|
1624
|
+
const handler = this.handler(i, precompile, void 0, void 0, table);
|
|
1484
1625
|
for (let p = 0; p < paths.length; p++) router.add(routeMethod, paths[p], handler);
|
|
1485
1626
|
} else {
|
|
1486
1627
|
const map = methods[routeMethod] ??= nullObject();
|
|
1487
|
-
const handler = this.handler(i, precompile, void 0,
|
|
1628
|
+
const handler = this.handler(i, precompile, void 0, {
|
|
1488
1629
|
method: routeMethod,
|
|
1489
1630
|
paths
|
|
1490
1631
|
}, table);
|
|
@@ -1493,19 +1634,28 @@ var Elysia = class Elysia {
|
|
|
1493
1634
|
}
|
|
1494
1635
|
this["~wsConfig"] = wsConfig;
|
|
1495
1636
|
}
|
|
1496
|
-
#fetchFn;
|
|
1497
1637
|
get fetch() {
|
|
1498
|
-
if (this
|
|
1499
|
-
|
|
1500
|
-
|
|
1638
|
+
if (this.fetchFn) return this.fetchFn;
|
|
1639
|
+
if (this.ready) return (request, ...rest) => {
|
|
1640
|
+
const run = () => this.fetch(request, ...rest);
|
|
1641
|
+
return this.ready ? this.modules.then(run, run) : run();
|
|
1642
|
+
};
|
|
1643
|
+
return this.#dispatch();
|
|
1644
|
+
}
|
|
1645
|
+
#dispatch() {
|
|
1646
|
+
this.#buildRouter(!this._pending);
|
|
1647
|
+
if (this.ready) return applyHoc(this, createFetchHandler(this));
|
|
1648
|
+
return this.fetchFn ??= applyHoc(this, createFetchHandler(this));
|
|
1501
1649
|
}
|
|
1502
|
-
#handle;
|
|
1503
1650
|
get handle() {
|
|
1504
|
-
return this
|
|
1651
|
+
return this._handle ??= async (requestOrUrl, options) => (this.fetchFn ?? this.#dispatch())(typeof requestOrUrl === "string" ? new Request(requestOrUrl.charCodeAt(0) === 47 ? `http://e.ly${requestOrUrl}` : requestOrUrl, options) : requestOrUrl);
|
|
1505
1652
|
}
|
|
1506
1653
|
listen(options, callback) {
|
|
1507
1654
|
const listen = (this["~config"]?.adapter ?? (isBun ? BunAdapter : void 0))?.listen;
|
|
1508
|
-
if (!listen)
|
|
1655
|
+
if (!listen) {
|
|
1656
|
+
const deno = typeof Deno !== "undefined";
|
|
1657
|
+
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"}`);
|
|
1658
|
+
}
|
|
1509
1659
|
if (!Capture.isAotBuildEnv()) listen(this, options, callback);
|
|
1510
1660
|
return this;
|
|
1511
1661
|
}
|
|
@@ -1526,8 +1676,8 @@ var Elysia = class Elysia {
|
|
|
1526
1676
|
*/
|
|
1527
1677
|
wrap(callback) {
|
|
1528
1678
|
this.#assertMutable("wrap");
|
|
1529
|
-
if (this
|
|
1530
|
-
const ext = this
|
|
1679
|
+
if (this.fetchFn && !this._pending) console.warn("[Elysia] .wrap() was called after the fetch handler was built");
|
|
1680
|
+
const ext = this.ext;
|
|
1531
1681
|
(ext.hoc ??= []).push(callback);
|
|
1532
1682
|
return this;
|
|
1533
1683
|
}
|
|
@@ -1545,31 +1695,49 @@ var Elysia = class Elysia {
|
|
|
1545
1695
|
* ```
|
|
1546
1696
|
*/
|
|
1547
1697
|
cleanup(handler) {
|
|
1698
|
+
if (this["~ext"]?.cleanupEpoch?.(handler)) return this;
|
|
1548
1699
|
this.#assertMutable("cleanup");
|
|
1549
|
-
|
|
1550
|
-
if (Array.isArray(handler)) arr.push(...handler);
|
|
1551
|
-
else arr.push(handler);
|
|
1700
|
+
(this.ext.cleanup ??= []).push(...[].concat(handler));
|
|
1552
1701
|
return this;
|
|
1553
1702
|
}
|
|
1554
1703
|
/**
|
|
1555
|
-
* Stop the underlying server (if any),
|
|
1556
|
-
* it has stopped. Mirrors `Server.stop()`.
|
|
1704
|
+
* Stop the underlying server (if any), then run every `cleanup` handler
|
|
1557
1705
|
*
|
|
1558
|
-
*
|
|
1559
|
-
*
|
|
1560
|
-
*
|
|
1706
|
+
* Awaiting `stop()` from inside a `setup`, `cleanup` or WebSocket lifecycle
|
|
1707
|
+
* callback is only supported while that callback is still synchronous
|
|
1708
|
+
*
|
|
1709
|
+
* @param closeActiveConnections Pass `true` to terminate active
|
|
1710
|
+
* transports. Omit (or pass `false`) to drain safely.
|
|
1561
1711
|
*/
|
|
1562
1712
|
stop(closeActiveConnections) {
|
|
1713
|
+
const stop = this["~ext"]?.stop;
|
|
1714
|
+
if (stop) return stop(closeActiveConnections);
|
|
1563
1715
|
const server = this.server;
|
|
1564
1716
|
if (!server) return;
|
|
1565
|
-
|
|
1566
|
-
|
|
1717
|
+
let result;
|
|
1718
|
+
const errors = [];
|
|
1719
|
+
try {
|
|
1720
|
+
result = server.stop?.(closeActiveConnections);
|
|
1721
|
+
} catch (error) {
|
|
1722
|
+
errors.push(error);
|
|
1723
|
+
} finally {
|
|
1724
|
+
this.server = void 0;
|
|
1725
|
+
}
|
|
1567
1726
|
const handlers = this["~ext"]?.cleanup;
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1727
|
+
if (!errors.length && !handlers?.length) return result && typeof result.then === "function" ? result : void 0;
|
|
1728
|
+
return (async () => {
|
|
1729
|
+
try {
|
|
1730
|
+
await result;
|
|
1731
|
+
} catch (error) {
|
|
1732
|
+
errors.push(error);
|
|
1733
|
+
}
|
|
1734
|
+
if (handlers) for (let i = 0; i < handlers.length; i++) try {
|
|
1735
|
+
await handlers[i](this);
|
|
1736
|
+
} catch (error) {
|
|
1737
|
+
errors.push(error);
|
|
1738
|
+
}
|
|
1739
|
+
throwLifecycleErrors(errors);
|
|
1740
|
+
})();
|
|
1573
1741
|
}
|
|
1574
1742
|
};
|
|
1575
1743
|
|