elysia 2.0.0-rc.1 → 2.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/dist/adapter/bun/index.js +8 -1
  2. package/dist/adapter/bun/index.mjs +8 -1
  3. package/dist/adapter/utils.d.ts +8 -12
  4. package/dist/adapter/utils.js +148 -127
  5. package/dist/adapter/utils.mjs +149 -128
  6. package/dist/adapter/web-standard/handler.js +26 -10
  7. package/dist/adapter/web-standard/handler.mjs +27 -11
  8. package/dist/adapter/web-standard/utils.js +3 -3
  9. package/dist/adapter/web-standard/utils.mjs +4 -4
  10. package/dist/base.d.ts +9 -8
  11. package/dist/base.js +164 -210
  12. package/dist/base.mjs +164 -210
  13. package/dist/compile/aot-capture.js +29 -16
  14. package/dist/compile/aot-capture.mjs +29 -16
  15. package/dist/compile/aot-emit.js +6 -0
  16. package/dist/compile/aot-emit.mjs +6 -0
  17. package/dist/compile/aot-reconstruct.d.ts +4 -3
  18. package/dist/compile/aot-reconstruct.js +20 -9
  19. package/dist/compile/aot-reconstruct.mjs +20 -9
  20. package/dist/compile/aot.d.ts +50 -17
  21. package/dist/compile/aot.js +31 -25
  22. package/dist/compile/aot.mjs +29 -27
  23. package/dist/compile/handler/descriptor.d.ts +2 -0
  24. package/dist/compile/handler/descriptor.js +9 -3
  25. package/dist/compile/handler/descriptor.mjs +9 -3
  26. package/dist/compile/handler/frozen-validator.d.ts +4 -3
  27. package/dist/compile/handler/frozen-validator.js +17 -24
  28. package/dist/compile/handler/frozen-validator.mjs +20 -26
  29. package/dist/compile/handler/index.d.ts +7 -6
  30. package/dist/compile/handler/index.js +57 -10
  31. package/dist/compile/handler/index.mjs +58 -11
  32. package/dist/compile/handler/jit.d.ts +4 -2
  33. package/dist/compile/handler/jit.js +26 -16
  34. package/dist/compile/handler/jit.mjs +26 -17
  35. package/dist/compile/handler/param-resolvers.d.ts +3 -2
  36. package/dist/compile/handler/param-resolvers.js +2 -0
  37. package/dist/compile/handler/param-resolvers.mjs +3 -2
  38. package/dist/compile/handler/param-table.js +1 -0
  39. package/dist/compile/handler/param-table.mjs +2 -1
  40. package/dist/compile/handler/params.d.ts +1 -5
  41. package/dist/compile/handler/params.js +2 -3
  42. package/dist/compile/handler/params.mjs +2 -2
  43. package/dist/compile/handler/reconstruct.js +4 -4
  44. package/dist/compile/handler/reconstruct.mjs +3 -3
  45. package/dist/compile/handler/route-shape.d.ts +9 -1
  46. package/dist/compile/handler/route-shape.js +14 -2
  47. package/dist/compile/handler/route-shape.mjs +13 -4
  48. package/dist/compile/handler/utils.d.ts +4 -2
  49. package/dist/compile/handler/utils.js +19 -3
  50. package/dist/compile/handler/utils.mjs +19 -4
  51. package/dist/compile/utils.d.ts +3 -1
  52. package/dist/compile/utils.js +2 -0
  53. package/dist/compile/utils.mjs +2 -1
  54. package/dist/constants.d.ts +2 -1
  55. package/dist/constants.js +2 -0
  56. package/dist/constants.mjs +2 -1
  57. package/dist/context.js +32 -9
  58. package/dist/context.mjs +33 -10
  59. package/dist/cookie/cookie.js +15 -12
  60. package/dist/cookie/cookie.mjs +16 -13
  61. package/dist/cookie/crypto.js +1 -1
  62. package/dist/cookie/crypto.mjs +1 -1
  63. package/dist/cookie/lib.js +1 -1
  64. package/dist/cookie/lib.mjs +2 -2
  65. package/dist/cookie/utils.js +56 -21
  66. package/dist/cookie/utils.mjs +57 -22
  67. package/dist/error.d.ts +12 -3
  68. package/dist/error.js +25 -17
  69. package/dist/error.mjs +22 -14
  70. package/dist/handler/error.d.ts +2 -1
  71. package/dist/handler/error.js +22 -18
  72. package/dist/handler/error.mjs +23 -20
  73. package/dist/handler/fetch.js +94 -146
  74. package/dist/handler/fetch.mjs +96 -148
  75. package/dist/handler/utils.js +2 -1
  76. package/dist/handler/utils.mjs +2 -1
  77. package/dist/index.d.ts +2 -2
  78. package/dist/package.js +1 -1
  79. package/dist/package.mjs +1 -1
  80. package/dist/parse-query.js +3 -2
  81. package/dist/parse-query.mjs +3 -2
  82. package/dist/plugin/aot/core.d.ts +41 -17
  83. package/dist/plugin/aot/core.js +47 -27
  84. package/dist/plugin/aot/core.mjs +43 -26
  85. package/dist/plugin/aot/hooks.d.ts +6 -1
  86. package/dist/plugin/aot/hooks.js +14 -13
  87. package/dist/plugin/aot/hooks.mjs +15 -14
  88. package/dist/plugin/aot/source.js +19 -22
  89. package/dist/plugin/aot/source.mjs +19 -22
  90. package/dist/plugin/auto-head.js +1 -1
  91. package/dist/plugin/auto-head.mjs +1 -1
  92. package/dist/plugin/trace.d.ts +1 -0
  93. package/dist/plugin/trace.js +3 -1
  94. package/dist/plugin/trace.mjs +4 -2
  95. package/dist/plugin/websocket.d.ts +1 -0
  96. package/dist/plugin/websocket.js +2 -1
  97. package/dist/plugin/websocket.mjs +3 -2
  98. package/dist/route-table.d.ts +0 -1
  99. package/dist/route-table.js +1 -2
  100. package/dist/route-table.mjs +1 -2
  101. package/dist/schema-snapshot.d.ts +9 -3
  102. package/dist/schema-snapshot.js +81 -22
  103. package/dist/schema-snapshot.mjs +82 -24
  104. package/dist/sucrose.d.ts +3 -2
  105. package/dist/sucrose.js +24 -5
  106. package/dist/sucrose.mjs +24 -5
  107. package/dist/trace.d.ts +31 -2
  108. package/dist/trace.js +84 -0
  109. package/dist/trace.mjs +83 -1
  110. package/dist/type/bridge.d.ts +4 -4
  111. package/dist/type/coerce-plan.js +1 -1
  112. package/dist/type/coerce-plan.mjs +2 -2
  113. package/dist/type/elysia/json-string.js +2 -2
  114. package/dist/type/elysia/json-string.mjs +3 -3
  115. package/dist/type/shared.d.ts +3 -1
  116. package/dist/type/shared.js +3 -1
  117. package/dist/type/shared.mjs +3 -2
  118. package/dist/type/typebox-type-live.d.ts +2 -1
  119. package/dist/type/typebox-type-live.js +12 -1
  120. package/dist/type/typebox-type-live.mjs +11 -1
  121. package/dist/type/typebox-type.d.ts +2 -1
  122. package/dist/type/typebox-type.js +12 -1
  123. package/dist/type/typebox-type.mjs +11 -1
  124. package/dist/type/typebox-value-require.js +9 -8
  125. package/dist/type/typebox-value-require.mjs +9 -8
  126. package/dist/type/validator/custom-error.d.ts +18 -3
  127. package/dist/type/validator/custom-error.js +3 -19
  128. package/dist/type/validator/custom-error.mjs +4 -20
  129. package/dist/type/validator/default-precompute.js +56 -38
  130. package/dist/type/validator/default-precompute.mjs +57 -39
  131. package/dist/type/validator/frozen-check.d.ts +3 -2
  132. package/dist/type/validator/frozen-check.js +20 -1
  133. package/dist/type/validator/frozen-check.mjs +19 -1
  134. package/dist/type/validator/index.d.ts +2 -0
  135. package/dist/type/validator/index.js +26 -17
  136. package/dist/type/validator/index.mjs +29 -20
  137. package/dist/type/validator/string-codec-aot.d.ts +1 -2
  138. package/dist/type/validator/string-codec-aot.js +4 -6
  139. package/dist/type/validator/string-codec-aot.mjs +4 -6
  140. package/dist/type/validator/validator-cache.js +13 -33
  141. package/dist/type/validator/validator-cache.mjs +13 -33
  142. package/dist/types.d.ts +12 -13
  143. package/dist/universal/file.d.ts +1 -0
  144. package/dist/universal/file.js +5 -0
  145. package/dist/universal/file.mjs +5 -0
  146. package/dist/utils.d.ts +10 -9
  147. package/dist/utils.js +84 -71
  148. package/dist/utils.mjs +79 -70
  149. package/dist/validator/index.js +3 -3
  150. package/dist/validator/index.mjs +2 -2
  151. package/dist/ws/context.d.ts +6 -2
  152. package/dist/ws/context.js +55 -26
  153. package/dist/ws/context.mjs +56 -28
  154. package/dist/ws/route.d.ts +4 -3
  155. package/dist/ws/route.js +127 -112
  156. package/dist/ws/route.mjs +134 -120
  157. package/dist/ws/types.d.ts +9 -3
  158. package/package.json +50 -8
  159. package/src/adapter/bun/index.ts +927 -0
  160. package/src/adapter/constants.ts +5 -0
  161. package/src/adapter/default-headers.ts +1 -0
  162. package/src/adapter/index.ts +11 -0
  163. package/src/adapter/origin.ts +60 -0
  164. package/src/adapter/response-ownership.ts +10 -0
  165. package/src/adapter/skip-clone.ts +2 -0
  166. package/src/adapter/types.ts +50 -0
  167. package/src/adapter/utils.ts +1087 -0
  168. package/src/adapter/web-standard/handler.ts +478 -0
  169. package/src/adapter/web-standard/index.ts +13 -0
  170. package/src/adapter/web-standard/parse.ts +50 -0
  171. package/src/adapter/web-standard/utils.ts +188 -0
  172. package/src/base.ts +8804 -0
  173. package/src/compile/aot-capture.ts +553 -0
  174. package/src/compile/aot-emit.ts +195 -0
  175. package/src/compile/aot-reconstruct.ts +292 -0
  176. package/src/compile/aot.ts +678 -0
  177. package/src/compile/handler/descriptor.ts +489 -0
  178. package/src/compile/handler/frozen-validator.ts +615 -0
  179. package/src/compile/handler/index.ts +924 -0
  180. package/src/compile/handler/jit.ts +1577 -0
  181. package/src/compile/handler/param-resolvers.ts +133 -0
  182. package/src/compile/handler/param-table.ts +115 -0
  183. package/src/compile/handler/params.ts +29 -0
  184. package/src/compile/handler/reconstruct.ts +80 -0
  185. package/src/compile/handler/route-shape.ts +301 -0
  186. package/src/compile/handler/static-clone-resolver.ts +3 -0
  187. package/src/compile/handler/utils.ts +770 -0
  188. package/src/compile/jit-probe.ts +38 -0
  189. package/src/compile/lexer.ts +481 -0
  190. package/src/compile/utils.ts +51 -0
  191. package/src/compiled.ts +15 -0
  192. package/src/constants.ts +110 -0
  193. package/src/context.ts +362 -0
  194. package/src/cookie/config.ts +367 -0
  195. package/src/cookie/cookie.ts +210 -0
  196. package/src/cookie/crypto.ts +345 -0
  197. package/src/cookie/error.ts +1 -0
  198. package/src/cookie/lib.ts +139 -0
  199. package/src/cookie/serialize.ts +58 -0
  200. package/src/cookie/types.ts +124 -0
  201. package/src/cookie/utils.ts +491 -0
  202. package/src/error.ts +1446 -0
  203. package/src/generation.ts +46 -0
  204. package/src/handler/error.ts +520 -0
  205. package/src/handler/fetch.ts +800 -0
  206. package/src/handler/utils.ts +177 -0
  207. package/src/index.ts +85 -0
  208. package/src/memory.ts +14 -0
  209. package/src/parse-query.ts +321 -0
  210. package/src/plugin/aot/bun.ts +52 -0
  211. package/src/plugin/aot/core.ts +1729 -0
  212. package/src/plugin/aot/esbuild.ts +86 -0
  213. package/src/plugin/aot/hooks.ts +374 -0
  214. package/src/plugin/aot/rspack-loader.ts +42 -0
  215. package/src/plugin/aot/rspack.ts +135 -0
  216. package/src/plugin/aot/source.ts +759 -0
  217. package/src/plugin/aot/treeshake.ts +128 -0
  218. package/src/plugin/aot/unplugin.ts +94 -0
  219. package/src/plugin/aot/vite.ts +41 -0
  220. package/src/plugin/aot/worker.ts +30 -0
  221. package/src/plugin/auto-head.ts +44 -0
  222. package/src/plugin/trace.ts +56 -0
  223. package/src/plugin/websocket.ts +82 -0
  224. package/src/route-table.ts +99 -0
  225. package/src/schema-snapshot.ts +603 -0
  226. package/src/sucrose.ts +497 -0
  227. package/src/trace.ts +743 -0
  228. package/src/type/bridge-live.ts +58 -0
  229. package/src/type/bridge.ts +142 -0
  230. package/src/type/coerce-plan.ts +382 -0
  231. package/src/type/coerce.ts +575 -0
  232. package/src/type/compat.ts +98 -0
  233. package/src/type/constants.ts +36 -0
  234. package/src/type/elysia/accelerate.ts +17 -0
  235. package/src/type/elysia/array-buffer.ts +60 -0
  236. package/src/type/elysia/array-string.ts +21 -0
  237. package/src/type/elysia/array.ts +14 -0
  238. package/src/type/elysia/boolean-string.ts +47 -0
  239. package/src/type/elysia/boolean.ts +9 -0
  240. package/src/type/elysia/cookie.ts +72 -0
  241. package/src/type/elysia/date.ts +167 -0
  242. package/src/type/elysia/file-type.ts +184 -0
  243. package/src/type/elysia/file.ts +102 -0
  244. package/src/type/elysia/files.ts +107 -0
  245. package/src/type/elysia/form.ts +45 -0
  246. package/src/type/elysia/integer-string.ts +36 -0
  247. package/src/type/elysia/integer.ts +9 -0
  248. package/src/type/elysia/intersect.ts +10 -0
  249. package/src/type/elysia/json-string.ts +73 -0
  250. package/src/type/elysia/keep-config.ts +114 -0
  251. package/src/type/elysia/maybe-empty.ts +32 -0
  252. package/src/type/elysia/no-validate.ts +7 -0
  253. package/src/type/elysia/nullable.ts +15 -0
  254. package/src/type/elysia/number.ts +24 -0
  255. package/src/type/elysia/numeric-enum.ts +61 -0
  256. package/src/type/elysia/numeric.ts +160 -0
  257. package/src/type/elysia/object-string.ts +23 -0
  258. package/src/type/elysia/object.ts +33 -0
  259. package/src/type/elysia/optional.ts +25 -0
  260. package/src/type/elysia/problem.ts +45 -0
  261. package/src/type/elysia/string.ts +54 -0
  262. package/src/type/elysia/uint8-array.ts +27 -0
  263. package/src/type/elysia/union-enum.ts +36 -0
  264. package/src/type/elysia/union.ts +11 -0
  265. package/src/type/elysia/utils.ts +126 -0
  266. package/src/type/exports.ts +53 -0
  267. package/src/type/index.ts +175 -0
  268. package/src/type/shared.ts +212 -0
  269. package/src/type/sync-require.ts +15 -0
  270. package/src/type/typebox-system-lite.ts +8 -0
  271. package/src/type/typebox-system-require.ts +31 -0
  272. package/src/type/typebox-type-live.ts +73 -0
  273. package/src/type/typebox-type.ts +152 -0
  274. package/src/type/typebox-value-live.ts +47 -0
  275. package/src/type/typebox-value-ops.ts +21 -0
  276. package/src/type/typebox-value-require.ts +34 -0
  277. package/src/type/typebox-value.ts +143 -0
  278. package/src/type/types.ts +294 -0
  279. package/src/type/utils.ts +63 -0
  280. package/src/type/validator/clean-safe.ts +156 -0
  281. package/src/type/validator/custom-error.ts +338 -0
  282. package/src/type/validator/default-precompute.ts +803 -0
  283. package/src/type/validator/exact-mirror-live.ts +25 -0
  284. package/src/type/validator/exact-mirror-require.ts +7 -0
  285. package/src/type/validator/exact-mirror.ts +36 -0
  286. package/src/type/validator/frozen-check.ts +58 -0
  287. package/src/type/validator/index.ts +1435 -0
  288. package/src/type/validator/string-codec-aot.ts +96 -0
  289. package/src/type/validator/validator-cache.ts +419 -0
  290. package/src/types.ts +4750 -0
  291. package/src/universal/constants.ts +25 -0
  292. package/src/universal/env.ts +7 -0
  293. package/src/universal/file.ts +177 -0
  294. package/src/universal/index.ts +13 -0
  295. package/src/universal/is-production.ts +4 -0
  296. package/src/universal/server.ts +82 -0
  297. package/src/utils.ts +1720 -0
  298. package/src/validator/index.ts +647 -0
  299. package/src/validator/route.ts +108 -0
  300. package/src/ws/context.ts +434 -0
  301. package/src/ws/index.ts +23 -0
  302. package/src/ws/parser.ts +84 -0
  303. package/src/ws/route.ts +1425 -0
  304. package/src/ws/types.ts +350 -0
