elysia 2.0.0-beta.2 → 2.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/dist/adapter/bun/index.d.ts +18 -2
  2. package/dist/adapter/bun/index.js +467 -110
  3. package/dist/adapter/bun/index.mjs +467 -112
  4. package/dist/adapter/types.d.ts +2 -21
  5. package/dist/adapter/utils.d.ts +14 -3
  6. package/dist/adapter/utils.js +146 -87
  7. package/dist/adapter/utils.mjs +148 -90
  8. package/dist/adapter/web-standard/handler.d.ts +1 -1
  9. package/dist/adapter/web-standard/handler.js +47 -36
  10. package/dist/adapter/web-standard/handler.mjs +48 -37
  11. package/dist/adapter/web-standard/index.js +2 -30
  12. package/dist/adapter/web-standard/index.mjs +2 -30
  13. package/dist/adapter/web-standard/utils.js +5 -18
  14. package/dist/adapter/web-standard/utils.mjs +5 -18
  15. package/dist/base.d.ts +99 -67
  16. package/dist/base.js +678 -510
  17. package/dist/base.mjs +682 -514
  18. package/dist/compile/aot-capture.d.ts +2 -13
  19. package/dist/compile/aot-capture.js +26 -69
  20. package/dist/compile/aot-capture.mjs +28 -67
  21. package/dist/compile/aot-emit.d.ts +9 -7
  22. package/dist/compile/aot-emit.js +42 -19
  23. package/dist/compile/aot-emit.mjs +42 -20
  24. package/dist/compile/aot.d.ts +17 -19
  25. package/dist/compile/aot.js +41 -51
  26. package/dist/compile/aot.mjs +39 -49
  27. package/dist/compile/handler/descriptor.d.ts +9 -12
  28. package/dist/compile/handler/descriptor.js +19 -44
  29. package/dist/compile/handler/descriptor.mjs +20 -42
  30. package/dist/compile/handler/frozen-validator.d.ts +5 -10
  31. package/dist/compile/handler/frozen-validator.js +55 -105
  32. package/dist/compile/handler/frozen-validator.mjs +53 -105
  33. package/dist/compile/handler/index.d.ts +7 -5
  34. package/dist/compile/handler/index.js +270 -111
  35. package/dist/compile/handler/index.mjs +270 -113
  36. package/dist/compile/handler/jit.d.ts +19 -17
  37. package/dist/compile/handler/jit.js +222 -149
  38. package/dist/compile/handler/jit.mjs +224 -152
  39. package/dist/compile/handler/params.d.ts +1 -4
  40. package/dist/compile/handler/params.js +10 -5
  41. package/dist/compile/handler/params.mjs +14 -8
  42. package/dist/compile/handler/reconstruct.d.ts +2 -2
  43. package/dist/compile/handler/reconstruct.js +6 -4
  44. package/dist/compile/handler/reconstruct.mjs +6 -4
  45. package/dist/compile/handler/static-clone-resolver.d.ts +6 -0
  46. package/dist/compile/handler/static-clone-resolver.js +8 -0
  47. package/dist/compile/handler/static-clone-resolver.mjs +7 -0
  48. package/dist/compile/handler/utils.d.ts +22 -11
  49. package/dist/compile/handler/utils.js +159 -253
  50. package/dist/compile/handler/utils.mjs +155 -252
  51. package/dist/compile/jit-probe.d.ts +2 -2
  52. package/dist/compile/jit-probe.js +2 -3
  53. package/dist/compile/jit-probe.mjs +2 -3
  54. package/dist/compile/lexer.d.ts +7 -4
  55. package/dist/compile/lexer.js +268 -6
  56. package/dist/compile/lexer.mjs +268 -4
  57. package/dist/compile/utils.js +7 -4
  58. package/dist/compile/utils.mjs +7 -4
  59. package/dist/compiled.d.ts +0 -1
  60. package/dist/compiled.js +0 -1
  61. package/dist/compiled.mjs +0 -1
  62. package/dist/context.d.ts +14 -4
  63. package/dist/context.js +17 -32
  64. package/dist/context.mjs +19 -34
  65. package/dist/cookie/config.d.ts +7 -2
  66. package/dist/cookie/config.js +76 -16
  67. package/dist/cookie/config.mjs +77 -18
  68. package/dist/cookie/cookie.d.ts +1 -1
  69. package/dist/cookie/cookie.js +8 -10
  70. package/dist/cookie/cookie.mjs +8 -10
  71. package/dist/cookie/crypto.d.ts +8 -7
  72. package/dist/cookie/crypto.js +51 -40
  73. package/dist/cookie/crypto.mjs +51 -41
  74. package/dist/cookie/error.d.ts +1 -2
  75. package/dist/cookie/error.js +6 -4
  76. package/dist/cookie/error.mjs +6 -4
  77. package/dist/cookie/lib.js +7 -2
  78. package/dist/cookie/lib.mjs +7 -2
  79. package/dist/cookie/serialize.js +1 -1
  80. package/dist/cookie/serialize.mjs +1 -1
  81. package/dist/cookie/types.d.ts +10 -0
  82. package/dist/cookie/utils.d.ts +4 -8
  83. package/dist/cookie/utils.js +86 -52
  84. package/dist/cookie/utils.mjs +89 -54
  85. package/dist/error.d.ts +113 -103
  86. package/dist/error.js +181 -117
  87. package/dist/error.mjs +179 -118
  88. package/dist/generation.d.ts +2 -2
  89. package/dist/handler/error.d.ts +26 -15
  90. package/dist/handler/error.js +77 -96
  91. package/dist/handler/error.mjs +74 -97
  92. package/dist/handler/fetch.js +87 -108
  93. package/dist/handler/fetch.mjs +89 -110
  94. package/dist/handler/utils.d.ts +12 -6
  95. package/dist/handler/utils.js +84 -28
  96. package/dist/handler/utils.mjs +80 -28
  97. package/dist/index.d.ts +12 -12
  98. package/dist/index.js +2 -9
  99. package/dist/index.mjs +1 -1
  100. package/dist/memory.js +1 -1
  101. package/dist/memory.mjs +1 -1
  102. package/dist/package.js +1 -1
  103. package/dist/package.mjs +1 -1
  104. package/dist/plugin/aot/bun.d.ts +8 -1
  105. package/dist/plugin/aot/bun.js +16 -9
  106. package/dist/plugin/aot/bun.mjs +17 -10
  107. package/dist/plugin/aot/core.d.ts +52 -60
  108. package/dist/plugin/aot/core.js +208 -109
  109. package/dist/plugin/aot/core.mjs +205 -111
  110. package/dist/plugin/aot/esbuild.js +8 -5
  111. package/dist/plugin/aot/esbuild.mjs +9 -6
  112. package/dist/plugin/aot/hooks.d.ts +6 -17
  113. package/dist/plugin/aot/hooks.js +36 -14
  114. package/dist/plugin/aot/hooks.mjs +37 -16
  115. package/dist/plugin/aot/rspack-loader.d.ts +1 -5
  116. package/dist/plugin/aot/rspack-loader.js +1 -10
  117. package/dist/plugin/aot/rspack-loader.mjs +1 -10
  118. package/dist/plugin/aot/rspack.js +2 -5
  119. package/dist/plugin/aot/rspack.mjs +3 -6
  120. package/dist/plugin/aot/source.d.ts +6 -42
  121. package/dist/plugin/aot/source.js +71 -71
  122. package/dist/plugin/aot/source.mjs +72 -72
  123. package/dist/plugin/aot/treeshake.js +2 -6
  124. package/dist/plugin/aot/treeshake.mjs +2 -6
  125. package/dist/plugin/aot/unplugin.d.ts +1 -4
  126. package/dist/plugin/aot/unplugin.js +4 -13
  127. package/dist/plugin/aot/unplugin.mjs +4 -13
  128. package/dist/plugin/aot/vite.d.ts +2 -6
  129. package/dist/plugin/aot/worker.js +2 -2
  130. package/dist/plugin/aot/worker.mjs +2 -2
  131. package/dist/plugin/auto-head.js +1 -10
  132. package/dist/plugin/auto-head.mjs +1 -10
  133. package/dist/plugin/trace.d.ts +2 -1
  134. package/dist/route-table.d.ts +3 -0
  135. package/dist/route-table.js +16 -11
  136. package/dist/route-table.mjs +16 -11
  137. package/dist/schema-snapshot.d.ts +0 -4
  138. package/dist/schema-snapshot.js +32 -49
  139. package/dist/schema-snapshot.mjs +32 -49
  140. package/dist/sucrose.d.ts +6 -55
  141. package/dist/sucrose.js +103 -731
  142. package/dist/sucrose.mjs +102 -724
  143. package/dist/trace.d.ts +5 -8
  144. package/dist/trace.js +23 -134
  145. package/dist/trace.mjs +24 -135
  146. package/dist/type/bridge-live.d.ts +4 -2
  147. package/dist/type/bridge-live.js +6 -3
  148. package/dist/type/bridge-live.mjs +4 -2
  149. package/dist/type/bridge.d.ts +6 -4
  150. package/dist/type/bridge.js +17 -9
  151. package/dist/type/bridge.mjs +5 -3
  152. package/dist/type/coerce-plan.d.ts +5 -5
  153. package/dist/type/coerce-plan.js +41 -39
  154. package/dist/type/coerce-plan.mjs +43 -39
  155. package/dist/type/coerce.d.ts +3 -7
  156. package/dist/type/coerce.js +18 -75
  157. package/dist/type/coerce.mjs +19 -76
  158. package/dist/type/compat.d.ts +3 -0
  159. package/dist/type/compat.js +23 -14
  160. package/dist/type/compat.mjs +20 -10
  161. package/dist/type/elysia/array-buffer.d.ts +4 -1
  162. package/dist/type/elysia/array-buffer.js +17 -17
  163. package/dist/type/elysia/array-buffer.mjs +17 -17
  164. package/dist/type/elysia/array-string.js +2 -40
  165. package/dist/type/elysia/array-string.mjs +2 -39
  166. package/dist/type/elysia/array.js +5 -9
  167. package/dist/type/elysia/array.mjs +5 -9
  168. package/dist/type/elysia/boolean-string.js +2 -3
  169. package/dist/type/elysia/boolean-string.mjs +1 -1
  170. package/dist/type/elysia/boolean.js +3 -12
  171. package/dist/type/elysia/boolean.mjs +3 -11
  172. package/dist/type/elysia/cookie.d.ts +3 -4
  173. package/dist/type/elysia/cookie.js +5 -15
  174. package/dist/type/elysia/cookie.mjs +5 -15
  175. package/dist/type/elysia/date.js +13 -20
  176. package/dist/type/elysia/date.mjs +10 -16
  177. package/dist/type/elysia/file-type.d.ts +11 -4
  178. package/dist/type/elysia/file-type.js +17 -2
  179. package/dist/type/elysia/file-type.mjs +17 -3
  180. package/dist/type/elysia/file.d.ts +1 -3
  181. package/dist/type/elysia/file.js +11 -27
  182. package/dist/type/elysia/file.mjs +11 -12
  183. package/dist/type/elysia/files.js +7 -11
  184. package/dist/type/elysia/files.mjs +7 -10
  185. package/dist/type/elysia/form.js +2 -3
  186. package/dist/type/elysia/form.mjs +3 -3
  187. package/dist/type/elysia/integer-string.d.ts +1 -1
  188. package/dist/type/elysia/integer-string.js +4 -30
  189. package/dist/type/elysia/integer-string.mjs +5 -30
  190. package/dist/type/elysia/integer.js +3 -12
  191. package/dist/type/elysia/integer.mjs +3 -11
  192. package/dist/type/elysia/intersect.js +0 -5
  193. package/dist/type/elysia/intersect.mjs +0 -5
  194. package/dist/type/elysia/json-string.d.ts +7 -0
  195. package/dist/type/elysia/json-string.js +47 -0
  196. package/dist/type/elysia/json-string.mjs +46 -0
  197. package/dist/type/elysia/keep-config.d.ts +14 -0
  198. package/dist/type/elysia/keep-config.js +62 -0
  199. package/dist/type/elysia/keep-config.mjs +53 -0
  200. package/dist/type/elysia/maybe-empty.js +3 -4
  201. package/dist/type/elysia/maybe-empty.mjs +1 -1
  202. package/dist/type/elysia/nullable.js +2 -3
  203. package/dist/type/elysia/nullable.mjs +1 -1
  204. package/dist/type/elysia/number.d.ts +2 -1
  205. package/dist/type/elysia/number.js +19 -11
  206. package/dist/type/elysia/number.mjs +18 -10
  207. package/dist/type/elysia/numeric-enum.d.ts +1 -1
  208. package/dist/type/elysia/numeric-enum.js +4 -5
  209. package/dist/type/elysia/numeric-enum.mjs +3 -3
  210. package/dist/type/elysia/numeric.d.ts +4 -2
  211. package/dist/type/elysia/numeric.js +20 -17
  212. package/dist/type/elysia/numeric.mjs +19 -16
  213. package/dist/type/elysia/object-string.js +2 -37
  214. package/dist/type/elysia/object-string.mjs +2 -36
  215. package/dist/type/elysia/object.js +5 -9
  216. package/dist/type/elysia/object.mjs +5 -9
  217. package/dist/type/elysia/optional.js +8 -8
  218. package/dist/type/elysia/optional.mjs +7 -7
  219. package/dist/type/elysia/problem.d.ts +20 -0
  220. package/dist/type/elysia/problem.js +25 -0
  221. package/dist/type/elysia/problem.mjs +24 -0
  222. package/dist/type/elysia/string.js +4 -3
  223. package/dist/type/elysia/string.mjs +4 -2
  224. package/dist/type/elysia/uint8-array.d.ts +1 -1
  225. package/dist/type/elysia/uint8-array.js +5 -20
  226. package/dist/type/elysia/uint8-array.mjs +5 -19
  227. package/dist/type/elysia/union-enum.js +7 -8
  228. package/dist/type/elysia/union-enum.mjs +6 -6
  229. package/dist/type/elysia/union.js +0 -5
  230. package/dist/type/elysia/union.mjs +0 -5
  231. package/dist/type/elysia/utils.d.ts +2 -4
  232. package/dist/type/elysia/utils.js +10 -21
  233. package/dist/type/elysia/utils.mjs +7 -15
  234. package/dist/type/exports.d.ts +4 -2
  235. package/dist/type/exports.js +23 -2
  236. package/dist/type/exports.mjs +11 -2
  237. package/dist/type/index.d.ts +10 -2
  238. package/dist/type/index.js +62 -15
  239. package/dist/type/index.mjs +65 -11
  240. package/dist/type/shared.d.ts +3 -9
  241. package/dist/type/shared.js +44 -97
  242. package/dist/type/shared.mjs +43 -97
  243. package/dist/type/sync-require.d.ts +11 -0
  244. package/dist/type/sync-require.js +14 -0
  245. package/dist/type/sync-require.mjs +12 -0
  246. package/dist/type/typebox-system-lite.d.ts +2 -0
  247. package/dist/type/typebox-system-lite.js +34 -0
  248. package/dist/type/typebox-system-lite.mjs +3 -0
  249. package/dist/type/typebox-system-require.d.ts +7 -0
  250. package/dist/type/typebox-system-require.js +24 -0
  251. package/dist/type/typebox-system-require.mjs +23 -0
  252. package/dist/type/typebox-type-live.d.ts +11 -0
  253. package/dist/type/typebox-type-live.js +45 -0
  254. package/dist/type/typebox-type-live.mjs +20 -0
  255. package/dist/type/typebox-type.d.ts +34 -0
  256. package/dist/type/typebox-type.js +199 -0
  257. package/dist/type/typebox-type.mjs +86 -0
  258. package/dist/type/typebox-value-live.d.ts +11 -0
  259. package/dist/type/typebox-value-live.js +31 -0
  260. package/dist/type/typebox-value-live.mjs +13 -0
  261. package/dist/type/typebox-value-ops.d.ts +4 -0
  262. package/dist/type/typebox-value-ops.js +90 -0
  263. package/dist/type/typebox-value-ops.mjs +5 -0
  264. package/dist/type/typebox-value-require.d.ts +8 -0
  265. package/dist/type/typebox-value-require.js +28 -0
  266. package/dist/type/typebox-value-require.mjs +25 -0
  267. package/dist/type/typebox-value.d.ts +35 -0
  268. package/dist/type/typebox-value.js +161 -0
  269. package/dist/type/typebox-value.mjs +74 -0
  270. package/dist/type/utils.js +1 -10
  271. package/dist/type/utils.mjs +1 -10
  272. package/dist/type/validator/clean-safe.d.ts +2 -4
  273. package/dist/type/validator/clean-safe.js +15 -11
  274. package/dist/type/validator/clean-safe.mjs +16 -10
  275. package/dist/type/validator/custom-error.js +12 -16
  276. package/dist/type/validator/custom-error.mjs +11 -14
  277. package/dist/type/validator/default-precompute.d.ts +9 -1
  278. package/dist/type/validator/default-precompute.js +40 -77
  279. package/dist/type/validator/default-precompute.mjs +37 -74
  280. package/dist/type/validator/exact-mirror-live.d.ts +8 -0
  281. package/dist/type/validator/exact-mirror-live.js +22 -0
  282. package/dist/type/validator/exact-mirror-live.mjs +17 -0
  283. package/dist/type/validator/exact-mirror-require.d.ts +4 -0
  284. package/dist/type/validator/exact-mirror-require.js +11 -0
  285. package/dist/type/validator/exact-mirror-require.mjs +9 -0
  286. package/dist/type/validator/exact-mirror.js +8 -8
  287. package/dist/type/validator/exact-mirror.mjs +9 -8
  288. package/dist/type/validator/frozen-check.js +5 -6
  289. package/dist/type/validator/frozen-check.mjs +6 -7
  290. package/dist/type/validator/index.d.ts +1 -0
  291. package/dist/type/validator/index.js +169 -166
  292. package/dist/type/validator/index.mjs +162 -158
  293. package/dist/type/validator/string-codec-aot.d.ts +2 -1
  294. package/dist/type/validator/string-codec-aot.js +8 -2
  295. package/dist/type/validator/string-codec-aot.mjs +7 -2
  296. package/dist/type/validator/validator-cache.d.ts +5 -4
  297. package/dist/type/validator/validator-cache.js +41 -24
  298. package/dist/type/validator/validator-cache.mjs +40 -22
  299. package/dist/types.d.ts +263 -95
  300. package/dist/universal/constants.d.ts +2 -1
  301. package/dist/universal/constants.js +3 -1
  302. package/dist/universal/constants.mjs +2 -1
  303. package/dist/universal/env.js +2 -3
  304. package/dist/universal/env.mjs +2 -3
  305. package/dist/universal/file.d.ts +6 -4
  306. package/dist/universal/file.js +11 -16
  307. package/dist/universal/file.mjs +12 -16
  308. package/dist/universal/index.d.ts +2 -2
  309. package/dist/universal/is-production.d.ts +1 -2
  310. package/dist/universal/is-production.js +1 -3
  311. package/dist/universal/is-production.mjs +2 -3
  312. package/dist/universal/server.d.ts +0 -272
  313. package/dist/utils.d.ts +43 -7
  314. package/dist/utils.js +181 -126
  315. package/dist/utils.mjs +168 -126
  316. package/dist/validator/index.d.ts +1 -1
  317. package/dist/validator/index.js +17 -30
  318. package/dist/validator/index.mjs +18 -31
  319. package/dist/validator/route.js +2 -1
  320. package/dist/validator/route.mjs +2 -1
  321. package/dist/ws/context.d.ts +8 -1
  322. package/dist/ws/context.js +68 -44
  323. package/dist/ws/context.mjs +67 -44
  324. package/dist/ws/parser.js +10 -20
  325. package/dist/ws/parser.mjs +10 -20
  326. package/dist/ws/route.d.ts +2 -2
  327. package/dist/ws/route.js +249 -141
  328. package/dist/ws/route.mjs +254 -146
  329. package/dist/ws/types.d.ts +2 -2
  330. package/package.json +23 -49
  331. package/dist/compile/analysis-cache.d.ts +0 -6
  332. package/dist/compile/analysis-cache.js +0 -12
  333. package/dist/compile/analysis-cache.mjs +0 -11
  334. package/dist/cookie/index.d.ts +0 -7
  335. package/dist/cookie/index.js +0 -13
  336. package/dist/cookie/index.mjs +0 -7
  337. package/dist/handler/index.d.ts +0 -2
  338. package/dist/handler/index.js +0 -5
  339. package/dist/handler/index.mjs +0 -3
