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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/dist/adapter/bun/index.d.ts +18 -2
  2. package/dist/adapter/bun/index.js +467 -110
  3. package/dist/adapter/bun/index.mjs +467 -112
  4. package/dist/adapter/types.d.ts +2 -21
  5. package/dist/adapter/utils.d.ts +14 -3
  6. package/dist/adapter/utils.js +146 -87
  7. package/dist/adapter/utils.mjs +148 -90
  8. package/dist/adapter/web-standard/handler.d.ts +1 -1
  9. package/dist/adapter/web-standard/handler.js +47 -36
  10. package/dist/adapter/web-standard/handler.mjs +48 -37
  11. package/dist/adapter/web-standard/index.js +2 -30
  12. package/dist/adapter/web-standard/index.mjs +2 -30
  13. package/dist/adapter/web-standard/utils.js +5 -18
  14. package/dist/adapter/web-standard/utils.mjs +5 -18
  15. package/dist/base.d.ts +99 -67
  16. package/dist/base.js +678 -510
  17. package/dist/base.mjs +682 -514
  18. package/dist/compile/aot-capture.d.ts +2 -13
  19. package/dist/compile/aot-capture.js +26 -69
  20. package/dist/compile/aot-capture.mjs +28 -67
  21. package/dist/compile/aot-emit.d.ts +9 -7
  22. package/dist/compile/aot-emit.js +42 -19
  23. package/dist/compile/aot-emit.mjs +42 -20
  24. package/dist/compile/aot.d.ts +17 -19
  25. package/dist/compile/aot.js +41 -51
  26. package/dist/compile/aot.mjs +39 -49
  27. package/dist/compile/handler/descriptor.d.ts +9 -12
  28. package/dist/compile/handler/descriptor.js +19 -44
  29. package/dist/compile/handler/descriptor.mjs +20 -42
  30. package/dist/compile/handler/frozen-validator.d.ts +5 -10
  31. package/dist/compile/handler/frozen-validator.js +55 -105
  32. package/dist/compile/handler/frozen-validator.mjs +53 -105
  33. package/dist/compile/handler/index.d.ts +7 -5
  34. package/dist/compile/handler/index.js +270 -111
  35. package/dist/compile/handler/index.mjs +270 -113
  36. package/dist/compile/handler/jit.d.ts +19 -17
  37. package/dist/compile/handler/jit.js +222 -149
  38. package/dist/compile/handler/jit.mjs +224 -152
  39. package/dist/compile/handler/params.d.ts +1 -4
  40. package/dist/compile/handler/params.js +10 -5
  41. package/dist/compile/handler/params.mjs +14 -8
  42. package/dist/compile/handler/reconstruct.d.ts +2 -2
  43. package/dist/compile/handler/reconstruct.js +6 -4
  44. package/dist/compile/handler/reconstruct.mjs +6 -4
  45. package/dist/compile/handler/static-clone-resolver.d.ts +6 -0
  46. package/dist/compile/handler/static-clone-resolver.js +8 -0
  47. package/dist/compile/handler/static-clone-resolver.mjs +7 -0
  48. package/dist/compile/handler/utils.d.ts +22 -11
  49. package/dist/compile/handler/utils.js +159 -253
  50. package/dist/compile/handler/utils.mjs +155 -252
  51. package/dist/compile/jit-probe.d.ts +2 -2
  52. package/dist/compile/jit-probe.js +2 -3
  53. package/dist/compile/jit-probe.mjs +2 -3
  54. package/dist/compile/lexer.d.ts +7 -4
  55. package/dist/compile/lexer.js +268 -6
  56. package/dist/compile/lexer.mjs +268 -4
  57. package/dist/compile/utils.js +7 -4
  58. package/dist/compile/utils.mjs +7 -4
  59. package/dist/compiled.d.ts +0 -1
  60. package/dist/compiled.js +0 -1
  61. package/dist/compiled.mjs +0 -1
  62. package/dist/context.d.ts +14 -4
  63. package/dist/context.js +17 -32
  64. package/dist/context.mjs +19 -34
  65. package/dist/cookie/config.d.ts +7 -2
  66. package/dist/cookie/config.js +76 -16
  67. package/dist/cookie/config.mjs +77 -18
  68. package/dist/cookie/cookie.d.ts +1 -1
  69. package/dist/cookie/cookie.js +8 -10
  70. package/dist/cookie/cookie.mjs +8 -10
  71. package/dist/cookie/crypto.d.ts +8 -7
  72. package/dist/cookie/crypto.js +51 -40
  73. package/dist/cookie/crypto.mjs +51 -41
  74. package/dist/cookie/error.d.ts +1 -2
  75. package/dist/cookie/error.js +6 -4
  76. package/dist/cookie/error.mjs +6 -4
  77. package/dist/cookie/lib.js +7 -2
  78. package/dist/cookie/lib.mjs +7 -2
  79. package/dist/cookie/serialize.js +1 -1
  80. package/dist/cookie/serialize.mjs +1 -1
  81. package/dist/cookie/types.d.ts +10 -0
  82. package/dist/cookie/utils.d.ts +4 -8
  83. package/dist/cookie/utils.js +86 -52
  84. package/dist/cookie/utils.mjs +89 -54
  85. package/dist/error.d.ts +113 -103
  86. package/dist/error.js +181 -117
  87. package/dist/error.mjs +179 -118
  88. package/dist/generation.d.ts +2 -2
  89. package/dist/handler/error.d.ts +26 -15
  90. package/dist/handler/error.js +77 -96
  91. package/dist/handler/error.mjs +74 -97
  92. package/dist/handler/fetch.js +87 -108
  93. package/dist/handler/fetch.mjs +89 -110
  94. package/dist/handler/utils.d.ts +12 -6
  95. package/dist/handler/utils.js +84 -28
  96. package/dist/handler/utils.mjs +80 -28
  97. package/dist/index.d.ts +12 -12
  98. package/dist/index.js +2 -9
  99. package/dist/index.mjs +1 -1
  100. package/dist/memory.js +1 -1
  101. package/dist/memory.mjs +1 -1
  102. package/dist/package.js +1 -1
  103. package/dist/package.mjs +1 -1
  104. package/dist/plugin/aot/bun.d.ts +8 -1
  105. package/dist/plugin/aot/bun.js +16 -9
  106. package/dist/plugin/aot/bun.mjs +17 -10
  107. package/dist/plugin/aot/core.d.ts +52 -60
  108. package/dist/plugin/aot/core.js +208 -109
  109. package/dist/plugin/aot/core.mjs +205 -111
  110. package/dist/plugin/aot/esbuild.js +8 -5
  111. package/dist/plugin/aot/esbuild.mjs +9 -6
  112. package/dist/plugin/aot/hooks.d.ts +6 -17
  113. package/dist/plugin/aot/hooks.js +36 -14
  114. package/dist/plugin/aot/hooks.mjs +37 -16
  115. package/dist/plugin/aot/rspack-loader.d.ts +1 -5
  116. package/dist/plugin/aot/rspack-loader.js +1 -10
  117. package/dist/plugin/aot/rspack-loader.mjs +1 -10
  118. package/dist/plugin/aot/rspack.js +2 -5
  119. package/dist/plugin/aot/rspack.mjs +3 -6
  120. package/dist/plugin/aot/source.d.ts +6 -42
  121. package/dist/plugin/aot/source.js +71 -71
  122. package/dist/plugin/aot/source.mjs +72 -72
  123. package/dist/plugin/aot/treeshake.js +2 -6
  124. package/dist/plugin/aot/treeshake.mjs +2 -6
  125. package/dist/plugin/aot/unplugin.d.ts +1 -4
  126. package/dist/plugin/aot/unplugin.js +4 -13
  127. package/dist/plugin/aot/unplugin.mjs +4 -13
  128. package/dist/plugin/aot/vite.d.ts +2 -6
  129. package/dist/plugin/aot/worker.js +2 -2
  130. package/dist/plugin/aot/worker.mjs +2 -2
  131. package/dist/plugin/auto-head.js +1 -10
  132. package/dist/plugin/auto-head.mjs +1 -10
  133. package/dist/plugin/trace.d.ts +2 -1
  134. package/dist/route-table.d.ts +3 -0
  135. package/dist/route-table.js +16 -11
  136. package/dist/route-table.mjs +16 -11
  137. package/dist/schema-snapshot.d.ts +0 -4
  138. package/dist/schema-snapshot.js +32 -49
  139. package/dist/schema-snapshot.mjs +32 -49
  140. package/dist/sucrose.d.ts +6 -55
  141. package/dist/sucrose.js +103 -731
  142. package/dist/sucrose.mjs +102 -724
  143. package/dist/trace.d.ts +5 -8
  144. package/dist/trace.js +23 -134
  145. package/dist/trace.mjs +24 -135
  146. package/dist/type/bridge-live.d.ts +4 -2
  147. package/dist/type/bridge-live.js +6 -3
  148. package/dist/type/bridge-live.mjs +4 -2
  149. package/dist/type/bridge.d.ts +6 -4
  150. package/dist/type/bridge.js +17 -9
  151. package/dist/type/bridge.mjs +5 -3
  152. package/dist/type/coerce-plan.d.ts +5 -5
  153. package/dist/type/coerce-plan.js +41 -39
  154. package/dist/type/coerce-plan.mjs +43 -39
  155. package/dist/type/coerce.d.ts +3 -7
  156. package/dist/type/coerce.js +18 -75
  157. package/dist/type/coerce.mjs +19 -76
  158. package/dist/type/compat.d.ts +3 -0
  159. package/dist/type/compat.js +23 -14
  160. package/dist/type/compat.mjs +20 -10
  161. package/dist/type/elysia/array-buffer.d.ts +4 -1
  162. package/dist/type/elysia/array-buffer.js +17 -17
  163. package/dist/type/elysia/array-buffer.mjs +17 -17
  164. package/dist/type/elysia/array-string.js +2 -40
  165. package/dist/type/elysia/array-string.mjs +2 -39
  166. package/dist/type/elysia/array.js +5 -9
  167. package/dist/type/elysia/array.mjs +5 -9
  168. package/dist/type/elysia/boolean-string.js +2 -3
  169. package/dist/type/elysia/boolean-string.mjs +1 -1
  170. package/dist/type/elysia/boolean.js +3 -12
  171. package/dist/type/elysia/boolean.mjs +3 -11
  172. package/dist/type/elysia/cookie.d.ts +3 -4
  173. package/dist/type/elysia/cookie.js +5 -15
  174. package/dist/type/elysia/cookie.mjs +5 -15
  175. package/dist/type/elysia/date.js +13 -20
  176. package/dist/type/elysia/date.mjs +10 -16
  177. package/dist/type/elysia/file-type.d.ts +11 -4
  178. package/dist/type/elysia/file-type.js +17 -2
  179. package/dist/type/elysia/file-type.mjs +17 -3
  180. package/dist/type/elysia/file.d.ts +1 -3
  181. package/dist/type/elysia/file.js +11 -27
  182. package/dist/type/elysia/file.mjs +11 -12
  183. package/dist/type/elysia/files.js +7 -11
  184. package/dist/type/elysia/files.mjs +7 -10
  185. package/dist/type/elysia/form.js +2 -3
  186. package/dist/type/elysia/form.mjs +3 -3
  187. package/dist/type/elysia/integer-string.d.ts +1 -1
  188. package/dist/type/elysia/integer-string.js +4 -30
  189. package/dist/type/elysia/integer-string.mjs +5 -30
  190. package/dist/type/elysia/integer.js +3 -12
  191. package/dist/type/elysia/integer.mjs +3 -11
  192. package/dist/type/elysia/intersect.js +0 -5
  193. package/dist/type/elysia/intersect.mjs +0 -5
  194. package/dist/type/elysia/json-string.d.ts +7 -0
  195. package/dist/type/elysia/json-string.js +47 -0
  196. package/dist/type/elysia/json-string.mjs +46 -0
  197. package/dist/type/elysia/keep-config.d.ts +14 -0
  198. package/dist/type/elysia/keep-config.js +62 -0
  199. package/dist/type/elysia/keep-config.mjs +53 -0
  200. package/dist/type/elysia/maybe-empty.js +3 -4
  201. package/dist/type/elysia/maybe-empty.mjs +1 -1
  202. package/dist/type/elysia/nullable.js +2 -3
  203. package/dist/type/elysia/nullable.mjs +1 -1
  204. package/dist/type/elysia/number.d.ts +2 -1
  205. package/dist/type/elysia/number.js +19 -11
  206. package/dist/type/elysia/number.mjs +18 -10
  207. package/dist/type/elysia/numeric-enum.d.ts +1 -1
  208. package/dist/type/elysia/numeric-enum.js +4 -5
  209. package/dist/type/elysia/numeric-enum.mjs +3 -3
  210. package/dist/type/elysia/numeric.d.ts +4 -2
  211. package/dist/type/elysia/numeric.js +20 -17
  212. package/dist/type/elysia/numeric.mjs +19 -16
  213. package/dist/type/elysia/object-string.js +2 -37
  214. package/dist/type/elysia/object-string.mjs +2 -36
  215. package/dist/type/elysia/object.js +5 -9
  216. package/dist/type/elysia/object.mjs +5 -9
  217. package/dist/type/elysia/optional.js +8 -8
  218. package/dist/type/elysia/optional.mjs +7 -7
  219. package/dist/type/elysia/problem.d.ts +20 -0
  220. package/dist/type/elysia/problem.js +25 -0
  221. package/dist/type/elysia/problem.mjs +24 -0
  222. package/dist/type/elysia/string.js +4 -3
  223. package/dist/type/elysia/string.mjs +4 -2
  224. package/dist/type/elysia/uint8-array.d.ts +1 -1
  225. package/dist/type/elysia/uint8-array.js +5 -20
  226. package/dist/type/elysia/uint8-array.mjs +5 -19
  227. package/dist/type/elysia/union-enum.js +7 -8
  228. package/dist/type/elysia/union-enum.mjs +6 -6
  229. package/dist/type/elysia/union.js +0 -5
  230. package/dist/type/elysia/union.mjs +0 -5
  231. package/dist/type/elysia/utils.d.ts +2 -4
  232. package/dist/type/elysia/utils.js +10 -21
  233. package/dist/type/elysia/utils.mjs +7 -15
  234. package/dist/type/exports.d.ts +4 -2
  235. package/dist/type/exports.js +23 -2
  236. package/dist/type/exports.mjs +11 -2
  237. package/dist/type/index.d.ts +10 -2
  238. package/dist/type/index.js +62 -15
  239. package/dist/type/index.mjs +65 -11
  240. package/dist/type/shared.d.ts +3 -9
  241. package/dist/type/shared.js +44 -97
  242. package/dist/type/shared.mjs +43 -97
  243. package/dist/type/sync-require.d.ts +11 -0
  244. package/dist/type/sync-require.js +14 -0
  245. package/dist/type/sync-require.mjs +12 -0
  246. package/dist/type/typebox-system-lite.d.ts +2 -0
  247. package/dist/type/typebox-system-lite.js +34 -0
  248. package/dist/type/typebox-system-lite.mjs +3 -0
  249. package/dist/type/typebox-system-require.d.ts +7 -0
  250. package/dist/type/typebox-system-require.js +24 -0
  251. package/dist/type/typebox-system-require.mjs +23 -0
  252. package/dist/type/typebox-type-live.d.ts +11 -0
  253. package/dist/type/typebox-type-live.js +45 -0
  254. package/dist/type/typebox-type-live.mjs +20 -0
  255. package/dist/type/typebox-type.d.ts +34 -0
  256. package/dist/type/typebox-type.js +199 -0
  257. package/dist/type/typebox-type.mjs +86 -0
  258. package/dist/type/typebox-value-live.d.ts +11 -0
  259. package/dist/type/typebox-value-live.js +31 -0
  260. package/dist/type/typebox-value-live.mjs +13 -0
  261. package/dist/type/typebox-value-ops.d.ts +4 -0
  262. package/dist/type/typebox-value-ops.js +90 -0
  263. package/dist/type/typebox-value-ops.mjs +5 -0
  264. package/dist/type/typebox-value-require.d.ts +8 -0
  265. package/dist/type/typebox-value-require.js +28 -0
  266. package/dist/type/typebox-value-require.mjs +25 -0
  267. package/dist/type/typebox-value.d.ts +35 -0
  268. package/dist/type/typebox-value.js +161 -0
  269. package/dist/type/typebox-value.mjs +74 -0
  270. package/dist/type/utils.js +1 -10
  271. package/dist/type/utils.mjs +1 -10
  272. package/dist/type/validator/clean-safe.d.ts +2 -4
  273. package/dist/type/validator/clean-safe.js +15 -11
  274. package/dist/type/validator/clean-safe.mjs +16 -10
  275. package/dist/type/validator/custom-error.js +12 -16
  276. package/dist/type/validator/custom-error.mjs +11 -14
  277. package/dist/type/validator/default-precompute.d.ts +9 -1
  278. package/dist/type/validator/default-precompute.js +40 -77
  279. package/dist/type/validator/default-precompute.mjs +37 -74
  280. package/dist/type/validator/exact-mirror-live.d.ts +8 -0
  281. package/dist/type/validator/exact-mirror-live.js +22 -0
  282. package/dist/type/validator/exact-mirror-live.mjs +17 -0
  283. package/dist/type/validator/exact-mirror-require.d.ts +4 -0
  284. package/dist/type/validator/exact-mirror-require.js +11 -0
  285. package/dist/type/validator/exact-mirror-require.mjs +9 -0
  286. package/dist/type/validator/exact-mirror.js +8 -8
  287. package/dist/type/validator/exact-mirror.mjs +9 -8
  288. package/dist/type/validator/frozen-check.js +5 -6
  289. package/dist/type/validator/frozen-check.mjs +6 -7
  290. package/dist/type/validator/index.d.ts +1 -0
  291. package/dist/type/validator/index.js +169 -166
  292. package/dist/type/validator/index.mjs +162 -158
  293. package/dist/type/validator/string-codec-aot.d.ts +2 -1
  294. package/dist/type/validator/string-codec-aot.js +8 -2
  295. package/dist/type/validator/string-codec-aot.mjs +7 -2
  296. package/dist/type/validator/validator-cache.d.ts +5 -4
  297. package/dist/type/validator/validator-cache.js +41 -24
  298. package/dist/type/validator/validator-cache.mjs +40 -22
  299. package/dist/types.d.ts +263 -95
  300. package/dist/universal/constants.d.ts +2 -1
  301. package/dist/universal/constants.js +3 -1
  302. package/dist/universal/constants.mjs +2 -1
  303. package/dist/universal/env.js +2 -3
  304. package/dist/universal/env.mjs +2 -3
  305. package/dist/universal/file.d.ts +6 -4
  306. package/dist/universal/file.js +11 -16
  307. package/dist/universal/file.mjs +12 -16
  308. package/dist/universal/index.d.ts +2 -2
  309. package/dist/universal/is-production.d.ts +1 -2
  310. package/dist/universal/is-production.js +1 -3
  311. package/dist/universal/is-production.mjs +2 -3
  312. package/dist/universal/server.d.ts +0 -272
  313. package/dist/utils.d.ts +43 -7
  314. package/dist/utils.js +181 -126
  315. package/dist/utils.mjs +168 -126
  316. package/dist/validator/index.d.ts +1 -1
  317. package/dist/validator/index.js +17 -30
  318. package/dist/validator/index.mjs +18 -31
  319. package/dist/validator/route.js +2 -1
  320. package/dist/validator/route.mjs +2 -1
  321. package/dist/ws/context.d.ts +8 -1
  322. package/dist/ws/context.js +68 -44
  323. package/dist/ws/context.mjs +67 -44
  324. package/dist/ws/parser.js +10 -20
  325. package/dist/ws/parser.mjs +10 -20
  326. package/dist/ws/route.d.ts +2 -2
  327. package/dist/ws/route.js +249 -141
  328. package/dist/ws/route.mjs +254 -146
  329. package/dist/ws/types.d.ts +2 -2
  330. package/package.json +23 -49
  331. package/dist/compile/analysis-cache.d.ts +0 -6
  332. package/dist/compile/analysis-cache.js +0 -12
  333. package/dist/compile/analysis-cache.mjs +0 -11
  334. package/dist/cookie/index.d.ts +0 -7
  335. package/dist/cookie/index.js +0 -13
  336. package/dist/cookie/index.mjs +0 -7
  337. package/dist/handler/index.d.ts +0 -2
  338. package/dist/handler/index.js +0 -5
  339. package/dist/handler/index.mjs +0 -3