@@ -189,7 +189,7 @@ const BunAdapter = require_adapter_index.createAdapter({
189
189
  const requestReady = Promise.withResolvers();
190
190
  function gatedFetch(request, srv) {
191
191
  return live && app.server === server ? live(request, srv) : requestReady.promise.then(() => {
192
- if (app.server !== server || !live) return unavailableFetch();
192
+ if (app.server !== server || !live || wsDrifted && request.headers.has("upgrade")) return unavailableFetch();
193
193
  return live(request, srv);
194
194
  });
195
195
  }
@@ -207,12 +207,18 @@ const BunAdapter = require_adapter_index.createAdapter({
207
207
  } : _options;
208
208
  const handoff = (request, server) => serve.fetch(request, server);
209
209
  const htmlRoutes = collectNativeRoutes(app, app.pending ? void 0 : handoff);
210
+ const wsBound = (app["~hasWS"] ? app["~ext"]?.capability?.ws?.provider : void 0)?.declaredOptions(app);
211
+ if (wsBound) serve.websocket = {
212
+ ...wsBound,
213
+ message() {}
214
+ };
210
215
  const server = app.server = Bun.serve(serve.routes || serve.error || htmlRoutes ? {
211
216
  ...serve,
212
217
  error: unavailableFetch,
213
218
  routes: htmlRoutes ?? {}
214
219
  } : serve);
215
220
  let live;
221
+ let wsDrifted = false;
216
222
  let shutdownAttempt;
217
223
  let wsLifecycle;
218
224
  let modulesReady;
@@ -229,6 +235,7 @@ const BunAdapter = require_adapter_index.createAdapter({
229
235
  if (app["~hasWS"]) {
230
236
  const resolved = require_generation.resolvedWsOf(app);
231
237
  if (!resolved) throw new Error("[Elysia] internal: WebSocket routes are present but no capability provider was resolved");
238
+ wsDrifted = !!wsBound && !Bun.deepEquals(wsBound, resolved.config ?? {});
232
239
  const handler = resolved.provider.buildGlobalWSHandler();
233
240
  websocket = resolved.config ? Object.assign(handler, resolved.config) : handler;
234
241
  const setter = Object.getOwnPropertyDescriptor(handler, "~lifecycle")?.set;
@@ -189,7 +189,7 @@ const BunAdapter = createAdapter({
189
189
  const requestReady = Promise.withResolvers();
190
190
  function gatedFetch(request, srv) {
191
191
  return live && app.server === server ? live(request, srv) : requestReady.promise.then(() => {
192
- if (app.server !== server || !live) return unavailableFetch();
192
+ if (app.server !== server || !live || wsDrifted && request.headers.has("upgrade")) return unavailableFetch();
193
193
  return live(request, srv);
194
194
  });
195
195
  }
@@ -207,12 +207,18 @@ const BunAdapter = createAdapter({
207
207
  } : _options;
208
208
  const handoff = (request, server) => serve.fetch(request, server);
209
209
  const htmlRoutes = collectNativeRoutes(app, app.pending ? void 0 : handoff);
210
+ const wsBound = (app["~hasWS"] ? app["~ext"]?.capability?.ws?.provider : void 0)?.declaredOptions(app);
211
+ if (wsBound) serve.websocket = {
212
+ ...wsBound,
213
+ message() {}
214
+ };
210
215
  const server = app.server = Bun.serve(serve.routes || serve.error || htmlRoutes ? {
211
216
  ...serve,
212
217
  error: unavailableFetch,
213
218
  routes: htmlRoutes ?? {}
214
219
  } : serve);
215
220
  let live;
221
+ let wsDrifted = false;
216
222
  let shutdownAttempt;
217
223
  let wsLifecycle;
218
224
  let modulesReady;
@@ -229,6 +235,7 @@ const BunAdapter = createAdapter({
229
235
  if (app["~hasWS"]) {
230
236
  const resolved = resolvedWsOf(app);
231
237
  if (!resolved) throw new Error("[Elysia] internal: WebSocket routes are present but no capability provider was resolved");
238
+ wsDrifted = !!wsBound && !Bun.deepEquals(wsBound, resolved.config ?? {});
232
239
  const handler = resolved.provider.buildGlobalWSHandler();
233
240
  websocket = resolved.config ? Object.assign(handler, resolved.config) : handler;
234
241
  const setter = Object.getOwnPropertyDescriptor(handler, "~lifecycle")?.set;
@@ -3,6 +3,7 @@ import { BaseCookie } from "../cookie/types.js";
3
3
  import { Context } from "../context.js";
4
4
  import { ElysiaFile } from "../universal/file.js";
5
5
  import { HTTPHeaders } from "../types.js";
6
+
6
7
  //#region src/adapter/utils.d.ts
7
8
  declare const hget: (h: Headers | Record<string, unknown>, k: string) => unknown;
8
9
  declare function hput(h: Headers | Record<string, unknown>, k: string, v: unknown, soft?: 1): void;
@@ -17,7 +18,7 @@ declare function responseToSetHeaders(response: Response, set?: Context['set']):
17
18
  redirect?: never;
18
19
  } | {
19
20
  headers: any;
20
- status: number | "Continue" | "Switching Protocols" | "Processing" | "Early Hints" | "OK" | "Created" | "Accepted" | "Non-Authoritative Information" | "No Content" | "Reset Content" | "Partial Content" | "Multi-Status" | "Already Reported" | "Multiple Choices" | "Moved Permanently" | "Found" | "See Other" | "Not Modified" | "Temporary Redirect" | "Permanent Redirect" | "Bad Request" | "Unauthorized" | "Payment Required" | "Forbidden" | "Not Found" | "Method Not Allowed" | "Not Acceptable" | "Proxy Authentication Required" | "Request Timeout" | "Conflict" | "Gone" | "Length Required" | "Precondition Failed" | "Payload Too Large" | "URI Too Long" | "Unsupported Media Type" | "Range Not Satisfiable" | "Expectation Failed" | "I'm a teapot" | "Enhance Your Calm" | "Misdirected Request" | "Unprocessable Content" | "Locked" | "Failed Dependency" | "Too Early" | "Upgrade Required" | "Precondition Required" | "Too Many Requests" | "Request Header Fields Too Large" | "Unavailable For Legal Reasons" | "Internal Server Error" | "Not Implemented" | "Bad Gateway" | "Service Unavailable" | "Gateway Timeout" | "HTTP Version Not Supported" | "Variant Also Negotiates" | "Insufficient Storage" | "Loop Detected" | "Not Extended" | "Network Authentication Required";
21
+ status: number | "Not Found" | "Continue" | "Switching Protocols" | "Processing" | "Early Hints" | "OK" | "Created" | "Accepted" | "Non-Authoritative Information" | "No Content" | "Reset Content" | "Partial Content" | "Multi-Status" | "Already Reported" | "Multiple Choices" | "Moved Permanently" | "Found" | "See Other" | "Not Modified" | "Temporary Redirect" | "Permanent Redirect" | "Bad Request" | "Unauthorized" | "Payment Required" | "Forbidden" | "Method Not Allowed" | "Not Acceptable" | "Proxy Authentication Required" | "Request Timeout" | "Conflict" | "Gone" | "Length Required" | "Precondition Failed" | "Payload Too Large" | "URI Too Long" | "Unsupported Media Type" | "Range Not Satisfiable" | "Expectation Failed" | "I'm a teapot" | "Enhance Your Calm" | "Misdirected Request" | "Unprocessable Content" | "Locked" | "Failed Dependency" | "Too Early" | "Upgrade Required" | "Precondition Required" | "Too Many Requests" | "Request Header Fields Too Large" | "Unavailable For Legal Reasons" | "Internal Server Error" | "Not Implemented" | "Bad Gateway" | "Service Unavailable" | "Gateway Timeout" | "HTTP Version Not Supported" | "Variant Also Negotiates" | "Insufficient Storage" | "Loop Detected" | "Not Extended" | "Network Authentication Required";
21
22
  };
22
23
  interface CreateHandlerParameter {
23
24
  mapResponse(response: unknown, set: Context['set'], request?: Request, owned?: boolean): Response;
@@ -38,23 +39,18 @@ declare function createResponseHandler(): (response: Response, set?: Context["se
38
39
  */
39
40
  declare function observeStream(source: ReadableStream): [ReadableStream, AsyncIterable<unknown>, AsyncIterableIterator<unknown>] | undefined;
40
41
  /**
41
- * Split async source into `branches` independent iterators
42
+ * Split async source into a value iterator and a completion iterator
42
43
  *
43
- * A producer drains the source ahead of consumers
44
+ * A producer drains the source ahead of the value consumer (response/client)
44
45
  *
45
46
  * To prevent long/infinite stream, the unconsumed window is capped:
46
- * Consumed-by-every-branch entries are trimmed off the front
47
47
  * Producer backpressures whenever the window hits `cap` ENTRIES or
48
48
  * `capBytes` bytes, whichever comes first
49
49
  *
50
- * Streams below both caps buffer eagerly
51
- * Only streams exceeding one gate on the slowest consumer
52
- *
53
- * Branch 0 is the value consumer (response/client)
54
- * When `return()` (client abort / early exit), source is stopped
55
- * so the observer branches can still reach completion instead of spinning
56
- * an infinite source
50
+ * The second iterator yields nothing: it settles once the source ends
51
+ * (rejects with its error) or the value iterator returns, which stops
52
+ * the source so an infinite one can't keep afterResponse waiting
57
53
  */
58
- declare function tee<T>(source: AsyncIterable<T>, branches?: number, cap?: number, capBytes?: number): AsyncIterableIterator<T>[];
54
+ declare function tee<T>(source: AsyncIterable<T>, cap?: number, capBytes?: number): AsyncIterableIterator<T>[];
59
55
  //#endregion
60
56
  export { createResponseHandler, createStreamHandler, handleFile, handleSet, hget, hput, materializeSetHeaders, normalizeContentType, observeStream, parseSetCookies, responseToSetHeaders, streamResponse, tee };
@@ -3,6 +3,7 @@ const require_universal_constants = require('../universal/constants.js');
3
3
  const require_constants = require('../constants.js');
4
4
  const require_utils = require('../utils.js');
5
5
  const require_adapter_skip_clone = require('./skip-clone.js');
6
+ const require_error = require('../error.js');
6
7
  const require_cookie_serialize = require('../cookie/serialize.js');
7
8
  const require_adapter_response_ownership = require('./response-ownership.js');
8
9
  const require_adapter_default_headers = require('./default-headers.js');
@@ -18,7 +19,7 @@ function hput(h, k, v, soft) {
18
19
  function materializeSetHeaders(set) {
19
20
  const headers = set.headers;
20
21
  if (headers["\0"] !== headers) return headers;
21
- return set.headers = Object.assign(require_utils.nullObject(), headers);
22
+ return set.headers = Object.assign(new require_utils.EmptyObject(), headers);
22
23
  }
23
24
  const sseFormat = (data) => require_utils.sseData(data) + "\n";
24
25
  const identityFormat = (data) => data;
@@ -45,7 +46,7 @@ function handleFile(response, set, request, size = response.size) {
45
46
  }
46
47
  if (!match[1] && !match[2] || start >= size || start > end) return new Response(null, {
47
48
  status: 416,
48
- headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? require_utils.nullObject())
49
+ headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? new require_utils.EmptyObject())
49
50
  });
50
51
  const contentLength = end - start + 1;
51
52
  const rangeHeaders = new Headers({
@@ -55,13 +56,13 @@ function handleFile(response, set, request, size = response.size) {
55
56
  });
56
57
  return new Response(response.slice(start, end + 1, response.type), {
57
58
  status: 206,
58
- headers: mergeHeaders(rangeHeaders, set?.headers ?? require_utils.nullObject())
59
+ headers: mergeHeaders(rangeHeaders, set?.headers ?? new require_utils.EmptyObject())
59
60
  });
60
61
  }
61
62
  }
62
63
  const body = "value" in response ? response.value : response;
63
64
  const immutable = set && (set.status === 206 || set.status === 304 || set.status === 412 || set.status === 416);
64
- const defaultHeader = immutable ? require_utils.nullObject() : { "accept-ranges": "bytes" };
65
+ const defaultHeader = immutable ? new require_utils.EmptyObject() : { "accept-ranges": "bytes" };
65
66
  if (!immutable && size) defaultHeader["content-range"] = `bytes 0-${size - 1}/${size}`;
66
67
  if (!set && !size) return new Response(body);
67
68
  if (!set) return new Response(body, { headers: defaultHeader });
@@ -81,7 +82,7 @@ function handleFile(response, set, request, size = response.size) {
81
82
  function normalizeHeaders(set) {
82
83
  const headers = set.headers;
83
84
  if (!(headers instanceof Headers)) return;
84
- const flat = Object.create(null);
85
+ const flat = new require_utils.EmptyObject();
85
86
  for (const [key, value] of headers) if (key !== setCookie) flat[key] = value;
86
87
  const cookies = headers.getSetCookie();
87
88
  if (cookies.length) flat[setCookie] = cookies;
@@ -101,7 +102,7 @@ function responseToSetHeaders(response, set) {
101
102
  else for (const [key, value] of response.headers.entries()) set.headers[key] = value;
102
103
  if (set.status === void 0 || set.status === 200) set.status = response.status;
103
104
  } else if (!response) return {
104
- headers: require_utils.nullObject(),
105
+ headers: new require_utils.EmptyObject(),
105
106
  status: set?.status ?? 200
106
107
  };
107
108
  else if (require_universal_constants.hasHeaderShorthand) set = {
@@ -110,7 +111,7 @@ function responseToSetHeaders(response, set) {
110
111
  };
111
112
  else {
112
113
  set = {
113
- headers: require_utils.nullObject(),
114
+ headers: new require_utils.EmptyObject(),
114
115
  status: set?.status ?? 200
115
116
  };
116
117
  for (const [key, value] of response.headers.entries()) set.headers[key] = value;
@@ -118,6 +119,23 @@ function responseToSetHeaders(response, set) {
118
119
  if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
119
120
  return set;
120
121
  }
122
+ const describesFields = (schema) => schema?.type === "object" || schema?.type === "array" || !!schema?.allOf?.some(describesFields);
123
+ const hasFields = (value) => Array.isArray(value) || Object.prototype.toString.call(value) === "[object Object]";
124
+ const unwrapChunk = (chunk, value, typedSSE) => chunk.toSSE ? {
125
+ ...chunk,
126
+ ...value,
127
+ data: value.data
128
+ } : typedSSE ? value.data : value;
129
+ function cleanChunk(validator, chunk, typedSSE) {
130
+ const payload = chunk.toSSE ? { ...chunk } : typedSSE ? { data: chunk } : chunk;
131
+ if (validator.Clean) return hasFields(payload) || !describesFields(validator.schema) ? unwrapChunk(chunk, validator.Clean(payload), typedSSE) : chunk;
132
+ try {
133
+ const parsed = validator.From(payload, "response", true);
134
+ return parsed instanceof Promise ? parsed.then((value) => unwrapChunk(chunk, value, typedSSE), () => chunk) : unwrapChunk(chunk, parsed, typedSSE);
135
+ } catch {
136
+ return chunk;
137
+ }
138
+ }
121
139
  function createStreamHandler({ mapResponse, mapCompactResponse }) {
122
140
  return async (generator, set, request, skipFormat, owned = false) => {
123
141
  if (request === null) return void 0;
@@ -130,6 +148,8 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
130
148
  }
131
149
  return new Response(generator, { headers: { "content-type": "application/octet-stream" } });
132
150
  }
151
+ const pickChunk = set?.["~chunk"];
152
+ if (pickChunk) set["~chunk"] = void 0;
133
153
  const typedSSE = !skipFormat && "sse" in generator && generator.sse === true;
134
154
  const sourceIterator = typeof generator.next === "function" ? generator : void 0;
135
155
  let init = typedSSE ? void 0 : generator.next?.();
@@ -147,15 +167,30 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
147
167
  const yieldedStream = init?.value instanceof ReadableStream;
148
168
  if (yieldedStream) generator = init.value;
149
169
  else if (init && (typeof init?.done === "undefined" || init?.done)) {
150
- if (set) return mapResponse(init.value, set, request, owned);
151
- return mapCompactResponse(init.value, request, owned);
170
+ let value = init.value;
171
+ if (pickChunk) {
172
+ if (value instanceof Promise || typeof value?.then === "function") value = await value;
173
+ const wrapped = value instanceof require_error.ElysiaStatus;
174
+ const validator = pickChunk(wrapped ? value.status : set?.status ?? 200);
175
+ if (validator) {
176
+ let body = wrapped ? value.response : value;
177
+ if (body instanceof Promise || typeof body?.then === "function") body = await body;
178
+ if (typeof body?.next === "function") {
179
+ if (set) set["~chunk"] = pickChunk;
180
+ } else if (!(body instanceof Error) && !(body instanceof Response) && !(body instanceof ReadableStream)) body = await (validator.mayReturnPromise ? validator.From(body, "response", true) : validator.EncodeFrom(body, "response"));
181
+ if (wrapped) value.response = body;
182
+ else value = body;
183
+ }
184
+ }
185
+ if (set) return mapResponse(value, set, request, owned);
186
+ return mapCompactResponse(value, request, owned);
152
187
  }
153
188
  const isSSE = typedSSE || !skipFormat && (init?.value?.sse ?? generator?.sse ?? (set && hget(set.headers, "content-type")?.startsWith("text/event-stream")));
154
189
  const format = isSSE ? sseFormat : identityFormat;
155
190
  const contentType = isSSE ? "text/event-stream" : init?.value && typeof init?.value === "object" ? ArrayBuffer.isView(init.value) ? "application/octet-stream" : "application/json" : "text/plain";
156
191
  set ??= {
157
192
  status: 200,
158
- headers: require_utils.nullObject()
193
+ headers: new require_utils.EmptyObject()
159
194
  };
160
195
  const headers = materializeSetHeaders(set);
161
196
  if (!typedSSE) hput(headers, "transfer-encoding", "chunked", 1);
@@ -227,48 +262,48 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
227
262
  controller.enqueue(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
228
263
  return;
229
264
  }
230
- if (typeof value === "object") try {
231
- controller.enqueue(textEncoder.encode(format(JSON.stringify(value))));
232
- } catch {
233
- controller.enqueue(textEncoder.encode(format(value.toString())));
234
- }
265
+ if (typeof value === "object") controller.enqueue(textEncoder.encode(format(JSON.stringify(value))));
235
266
  else controller.enqueue(textEncoder.encode(format(value.toString())));
236
267
  };
268
+ const validator = sourceStream ? void 0 : pickChunk?.(set.status ?? 200);
269
+ const enqueueChunk = validator?.Clean || validator?.mayReturnPromise ? (controller, value) => {
270
+ const cleaned = cleanChunk(validator, value, typedSSE);
271
+ return cleaned instanceof Promise && cleaned !== value ? cleaned.then((value) => enqueueValue(controller, value)) : enqueueValue(controller, cleaned);
272
+ } : enqueueValue;
273
+ let controller;
274
+ const fail = (error) => {
275
+ finalize("error", controller, error);
276
+ };
277
+ const step = (result) => {
278
+ while (true) {
279
+ if (result.done || end) {
280
+ finalize("close", controller);
281
+ return;
282
+ }
283
+ const chunk = result.value;
284
+ if (chunk !== void 0 && chunk !== null) return enqueueChunk(controller, chunk);
285
+ const next = iterator.next();
286
+ if (typeof next.then === "function") return Promise.resolve(next).then(step);
287
+ result = next;
288
+ }
289
+ };
237
290
  return new Response(new ReadableStream({
238
- start(controller) {
291
+ start(c) {
292
+ controller = c;
239
293
  if (signal) {
240
294
  onAbort = () => finalize("close", controller);
241
295
  if (signal.aborted) onAbort();
242
296
  else signal.addEventListener("abort", onAbort, { once: true });
243
297
  }
244
298
  if (!init || init.value instanceof ReadableStream || init.value === void 0 || init.value === null) return;
245
- const fail = (error) => {
246
- finalize("error", controller, error);
247
- };
248
299
  try {
249
- return enqueueValue(controller, init.value)?.catch(fail);
300
+ return enqueueChunk(controller, init.value)?.catch(fail);
250
301
  } catch (error) {
251
302
  fail(error);
252
303
  }
253
304
  },
254
- pull(controller) {
305
+ pull() {
255
306
  if (end) return;
256
- const fail = (error) => {
257
- finalize("error", controller, error);
258
- };
259
- const step = (result) => {
260
- while (true) {
261
- if (result.done || end) {
262
- finalize("close", controller);
263
- return;
264
- }
265
- const chunk = result.value;
266
- if (chunk !== void 0 && chunk !== null) return enqueueValue(controller, chunk);
267
- const next = iterator.next();
268
- if (typeof next.then === "function") return Promise.resolve(next).then(step);
269
- result = next;
270
- }
271
- };
272
307
  try {
273
308
  const next = iterator.next();
274
309
  return (typeof next.then === "function" ? Promise.resolve(next).then(step) : step(next))?.catch(fail);
@@ -290,8 +325,8 @@ function handleSet(set) {
290
325
  if (typeof set.status === "string") set.status = require_constants.StatusMap[set.status];
291
326
  if (set.headers instanceof Headers) normalizeHeaders(set);
292
327
  const proto = Object.getPrototypeOf(set.headers);
293
- if (proto !== null && proto !== Object.prototype) {
294
- const flat = Object.create(null);
328
+ if (proto !== null && proto !== Object.prototype && proto !== require_utils.EmptyObject.prototype) {
329
+ const flat = new require_utils.EmptyObject();
295
330
  for (const key of Object.keys(set.headers)) flat[key] = set.headers[key];
296
331
  set.headers = flat;
297
332
  }
@@ -420,20 +455,23 @@ function observeStream(source) {
420
455
  value
421
456
  ];
422
457
  }
423
- function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
458
+ function tee(source, cap = 64, capBytes = 1 << 22) {
424
459
  const iterator = source[Symbol.asyncIterator]?.() ?? source[Symbol.iterator]();
425
460
  const buffer = [];
426
461
  const sizes = [];
427
- let base = 0;
428
462
  let windowBytes = 0;
429
463
  let done = false;
430
464
  let stopped = false;
431
465
  let failed = false;
432
466
  let sourceError;
433
467
  let drainResume = null;
434
- const cursors = new Array(branches).fill(0);
435
- let active = branches;
436
- const pending = new Array(branches).fill(null);
468
+ let pending = null;
469
+ let finish;
470
+ const completed = new Promise((resolve, reject) => finish = {
471
+ resolve,
472
+ reject
473
+ });
474
+ completed.catch(() => {});
437
475
  const resumeProducer = () => {
438
476
  if (drainResume) {
439
477
  const resume = drainResume;
@@ -441,119 +479,102 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
441
479
  resume();
442
480
  }
443
481
  };
444
- const trim = () => {
445
- if (active > 0) {
446
- let min = Infinity;
447
- for (const c of cursors) if (c < min) min = c;
448
- const consumed = min - base;
449
- if (min !== Infinity && consumed > 0) {
450
- for (let i = 0; i < consumed; i++) windowBytes -= sizes[i];
451
- buffer.splice(0, consumed);
452
- sizes.splice(0, consumed);
453
- base = min;
454
- }
455
- }
456
- if (buffer.length < cap && windowBytes < capBytes) resumeProducer();
457
- };
458
- const closeBranch = (me) => {
459
- if (cursors[me] === Infinity) return;
460
- cursors[me] = Infinity;
461
- active--;
462
- if (me === 0 && !stopped) {
463
- stopped = true;
464
- done = true;
465
- resumeProducer();
466
- try {
467
- const r = iterator.return?.();
468
- if (r && typeof r.then === "function") r.catch(() => {});
469
- } catch {}
470
- wakeAll();
471
- }
472
- if (active === 0) {
473
- buffer.length = 0;
474
- sizes.length = 0;
475
- windowBytes = 0;
476
- } else trim();
477
- };
478
- const serve = (me, p) => {
479
- const i = cursors[me];
480
- if (i === Infinity) return p.resolve(doneResult);
481
- if (i < base + buffer.length) {
482
- const value = buffer[i - base];
483
- cursors[me] = i + 1;
484
- trim();
485
- return p.resolve({
486
- done: false,
487
- value
488
- });
489
- }
490
- if (failed) return p.reject(sourceError);
491
- if (done) {
492
- closeBranch(me);
493
- return p.resolve(doneResult);
494
- }
495
- pending[me] = p;
496
- };
497
- const wakeAll = () => {
498
- for (let b = 0; b < branches; b++) {
499
- const p = pending[b];
500
- if (!p) continue;
501
- pending[b] = null;
502
- serve(b, p);
503
- }
482
+ const stop = (p) => {
483
+ pending = null;
484
+ p?.resolve(doneResult);
485
+ if (stopped) return;
486
+ stopped = done = true;
487
+ buffer.length = sizes.length = windowBytes = 0;
488
+ resumeProducer();
489
+ try {
490
+ const r = iterator.return?.();
491
+ if (r && typeof r.then === "function") r.catch(() => {});
492
+ } catch {}
493
+ finish.resolve(doneResult);
504
494
  };
505
495
  (async () => {
506
496
  try {
507
497
  while (!stopped) {
508
498
  const result = await iterator.next();
509
499
  if (result.done || stopped) break;
500
+ const p = pending;
501
+ if (p) {
502
+ pending = null;
503
+ p.resolve({
504
+ done: false,
505
+ value: result.value
506
+ });
507
+ continue;
508
+ }
510
509
  buffer.push(result.value);
511
510
  sizes.push(teeChunkCost(result.value));
512
511
  windowBytes += sizes[sizes.length - 1];
513
- wakeAll();
514
- if ((buffer.length >= cap || windowBytes >= capBytes) && active > 0 && !stopped) await new Promise((resolve) => {
512
+ if ((buffer.length >= cap || windowBytes >= capBytes) && !stopped) await new Promise((resolve) => {
515
513
  drainResume = resolve;
516
514
  });
517
515
  }
518
516
  } catch (error) {
519
- failed = true;
517
+ failed = !stopped;
520
518
  sourceError = error;
521
519
  } finally {
522
520
  done = true;
523
- wakeAll();
521
+ const p = pending;
522
+ pending = null;
523
+ if (failed) {
524
+ p?.reject(sourceError);
525
+ finish.reject(sourceError);
526
+ } else {
527
+ p?.resolve(doneResult);
528
+ finish.resolve(doneResult);
529
+ }
524
530
  }
525
531
  })();
526
- const makeBranch = (me) => Object.assign(Object.create(null), {
532
+ const value = Object.assign(Object.create(null), {
527
533
  [Symbol.asyncIterator]() {
528
534
  return this;
529
535
  },
530
- next: () => new Promise((resolve, reject) => serve(me, {
531
- resolve,
532
- reject
533
- })),
534
- return: (value) => {
535
- const p = pending[me];
536
- if (p) {
537
- pending[me] = null;
538
- p.resolve(doneResult);
536
+ next: () => {
537
+ if (buffer.length) {
538
+ const value = buffer.shift();
539
+ windowBytes -= sizes.shift();
540
+ if (buffer.length < cap && windowBytes < capBytes) resumeProducer();
541
+ return Promise.resolve({
542
+ done: false,
543
+ value
544
+ });
539
545
  }
540
- closeBranch(me);
546
+ if (failed) return Promise.reject(sourceError);
547
+ if (done) return Promise.resolve(doneResult);
548
+ return new Promise((resolve, reject) => pending = {
549
+ resolve,
550
+ reject
551
+ });
552
+ },
553
+ return: (result) => {
554
+ stop(pending);
541
555
  return Promise.resolve({
542
556
  done: true,
543
- value
557
+ value: result
544
558
  });
545
559
  },
546
560
  throw: (error) => {
547
- const p = pending[me];
548
- if (p) {
549
- pending[me] = null;
550
- p.resolve(doneResult);
551
- }
552
- closeBranch(me);
561
+ stop(pending);
553
562
  return Promise.reject(error);
554
563
  }
555
564
  });
556
- return Array.from({ length: branches }, (_, b) => makeBranch(b));
565
+ const observer = Object.assign(Object.create(null), {
566
+ [Symbol.asyncIterator]() {
567
+ return this;
568
+ },
569
+ next: () => completed,
570
+ return: (result) => Promise.resolve({
571
+ done: true,
572
+ value: result
573
+ }),
574
+ throw: (error) => Promise.reject(error)
575
+ });
576
+ if (source.sse === true) value.sse = true;
577
+ return [value, observer];
557
578
  }
558
579
 
559
580
  //#endregion