elysia 2.0.0-exp.1 → 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 (168) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +0 -2
  2. package/dist/adapter/bun/index.d.ts +1 -1
  3. package/dist/adapter/bun/router.js +2 -2
  4. package/dist/adapter/bun/router.mjs +2 -2
  5. package/dist/adapter/constants.d.ts +1 -1
  6. package/dist/adapter/index.d.ts +1 -1
  7. package/dist/adapter/utils.js +4 -2
  8. package/dist/adapter/utils.mjs +4 -2
  9. package/dist/adapter/web-standard/handler.js +5 -2
  10. package/dist/adapter/web-standard/handler.mjs +6 -3
  11. package/dist/adapter/web-standard/index.d.ts +1 -1
  12. package/dist/base.js +59 -36
  13. package/dist/base.mjs +61 -38
  14. package/dist/compile/aot.d.ts +45 -35
  15. package/dist/compile/aot.js +16 -37
  16. package/dist/compile/aot.mjs +16 -38
  17. package/dist/compile/handler/index.d.ts +4 -2
  18. package/dist/compile/handler/index.js +82 -30
  19. package/dist/compile/handler/index.mjs +83 -32
  20. package/dist/compile/handler/params.js +1 -0
  21. package/dist/compile/handler/params.mjs +2 -1
  22. package/dist/compile/handler/utils.d.ts +2 -1
  23. package/dist/compile/handler/utils.js +9 -3
  24. package/dist/compile/handler/utils.mjs +9 -4
  25. package/dist/compile/index.d.ts +2 -2
  26. package/dist/compile/index.js +2 -1
  27. package/dist/compile/index.mjs +2 -2
  28. package/dist/cookie/config.js +7 -6
  29. package/dist/cookie/config.mjs +7 -6
  30. package/dist/cookie/cookie.js +1 -3
  31. package/dist/cookie/cookie.mjs +1 -3
  32. package/dist/cookie/utils.js +7 -5
  33. package/dist/cookie/utils.mjs +7 -5
  34. package/dist/error.d.ts +5 -8
  35. package/dist/error.js +26 -19
  36. package/dist/error.mjs +26 -19
  37. package/dist/handler/error.js +4 -4
  38. package/dist/handler/error.mjs +5 -5
  39. package/dist/handler/fetch.js +47 -16
  40. package/dist/handler/fetch.mjs +48 -17
  41. package/dist/index.d.ts +2 -2
  42. package/dist/index.js +2 -7
  43. package/dist/index.mjs +2 -2
  44. package/dist/parse-query.js +1 -1
  45. package/dist/parse-query.mjs +1 -1
  46. package/dist/plugin/bun.js +29 -3
  47. package/dist/plugin/bun.mjs +28 -3
  48. package/dist/plugin/core.d.ts +8 -1
  49. package/dist/plugin/core.js +16 -10
  50. package/dist/plugin/core.mjs +16 -10
  51. package/dist/plugin/esbuild.js +28 -3
  52. package/dist/plugin/esbuild.mjs +28 -3
  53. package/dist/plugin/source.js +30 -4
  54. package/dist/plugin/source.mjs +31 -5
  55. package/dist/plugin/treeshake.d.ts +10 -0
  56. package/dist/plugin/treeshake.js +63 -0
  57. package/dist/plugin/treeshake.mjs +61 -0
  58. package/dist/plugin/vite.js +7 -1
  59. package/dist/plugin/vite.mjs +7 -1
  60. package/dist/sucrose.js +23 -10
  61. package/dist/sucrose.mjs +23 -10
  62. package/dist/trace.js +1 -1
  63. package/dist/trace.mjs +1 -1
  64. package/dist/type/bridge.d.ts +9 -12
  65. package/dist/type/bridge.js +0 -10
  66. package/dist/type/bridge.mjs +1 -9
  67. package/dist/type/coerce.d.ts +19 -1
  68. package/dist/type/coerce.js +148 -4
  69. package/dist/type/coerce.mjs +147 -6
  70. package/dist/type/compat.js +6 -7
  71. package/dist/type/compat.mjs +7 -8
  72. package/dist/type/constants.d.ts +1 -1
  73. package/dist/type/elysia/array-buffer.js +4 -4
  74. package/dist/type/elysia/array-buffer.mjs +4 -4
  75. package/dist/type/elysia/array-string.d.ts +2 -2
  76. package/dist/type/elysia/array-string.js +5 -5
  77. package/dist/type/elysia/array-string.mjs +6 -6
  78. package/dist/type/elysia/array.js +11 -8
  79. package/dist/type/elysia/array.mjs +11 -8
  80. package/dist/type/elysia/boolean-string.js +4 -4
  81. package/dist/type/elysia/boolean-string.mjs +4 -4
  82. package/dist/type/elysia/boolean.js +2 -2
  83. package/dist/type/elysia/boolean.mjs +2 -2
  84. package/dist/type/elysia/cookie.js +1 -4
  85. package/dist/type/elysia/cookie.mjs +1 -4
  86. package/dist/type/elysia/date.js +11 -10
  87. package/dist/type/elysia/date.mjs +11 -10
  88. package/dist/type/elysia/file.js +4 -4
  89. package/dist/type/elysia/file.mjs +4 -4
  90. package/dist/type/elysia/files.js +4 -4
  91. package/dist/type/elysia/files.mjs +4 -4
  92. package/dist/type/elysia/form.js +2 -2
  93. package/dist/type/elysia/form.mjs +4 -4
  94. package/dist/type/elysia/integer-string.js +7 -7
  95. package/dist/type/elysia/integer-string.mjs +8 -8
  96. package/dist/type/elysia/integer.js +2 -2
  97. package/dist/type/elysia/integer.mjs +2 -2
  98. package/dist/type/elysia/maybe-empty.d.ts +3 -2
  99. package/dist/type/elysia/maybe-empty.js +4 -4
  100. package/dist/type/elysia/maybe-empty.mjs +4 -4
  101. package/dist/type/elysia/nullable.d.ts +3 -2
  102. package/dist/type/elysia/nullable.js +3 -3
  103. package/dist/type/elysia/nullable.mjs +3 -3
  104. package/dist/type/elysia/number.js +2 -2
  105. package/dist/type/elysia/number.mjs +2 -2
  106. package/dist/type/elysia/numeric-enum.js +3 -3
  107. package/dist/type/elysia/numeric-enum.mjs +3 -3
  108. package/dist/type/elysia/numeric.js +7 -7
  109. package/dist/type/elysia/numeric.mjs +7 -7
  110. package/dist/type/elysia/object-string.d.ts +2 -2
  111. package/dist/type/elysia/object-string.js +5 -5
  112. package/dist/type/elysia/object-string.mjs +6 -6
  113. package/dist/type/elysia/object.js +12 -9
  114. package/dist/type/elysia/object.mjs +12 -9
  115. package/dist/type/elysia/optional.js +12 -5
  116. package/dist/type/elysia/optional.mjs +12 -5
  117. package/dist/type/elysia/string.js +2 -2
  118. package/dist/type/elysia/string.mjs +2 -2
  119. package/dist/type/elysia/uint8-array.js +2 -2
  120. package/dist/type/elysia/uint8-array.mjs +2 -2
  121. package/dist/type/elysia/union-enum.d.ts +3 -2
  122. package/dist/type/elysia/union-enum.js +2 -2
  123. package/dist/type/elysia/union-enum.mjs +2 -2
  124. package/dist/type/elysia/utils.js +4 -8
  125. package/dist/type/elysia/utils.mjs +4 -8
  126. package/dist/type/exports.js +2071 -39
  127. package/dist/type/exports.mjs +307 -17
  128. package/dist/type/index.d.ts +3 -3
  129. package/dist/type/index.js +4 -31
  130. package/dist/type/index.mjs +4 -26
  131. package/dist/type/types.d.ts +1 -1
  132. package/dist/type/utils.js +4 -4
  133. package/dist/type/utils.mjs +4 -4
  134. package/dist/type/validator/custom-error.d.ts +10 -0
  135. package/dist/type/validator/custom-error.js +113 -0
  136. package/dist/type/validator/custom-error.mjs +110 -0
  137. package/dist/type/validator/default-precompute.d.ts +11 -0
  138. package/dist/type/validator/default-precompute.js +216 -0
  139. package/dist/type/validator/default-precompute.mjs +212 -0
  140. package/dist/type/validator/frozen-check.d.ts +11 -0
  141. package/dist/type/validator/frozen-check.js +19 -0
  142. package/dist/type/validator/frozen-check.mjs +18 -0
  143. package/dist/type/{validator.d.ts → validator/index.d.ts} +6 -19
  144. package/dist/type/{validator.js → validator/index.js} +215 -346
  145. package/dist/type/validator/index.mjs +531 -0
  146. package/dist/type/validator/string-codec-aot.d.ts +9 -0
  147. package/dist/type/validator/string-codec-aot.js +106 -0
  148. package/dist/type/validator/string-codec-aot.mjs +102 -0
  149. package/dist/type/validator/validator-cache.d.ts +21 -0
  150. package/dist/type/validator/validator-cache.js +163 -0
  151. package/dist/type/validator/validator-cache.mjs +161 -0
  152. package/dist/types.d.ts +7 -1
  153. package/dist/universal/file.js +1 -1
  154. package/dist/universal/file.mjs +1 -1
  155. package/dist/utils.d.ts +8 -1
  156. package/dist/utils.js +82 -46
  157. package/dist/utils.mjs +82 -47
  158. package/dist/validator/index.d.ts +1 -1
  159. package/dist/validator/index.js +13 -6
  160. package/dist/validator/index.mjs +13 -6
  161. package/dist/validator/route.js +1 -1
  162. package/dist/validator/route.mjs +1 -1
  163. package/dist/ws/context.js +4 -7
  164. package/dist/ws/context.mjs +4 -7
  165. package/dist/ws/route.js +41 -26
  166. package/dist/ws/route.mjs +41 -26
  167. package/package.json +10 -2
  168. package/dist/type/validator.mjs +0 -663
