elysia 2.0.0-exp.2 → 2.0.0-exp.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/adapter/bun/index.d.ts +1 -1
  2. package/dist/adapter/bun/router.js +1 -1
  3. package/dist/adapter/bun/router.mjs +1 -1
  4. package/dist/adapter/constants.d.ts +1 -1
  5. package/dist/adapter/index.d.ts +1 -1
  6. package/dist/adapter/web-standard/handler.js +5 -2
  7. package/dist/adapter/web-standard/handler.mjs +6 -3
  8. package/dist/adapter/web-standard/index.d.ts +1 -1
  9. package/dist/base.d.ts +1 -1
  10. package/dist/base.js +50 -52
  11. package/dist/base.mjs +50 -52
  12. package/dist/compile/aot.d.ts +22 -1
  13. package/dist/compile/aot.js +22 -0
  14. package/dist/compile/aot.mjs +22 -0
  15. package/dist/compile/handler/index.d.ts +1 -1
  16. package/dist/compile/handler/index.js +57 -441
  17. package/dist/compile/handler/index.mjs +58 -442
  18. package/dist/compile/handler/jit.d.ts +35 -0
  19. package/dist/compile/handler/jit.js +445 -0
  20. package/dist/compile/handler/jit.mjs +443 -0
  21. package/dist/compile/handler/params.js +1 -0
  22. package/dist/compile/handler/params.mjs +2 -1
  23. package/dist/compile/handler/reconstruct.d.ts +13 -0
  24. package/dist/compile/handler/reconstruct.js +29 -0
  25. package/dist/compile/handler/reconstruct.mjs +28 -0
  26. package/dist/compile/handler/utils.d.ts +2 -1
  27. package/dist/compile/handler/utils.js +6 -0
  28. package/dist/compile/handler/utils.mjs +6 -1
  29. package/dist/compile/jit-probe.d.ts +19 -0
  30. package/dist/compile/jit-probe.js +38 -0
  31. package/dist/compile/jit-probe.mjs +36 -0
  32. package/dist/cookie/utils.js +1 -1
  33. package/dist/cookie/utils.mjs +1 -1
  34. package/dist/handler/error.js +2 -2
  35. package/dist/handler/error.mjs +3 -3
  36. package/dist/handler/fetch.js +27 -15
  37. package/dist/handler/fetch.mjs +28 -16
  38. package/dist/parse-query.js +1 -1
  39. package/dist/parse-query.mjs +1 -1
  40. package/dist/plugin/bun.js +8 -1
  41. package/dist/plugin/bun.mjs +9 -2
  42. package/dist/plugin/core.d.ts +45 -1
  43. package/dist/plugin/core.js +74 -10
  44. package/dist/plugin/core.mjs +74 -12
  45. package/dist/plugin/esbuild.js +8 -1
  46. package/dist/plugin/esbuild.mjs +9 -2
  47. package/dist/plugin/source.d.ts +38 -1
  48. package/dist/plugin/source.js +104 -13
  49. package/dist/plugin/source.mjs +102 -14
  50. package/dist/plugin/vite.js +12 -1
  51. package/dist/plugin/vite.mjs +13 -2
  52. package/dist/sucrose.js +23 -10
  53. package/dist/sucrose.mjs +23 -10
  54. package/dist/trace.d.ts +1 -1
  55. package/dist/trace.js +4 -6
  56. package/dist/trace.mjs +4 -6
  57. package/dist/type/bridge.d.ts +9 -8
  58. package/dist/type/coerce.d.ts +20 -2
  59. package/dist/type/coerce.js +110 -0
  60. package/dist/type/coerce.mjs +109 -2
  61. package/dist/type/compat.js +4 -3
  62. package/dist/type/compat.mjs +2 -1
  63. package/dist/type/constants.d.ts +1 -1
  64. package/dist/type/elysia/boolean-string.js +1 -1
  65. package/dist/type/elysia/boolean-string.mjs +1 -1
  66. package/dist/type/elysia/integer-string.js +1 -1
  67. package/dist/type/elysia/integer-string.mjs +1 -1
  68. package/dist/type/types.d.ts +1 -1
  69. package/dist/type/utils.js +4 -4
  70. package/dist/type/utils.mjs +4 -4
  71. package/dist/type/validator/custom-error.d.ts +10 -0
  72. package/dist/type/validator/custom-error.js +113 -0
  73. package/dist/type/validator/custom-error.mjs +110 -0
  74. package/dist/type/validator/default-precompute.d.ts +19 -0
  75. package/dist/type/validator/default-precompute.js +336 -0
  76. package/dist/type/validator/default-precompute.mjs +327 -0
  77. package/dist/type/validator/frozen-check.d.ts +11 -0
  78. package/dist/type/validator/frozen-check.js +19 -0
  79. package/dist/type/validator/frozen-check.mjs +18 -0
  80. package/dist/type/{validator.d.ts → validator/index.d.ts} +7 -20
  81. package/dist/type/validator/index.js +568 -0
  82. package/dist/type/validator/index.mjs +563 -0
  83. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  84. package/dist/type/validator/string-codec-aot.js +106 -0
  85. package/dist/type/validator/string-codec-aot.mjs +102 -0
  86. package/dist/type/validator/validator-cache.d.ts +21 -0
  87. package/dist/type/validator/validator-cache.js +163 -0
  88. package/dist/type/validator/validator-cache.mjs +161 -0
  89. package/dist/types.d.ts +7 -1
  90. package/dist/universal/file.js +1 -1
  91. package/dist/universal/file.mjs +1 -1
  92. package/dist/utils.d.ts +8 -1
  93. package/dist/utils.js +77 -45
  94. package/dist/utils.mjs +77 -46
  95. package/dist/validator/index.d.ts +1 -1
  96. package/dist/validator/index.js +6 -0
  97. package/dist/validator/index.mjs +6 -0
  98. package/dist/ws/route.js +35 -22
  99. package/dist/ws/route.mjs +35 -22
  100. package/package.json +2 -2
  101. package/dist/type/validator.js +0 -1033
  102. package/dist/type/validator.mjs +0 -1029
