elysia 2.0.0-rc.0 → 2.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) 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.js +78 -39
  4. package/dist/adapter/utils.mjs +79 -40
  5. package/dist/adapter/web-standard/handler.js +26 -10
  6. package/dist/adapter/web-standard/handler.mjs +27 -11
  7. package/dist/adapter/web-standard/utils.js +3 -3
  8. package/dist/adapter/web-standard/utils.mjs +4 -4
  9. package/dist/base.d.ts +29 -27
  10. package/dist/base.js +201 -81
  11. package/dist/base.mjs +203 -83
  12. package/dist/compile/aot-capture.js +6 -12
  13. package/dist/compile/aot-capture.mjs +6 -12
  14. package/dist/compile/aot-reconstruct.d.ts +4 -3
  15. package/dist/compile/aot-reconstruct.js +20 -9
  16. package/dist/compile/aot-reconstruct.mjs +20 -9
  17. package/dist/compile/aot.d.ts +7 -7
  18. package/dist/compile/handler/frozen-validator.d.ts +3 -1
  19. package/dist/compile/handler/frozen-validator.js +18 -23
  20. package/dist/compile/handler/frozen-validator.mjs +20 -25
  21. package/dist/compile/handler/index.d.ts +7 -6
  22. package/dist/compile/handler/index.js +66 -10
  23. package/dist/compile/handler/index.mjs +67 -11
  24. package/dist/compile/handler/jit.js +26 -4
  25. package/dist/compile/handler/jit.mjs +26 -4
  26. package/dist/constants.d.ts +2 -1
  27. package/dist/constants.js +2 -0
  28. package/dist/constants.mjs +2 -1
  29. package/dist/context.js +30 -9
  30. package/dist/context.mjs +31 -10
  31. package/dist/cookie/config.d.ts +1 -0
  32. package/dist/cookie/config.js +28 -5
  33. package/dist/cookie/config.mjs +25 -2
  34. package/dist/cookie/cookie.d.ts +1 -1
  35. package/dist/cookie/cookie.js +26 -12
  36. package/dist/cookie/cookie.mjs +27 -13
  37. package/dist/cookie/crypto.js +7 -7
  38. package/dist/cookie/crypto.mjs +2 -2
  39. package/dist/cookie/error.d.ts +1 -15
  40. package/dist/cookie/error.js +1 -24
  41. package/dist/cookie/error.mjs +1 -24
  42. package/dist/cookie/lib.js +6 -6
  43. package/dist/cookie/lib.mjs +3 -3
  44. package/dist/cookie/serialize.d.ts +3 -1
  45. package/dist/cookie/serialize.js +15 -6
  46. package/dist/cookie/serialize.mjs +15 -7
  47. package/dist/cookie/utils.js +26 -18
  48. package/dist/cookie/utils.mjs +25 -17
  49. package/dist/error.d.ts +18 -4
  50. package/dist/error.js +46 -17
  51. package/dist/error.mjs +43 -15
  52. package/dist/handler/error.d.ts +2 -1
  53. package/dist/handler/error.js +18 -16
  54. package/dist/handler/error.mjs +19 -18
  55. package/dist/handler/fetch.js +3 -2
  56. package/dist/handler/fetch.mjs +3 -2
  57. package/dist/handler/utils.js +2 -1
  58. package/dist/handler/utils.mjs +2 -1
  59. package/dist/index.d.ts +3 -3
  60. package/dist/index.js +1 -2
  61. package/dist/index.mjs +1 -2
  62. package/dist/package.js +1 -1
  63. package/dist/package.mjs +1 -1
  64. package/dist/parse-query.js +3 -2
  65. package/dist/parse-query.mjs +3 -2
  66. package/dist/plugin/aot/core.d.ts +15 -3
  67. package/dist/plugin/aot/core.js +27 -12
  68. package/dist/plugin/aot/core.mjs +26 -13
  69. package/dist/plugin/aot/hooks.d.ts +6 -1
  70. package/dist/plugin/aot/hooks.js +14 -13
  71. package/dist/plugin/aot/hooks.mjs +15 -14
  72. package/dist/plugin/aot/source.js +12 -21
  73. package/dist/plugin/aot/source.mjs +12 -21
  74. package/dist/plugin/auto-head.js +1 -1
  75. package/dist/plugin/auto-head.mjs +1 -1
  76. package/dist/plugin/websocket.js +2 -1
  77. package/dist/plugin/websocket.mjs +3 -2
  78. package/dist/schema-snapshot.d.ts +2 -1
  79. package/dist/schema-snapshot.js +31 -6
  80. package/dist/schema-snapshot.mjs +31 -7
  81. package/dist/sucrose.js +4 -1
  82. package/dist/sucrose.mjs +4 -1
  83. package/dist/type/bridge-live.d.ts +2 -2
  84. package/dist/type/bridge-live.js +1 -0
  85. package/dist/type/bridge-live.mjs +2 -2
  86. package/dist/type/bridge.d.ts +8 -6
  87. package/dist/type/bridge.js +8 -0
  88. package/dist/type/bridge.mjs +3 -1
  89. package/dist/type/coerce-plan.d.ts +8 -1
  90. package/dist/type/coerce-plan.js +47 -2
  91. package/dist/type/coerce-plan.mjs +45 -5
  92. package/dist/type/coerce.d.ts +5 -1
  93. package/dist/type/coerce.js +33 -13
  94. package/dist/type/coerce.mjs +34 -14
  95. package/dist/type/compat.js +1 -0
  96. package/dist/type/compat.mjs +2 -1
  97. package/dist/type/constants.d.ts +2 -1
  98. package/dist/type/constants.js +2 -1
  99. package/dist/type/constants.mjs +2 -1
  100. package/dist/type/elysia/array.js +2 -13
  101. package/dist/type/elysia/array.mjs +2 -14
  102. package/dist/type/elysia/json-string.js +2 -2
  103. package/dist/type/elysia/json-string.mjs +3 -3
  104. package/dist/type/elysia/maybe-empty.d.ts +7 -4
  105. package/dist/type/elysia/maybe-empty.js +3 -2
  106. package/dist/type/elysia/maybe-empty.mjs +3 -2
  107. package/dist/type/elysia/numeric.d.ts +1 -1
  108. package/dist/type/elysia/numeric.js +20 -9
  109. package/dist/type/elysia/numeric.mjs +20 -9
  110. package/dist/type/elysia/object.js +2 -14
  111. package/dist/type/elysia/object.mjs +2 -15
  112. package/dist/type/elysia/optional.d.ts +6 -1
  113. package/dist/type/elysia/optional.js +2 -1
  114. package/dist/type/elysia/optional.mjs +1 -1
  115. package/dist/type/exports.d.ts +3 -3
  116. package/dist/type/exports.js +1 -1
  117. package/dist/type/exports.mjs +1 -1
  118. package/dist/type/index.js +1 -1
  119. package/dist/type/index.mjs +1 -1
  120. package/dist/type/shared.d.ts +3 -1
  121. package/dist/type/shared.js +3 -1
  122. package/dist/type/shared.mjs +3 -2
  123. package/dist/type/typebox-type-live.d.ts +2 -1
  124. package/dist/type/typebox-type-live.js +12 -1
  125. package/dist/type/typebox-type-live.mjs +11 -1
  126. package/dist/type/typebox-type.d.ts +2 -1
  127. package/dist/type/typebox-type.js +12 -1
  128. package/dist/type/typebox-type.mjs +11 -1
  129. package/dist/type/validator/custom-error.js +2 -1
  130. package/dist/type/validator/custom-error.mjs +2 -1
  131. package/dist/type/validator/default-precompute.js +56 -38
  132. package/dist/type/validator/default-precompute.mjs +57 -39
  133. package/dist/type/validator/index.d.ts +2 -0
  134. package/dist/type/validator/index.js +63 -22
  135. package/dist/type/validator/index.mjs +66 -25
  136. package/dist/type/validator/string-codec-aot.d.ts +1 -2
  137. package/dist/type/validator/string-codec-aot.js +3 -5
  138. package/dist/type/validator/string-codec-aot.mjs +3 -5
  139. package/dist/type/validator/validator-cache.js +13 -32
  140. package/dist/type/validator/validator-cache.mjs +13 -32
  141. package/dist/types.d.ts +210 -41
  142. package/dist/universal/file.d.ts +1 -0
  143. package/dist/universal/file.js +5 -0
  144. package/dist/universal/file.mjs +5 -0
  145. package/dist/utils.d.ts +22 -8
  146. package/dist/utils.js +135 -41
  147. package/dist/utils.mjs +129 -41
  148. package/dist/validator/index.js +1 -0
  149. package/dist/validator/index.mjs +1 -0
  150. package/dist/validator/route.js +1 -1
  151. package/dist/validator/route.mjs +1 -1
  152. package/dist/ws/context.d.ts +13 -7
  153. package/dist/ws/context.js +67 -18
  154. package/dist/ws/context.mjs +64 -18
  155. package/dist/ws/route.d.ts +4 -3
  156. package/dist/ws/route.js +105 -89
  157. package/dist/ws/route.mjs +110 -95
  158. package/dist/ws/types.d.ts +30 -14
  159. package/package.json +44 -8
  160. package/src/adapter/bun/index.ts +927 -0
  161. package/src/adapter/constants.ts +5 -0
  162. package/src/adapter/default-headers.ts +1 -0
  163. package/src/adapter/index.ts +11 -0
  164. package/src/adapter/origin.ts +60 -0
  165. package/src/adapter/response-ownership.ts +10 -0
  166. package/src/adapter/skip-clone.ts +2 -0
  167. package/src/adapter/types.ts +50 -0
  168. package/src/adapter/utils.ts +1101 -0
  169. package/src/adapter/web-standard/handler.ts +478 -0
  170. package/src/adapter/web-standard/index.ts +13 -0
  171. package/src/adapter/web-standard/parse.ts +50 -0
  172. package/src/adapter/web-standard/utils.ts +188 -0
  173. package/src/base.ts +9022 -0
  174. package/src/compile/aot-capture.ts +526 -0
  175. package/src/compile/aot-emit.ts +190 -0
  176. package/src/compile/aot-reconstruct.ts +292 -0
  177. package/src/compile/aot.ts +618 -0
  178. package/src/compile/handler/descriptor.ts +465 -0
  179. package/src/compile/handler/frozen-validator.ts +619 -0
  180. package/src/compile/handler/index.ts +919 -0
  181. package/src/compile/handler/jit.ts +1530 -0
  182. package/src/compile/handler/param-resolvers.ts +131 -0
  183. package/src/compile/handler/param-table.ts +113 -0
  184. package/src/compile/handler/params.ts +33 -0
  185. package/src/compile/handler/reconstruct.ts +83 -0
  186. package/src/compile/handler/route-shape.ts +277 -0
  187. package/src/compile/handler/static-clone-resolver.ts +3 -0
  188. package/src/compile/handler/utils.ts +754 -0
  189. package/src/compile/jit-probe.ts +38 -0
  190. package/src/compile/lexer.ts +481 -0
  191. package/src/compile/utils.ts +47 -0
  192. package/src/compiled.ts +15 -0
  193. package/src/constants.ts +110 -0
  194. package/src/context.ts +356 -0
  195. package/src/cookie/config.ts +367 -0
  196. package/src/cookie/cookie.ts +210 -0
  197. package/src/cookie/crypto.ts +345 -0
  198. package/src/cookie/error.ts +1 -0
  199. package/src/cookie/lib.ts +139 -0
  200. package/src/cookie/serialize.ts +58 -0
  201. package/src/cookie/types.ts +124 -0
  202. package/src/cookie/utils.ts +454 -0
  203. package/src/error.ts +1421 -0
  204. package/src/generation.ts +46 -0
  205. package/src/handler/error.ts +512 -0
  206. package/src/handler/fetch.ts +867 -0
  207. package/src/handler/utils.ts +177 -0
  208. package/src/index.ts +85 -0
  209. package/src/memory.ts +14 -0
  210. package/src/parse-query.ts +321 -0
  211. package/src/plugin/aot/bun.ts +52 -0
  212. package/src/plugin/aot/core.ts +1679 -0
  213. package/src/plugin/aot/esbuild.ts +86 -0
  214. package/src/plugin/aot/hooks.ts +374 -0
  215. package/src/plugin/aot/rspack-loader.ts +42 -0
  216. package/src/plugin/aot/rspack.ts +135 -0
  217. package/src/plugin/aot/source.ts +744 -0
  218. package/src/plugin/aot/treeshake.ts +128 -0
  219. package/src/plugin/aot/unplugin.ts +94 -0
  220. package/src/plugin/aot/vite.ts +41 -0
  221. package/src/plugin/aot/worker.ts +30 -0
  222. package/src/plugin/auto-head.ts +44 -0
  223. package/src/plugin/trace.ts +49 -0
  224. package/src/plugin/websocket.ts +82 -0
  225. package/src/route-table.ts +100 -0
  226. package/src/schema-snapshot.ts +522 -0
  227. package/src/sucrose.ts +466 -0
  228. package/src/trace.ts +559 -0
  229. package/src/type/bridge-live.ts +58 -0
  230. package/src/type/bridge.ts +142 -0
  231. package/src/type/coerce-plan.ts +382 -0
  232. package/src/type/coerce.ts +575 -0
  233. package/src/type/compat.ts +98 -0
  234. package/src/type/constants.ts +36 -0
  235. package/src/type/elysia/accelerate.ts +17 -0
  236. package/src/type/elysia/array-buffer.ts +60 -0
  237. package/src/type/elysia/array-string.ts +21 -0
  238. package/src/type/elysia/array.ts +14 -0
  239. package/src/type/elysia/boolean-string.ts +47 -0
  240. package/src/type/elysia/boolean.ts +9 -0
  241. package/src/type/elysia/cookie.ts +72 -0
  242. package/src/type/elysia/date.ts +167 -0
  243. package/src/type/elysia/file-type.ts +184 -0
  244. package/src/type/elysia/file.ts +102 -0
  245. package/src/type/elysia/files.ts +107 -0
  246. package/src/type/elysia/form.ts +45 -0
  247. package/src/type/elysia/integer-string.ts +36 -0
  248. package/src/type/elysia/integer.ts +9 -0
  249. package/src/type/elysia/intersect.ts +10 -0
  250. package/src/type/elysia/json-string.ts +73 -0
  251. package/src/type/elysia/keep-config.ts +114 -0
  252. package/src/type/elysia/maybe-empty.ts +32 -0
  253. package/src/type/elysia/no-validate.ts +7 -0
  254. package/src/type/elysia/nullable.ts +15 -0
  255. package/src/type/elysia/number.ts +24 -0
  256. package/src/type/elysia/numeric-enum.ts +61 -0
  257. package/src/type/elysia/numeric.ts +160 -0
  258. package/src/type/elysia/object-string.ts +23 -0
  259. package/src/type/elysia/object.ts +33 -0
  260. package/src/type/elysia/optional.ts +25 -0
  261. package/src/type/elysia/problem.ts +45 -0
  262. package/src/type/elysia/string.ts +54 -0
  263. package/src/type/elysia/uint8-array.ts +27 -0
  264. package/src/type/elysia/union-enum.ts +36 -0
  265. package/src/type/elysia/union.ts +11 -0
  266. package/src/type/elysia/utils.ts +126 -0
  267. package/src/type/exports.ts +53 -0
  268. package/src/type/index.ts +175 -0
  269. package/src/type/shared.ts +212 -0
  270. package/src/type/sync-require.ts +15 -0
  271. package/src/type/typebox-system-lite.ts +8 -0
  272. package/src/type/typebox-system-require.ts +31 -0
  273. package/src/type/typebox-type-live.ts +73 -0
  274. package/src/type/typebox-type.ts +152 -0
  275. package/src/type/typebox-value-live.ts +47 -0
  276. package/src/type/typebox-value-ops.ts +21 -0
  277. package/src/type/typebox-value-require.ts +30 -0
  278. package/src/type/typebox-value.ts +143 -0
  279. package/src/type/types.ts +294 -0
  280. package/src/type/utils.ts +63 -0
  281. package/src/type/validator/clean-safe.ts +156 -0
  282. package/src/type/validator/custom-error.ts +369 -0
  283. package/src/type/validator/default-precompute.ts +803 -0
  284. package/src/type/validator/exact-mirror-live.ts +25 -0
  285. package/src/type/validator/exact-mirror-require.ts +7 -0
  286. package/src/type/validator/exact-mirror.ts +36 -0
  287. package/src/type/validator/frozen-check.ts +28 -0
  288. package/src/type/validator/index.ts +1435 -0
  289. package/src/type/validator/string-codec-aot.ts +96 -0
  290. package/src/type/validator/validator-cache.ts +419 -0
  291. package/src/types.ts +4753 -0
  292. package/src/universal/constants.ts +25 -0
  293. package/src/universal/env.ts +7 -0
  294. package/src/universal/file.ts +177 -0
  295. package/src/universal/index.ts +13 -0
  296. package/src/universal/is-production.ts +4 -0
  297. package/src/universal/server.ts +82 -0
  298. package/src/utils.ts +1774 -0
  299. package/src/validator/index.ts +650 -0
  300. package/src/validator/route.ts +108 -0
  301. package/src/ws/context.ts +442 -0
  302. package/src/ws/index.ts +23 -0
  303. package/src/ws/parser.ts +84 -0
  304. package/src/ws/route.ts +1406 -0
  305. 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;
