elysia 2.0.0-exp.2 → 2.0.0-exp.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.
Files changed (135) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +2 -0
  2. package/dist/adapter/bun/index.d.ts +2 -25
  3. package/dist/adapter/bun/index.js +18 -12
  4. package/dist/adapter/bun/index.mjs +19 -13
  5. package/dist/adapter/bun/router.js +1 -1
  6. package/dist/adapter/bun/router.mjs +1 -1
  7. package/dist/adapter/constants.d.ts +3 -26
  8. package/dist/adapter/index.d.ts +1 -26
  9. package/dist/adapter/index.js +1 -17
  10. package/dist/adapter/index.mjs +1 -17
  11. package/dist/adapter/types.d.ts +1 -0
  12. package/dist/adapter/utils.d.ts +3 -4
  13. package/dist/adapter/utils.js +83 -81
  14. package/dist/adapter/utils.mjs +82 -80
  15. package/dist/adapter/web-standard/handler.js +6 -3
  16. package/dist/adapter/web-standard/handler.mjs +6 -3
  17. package/dist/adapter/web-standard/index.d.ts +2 -26
  18. package/dist/adapter/web-standard/index.js +12 -1
  19. package/dist/adapter/web-standard/index.mjs +12 -1
  20. package/dist/base.d.ts +38 -68
  21. package/dist/base.js +133 -97
  22. package/dist/base.mjs +133 -97
  23. package/dist/compile/aot.d.ts +22 -1
  24. package/dist/compile/aot.js +22 -0
  25. package/dist/compile/aot.mjs +22 -0
  26. package/dist/compile/handler/index.d.ts +2 -2
  27. package/dist/compile/handler/index.js +85 -456
  28. package/dist/compile/handler/index.mjs +86 -457
  29. package/dist/compile/handler/jit.d.ts +35 -0
  30. package/dist/compile/handler/jit.js +445 -0
  31. package/dist/compile/handler/jit.mjs +443 -0
  32. package/dist/compile/handler/params.js +3 -2
  33. package/dist/compile/handler/params.mjs +4 -3
  34. package/dist/compile/handler/reconstruct.d.ts +13 -0
  35. package/dist/compile/handler/reconstruct.js +29 -0
  36. package/dist/compile/handler/reconstruct.mjs +28 -0
  37. package/dist/compile/handler/utils.d.ts +2 -1
  38. package/dist/compile/handler/utils.js +9 -3
  39. package/dist/compile/handler/utils.mjs +9 -4
  40. package/dist/compile/jit-probe.d.ts +19 -0
  41. package/dist/compile/jit-probe.js +38 -0
  42. package/dist/compile/jit-probe.mjs +36 -0
  43. package/dist/cookie/index.d.ts +4 -3
  44. package/dist/cookie/index.js +2 -1
  45. package/dist/cookie/index.mjs +2 -1
  46. package/dist/cookie/serialize.d.ts +6 -0
  47. package/dist/cookie/serialize.js +28 -0
  48. package/dist/cookie/serialize.mjs +27 -0
  49. package/dist/cookie/utils.d.ts +1 -2
  50. package/dist/cookie/utils.js +2 -23
  51. package/dist/cookie/utils.mjs +5 -25
  52. package/dist/handler/error.js +2 -2
  53. package/dist/handler/error.mjs +3 -3
  54. package/dist/handler/fetch.js +49 -42
  55. package/dist/handler/fetch.mjs +50 -43
  56. package/dist/index.d.ts +13 -8
  57. package/dist/index.js +11 -4
  58. package/dist/index.mjs +7 -6
  59. package/dist/parse-query.js +1 -1
  60. package/dist/parse-query.mjs +1 -1
  61. package/dist/plugin/bun.d.ts +10 -0
  62. package/dist/plugin/bun.js +18 -1
  63. package/dist/plugin/bun.mjs +19 -2
  64. package/dist/plugin/core.d.ts +61 -1
  65. package/dist/plugin/core.js +90 -10
  66. package/dist/plugin/core.mjs +90 -12
  67. package/dist/plugin/esbuild.d.ts +10 -0
  68. package/dist/plugin/esbuild.js +18 -1
  69. package/dist/plugin/esbuild.mjs +19 -2
  70. package/dist/plugin/source.d.ts +38 -1
  71. package/dist/plugin/source.js +104 -13
  72. package/dist/plugin/source.mjs +102 -14
  73. package/dist/plugin/vite.d.ts +7 -0
  74. package/dist/plugin/vite.js +22 -1
  75. package/dist/plugin/vite.mjs +23 -2
  76. package/dist/sucrose.js +23 -10
  77. package/dist/sucrose.mjs +23 -10
  78. package/dist/trace.d.ts +1 -1
  79. package/dist/trace.js +4 -6
  80. package/dist/trace.mjs +4 -6
  81. package/dist/type/bridge.d.ts +9 -8
  82. package/dist/type/coerce.d.ts +20 -2
  83. package/dist/type/coerce.js +110 -0
  84. package/dist/type/coerce.mjs +109 -2
  85. package/dist/type/compat.js +4 -3
  86. package/dist/type/compat.mjs +2 -1
  87. package/dist/type/constants.d.ts +1 -1
  88. package/dist/type/elysia/boolean-string.js +1 -1
  89. package/dist/type/elysia/boolean-string.mjs +1 -1
  90. package/dist/type/elysia/file-type.js +1 -1
  91. package/dist/type/elysia/file-type.mjs +1 -1
  92. package/dist/type/elysia/integer-string.js +1 -1
  93. package/dist/type/elysia/integer-string.mjs +1 -1
  94. package/dist/type/exports.js +29 -2059
  95. package/dist/type/exports.mjs +7 -295
  96. package/dist/type/index.d.ts +6 -2
  97. package/dist/type/index.js +4 -0
  98. package/dist/type/index.mjs +3 -1
  99. package/dist/type/types.d.ts +1 -1
  100. package/dist/type/utils.js +4 -4
  101. package/dist/type/utils.mjs +4 -4
  102. package/dist/type/validator/custom-error.d.ts +10 -0
  103. package/dist/type/validator/custom-error.js +113 -0
  104. package/dist/type/validator/custom-error.mjs +110 -0
  105. package/dist/type/validator/default-precompute.d.ts +22 -0
  106. package/dist/type/validator/default-precompute.js +476 -0
  107. package/dist/type/validator/default-precompute.mjs +465 -0
  108. package/dist/type/validator/frozen-check.d.ts +11 -0
  109. package/dist/type/validator/frozen-check.js +19 -0
  110. package/dist/type/validator/frozen-check.mjs +18 -0
  111. package/dist/type/{validator.d.ts → validator/index.d.ts} +7 -20
  112. package/dist/type/validator/index.js +572 -0
  113. package/dist/type/validator/index.mjs +567 -0
  114. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  115. package/dist/type/validator/string-codec-aot.js +106 -0
  116. package/dist/type/validator/string-codec-aot.mjs +102 -0
  117. package/dist/type/validator/validator-cache.d.ts +21 -0
  118. package/dist/type/validator/validator-cache.js +163 -0
  119. package/dist/type/validator/validator-cache.mjs +161 -0
  120. package/dist/types.d.ts +22 -14
  121. package/dist/universal/file.d.ts +1 -1
  122. package/dist/universal/file.js +35 -29
  123. package/dist/universal/file.mjs +35 -29
  124. package/dist/utils.d.ts +12 -1
  125. package/dist/utils.js +89 -45
  126. package/dist/utils.mjs +88 -46
  127. package/dist/validator/index.d.ts +1 -1
  128. package/dist/validator/index.js +15 -2
  129. package/dist/validator/index.mjs +15 -2
  130. package/dist/validator/route.d.ts +0 -1
  131. package/dist/ws/route.js +47 -24
  132. package/dist/ws/route.mjs +48 -25
  133. package/package.json +10 -4
  134. package/dist/type/validator.js +0 -1033
  135. package/dist/type/validator.mjs +0 -1029
