elysia 2.0.0-exp.2 → 2.0.0-exp.3

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 (81) 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/utils.d.ts +1 -1
  7. package/dist/adapter/web-standard/handler.js +5 -2
  8. package/dist/adapter/web-standard/handler.mjs +6 -3
  9. package/dist/adapter/web-standard/index.d.ts +1 -1
  10. package/dist/base.js +29 -43
  11. package/dist/base.mjs +29 -43
  12. package/dist/compile/aot.d.ts +4 -0
  13. package/dist/compile/aot.js +3 -0
  14. package/dist/compile/aot.mjs +3 -0
  15. package/dist/compile/handler/index.js +53 -16
  16. package/dist/compile/handler/index.mjs +54 -17
  17. package/dist/compile/handler/params.js +1 -0
  18. package/dist/compile/handler/params.mjs +2 -1
  19. package/dist/compile/handler/utils.d.ts +2 -1
  20. package/dist/compile/handler/utils.js +6 -0
  21. package/dist/compile/handler/utils.mjs +6 -1
  22. package/dist/cookie/utils.js +1 -1
  23. package/dist/cookie/utils.mjs +1 -1
  24. package/dist/error.d.ts +1 -1
  25. package/dist/handler/error.js +2 -2
  26. package/dist/handler/error.mjs +3 -3
  27. package/dist/handler/fetch.js +7 -5
  28. package/dist/handler/fetch.mjs +7 -5
  29. package/dist/parse-query.js +1 -1
  30. package/dist/parse-query.mjs +1 -1
  31. package/dist/plugin/core.js +16 -10
  32. package/dist/plugin/core.mjs +16 -10
  33. package/dist/plugin/source.js +9 -5
  34. package/dist/plugin/source.mjs +9 -5
  35. package/dist/sucrose.js +23 -10
  36. package/dist/sucrose.mjs +23 -10
  37. package/dist/type/bridge.d.ts +2 -1
  38. package/dist/type/coerce.d.ts +20 -2
  39. package/dist/type/coerce.js +110 -0
  40. package/dist/type/coerce.mjs +109 -2
  41. package/dist/type/compat.js +4 -3
  42. package/dist/type/compat.mjs +2 -1
  43. package/dist/type/constants.d.ts +1 -1
  44. package/dist/type/elysia/boolean-string.js +1 -1
  45. package/dist/type/elysia/boolean-string.mjs +1 -1
  46. package/dist/type/elysia/integer-string.js +1 -1
  47. package/dist/type/elysia/integer-string.mjs +1 -1
  48. package/dist/type/utils.js +4 -4
  49. package/dist/type/utils.mjs +4 -4
  50. package/dist/type/validator/custom-error.d.ts +10 -0
  51. package/dist/type/validator/custom-error.js +113 -0
  52. package/dist/type/validator/custom-error.mjs +110 -0
  53. package/dist/type/validator/default-precompute.d.ts +11 -0
  54. package/dist/type/validator/default-precompute.js +216 -0
  55. package/dist/type/validator/default-precompute.mjs +212 -0
  56. package/dist/type/validator/frozen-check.d.ts +11 -0
  57. package/dist/type/validator/frozen-check.js +19 -0
  58. package/dist/type/validator/frozen-check.mjs +18 -0
  59. package/dist/type/{validator.d.ts → validator/index.d.ts} +6 -19
  60. package/dist/type/validator/index.js +536 -0
  61. package/dist/type/validator/index.mjs +531 -0
  62. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  63. package/dist/type/validator/string-codec-aot.js +106 -0
  64. package/dist/type/validator/string-codec-aot.mjs +102 -0
  65. package/dist/type/validator/validator-cache.d.ts +21 -0
  66. package/dist/type/validator/validator-cache.js +163 -0
  67. package/dist/type/validator/validator-cache.mjs +161 -0
  68. package/dist/types.d.ts +6 -0
  69. package/dist/universal/file.js +1 -1
  70. package/dist/universal/file.mjs +1 -1
  71. package/dist/utils.d.ts +8 -1
  72. package/dist/utils.js +71 -37
  73. package/dist/utils.mjs +71 -38
  74. package/dist/validator/index.d.ts +1 -1
  75. package/dist/validator/index.js +6 -0
  76. package/dist/validator/index.mjs +6 -0
  77. package/dist/ws/route.js +35 -22
  78. package/dist/ws/route.mjs +35 -22
  79. package/package.json +1 -1
  80. package/dist/type/validator.js +0 -1033
  81. 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[]>>;
@@ -12,7 +12,7 @@ declare function responseToSetHeaders(response: Response, set?: Context['set']):
12
12
  cookie?: Record<string, BaseCookie>;