@@ -18,7 +18,7 @@ function hput(h, k, v, soft) {
18
18
  function materializeSetHeaders(set) {
19
19
  const headers = set.headers;
20
20
  if (headers["\0"] !== headers) return headers;
21
- return set.headers = Object.assign(require_utils.nullObject(), headers);
21
+ return set.headers = Object.assign(new require_utils.EmptyObject(), headers);
22
22
  }
23
23
  const sseFormat = (data) => require_utils.sseData(data) + "\n";
24
24
  const identityFormat = (data) => data;
@@ -45,7 +45,7 @@ function handleFile(response, set, request, size = response.size) {
45
45
  }
46
46
  if (!match[1] && !match[2] || start >= size || start > end) return new Response(null, {
47
47
  status: 416,
48
- headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? require_utils.nullObject())
48
+ headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? new require_utils.EmptyObject())
49
49
  });
50
50
  const contentLength = end - start + 1;
51
51
  const rangeHeaders = new Headers({
@@ -55,13 +55,13 @@ function handleFile(response, set, request, size = response.size) {
55
55
  });
56
56
  return new Response(response.slice(start, end + 1, response.type), {
57
57
  status: 206,
58
- headers: mergeHeaders(rangeHeaders, set?.headers ?? require_utils.nullObject())
58
+ headers: mergeHeaders(rangeHeaders, set?.headers ?? new require_utils.EmptyObject())
59
59
  });
60
60
  }
