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
package/dist/ws/route.mjs CHANGED
@@ -1,88 +1,27 @@
1
1
  import { isBun } from "../universal/constants.mjs";
2
- import { deriveEntryFn, isNotEmpty, nullObject } from "../utils.mjs";
2
+ import { assignOwn, deriveEntryFn, isSocketQuiet, nullObject } from "../utils.mjs";
3
3
  import { isBridgeLive } from "../type/bridge.mjs";
4
- import { isProduction } from "../universal/is-production.mjs";
5
- import { ElysiaError, ElysiaStatus, ValidationError, internalServerErrorBodyString, problemBody, problemResponse } from "../error.mjs";
4
+ import { ElysiaError, ElysiaStatus, ValidationError, elysiaErrorProblem, internalServerErrorBodyString, problemBody, problemResponse } from "../error.mjs";
5
+ import { hasSyncHmac } from "../cookie/crypto.mjs";
6
6
  import { mapResponse } from "../adapter/web-standard/handler.mjs";
7
7
  import { parseQueryFromURL } from "../parse-query.mjs";
8
+ import { Capture, Compiled, aotDrift, warnAotDrift } from "../compile/aot.mjs";
8
9
  import { frozenRootOf } from "../generation.mjs";
9
- import { createErrorHandler } from "../handler/error.mjs";
10
+ import { compileCookieConfig } from "../cookie/config.mjs";
11
+ import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, signCookieValues } from "../cookie/utils.mjs";
12
+ import { finalizeRouteError } from "../handler/utils.mjs";
13
+ import { adoptErrorType, claimsProblemType, createErrorHandler, readAnnotation, resolveStatus, statusFallbackBody } from "../handler/error.mjs";
10
14
  import { deriveModes, getQueryParseChannels, replaceDeriveContext } from "../compile/handler/utils.mjs";
15
+ import { sucrose } from "../sucrose.mjs";
11
16
  import { StandardValidator } from "../validator/index.mjs";
12
17
  import { RouteValidator } from "../validator/route.mjs";
13
18
  import { buildFrozenRouteValidator, isBridgeNotInitialized } from "../compile/handler/frozen-validator.mjs";
14
- import { composeRouteHook, localMacroRoot, resolveWSLocalHook } from "../compile/handler/index.mjs";
15
- import { ElysiaWS, isGeneratorObject } from "./context.mjs";
19
+ import { composeRouteHook, localMacroRoot, resolveWSLocalHook, routeShape } from "../compile/handler/index.mjs";
20
+ import { ElysiaWS, isGeneratorObject, trackWSSettling } from "./context.mjs";
16
21
  import { createMessageParser } from "./parser.mjs";
17
22
 
18
23
  //#region src/ws/route.ts
19
24
  const EMPTY_HOOKS = Object.freeze([]);