13
13
  } | {
14
14
  headers: any;
15
- status: number | "Continue" | "Switching Protocols" | "Processing" | "Early Hints" | "OK" | "Created" | "Accepted" | "Non-Authoritative Information" | "No Content" | "Reset Content" | "Partial Content" | "Multi-Status" | "Already Reported" | "Multiple Choices" | "Moved Permanently" | "Found" | "See Other" | "Not Modified" | "Temporary Redirect" | "Permanent Redirect" | "Bad Request" | "Unauthorized" | "Payment Required" | "Forbidden" | "Not Found" | "Method Not Allowed" | "Not Acceptable" | "Proxy Authentication Required" | "Request Timeout" | "Conflict" | "Gone" | "Length Required" | "Precondition Failed" | "Payload Too Large" | "URI Too Long" | "Unsupported Media Type" | "Range Not Satisfiable" | "Expectation Failed" | "I'm a teapot" | "Enhance Your Calm" | "Misdirected Request" | "Unprocessable Content" | "Locked" | "Failed Dependency" | "Too Early" | "Upgrade Required" | "Precondition Required" | "Too Many Requests" | "Request Header Fields Too Large" | "Unavailable For Legal Reasons" | "Internal Server Error" | "Not Implemented" | "Bad Gateway" | "Service Unavailable" | "Gateway Timeout" | "HTTP Version Not Supported" | "Variant Also Negotiates" | "Insufficient Storage" | "Loop Detected" | "Not Extended" | "Network Authentication Required";
15
+ status: number | "Bad Request" | "Continue" | "Switching Protocols" | "Processing" | "Early Hints" | "OK" | "Created" | "Accepted" | "Non-Authoritative Information" | "No Content" | "Reset Content" | "Partial Content" | "Multi-Status" | "Already Reported" | "Multiple Choices" | "Moved Permanently" | "Found" | "See Other" | "Not Modified" | "Temporary Redirect" | "Permanent Redirect" | "Unauthorized" | "Payment Required" | "Forbidden" | "Not Found" | "Method Not Allowed" | "Not Acceptable" | "Proxy Authentication Required" | "Request Timeout" | "Conflict" | "Gone" | "Length Required" | "Precondition Failed" | "Payload Too Large" | "URI Too Long" | "Unsupported Media Type" | "Range Not Satisfiable" | "Expectation Failed" | "I'm a teapot" | "Enhance Your Calm" | "Misdirected Request" | "Unprocessable Content" | "Locked" | "Failed Dependency" | "Too Early" | "Upgrade Required" | "Precondition Required" | "Too Many Requests" | "Request Header Fields Too Large" | "Unavailable For Legal Reasons" | "Internal Server Error" | "Not Implemented" | "Bad Gateway" | "Service Unavailable" | "Gateway Timeout" | "HTTP Version Not Supported" | "Variant Also Negotiates" | "Insufficient Storage" | "Loop Detected" | "Not Extended" | "Network Authentication Required";
16
16
  };
17
17
  interface CreateHandlerParameter {
18
18
  mapResponse(response: unknown, set: Context['set'], request?: Request): Response;
@@ -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.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
  }
@@ -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;
@@ -913,7 +898,7 @@ var Elysia = class Elysia {
913
898
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
914
899
  const strict = !!this["~config"]?.strictPath;
915
900
  let explicitPaths;
916
- if (!strict) {
901
+ if (!strict && this["~config"]?.distinctPath) {
917
902
  explicitPaths = /* @__PURE__ */ new Map();
918
903
  for (let i = 0; i < length; i++) {
919
904
  const route = this.#history[i];
@@ -975,39 +960,40 @@ var Elysia = class Elysia {
975
960
  }
976
961
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
977
962
  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);
963
+ const isDynamic = require_constants.isDynamicRegex.test(path);
964
+ const registerLoose = !isDynamic && !strict;
965
+ const explicitMain = registerLoose ? explicitPaths?.get(method) : void 0;
966
+ const variants = [path];
967
+ if (require_constants.needEncodeRegex.test(path)) {
968
+ const encoded = encodeURI(path);
969
+ if (encoded !== path) variants.push(encoded);
970
+ }
971
+ const paths = [];
972
+ for (let v = 0; v < variants.length; v++) {
973
+ const p = variants[v];
974
+ paths.push(p);
975
+ if (registerLoose) {
976
+ const loose = require_utils.getLoosePath(p);
977
+ if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
995
978
  }
996
- };
997
- if (require_constants.isDynamicRegex.test(path)) {
979
+ }
980
+ if (isDynamic) {
998
981
  const router = this["~router"] ??= new memoirist.default();
999
982
  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);
983
+ const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
984
+ for (let p = 0; p < paths.length; p++) {
985
+ router.add(method, paths[p], handler, false);
986
+ if (headHandler) router.add("HEAD", paths[p], headHandler, false);
987
+ }
1001
988
  } else {
1002
989
  const map = methods[method] ??= require_utils.nullObject();
1003
990
  const handler = this.handler(i, precompile, route, sharedStatic);
1004
991
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1005
992
  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);
993
+ for (let p = 0; p < paths.length; p++) {
994
+ map[paths[p]] = handler;
995
+ if (headHandler) head[paths[p]] = headHandler;
996
+ }
1011
997
  }
1012
998
  }