61
61
  }
62
62
  const body = "value" in response ? response.value : response;
63
63
  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" };
64
+ const defaultHeader = immutable ? new require_utils.EmptyObject() : { "accept-ranges": "bytes" };
65
65
  if (!immutable && size) defaultHeader["content-range"] = `bytes 0-${size - 1}/${size}`;
66
66
  if (!set && !size) return new Response(body);
67
67
  if (!set) return new Response(body, { headers: defaultHeader });
@@ -81,7 +81,7 @@ function handleFile(response, set, request, size = response.size) {
81
81
  function normalizeHeaders(set) {
82
82
  const headers = set.headers;
83
83
  if (!(headers instanceof Headers)) return;
84
- const flat = Object.create(null);
84
+ const flat = new require_utils.EmptyObject();
85
85
  for (const [key, value] of headers) if (key !== setCookie) flat[key] = value;
86
86
  const cookies = headers.getSetCookie();
87
87
  if (cookies.length) flat[setCookie] = cookies;
@@ -101,7 +101,7 @@ function responseToSetHeaders(response, set) {
101
101
  else for (const [key, value] of response.headers.entries()) set.headers[key] = value;
102
102
  if (set.status === void 0 || set.status === 200) set.status = response.status;
103
103
  } else if (!response) return {
104
- headers: require_utils.nullObject(),
104
+ headers: new require_utils.EmptyObject(),
105
105
  status: set?.status ?? 200
106
106
  };
107
107
  else if (require_universal_constants.hasHeaderShorthand) set = {
@@ -110,7 +110,7 @@ function responseToSetHeaders(response, set) {
110
110
  };
111
111
  else {
112
112
  set = {
113
- headers: require_utils.nullObject(),
113
+ headers: new require_utils.EmptyObject(),
114
114
  status: set?.status ?? 200
115
115
  };
116
116
  for (const [key, value] of response.headers.entries()) set.headers[key] = value;
@@ -118,6 +118,23 @@ function responseToSetHeaders(response, set) {
118
118
  if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
119
119
  return set;
120
120
  }
121
+ const describesFields = (schema) => schema?.type === "object" || schema?.type === "array" || !!schema?.allOf?.some(describesFields);
122
+ const hasFields = (value) => Array.isArray(value) || Object.prototype.toString.call(value) === "[object Object]";
123
+ const unwrapChunk = (chunk, value, typedSSE) => chunk.toSSE ? {
124
+ ...chunk,
125
+ ...value,
126
+ data: value.data
127
+ } : typedSSE ? value.data : value;
128
+ function cleanChunk(validator, chunk, typedSSE) {
129
+ const payload = chunk.toSSE ? { ...chunk } : typedSSE ? { data: chunk } : chunk;
130
+ if (validator.Clean) return hasFields(payload) || !describesFields(validator.schema) ? unwrapChunk(chunk, validator.Clean(payload), typedSSE) : chunk;
131
+ try {
132
+ const parsed = validator.From(payload, "response", true);
133
+ return parsed instanceof Promise ? parsed.then((value) => unwrapChunk(chunk, value, typedSSE), () => chunk) : unwrapChunk(chunk, parsed, typedSSE);
134
+ } catch {
135
+ return chunk;
136
+ }
137
+ }
121
138
  function createStreamHandler({ mapResponse, mapCompactResponse }) {
122
139
  return async (generator, set, request, skipFormat, owned = false) => {
123
140
  if (request === null) return void 0;
@@ -130,6 +147,8 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
130
147
  }
131
148
  return new Response(generator, { headers: { "content-type": "application/octet-stream" } });
132
149
  }
150
+ const responses = set?.["~chunk"];
151
+ if (responses) set["~chunk"] = void 0;
133
152
  const typedSSE = !skipFormat && "sse" in generator && generator.sse === true;
134
153
  const sourceIterator = typeof generator.next === "function" ? generator : void 0;
135
154
  let init = typedSSE ? void 0 : generator.next?.();
@@ -155,7 +174,7 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
155
174
  const contentType = isSSE ? "text/event-stream" : init?.value && typeof init?.value === "object" ? ArrayBuffer.isView(init.value) ? "application/octet-stream" : "application/json" : "text/plain";
156
175
  set ??= {
157
176
  status: 200,
158
- headers: require_utils.nullObject()
177
+ headers: new require_utils.EmptyObject()
159
178
  };
160
179
  const headers = materializeSetHeaders(set);
161
180
  if (!typedSSE) hput(headers, "transfer-encoding", "chunked", 1);
@@ -234,41 +253,45 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
234
253
  }
235
254
  else controller.enqueue(textEncoder.encode(format(value.toString())));
236
255
  };
256
+ const validator = sourceStream ? void 0 : responses?.get(set.status ?? 200);
257
+ const enqueueChunk = validator?.Clean || validator?.mayReturnPromise ? (controller, value) => {
258
+ const cleaned = cleanChunk(validator, value, typedSSE);
259
+ return cleaned instanceof Promise && cleaned !== value ? cleaned.then((value) => enqueueValue(controller, value)) : enqueueValue(controller, cleaned);
260
+ } : enqueueValue;
261
+ let controller;
262
+ const fail = (error) => {
263
+ finalize("error", controller, error);
264
+ };
265
+ const step = (result) => {
266
+ while (true) {
267
+ if (result.done || end) {
268
+ finalize("close", controller);
269
+ return;
270
+ }
271
+ const chunk = result.value;
272
+ if (chunk !== void 0 && chunk !== null) return enqueueChunk(controller, chunk);
273
+ const next = iterator.next();
274
+ if (typeof next.then === "function") return Promise.resolve(next).then(step);
275
+ result = next;
276
+ }
277
+ };
237
278
  return new Response(new ReadableStream({
238
- start(controller) {
279
+ start(c) {
280
+ controller = c;
239
281
  if (signal) {
240
282
  onAbort = () => finalize("close", controller);
241
283
  if (signal.aborted) onAbort();
242
284
  else signal.addEventListener("abort", onAbort, { once: true });
243
285
  }
244
286
  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
287
  try {
249
- return enqueueValue(controller, init.value)?.catch(fail);
288
+ return enqueueChunk(controller, init.value)?.catch(fail);
250
289
  } catch (error) {
251
290
  fail(error);
252
291
  }
253
292
  },
254
- pull(controller) {
293
+ pull() {
255
294
  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
295
  try {
273
296
  const next = iterator.next();
274
297
  return (typeof next.then === "function" ? Promise.resolve(next).then(step) : step(next))?.catch(fail);
@@ -290,8 +313,8 @@ function handleSet(set) {
290
313
  if (typeof set.status === "string") set.status = require_constants.StatusMap[set.status];
291
314
  if (set.headers instanceof Headers) normalizeHeaders(set);
292
315
  const proto = Object.getPrototypeOf(set.headers);
293
- if (proto !== null && proto !== Object.prototype) {
294
- const flat = Object.create(null);
316
+ if (proto !== null && proto !== Object.prototype && proto !== require_utils.EmptyObject.prototype) {
317
+ const flat = new require_utils.EmptyObject();
295
318
  for (const key of Object.keys(set.headers)) flat[key] = set.headers[key];
296
319
  set.headers = flat;
297
320
  }
@@ -448,8 +471,10 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
448
471
  const consumed = min - base;
449
472
  if (min !== Infinity && consumed > 0) {
450
473
  for (let i = 0; i < consumed; i++) windowBytes -= sizes[i];
451
- buffer.splice(0, consumed);
452
- sizes.splice(0, consumed);
474
+ buffer.copyWithin(0, consumed);
475
+ buffer.length -= consumed;
476
+ sizes.copyWithin(0, consumed);
477
+ sizes.length -= consumed;
453
478
  base = min;
454
479
  }
455
480
  }
@@ -527,10 +552,22 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
527
552
  [Symbol.asyncIterator]() {
528
553
  return this;
529
554
  },
530
- next: () => new Promise((resolve, reject) => serve(me, {
531
- resolve,
532
- reject
533
- })),
555
+ next: () => {
556
+ const i = cursors[me];
557
+ if (i < base + buffer.length) {
558
+ const value = buffer[i - base];
559
+ cursors[me] = i + 1;
560
+ trim();
561
+ return Promise.resolve({
562
+ done: false,
563
+ value
564
+ });
565
+ }
566
+ return new Promise((resolve, reject) => serve(me, {
567
+ resolve,
568
+ reject
569
+ }));
570
+ },
534
571
  return: (value) => {
535
572
  const p = pending[me];
536
573
  if (p) {
@@ -553,7 +590,9 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
553
590
  return Promise.reject(error);
554
591
  }
555
592
  });
556
- return Array.from({ length: branches }, (_, b) => makeBranch(b));
593
+ const out = Array.from({ length: branches }, (_, b) => makeBranch(b));
594
+ if (source.sse === true) out[0].sse = true;
595
+ return out;
557
596
  }
558
597
 
559
598
  //#endregion
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import { hasHeaderShorthand } from "../universal/constants.mjs";
3
3
  import { StatusMap } from "../constants.mjs";
4
- import { isByteStream, isNotEmpty, nullObject, sseData } from "../utils.mjs";
4
+ import { EmptyObject, isByteStream, isNotEmpty, sseData } from "../utils.mjs";
5
5
  import { skipClone } from "./skip-clone.mjs";
6
6
  import { serializeCookie } from "../cookie/serialize.mjs";
7
7
  import { isBorrowedResponse } from "./response-ownership.mjs";
@@ -18,7 +18,7 @@ function hput(h, k, v, soft) {
18
18
  function materializeSetHeaders(set) {
19
19
  const headers = set.headers;
20
20
  if (headers["\0"] !== headers) return headers;
21
- return set.headers = Object.assign(nullObject(), headers);
21
+ return set.headers = Object.assign(new EmptyObject(), headers);
22
22
  }
23
23
  const sseFormat = (data) => sseData(data) + "\n";
24
24
  const identityFormat = (data) => data;
@@ -45,7 +45,7 @@ function handleFile(response, set, request, size = response.size) {
45
45
  }
46
46
  if (!match[1] && !match[2] || start >= size || start > end) return new Response(null, {
47
47
  status: 416,
48
- headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? nullObject())
48
+ headers: mergeHeaders(new Headers({ "content-range": `bytes */${size}` }), set?.headers ?? new EmptyObject())
49
49
  });
50
50
  const contentLength = end - start + 1;
51
51
  const rangeHeaders = new Headers({
@@ -55,13 +55,13 @@ function handleFile(response, set, request, size = response.size) {
55
55
  });
56
56
  return new Response(response.slice(start, end + 1, response.type), {
57
57
  status: 206,
58
- headers: mergeHeaders(rangeHeaders, set?.headers ?? nullObject())
58
+ headers: mergeHeaders(rangeHeaders, set?.headers ?? new EmptyObject())
59
59
  });
60
60
  }
61
61
  }
62
62
  const body = "value" in response ? response.value : response;
63
63
  const immutable = set && (set.status === 206 || set.status === 304 || set.status === 412 || set.status === 416);
64
- const defaultHeader = immutable ? nullObject() : { "accept-ranges": "bytes" };
64
+ const defaultHeader = immutable ? new EmptyObject() : { "accept-ranges": "bytes" };
65
65
  if (!immutable && size) defaultHeader["content-range"] = `bytes 0-${size - 1}/${size}`;
66
66
  if (!set && !size) return new Response(body);
67
67
  if (!set) return new Response(body, { headers: defaultHeader });
@@ -81,7 +81,7 @@ function handleFile(response, set, request, size = response.size) {
81
81
  function normalizeHeaders(set) {
82
82
  const headers = set.headers;
83
83
  if (!(headers instanceof Headers)) return;
84
- const flat = Object.create(null);
84
+ const flat = new EmptyObject();
85
85
  for (const [key, value] of headers) if (key !== setCookie) flat[key] = value;
86
86
  const cookies = headers.getSetCookie();
87
87
  if (cookies.length) flat[setCookie] = cookies;
@@ -101,7 +101,7 @@ function responseToSetHeaders(response, set) {
101
101
  else for (const [key, value] of response.headers.entries()) set.headers[key] = value;
102
102
  if (set.status === void 0 || set.status === 200) set.status = response.status;
103
103
  } else if (!response) return {
104
- headers: nullObject(),
104
+ headers: new EmptyObject(),
105
105
  status: set?.status ?? 200
106
106
  };
107
107
  else if (hasHeaderShorthand) set = {
@@ -110,7 +110,7 @@ function responseToSetHeaders(response, set) {
110
110
  };
111
111
  else {
112
112
  set = {
113
- headers: nullObject(),
113
+ headers: new EmptyObject(),
114
114
  status: set?.status ?? 200
115
115
  };
116
116
  for (const [key, value] of response.headers.entries()) set.headers[key] = value;
@@ -118,6 +118,23 @@ function responseToSetHeaders(response, set) {
118
118
  if (set.headers["content-encoding"]) delete set.headers["content-encoding"];
119
119
  return set;
120
120
  }
121
+ const describesFields = (schema) => schema?.type === "object" || schema?.type === "array" || !!schema?.allOf?.some(describesFields);
122
+ const hasFields = (value) => Array.isArray(value) || Object.prototype.toString.call(value) === "[object Object]";
123
+ const unwrapChunk = (chunk, value, typedSSE) => chunk.toSSE ? {
124
+ ...chunk,
125
+ ...value,
126
+ data: value.data
127
+ } : typedSSE ? value.data : value;
128
+ function cleanChunk(validator, chunk, typedSSE) {
129
+ const payload = chunk.toSSE ? { ...chunk } : typedSSE ? { data: chunk } : chunk;
130
+ if (validator.Clean) return hasFields(payload) || !describesFields(validator.schema) ? unwrapChunk(chunk, validator.Clean(payload), typedSSE) : chunk;
131
+ try {
132
+ const parsed = validator.From(payload, "response", true);
133
+ return parsed instanceof Promise ? parsed.then((value) => unwrapChunk(chunk, value, typedSSE), () => chunk) : unwrapChunk(chunk, parsed, typedSSE);
134
+ } catch {
135
+ return chunk;
136
+ }
137
+ }
121
138
  function createStreamHandler({ mapResponse, mapCompactResponse }) {
122
139
  return async (generator, set, request, skipFormat, owned = false) => {
123
140
  if (request === null) return void 0;
@@ -130,6 +147,8 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
130
147
  }
131
148
  return new Response(generator, { headers: { "content-type": "application/octet-stream" } });
132
149
  }
150
+ const responses = set?.["~chunk"];
151
+ if (responses) set["~chunk"] = void 0;
133
152
  const typedSSE = !skipFormat && "sse" in generator && generator.sse === true;
134
153
  const sourceIterator = typeof generator.next === "function" ? generator : void 0;
135
154
  let init = typedSSE ? void 0 : generator.next?.();
@@ -155,7 +174,7 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
155
174
  const contentType = isSSE ? "text/event-stream" : init?.value && typeof init?.value === "object" ? ArrayBuffer.isView(init.value) ? "application/octet-stream" : "application/json" : "text/plain";
156
175
  set ??= {
157
176
  status: 200,
158
- headers: nullObject()
177
+ headers: new EmptyObject()
159
178
  };
160
179
  const headers = materializeSetHeaders(set);
161
180
  if (!typedSSE) hput(headers, "transfer-encoding", "chunked", 1);
@@ -234,41 +253,45 @@ function createStreamHandler({ mapResponse, mapCompactResponse }) {
234
253
  }
235
254
  else controller.enqueue(textEncoder.encode(format(value.toString())));
236
255
  };
256
+ const validator = sourceStream ? void 0 : responses?.get(set.status ?? 200);
257
+ const enqueueChunk = validator?.Clean || validator?.mayReturnPromise ? (controller, value) => {
258
+ const cleaned = cleanChunk(validator, value, typedSSE);
259
+ return cleaned instanceof Promise && cleaned !== value ? cleaned.then((value) => enqueueValue(controller, value)) : enqueueValue(controller, cleaned);
260
+ } : enqueueValue;
261
+ let controller;
262
+ const fail = (error) => {
263
+ finalize("error", controller, error);
264
+ };
265
+ const step = (result) => {
266
+ while (true) {
267
+ if (result.done || end) {
268
+ finalize("close", controller);
269
+ return;
270
+ }
271
+ const chunk = result.value;
272
+ if (chunk !== void 0 && chunk !== null) return enqueueChunk(controller, chunk);
273
+ const next = iterator.next();
274
+ if (typeof next.then === "function") return Promise.resolve(next).then(step);
275
+ result = next;
276
+ }
277
+ };
237
278
  return new Response(new ReadableStream({
238
- start(controller) {
279
+ start(c) {
280
+ controller = c;
239
281
  if (signal) {
240
282
  onAbort = () => finalize("close", controller);
241
283
  if (signal.aborted) onAbort();
242
284
  else signal.addEventListener("abort", onAbort, { once: true });
243
285
  }
244
286
  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
287
  try {
249
- return enqueueValue(controller, init.value)?.catch(fail);
288
+ return enqueueChunk(controller, init.value)?.catch(fail);
250
289
  } catch (error) {
251
290
  fail(error);
252
291
  }
253
292
  },
254
- pull(controller) {
293
+ pull() {
255
294
  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
295
  try {
273
296
  const next = iterator.next();
274
297
  return (typeof next.then === "function" ? Promise.resolve(next).then(step) : step(next))?.catch(fail);
@@ -290,8 +313,8 @@ function handleSet(set) {
290
313
  if (typeof set.status === "string") set.status = StatusMap[set.status];
291
314
  if (set.headers instanceof Headers) normalizeHeaders(set);
292
315
  const proto = Object.getPrototypeOf(set.headers);
293
- if (proto !== null && proto !== Object.prototype) {
294
- const flat = Object.create(null);
316
+ if (proto !== null && proto !== Object.prototype && proto !== EmptyObject.prototype) {
317
+ const flat = new EmptyObject();
295
318
  for (const key of Object.keys(set.headers)) flat[key] = set.headers[key];
296
319
  set.headers = flat;
297
320
  }
@@ -448,8 +471,10 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
448
471
  const consumed = min - base;
449
472
  if (min !== Infinity && consumed > 0) {
450
473
  for (let i = 0; i < consumed; i++) windowBytes -= sizes[i];
451
- buffer.splice(0, consumed);
452
- sizes.splice(0, consumed);
474
+ buffer.copyWithin(0, consumed);
475
+ buffer.length -= consumed;
476
+ sizes.copyWithin(0, consumed);
477
+ sizes.length -= consumed;
453
478
  base = min;
454
479
  }
455
480
  }
@@ -527,10 +552,22 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
527
552
  [Symbol.asyncIterator]() {
528
553
  return this;
529
554
  },
530
- next: () => new Promise((resolve, reject) => serve(me, {
531
- resolve,
532
- reject
533
- })),
555
+ next: () => {
556
+ const i = cursors[me];
557
+ if (i < base + buffer.length) {
558
+ const value = buffer[i - base];
559
+ cursors[me] = i + 1;
560
+ trim();
561
+ return Promise.resolve({
562
+ done: false,
563
+ value
564
+ });
565
+ }
566
+ return new Promise((resolve, reject) => serve(me, {
567
+ resolve,
568
+ reject
569
+ }));
570
+ },
534
571
  return: (value) => {
535
572
  const p = pending[me];
536
573
  if (p) {
@@ -553,7 +590,9 @@ function tee(source, branches = 2, cap = 64, capBytes = 1 << 22) {
553
590
  return Promise.reject(error);
554
591
  }
555
592
  });
556
- return Array.from({ length: branches }, (_, b) => makeBranch(b));
593
+ const out = Array.from({ length: branches }, (_, b) => makeBranch(b));
594
+ if (source.sse === true) out[0].sse = true;
595
+ return out;
557
596
  }
558
597
 
559
598
  //#endregion
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_universal_constants = require('../../universal/constants.js');
3
+ const require_constants = require('../../constants.js');
3
4
  const require_universal_file = require('../../universal/file.js');
4
5
  const require_utils = require('../../utils.js');
5
6
  const require_universal_is_production = require('../../universal/is-production.js');
@@ -10,7 +11,7 @@ const require_cookie_cookie = require('../../cookie/cookie.js');
10
11
 
11
12
  //#region src/adapter/web-standard/handler.ts
12
13
  const textPlainInit = { headers: { "content-type": "text/plain" } };
13
- function handleElysiaFile(file, set = { headers: require_utils.nullObject() }, request) {
14
+ function handleElysiaFile(file, set = { headers: new require_utils.EmptyObject() }, request) {
14
15
  const contentType = file.type;
15
16
  const headers = require_adapter_utils.materializeSetHeaders(set);
16
17
  if (contentType !== "application/octet-stream") require_adapter_utils.hput(headers, "content-type", contentType);
@@ -58,12 +59,27 @@ function mapResponseWithSet(response, set, request, owned) {
58
59
  }
59
60
  }
60
61
  function withStatus(response, set, request, owned) {
61
- if (set) set.status = response.status;
62
- else set = {
63
- status: response.status,
64
- headers: require_utils.nullObject()
65
- };
66
- if (response.headers) {
62
+ let extra;
63
+ if (set) {
64
+ set.status = response.status;
65
+ extra = response.headers;
66
+ } else {
67
+ const status = response.status;
68
+ extra = response.headers;
69
+ if (require_universal_constants.isBun && !extra) {
70
+ const body = response.response;
71
+ if (typeof body === "string") return new Response(body, { status });
72
+ return mapResponseWithSet(body, {
73
+ status,
74
+ headers: new require_utils.EmptyObject()
75
+ }, request, owned);
76
+ }
77
+ set = {
78
+ status,
79
+ headers: new require_utils.EmptyObject()
80
+ };
81
+ }
82
+ if (extra) {
67
83
  const headers = require_adapter_utils.materializeSetHeaders(set);
68
84
  for (const [key, value] of Object.entries(response.headers)) if (key.toLowerCase() !== "set-cookie") require_adapter_utils.hput(headers, key, value);
69
85
  else if (headers instanceof Headers) for (const cookie of [].concat(value)) headers.append(key, cookie);
@@ -112,7 +128,7 @@ function mapCompactResponse(response, request, owned) {
112
128
  }
113
129
  function errorToResponse(error, set, request, owned = false) {
114
130
  if (error?.toResponse) {
115
- const targetSet = set ?? { headers: require_utils.nullObject() };
131
+ const targetSet = set ?? { headers: new require_utils.EmptyObject() };
116
132
  const apply = (resolved) => {
117
133
  if (resolved instanceof Response) targetSet.status = resolved.status;
118
134
  return mapResponse(resolved, targetSet, request, owned);
@@ -123,8 +139,8 @@ function errorToResponse(error, set, request, owned = false) {
123
139
  const status = set?.status && set.status !== 200 ? set.status : 500;
124
140
  const body = require_error.internalServerErrorBody(error);
125
141
  body.status = status;
126
- const headers = set ? require_adapter_utils.materializeSetHeaders(set) : require_utils.nullObject();
127
- require_adapter_utils.hput(headers, "content-type", require_error.PROBLEM_JSON);
142
+ const headers = set ? require_adapter_utils.materializeSetHeaders(set) : new require_utils.EmptyObject();
143
+ require_adapter_utils.hput(headers, "content-type", require_constants.PROBLEM_JSON);
128
144
  return new Response(JSON.stringify(body), {
129
145
  status,
130
146
  headers