@@ -1,13 +1,56 @@
1
1
  import { createAdapter } from "../index.mjs";
2
- import { isDynamicRegex, needEncodeRegex } from "../../constants.mjs";
3
- import { flattenChain, getLoosePath, nullObject } from "../../utils.mjs";
2
+ import { flattenChain, getLoosePath, isHTMLBundle, isSocketQuiet, nullObject, throwLifecycleErrors } from "../../utils.mjs";
3
+ import { preloadTypebox } from "../../type/bridge.mjs";
4
+ import { isProduction } from "../../universal/is-production.mjs";
4
5
  import { WebStandardAdapter } from "../web-standard/index.mjs";
5
6
  import { frozenRootOf, resolvedWsOf } from "../../generation.mjs";
6
7
  import { origin } from "../origin.mjs";
7
8
  import { buildNativeStaticResponse } from "../../compile/handler/index.mjs";
8
- import { routeRow } from "../../route-table.mjs";
9
+ import { RouteFlag, routeRow } from "../../route-table.mjs";
9
10
 
10
11
  //#region src/adapter/bun/index.ts
12
+ function runLifecycle(epoch, callback, ...args) {
13
+ const invoking = epoch.invoking;
14
+ epoch.invoking = true;
15
+ try {
16
+ return callback(...args);
17
+ } finally {
18
+ epoch.invoking = invoking;
19
+ }
20
+ }
21
+ const unavailableFetch = () => new Response(null, {
22
+ headers: { connection: "close" },
23
+ status: 503
24
+ });
25
+ function releaseLifecycle(app, ext, createdExt, stop, registerCleanup) {
26
+ if (ext.stop === stop) delete ext.stop;
27
+ if (ext.cleanupEpoch === registerCleanup) delete ext.cleanupEpoch;
28
+ if (createdExt && app["~ext"] === ext && !Object.keys(ext).length) app["~ext"] = void 0;
29
+ }
30
+ async function waitForServerRequests(server, abandoned) {
31
+ while (server.pendingRequests && !abandoned()) await Bun.sleep(1);
32
+ }
33
+ async function settleServerWebSockets(lifecycle, errors) {
34
+ if (!lifecycle) return true;
35
+ lifecycle.closing = true;
36
+ let failed = false;
37
+ do {
38
+ for (const socket of lifecycle.sockets) if (socket.readyState < 3) try {
39
+ socket.terminate();
40
+ } catch (error) {
41
+ errors.push(error);
42
+ failed = true;
43
+ }
44
+ if (failed) return false;
45
+ await Bun.sleep(1);
46
+ const abandon = lifecycle.abandon === true;
47
+ for (const socket of lifecycle.sockets) if (abandon || isSocketQuiet(socket)) {
48
+ delete socket.data["~lifecycleRun"];
49
+ lifecycle.sockets.delete(socket);
50
+ }
51
+ } while (lifecycle.sockets.size);
52
+ return true;
53
+ }
11
54
  /**
12
55
  * ! This may looks like it would cause race condition, but it is not
13
56
  * Bun is single-threaded and synchronous, so the `finally` block will
@@ -25,102 +68,186 @@ const withOrigin = (fetch) => (request, server) => {
25
68
  origin.request = void 0;
26
69
  }
27
70
  };
28
- const nativeStaticMethods = new Set([
29
- "GET",
30
- "POST",
31
- "PUT",
32
- "DELETE",
33
- "PATCH",
34
- "HEAD",
35
- "OPTIONS"
36
- ]);
71
+ const isNativeStaticMethod = (method) => method === "GET" || method === "POST" || method === "PUT" || method === "DELETE" || method === "PATCH" || method === "HEAD" || method === "OPTIONS";
72
+ function expandOptional(path) {
73
+ const at = path.indexOf("?");
74
+ if (at === -1) return [path];
75
+ const start = path.lastIndexOf("/", at);
76
+ const rest = path.slice(at + 1);
77
+ return [...expandOptional(path.slice(0, start) + rest), ...expandOptional(path.slice(0, at) + rest)].map((variant) => variant || "/");
78
+ }
79
+ function isNativePath(path) {
80
+ const names = /* @__PURE__ */ new Set();
81
+ const segments = path.split("/");
82
+ for (let i = 0; i < segments.length; i++) {
83
+ const segment = segments[i];
84
+ if (segment.indexOf("*") !== -1) {
85
+ if (segment !== "*" || i !== segments.length - 1) return false;
86
+ } else if (segment.indexOf(":") !== -1) {
87
+ if (!/^:[A-Za-z_$][\w$]*$/.test(segment)) return false;
88
+ if (names.has(segment)) return false;
89
+ names.add(segment);
90
+ }
91
+ }
92
+ return true;
93
+ }
94
+ /**
95
+ * HTML bundles served by Bun's native router.
96
+ *
97
+ * A `:param` / `*` bundle (SPA fallback) matches before `fetch`, so with a
98
+ * `handoff` every other route of that method is registered natively too,
99
+ * handing off to `fetch`: Bun's specificity (exact > param > wildcard) then
100
+ * picks the Elysia route, and only unmatched paths reach the bundle (Elysia's
101
+ * own router leaves these bundles out, see `#buildRouterUnsafe`).
102
+ *
103
+ * All or nothing: when any route cannot be expressed in Bun's router, dynamic
104
+ * bundles are not served natively at all, since that route would be shadowed.
105
+ */
106
+ function collectHTMLBundleRoutes(app, handoff, routes) {
107
+ let dynamic;
108
+ let bundles;
109
+ for (const route of app["~routes"]) {
110
+ const [method, path, handler] = route;
111
+ if (!isNativeStaticMethod(method) || !isHTMLBundle(handler)) continue;
112
+ if (path.indexOf(":") !== -1 || path.indexOf("*") !== -1) {
113
+ if (!handoff) continue;
114
+ (dynamic ??= /* @__PURE__ */ new Set()).add(method);
115
+ (bundles ??= []).push([
116
+ method,
117
+ path,
118
+ handler
119
+ ]);
120
+ } else ((routes ??= nullObject())[path] ??= nullObject())[method] = handler;
121
+ if (!isProduction() && (route[4] || route[5] || route[6])) console.warn(`[Elysia] ${method} ${path} is an HTML bundle served natively, hooks do not run for it`);
122
+ }
123
+ if (!dynamic) return routes;
124
+ const strictPath = app["~config"]?.strictPath === true;
125
+ const handoffs = [];
126
+ for (const [method, path, handler] of app["~routes"]) {
127
+ if (isHTMLBundle(handler)) continue;
128
+ const targets = method === "*" ? dynamic : dynamic.has(method) ? [method] : void 0;
129
+ if (!targets) continue;
130
+ for (const variant of expandOptional(path)) {
131
+ const loose = strictPath || variant.endsWith("*") ? variant : getLoosePath(variant);
132
+ for (const raw of loose === variant ? [variant] : [variant, loose]) {
133
+ if (!isNativePath(raw)) {
134
+ if (!isProduction()) console.warn(`[Elysia] ${method} ${path} cannot be expressed in Bun's router, so :param / * HTML bundles are not served natively (they would shadow it)`);
135
+ return routes;
136
+ }
137
+ const encoded = encodeURI(raw);
138
+ for (const target of targets) {
139
+ if (!/[^ -~]/.test(raw)) handoffs.push([raw, target]);
140
+ if (encoded !== raw) handoffs.push([encoded, target]);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ for (const [method, path, bundle] of bundles) ((routes ??= nullObject())[path] ??= nullObject())[method] = bundle;
146
+ for (const [key, method] of handoffs) (routes[key] ??= nullObject())[method] ??= handoff;
147
+ return routes;
148
+ }
37
149
  function collectStaticRoutes(app) {
38
- if (app["~config"]?.nativeStaticResponse === false) return;
39
150
  app.fetch;
40
151
  const frozenRoot = frozenRootOf(app);
41
152
  const fetchLevelHook = flattenChain(frozenRoot["~hookChain"]);
42
- if (fetchLevelHook?.request?.length || fetchLevelHook?.trace?.length || frozenRoot["~ext"]?.hoc?.length) return;
153
+ const promoteResponses = app["~config"]?.nativeStaticResponse !== false && !fetchLevelHook?.request?.length && !fetchLevelHook?.trace?.length && !frozenRoot["~ext"]?.hoc?.length;
43
154
  const table = app["~generation"]?.routeTable ?? app["~routeTable"];
44
155
  const length = table?.length ?? 0;
45
156
  if (!table || !length) return;
46
- const methods = table.method;
47
- const paths = table.path;
48
- const handlers = table.handler;
157
+ const { method: methods, path: paths, handler: handlers, flags } = table;
158
+ const isStatic = (i) => isNativeStaticMethod(methods[i]) && (flags[i] & RouteFlag.Dynamic) === 0;
159
+ const isPromotable = (h) => promoteResponses && typeof h !== "function" && !(h instanceof Error) && !(h instanceof Promise);
49
160
  let hasCandidate = false;
50
161
  for (let i = 0; i < length; i++) {
162
+ if (!isStatic(i)) continue;
51
163
  const h = handlers[i];
52
- if (typeof h === "function" || h instanceof Error || h instanceof Promise) continue;
53
- if (!nativeStaticMethods.has(methods[i])) continue;
54
- hasCandidate = true;
55
- break;
164
+ if (isHTMLBundle(h) || isPromotable(h)) {
165
+ hasCandidate = true;
166
+ break;
167
+ }
56
168
  }
57
169
  if (!hasCandidate) return;
58
- const ready = nullObject();
59
170
  const strictPath = frozenRoot["~config"]?.strictPath === true;
60
- const seen = /* @__PURE__ */ new Map();
61
- for (let i = 0; i < length; i++) seen.set(methods[i] + " " + paths[i], i);
62
- let explicitPaths;
63
- if (!strictPath) {
64
- explicitPaths = /* @__PURE__ */ new Map();
65
- for (let i = 0; i < length; i++) {
66
- const method = methods[i];
67
- const path = paths[i];
68
- let set = explicitPaths.get(method);
69
- if (!set) explicitPaths.set(method, set = /* @__PURE__ */ new Set());
70
- set.add(path);
71
- if (needEncodeRegex.test(path)) {
72
- const encoded = encodeURI(path);
73
- if (encoded !== path) set.add(encoded);
74
- }
171
+ const routeIndex = /* @__PURE__ */ new Map();
172
+ for (let i = 0; i < length; i++) {
173
+ if (!isStatic(i)) continue;
174
+ const method = methods[i];
175
+ const path = paths[i];
176
+ let pathsByMethod = routeIndex.get(method);
177
+ if (!pathsByMethod) routeIndex.set(method, pathsByMethod = /* @__PURE__ */ new Map());
178
+ pathsByMethod.set(path, i);
179
+ if (!strictPath && (flags[i] & RouteFlag.Encode) !== 0) {
180
+ const encoded = encodeURI(path);
181
+ if (encoded !== path && !pathsByMethod.has(encoded)) pathsByMethod.set(encoded, -1);
75
182
  }
76
183
  }
77
- const add = (method, path, value) => {
78
- if (needEncodeRegex.test(path)) path = encodeURI(path);
184
+ const ready = nullObject();
185
+ let hasReady = false;
186
+ const add = (method, path, value, needsEncode) => {
187
+ if (needsEncode) path = encodeURI(path);
79
188
  (ready[path] ??= nullObject())[method] = value;
189
+ hasReady = true;
80
190
  };
81
191
  for (let i = 0; i < length; i++) {
192
+ if (!isStatic(i)) continue;
82
193
  const method = methods[i];
83
- if (method === "WS") continue;
194
+ const pathsByMethod = routeIndex.get(method);
84
195
  const path = paths[i];
85
- if (seen.get(method + " " + path) !== i) continue;
86
- if (!nativeStaticMethods.has(method)) continue;
196
+ if (pathsByMethod.get(path) !== i) continue;
87
197
  const h = handlers[i];
88
- if (typeof h === "function" || h instanceof Error || h instanceof Promise) continue;
89
- const value = buildNativeStaticResponse(routeRow(table, i), app);
198
+ let value;
199
+ if (isHTMLBundle(h)) value = h;
200
+ else if (!isPromotable(h)) continue;
201
+ else value = buildNativeStaticResponse(routeRow(table, i), app);
90
202
  if (!value) continue;
91
- add(method, path, value);
92
- if (!strictPath && !isDynamicRegex.test(path)) {
203
+ const needsEncode = (flags[i] & RouteFlag.Encode) !== 0;
204
+ add(method, path, value, needsEncode);
205
+ if (!strictPath) {
93
206
  const loose = getLoosePath(path);
94
- if (loose !== path && !explicitPaths?.get(method)?.has(loose)) add(method, loose, value);
207
+ if (loose !== path && !pathsByMethod.has(loose)) add(method, loose, value, needsEncode);
95
208
  }
96
209
  }
97
- if (!Object.keys(ready).length) return;
98
- return [ready, []];
210
+ if (!hasReady) return;
211
+ return ready;
99
212
  }
100
213
  const BunAdapter = createAdapter({
101
- name: "bun",
102
- runtime: "bun",
103
- isWebStandard: true,
104
214
  parse: WebStandardAdapter.parse,
105
215
  response: WebStandardAdapter.response,
106
216
  listen(app, options, callback) {
107
- const _config = app["~config"]?.serve;
108
- const optionsIsObject = typeof options === "object";
109
- let live;
110
- const gatedFetch = (request, server) => live ? live(request, server) : Promise.resolve(ready).then(() => {
111
- if (!live) throw new Error("[Elysia] Server was stopped before it was ready");
112
- return live(request, server);
113
- });
114
- const _options = optionsIsObject ? { ...options } : {
217
+ if (app.server || app["~ext"]?.stop) throw new Error("[Elysia] Cannot call listen() while a server or teardown is active");
218
+ const requestReady = Promise.withResolvers();
219
+ function gatedFetch(request, server) {
220
+ return live && !cancelled ? live(request, server) : requestReady.promise.then(() => {
221
+ if (cancelled || !live) return unavailableFetch();
222
+ return live(request, server);
223
+ });
224
+ }
225
+ const _options = typeof options === "object" ? {
226
+ ...options,
227
+ fetch: gatedFetch
228
+ } : {
115
229
  port: +options,
116
230
  fetch: gatedFetch
117
231
  };
118
- if (optionsIsObject) _options.fetch = gatedFetch;
232
+ const _config = app["~config"]?.serve;
119
233
  const serve = _config ? {
120
234
  ..._config,
121
235
  ..._options
122
236
  } : _options;
123
- let ready;
237
+ const handoff = (request, server) => serve.fetch(request, server);
238
+ const htmlRoutes = collectHTMLBundleRoutes(app, app.pending ? void 0 : handoff);
239
+ const server = app.server = Bun.serve(serve.routes || serve.error || htmlRoutes ? {
240
+ ...serve,
241
+ error: unavailableFetch,
242
+ routes: htmlRoutes ?? {}
243
+ } : serve);
244
+ let live;
245
+ let cancelled = false;
246
+ let shutdownAttempt;
247
+ let wsLifecycle;
248
+ let modulesReady;
249
+ let pendingSetups;
250
+ let setupsSettled;
124
251
  const build = () => {
125
252
  const fetch = app.fetch;
126
253
  let routes;
@@ -129,11 +256,22 @@ const BunAdapter = createAdapter({
129
256
  } catch (error) {
130
257
  console.warn("[Elysia] Native static promotion was skipped:", error);
131
258
  }
259
+ routes = collectHTMLBundleRoutes(app, handoff, routes);
132
260
  let websocket;
133
261
  if (app["~hasWS"]) {
134
262
  const resolved = resolvedWsOf(app);
135
263
  if (!resolved) throw new Error("[Elysia] internal: WebSocket routes are present but no capability provider was resolved");
136
- websocket = resolved.config ? Object.assign(resolved.provider.buildGlobalWSHandler(), resolved.config) : resolved.provider.buildGlobalWSHandler();
264
+ const handler = resolved.provider.buildGlobalWSHandler();
265
+ websocket = resolved.config ? Object.assign(handler, resolved.config) : handler;
266
+ const setter = Object.getOwnPropertyDescriptor(handler, "~lifecycle")?.set;
267
+ if (setter) {
268
+ wsLifecycle = {
269
+ closing: false,
270
+ sockets: /* @__PURE__ */ new Set(),
271
+ run: runLifecycle.bind(null, epoch)
272
+ };
273
+ setter.call(handler, wsLifecycle);
274
+ }
137
275
  }
138
276
  return {
139
277
  fetch,
@@ -141,79 +279,296 @@ const BunAdapter = createAdapter({
141
279
  websocket
142
280
  };
143
281
  };
144
- let built;
145
- const server = app.server = Bun.serve(serve);
146
- const reload = () => {
282
+ let startupFailure;
283
+ let forceRequested = false;
284
+ const force = Promise.withResolvers();
285
+ const abandon = Promise.withResolvers();
286
+ let forceDone = false;
287
+ let nativeStopped = false;
288
+ let abandoned = false;
289
+ let published = false;
290
+ let cleanupCompleted = false;
291
+ let idleRequired = false;
292
+ let cleanupFailures;
293
+ let observedOutcome;
294
+ let persistentCleanup;
295
+ let persistentCleanupLength = -1;
296
+ const epochCleanup = [];
297
+ const createdExt = app["~ext"] === void 0;
298
+ const ext = app["~ext"] ??= nullObject();
299
+ const epoch = {
300
+ setup: false,
301
+ invoking: false
302
+ };
303
+ const snapshotCleanup = () => {
304
+ if (persistentCleanupLength !== -1) return;
305
+ persistentCleanup = ext.cleanup;
306
+ persistentCleanupLength = persistentCleanup?.length ?? 0;
307
+ };
308
+ const registerCleanup = (handler) => {
309
+ if (ext.cleanupEpoch !== registerCleanup) return false;
310
+ if (!epoch.setup) throw new Error("[Elysia] .cleanup() called after its setup epoch settled");
311
+ if (Array.isArray(handler)) epochCleanup.push(...handler);
312
+ else epochCleanup.push(handler);
313
+ return true;
314
+ };
315
+ const gate = () => {
316
+ if (!published) return;
317
+ live = void 0;
318
+ if (wsLifecycle) wsLifecycle.closing = true;
147
319
  try {
148
- server.reload(serve);
320
+ server.reload({
321
+ ...serve,
322
+ fetch: unavailableFetch,
323
+ error: unavailableFetch,
324
+ routes: {}
325
+ });
149
326
  } catch (error) {
150
- if (!serve.routes) throw error;
151
- delete serve.routes;
152
- console.warn("[Elysia] Native static promotion was skipped:", error);
153
- try {
154
- server.reload(serve);
155
- } catch (fallbackError) {
156
- console.error("[Elysia] Failed to reload Bun server:", fallbackError);
157
- throw fallbackError;
327
+ return { error };
328
+ }
329
+ };
330
+ const nativeStop = async (closeActiveConnections, errors) => {
331
+ try {
332
+ const stopping = server.stop(closeActiveConnections);
333
+ await (closeActiveConnections ? stopping : Promise.race([stopping, force.promise]));
334
+ if (!closeActiveConnections && forceRequested && !forceDone) return false;
335
+ nativeStopped = true;
336
+ if (closeActiveConnections) {
337
+ forceDone = true;
338
+ forceRequested = false;
339
+ }
340
+ return true;
341
+ } catch (error) {
342
+ if (closeActiveConnections) forceRequested = true;
343
+ errors.push(error);
344
+ return false;
345
+ }
346
+ };
347
+ const isAbandoned = () => abandoned;
348
+ const quiesce = async (force) => {
349
+ const errors = [];
350
+ if (!published) return {
351
+ errors,
352
+ releasable: await nativeStop(true, errors),
353
+ safe: true
354
+ };
355
+ if (force && !idleRequired && !wsLifecycle?.closing) {
356
+ const stopped = await nativeStop(true, errors);
357
+ return {
358
+ errors,
359
+ releasable: stopped,
360
+ safe: stopped
361
+ };
362
+ }
363
+ const gateFailure = gate();
364
+ if (gateFailure) errors.push(gateFailure.error);
365
+ let socketsSettled = await settleServerWebSockets(wsLifecycle, errors);
366
+ await Promise.resolve();
367
+ let close = forceRequested || gateFailure !== void 0 || !socketsSettled;
368
+ if (!close && nativeStopped) await waitForServerRequests(server, isAbandoned);
369
+ idleRequired = true;
370
+ let stopped = true;
371
+ while (!nativeStopped || forceRequested && !forceDone) {
372
+ if (nativeStopped) close = true;
373
+ stopped = await nativeStop(close, errors);
374
+ if (stopped) {
375
+ if (socketsSettled) socketsSettled = await settleServerWebSockets(wsLifecycle, errors);
376
+ continue;
377
+ }
378
+ if (close) break;
379
+ await waitForServerRequests(server, isAbandoned);
380
+ close = true;
381
+ }
382
+ let idleClosed = true;
383
+ if (idleRequired) {
384
+ const closeIdle = server.closeIdleConnections;
385
+ if (closeIdle) try {
386
+ closeIdle.call(server);
387
+ } catch (error) {
388
+ errors.push(error);
389
+ idleClosed = false;
158
390
  }
391
+ if (idleClosed && !gateFailure) idleRequired = false;
159
392
  }
393
+ const safe = socketsSettled && stopped && idleClosed && (!gateFailure || forceDone);
394
+ return {
395
+ errors,
396
+ releasable: safe,
397
+ safe
398
+ };
160
399
  };
161
400
  const setup = () => {
162
- const onSetup = app["~ext"]?.setup;
401
+ snapshotCleanup();
402
+ const onSetup = ext.setup;
163
403
  if (!onSetup) return;
164
- let pendingSetups;
404
+ epoch.setup = true;
405
+ ext.cleanupEpoch = registerCleanup;
165
406
  for (let i = 0; i < onSetup.length; i++) {
166
- const result = onSetup[i](app);
167
- if (result && typeof result.then === "function") (pendingSetups ??= []).push(result);
407
+ if (cancelled) break;
408
+ try {
409
+ const result = runLifecycle(epoch, onSetup[i], app);
410
+ if (result && typeof result.then === "function") (pendingSetups ??= []).push(Promise.resolve(result));
411
+ } catch (error) {
412
+ if (!pendingSetups) epoch.setup = false;
413
+ stop(true, { error }).catch(() => {});
414
+ throw error;
415
+ }
168
416
  }
169
- if (pendingSetups) return Promise.all(pendingSetups);
417
+ if (pendingSetups) {
418
+ setupsSettled = Promise.allSettled(pendingSetups);
419
+ return Promise.all(pendingSetups).then(() => epoch.setup = false);
420
+ }
421
+ epoch.setup = false;
170
422
  };
171
- const rollback = (error) => {
172
- if (app.server !== server) return;
173
- try {
174
- server.stop(true);
175
- } catch (stopError) {
176
- console.error(stopError);
177
- } finally {
178
- app.server = void 0;
179
- }
180
- const cleanup = app["~ext"]?.cleanup;
181
- if (cleanup) for (let i = cleanup.length - 1; i >= 0; i--) try {
182
- const result = cleanup[i](app);
183
- if (result && typeof result.then === "function") Promise.resolve(result).catch(console.error);
184
- } catch (cleanupError) {
185
- console.error(cleanupError);
186
- }
187
- return error;
423
+ const stop = (closeActiveConnections, failure) => {
424
+ const reentrant = epoch.invoking;
425
+ if (failure) startupFailure ??= failure;
426
+ if (closeActiveConnections === true) {
427
+ force.resolve();
428
+ if (!failure) abandon.resolve();
429
+ if (!forceDone) forceRequested = true;
430
+ }
431
+ cancelled = true;
432
+ requestReady.resolve();
433
+ if (app.server === server) app.server = void 0;
434
+ let outcome;
435
+ if (shutdownAttempt) {
436
+ if (closeActiveConnections === true && !forceDone) {
437
+ abandoned = true;
438
+ if (wsLifecycle) wsLifecycle.abandon = true;
439
+ }
440
+ outcome = shutdownAttempt;
441
+ } else {
442
+ const { promise, resolve, reject } = Promise.withResolvers();
443
+ outcome = shutdownAttempt = promise;
444
+ const quiescence = quiesce(forceRequested || !published);
445
+ let releasable = false;
446
+ let abandonedSetups;
447
+ (async () => {
448
+ try {
449
+ await Promise.resolve();
450
+ if (modulesReady) try {
451
+ await Promise.race([modulesReady, force.promise]);
452
+ } catch (error) {
453
+ startupFailure ??= { error };
454
+ }
455
+ if (setupsSettled) {
456
+ const setupResults = await Promise.race([setupsSettled, abandon.promise]);
457
+ if (!setupResults) abandonedSetups = setupsSettled;
458
+ else if (!startupFailure) for (let i = 0; i < setupResults.length; i++) {
459
+ const result = setupResults[i];
460
+ if (result.status === "rejected") {
461
+ startupFailure = { error: result.reason };
462
+ break;
463
+ }
464
+ }
465
+ }
466
+ epoch.setup = false;
467
+ const errors = [];
468
+ const quiesced = await quiescence;
469
+ if (startupFailure) errors.push(startupFailure.error);
470
+ errors.push(...quiesced.errors);
471
+ releasable = quiesced.releasable;
472
+ if (!quiesced.safe) {
473
+ if (cleanupFailures) errors.push(...cleanupFailures);
474
+ throwLifecycleErrors(errors);
475
+ }
476
+ if (!cleanupCompleted) {
477
+ snapshotCleanup();
478
+ if (ext.stop === stop) {
479
+ const length = persistentCleanupLength + epochCleanup.length;
480
+ for (let n = 0; n < length; n++) {
481
+ if (ext.stop !== stop) break;
482
+ const i = startupFailure ? length - 1 - n : n;
483
+ const handler = i < persistentCleanupLength ? persistentCleanup[i] : epochCleanup[i - persistentCleanupLength];
484
+ try {
485
+ await runLifecycle(epoch, handler, app);
486
+ } catch (error) {
487
+ (cleanupFailures ??= []).push(error);
488
+ }
489
+ }
490
+ }
491
+ cleanupCompleted = true;
492
+ epochCleanup.length = 0;
493
+ }
494
+ if (cleanupFailures) errors.push(...cleanupFailures);
495
+ const release = () => releaseLifecycle(app, ext, createdExt, stop, registerCleanup);
496
+ if (releasable && abandonedSetups) abandonedSetups.then((results) => {
497
+ for (const result of results) if (result.status === "rejected") console.error("[Elysia] setup abandoned by stop(true) failed:", result.reason);
498
+ release();
499
+ });
500
+ else if (releasable) release();
501
+ throwLifecycleErrors(errors);
502
+ } finally {
503
+ epoch.setup = false;
504
+ if (!releasable) shutdownAttempt = void 0;
505
+ }
506
+ })().then(resolve, reject);
507
+ }
508
+ if (!reentrant) return outcome;
509
+ if (observedOutcome !== outcome) {
510
+ observedOutcome = outcome;
511
+ outcome.catch((error) => {
512
+ console.error("[Elysia] stop() failed:", error);
513
+ });
514
+ }
515
+ return Promise.resolve();
188
516
  };
517
+ ext.stop = stop;
189
518
  const publish = () => {
190
- if (app.server !== server) return;
191
- built ??= build();
192
- live = serve.fetch = withOrigin(built.fetch);
193
- if (built.websocket) serve.websocket = built.websocket;
194
- if (built.routes) serve.routes = built.routes[0];
195
- reload();
196
- if (callback) callback(server);
519
+ if (cancelled || app.server !== server) {
520
+ requestReady.resolve();
521
+ return;
522
+ }
523
+ try {
524
+ const built = build();
525
+ live = serve.fetch = withOrigin(built.fetch);
526
+ published = true;
527
+ if (built.websocket) serve.websocket = built.websocket;
528
+ if (built.routes) serve.routes = built.routes;
529
+ try {
530
+ server.reload(serve);
531
+ } catch (error) {
532
+ if (!serve.routes) throw error;
533
+ delete serve.routes;
534
+ console.warn("[Elysia] Native static promotion was skipped:", error);
535
+ try {
536
+ server.reload(serve);
537
+ } catch (fallbackError) {
538
+ console.error("[Elysia] Failed to reload Bun server:", fallbackError);
539
+ throw fallbackError;
540
+ }
541
+ }
542
+ if (callback) callback(server);
543
+ } catch (error) {
544
+ startupFailure ??= { error };
545
+ throw error;
546
+ }
547
+ requestReady.resolve();
197
548
  };
198
549
  const start = () => {
199
- if (app.server !== server) return;
550
+ modulesReady = void 0;
551
+ if (cancelled || app.server !== server) {
552
+ requestReady.resolve();
553
+ return;
554
+ }
200
555
  const setupReady = setup();
201
- if (setupReady && typeof setupReady.then === "function") return Promise.resolve(setupReady).then(publish);
556
+ if (setupReady) return setupReady.then(publish);
202
557
  publish();
203
558
  };
204
559
  try {
205
- if (app.pending) ready = app.modules.then(start);
206
- else ready = Promise.resolve().then(start);
207
- ready.catch((error) => {
560
+ const modules = modulesReady = app.modules;
561
+ const preload = preloadTypebox();
562
+ (preload ? Promise.all([modules, preload]) : modules).then(start).catch((error) => stop(true, { error })).catch((error) => {
208
563
  console.error("[Elysia] listen() failed:", error);
209
- return rollback(error);
564
+ if (typeof process !== "undefined") process.exitCode = 1;
210
565
  });
211
566
  } catch (error) {
212
- rollback(error);
567
+ stop(true, { error }).catch(console.error);
213
568
  throw error;
214
569
  }
215
570
  }
216
571
  });
217
572
 
218
573
  //#endregion
219
- export { BunAdapter, collectStaticRoutes };
574
+ export { BunAdapter, collectHTMLBundleRoutes, collectStaticRoutes, isHTMLBundle };