1013
999
  }
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;
@@ -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;
@@ -910,7 +895,7 @@ var Elysia = class Elysia {
910
895
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
911
896
  const strict = !!this["~config"]?.strictPath;
912
897
  let explicitPaths;
913
- if (!strict) {
898
+ if (!strict && this["~config"]?.distinctPath) {
914
899
  explicitPaths = /* @__PURE__ */ new Map();
915
900
  for (let i = 0; i < length; i++) {
916
901
  const route = this.#history[i];
@@ -972,39 +957,40 @@ var Elysia = class Elysia {
972
957
  }
973
958
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
974
959
  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);
960
+ const isDynamic = isDynamicRegex.test(path);
961
+ const registerLoose = !isDynamic && !strict;
962
+ const explicitMain = registerLoose ? explicitPaths?.get(method) : void 0;
963
+ const variants = [path];
964
+ if (needEncodeRegex.test(path)) {
965
+ const encoded = encodeURI(path);
966
+ if (encoded !== path) variants.push(encoded);
967
+ }
968
+ const paths = [];
969
+ for (let v = 0; v < variants.length; v++) {
970
+ const p = variants[v];
971
+ paths.push(p);
972
+ if (registerLoose) {
973
+ const loose = getLoosePath(p);
974
+ if (loose !== p && !explicitMain?.has(loose)) paths.push(loose);
992
975
  }
993
- };
994
- if (isDynamicRegex.test(path)) {
976
+ }
977
+ if (isDynamic) {
995
978
  const router = this["~router"] ??= new Memoirist();
996
979
  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);
980
+ const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
981
+ for (let p = 0; p < paths.length; p++) {
982
+ router.add(method, paths[p], handler, false);
983
+ if (headHandler) router.add("HEAD", paths[p], headHandler, false);
984
+ }
998
985
  } else {
999
986
  const map = methods[method] ??= nullObject();
1000
987
  const handler = this.handler(i, precompile, route, sharedStatic);
1001
988
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
1002
989
  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);
990
+ for (let p = 0; p < paths.length; p++) {
991
+ map[paths[p]] = handler;
992
+ if (headHandler) head[paths[p]] = headHandler;
993
+ }
1008
994
  }
1009
995
  }
1010
996
  }
@@ -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;
@@ -45,6 +47,7 @@ interface FrozenValidator {
45
47
  x?: 1;
46
48
  };
47
49
  }>;
50
+ cp?: CoercePlan;
48
51
  }
49
52
  interface ValidatorManifest {
50
53
  [method: string]: {
@@ -158,6 +161,7 @@ interface CapturedValidator {
158
161
  external: boolean;
159
162
  decode: CapturedMirror;
160
163
  }>;
164
+ coercePlan?: CoercePlan;
161
165
  }
162
166
  declare function beginValidatorCapture(): void;
163
167
  declare function endValidatorCapture(): CapturedValidator[];
@@ -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;
@@ -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;
@@ -94,20 +94,22 @@ c.contentType=ct
94
94
  const child = report?.resolveChild("default");
95
95
  const begin = child ? child.begin : "";
96
96
  const end = child ? child.end() : "";
97
- const guard = bodyVali ? "ct" : "ct&&c.request.body";
97
+ const guard = bodyVali ? "ct" : "ct&&hb(c.request)";
98
98
  code += hasFn ? `if(!hasBody&&${guard}){${begin}c.body=await pd(c,ct)\n${end}}\n` : `if(${guard}){${begin}c.body=await pd(c,ct)\n${end}}\n`;
99
+ if (!bodyVali) link(require_compile_handler_utils.hasRequestBody, "hb");
99
100
  link(adapter.default, "pd");
100
101
  }
101
102
  return hasFn ? "let hasBody=false,_bp\n" + code : code;
102
103
  }
103
104
  const isAsyncValidator = (vali) => vali?.isAsync ?? true;