@@ -32,7 +32,6 @@ var __copyProps = (to, from, except, desc) => {
32
32
  }
33
33
  return to;
34
34
  };
35
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
36
35
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
37
36
  value: mod,
38
37
  enumerable: true
@@ -41,5 +40,4 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
41
40
  //#endregion
42
41
 
43
42
  exports.__exportAll = __exportAll;
44
- exports.__reExport = __reExport;
45
43
  exports.__toESM = __toESM;
@@ -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 | ArrayBuffer | unknown[] | 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();
@@ -62,13 +62,13 @@ function createPlainHandler(handler, handleError, Context) {
62
62
  }
63
63
  function createRouteMap(app) {
64
64
  const Context = createBunContext(app);
65
+ const handleError = require_handler_error.createErrorHandler(require_utils.flattenChain(app["~hookChain"])?.error, require_adapter_web_standard_index.WebStandardAdapter.response.map, new Response("Not Found", { status: 404 }), app["~config"]?.allowUnsafeValidationDetails);
65
66
  function fetch(request) {
66
67
  return handleError(new Context(request), new require_error.NotFound());
67
68
  }
68
69
  const history = app.history;
69
70
  const length = history?.length ?? 0;
70
71
  if (length === 0) return [{ "/elysia": new Response("hi") }, fetch];
71
- const handleError = require_handler_error.createErrorHandler(require_utils.flattenChain(app["~hookChain"])?.error, require_adapter_web_standard_index.WebStandardAdapter.response.map, new Response("Not Found", { status: 404 }), app["~config"]?.allowUnsafeValidationDetails);
72
72
  const routes = require_utils.nullObject();
73
73
  for (let i = 0; i < length; i++) {
74
74
  const route = history[i];
@@ -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();
@@ -61,13 +61,13 @@ function createPlainHandler(handler, handleError, Context) {
61
61
  }
62
62
  function createRouteMap(app) {
63
63
  const Context = createBunContext(app);
64
+ const handleError = createErrorHandler(flattenChain(app["~hookChain"])?.error, WebStandardAdapter.response.map, new Response("Not Found", { status: 404 }), app["~config"]?.allowUnsafeValidationDetails);
64
65
  function fetch(request) {
65
66
  return handleError(new Context(request), new NotFound());
66
67
  }
67
68
  const history = app.history;
68
69
  const length = history?.length ?? 0;
69
70
  if (length === 0) return [{ "/elysia": new Response("hi") }, fetch];
70
- const handleError = createErrorHandler(flattenChain(app["~hookChain"])?.error, WebStandardAdapter.response.map, new Response("Not Found", { status: 404 }), app["~config"]?.allowUnsafeValidationDetails);
71
71
  const routes = nullObject();
72
72
  for (let i = 0; i < length; i++) {
73
73
  const route = history[i];
@@ -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 | ArrayBuffer | unknown[] | 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 | ArrayBuffer | unknown[] | 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[]>>;
@@ -51,7 +51,7 @@ function handleFile(response, set, request) {
51
51
  if (!set && !size) return new Response(response);
52
52
  if (!set) return new Response(response, { headers: defaultHeader });
53
53
  if (set.headers instanceof Headers) {
54
- for (const key of Object.keys(defaultHeader)) if (key in set.headers) set.headers.append(key, defaultHeader[key]);
54
+ for (const key of Object.keys(defaultHeader)) if (!set.headers.has(key)) set.headers.append(key, defaultHeader[key]);
55
55
  if (immutable) {
56
56
  set.headers.delete("content-length");
57
57
  set.headers.delete("accept-ranges");
@@ -96,7 +96,9 @@ function responseToSetHeaders(response, set) {
96
96
  };
97
97
  for (const [key, value] of response.headers.entries()) set.headers[key] = value;
98
98
  }
99
- if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
99
+ if (set.headers instanceof Headers) {
100
+ if (set.headers.has("content-encoding")) set.headers.delete("content-encoding");
101
+ } else if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
100
102
  return set;
101
103
  }
102
104
  const enqueueBinaryChunk = (controller, chunk) => {
@@ -50,7 +50,7 @@ function handleFile(response, set, request) {
50
50
  if (!set && !size) return new Response(response);
51
51
  if (!set) return new Response(response, { headers: defaultHeader });
52
52
  if (set.headers instanceof Headers) {
53
- for (const key of Object.keys(defaultHeader)) if (key in set.headers) set.headers.append(key, defaultHeader[key]);
53
+ for (const key of Object.keys(defaultHeader)) if (!set.headers.has(key)) set.headers.append(key, defaultHeader[key]);
54
54
  if (immutable) {
55
55
  set.headers.delete("content-length");
56
56
  set.headers.delete("accept-ranges");
@@ -95,7 +95,9 @@ function responseToSetHeaders(response, set) {
95
95
  };
96
96
  for (const [key, value] of response.headers.entries()) set.headers[key] = value;
97
97
  }
98
- if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
98
+ if (set.headers instanceof Headers) {
99
+ if (set.headers.has("content-encoding")) set.headers.delete("content-encoding");
100
+ } else if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
99
101
  return set;
100
102
  }
101
103
  const enqueueBinaryChunk = (controller, chunk) => {
@@ -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 | ArrayBuffer | unknown[] | 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
@@ -31,7 +31,7 @@ var Elysia = class Elysia {
31
31
  }
32
32
  }
33
33
  get history() {
34
- if (!this.#history) return void 0;
34
+ if (!this.#history) return;
35
35
  this.#resolveMacros();
36
36
  return this.#history;
37
37
  }
@@ -47,9 +47,8 @@ var Elysia = class Elysia {
47
47
  if (!this.#history) return [];
48
48
  if (this.#cachedRoutes) return this.#cachedRoutes;
49
49
  this.#resolveMacros();
50
- const routes = this.#history.map(([method, path, handler, , hook, appHook]) => {
51
- const flatAppHook = require_utils.flattenChain(appHook);
52
- const merged = flatAppHook ? hook ? require_utils.mergeHook(require_utils.cloneHook(hook), flatAppHook) : flatAppHook : hook;
50
+ const routes = this.#history.map(([method, path, handler, instance, hook, appHook, inheritedChain]) => {
51
+ const merged = require_compile_handler_index.composeRouteHook(instance, hook, appHook, inheritedChain, this);
53
52
  if (merged?.schemas?.length) for (const entry of merged.schemas) {
54
53
  if (!entry?.response) continue;
55
54
  merged.response = require_utils.mergeResponse(merged.response, entry.response);
@@ -138,7 +137,7 @@ var Elysia = class Elysia {
138
137
  headers(headers) {
139
138
  const ext = this.#ext;
140
139
  if (ext.headers) Object.assign(ext.headers, headers);
141
- else ext.headers = headers;
140
+ else ext.headers = Object.assign(require_utils.nullObject(), headers);
142
141
  return this;
143
142
  }
144
143
  #on(type, fn, scope = this["~config"]?.as) {
@@ -293,7 +292,8 @@ var Elysia = class Elysia {
293
292
  require_utils.hookToGuard(hook);
294
293
  if (hook.derive) {
295
294
  this["~derive"] ??= /* @__PURE__ */ new WeakSet();
296
- this["~derive"].add(hook.derive);
295
+ if (Array.isArray(hook.derive)) for (const fn of hook.derive) this["~derive"].add(fn);
296
+ else this["~derive"].add(hook.derive);
297
297
  }
298
298
  const trackFn = (fn) => {
299
299
  if (typeof fn !== "function") return;
@@ -355,7 +355,8 @@ var Elysia = class Elysia {
355
355
  if (hook.derive) {
356
356
  const promoted = require_utils.nullObject();
357
357
  for (const key of Object.keys(hook)) {
358
- if (!require_utils.eventProperties.has(key)) continue;
358
+ if (key === "derive" || key === "resolve") continue;
359
+ if (!require_utils.eventProperties.has(key) && !require_utils.schemaProperties.has(key) && key !== "schema" && key !== "schemas") continue;
359
360
  promoted[key] = hook[key];
360
361
  }
361
362
  const extras = [];
@@ -542,8 +543,11 @@ var Elysia = class Elysia {
542
543
  if (app["~ext"]) {
543
544
  const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
544
545
  const ext = this["~ext"] ??= require_utils.nullObject();
545
- if (decorator) if (ext.decorator) require_utils.mergeDeep(ext.decorator, decorator);
546
- else ext.decorator = Object.assign(require_utils.nullObject(), decorator);
546
+ if (decorator) {
547
+ const cloned = require_utils.clonePlainDecorators(decorator);
548
+ if (ext.decorator) require_utils.mergeDeep(ext.decorator, cloned);
549
+ else ext.decorator = Object.assign(require_utils.nullObject(), cloned);
550
+ }
547
551
  if (store) if (ext.store) require_utils.mergeDeep(ext.store, store);
548
552
  else ext.store = Object.assign(require_utils.nullObject(), store);
549
553
  if (headers) if (ext.headers) Object.assign(ext.headers, headers);
@@ -774,7 +778,7 @@ var Elysia = class Elysia {
774
778
  if (!adapter?.websocket && !require_universal_constants.isBun) throw new Error(`[Elysia] WebSocket is not supported on '${adapter?.name ?? "web-standard"}' adapter.`);
775
779
  let opts;
776
780
  if (handler !== void 0) {
777
- opts = optionsOrHandler ?? require_utils.nullObject();
781
+ opts = Object.assign(require_utils.nullObject(), optionsOrHandler);
778
782
  if (opts.message != null && opts.message !== handler) throw new Error("[Elysia] .ws(): cannot specify 'message' as both positional handler and options.message");
779
783
  opts.message = handler;
780
784
  } else if (typeof optionsOrHandler === "function") {
@@ -847,6 +851,7 @@ var Elysia = class Elysia {
847
851
  };
848
852
  }
849
853
  #saveHandler(method, path, handler) {
854
+ if (require_constants.isDynamicRegex.test(path)) return;
850
855
  this.#initMap();
851
856
  const map = this["~map"][require_utils.mapMethodBack(method)] ??= require_utils.nullObject();
852
857
  map[path] = handler;
@@ -892,6 +897,22 @@ var Elysia = class Elysia {
892
897
  }
893
898
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
894
899
  const strict = !!this["~config"]?.strictPath;
900
+ let explicitPaths;
901
+ if (!strict && this["~config"]?.distinctPath) {
902
+ explicitPaths = /* @__PURE__ */ new Map();
903
+ for (let i = 0; i < length; i++) {
904
+ const route = this.#history[i];
905
+ const m = route[0] === "WS" ? "WS" : require_utils.mapMethodBack(route[0]);
906
+ const p = route[1];
907
+ let set = explicitPaths.get(m);
908
+ if (!set) explicitPaths.set(m, set = /* @__PURE__ */ new Set());
909
+ set.add(p);
910
+ if (require_constants.needEncodeRegex.test(p)) {
911
+ const encoded = encodeURI(p);
912
+ if (encoded !== p) set.add(encoded);
913
+ }
914
+ }
915
+ }
895
916
  for (let i = 0; i < length; i++) {
896
917
  const route = this.#history[i];
897
918
  const method = require_utils.mapMethodBack(route[0]);
@@ -907,7 +928,7 @@ var Elysia = class Elysia {
907
928
  wsMap[path] = handler;
908
929
  if (!this["~config"]?.strictPath) {
909
930
  const loose = require_utils.getLoosePath(path);
910
- if (loose !== path) wsMap[loose] = handler;
931
+ if (loose !== path && !explicitPaths?.get("WS")?.has(loose)) wsMap[loose] = handler;
911
932
  }
912
933
  }
913
934
  if (options && require_utils.isNotEmpty(options)) {
@@ -933,44 +954,46 @@ var Elysia = class Elysia {
933
954
  (target[path] ??= require_utils.nullObject())[method] = staticResponse;
934
955
  if (!this["~config"]?.strictPath) {
935
956
  const loose = require_utils.getLoosePath(path);
936
- (target[loose] ??= require_utils.nullObject())[method] = staticResponse;
957
+ if (!explicitPaths?.get(method)?.has(loose)) (target[loose] ??= require_utils.nullObject())[method] = staticResponse;
937
958
  }
938
959
  }
939
960
  }
940
961
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
941
962
  const autoHead = enableAutoHead && method === "GET" && !explicitHead?.has(path);
942
- const registerPattern = (registerMain, registerHead, handler, headHandler) => {
943
- const add = (p) => {
944
- registerMain(p, handler);
945
- if (headHandler) registerHead(p, headHandler);
946
- if (!strict) {
947
- const loose = require_utils.getLoosePath(p);
948
- if (loose !== p) {
949
- registerMain(loose, handler);
950
- if (headHandler) registerHead(loose, headHandler);
951
- }
952
- }
953
- };
954
- add(path);
955
- if (require_constants.needEncodeRegex.test(path)) {
956
- const encoded = encodeURI(path);
957
- 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);
958
978
  }
959
- };
960
- if (require_constants.isDynamicRegex.test(path)) {
979
+ }
980
+ if (isDynamic) {
961
981
  const router = this["~router"] ??= new memoirist.default();
962
982
  const handler = this.handler(i, precompile, void 0, sharedStatic);
963
- registerPattern((p, h) => router.add(method, p, h, false), (p, h) => router.add("HEAD", p, h, false), handler, autoHead ? wrapHeadHandler(handler) : void 0);
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
+ }
964
988
  } else {
965
989
  const map = methods[method] ??= require_utils.nullObject();
966
990
  const handler = this.handler(i, precompile, route, sharedStatic);
967
991
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
968
992
  const head = autoHead ? methods["HEAD"] ??= require_utils.nullObject() : void 0;
969
- registerPattern((p, h) => {
970
- map[p] = h;
971
- }, (p, h) => {
972
- head[p] = h;
973
- }, handler, headHandler);
993
+ for (let p = 0; p < paths.length; p++) {
994
+ map[paths[p]] = handler;
995
+ if (headHandler) head[paths[p]] = headHandler;
996
+ }
974
997
  }
975
998
  }
976
999
  }
package/dist/base.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import { isBun } from "./universal/constants.mjs";
2
2
  import { MethodMap, isDynamicRegex, needEncodeRegex } from "./constants.mjs";
3
- import { cloneHook, coalesceStandaloneSchemas, createErrorEventHandler, eventProperties, flattenChain, fnOrigin, fnv1a, getLoosePath, hookToGuard, isEmpty, isNotEmpty, isRecordNumber, joinPath, mapMethodBack, mergeDeep, mergeHook, 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";
7
7
  import { BunAdapter } from "./adapter/bun/index.mjs";
8
8
  import { applyHoc, createFetchHandler } from "./handler/fetch.mjs";
9
- import { buildNativeStaticResponse, compileHandler } from "./compile/handler/index.mjs";
9
+ import { buildNativeStaticResponse, compileHandler, composeRouteHook } from "./compile/handler/index.mjs";
10
10
  import Memoirist from "memoirist";
11
11
 
12
12
  //#region src/base.ts
@@ -28,7 +28,7 @@ var Elysia = class Elysia {
28
28
  }
29
29
  }
30
30
  get history() {
31
- if (!this.#history) return void 0;
31
+ if (!this.#history) return;
32
32
  this.#resolveMacros();
33
33
  return this.#history;
34
34
  }
@@ -44,9 +44,8 @@ var Elysia = class Elysia {
44
44
  if (!this.#history) return [];
45
45
  if (this.#cachedRoutes) return this.#cachedRoutes;
46
46
  this.#resolveMacros();
47
- const routes = this.#history.map(([method, path, handler, , hook, appHook]) => {
48
- const flatAppHook = flattenChain(appHook);
49
- const merged = flatAppHook ? hook ? mergeHook(cloneHook(hook), flatAppHook) : flatAppHook : hook;
47
+ const routes = this.#history.map(([method, path, handler, instance, hook, appHook, inheritedChain]) => {
48
+ const merged = composeRouteHook(instance, hook, appHook, inheritedChain, this);
50
49
  if (merged?.schemas?.length) for (const entry of merged.schemas) {
51
50
  if (!entry?.response) continue;
52
51
  merged.response = mergeResponse(merged.response, entry.response);
@@ -135,7 +134,7 @@ var Elysia = class Elysia {
135
134
  headers(headers) {
136
135
  const ext = this.#ext;
137
136
  if (ext.headers) Object.assign(ext.headers, headers);
138
- else ext.headers = headers;
137
+ else ext.headers = Object.assign(nullObject(), headers);
139
138
  return this;
140
139
  }
141
140
  #on(type, fn, scope = this["~config"]?.as) {
@@ -290,7 +289,8 @@ var Elysia = class Elysia {
290
289
  hookToGuard(hook);
291
290
  if (hook.derive) {
292
291
  this["~derive"] ??= /* @__PURE__ */ new WeakSet();
293
- this["~derive"].add(hook.derive);
292
+ if (Array.isArray(hook.derive)) for (const fn of hook.derive) this["~derive"].add(fn);
293
+ else this["~derive"].add(hook.derive);
294
294
  }
295
295
  const trackFn = (fn) => {
296
296
  if (typeof fn !== "function") return;
@@ -352,7 +352,8 @@ var Elysia = class Elysia {
352
352
  if (hook.derive) {
353
353
  const promoted = nullObject();
354
354
  for (const key of Object.keys(hook)) {
355
- if (!eventProperties.has(key)) continue;
355
+ if (key === "derive" || key === "resolve") continue;
356
+ if (!eventProperties.has(key) && !schemaProperties.has(key) && key !== "schema" && key !== "schemas") continue;
356
357
  promoted[key] = hook[key];
357
358
  }
358
359
  const extras = [];
@@ -539,8 +540,11 @@ var Elysia = class Elysia {
539
540
  if (app["~ext"]) {
540
541
  const { decorator, store, headers, models, parser, macro, error, hoc } = app["~ext"];
541
542
  const ext = this["~ext"] ??= nullObject();
542
- if (decorator) if (ext.decorator) mergeDeep(ext.decorator, decorator);
543
- else ext.decorator = Object.assign(nullObject(), decorator);
543
+ if (decorator) {
544
+ const cloned = clonePlainDecorators(decorator);
545
+ if (ext.decorator) mergeDeep(ext.decorator, cloned);
546
+ else ext.decorator = Object.assign(nullObject(), cloned);
547
+ }
544
548
  if (store) if (ext.store) mergeDeep(ext.store, store);
545
549
  else ext.store = Object.assign(nullObject(), store);
546
550
  if (headers) if (ext.headers) Object.assign(ext.headers, headers);
@@ -771,7 +775,7 @@ var Elysia = class Elysia {
771
775
  if (!adapter?.websocket && !isBun) throw new Error(`[Elysia] WebSocket is not supported on '${adapter?.name ?? "web-standard"}' adapter.`);
772
776
  let opts;
773
777
  if (handler !== void 0) {
774
- opts = optionsOrHandler ?? nullObject();
778
+ opts = Object.assign(nullObject(), optionsOrHandler);
775
779
  if (opts.message != null && opts.message !== handler) throw new Error("[Elysia] .ws(): cannot specify 'message' as both positional handler and options.message");
776
780
  opts.message = handler;
777
781
  } else if (typeof optionsOrHandler === "function") {
@@ -844,6 +848,7 @@ var Elysia = class Elysia {
844
848
  };
845
849
  }
846
850
  #saveHandler(method, path, handler) {
851
+ if (isDynamicRegex.test(path)) return;
847
852
  this.#initMap();
848
853
  const map = this["~map"][mapMethodBack(method)] ??= nullObject();
849
854
  map[path] = handler;
@@ -889,6 +894,22 @@ var Elysia = class Elysia {
889
894
  }
890
895
  const wrapHeadHandler = Elysia.#wrapHeadHandler;
891
896
  const strict = !!this["~config"]?.strictPath;
897
+ let explicitPaths;
898
+ if (!strict && this["~config"]?.distinctPath) {
899
+ explicitPaths = /* @__PURE__ */ new Map();
900
+ for (let i = 0; i < length; i++) {
901
+ const route = this.#history[i];
902
+ const m = route[0] === "WS" ? "WS" : mapMethodBack(route[0]);
903
+ const p = route[1];
904
+ let set = explicitPaths.get(m);
905
+ if (!set) explicitPaths.set(m, set = /* @__PURE__ */ new Set());
906
+ set.add(p);
907
+ if (needEncodeRegex.test(p)) {
908
+ const encoded = encodeURI(p);
909
+ if (encoded !== p) set.add(encoded);
910
+ }
911
+ }
912
+ }
892
913
  for (let i = 0; i < length; i++) {
893
914
  const route = this.#history[i];
894
915
  const method = mapMethodBack(route[0]);
@@ -904,7 +925,7 @@ var Elysia = class Elysia {
904
925
  wsMap[path] = handler;
905
926
  if (!this["~config"]?.strictPath) {
906
927
  const loose = getLoosePath(path);
907
- if (loose !== path) wsMap[loose] = handler;
928
+ if (loose !== path && !explicitPaths?.get("WS")?.has(loose)) wsMap[loose] = handler;
908
929
  }
909
930
  }
910
931
  if (options && isNotEmpty(options)) {
@@ -930,44 +951,46 @@ var Elysia = class Elysia {
930
951
  (target[path] ??= nullObject())[method] = staticResponse;
931
952
  if (!this["~config"]?.strictPath) {
932
953
  const loose = getLoosePath(path);
933
- (target[loose] ??= nullObject())[method] = staticResponse;
954
+ if (!explicitPaths?.get(method)?.has(loose)) (target[loose] ??= nullObject())[method] = staticResponse;
934
955
  }
935
956
  }
936
957
  }
937
958
  const sharedStatic = maybeStatic && staticResponse instanceof Response ? staticResponse : void 0;
938
959
  const autoHead = enableAutoHead && method === "GET" && !explicitHead?.has(path);
939
- const registerPattern = (registerMain, registerHead, handler, headHandler) => {
940
- const add = (p) => {
941
- registerMain(p, handler);
942
- if (headHandler) registerHead(p, headHandler);
943
- if (!strict) {
944
- const loose = getLoosePath(p);
945
- if (loose !== p) {
946
- registerMain(loose, handler);
947
- if (headHandler) registerHead(loose, headHandler);
948
- }
949
- }
950
- };
951
- add(path);
952
- if (needEncodeRegex.test(path)) {
953
- const encoded = encodeURI(path);
954
- 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);
955
975
  }
956
- };
957
- if (isDynamicRegex.test(path)) {
976
+ }
977
+ if (isDynamic) {
958
978
  const router = this["~router"] ??= new Memoirist();
959
979
  const handler = this.handler(i, precompile, void 0, sharedStatic);
960
- registerPattern((p, h) => router.add(method, p, h, false), (p, h) => router.add("HEAD", p, h, false), handler, autoHead ? wrapHeadHandler(handler) : void 0);
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
+ }
961
985
  } else {
962
986
  const map = methods[method] ??= nullObject();
963
987
  const handler = this.handler(i, precompile, route, sharedStatic);
964
988
  const headHandler = autoHead ? wrapHeadHandler(handler) : void 0;
965
989
  const head = autoHead ? methods["HEAD"] ??= nullObject() : void 0;
966
- registerPattern((p, h) => {
967
- map[p] = h;
968
- }, (p, h) => {
969
- head[p] = h;
970
- }, handler, headHandler);
990
+ for (let p = 0; p < paths.length; p++) {
991
+ map[paths[p]] = handler;
992
+ if (headHandler) head[paths[p]] = headHandler;
993
+ }
971
994
  }
972
995
  }
973
996
  }