package/dist/base.mjs CHANGED
@@ -1,35 +1,20 @@
1
1
  import { isBun } from "./universal/constants.mjs";
2
2
  import { MethodMap, isDynamicRegex, needEncodeRegex } from "./constants.mjs";
3
- import { coalesceStandaloneSchemas, createErrorEventHandler, eventProperties, flattenChain, fnOrigin, fnv1a, getLoosePath, hookToGuard, isEmpty, isNotEmpty, isRecordNumber, joinPath, mapMethodBack, mergeDeep, mergeResponse, nullObject, pushField, replaceUrlPath, schemaProperties } from "./utils.mjs";
3
+ import { clonePlainDecorators, coalesceStandaloneSchemas, createErrorEventHandler, eventProperties, flattenChain, fnOrigin, fnv1a, getLoosePath, hookToGuard, isEmpty, isNotEmpty, isRecordNumber, joinPath, mapMethodBack, mergeDeep, mergeResponse, nullObject, pushField, replaceUrlPath, schemaProperties } from "./utils.mjs";
4
4
  import { Ref } from "./type/bridge.mjs";
5
5
  import { env } from "./universal/env.mjs";
6
+ import { Capture } from "./compile/aot.mjs";
7
+ import { buildNativeStaticResponse, compileHandler, composeRouteHook } from "./compile/handler/index.mjs";
6
8
  import { buildWSRoute } from "./ws/route.mjs";