104
- function applyHook(localHook, appHook, rootHook) {
105
+ function applyHook(localHook, appHook, rootHook, appHookFresh = false) {
105
106
  let hook;
106
107
  if (localHook && appHook) hook = require_utils.mergeHook(require_utils.cloneHook(localHook), appHook, true);
107
108
  else {
108
109
  const base = localHook ?? appHook;
109
- if (!rootHook) return base ? require_utils.cloneHook(base) : base;
110
- hook = base ? require_utils.cloneHook(base) : require_utils.nullObject();
110
+ const ownsBase = appHookFresh && !localHook && base !== void 0;
111
+ if (!rootHook) return ownsBase ? base : base ? require_utils.cloneHook(base) : base;
112
+ hook = ownsBase ? base : base ? require_utils.cloneHook(base) : require_utils.nullObject();
111
113
  }
112
114
  if (rootHook) require_utils.mergeHook(hook, rootHook, true, true);
113
115
  return hook;
@@ -135,11 +137,16 @@ function dropHooksByOrigin(hook, skip) {
135
137
  const v = hook[key];
136
138
  if (!v) continue;
137
139
  if (Array.isArray(v)) {
138
- const kept = v.filter((fn) => {
140
+ let kept;
141
+ for (let i = 0; i < v.length; i++) {
142
+ const fn = v[i];
139
143
  const origin = require_utils.fnOrigin.get(fn);
140
- return origin === void 0 || !skip.has(origin);
141
- });
142
- if (kept.length !== v.length) {
144
+ const keep = origin === void 0 || !skip.has(origin);
145
+ if (kept) {
146
+ if (keep) kept.push(fn);
147
+ } else if (!keep) kept = v.slice(0, i);
148
+ }
149
+ if (kept) {
143
150
  if (out === hook) out = { ...hook };
144
151
  out[key] = kept;
145
152
  }
@@ -153,6 +160,21 @@ function dropHooksByOrigin(hook, skip) {
153
160
  }
154
161
  return out;
155
162
  }
163
+ function reconstructNeedsHookState(names) {
164
+ for (let i = 0; i < names.length; i++) switch (names[i]) {
165
+ case "ho":
166
+ case "tf":
167
+ case "bf":
168
+ case "af":
169
+ case "mr":
170
+ case "er":
171
+ case "ar":
172
+ case "va":
173
+ case "cc":
174
+ case "tr": return true;
175
+ }
176
+ return false;
177
+ }
156
178
  const createInlineHandler = (map, h) => ((c) => {
157
179
  const r = h(c);
158
180
  if (r instanceof Error) throw r;
@@ -203,7 +225,7 @@ function buildNativeStaticResponse([, , handler, instance, localHook, appHook, i
203
225
  if (localHook) root["~applyMacro"](localHook);
204
226
  resolveChainMacros(root, appHook);
205
227
  if (inheritedChain) resolveChainMacros(root, inheritedChain);
206
- const hook = applyHook(localHook, require_utils.flattenChainMemo(root, appHook), instance !== root ? composeRootHook(root, inheritedChain) : void 0);
228
+ const hook = applyHook(localHook, require_utils.flattenChainMemo(root, appHook), instance !== root ? composeRootHook(root, inheritedChain) : void 0, true);
207
229
  const has = (v) => Array.isArray(v) ? v.length > 0 : !!v;
208
230
  if (has(hook?.parse) || has(hook?.transform) || has(hook?.beforeHandle) || has(hook?.afterHandle) || has(hook?.mapResponse) || has(hook?.afterResponse) || has(hook?.trace)) return;
209
231
  if (hook?.body || hook?.query || hook?.params || hook?.headers || hook?.cookie || (hook?.schemas)?.length) return;
@@ -231,7 +253,7 @@ function composeRouteHook(instance, localHook, appHook, inheritedChain, root) {
231
253
  collectHookOrigins(flatAppHook, present);
232
254
  if (present.size) rootHook = dropHooksByOrigin(rootHook, present);
233
255
  }
234
- let hook = applyHook(localHook, flatAppHook, rootHook);
256
+ let hook = applyHook(localHook, flatAppHook, rootHook, true);
235
257
  if (instance !== root) {
236
258
  const errors = require_utils.flattenChain(instance["~hookChain"], require_utils.isLocalScope)?.error;
237
259
  if (errors) {
@@ -249,6 +271,16 @@ function composeRouteHook(instance, localHook, appHook, inheritedChain, root) {
249
271
  }
250
272
  function compileHandler([_method, path, handler, instance, localHook, appHook, inheritedChain], root, precomputedStatic) {
251
273
  const adapter = root["~config"]?.adapter ?? require_adapter_constants.defaultAdapter;
274
+ const method = require_utils.mapMethodBack(_method);
275
+ const reconstructed = require_compile_aot.Compiled.handlers?.[method]?.[path];
276
+ if (reconstructed && !precomputedStatic && typeof handler === "function" && !root["~ext"]?.macro && !reconstructNeedsHookState(reconstructed.a)) return reconstructed.f(handler, ...require_compile_handler_params.resolveHandlerParams(reconstructed.a, {
277
+ parse: adapter.parse,
278
+ res: adapter.response,
279
+ hook: require_utils.nullObject(),
280
+ vali: void 0,
281
+ cookieConfig: void 0,
282
+ tracers: void 0
283
+ }));
252
284
  if (root["~ext"]?.macro) {
253
285
  if (localHook) root["~applyMacro"](localHook);
254
286
  if (appHook) resolveChainMacros(root, appHook);
@@ -265,8 +297,7 @@ function compileHandler([_method, path, handler, instance, localHook, appHook, i
265
297
  toArray("afterResponse", hook);
266
298
  toArray("error", hook);
267
299
  }
268
- const method = require_utils.mapMethodBack(_method);
269
- const vali = hook ? new require_validator_route.RouteValidator(hook, {
300
+ const buildValidator = () => hook ? new require_validator_route.RouteValidator(hook, {
270
301
  models: root["~ext"]?.models,
271
302
  normalize: root["~config"]?.normalize,
272
303
  sanitize: root["~config"]?.sanitize,
@@ -297,15 +328,15 @@ function compileHandler([_method, path, handler, instance, localHook, appHook, i
297
328
  const resolve = (p) => typeof p === "string" && p in namedParsers ? namedParsers[p] : p;
298
329
  hook.parse = Array.isArray(hook.parse) ? hook.parse.map(resolve) : resolve(hook.parse);
299
330
  }
300
- const reconstructed = require_compile_aot.Compiled.handlers?.[method]?.[path];
301
331
  if (reconstructed) return reconstructed.f(handler, ...require_compile_handler_params.resolveHandlerParams(reconstructed.a, {
302
332
  parse: adapter.parse,
303
333
  res: adapter.response,
304
334
  hook: hook ?? require_utils.nullObject(),
305
- vali,
335
+ vali: reconstructed.a.includes("va") ? buildValidator() : void 0,
306
336
  cookieConfig: reconstructed.a.includes("cc") ? require_cookie_config.compileCookieConfig(hook?.cookie, root["~config"]?.cookie) : void 0,
307
337
  tracers: reconstructed.a.includes("tr") ? (hook?.trace)?.map((fn) => require_trace.createTracer(fn)) : void 0
308
338
  }));
339
+ const vali = buildValidator();
309
340
  const inference = require_sucrose.sucrose(handler, hook);
310
341
  const params = /* @__PURE__ */ new Set();
311
342
  let alias = "";
@@ -374,7 +405,13 @@ function compileHandler([_method, path, handler, instance, localHook, appHook, i
374
405
  };
375
406
  } };
376
407
  };
377
- const responseValiAsync = !!(vali?.response && Object.values(vali.response).find(isAsyncValidator));
408
+ let responseValiAsync = false;
409
+ if (vali?.response) {
410
+ for (const code in vali.response) if (isAsyncValidator(vali.response[code])) {
411
+ responseValiAsync = true;
412
+ break;
413
+ }
414
+ }
378
415
  const handlerIsAsync = isHandleFunction && require_compile_utils.isAsyncFunction(handler);
379
416
  const errorHookForcesAsync = hasErrorHook && (hasAfterHandle || hasMapResponse || hasResponseValidator);
380
417
  const responseValiForcesAsync = hasResponseValidator && isHandleFunction && !handlerIsAsync && (require_compile_utils.mayReturnPromise(handler) || mayReturnIdentifier(handler));
@@ -610,7 +647,7 @@ let _r${hasMapResponse ? ",tmp" : ""}\n` + require_compile_handler_utils.mapErro
610
647
  if (alias === "rc" || !isAsync && !syncErrorHook && alias === "rc,fe") return createInlineHandler(res.compact ?? res.map, handler);
611
648
  else if (alias === "rm" || !isAsync && !syncErrorHook && alias === "rm,fe") return createInlineHandlerWithSet(res.map, handler);
612
649
  }
613
- if (!precomputedStatic) require_compile_aot.Capture.handler({
650
+ require_compile_aot.Capture.handler({
614
651
  method,
615
652
  path,
616
653
  alias,