20
- /**
21
- * Build-time (route-registration-time) analysis of a WS `message` handler to
22
- * decide whether the per-frame `ws.body` view must be assigned.
23
- */
24
- function handlerMayTouchBody(fn) {
25
- if (!fn) return false;
26
- let source;
27
- try {
28
- source = Function.prototype.toString.call(fn);
29
- } catch {
30
- return true;
31
- }
32
- if (source.indexOf("[native code]") !== -1) return true;
33
- if (/\bbody\b/.test(source)) return true;
34
- if (/\barguments\b/.test(source)) return true;
35
- if (source.indexOf("[") !== -1) return true;
36
- if (source.indexOf("...") !== -1) return true;
37
- const parsed = firstParamIdentifier(source);
38
- if (parsed === void 0) return true;
39
- const { name: wsName, bodyStart, paramsEnd } = parsed;
40
- if (source.slice(0, paramsEnd).indexOf("(", 1) !== -1) return true;
41
- const body = source.slice(bodyStart);
42
- const safeName = wsName.replace(/[$]/g, "\\$&");
43
- if (new RegExp(`(?<![\\w$.])${safeName}(?![\\w$]|\\s*\\.)`).test(body)) return true;
44
- return false;
45
- }
46
- function firstParamIdentifier(source) {
47
- const open = source.indexOf("(");
48
- if (open === -1) {
49
- const m = /^\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/.exec(source);
50
- if (!m) return void 0;
51
- const end = m.index + m[0].length;
52
- return {
53
- name: m[1],
54
- bodyStart: end,
55
- paramsEnd: end
56
- };
57
- }
58
- let depth = 0;
59
- let close = -1;
60
- for (let i = open; i < source.length; i++) {
61
- const c = source[i];
62
- if (c === "(") depth++;
63
- else if (c === ")") {
64
- depth--;
65
- if (depth === 0) {
66
- close = i;
67
- break;
68
- }
69
- }
70
- }
71
- if (close === -1) return void 0;
72
- const params = source.slice(open + 1, close).trim();
73
- if (params.length === 0) return void 0;
74
- let first = params;
75
- const comma = params.indexOf(",");
76
- if (comma !== -1) first = params.slice(0, comma).trim();
77
- if (first[0] === "{" || first[0] === "[") return void 0;
78
- const m = /^([A-Za-z_$][\w$]*)/.exec(first);
79
- if (!m) return void 0;
80
- return {
81
- name: m[1],
82
- bodyStart: close + 1,
83
- paramsEnd: close + 1
84
- };
85
- }
86
25
  function concatHooks(...sources) {
87
26
  let result;
88
27
  for (let i = 0; i < sources.length; i++) {
@@ -103,7 +42,6 @@ async function applyMapResponse(ws, value, mapResponses) {
103
42
  }
104
43
  return value;
105
44
  }
106
- const isBackpressured = (status) => typeof status === "number" && status <= 0;
107
45
  const isEmptyPayload = (payload) => {
108
46
  if (payload === "" || payload == null) return true;
109
47
  if (typeof payload === "string") return false;
@@ -135,7 +73,7 @@ async function handleWSResponse(ws, value, mapResponses) {
135
73
  const mapped = mapResponses.length ? await applyMapResponse(ws, yielded, mapResponses) : yielded;
136
74
  let status = ws.send(mapped);
137
75
  const canBackpressure = !isEmptyPayload(mapped);
138
- while (canBackpressure && isBackpressured(status)) {
76
+ while (canBackpressure && typeof status === "number" && status <= 0) {
139
77
  if (ws.readyState >= 2) return;
140
78
  await waitForDrain(ws);
141
79
  if (ws.readyState >= 2) return;
@@ -154,6 +92,38 @@ async function handleWSResponse(ws, value, mapResponses) {
154
92
  const mapped = mapResponses.length ? await applyMapResponse(ws, value, mapResponses) : value;
155
93
  ws.send(mapped);
156
94
  }
95
+ function wsErrorFrameFallback(error) {
96
+ if (claimsProblemType(error)) try {
97
+ const status = resolveStatus(error.status);
98
+ const served = typeof status === "number" && status >= 100 ? status : 500;
99
+ const stringify = (value) => typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
100
+ const problemFrame = (detail) => JSON.stringify(problemBody({
101
+ type: error.type ?? "about:blank",
102
+ ...typeof error.code === "string" ? { code: error.code } : {},
103
+ detail,
104
+ status: served
105
+ }));
106
+ const serveMessage = () => problemFrame(statusFallbackBody(error, served));
107
+ const serveDetail = () => {
108
+ const detail = readAnnotation(error, "detail", true);
109
+ if (detail === void 0) return serveMessage();
110
+ if (detail instanceof Promise) return detail.then((resolved) => resolved === void 0 ? serveMessage() : problemFrame(resolved)).catch(() => wsLegacyFrame(error));
111
+ return problemFrame(detail);
112
+ };
113
+ const value = readAnnotation(error, "value", true);
114
+ if (value === void 0) return serveDetail();
115
+ if (value instanceof Promise) return value.then((resolved) => resolved === void 0 ? serveDetail() : stringify(resolved)).catch(() => wsLegacyFrame(error));
116
+ return stringify(value);
117
+ } catch {}
118
+ return wsLegacyFrame(error);
119
+ }
120
+ function wsLegacyFrame(error) {
121
+ if (error?.status) {
122
+ const body = statusFallbackBody(error, error.status);
123
+ return typeof body === "object" ? JSON.stringify(body) : String(body);
124
+ }
125
+ return internalServerErrorBodyString(error);
126
+ }
157
127
  function wsErrorFrame(error) {
158
128
  if (error instanceof ValidationError) try {
159
129
  return JSON.stringify(error.payload);
@@ -166,12 +136,7 @@ function wsErrorFrame(error) {
166
136
  } catch {}
167
137
  if (typeof error?.toResponse === "function") {
168
138
  if (error instanceof ElysiaError && error.toResponse === ElysiaError.prototype.toResponse) try {
169
- return JSON.stringify(problemBody({
170
- type: error.problemType,
171
- title: error.problemTitle,
172
- status: error.status ?? 500,
173
- detail: error.response !== void 0 && error.response !== error.problemTitle ? error.response : void 0
174
- }));
139
+ return JSON.stringify(problemBody(elysiaErrorProblem(error)));
175
140
  } catch {}
176
141
  try {
177
142
  const r = error.toResponse();
@@ -180,13 +145,6 @@ function wsErrorFrame(error) {
180
145
  }
181
146
  return wsErrorFrameFallback(error);
182
147
  }
183
- function wsErrorFrameFallback(error) {
184
- if (error?.status) {
185
- const body = error.response !== void 0 ? error.response : isProduction() ? error.status >= 500 ? "Internal Server Error" : "" : error.message ?? "";
186
- return typeof body === "object" ? JSON.stringify(body) : String(body);
187
- }
188
- return internalServerErrorBodyString(error);
189
- }
190
148
  function sendErrorFrame(ws, error) {
191
149
  const frame = wsErrorFrame(error);
192
150
  if (typeof frame === "string") {
@@ -202,9 +160,7 @@ function sendErrorFrame(ws, error) {
202
160
  }, () => {});
203
161
  }
204
162
  function validateUpgradeChannel(validator, value, type) {
205
- if (validator instanceof StandardValidator) return validator.From(value, type);
206
- if (validator.hasCodec) return validator.From(value, type);
207
- return validator.EncodeFrom(value, type);
163
+ return validator.hasCodec || validator instanceof StandardValidator ? validator.From(value, type) : validator.EncodeFrom(value, type);
208
164
  }
209
165
  const wsOptions = [
210
166
  "maxPayloadLength",
@@ -217,14 +173,35 @@ const wsOptions = [
217
173
  ];
218
174
  function buildWSRoute(route, app) {
219
175
  const hook = resolveWSLocalHook(localMacroRoot(route[7] ?? route[3] ?? app, app), route[4], app) ?? nullObject();
176
+ const instance = route[3] ?? app;
177
+ const appHookChain = route[5];
178
+ const inheritedChain = route[6];
179
+ const composed = composeRouteHook(instance, route[4], appHookChain, inheritedChain, app, route[7]) ?? hook;
220
180
  let validators;
221
- const frozenEager = isBridgeLive() ? void 0 : buildFrozenRouteValidator(hook, app, "WS", route[1]);
181
+ const programId = frozenRootOf(app)["~programId"];
182
+ const captured = Compiled.getHandler(programId, "WS", route[1]);
183
+ let live = false;
184
+ if (Capture.isCapturing()) Capture.handler({
185
+ method: "WS",
186
+ path: route[1],
187
+ alias: "",
188
+ code: "",
189
+ k: routeShape(composed, void 0, app)
190
+ });
191
+ else if (Compiled.hasProgram(programId)) {
192
+ const shape = routeShape(composed, void 0, app);
193
+ live = shape === void 0 || captured?.k !== shape;
194
+ }
195
+ const frozenEager = isBridgeLive() || live ? void 0 : buildFrozenRouteValidator(composed, app, "WS", route[1]);
222
196
  if (frozenEager) validators = frozenEager;
223
197
  else try {
224
- validators = new RouteValidator(hook, {
198
+ validators = new RouteValidator(composed, {
225
199
  models: frozenRootOf(app)["~ext"]?.models,
226
200
  app,
227
- aot: {
201
+ normalize: frozenRootOf(app)["~config"]?.normalize,
202
+ sanitize: frozenRootOf(app)["~config"]?.sanitize,
203
+ schemas: composed.schemas,
204
+ aot: live ? void 0 : {
228
205
  method: "WS",
229
206
  path: route[1]
230
207
  },
@@ -232,23 +209,23 @@ function buildWSRoute(route, app) {
232
209
  });
233
210
  } catch (error) {
234
211
  if (!isBridgeNotInitialized(error)) throw error;
235
- const frozen = buildFrozenRouteValidator(hook, app, "WS", route[1]);
212
+ if (live) throw new Error(aotDrift("WS", route[1]), { cause: error });
213
+ const frozen = buildFrozenRouteValidator(composed, app, "WS", route[1]);
236
214
  if (!frozen) throw error;
237
215
  validators = frozen;
238
216
  }
217
+ if (live && captured) warnAotDrift("WS", route[1]);
239
218
  const responseValidator = validators.response;
240
219
  const defaultResponseValidator = responseValidator ? responseValidator[200] ?? responseValidator[Object.keys(responseValidator)[0]] : void 0;
220
+ const cookieIsOptional = !!composed.cookie?.["~optional"];
241
221
  const queryChannels = getQueryParseChannels(validators.query?.schema);
242
222
  const queryArray = queryChannels?.array;
243
223
  const queryObject = queryChannels?.object;
244
- const instance = route[3] ?? app;
245
- const appHookChain = route[5];
246
- const inheritedChain = route[6];
247
- const flatAppHook = composeRouteHook(instance, void 0, appHookChain, inheritedChain, app, route[7]) ?? {};
248
- const parseHooks = hook.parse == null ? [] : Array.isArray(hook.parse) ? hook.parse : [hook.parse];
224
+ const flatAppHook = composeRouteHook(instance, void 0, appHookChain, inheritedChain, app, route[7], false) ?? {};
225
+ const parseHooks = concatHooks(hook.parse);
249
226
  const transforms = concatHooks(flatAppHook.transform, hook.transform);
250
227
  const allBeforeHandles = concatHooks(flatAppHook.beforeHandle, hook.beforeHandle);
251
- const deriveEntries = [...flatAppHook["~deriveEntries"] ?? [], ...hook["~deriveEntries"] ?? []];
228
+ const deriveEntries = concatHooks(flatAppHook["~deriveEntries"], hook["~deriveEntries"]);
252
229
  const deriveSet = deriveEntries.length ? new Set(deriveEntries.map(deriveEntryFn)) : void 0;
253
230
  const upgradeDeriveModes = deriveModes(allBeforeHandles, deriveEntries);
254
231
  const messageBeforeHandles = allBeforeHandles.filter((fn) => !deriveSet?.has(fn));
@@ -256,8 +233,31 @@ function buildWSRoute(route, app) {
256
233
  const mapResponses = concatHooks(flatAppHook.mapResponse, hook.mapResponse);
257
234
  const afterResponses = concatHooks(flatAppHook.afterResponse, hook.afterResponse);
258
235
  const errorHandlers = concatHooks(hook.error, flatAppHook.error);
236
+ const inference = sucrose(hook.message, {
237
+ beforeHandle: [
238
+ ...allBeforeHandles,
239
+ hook.open,
240
+ hook.close,
241
+ hook.drain,
242
+ hook.ping,
243
+ hook.pong,
244
+ typeof hook.upgrade === "function" ? hook.upgrade : void 0
245
+ ].filter(Boolean),
246
+ parse: parseHooks,
247
+ transform: transforms,
248
+ error: errorHandlers,
249
+ afterHandle: afterHandles,
250
+ mapResponse: mapResponses,
251
+ afterResponse: afterResponses
252
+ });
253
+ const cookieConfig = validators.cookie || inference.cookie ? compileCookieConfig(composed.cookie, frozenRootOf(app)["~config"]?.cookie, frozenRootOf(app)["~ext"]?.models, composed.schemas) : void 0;
254
+ const signCookies = cookieConfig?.hasSign ? (set) => signCookieValues(set.cookie, cookieConfig) : void 0;
259
255
  const parseMessage = createMessageParser(parseHooks);
260
- const handleUpgradeError = createErrorHandler(errorHandlers.length ? errorHandlers : void 0, ((response, set, context) => mapResponse(response, set, context?.request)), void 0, frozenRootOf(app)["~config"]?.allowUnsafeValidationDetails);
256
+ const handleUpgradeError = createErrorHandler(errorHandlers.length ? errorHandlers : void 0, ((response, set, context) => {
257
+ const map = () => mapResponse(response, set, context?.request);
258
+ const pending = signCookies?.(set);
259
+ return pending ? pending.then(map) : map();
260
+ }), frozenRootOf(app)["~config"]?.allowUnsafeValidationDetails);
261
261
  async function handleError(ws, error) {
262
262
  const errCtx = Object.create(ws);
263
263
  errCtx.error = error;
@@ -271,6 +271,7 @@ function buildWSRoute(route, app) {
271
271
  break;
272
272
  }
273
273
  if (r !== void 0) {
274
+ r = adoptErrorType(r, error);
274
275
  try {
275
276
  await handleWSResponse(ws, r, mapResponses);
276
277
  } catch {}
@@ -280,12 +281,6 @@ function buildWSRoute(route, app) {
280
281
  sendErrorFrame(ws, error);
281
282
  }
282
283
  const bodyValidator = validators.body;
283
- function validateMessageBody(message) {
284
- if (!bodyValidator) return message;
285
- if (bodyValidator.hasCodec) return bodyValidator.From(message, "body");
286
- if (bodyValidator instanceof StandardValidator) return bodyValidator.From(message, "body");
287
- return bodyValidator.EncodeFrom(message, "body");
288
- }
289
284
  function onMessageValidationError(ws, error) {
290
285
  if (errorHandlers.length === 0) {
291
286
  if (frozenRootOf(app)["~config"]?.allowUnsafeValidationDetails && error instanceof ValidationError) error.allowUnsafeValidationDetails = true;
@@ -293,7 +288,6 @@ function buildWSRoute(route, app) {
293
288
  }
294
289
  return handleError(ws, error);
295
290
  }
296
- const messageHandlerTouchesBody = !!bodyValidator || handlerMayTouchBody(hook.message) || errorHandlers.some(handlerMayTouchBody);
297
291
  const syncDispatchEligible = transforms.length === 0 && messageBeforeHandles.length === 0 && afterHandles.length === 0 && afterResponses.length === 0 && mapResponses.length === 0;
298
292
  function finishMessageResult(ws, value) {
299
293
  if (value === void 0) return;
@@ -308,7 +302,7 @@ function buildWSRoute(route, app) {
308
302
  if (bodyValidator) {
309
303
  let decoded;
310
304
  try {
311
- decoded = validateMessageBody(message);
305
+ decoded = validateUpgradeChannel(bodyValidator, message, "body");
312
306
  } catch (error) {
313
307
  return onMessageValidationError(ws, error);
314
308
  }
@@ -319,7 +313,7 @@ function buildWSRoute(route, app) {
319
313
  }
320
314
  function runMessageSync(ws, message) {
321
315
  try {
322
- if (messageHandlerTouchesBody) ws.body = message;
316
+ ws.body = message;
323
317
  const result = hook.message(ws, message);
324
318
  if (result instanceof Promise) return result.then((resolved) => finishMessageResult(ws, resolved), (error) => handleError(ws, error));
325
319
  return finishMessageResult(ws, result);
@@ -405,19 +399,37 @@ function buildWSRoute(route, app) {
405
399
  if (r instanceof Promise) r = await r;
406
400
  context.params = r;
407
401
  }
408
- if (validators.query) {
402
+ if (validators.query || inference.query) {
409
403
  const url = request.url;
410
- const query = parseQueryFromURL(url, context.qi ?? url.indexOf("?"), queryArray, queryObject);
411
- let r = validateUpgradeChannel(validators.query, query, "query");
412
- if (r instanceof Promise) r = await r;
404
+ let r = parseQueryFromURL(url, context.qi ?? url.indexOf("?"), queryArray, queryObject);
405
+ if (validators.query) {
406
+ r = validateUpgradeChannel(validators.query, r, "query");
407
+ if (r instanceof Promise) r = await r;
408
+ }
413
409
  context.query = r;
414
410
  }
415
- if (validators.headers) {
416
- const headers = isBun ? request.headers.toJSON() : Object.fromEntries(request.headers);
417
- let r = validateUpgradeChannel(validators.headers, headers, "headers");
418
- if (r instanceof Promise) r = await r;
411
+ if (validators.headers || inference.headers) {
412
+ let r = isBun ? request.headers.toJSON() : Object.fromEntries(request.headers);
413
+ if (validators.headers) {
414
+ r = validateUpgradeChannel(validators.headers, r, "headers");
415
+ if (r instanceof Promise) r = await r;
416
+ }
419
417
  context.headers = r;
420
418
  }
419
+ if (cookieConfig) {
420
+ const cookieHeader = request.headers.get("cookie");
421
+ if (validators.cookie) {
422
+ const raw = await parseCookieRaw(cookieHeader, cookieConfig);
423
+ let r = raw;
424
+ if (!cookieIsOptional || Object.keys(raw).length) {
425
+ r = validateUpgradeChannel(validators.cookie, raw, "cookie");
426
+ if (r instanceof Promise) r = await r;
427
+ }
428
+ context.cookie = buildCookieJar(context.set, r, cookieConfig);
429
+ } else if (!cookieConfig.hasSign) context.cookie = buildCookieJar(context.set, parseCookieRawDeferred(cookieHeader, cookieConfig), cookieConfig, void 0, 1);
430
+ else if (hasSyncHmac && cookieConfig.verify === "lazy") context.cookie = buildCookieJar(context.set, parseCookieRawLazy(cookieHeader, cookieConfig), cookieConfig, 1);
431
+ else context.cookie = buildCookieJar(context.set, await parseCookieRaw(cookieHeader, cookieConfig, cookieConfig.verify === "lazy" ? 1 : void 0), cookieConfig);
432
+ }
421
433
  for (let i = 0; i < transforms.length; i++) {
422
434
  const r = transforms[i](context);
423
435
  if (r instanceof Promise) await r;
@@ -429,9 +441,10 @@ function buildWSRoute(route, app) {
429
441
  const deriveMode = upgradeDeriveModes?.[i];
430
442
  if (deriveMode !== void 0 && !(r instanceof ElysiaStatus)) {
431
443
  if (r && typeof r === "object") if (deriveMode) context = replaceDeriveContext(context, r);
432
- else Object.assign(context, r);
444
+ else assignOwn(context, r);
433
445
  } else if (r !== void 0) {
434
446
  if (r instanceof Response) return r;
447
+ if (signCookies) await signCookies(context.set);
435
448
  return mapResponse(r, context.set, context.request);
436
449
  }
437
450
  }
@@ -464,7 +477,11 @@ function buildWSRoute(route, app) {
464
477
  }
465
478
  })) return new Response("Expected a websocket connection", { status: 400 });
466
479
  } catch (error) {
467
- return handleUpgradeError(context, error);
480
+ try {
481
+ return await handleUpgradeError(context, error);
482
+ } catch (thrown) {
483
+ return finalizeRouteError(app, context, thrown, signCookies);
484
+ }
468
485
  }
469
486
  };
470
487
  const options = nullObject();
@@ -474,33 +491,46 @@ function buildWSRoute(route, app) {
474
491
  function resolveWSOptions(entries) {
475
492
  if (!entries || entries.length === 0) return void 0;
476
493
  if (entries.length === 1) return { ...entries[0].value };
477
- const ordered = entries.map((entry, index) => ({
478
- entry,
479
- index
480
- })).sort((a, b) => b.entry.depth - a.entry.depth || a.index - b.index);
494
+ const ordered = entries.toSorted((a, b) => b.depth - a.depth);
481
495
  const result = {};
482
496
  let warned;
483
- for (const { entry } of ordered) for (const key in entry.value) {
497
+ for (const entry of ordered) for (const key in entry.value) {
484
498
  const incoming = entry.value[key];
485
499
  if (key in result && result[key] !== incoming && !warned?.has(key)) {
486
500
  (warned ??= /* @__PURE__ */ new Set()).add(key);
487
- console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket()) registrations; the shallowest (nearest-root) registration wins.`);
501
+ console.warn(`[Elysia] Conflicting WebSocket option '${key}' across .use(websocket()). Using nearest-root registration.`);
488
502
  }
489
503
  result[key] = incoming;
490
504
  }
491
505
  return result;
492
506
  }
493
- function accumulateWSOptions(target, routeOptions, _path) {
494
- if (!isNotEmpty(routeOptions)) return;
495
- if (isBun) {
496
- for (const key in routeOptions) if (key in target && target[key] !== routeOptions[key]) {
497
- console.warn(`[Elysia] Conflicting per-route WebSocket option '${key}'\nBun uses one global WebSocket config per server, per-route values are not enforced (the last-registered route wins).`);
498
- console.warn((/* @__PURE__ */ new Error()).stack);
507
+ const wsLimits = [
508
+ "maxPayloadLength",
509
+ "backpressureLimit",
510
+ "idleTimeout"
511
+ ];
512
+ const routeOwnedKeys = /* @__PURE__ */ new WeakMap();
513
+ function accumulateWSOptions(target, routeOptions) {
514
+ let owned = routeOwnedKeys.get(target);
515
+ if (!owned) routeOwnedKeys.set(target, owned = /* @__PURE__ */ new Set());
516
+ for (const key in routeOptions) {
517
+ const incoming = routeOptions[key];
518
+ const current = target[key];
519
+ if (key in target && current !== incoming) {
520
+ if (isBun) {
521
+ console.warn(`[Elysia] Conflicting per-route WebSocket option '${key}'\nBun uses one global WebSocket config per server, per-route values are not enforced (for limits the strictest route wins, otherwise the last-registered route).`);
522
+ console.warn((/* @__PURE__ */ new Error()).stack);
523
+ }
524
+ if (owned.has(key) && typeof current === "number" && typeof incoming === "number" && current < incoming && wsLimits.includes(key)) continue;
499
525
  }
526
+ owned.add(key);
527
+ target[key] = incoming;
500
528
  }
501
- Object.assign(target, routeOptions);
502
529
  }
530
+ const MAX_INFLIGHT_MESSAGES = 256;
503
531
  function buildGlobalWSHandler() {
532
+ let lifecycle;
533
+ const runLifecycle = (callback, ...args) => lifecycle ? lifecycle.run(callback, ...args) : callback(...args);
504
534
  function getElysia(ws) {
505
535
  let elysia = ws.data.elysia;
506
536
  if (!elysia) {
@@ -515,39 +545,117 @@ function buildGlobalWSHandler() {
515
545
  ws.send(typeof error?.message === "string" ? error.message : "Internal Server Error");
516
546
  } catch {}
517
547
  };
518
- return {
548
+ const releaseLifecycle = (ws) => {
549
+ if (!lifecycle?.closing && isSocketQuiet(ws)) {
550
+ delete ws.data["~lifecycleRun"];
551
+ lifecycle?.sockets.delete(ws);
552
+ }
553
+ };
554
+ const release = (ws) => {
555
+ const data = ws.data;
556
+ const inflight = data.inflight;
557
+ if (inflight) {
558
+ data.inflight = inflight - 1;
559
+ if (inflight === 1 && data.closeHandlerInvoked) releaseLifecycle(ws);
560
+ }
561
+ };
562
+ function dispatch(ws, message) {
563
+ let result;
564
+ try {
565
+ result = ws.data.message(getElysia(ws), message);
566
+ } catch (error) {
567
+ release(ws);
568
+ sendErrMsg(ws, error);
569
+ return;
570
+ }
571
+ if (result instanceof Promise) result.then(() => release(ws), (error) => {
572
+ release(ws);
573
+ sendErrMsg(ws, error);
574
+ });
575
+ else release(ws);
576
+ }
577
+ const handler = {
519
578
  message(ws, message) {
520
- let result;
521
- try {
522
- result = ws.data.message?.(getElysia(ws), message);
523
- } catch (error) {
524
- sendErrMsg(ws, error);
579
+ if (lifecycle?.closing) return;
580
+ const data = ws.data;
581
+ if (!data.message) return;
582
+ const inflight = (data.inflight ?? 0) + 1;
583
+ if (inflight > MAX_INFLIGHT_MESSAGES) {
584
+ try {
585
+ ws.close(1013, "Too many in-flight messages");
586
+ } catch {}
525
587
  return;
526
588
  }
527
- if (result instanceof Promise) result.catch((error) => sendErrMsg(ws, error));
589
+ data.inflight = inflight;
590
+ const opening = data.opening;
591
+ if (opening) return void opening.then(() => {
592
+ if (lifecycle?.closing || ws.readyState > 1) return release(ws);
593
+ dispatch(ws, message);
594
+ });
595
+ dispatch(ws, message);
528
596
  },
529
597
  open(ws) {
530
- ws.data.open?.(getElysia(ws));
598
+ if (lifecycle) Object.defineProperty(ws.data, "~lifecycleRun", {
599
+ configurable: true,
600
+ value: lifecycle.run
601
+ });
602
+ lifecycle?.sockets.add(ws);
603
+ if (lifecycle?.closing) {
604
+ ws.data.closeHandlerInvoked = true;
605
+ try {
606
+ ws.terminate();
607
+ } catch {}
608
+ return;
609
+ }
610
+ const open = ws.data.open;
611
+ const result = open && runLifecycle(open, getElysia(ws));
612
+ if (result instanceof Promise) {
613
+ const clear = () => {
614
+ ws.data.opening = void 0;
615
+ releaseLifecycle(ws);
616
+ };
617
+ ws.data.opening = result.then(clear, clear);
618
+ }
531
619
  },
532
620
  drain(ws) {
621
+ if (lifecycle?.closing) return;
533
622
  const elyWs = getElysia(ws);
534
623
  drainWaiters(elyWs);
535
- ws.data.drain?.(elyWs);
624
+ const drain = ws.data.drain;
625
+ trackWSSettling(ws.data, drain && runLifecycle(drain, elyWs), () => releaseLifecycle(ws));
536
626
  },
537
627
  close(ws, code, reason) {
538
628
  const elyWs = getElysia(ws);
539
629
  drainWaiters(elyWs);
540
- if (ws.data.closeHandlerInvoked) return;
630
+ if (ws.data.closeHandlerInvoked) return releaseLifecycle(ws);
541
631
  ws.data.closeHandlerInvoked = true;
542
- ws.data.close?.(elyWs, code, reason);
632
+ let result;
633
+ try {
634
+ const close = ws.data.close;
635
+ result = close && runLifecycle(close, elyWs, code, reason);
636
+ } finally {
637
+ if (!(result instanceof Promise)) releaseLifecycle(ws);
638
+ }
639
+ if (result instanceof Promise) {
640
+ const closing = result.catch(() => {});
641
+ trackWSSettling(ws.data, closing, () => releaseLifecycle(ws));
642
+ }
543
643
  },
544
644
  ping(ws, data) {
545
- ws.data.ping?.(getElysia(ws), data);
645
+ if (lifecycle?.closing) return;
646
+ const ping = ws.data.ping;
647
+ trackWSSettling(ws.data, ping && runLifecycle(ping, getElysia(ws), data), () => releaseLifecycle(ws));
546
648
  },
547
649
  pong(ws, data) {
548
- ws.data.pong?.(getElysia(ws), data);
650
+ if (lifecycle?.closing) return;
651
+ const pong = ws.data.pong;
652
+ trackWSSettling(ws.data, pong && runLifecycle(pong, getElysia(ws), data), () => releaseLifecycle(ws));
549
653
  }
550
654
  };
655
+ Object.defineProperty(handler, "~lifecycle", { set(value) {
656
+ lifecycle = value;
657
+ } });
658
+ return handler;
551
659
  }
552
660
 
553
661
  //#endregion
@@ -1,5 +1,5 @@
1
- import { AfterResponseHandler, BaseMacro, DocumentDecoration, ErrorHandler, InlineHandlerResponse, InternalRoute, MapResponse, MaybeArray, MaybePromise, OptionalHandler, Prettify, RouteSchema, SingletonBase, TransformHandler } from "../types.js";
2
1
  import { Context } from "../context.js";
2
+ import { AfterResponseHandler, BaseMacro, DocumentDecoration, ErrorHandler, InlineHandlerResponse, InternalRoute, MapResponse, MaybeArray, MaybePromise, OptionalHandler, Prettify, RouteSchema, SingletonBase, TransformHandler } from "../types.js";
3
3
  import { AnyElysia } from "../base.js";
4
4
 
5
5
  //#region src/ws/types.d.ts
@@ -151,7 +151,7 @@ interface WSCapability {
151
151
  * Fold a single route's server-tuning options into the build-local config,
152
152
  * warning on conflicting keys (Bun uses one global config per server).
153
153
  */
154
- accumulateOptions(target: WSOptions, routeOptions: WSOptions, path: string): void;
154
+ accumulateOptions(target: WSOptions, routeOptions: WSOptions): void;
155
155
  }
156
156
  //#endregion
157
157
  export { AnyWSLocalHook, BufferSource, ElysiaWSLike, FlattenResponse, ServerWebSocket, ServerWebSocketSendStatus, WSCapability, WSHandlerResponse, WSHandlerResult, WSLocalHook, WSMessageHandler, WSOptions, WSOptionsEntry, WSParseHandler, WSResponseValidator, WSValidatorLike, WebSocketCompressor, WebSocketHandler, WebSocketReadyState };