7
9
  import { BunAdapter } from "./adapter/bun/index.mjs";
8
10
  import { applyHoc, createFetchHandler } from "./handler/fetch.mjs";
9
- import { buildNativeStaticResponse, compileHandler, composeRouteHook } from "./compile/handler/index.mjs";
10
11
  import Memoirist from "memoirist";
11
12
 
12
13
  //#region src/base.ts
13
14
  const useNodesBuffer = [];
14
- const isPlainObject = (v) => {
15
- if (!v || typeof v !== "object" || Array.isArray(v)) return false;
16
- const proto = Object.getPrototypeOf(v);
17
- return proto === Object.prototype || proto === null;
18
- };
19
- function clonePlainDecorators(source, seen = /* @__PURE__ */ new WeakMap()) {
20
- const existing = seen.get(source);
21
- if (existing) return existing;
22
- const out = nullObject();
23
- seen.set(source, out);
24
- for (const key in source) {
25
- const value = source[key];
26
- out[key] = isPlainObject(value) ? clonePlainDecorators(value, seen) : value;
27
- }
28
- return out;
29
- }
30
15
  var Elysia = class Elysia {
31
- #hasPlugin = false;
32
- #hasGlobal = false;
16
+ #hasPlugin;
17
+ #hasGlobal;
33
18
  #ready;
34
19
  #pending = 0;
35
20
  #error;
@@ -50,6 +35,7 @@ var Elysia = class Elysia {
50
35
  }
51
36
  #compiled;
52
37
  #cachedRoutes;
38
+ #hasMapResponse;
53
39
  constructor(config) {
54
40
  this["~config"] = config;
55
41
  this["~Prefix"] = config?.prefix;
@@ -170,23 +156,8 @@ var Elysia = class Elysia {
170
156
  #onBranch(type, scopeOrFn, fn) {
171
157
  return fn ? this.#on(type, fn, scopeOrFn) : this.#on(type, scopeOrFn);
172
158
  }
173
- on(...args) {
174
- if (args.length === 2) {
175
- const [event, fn] = args;
176
- if (event === "parse" && typeof fn === "string") {
177
- const named = this["~ext"]?.parser?.[fn];
178
- return this.#onBranch("parse", named ?? fn);
179
- }
180
- return this.#onBranch(event, fn);
181
- }
182
- if (args.length === 3) {
183
- const [scope, event, fn] = args;
184
- return this.#onBranch(event, scope, fn);
185
- }
186
- return this;
187
- }
188
- request(scopeOrFn, fn) {
189
- return this.#onBranch("request", scopeOrFn, fn);
159
+ request(fn) {
160
+ return this.#on("request", fn, "global");
190
161
  }
191
162
  parse(scopeOrFnOrName, fn) {
192
163
  if (fn === void 0 && typeof scopeOrFnOrName === "string") {
@@ -201,10 +172,24 @@ var Elysia = class Elysia {
201
172
  parsers[name] = fn;
202
173
  return this;
203
174
  }
204
- onStart(_listener) {
205
- return this;
206
- }
207
- onStop(_listener) {
175
+ /**
176
+ * ### setup | Life cycle event
177
+ * Called after server is ready for serving
178
+ *
179
+ * ---
180
+ * @example
181
+ * ```typescript
182
+ * new Elysia()
183
+ * .setup(({ server }) => {
184
+ * console.log("Running at ${server?.url}:${server?.port}")
185
+ * })
186
+ * .listen(3000)
187
+ * ```
188
+ */
189
+ setup(handler) {
190
+ const arr = this.#ext.setup ??= [];
191
+ if (Array.isArray(handler)) arr.push(...handler);
192
+ else arr.push(handler);
208
193
  return this;
209
194
  }
210
195
  transform(scopeOrFn, fn) {
@@ -225,6 +210,7 @@ var Elysia = class Elysia {
225
210
  return this.#onBranch("afterHandle", scopeOrFn, fn);
226
211
  }
227
212
  mapResponse(scopeOrFn, fn) {
213
+ this.#hasMapResponse = true;
228
214
  return this.#onBranch("mapResponse", scopeOrFn, fn);
229
215
  }
230
216
  afterResponse(scopeOrFn, fn) {
@@ -286,15 +272,7 @@ var Elysia = class Elysia {
286
272
  }
287
273
  }
288
274
  guard() {
289
- if (arguments.length === 1) {
290
- const arg = arguments[0];
291
- let scope = "local";
292
- if (arg && typeof arg === "object" && "as" in arg && arg.as) {
293
- scope = arg.as;
294
- delete arg.as;
295
- }
296
- return this.#guard(scope, arg);
297
- }
275
+ if (arguments.length === 1) return this.#guard("local", arguments[0]);
298
276
  if (arguments.length === 2) {
299
277
  if (typeof arguments[1] === "function") return this.group("", arguments[0], arguments[1]);
300
278
  return this.#guard(arguments[0], arguments[1]);
@@ -351,9 +329,8 @@ var Elysia = class Elysia {
351
329
  const finalize = () => {
352
330
  const childFlat = flattenChain(child["~hookChain"]);
353
331
  const lifted = nullObject();
354
- if (childFlat?.request) lifted.request = childFlat.request;
355
332
  if (childFlat?.parse) lifted.parse = childFlat.parse;
356
- if (lifted.request || lifted.parse) this.#pushHook(lifted);
333
+ if (lifted.parse) this.#pushHook(lifted);
357
334
  return child;
358
335
  };
359
336
  if (child.pending) return this.#useAsync(child.modules.then(finalize));
@@ -391,7 +368,7 @@ var Elysia = class Elysia {
391
368
  return this;
392
369
  }
393
370
  macro(macro) {
394
- if (typeof macro === "function") throw new Error("Use `.macro({ name: fn })` instead of `.macro(fn)`");
371
+ if (typeof macro === "function") throw new Error("use `.macro({ name: fn })` instead of `.macro(fn)`");
395
372
  const ext = this.#ext;
396
373
  const m = ext.macro ??= nullObject();
397
374
  for (const key in macro) if (typeof macro[key] === "object") macro[key] = hookToGuard(macro[key]);
@@ -487,7 +464,8 @@ var Elysia = class Elysia {
487
464
  for (const plugin of app) this.#use(plugin);
488
465
  return this;
489
466
  }
490
- if (app !== this && app.pending) return this.#useAsync(app.modules.then(() => app));
467
+ if (app === this) return this;
468
+ if (app.pending) return this.#useAsync(app.modules.then(() => app));
491
469
  this.#use(app);
492
470
  return this;
493
471
  }
@@ -553,8 +531,9 @@ var Elysia = class Elysia {
553
531
  }
554
532
  }
555
533
  const hookChain = app["~hookChain"];
534
+ if (!this.#hasMapResponse && app.#hasMapResponse) this.#hasMapResponse = true;
556
535
  if (app["~ext"]) {
557
- const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
536
+ const { decorator, store, headers, models, parser, macro, error, hoc, setup, cleanup } = app["~ext"];
558
537
  const ext = this["~ext"] ??= nullObject();
559
538
  if (decorator) {
560
539
  const cloned = clonePlainDecorators(decorator);
@@ -576,6 +555,12 @@ var Elysia = class Elysia {
576
555
  if (hoc) if (ext.hoc) {
577
556
  for (const fn of hoc) if (!ext.hoc.includes(fn)) ext.hoc.push(fn);
578
557
  } else ext.hoc = hoc.slice();
558
+ if (setup) if (ext.setup) {
559
+ for (const fn of setup) if (!ext.setup.includes(fn)) ext.setup.push(fn);
560
+ } else ext.setup = setup.slice();
561
+ if (cleanup) if (ext.cleanup) {
562
+ for (const fn of cleanup) if (!ext.cleanup.includes(fn)) ext.cleanup.push(fn);
563
+ } else ext.cleanup = cleanup.slice();
579
564
  }
580
565
  if (app.#hasPlugin || app.#hasGlobal || hookChain) {
581
566
  let pluginEvents;
@@ -826,18 +811,23 @@ var Elysia = class Elysia {
826
811
  }
827
812
  #initMap() {
828
813
  this["~map"] ??= {
829
- GET: nullObject(),
830
- POST: nullObject(),
831
- PUT: nullObject(),
832
- DELETE: nullObject(),
833
- PATCH: nullObject(),
834
- HEAD: nullObject(),
835
- OPTIONS: nullObject()
814
+ GET: void 0,
815
+ POST: void 0,
816
+ PUT: void 0,
817
+ DELETE: void 0,
818
+ PATCH: void 0,
819
+ HEAD: void 0,
820
+ OPTIONS: void 0
836
821
  };
837
822
  }
838
823
  compile() {
839
824
  this["~config"] ??= nullObject();
840
825
  this["~config"].precompile = true;
826
+ this.#routerBuilt = false;
827
+ if (Capture.isCapturing()) {
828
+ this.#compiled = void 0;
829
+ this.#fetchFn = void 0;
830
+ }
841
831
  this.fetch;
842
832
  return this;
843
833
  }
@@ -864,6 +854,7 @@ var Elysia = class Elysia {
864
854
  };
865
855
  }
866
856
  #saveHandler(method, path, handler) {
857
+ if (isDynamicRegex.test(path)) return;
867
858
  this.#initMap();
868
859
  const map = this["~map"][mapMethodBack(method)] ??= nullObject();
869
860
  map[path] = handler;
@@ -908,9 +899,9 @@ var Elysia = class Elysia {
908
899
  for (let i = 0; i < length; i++) if (mapMethodBack(this.#history[i][0]) === "HEAD") (explicitHead ??= /* @__PURE__ */ new Set()).add(this.#history[i][1]);
909
900
  }
910
901
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
911
- const strict = !!this["~config"]?.strictPath;
902
+ const preferLoosePath = this["~config"]?.strictPath !== true;
912
903
  let explicitPaths;
913
- if (!strict) {
904
+ if (preferLoosePath && this["~config"]?.distinctPath) {
914
905
  explicitPaths = /* @__PURE__ */ new Map();
915
906
  for (let i = 0; i < length; i++) {
916
907
  const route = this.#history[i];
@@ -933,7 +924,7 @@ var Elysia = class Elysia {
933
924
  const ws = buildWSRoute(route, this);
934
925
  const handler = ws[0];
935
926
  const options = ws[1];
936
- if (isDynamicRegex.test(path)) (this["~router"] ??= new Memoirist()).add("WS", path, handler, false);
927
+ if (isDynamicRegex.test(path)) (this["~router"] ??= new Memoirist({ loosePath: preferLoosePath })).add("WS", path, handler, false);
937
928
  else {
938
929
  this.#initMap();
939
930
  const wsMap = this["~map"]["WS"] ??= nullObject();
@@ -960,51 +951,70 @@ var Elysia = class Elysia {
960
951
  let staticResponse;
961
952
  const maybeStatic = buildStatic && typeof route[2] !== "function";
962
953
  if (maybeStatic) {
963
- staticResponse = buildNativeStaticResponse(route, this);
954
+ staticResponse = buildNativeStaticResponse(route, this, this.#hasMapResponse);
964
955
  if (staticResponse) {
965
- const target = this["~staticResponse"] ??= nullObject();
966
- (target[path] ??= nullObject())[method] = staticResponse;
956
+ const target = this["~staticResponse"] ??= {
957
+ GET: void 0,
958
+ POST: void 0,
959
+ PUT: void 0,
960
+ DELETE: void 0,
961
+ PATCH: void 0,
962
+ HEAD: void 0,
963
+ OPTIONS: void 0
964
+ };
965
+ (target[method] ??= nullObject())[path] = staticResponse;
967
966
  if (!this["~config"]?.strictPath) {
968
967
  const loose = getLoosePath(path);
969
- if (!explicitPaths?.get(method)?.has(loose)) (target[loose] ??= nullObject())[method] = staticResponse;
968
+ if (!explicitPaths?.get(method)?.has(loose)) (target[method] ??= nullObject())[loose] = staticResponse;
970
969
  }
971
970
  }
972
971
  }
973
972
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
974
973
  const autoHead = enableAutoHead && method === "GET" && !explicitHead?.has(path);
975
- const registerPattern = (registerMain, registerHead, handler, headHandler, registerLoose) => {
976
- const explicitMain = explicitPaths?.get(method);
977
- const add = (p) => {
978
- registerMain(p, handler);
979
- if (headHandler) registerHead(p, headHandler);
980
- if (registerLoose) {
981
- const loose = getLoosePath(p);
982
- if (loose !== p && !explicitMain?.has(loose)) {
983
- registerMain(loose, handler);
984
- if (headHandler) registerHead(loose, headHandler);
985
- }
986
- }
987
- };
988
- add(path);
989
- if (needEncodeRegex.test(path)) {
990
- const encoded = encodeURI(path);
991
- if (encoded !== path) add(encoded);
974
+ const isDynamic = isDynamicRegex.test(path);
975
+ const registerLoose = !isDynamic && preferLoosePath && (path.length === 0 || path.charCodeAt(path.length - 1) === 47);
976
+ const explicitMain = registerLoose ? explicitPaths?.get(method) : void 0;
977
+ if (!isDynamic && !needEncodeRegex.test(path) && !registerLoose) {
978
+ const map = methods[method] ??= nullObject();
979
+ const handler = this.handler(i, precompile, route, sharedStatic);
980
+ map[path] = handler;
981
+ if (autoHead) {
982
+ const head = methods["HEAD"] ??= nullObject();
983
+ head[path] = wrapHeadHandler(handler);
992
984
  }
993
- };
994
- if (isDynamicRegex.test(path)) {
995
- const router = this["~router"] ??= new Memoirist();
985
+ continue;
986
+ }
987
+ const variants = [path];
988
+ if (needEncodeRegex.test(path)) {
989
+ const encoded = encodeURI(path);
990
+ if (encoded !== path) variants.push(encoded);
991
+ }
992
+ const paths = [];
993
+ for (let v = 0; v < variants.length; v++) {
994
+ const p = variants[v];
995
+ paths.push(p);
996
+ if (registerLoose) {
997
+ const loose = getLoosePath(p);
998
+ if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
999
+ }
1000
+ }
1001
+ if (isDynamic) {
1002
+ const router = this["~router"] ??= new Memoirist({ loosePath: preferLoosePath });
996
1003
  const handler = this.handler(i, precompile, void 0, sharedStatic);
997
- registerPattern((p, h) => router.add(method, p, h, false), (p, h) => router.add("HEAD", p, h, false), handler, autoHead ? wrapHeadHandler(handler) : void 0, false);
1004
+ const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1005
+ for (let p = 0; p < paths.length; p++) {
1006
+ router.add(method, paths[p], handler, false);
1007
+ if (headHandler) router.add("HEAD", paths[p], headHandler, false);
1008
+ }
998
1009
  } else {
999
1010
  const map = methods[method] ??= nullObject();
1000
1011
  const handler = this.handler(i, precompile, route, sharedStatic);
1001
1012
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1002
1013
  const head = autoHead ? methods["HEAD"] ??= nullObject() : void 0;
1003
- registerPattern((p, h) => {
1004
- map[p] = h;
1005
- }, (p, h) => {
1006
- head[p] = h;
1007
- }, handler, headHandler, !strict);
1014
+ for (let p = 0; p < paths.length; p++) {
1015
+ map[paths[p]] = handler;
1016
+ if (headHandler) head[paths[p]] = headHandler;
1017
+ }
1008
1018
  }
1009
1019
  }
1010
1020
  }
@@ -1029,13 +1039,33 @@ var Elysia = class Elysia {
1029
1039
  return this;
1030
1040
  }
1031
1041
  wrap(callback) {
1032
- if (this.#fetchFn) console.warn("[Elysia] .wrap() was called after the fetch handler was built, so it will not take effect. Register .wrap() before .listen() or before accessing .fetch/.handle.");
1042
+ if (this.#fetchFn) console.warn("[Elysia] .wrap() was called after the fetch handler was built");
1033
1043
  const ext = this.#ext;
1034
1044
  (ext.hoc ??= []).push(callback);
1035
1045
  return this;
1036
1046
  }
1037
1047
  /**
1038
- * Stop the underlying server (if any). Mirrors `Server.stop()`.
1048
+ * ### cleanup | Life cycle event
1049
+ * Called after server stop serving request
1050
+ *
1051
+ * ---
1052
+ * @example
1053
+ * ```typescript
1054
+ * new Elysia()
1055
+ * .cleanup((app) => {
1056
+ * closeDatabase()
1057
+ * })
1058
+ * ```
1059
+ */
1060
+ cleanup(handler) {
1061
+ const arr = this.#ext.cleanup ??= [];
1062
+ if (Array.isArray(handler)) arr.push(...handler);
1063
+ else arr.push(handler);
1064
+ return this;
1065
+ }
1066
+ /**
1067
+ * Stop the underlying server (if any), running every `cleanup` handler once
1068
+ * it has stopped. Mirrors `Server.stop()`.
1039
1069
  *
1040
1070
  * @param closeActiveConnections Pass `true` to terminate in-flight
1041
1071
  * requests and WebSocket connections immediately. Defaults to
@@ -1046,6 +1076,12 @@ var Elysia = class Elysia {
1046
1076
  if (!server) return;
1047
1077
  const r = server.stop?.(closeActiveConnections);
1048
1078
  this.server = void 0;
1079
+ const handlers = this["~ext"]?.cleanup;
1080
+ const fire = handlers ? () => {
1081
+ for (let i = 0; i < handlers.length; i++) handlers[i](this);
1082
+ } : void 0;
1083
+ if (r && typeof r.then === "function") return fire ? r.then(fire) : r;
1084
+ fire?.();
1049
1085
  return r;
1050
1086
  }
1051
1087
  };
@@ -1,3 +1,5 @@
1
+ import { CoercePlan } from "../type/coerce.js";
2
+
1
3
  //#region src/compile/aot.d.ts
2
4
  type ValidatorSlot = 'body' | 'query' | 'params' | 'headers' | 'cookie' | `response:${number}`;
3
5
  type FrozenCheckFactory = (External: unknown) => (value: unknown) => boolean;
@@ -31,7 +33,10 @@ interface FrozenValidator {
31
33
  r?: 1;
32
34
  ps?: 1;
33
35
  pd?: unknown;
36
+ pn?: 1;
34
37
  pod?: Record<string, unknown>;
38
+ dc?: () => unknown;
39
+ pm?: (value: Record<string, unknown>) => Record<string, unknown>;
35
40
  ce?: Array<{
36
41
  p: string;
37
42
  c: FrozenCheckFactory;
@@ -45,6 +50,7 @@ interface FrozenValidator {
45
50
  x?: 1;
46
51
  };
47
52
  }>;
53
+ cp?: CoercePlan;
48
54
  }
49
55
  interface ValidatorManifest {
50
56
  [method: string]: {
@@ -60,6 +66,13 @@ interface HandlerManifest {
60
66
  [path: string]: FrozenHandler;
61
67
  };
62
68
  }
69
+ interface CompiledSnapshot {
70
+ validators: ValidatorManifest | undefined;
71
+ handlers: HandlerManifest | undefined;
72
+ lazyGroups: Array<() => ValidatorManifest> | undefined;
73
+ lazyGroupOf: Record<string, Record<string, number>> | undefined;
74
+ builtGroups: number[];
75
+ }
63
76
  declare abstract class Compiled {
64
77
  static get handlers(): HandlerManifest | undefined;
65
78
  static set handlers(manifest: HandlerManifest);
@@ -68,6 +81,10 @@ declare abstract class Compiled {
68
81
  static registerLazyValidators(groups: Array<() => ValidatorManifest>, groupOf: Record<string, Record<string, number>>): void;
69
82
  static getValidator(method: string, path: string, slot: ValidatorSlot): FrozenValidator | undefined;
70
83
  static hasValidator(method: string, path: string, slot: ValidatorSlot): boolean;
84
+ /** @internal preserve registry around in-process AOT analysis */
85
+ static snapshot(): CompiledSnapshot;
86
+ /** @internal restore registry after in-process AOT analysis */
87
+ static restore(snapshot: CompiledSnapshot): void;
71
88
  /** @internal test isolation */
72
89
  static clear(): void;
73
90
  }
@@ -142,7 +159,10 @@ interface CapturedValidator {
142
159
  encodeMirror?: CapturedMirror;
143
160
  precomputeSafe?: boolean;
144
161
  precomputedDefault?: unknown;
162
+ precomputeNull?: boolean;
145
163
  precomputedObjectDefault?: Record<string, unknown>;
164
+ defaultCloner?: string;
165
+ objectDefaultMerger?: string;
146
166
  customErrors?: Array<{
147
167
  path: string;
148
168
  identifier: string;
@@ -158,6 +178,7 @@ interface CapturedValidator {
158
178
  external: boolean;
159
179
  decode: CapturedMirror;
160
180
  }>;
181
+ coercePlan?: CoercePlan;
161
182
  }
162
183
  declare function beginValidatorCapture(): void;
163
184
  declare function endValidatorCapture(): CapturedValidator[];
@@ -182,4 +203,4 @@ declare const Capture: {
182
203
  readonly isCapturing: () => boolean;
183
204
  };
184
205
  //#endregion
185
- export { Capture, CapturedHandler, CapturedMirror, CapturedValidator, CheckBuildResult, Compiled, EMPTY_EXTERNALS, FrozenBothFactory, FrozenCheckFactory, FrozenHandler, FrozenMirror, FrozenMirrorFactory, FrozenValidator, HandlerManifest, Source, ValidatorManifest, ValidatorSlot, beginValidatorCapture, collectExternals, endHandlerCapture, endValidatorCapture, externalsMatch, instantiateFrozenBoth, instantiateFrozenDecodeMirror, instantiateFrozenEncodeMirror, instantiateFrozenMirror, reconstructCheck };
206
+ export { Capture, CapturedHandler, CapturedMirror, CapturedValidator, CheckBuildResult, Compiled, CompiledSnapshot, EMPTY_EXTERNALS, FrozenBothFactory, FrozenCheckFactory, FrozenHandler, FrozenMirror, FrozenMirrorFactory, FrozenValidator, HandlerManifest, Source, ValidatorManifest, ValidatorSlot, beginValidatorCapture, collectExternals, endHandlerCapture, endValidatorCapture, externalsMatch, instantiateFrozenBoth, instantiateFrozenDecodeMirror, instantiateFrozenEncodeMirror, instantiateFrozenMirror, reconstructCheck };
@@ -20,6 +20,9 @@ var Compiled = class {
20
20
  }
21
21
  static set validators(manifest) {
22
22
  validators = manifest;
23
+ lazyGroups = void 0;
24
+ lazyGroupOf = void 0;
25
+ builtGroups.clear();
23
26
  }
24
27
  static registerLazyValidators(groups, groupOf) {
25
28
  lazyGroups = groups;
@@ -45,6 +48,25 @@ var Compiled = class {
45
48
  static hasValidator(method, path, slot) {
46
49
  return validators?.[method]?.[path]?.[slot] !== void 0 || lazyGroupOf?.[method]?.[path] !== void 0;
47
50
  }
51
+ /** @internal preserve registry around in-process AOT analysis */
52
+ static snapshot() {
53
+ return {
54
+ validators,
55
+ handlers,
56
+ lazyGroups,
57
+ lazyGroupOf,
58
+ builtGroups: [...builtGroups]
59
+ };
60
+ }
61
+ /** @internal restore registry after in-process AOT analysis */
62
+ static restore(snapshot) {
63
+ validators = snapshot.validators;
64
+ handlers = snapshot.handlers;
65
+ lazyGroups = snapshot.lazyGroups;
66
+ lazyGroupOf = snapshot.lazyGroupOf;
67
+ builtGroups.clear();
68
+ for (const group of snapshot.builtGroups) builtGroups.add(group);
69
+ }
48
70
  /** @internal test isolation */
49
71
  static clear() {
50
72
  validators = void 0;
@@ -19,6 +19,9 @@ var Compiled = class {
19
19
  }
20
20
  static set validators(manifest) {
21
21
  validators = manifest;
22
+ lazyGroups = void 0;
23
+ lazyGroupOf = void 0;
24
+ builtGroups.clear();
22
25
  }
23
26
  static registerLazyValidators(groups, groupOf) {
24
27
  lazyGroups = groups;
@@ -44,6 +47,25 @@ var Compiled = class {
44
47
  static hasValidator(method, path, slot) {
45
48
  return validators?.[method]?.[path]?.[slot] !== void 0 || lazyGroupOf?.[method]?.[path] !== void 0;
46
49
  }
50
+ /** @internal preserve registry around in-process AOT analysis */
51
+ static snapshot() {
52
+ return {
53
+ validators,
54
+ handlers,
55
+ lazyGroups,
56
+ lazyGroupOf,
57
+ builtGroups: [...builtGroups]
58
+ };
59
+ }
60
+ /** @internal restore registry after in-process AOT analysis */
61
+ static restore(snapshot) {
62
+ validators = snapshot.validators;
63
+ handlers = snapshot.handlers;
64
+ lazyGroups = snapshot.lazyGroups;
65
+ lazyGroupOf = snapshot.lazyGroupOf;
66
+ builtGroups.clear();
67
+ for (const group of snapshot.builtGroups) builtGroups.add(group);
68
+ }
47
69
  /** @internal test isolation */
48
70
  static clear() {
49
71
  validators = void 0;
@@ -1,10 +1,10 @@
1
1
  import { AnyLocalHook, CompiledHandler, InternalRoute } from "../../types.js";
2
2
  import { ChainNode } from "../../utils.js";
3
3
  import { AnyElysia } from "../../base.js";
4
+ import { setCaptureHeaderShorthand } from "./jit.js";
4
5
 
5
6
  //#region src/compile/handler/index.d.ts
6
- declare const setCaptureHeaderShorthand: (value: boolean | undefined) => void;
7
- declare function buildNativeStaticResponse([,, handler, instance, localHook, appHook, inheritedChain]: InternalRoute, root: AnyElysia): Response | Promise<Response> | undefined;
7
+ declare function buildNativeStaticResponse([,, handler, instance, localHook, appHook, inheritedChain]: InternalRoute, root: AnyElysia, hasMapResponse?: boolean): Response | Promise<Response> | undefined;
8
8
  declare function composeRouteHook(instance: AnyElysia, localHook: Partial<AnyLocalHook> | undefined, appHook: ChainNode | undefined, inheritedChain: ChainNode | undefined, root: AnyElysia): AnyLocalHook | undefined;
9
9
  declare function compileHandler([_method, path, handler, instance, localHook, appHook, inheritedChain]: InternalRoute, root: AnyElysia, precomputedStatic?: Response): CompiledHandler;
10
10
  //#endregion