@@ -1,8 +1,8 @@
1
- import { flattenChain, isNotEmpty, nullObject, requestId } from "../utils.mjs";
1
+ import { authorityEnd, flattenChain, isNotEmpty, nullObject, requestId } from "../utils.mjs";
2
2
  import { isProduction } from "../universal/is-production.mjs";
3
3
  import { NotFound, PROBLEM_JSON, internalServerErrorResponse } from "../error.mjs";
4
4
  import { handleSet, materializeSetHeaders } from "../adapter/utils.mjs";
5
- import { NOT_FOUND_BODY, emptyResponse, getAsyncIndexes, getNotFound } from "./utils.mjs";
5
+ import { drainDisposables, emptyResponse, getNotFound, getNotFoundBody, hasAsync } from "./utils.mjs";
6
6
  import { createErrorHandler } from "./error.mjs";
7
7
  import { origin } from "../adapter/origin.mjs";
8
8
  import { defaultAdapter } from "../adapter/constants.mjs";
@@ -10,8 +10,8 @@ import { createContext } from "../context.mjs";
10
10
  import decodeComponent from "deuri";
11
11
 
12
12
  //#region src/handler/fetch.ts
13
- function extractPath(url, context, pathStart) {
14
- const s = url.indexOf("/", pathStart);
13
+ function extractPath(url, context) {
14
+ const s = url.indexOf("/", authorityEnd(url));
15
15
  const q = context.qi = url.indexOf("?", s);
16
16
  return context.path = q === -1 ? url.slice(s) : url.substring(s, q);
17
17
  }
@@ -20,7 +20,7 @@ function notFound(context) {
20
20
  if (set.cookie || isNotEmpty(set.headers)) {
21
21
  handleSet(set);
22
22
  if (!set.headers["content-type"]) materializeSetHeaders(set)["content-type"] = PROBLEM_JSON;
23
- return new Response(NOT_FOUND_BODY, {
23
+ return new Response(getNotFoundBody(), {
24
24
  status: 404,
25
25
  headers: set.headers
26
26
  });
@@ -34,12 +34,16 @@ function decodeParams(params) {
34
34
  }
35
35
  return params;
36
36
  }
37
- const notFoundBody = Object.freeze({ code: "NOT_FOUND" });
38
- function finalizeError(context, handleError, afterResponse, error) {
39
- if (error === notFoundBody) error = new NotFound();
37
+ const warnedPathMutation = /* @__PURE__ */ new WeakSet();
38
+ function warnPathMutation(app) {
39
+ if (warnedPathMutation.has(app)) return;
40
+ warnedPathMutation.add(app);
41
+ console.warn("[elysia] context.path is readonly; request-hook rerouting will stop working in a future release.");
42
+ }
43
+ function finalizeError(context, handleError, afterResponse, error, sign) {
40
44
  let resp;
41
45
  try {
42
- resp = handleError(context, error);
46
+ resp = handleError(context, error, sign);
43
47
  } catch (errorPipelineThrow) {
44
48
  if (!isProduction()) console.error(errorPipelineThrow);
45
49
  resp = internalServerErrorResponse(error);
@@ -64,23 +68,19 @@ function dispatchResult(result, context, handleError, afterResponse) {
64
68
  }
65
69
  function findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS, hasDynamicWS) {
66
70
  const path = context.path;
67
- if (hasWS && request.method === "GET") {
71
+ const method = request.method;
72
+ if (hasWS && method === "GET") {
68
73
  const handler = map["WS"]?.[path];
69
74
  const found = handler === void 0 && hasDynamicWS ? router?.find("WS", path) : void 0;
70
75
  if (handler !== void 0 || found) {
71
76
  const upgrade = request.headers.get("upgrade");
72
77
  if (upgrade && upgrade.toLowerCase() === "websocket") {
73
- if (handler) {
74
- const r = handler(context);
75
- return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
76
- }
78
+ if (handler) return dispatchResult(handler(context), context, handleError, afterResponse);
77
79
  context.params = path.indexOf("%") === -1 ? found.params : decodeParams(found.params);
78
- const r = found.store(context);
79
- return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
80
+ return dispatchResult(found.store(context), context, handleError, afterResponse);
80
81
  }
81
82
  }
82
83
  }
83
- const method = request.method;
84
84
  const methodMap = map[method];
85
85
  let handler = methodMap?.[path];
86
86
  if (!handler) if (!strictPath && path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
@@ -97,7 +97,7 @@ function findRoute(context, request, map, router, hasError, handleError, afterRe
97
97
  context.params = path.indexOf("%") === -1 ? found.params : decodeParams(found.params);
98
98
  return dispatchResult(found.store(context), context, handleError, afterResponse);
99
99
  }
100
- if (hasError) return finalizeError(context, handleError, afterResponse, notFoundBody);
100
+ if (hasError) return finalizeError(context, handleError, afterResponse, new NotFound());
101
101
  afterResponse?.(context, 404);
102
102
  return notFound(context);
103
103
  }
@@ -108,10 +108,10 @@ function createFetchHandler(app) {
108
108
  const hasWS = !!app["~hasWS"];
109
109
  const hasDynamicWS = hasWS && !!app["~hasDynamicWS"];
110
110
  const strictPath = !!app["~config"]?.strictPath;
111
- const pathStart = app["~config"]?.handler?.standardHostname === false ? 7 : 11;
112
111
  const hook = flattenChain(app["~hookChain"]);
113
112
  const hasError = !!hook?.error;
114
113
  const abortSignal = app["~config"]?.abortSignal !== false;
114
+ const watchPath = !isProduction();
115
115
  /**
116
116
  * Arm `context['~sig']` unless this request is provably the untouched
117
117
  * `Request` the Bun adapter received, in which case materializing
@@ -127,31 +127,38 @@ function createFetchHandler(app) {
127
127
  return (context["~sig"] = request.signal).aborted;
128
128
  };
129
129
  /**
130
- * Post-suspension check: arm if nobody has yet, then read. Only emitted on
131
- * lanes that actually awaited, so a deferred request that never suspends
132
- * never reaches it.
130
+ * Peek after each callback. The actual await branch arms deferred requests;
131
+ * immediate callbacks must not materialize a signal just for this check.
133
132
  */
134
- const armedAbort = (request, context) => abortSignal && (context["~sig"] ??= request.signal).aborted === true;
133
+ const armedAbort = (context) => abortSignal && context["~sig"]?.aborted === true;
135
134
  const baseMapResponse = (app["~config"]?.adapter ?? defaultAdapter).response.map;
135
+ function finalMap(response, set, request, sign) {
136
+ if (!sign) return baseMapResponse(response, set, request, true);
137
+ let pending;
138
+ try {
139
+ pending = sign(set);
140
+ } catch {}
141
+ return pending ? pending.then(() => baseMapResponse(response, set, request, true), () => baseMapResponse(response, set, request, true)) : baseMapResponse(response, set, request, true);
142
+ }
136
143
  const mapResponseHooks = hook?.mapResponse;
137
- const mapResponse = mapResponseHooks?.length ? (response, set, context) => {
144
+ const mapResponse = mapResponseHooks?.length ? (response, set, context, sign) => {
138
145
  if (!context) return baseMapResponse(response, set, void 0, true);
139
146
  context.responseValue = response;
140
147
  const request = context.request;
141
148
  const run = (i) => {
142
149
  for (; i < mapResponseHooks.length; i++) {
143
150
  const result = mapResponseHooks[i](context);
144
- if (result instanceof Promise) return result.then((resolved) => {
145
- if (resolved !== void 0) return baseMapResponse(resolved, set, request, true);
151
+ if (typeof result?.then === "function") return Promise.resolve(result).then((resolved) => {
152
+ if (resolved !== void 0) return finalMap(resolved, set, request, sign);
146
153
  return run(i + 1);
147
154
  });
148
- if (result !== void 0) return baseMapResponse(result, set, request, true);
155
+ if (result !== void 0) return finalMap(result, set, request, sign);
149
156
  }
150
- return baseMapResponse(response, set, request, true);
157
+ return finalMap(response, set, request, sign);
151
158
  };
152
159
  return run(0);
153
- } : (response, set, context) => baseMapResponse(response, set, context?.request, true);
154
- const handleError = createErrorHandler(hook?.error, mapResponse, void 0, app["~config"]?.allowUnsafeValidationDetails);
160
+ } : (response, set, context, sign) => finalMap(response, set, context?.request, sign);
161
+ const handleError = createErrorHandler(hook?.error, mapResponse, app["~config"]?.allowUnsafeValidationDetails);
155
162
  const traceHandlers = hook?.trace;
156
163
  const hasTrace = !!traceHandlers?.length;
157
164
  const traceProvider = hasTrace ? app["~resolvedCapability"]("trace") : void 0;
@@ -163,11 +170,32 @@ function createFetchHandler(app) {
163
170
  const afterResponse = (context, status) => {
164
171
  if (context._arf) return;
165
172
  const queue = context["~afterResponse"];
166
- if (!afterResponses?.length && !traceAfterResponsePhase && !queue?.length) return;
173
+ if (!afterResponses?.length && !traceAfterResponsePhase && !queue?.length && !context["~dispose"]) return;
167
174
  context._arf = true;
168
175
  if (status !== void 0) context.set.status = status;
169
176
  queueMicrotask(async () => {
170
177
  if (afterResponses?.length || queue?.length) materializeSetHeaders(context.set);
178
+ let cache;
179
+ let reports;
180
+ if (traceAfterResponsePhase) {
181
+ cache = context.trace;
182
+ if (!cache && tracerFactories) {
183
+ context.rid ??= requestId();
184
+ cache = tracerFactories.map((f) => f(context));
185
+ context.trace = cache;
186
+ }
187
+ if (cache) {
188
+ const total = afterResponses?.length ?? 0;
189
+ reports = new Array(cache.length);
190
+ for (let i = 0; i < cache.length; i++) reports[i] = cache[i].b(7, total) || cache[i].begin(7, {
191
+ id: context.rid ?? "",
192
+ event: "afterResponse",
193
+ name: "afterResponse",
194
+ begin: performance.now(),
195
+ total
196
+ });
197
+ }
198
+ }
171
199
  if (afterResponses) for (let i = 0; i < afterResponses.length; i++) try {
172
200
  await afterResponses[i](context);
173
201
  } catch (e) {
@@ -182,39 +210,19 @@ function createFetchHandler(app) {
182
210
  console.error(e);
183
211
  }
184
212
  }
185
- if (traceAfterResponsePhase) {
186
- let cache = context.trace;
187
- if (!cache && tracerFactories) {
188
- context.rid ??= requestId();
189
- cache = tracerFactories.map((f) => f(context));
190
- context.trace = cache;
191
- }
192
- if (cache) for (let i = 0; i < cache.length; i++) {
193
- const fast = cache[i].b(7, afterResponses?.length ?? 0);
194
- if (fast) {
195
- cache[i].r(fast);
196
- continue;
197
- }
198
- cache[i].begin(7, {
199
- id: context.rid ?? "",
200
- event: "afterResponse",
201
- name: "afterResponse",
202
- begin: performance.now(),
203
- total: afterResponses?.length ?? 0
204
- }).resolve();
205
- }
206
- }
213
+ await drainDisposables(context);
214
+ if (reports) for (let i = 0; i < reports.length; i++) cache[i].r(reports[i]);
207
215
  });
208
216
  };
209
- app["~finalizeError"] = (context, error) => finalizeError(context, handleError, afterResponse, error);
217
+ const fail = (context, error, sign) => finalizeError(context, handleError, afterResponse, error, sign);
218
+ app["~finalizeError"] = fail;
210
219
  if (traceRequestPhase) {
211
220
  const onRequests = hook?.request ?? [];
212
- const asyncIndexes = onRequests.length ? getAsyncIndexes(onRequests) : void 0;
213
221
  return async (request, server) => {
214
222
  const context = new Context(request);
215
223
  materializeSetHeaders(context.set);
216
224
  if (armEager(request, context)) return emptyResponse.clone();
217
- extractPath(request.url, context, pathStart);
225
+ const path = extractPath(request.url, context);
218
226
  context.server = server ?? null;
219
227
  context.rid = requestId();
220
228
  const traceLength = tracerFactories.length;
@@ -232,15 +240,20 @@ function createFetchHandler(app) {
232
240
  try {
233
241
  const endReports = new Array(traceLength);
234
242
  for (let i = 0; i < onRequests.length; i++) {
235
- for (let j = 0; j < traceLength; j++) endReports[j] = requestReports[j].resolveChild?.shift?.()?.({
243
+ for (let j = 0; j < traceLength; j++) endReports[j] = requestReports[j].shift?.()?.({
236
244
  id: context.rid,
237
245
  event: "request",
238
246
  name: onRequests[i].name || "anonymous",
239
247
  begin: performance.now()
240
248
  });
241
- const result = asyncIndexes?.[i] ? await onRequests[i](context) : onRequests[i](context);
249
+ let result = onRequests[i](context);
250
+ if (typeof result?.then === "function") {
251
+ if (abortSignal) context["~sig"] ??= request.signal;
252
+ result = await result;
253
+ }
254
+ if (watchPath && context.path !== path) warnPathMutation(app);
242
255
  for (let i = 0; i < traceLength; i++) endReports[i]?.();
243
- if (armedAbort(request, context)) {
256
+ if (armedAbort(context)) {
244
257
  for (let j = 0; j < traceLength; j++) trace[j].r(requestReports[j]);
245
258
  return emptyResponse.clone();
246
259
  }
@@ -255,24 +268,27 @@ function createFetchHandler(app) {
255
268
  return await findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS, hasDynamicWS);
256
269
  } catch (error) {
257
270
  for (let i = 0; i < traceLength; i++) trace[i].r(requestReports[i], error);
258
- return finalizeError(context, handleError, afterResponse, error);
271
+ return fail(context, error);
259
272
  }
260
273
  };
261
274
  }
262
275
  if (hook?.request) {
263
276
  const onRequests = hook.request;
264
- const asyncIndexes = getAsyncIndexes(onRequests);
265
- if (asyncIndexes) return async (request, server) => {
277
+ if (hasAsync(onRequests)) return async (request, server) => {
266
278
  const context = new Context(request);
267
279
  materializeSetHeaders(context.set);
268
280
  if (armEager(request, context)) return emptyResponse.clone();
269
- extractPath(request.url, context, pathStart);
281
+ const path = extractPath(request.url, context);
270
282
  context.server = server ?? null;
271
283
  try {
272
284
  for (let i = 0; i < onRequests.length; i++) {
273
- let result = asyncIndexes?.[i] ? await onRequests[i](context) : onRequests[i](context);
274
- if (result instanceof Promise) result = await result;
275
- if (armedAbort(request, context)) return emptyResponse.clone();
285
+ let result = onRequests[i](context);
286
+ if (typeof result?.then === "function") {
287
+ if (abortSignal) context["~sig"] ??= request.signal;
288
+ result = await result;
289
+ }
290
+ if (watchPath && context.path !== path) warnPathMutation(app);
291
+ if (armedAbort(context)) return emptyResponse.clone();
276
292
  if (result !== void 0) {
277
293
  const response = await mapResponse(result, context.set, context);
278
294
  afterResponse?.(context);
@@ -281,18 +297,19 @@ function createFetchHandler(app) {
281
297
  }
282
298
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS, hasDynamicWS);
283
299
  } catch (error) {
284
- return finalizeError(context, handleError, afterResponse, error);
300
+ return fail(context, error);
285
301
  }
286
302
  };
287
303
  return (request, server) => {
288
304
  const context = new Context(request);
289
305
  materializeSetHeaders(context.set);
290
306
  if (armEager(request, context)) return emptyResponse.clone();
291
- extractPath(request.url, context, pathStart);
307
+ const path = extractPath(request.url, context);
292
308
  context.server = server ?? null;
293
309
  try {
294
310
  for (let i = 0; i < onRequests.length; i++) {
295
311
  const result = onRequests[i](context);
312
+ if (watchPath && context.path !== path) warnPathMutation(app);
296
313
  if (abortSignal && context["~sig"]?.aborted) return emptyResponse.clone();
297
314
  if (result !== void 0) {
298
315
  const response = mapResponse(result, context.set, context);
@@ -306,57 +323,19 @@ function createFetchHandler(app) {
306
323
  }
307
324
  return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS, hasDynamicWS);
308
325
  } catch (error) {
309
- return finalizeError(context, handleError, afterResponse, error);
326
+ return fail(context, error);
310
327
  }
311
328
  };
312
329
  }
313
330
  return (request, server) => {
314
331
  const context = new Context(request);
315
- const path = extractPath(request.url, context, pathStart);
332
+ extractPath(request.url, context);
316
333
  context.server = server ?? null;
317
- const method = request.method;
318
- if (hasWS && method === "GET") {
319
- const handler = map["WS"]?.[path];
320
- const found = handler === void 0 && hasDynamicWS ? router?.find("WS", path) : void 0;
321
- if (handler !== void 0 || found) {
322
- const upgrade = request.headers.get("upgrade");
323
- if (upgrade && upgrade.toLowerCase() === "websocket") try {
324
- if (handler) {
325
- const r = handler(context);
326
- return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
327
- }
328
- context.params = path.indexOf("%") === -1 ? found.params : decodeParams(found.params);
329
- const r = found.store(context);
330
- return r instanceof Promise ? r.catch(catchError(context, handleError, afterResponse)) : r;
331
- } catch (error) {
332
- return finalizeError(context, handleError, afterResponse, error);
333
- }
334
- }
335
- }
336
334
  try {
337
- const methodMap = map[method];
338
- let handler = methodMap?.[path];
339
- if (handler) return dispatchResult(handler(context), context, handleError, afterResponse);
340
- if (!strictPath && path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
341
- const loose = path.slice(0, -1);
342
- handler = methodMap?.[loose];
343
- if (!handler) {
344
- const anyMap = map["*"];
345
- handler = anyMap?.[path] ?? anyMap?.[loose];
346
- }
347
- } else handler = map["*"]?.[path];
348
- if (handler) return dispatchResult(handler(context), context, handleError, afterResponse);
349
- const result = router?.find(method, path) ?? router?.find("*", path);
350
- if (result) {
351
- context.params = path.indexOf("%") === -1 ? result.params : decodeParams(result.params);
352
- return dispatchResult(result.store(context), context, handleError, afterResponse);
353
- }
335
+ return findRoute(context, request, map, router, hasError, handleError, afterResponse, strictPath, hasWS, hasDynamicWS);
354
336
  } catch (error) {
355
- return finalizeError(context, handleError, afterResponse, error);
337
+ return fail(context, error);
356
338
  }
357
- if (hasError) return finalizeError(context, handleError, afterResponse, notFoundBody);
358
- afterResponse?.(context, 404);
359
- return notFound(context);
360
339
  };
361
340
  }
362
341
  function applyHoc(app, fetch) {
@@ -1,15 +1,21 @@
1
- import { MaybePromise } from "../types.js";
2
1
  import { Context } from "../context.js";
2
+ import { MaybePromise } from "../types.js";
3
3
  import { AnyElysia } from "../base.js";
4
4
 
5
5
  //#region src/handler/utils.d.ts
6
6
  declare const emptyResponse: Response | {
7
7
  clone: () => Response;
8
8
  };
9
- declare const NOT_FOUND_BODY: string;
10
- declare const getNotFound: () => Response;
9
+ declare function getNotFoundBody(): string;
10
+ declare function getNotFound(): Response;
11
11
  declare function forwardError<T>(value: T): T;
12
- declare function finalizeRouteError(app: AnyElysia, context: Partial<Context>, error: unknown): MaybePromise<Response>;
13
- declare function getAsyncIndexes(onRequests: Function[]): (true | undefined)[] | undefined;
12
+ declare function returnedErrorClasses(hook: {
13
+ error?: unknown;
14
+ } | undefined, root: AnyElysia): Function[] | undefined;
15
+ declare const forwardErrorOf: (classes: Function[]) => <T>(value: T) => T;
16
+ declare function finalizeRouteError(app: AnyElysia, context: Partial<Context>, error: unknown, sign?: (set: Context['set']) => unknown): MaybePromise<Response>;
17
+ declare function registerDeriveDisposable(context: any, value: unknown, scan?: any): void;
18
+ declare function drainDisposables(context: any): Promise<void>;
19
+ declare const hasAsync: (fns: Function[]) => boolean;
14
20
  //#endregion
15
- export { NOT_FOUND_BODY, emptyResponse, finalizeRouteError, forwardError, getAsyncIndexes, getNotFound };
21
+ export { drainDisposables, emptyResponse, finalizeRouteError, forwardError, forwardErrorOf, getNotFound, getNotFoundBody, hasAsync, registerDeriveDisposable, returnedErrorClasses };
@@ -1,48 +1,104 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_universal_constants = require('../universal/constants.js');
3
+ const require_utils = require('../utils.js');
4
+ const require_universal_env = require('../universal/env.js');
3
5
  const require_error = require('../error.js');
4
6
  const require_compile_utils = require('../compile/utils.js');
5
7
 
6
8
  //#region src/handler/utils.ts
7
- const emptyResponse = require_universal_constants.isCloudflareWorker ? { clone: () => new Response(null) } : new Response(null);
8
- function cachedResponse(body, status, headers) {
9
- let cached;
10
- return () => require_universal_constants.isCloudflareWorker ? new Response(body, {
11
- status,
12
- headers
13
- }) : (cached ??= new Response(body, {
14
- status,
15
- headers
16
- })).clone();
17
- }
18
- const NOT_FOUND_BODY = JSON.stringify({
19
- type: "not-found",
20
- title: "Not Found",
21
- status: 404
22
- });
23
- const getNotFound = cachedResponse(NOT_FOUND_BODY, 404, { "content-type": require_error.PROBLEM_JSON });
9
+ const isPreallocateResponseUnsafe = require_universal_constants.isCloudflareWorker || require_universal_constants.isFastly || require_universal_env.env.ELYSIA_PREALLOCATE_RESPONSE === "false";
10
+ const emptyResponse = isPreallocateResponseUnsafe ? { clone: () => new Response(null) } : new Response(null);
11
+ let notFoundBase;
12
+ let notFoundBody;
13
+ let notFoundResponse;
14
+ function getNotFoundBody() {
15
+ const base = require_error.HTTPError.typeBase;
16
+ if (notFoundBody === void 0 || base !== notFoundBase) {
17
+ notFoundBase = base;
18
+ notFoundResponse = void 0;
19
+ notFoundBody = JSON.stringify({
20
+ type: require_error.problemTypeOf("not-found"),
21
+ code: "not-found",
22
+ status: 404,
23
+ title: "Not Found"
24
+ });
25
+ }
26
+ return notFoundBody;
27
+ }
28
+ const notFoundInit = {
29
+ status: 404,
30
+ headers: { "content-type": require_error.PROBLEM_JSON }
31
+ };
32
+ function getNotFound() {
33
+ const body = getNotFoundBody();
34
+ if (isPreallocateResponseUnsafe) return new Response(body, notFoundInit);
35
+ return (notFoundResponse ??= new Response(body, notFoundInit)).clone();
36
+ }
24
37
  function forwardError(value) {
25
38
  if (value instanceof Error) throw value;
26
39
  return value;
27
40
  }
28
- function finalizeRouteError(app, context, error) {
41
+ const chainErrorClasses = /* @__PURE__ */ new WeakMap();
42
+ function collectErrorClasses(error, into) {
43
+ if (!error) return into;
44
+ const list = Array.isArray(error) ? error : [error];
45
+ for (let i = 0; i < list.length; i++) {
46
+ const C = list[i]?.["~errorClass"];
47
+ if (C && !into?.includes(C)) (into ??= []).push(C);
48
+ }
49
+ return into;
50
+ }
51
+ function returnedErrorClasses(hook, root) {
52
+ const head = root["~hookChain"];
53
+ let rootClasses = head && chainErrorClasses.get(head);
54
+ if (head && rootClasses === void 0) chainErrorClasses.set(head, rootClasses = collectErrorClasses(require_utils.flattenChain(head)?.error, void 0) ?? null);
55
+ return collectErrorClasses(hook?.error, rootClasses?.slice());
56
+ }
57
+ const forwardErrorOf = (classes) => (value) => {
58
+ if (value instanceof Error) throw value;
59
+ for (let i = 0; i < classes.length; i++) if (value instanceof classes[i]) throw value;
60
+ return value;
61
+ };
62
+ function finalizeRouteError(app, context, error, sign) {
29
63
  const finalize = app["~finalizeError"];
30
64
  if (!finalize) throw error;
31
- return finalize(context, error);
65
+ return finalize(context, error, sign);
66
+ }
67
+ function registerDeriveDisposable(context, value, scan = context) {
68
+ if (!require_utils.isDisposable(value)) return;
69
+ if (require_utils.isSingleton(value)) return;
70
+ for (const key in scan) if (scan[key] === value) return;
71
+ const disposable = value;
72
+ const asyncDispose = disposable[Symbol.asyncDispose];
73
+ const dispose = typeof asyncDispose === "function" ? asyncDispose : disposable[Symbol.dispose];
74
+ (context["~dispose"] ??= []).push(() => dispose.call(value));
32
75
  }
33
- function getAsyncIndexes(onRequests) {
34
- let asyncIndexes;
35
- for (let i = 0; i < onRequests.length; i++) if (require_compile_utils.isAsyncFunction(onRequests[i]) || require_compile_utils.mayReturnPromise(onRequests[i])) {
36
- asyncIndexes ??= new Array(onRequests.length);
37
- asyncIndexes[i] = true;
76
+ async function drainDisposables(context) {
77
+ const stack = context["~dispose"];
78
+ if (!stack) return;
79
+ try {
80
+ if (!Array.isArray(stack)) throw new TypeError("Invalid disposable stack");
81
+ const errors = [];
82
+ while (stack.length) try {
83
+ await stack.pop()();
84
+ } catch (error) {
85
+ errors.push(error);
86
+ }
87
+ if (errors.length) throw errors.length === 1 ? errors[0] : new AggregateError(errors, "Multiple disposers failed");
88
+ } catch (error) {
89
+ console.error(error);
38
90
  }
39
- return asyncIndexes;
40
91
  }
92
+ const hasAsync = (fns) => fns.some((fn) => require_compile_utils.isAsyncFunction(fn) || require_compile_utils.mayReturnPromise(fn));
41
93
 
42
94
  //#endregion
43
- exports.NOT_FOUND_BODY = NOT_FOUND_BODY;
95
+ exports.drainDisposables = drainDisposables;
44
96
  exports.emptyResponse = emptyResponse;
45
97
  exports.finalizeRouteError = finalizeRouteError;
46
98
  exports.forwardError = forwardError;
47
- exports.getAsyncIndexes = getAsyncIndexes;
48
- exports.getNotFound = getNotFound;
99
+ exports.forwardErrorOf = forwardErrorOf;
100
+ exports.getNotFound = getNotFound;
101
+ exports.getNotFoundBody = getNotFoundBody;
102
+ exports.hasAsync = hasAsync;
103
+ exports.registerDeriveDisposable = registerDeriveDisposable;
104
+ exports.returnedErrorClasses = returnedErrorClasses;
@@ -1,42 +1,94 @@
1
- import { isCloudflareWorker } from "../universal/constants.mjs";
2
- import { PROBLEM_JSON } from "../error.mjs";
1
+ import { isCloudflareWorker, isFastly } from "../universal/constants.mjs";
2
+ import { flattenChain, isDisposable, isSingleton } from "../utils.mjs";
3
+ import { env } from "../universal/env.mjs";
4
+ import { HTTPError, PROBLEM_JSON, problemTypeOf } from "../error.mjs";
3
5
  import { isAsyncFunction, mayReturnPromise } from "../compile/utils.mjs";
4
6
 
5
7
  //#region src/handler/utils.ts
6
- const emptyResponse = isCloudflareWorker ? { clone: () => new Response(null) } : new Response(null);
7
- function cachedResponse(body, status, headers) {
8
- let cached;
9
- return () => isCloudflareWorker ? new Response(body, {
10
- status,
11
- headers
12
- }) : (cached ??= new Response(body, {
13
- status,
14
- headers
15
- })).clone();
16
- }
17
- const NOT_FOUND_BODY = JSON.stringify({
18
- type: "not-found",
19
- title: "Not Found",
20
- status: 404
21
- });
22
- const getNotFound = cachedResponse(NOT_FOUND_BODY, 404, { "content-type": PROBLEM_JSON });
8
+ const isPreallocateResponseUnsafe = isCloudflareWorker || isFastly || env.ELYSIA_PREALLOCATE_RESPONSE === "false";
9
+ const emptyResponse = isPreallocateResponseUnsafe ? { clone: () => new Response(null) } : new Response(null);
10
+ let notFoundBase;
11
+ let notFoundBody;
12
+ let notFoundResponse;
13
+ function getNotFoundBody() {
14
+ const base = HTTPError.typeBase;
15
+ if (notFoundBody === void 0 || base !== notFoundBase) {
16
+ notFoundBase = base;
17
+ notFoundResponse = void 0;
18
+ notFoundBody = JSON.stringify({
19
+ type: problemTypeOf("not-found"),
20
+ code: "not-found",
21
+ status: 404,
22
+ title: "Not Found"
23
+ });
24
+ }
25
+ return notFoundBody;
26
+ }
27
+ const notFoundInit = {
28
+ status: 404,
29
+ headers: { "content-type": PROBLEM_JSON }
30
+ };
31
+ function getNotFound() {
32
+ const body = getNotFoundBody();
33
+ if (isPreallocateResponseUnsafe) return new Response(body, notFoundInit);
34
+ return (notFoundResponse ??= new Response(body, notFoundInit)).clone();
35
+ }
23
36
  function forwardError(value) {
24
37
  if (value instanceof Error) throw value;
25
38
  return value;
26
39
  }
27
- function finalizeRouteError(app, context, error) {
40
+ const chainErrorClasses = /* @__PURE__ */ new WeakMap();
41
+ function collectErrorClasses(error, into) {
42
+ if (!error) return into;
43
+ const list = Array.isArray(error) ? error : [error];
44
+ for (let i = 0; i < list.length; i++) {
45
+ const C = list[i]?.["~errorClass"];
46
+ if (C && !into?.includes(C)) (into ??= []).push(C);
47
+ }
48
+ return into;
49
+ }
50
+ function returnedErrorClasses(hook, root) {
51
+ const head = root["~hookChain"];
52
+ let rootClasses = head && chainErrorClasses.get(head);
53
+ if (head && rootClasses === void 0) chainErrorClasses.set(head, rootClasses = collectErrorClasses(flattenChain(head)?.error, void 0) ?? null);
54
+ return collectErrorClasses(hook?.error, rootClasses?.slice());
55
+ }
56
+ const forwardErrorOf = (classes) => (value) => {
57
+ if (value instanceof Error) throw value;
58
+ for (let i = 0; i < classes.length; i++) if (value instanceof classes[i]) throw value;
59
+ return value;
60
+ };
61
+ function finalizeRouteError(app, context, error, sign) {
28
62
  const finalize = app["~finalizeError"];
29
63
  if (!finalize) throw error;
30
- return finalize(context, error);
64
+ return finalize(context, error, sign);
65
+ }
66
+ function registerDeriveDisposable(context, value, scan = context) {
67
+ if (!isDisposable(value)) return;
68
+ if (isSingleton(value)) return;
69
+ for (const key in scan) if (scan[key] === value) return;
70
+ const disposable = value;
71
+ const asyncDispose = disposable[Symbol.asyncDispose];
72
+ const dispose = typeof asyncDispose === "function" ? asyncDispose : disposable[Symbol.dispose];
73
+ (context["~dispose"] ??= []).push(() => dispose.call(value));
31
74
  }
32
- function getAsyncIndexes(onRequests) {
33
- let asyncIndexes;
34
- for (let i = 0; i < onRequests.length; i++) if (isAsyncFunction(onRequests[i]) || mayReturnPromise(onRequests[i])) {
35
- asyncIndexes ??= new Array(onRequests.length);
36
- asyncIndexes[i] = true;
75
+ async function drainDisposables(context) {
76
+ const stack = context["~dispose"];
77
+ if (!stack) return;
78
+ try {
79
+ if (!Array.isArray(stack)) throw new TypeError("Invalid disposable stack");
80
+ const errors = [];
81
+ while (stack.length) try {
82
+ await stack.pop()();
83
+ } catch (error) {
84
+ errors.push(error);
85
+ }
86
+ if (errors.length) throw errors.length === 1 ? errors[0] : new AggregateError(errors, "Multiple disposers failed");
87
+ } catch (error) {
88
+ console.error(error);
37
89
  }
38
- return asyncIndexes;
39
90
  }
91
+ const hasAsync = (fns) => fns.some((fn) => isAsyncFunction(fn) || mayReturnPromise(fn));
40
92
 
41
93
  //#endregion
42
- export { NOT_FOUND_BODY, emptyResponse, finalizeRouteError, forwardError, getAsyncIndexes, getNotFound };
94
+ export { drainDisposables, emptyResponse, finalizeRouteError, forwardError, forwardErrorOf, getNotFound, getNotFoundBody, hasAsync, registerDeriveDisposable, returnedErrorClasses };