@@ -6,7 +6,7 @@ import { AnyElysia } from "../../base.js";
6
6
  declare function collectStaticRoutes(app: AnyElysia): readonly [Record<string, Record<string, Response>>, Promise<void>[]] | undefined;
7
7
  declare const BunAdapter: {
8
8
  parse: {
9
- default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<Record<string, unknown>> | Promise<ArrayBuffer> | Promise<string> | Promise<unknown[] | Record<string | number | symbol, undefined>> | undefined;
9
+ default: (context: Context, contentType: string) => string | ArrayBuffer | unknown[] | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
10
10
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
11
11
  text: (context: Context) => MaybePromise<string>;
12
12
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -9,7 +9,7 @@ const require_handler_error = require('../../handler/error.js');
9
9
 
10
10
  //#region src/adapter/bun/router.ts
11
11
  function createBunContext(app) {
12
- const headers = app["~ext"]?.headers ? Object.assign(require_utils.nullObject(), structuredClone(app["~ext"].headers)) : null;
12
+ const headers = app["~ext"]?.headers ? Object.assign(require_utils.nullObject(), app["~ext"].headers) : null;
13
13
  return class Context extends require_context.createBaseContext(app) {
14
14
  constructor(request) {
15
15
  super();
@@ -8,7 +8,7 @@ import { createErrorHandler } from "../../handler/error.mjs";
8
8
 
9
9
  //#region src/adapter/bun/router.ts
10
10
  function createBunContext(app) {
11
- const headers = app["~ext"]?.headers ? Object.assign(nullObject(), structuredClone(app["~ext"].headers)) : null;
11
+ const headers = app["~ext"]?.headers ? Object.assign(nullObject(), app["~ext"].headers) : null;
12
12
  return class Context extends createBaseContext(app) {
13
13
  constructor(request) {
14
14
  super();
@@ -5,7 +5,7 @@ import { AnyElysia } from "../base.js";
5
5
  //#region src/adapter/constants.d.ts
6
6
  declare const defaultAdapter: {
7
7
  parse: {
8
- default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<Record<string, unknown>> | Promise<ArrayBuffer> | Promise<string> | Promise<unknown[] | Record<string | number | symbol, undefined>> | undefined;
8
+ default: (context: Context, contentType: string) => string | ArrayBuffer | unknown[] | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
9
9
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
10
10
  text: (context: Context) => MaybePromise<string>;
11
11
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -7,7 +7,7 @@ import { AnyElysia } from "../base.js";
7
7
  //#region src/adapter/index.d.ts
8
8
  declare function createAdapter(adapter: ElysiaAdapterOptions): {
9
9
  parse: {
10
- default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<Record<string, unknown>> | Promise<ArrayBuffer> | Promise<string> | Promise<unknown[] | Record<string | number | symbol, undefined>> | undefined;
10
+ default: (context: Context, contentType: string) => string | ArrayBuffer | unknown[] | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
11
11
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
12
12
  text: (context: Context) => MaybePromise<string>;
13
13
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
@@ -8,7 +8,7 @@ const require_adapter_utils = require('../utils.js');
8
8
  //#region src/adapter/web-standard/handler.ts
9
9
  function handleElysiaFile(file, set = { headers: require_utils.nullObject() }, request) {
10
10
  const path = file.path;
11
- const contentType = require_universal_file.mime[path.slice(path.lastIndexOf(".") + 1)];
11
+ const contentType = require_universal_file.mime[path.slice(path.lastIndexOf(".") + 1).toLowerCase()];
12
12
  const headers = set.headers;
13
13
  if (contentType) headers["content-type"] = contentType;
14
14
  if (file.stats && set.status !== 206 && set.status !== 304 && set.status !== 412 && set.status !== 416) return file.stats.then((stat) => {
@@ -97,7 +97,10 @@ function errorToResponse(error, set) {
97
97
  return typeof raw?.then === "function" ? raw.then(apply) : apply(raw);
98
98
  }
99
99
  const headers = set?.headers ?? require_utils.nullObject();
100
- return Response.json({
100
+ return Response.json(require_error.isProduction() ? {
101
+ name: error?.name,
102
+ message: "Internal Server Error"
103
+ } : {
101
104
  name: error?.name,
102
105
  message: error?.message,
103
106
  cause: error?.cause
@@ -1,13 +1,13 @@
1
1
  import { isBun } from "../../universal/constants.mjs";
2
2
  import { mime } from "../../universal/file.mjs";
3
3
  import { formToFormData, isNotEmpty, nullObject } from "../../utils.mjs";
4
- import { ElysiaStatus } from "../../error.mjs";
4
+ import { ElysiaStatus, isProduction } from "../../error.mjs";
5
5
  import { createResponseHandler, createStreamHandler, handleFile, handleSet } from "../utils.mjs";
6
6
 
7
7
  //#region src/adapter/web-standard/handler.ts
8
8
  function handleElysiaFile(file, set = { headers: nullObject() }, request) {
9
9
  const path = file.path;
10
- const contentType = mime[path.slice(path.lastIndexOf(".") + 1)];
10
+ const contentType = mime[path.slice(path.lastIndexOf(".") + 1).toLowerCase()];
11
11
  const headers = set.headers;
12
12
  if (contentType) headers["content-type"] = contentType;
13
13
  if (file.stats && set.status !== 206 && set.status !== 304 && set.status !== 412 && set.status !== 416) return file.stats.then((stat) => {
@@ -96,7 +96,10 @@ function errorToResponse(error, set) {
96
96
  return typeof raw?.then === "function" ? raw.then(apply) : apply(raw);
97
97
  }
98
98
  const headers = set?.headers ?? nullObject();
99
- return Response.json({
99
+ return Response.json(isProduction() ? {
100
+ name: error?.name,
101
+ message: "Internal Server Error"
102
+ } : {
100
103
  name: error?.name,
101
104
  message: error?.message,
102
105
  cause: error?.cause
@@ -5,7 +5,7 @@ import { AnyElysia } from "../../base.js";
5
5
  //#region src/adapter/web-standard/index.d.ts
6
6
  declare const WebStandardAdapter: {
7
7
  parse: {
8
- default: (context: Context, contentType: string) => string | unknown[] | ArrayBuffer | Record<string, unknown> | Promise<Record<string, unknown>> | Promise<ArrayBuffer> | Promise<string> | Promise<unknown[] | Record<string | number | symbol, undefined>> | undefined;
8
+ default: (context: Context, contentType: string) => string | ArrayBuffer | unknown[] | Record<string, unknown> | Promise<unknown[] | Record<string | number | symbol, undefined>> | Promise<ArrayBuffer> | Promise<Record<string, unknown>> | Promise<string> | undefined;
9
9
  json: (context: Context) => MaybePromise<Record<keyof any, undefined> | unknown[]>;
10
10
  text: (context: Context) => MaybePromise<string>;
11
11
  urlencoded: (context: Context) => MaybePromise<Record<string, string | string[]>>;
package/dist/base.d.ts CHANGED
@@ -43,7 +43,7 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
43
43
  '~map'?: {
44
44
  [method: string]: {
45
45
  [path: string]: CompiledHandler;
46
- };
46
+ } | undefined;
47
47
  };
48
48
  '~staticResponse'?: {
49
49
  [path: string]: {
package/dist/base.js CHANGED
@@ -14,22 +14,6 @@ memoirist = require_runtime.__toESM(memoirist);
14
14
 
15
15
  //#region src/base.ts
16
16
  const useNodesBuffer = [];
17
- const isPlainObject = (v) => {
18
- if (!v || typeof v !== "object" || Array.isArray(v)) return false;
19
- const proto = Object.getPrototypeOf(v);
20
- return proto === Object.prototype || proto === null;
21
- };
22
- function clonePlainDecorators(source, seen = /* @__PURE__ */ new WeakMap()) {
23
- const existing = seen.get(source);
24
- if (existing) return existing;
25
- const out = require_utils.nullObject();
26
- seen.set(source, out);
27
- for (const key in source) {
28
- const value = source[key];
29
- out[key] = isPlainObject(value) ? clonePlainDecorators(value, seen) : value;
30
- }
31
- return out;
32
- }
33
17
  var Elysia = class Elysia {
34
18
  #hasPlugin = false;
35
19
  #hasGlobal = false;
@@ -560,7 +544,7 @@ var Elysia = class Elysia {
560
544
  const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
561
545
  const ext = this["~ext"] ??= require_utils.nullObject();
562
546
  if (decorator) {
563
- const cloned = clonePlainDecorators(decorator);
547
+ const cloned = require_utils.clonePlainDecorators(decorator);
564
548
  if (ext.decorator) require_utils.mergeDeep(ext.decorator, cloned);
565
549
  else ext.decorator = Object.assign(require_utils.nullObject(), cloned);
566
550
  }
@@ -829,13 +813,13 @@ var Elysia = class Elysia {
829
813
  }
830
814
  #initMap() {
831
815
  this["~map"] ??= {
832
- GET: require_utils.nullObject(),
833
- POST: require_utils.nullObject(),
834
- PUT: require_utils.nullObject(),
835
- DELETE: require_utils.nullObject(),
836
- PATCH: require_utils.nullObject(),
837
- HEAD: require_utils.nullObject(),
838
- OPTIONS: require_utils.nullObject()
816
+ GET: void 0,
817
+ POST: void 0,
818
+ PUT: void 0,
819
+ DELETE: void 0,
820
+ PATCH: void 0,
821
+ HEAD: void 0,
822
+ OPTIONS: void 0
839
823
  };
840
824
  }
841
825
  compile() {
@@ -867,6 +851,7 @@ var Elysia = class Elysia {
867
851
  };
868
852
  }
869
853
  #saveHandler(method, path, handler) {
854
+ if (require_constants.isDynamicRegex.test(path)) return;
870
855
  this.#initMap();
871
856
  const map = this["~map"][require_utils.mapMethodBack(method)] ??= require_utils.nullObject();
872
857
  map[path] = handler;
@@ -912,8 +897,10 @@ var Elysia = class Elysia {
912
897
  }
913
898
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
914
899
  const strict = !!this["~config"]?.strictPath;
900
+ const routerOptions = strict ? void 0 : { loosePath: true };
901
+ const getRouter = () => this["~router"] ??= new memoirist.default(routerOptions);
915
902
  let explicitPaths;
916
- if (!strict) {
903
+ if (!strict && this["~config"]?.distinctPath) {
917
904
  explicitPaths = /* @__PURE__ */ new Map();
918
905
  for (let i = 0; i < length; i++) {
919
906
  const route = this.#history[i];
@@ -936,7 +923,7 @@ var Elysia = class Elysia {
936
923
  const ws = require_ws_route.buildWSRoute(route, this);
937
924
  const handler = ws[0];
938
925
  const options = ws[1];
939
- if (require_constants.isDynamicRegex.test(path)) (this["~router"] ??= new memoirist.default()).add("WS", path, handler, false);
926
+ if (require_constants.isDynamicRegex.test(path)) getRouter().add("WS", path, handler, false);
940
927
  else {
941
928
  this.#initMap();
942
929
  const wsMap = this["~map"]["WS"] ??= require_utils.nullObject();
@@ -975,39 +962,50 @@ var Elysia = class Elysia {
975
962
  }
976
963
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
977
964
  const autoHead = enableAutoHead && method === "GET" && !explicitHead?.has(path);
978
- const registerPattern = (registerMain, registerHead, handler, headHandler, registerLoose) => {
979
- const explicitMain = explicitPaths?.get(method);
980
- const add = (p) => {
981
- registerMain(p, handler);
982
- if (headHandler) registerHead(p, headHandler);
983
- if (registerLoose) {
984
- const loose = require_utils.getLoosePath(p);
985
- if (loose !== p && !explicitMain?.has(loose)) {
986
- registerMain(loose, handler);
987
- if (headHandler) registerHead(loose, headHandler);
988
- }
989
- }
990
- };
991
- add(path);
992
- if (require_constants.needEncodeRegex.test(path)) {
993
- const encoded = encodeURI(path);
994
- if (encoded !== path) add(encoded);
965
+ const isDynamic = require_constants.isDynamicRegex.test(path);
966
+ const registerLoose = !isDynamic && !strict && (path.length === 0 || path.charCodeAt(path.length - 1) === 47);
967
+ const explicitMain = registerLoose ? explicitPaths?.get(method) : void 0;
968
+ if (!isDynamic && !require_constants.needEncodeRegex.test(path) && !registerLoose) {
969
+ const map = methods[method] ??= require_utils.nullObject();
970
+ const handler = this.handler(i, precompile, route, sharedStatic);
971
+ map[path] = handler;
972
+ if (autoHead) {
973
+ const head = methods["HEAD"] ??= require_utils.nullObject();
974
+ head[path] = wrapHeadHandler(handler);
995
975
  }
996
- };
997
- if (require_constants.isDynamicRegex.test(path)) {
998
- const router = this["~router"] ??= new memoirist.default();
976
+ continue;
977
+ }
978
+ const variants = [path];
979
+ if (require_constants.needEncodeRegex.test(path)) {
980
+ const encoded = encodeURI(path);
981
+ if (encoded !== path) variants.push(encoded);
982
+ }
983
+ const paths = [];
984
+ for (let v = 0; v < variants.length; v++) {
985
+ const p = variants[v];
986
+ paths.push(p);
987
+ if (registerLoose) {
988
+ const loose = require_utils.getLoosePath(p);
989
+ if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
990
+ }
991
+ }
992
+ if (isDynamic) {
993
+ const router = getRouter();
999
994
  const handler = this.handler(i, precompile, void 0, sharedStatic);
1000
- registerPattern((p, h) => router.add(method, p, h, false), (p, h) => router.add("HEAD", p, h, false), handler, autoHead ? wrapHeadHandler(handler) : void 0, false);
995
+ const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
996
+ for (let p = 0; p < paths.length; p++) {
997
+ router.add(method, paths[p], handler, false);
998
+ if (headHandler) router.add("HEAD", paths[p], headHandler, false);
999
+ }
1001
1000
  } else {
1002
1001
  const map = methods[method] ??= require_utils.nullObject();
1003
1002
  const handler = this.handler(i, precompile, route, sharedStatic);
1004
1003
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1005
1004
  const head = autoHead ? methods["HEAD"] ??= require_utils.nullObject() : void 0;
1006
- registerPattern((p, h) => {
1007
- map[p] = h;
1008
- }, (p, h) => {
1009
- head[p] = h;
1010
- }, handler, headHandler, !strict);
1005
+ for (let p = 0; p < paths.length; p++) {
1006
+ map[paths[p]] = handler;
1007
+ if (headHandler) head[paths[p]] = headHandler;
1008
+ }
1011
1009
  }
1012
1010
  }
1013
1011
  }
package/dist/base.mjs CHANGED
@@ -1,6 +1,6 @@
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
6
  import { buildWSRoute } from "./ws/route.mjs";
@@ -11,22 +11,6 @@ import Memoirist from "memoirist";
11
11
 
12
12
  //#region src/base.ts
13
13
  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
14
  var Elysia = class Elysia {
31
15
  #hasPlugin = false;
32
16
  #hasGlobal = false;
@@ -826,13 +810,13 @@ var Elysia = class Elysia {
826
810
  }
827
811
  #initMap() {
828
812
  this["~map"] ??= {
829
- GET: nullObject(),
830
- POST: nullObject(),
831
- PUT: nullObject(),
832
- DELETE: nullObject(),
833
- PATCH: nullObject(),
834
- HEAD: nullObject(),
835
- OPTIONS: nullObject()
813
+ GET: void 0,
814
+ POST: void 0,
815
+ PUT: void 0,
816
+ DELETE: void 0,
817
+ PATCH: void 0,
818
+ HEAD: void 0,
819
+ OPTIONS: void 0
836
820
  };
837
821
  }
838
822
  compile() {
@@ -864,6 +848,7 @@ var Elysia = class Elysia {
864
848
  };
865
849
  }
866
850
  #saveHandler(method, path, handler) {
851
+ if (isDynamicRegex.test(path)) return;
867
852
  this.#initMap();
868
853
  const map = this["~map"][mapMethodBack(method)] ??= nullObject();
869
854
  map[path] = handler;
@@ -909,8 +894,10 @@ var Elysia = class Elysia {
909
894
  }
910
895
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
911
896
  const strict = !!this["~config"]?.strictPath;
897
+ const routerOptions = strict ? void 0 : { loosePath: true };
898
+ const getRouter = () => this["~router"] ??= new Memoirist(routerOptions);
912
899
  let explicitPaths;
913
- if (!strict) {
900
+ if (!strict && this["~config"]?.distinctPath) {
914
901
  explicitPaths = /* @__PURE__ */ new Map();
915
902
  for (let i = 0; i < length; i++) {
916
903
  const route = this.#history[i];
@@ -933,7 +920,7 @@ var Elysia = class Elysia {
933
920
  const ws = buildWSRoute(route, this);
934
921
  const handler = ws[0];
935
922
  const options = ws[1];
936
- if (isDynamicRegex.test(path)) (this["~router"] ??= new Memoirist()).add("WS", path, handler, false);
923
+ if (isDynamicRegex.test(path)) getRouter().add("WS", path, handler, false);
937
924
  else {
938
925
  this.#initMap();
939
926
  const wsMap = this["~map"]["WS"] ??= nullObject();
@@ -972,39 +959,50 @@ var Elysia = class Elysia {
972
959
  }
973
960
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
974
961
  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);
962
+ const isDynamic = isDynamicRegex.test(path);
963
+ const registerLoose = !isDynamic && !strict && (path.length === 0 || path.charCodeAt(path.length - 1) === 47);
964
+ const explicitMain = registerLoose ? explicitPaths?.get(method) : void 0;
965
+ if (!isDynamic && !needEncodeRegex.test(path) && !registerLoose) {
966
+ const map = methods[method] ??= nullObject();
967
+ const handler = this.handler(i, precompile, route, sharedStatic);
968
+ map[path] = handler;
969
+ if (autoHead) {
970
+ const head = methods["HEAD"] ??= nullObject();
971
+ head[path] = wrapHeadHandler(handler);
992
972
  }
993
- };
994
- if (isDynamicRegex.test(path)) {
995
- const router = this["~router"] ??= new Memoirist();
973
+ continue;
974
+ }
975
+ const variants = [path];
976
+ if (needEncodeRegex.test(path)) {
977
+ const encoded = encodeURI(path);
978
+ if (encoded !== path) variants.push(encoded);
979
+ }
980
+ const paths = [];
981
+ for (let v = 0; v < variants.length; v++) {
982
+ const p = variants[v];
983
+ paths.push(p);
984
+ if (registerLoose) {
985
+ const loose = getLoosePath(p);
986
+ if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
987
+ }
988
+ }
989
+ if (isDynamic) {
990
+ const router = getRouter();
996
991
  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);
992
+ const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
993
+ for (let p = 0; p < paths.length; p++) {
994
+ router.add(method, paths[p], handler, false);
995
+ if (headHandler) router.add("HEAD", paths[p], headHandler, false);
996
+ }
998
997
  } else {
999
998
  const map = methods[method] ??= nullObject();
1000
999
  const handler = this.handler(i, precompile, route, sharedStatic);
1001
1000
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1002
1001
  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);
1002
+ for (let p = 0; p < paths.length; p++) {
1003
+ map[paths[p]] = handler;
1004
+ if (headHandler) head[paths[p]] = headHandler;
1005
+ }
1008
1006
  }
1009
1007
  }
1010
1008
  }
@@ -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,9 +1,9 @@
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
7
  declare function buildNativeStaticResponse([,, handler, instance, localHook, appHook, inheritedChain]: InternalRoute, root: AnyElysia): 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;