elysia 2.0.0-beta.2 → 2.0.0-beta.20

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 (337) 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 +11 -13
  25. package/dist/compile/aot.js +34 -46
  26. package/dist/compile/aot.mjs +35 -45
  27. package/dist/compile/handler/descriptor.d.ts +9 -12
  28. package/dist/compile/handler/descriptor.js +17 -41
  29. package/dist/compile/handler/descriptor.mjs +18 -39
  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 +6 -5
  34. package/dist/compile/handler/index.js +148 -109
  35. package/dist/compile/handler/index.mjs +149 -111
  36. package/dist/compile/handler/jit.d.ts +17 -17
  37. package/dist/compile/handler/jit.js +220 -148
  38. package/dist/compile/handler/jit.mjs +222 -151
  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 +4 -3
  44. package/dist/compile/handler/reconstruct.mjs +4 -3
  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 +1 -0
  66. package/dist/cookie/config.js +9 -9
  67. package/dist/cookie/config.mjs +9 -9
  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 +47 -60
  108. package/dist/plugin/aot/core.js +172 -109
  109. package/dist/plugin/aot/core.mjs +169 -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 +47 -62
  122. package/dist/plugin/aot/source.mjs +48 -63
  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 +29 -47
  139. package/dist/schema-snapshot.mjs +29 -47
  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 +2 -6
  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/constants.d.ts +1 -1
  162. package/dist/type/elysia/array-buffer.d.ts +4 -1
  163. package/dist/type/elysia/array-buffer.js +17 -17
  164. package/dist/type/elysia/array-buffer.mjs +17 -17
  165. package/dist/type/elysia/array-string.js +2 -40
  166. package/dist/type/elysia/array-string.mjs +2 -39
  167. package/dist/type/elysia/array.js +5 -9
  168. package/dist/type/elysia/array.mjs +5 -9
  169. package/dist/type/elysia/boolean-string.js +2 -3
  170. package/dist/type/elysia/boolean-string.mjs +1 -1
  171. package/dist/type/elysia/boolean.js +3 -12
  172. package/dist/type/elysia/boolean.mjs +3 -11
  173. package/dist/type/elysia/cookie.d.ts +3 -4
  174. package/dist/type/elysia/cookie.js +5 -15
  175. package/dist/type/elysia/cookie.mjs +5 -15
  176. package/dist/type/elysia/date.js +13 -20
  177. package/dist/type/elysia/date.mjs +10 -16
  178. package/dist/type/elysia/file-type.d.ts +11 -4
  179. package/dist/type/elysia/file-type.js +17 -2
  180. package/dist/type/elysia/file-type.mjs +17 -3
  181. package/dist/type/elysia/file.d.ts +1 -3
  182. package/dist/type/elysia/file.js +11 -27
  183. package/dist/type/elysia/file.mjs +11 -12
  184. package/dist/type/elysia/files.js +7 -11
  185. package/dist/type/elysia/files.mjs +7 -10
  186. package/dist/type/elysia/form.js +2 -3
  187. package/dist/type/elysia/form.mjs +3 -3
  188. package/dist/type/elysia/integer-string.d.ts +1 -1
  189. package/dist/type/elysia/integer-string.js +4 -30
  190. package/dist/type/elysia/integer-string.mjs +5 -30
  191. package/dist/type/elysia/integer.js +3 -12
  192. package/dist/type/elysia/integer.mjs +3 -11
  193. package/dist/type/elysia/intersect.js +0 -5
  194. package/dist/type/elysia/intersect.mjs +0 -5
  195. package/dist/type/elysia/json-string.d.ts +7 -0
  196. package/dist/type/elysia/json-string.js +47 -0
  197. package/dist/type/elysia/json-string.mjs +46 -0
  198. package/dist/type/elysia/maybe-empty.js +3 -4
  199. package/dist/type/elysia/maybe-empty.mjs +1 -1
  200. package/dist/type/elysia/nullable.js +2 -3
  201. package/dist/type/elysia/nullable.mjs +1 -1
  202. package/dist/type/elysia/number.d.ts +2 -1
  203. package/dist/type/elysia/number.js +19 -11
  204. package/dist/type/elysia/number.mjs +18 -10
  205. package/dist/type/elysia/numeric-enum.d.ts +1 -1
  206. package/dist/type/elysia/numeric-enum.js +4 -5
  207. package/dist/type/elysia/numeric-enum.mjs +3 -3
  208. package/dist/type/elysia/numeric.d.ts +4 -2
  209. package/dist/type/elysia/numeric.js +20 -17
  210. package/dist/type/elysia/numeric.mjs +19 -16
  211. package/dist/type/elysia/object-string.js +2 -37
  212. package/dist/type/elysia/object-string.mjs +2 -36
  213. package/dist/type/elysia/object.js +5 -9
  214. package/dist/type/elysia/object.mjs +5 -9
  215. package/dist/type/elysia/optional.js +8 -8
  216. package/dist/type/elysia/optional.mjs +7 -7
  217. package/dist/type/elysia/problem.d.ts +20 -0
  218. package/dist/type/elysia/problem.js +25 -0
  219. package/dist/type/elysia/problem.mjs +24 -0
  220. package/dist/type/elysia/string.js +4 -3
  221. package/dist/type/elysia/string.mjs +4 -2
  222. package/dist/type/elysia/uint8-array.d.ts +1 -1
  223. package/dist/type/elysia/uint8-array.js +5 -20
  224. package/dist/type/elysia/uint8-array.mjs +5 -19
  225. package/dist/type/elysia/union-enum.js +7 -8
  226. package/dist/type/elysia/union-enum.mjs +6 -6
  227. package/dist/type/elysia/union.js +0 -5
  228. package/dist/type/elysia/union.mjs +0 -5
  229. package/dist/type/elysia/utils.d.ts +2 -4
  230. package/dist/type/elysia/utils.js +10 -21
  231. package/dist/type/elysia/utils.mjs +7 -15
  232. package/dist/type/exports.d.ts +3 -2
  233. package/dist/type/exports.js +13 -2
  234. package/dist/type/exports.mjs +10 -2
  235. package/dist/type/index.d.ts +10 -2
  236. package/dist/type/index.js +52 -15
  237. package/dist/type/index.mjs +55 -11
  238. package/dist/type/shared.d.ts +3 -9
  239. package/dist/type/shared.js +44 -97
  240. package/dist/type/shared.mjs +43 -97
  241. package/dist/type/sync-require.d.ts +11 -0
  242. package/dist/type/sync-require.js +14 -0
  243. package/dist/type/sync-require.mjs +12 -0
  244. package/dist/type/typebox-system-lite.d.ts +2 -0
  245. package/dist/type/typebox-system-lite.js +34 -0
  246. package/dist/type/typebox-system-lite.mjs +3 -0
  247. package/dist/type/typebox-system-require.d.ts +7 -0
  248. package/dist/type/typebox-system-require.js +24 -0
  249. package/dist/type/typebox-system-require.mjs +23 -0
  250. package/dist/type/typebox-type-live.d.ts +11 -0
  251. package/dist/type/typebox-type-live.js +37 -0
  252. package/dist/type/typebox-type-live.mjs +20 -0
  253. package/dist/type/typebox-type.d.ts +26 -0
  254. package/dist/type/typebox-type.js +135 -0
  255. package/dist/type/typebox-type.mjs +70 -0
  256. package/dist/type/typebox-value-live.d.ts +11 -0
  257. package/dist/type/typebox-value-live.js +31 -0
  258. package/dist/type/typebox-value-live.mjs +13 -0
  259. package/dist/type/typebox-value-ops.d.ts +4 -0
  260. package/dist/type/typebox-value-ops.js +90 -0
  261. package/dist/type/typebox-value-ops.mjs +5 -0
  262. package/dist/type/typebox-value-require.d.ts +8 -0
  263. package/dist/type/typebox-value-require.js +28 -0
  264. package/dist/type/typebox-value-require.mjs +25 -0
  265. package/dist/type/typebox-value.d.ts +35 -0
  266. package/dist/type/typebox-value.js +161 -0
  267. package/dist/type/typebox-value.mjs +74 -0
  268. package/dist/type/utils.js +1 -10
  269. package/dist/type/utils.mjs +1 -10
  270. package/dist/type/validator/clean-safe.d.ts +2 -4
  271. package/dist/type/validator/clean-safe.js +15 -11
  272. package/dist/type/validator/clean-safe.mjs +16 -10
  273. package/dist/type/validator/custom-error.js +12 -16
  274. package/dist/type/validator/custom-error.mjs +11 -14
  275. package/dist/type/validator/default-precompute.d.ts +9 -1
  276. package/dist/type/validator/default-precompute.js +40 -77
  277. package/dist/type/validator/default-precompute.mjs +37 -74
  278. package/dist/type/validator/exact-mirror-live.d.ts +8 -0
  279. package/dist/type/validator/exact-mirror-live.js +22 -0
  280. package/dist/type/validator/exact-mirror-live.mjs +17 -0
  281. package/dist/type/validator/exact-mirror-require.d.ts +4 -0
  282. package/dist/type/validator/exact-mirror-require.js +11 -0
  283. package/dist/type/validator/exact-mirror-require.mjs +9 -0
  284. package/dist/type/validator/exact-mirror.js +8 -8
  285. package/dist/type/validator/exact-mirror.mjs +9 -8
  286. package/dist/type/validator/frozen-check.js +5 -6
  287. package/dist/type/validator/frozen-check.mjs +6 -7
  288. package/dist/type/validator/index.d.ts +1 -0
  289. package/dist/type/validator/index.js +169 -166
  290. package/dist/type/validator/index.mjs +162 -158
  291. package/dist/type/validator/string-codec-aot.d.ts +2 -1
  292. package/dist/type/validator/string-codec-aot.js +8 -2
  293. package/dist/type/validator/string-codec-aot.mjs +7 -2
  294. package/dist/type/validator/validator-cache.d.ts +5 -4
  295. package/dist/type/validator/validator-cache.js +41 -24
  296. package/dist/type/validator/validator-cache.mjs +40 -22
  297. package/dist/types.d.ts +261 -94
  298. package/dist/universal/constants.d.ts +2 -1
  299. package/dist/universal/constants.js +3 -1
  300. package/dist/universal/constants.mjs +2 -1
  301. package/dist/universal/env.js +2 -3
  302. package/dist/universal/env.mjs +2 -3
  303. package/dist/universal/file.d.ts +6 -4
  304. package/dist/universal/file.js +11 -16
  305. package/dist/universal/file.mjs +12 -16
  306. package/dist/universal/index.d.ts +2 -2
  307. package/dist/universal/is-production.d.ts +1 -2
  308. package/dist/universal/is-production.js +1 -3
  309. package/dist/universal/is-production.mjs +2 -3
  310. package/dist/universal/server.d.ts +0 -272
  311. package/dist/utils.d.ts +41 -7
  312. package/dist/utils.js +158 -126
  313. package/dist/utils.mjs +147 -126
  314. package/dist/validator/index.d.ts +1 -1
  315. package/dist/validator/index.js +17 -30
  316. package/dist/validator/index.mjs +18 -31
  317. package/dist/validator/route.js +2 -1
  318. package/dist/validator/route.mjs +2 -1
  319. package/dist/ws/context.d.ts +8 -1
  320. package/dist/ws/context.js +68 -44
  321. package/dist/ws/context.mjs +67 -44
  322. package/dist/ws/parser.js +10 -20
  323. package/dist/ws/parser.mjs +10 -20
  324. package/dist/ws/route.d.ts +2 -2
  325. package/dist/ws/route.js +219 -139
  326. package/dist/ws/route.mjs +223 -143
  327. package/dist/ws/types.d.ts +2 -2
  328. package/package.json +23 -49
  329. package/dist/compile/analysis-cache.d.ts +0 -6
  330. package/dist/compile/analysis-cache.js +0 -12
  331. package/dist/compile/analysis-cache.mjs +0 -11
  332. package/dist/cookie/index.d.ts +0 -7
  333. package/dist/cookie/index.js +0 -13
  334. package/dist/cookie/index.mjs +0 -7
  335. package/dist/handler/index.d.ts +0 -2
  336. package/dist/handler/index.js +0 -5
  337. package/dist/handler/index.mjs +0 -3
@@ -1,10 +1,10 @@
1
- import { isStandardSchema, mergeSchemasAllStandard } from "../../compile/handler/frozen-validator.mjs";
1
+ import { REQUEST_SLOTS, isResponseMap, isStandardSchema, mergeSchemasAllStandard, resolveModelRef } from "../../compile/handler/frozen-validator.mjs";
2
2
  import { composeRouteHook } from "../../compile/handler/index.mjs";
3
3
  import { captureArtifacts, compileToSource, replayStubbability } from "./source.mjs";
4
4
  import { createRequire } from "node:module";
5
- import { existsSync, realpathSync } from "node:fs";
6
- import { dirname, join, resolve } from "node:path";
7
- import { pathToFileURL } from "node:url";
5
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
6
+ import { dirname, extname, join, resolve } from "node:path";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
8
  import { Worker } from "node:worker_threads";
9
9
 
10
10
  //#region src/plugin/aot/core.ts
@@ -18,8 +18,31 @@ function findPackageRoot(from = process.cwd()) {
18
18
  return dir;
19
19
  }
20
20
  const resolveEntry = (entry) => resolve(findPackageRoot(), entry);
21
+ /** @internal Resolve the package condition used to evaluate an AOT entry. */
22
+ const resolveEntryModuleKind = (entry) => {
23
+ const entryPath = resolveEntry(entry);
24
+ switch (extname(entryPath)) {
25
+ case ".cjs":
26
+ case ".cts": return "cjs";
27
+ case ".mjs":
28
+ case ".mts":
29
+ case ".ts":
30
+ case ".tsx": return "esm";
31
+ case ".js":
32
+ case ".jsx": {
33
+ const packagePath = join(findPackageRoot(dirname(entryPath)), "package.json");
34
+ if (!existsSync(packagePath)) return "cjs";
35
+ const pkg = JSON.parse(readFileSync(packagePath, "utf8"));
36
+ if (pkg.type === "module") return "esm";
37
+ if (pkg.type === void 0 || pkg.type === "commonjs") return "cjs";
38
+ throw new Error(`[elysia-aot] package.json has unsupported "type" ${JSON.stringify(pkg.type)} for JavaScript entry ${JSON.stringify(entryPath)}.`);
39
+ }
40
+ default: throw new Error(`[elysia-aot] entry ${JSON.stringify(entryPath)} has an ambiguous module condition. Use a .cjs/.cts CommonJS entry or a .mjs/.mts/.ts/.tsx ESM entry; .js/.jsx follows the nearest package.json "type".`);
41
+ }
42
+ };
21
43
  const NO_STUB = {
22
44
  jit: false,
45
+ staticClone: false,
23
46
  ws: false,
24
47
  reconstruct: false,
25
48
  cookie: false,
@@ -27,6 +50,8 @@ const NO_STUB = {
27
50
  sucrose: false,
28
51
  compat: false,
29
52
  bridge: false,
53
+ typeboxValue: false,
54
+ exactMirror: false,
30
55
  adapter: false,
31
56
  isProduction: false
32
57
  };
@@ -47,20 +72,23 @@ const NO_STUB = {
47
72
  * is not active, so the bridge must stay wired the ordinary way. No compat
48
73
  * stub, no reroute.
49
74
  */
50
- function planFromReport(strip, report, hasWS, mayTrace, aliases, allBridgeFree, zeroCapture, adapterStub = false, productionStub = true) {
75
+ function planFromReport(strip, report, hasWS, mayTrace, aliases, allBridgeFree, zeroCapture, adapterStub = false, productionStub = true, wsCookie = false, exactMirror = false) {
51
76
  const jit = report.jit;
52
77
  if (strip === true && !jit) throw new Error(`[elysia-aot] strip: true requires every route to be covered by the AOT handler manifest, but handler JIT is still reachable (${report.reasons.join(", ") || "unknown"}). Use strip: 'auto' to skip stubbing when the app is not fully precompiled.`);
53
78
  const mode = !jit ? "off" : allBridgeFree ? "sealed" : hasWS && zeroCapture ? "off" : "wired";
54
79
  return {
55
80
  plan: {
56
81
  jit,
82
+ staticClone: jit && !aliases.has("scl"),
57
83
  ws: !hasWS,
58
84
  reconstruct: jit && !aliases.has("va") && !aliases.has("cc") && !aliases.has("tr"),
59
- cookie: jit && !aliases.has("cc"),
85
+ cookie: jit && !aliases.has("cc") && !wsCookie,
60
86
  trace: !aliases.has("tr") && (jit || !mayTrace),
61
87
  sucrose: jit,
62
88
  compat: mode !== "off",
63
89
  bridge: mode === "wired",
90
+ typeboxValue: mode !== "sealed",
91
+ exactMirror: exactMirror && mode !== "sealed",
64
92
  adapter: adapterStub,
65
93
  isProduction: productionStub
66
94
  },
@@ -71,71 +99,48 @@ function adapterConstantsSource(target) {
71
99
  if (target === "bun") return "import { BunAdapter } from './bun/index'\nexport const defaultAdapter = BunAdapter\n";
72
100
  return "import { WebStandardAdapter } from './web-standard/index'\nexport const defaultAdapter = WebStandardAdapter\n";
73
101
  }
74
- /** Filter matching elysia's own `adapter/constants` module (src + dist). */
75
102
  const ADAPTER_CONSTANTS_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]adapter[\\/]constants\.(m?js|ts)$/;
76
103
  const ADAPTER_BUN_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]adapter[\\/]bun[\\/]index\.(m?js|ts)$/;
77
104
  const IS_PRODUCTION_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]universal[\\/]is-production\.(m?js|ts)$/;
78
- /**
79
- * Loose fallback filter
80
- *
81
- * Matches the `/elysia/(dist|src)/` segment anywhere in a path (node_modules layouts,
82
- * monorepos, linked installs). Used by esbuild as a broad pre-filter
83
- *
84
- * The caller must further check that the path is under the resolved elysia package root
85
- * to avoid matching user code in a directory that happens to be named "elysia"
86
- *
87
- * @internal
88
- */
105
+ const TYPEBOX_TYPE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-type\.(m?js|ts)$/;
106
+ const TYPEBOX_SYSTEM_LITE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-system-lite\.(m?js|ts)$/;
107
+ const TYPEBOX_REQUIRE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-value-require\.(m?js|ts)$/;
108
+ const EXACT_MIRROR_REQUIRE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]validator[\\/]exact-mirror-require\.(m?js|ts)$/;
89
109
  const ELYSIA_MODULE_FILTER = /[\\/]elysia[\\/](dist|src)[\\/].+\.(m?js|ts)x?$/;
90
- /**
91
- * Build a predicate that returns `true` only for modules that are under the
92
- * resolved elysia package root (i.e. actually elysia's own files).
93
- *
94
- * Anchoring to the real package root prevents user projects rooted in a
95
- * directory named `elysia` (like this repo itself) from having their code
96
- * rewritten.
97
- *
98
- * Pass the result to both the esbuild `filter` (convert to RegExp via
99
- * `makeElysiaModuleFilterRegex`) and the Vite transform (`isElysiaModule`).
100
- */
101
- function resolveElysiaRoot(from = process.cwd()) {
110
+ function resolveElysiaRoot(from) {
102
111
  try {
103
112
  return dirname(createRequire(join(from, "package.json")).resolve("elysia/package.json"));
104
113
  } catch {
105
114
  return from;
106
115
  }
107
116
  }
108
- /**
109
- * Returns a predicate that is `true` only when the given module path is under
110
- * the resolved elysia package root AND matches the broad module filter.
111
- */
117
+ function resolveExactMirror(from) {
118
+ try {
119
+ createRequire(join(resolveElysiaRoot(from), "package.json")).resolve("exact-mirror");
120
+ return true;
121
+ } catch {
122
+ return false;
123
+ }
124
+ }
112
125
  function makeIsElysiaModule(elysiaRoot) {
113
126
  const root = elysiaRoot.replace(/\\/g, "/");
114
127
  return (path) => {
115
128
  return path.replace(/\\/g, "/").startsWith(root + "/") && ELYSIA_MODULE_FILTER.test(path);
116
129
  };
117
130
  }
118
- /**
119
- * Build an esbuild-compatible RegExp that anchors to the resolved elysia root
120
- * so the `onLoad` pre-filter is as tight as possible. esbuild uses this as an
121
- * initial path filter before calling the callback, so we still double-check
122
- * with `makeIsElysiaModule` inside the callback.
123
- */
124
- function makeElysiaModuleFilterRegex(elysiaRoot) {
125
- const escaped = elysiaRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
126
- return new RegExp("^" + escaped + "[\\\\/](dist|src)[\\\\/].+\\.(m?js|ts)x?$");
127
- }
128
- function rewriteIsProductionCalls(code) {
129
- return code.replace(/(?<![.?])\bisProduction\(\)/g, "true");
130
- }
131
- const bunAdapterStubSource = "const e=(t)=>{throw new Error(`[elysia-aot] Bun adapter was stripped for target 'web-standard' .listen() is unavailable; use the exported fetch handler or rebuild with a different target.`)}\nexport const BunAdapter={name:'bun',runtime:'bun',isWebStandard:true,parse:{},response:{},listen:e}\nexport function collectStaticRoutes(){}\n";
131
+ const rewriteIsProductionCalls = (code) => code.replace(/(?<![.?])\bisProduction\(\)/g, "true");
132
+ const bunAdapterStubSource = "const e=(t)=>{throw new Error(`[elysia-aot] Bun adapter was stripped for target 'web-standard' .listen() is unavailable; use the exported fetch handler or rebuild with a different target.`)}\nexport const BunAdapter={parse:{},response:{},listen:e}\nexport function collectStaticRoutes(){}\n";
132
133
  const STUB_SOURCES = {
134
+ staticClone: [{
135
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]static-clone-resolver\.(m?js|ts)$/,
136
+ source: `export const staticCloneResolver = undefined\n`
137
+ }],
133
138
  jit: [{
134
139
  filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]jit\.(m?js|ts)$/,
135
140
  source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function compileHandlerJit(){return e()}\nexport function createInlineHandler(){return e()}\nexport function setCaptureHeaderShorthand(){}\n"
136
141
  }, {
137
142
  filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]descriptor\.(m?js|ts)$/,
138
- source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function describeRoute(){return e()}\nexport const routeDescriptors=new WeakMap()\nexport function isEmptyPipelineHook(hook){\n if(!hook)return true\n for(const key in hook){\n if(key==='detail'||key==='tags')continue\n const value=hook[key]\n if(value!==undefined&&value!==false&&(!Array.isArray(value)||value.length))return false\n }\n return true\n}\n"
143
+ source: "const e=()=>{throw new Error(\"[elysia-aot] handler compiler JIT was stripped (strip mode) but a route needed runtime compilation. Rebuild with strip:false.\")}\nexport function describeRoute(){return e()}\nexport const routeDescriptors=new WeakMap()\n"
139
144
  }],
140
145
  ws: [{
141
146
  filter: /[\\/]elysia[\\/](dist|src)[\\/]ws[\\/]route\.(m?js|ts)$/,
@@ -145,13 +150,20 @@ const STUB_SOURCES = {
145
150
  filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]handler[\\/]reconstruct\.(m?js|ts)$/,
146
151
  source: "const e=()=>{throw new Error(\"[elysia-aot] handler reconstruction was stripped (strip mode) but a route needed it. Rebuild with strip:false.\")}\nexport class Reconstrct {\n static validator(){return e()}\n static cookie(){return e()}\n static trace(){return e()}\n}\n"
147
152
  }],
148
- cookie: [{
149
- filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]utils\.(m?js|ts)$/,
150
- source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport const hasSyncHmac=false\nexport function parseCookie(){return e()}\nexport function parseCookieRaw(){return e()}\nexport function parseCookieRawSync(){return e()}\nexport function parseCookieRawSigned(){return e()}\nexport function parseCookieRawLazy(){return e()}\nexport function parseCookieRawDeferred(){return e()}\nexport function buildCookieJar(){return e()}\nexport function signCookieValues(){return e()}\nexport function signCookie(){return e()}\nexport function signCookieSubtle(){return e()}\nexport function signCookieSync(){return e()}\nexport function unsignCookie(){return e()}\nexport function unsignCookieSync(){return e()}\n"
151
- }, {
152
- filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]config\.(m?js|ts)$/,
153
- source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport function compileCookieConfig(){return e()}\nexport function isCookieSigned(){return e()}\n"
154
- }],
153
+ cookie: [
154
+ {
155
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]crypto\.(m?js|ts)$/,
156
+ source: `export function resolvePendingCookie(){throw new Error("[elysia-aot] cookie support was stripped (strip mode) but a signed cookie was read. Rebuild with strip:false.")}\n`
157
+ },
158
+ {
159
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]utils\.(m?js|ts)$/,
160
+ source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport const hasSyncHmac=false\nexport function parseCookieRaw(){return e()}\nexport function parseCookieRawSync(){return e()}\nexport function parseCookieRawSigned(){return e()}\nexport function parseCookieRawLazy(){return e()}\nexport function parseCookieRawDeferred(){return e()}\nexport function buildCookieJar(){return e()}\nexport function signCookieValues(){return e()}\n"
161
+ },
162
+ {
163
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]cookie[\\/]config\.(m?js|ts)$/,
164
+ source: "const e=()=>{throw new Error(\"[elysia-aot] cookie support was stripped (strip mode) but a route used cookies. Rebuild with strip:false.\")}\nexport function compileCookieConfig(){return e()}\n"
165
+ }
166
+ ],
155
167
  trace: [{
156
168
  filter: /[\\/]elysia[\\/](dist|src)[\\/]trace\.(m?js|ts)$/,
157
169
  source: "const e=()=>{throw new Error(\"[elysia-aot] trace support was stripped (strip mode) but a route used trace. Rebuild with strip:false.\")}\nexport function createTracer(){return e()}\nexport function unionTracePhases(){return new Set()}\n"
@@ -159,9 +171,6 @@ const STUB_SOURCES = {
159
171
  sucrose: [{
160
172
  filter: /[\\/]elysia[\\/](dist|src)[\\/]memory\.(m?js|ts)$/,
161
173
  source: "import { clearContextCache } from './context'\nimport { Validator } from './validator'\nexport function flushMemory() {\n clearContextCache()\n Validator.clear()\n}\n"
162
- }, {
163
- filter: /[\\/]elysia[\\/](dist|src)[\\/]compile[\\/]analysis-cache\.(m?js|ts)$/,
164
- source: "import { clearHandlerAnalysisCaches } from './handler/index'\nimport { clearFlattenChainMemo } from '../utils'\nexport function clearAuthoringAnalysisCaches(root) {\n clearHandlerAnalysisCaches(root)\n clearFlattenChainMemo(root)\n}\n"
165
174
  }],
166
175
  compat: [{
167
176
  filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]compat\.(m?js|ts)$/,
@@ -170,11 +179,23 @@ const STUB_SOURCES = {
170
179
  bridge: [{
171
180
  filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]bridge\.(m?js|ts)$/,
172
181
  source: `export * from './bridge-live'\n`
182
+ }],
183
+ typeboxValue: [{
184
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]typebox-value\.(m?js|ts)$/,
185
+ source: `export * from './typebox-value-live'\n`
186
+ }],
187
+ exactMirror: [{
188
+ filter: /[\\/]elysia[\\/](dist|src)[\\/]type[\\/]validator[\\/]exact-mirror\.(m?js|ts)$/,
189
+ source: `export * from './exact-mirror-live'\n`
173
190
  }]
174
191
  };
175
192
  const alignStubExtensions = (stubSource, targetPath) => {
176
193
  const ext = targetPath.slice(targetPath.lastIndexOf("."));
177
194
  if (ext !== ".mjs" && ext !== ".js" && ext !== ".cjs") return stubSource;
195
+ if (ext !== ".mjs") {
196
+ const reexport = /^export \* from '(\.[^']+)'\n$/.exec(stubSource);
197
+ if (reexport) return `let m;const t=()=>m??=require('${reexport[1]}${ext}'),d=(o,k)=>Reflect.getOwnPropertyDescriptor(o,k)\nmodule.exports=new Proxy({},{get:(_,k)=>t()[k],has:(_,k)=>k in t(),ownKeys:()=>Reflect.ownKeys(t()),getOwnPropertyDescriptor:(o,k)=>{let x=d(o,k);if(x)return x;x=d(t(),k);if(x)x.configurable=true;return x},preventExtensions:o=>{for(const k of Reflect.ownKeys(t()))Object.defineProperty(o,k,d(t(),k));return Reflect.preventExtensions(o)}})\n`;
198
+ }
178
199
  return stubSource.replace(/(from ')(\.[^']+)(')/g, (_m, open, spec, close) => open + (spec === "./validator" ? spec + "/index" : spec) + ext + close);
179
200
  };
180
201
  const OVERRIDE_MAP = {
@@ -270,6 +291,10 @@ const OVERRIDE_MAP = {
270
291
  leaf: "optional",
271
292
  export: "Optional"
272
293
  },
294
+ Problem: {
295
+ leaf: "problem",
296
+ export: "Problem"
297
+ },
273
298
  String: {
274
299
  leaf: "string",
275
300
  export: "StringType"
@@ -288,17 +313,20 @@ const OVERRIDE_MAP = {
288
313
  }
289
314
  };
290
315
  const requireFromHere = createRequire(import.meta.url);
291
- const resolveSpecifier = (specifier) => {
292
- const meta = import.meta;
293
- if (typeof meta.resolve === "function") {
294
- const url = meta.resolve(specifier);
295
- return url.startsWith("file://") ? new URL(url).pathname : url;
316
+ const moduleMeta = import.meta;
317
+ const loadedModuleCondition = import.meta.url.endsWith(".js") ? "cjs" : "esm";
318
+ const resolveSpecifier = (specifier, moduleCondition) => {
319
+ if (moduleCondition === "cjs") return requireFromHere.resolve(specifier);
320
+ if (moduleMeta.resolve) {
321
+ const url = moduleMeta.resolve(specifier);
322
+ return url.startsWith("file://") ? fileURLToPath(url) : url;
296
323
  }
324
+ if (moduleCondition === "esm") throw new Error("[elysia-aot] CommonJS-loaded build plugin cannot resolve the ESM package condition. Load the build plugin through import for an ESM entry.");
297
325
  return requireFromHere.resolve(specifier);
298
326
  };
299
- async function generateVirtualType(typeSpecifier = "elysia/type") {
300
- const typePath = resolveSpecifier(typeSpecifier);
301
- const typeboxPath = resolveSpecifier("typebox/type");
327
+ async function generateVirtualType(moduleCondition) {
328
+ const typePath = resolveSpecifier("elysia/type", moduleCondition);
329
+ const typeboxPath = resolveSpecifier("typebox/type", moduleCondition);
302
330
  const ext = typePath.slice(typePath.lastIndexOf("."));
303
331
  const leafDir = join(dirname(typePath), "elysia");
304
332
  const typebox = await import(pathToFileURL(typeboxPath).href);
@@ -314,13 +342,6 @@ async function generateVirtualType(typeSpecifier = "elysia/type") {
314
342
  return source;
315
343
  }
316
344
  const _importedEntries = /* @__PURE__ */ new Set();
317
- let activeGenerationWorkers = 0;
318
- let lastGenerationWorkerExit;
319
- /** @internal Test diagnostic for deterministic worker cleanup. */
320
- const getAotWorkerDiagnostics = () => ({
321
- activeWorkers: activeGenerationWorkers,
322
- lastExit: lastGenerationWorkerExit
323
- });
324
345
  /**
325
346
  * Extension mirroring the running module's own build output, so a sibling
326
347
  * source file can be resolved from `import.meta.url` in `.mjs`/`.js`/`.ts`
@@ -334,16 +355,15 @@ const workerUrl = () => {
334
355
  return new URL("./worker" + siblingModuleExt(moduleUrl), moduleUrl);
335
356
  };
336
357
  /** @internal Re-evaluate an entry in a disposable worker for watch rebuilds. */
337
- async function generateCompiledArtifactsIsolated(file, options) {
358
+ async function generateCompiledArtifactsIsolated(file, options, moduleCondition = resolveEntryModuleKind(file)) {
338
359
  const entry = resolveEntry(file);
339
360
  console.warn("[elysia-aot] re-evaluating \"" + entry + "\" in an isolated worker for rebuild. Top-level side effects run only inside the worker.");
340
361
  const worker = new Worker(workerUrl(), { workerData: {
341
362
  file: entry,
342
- options
363
+ options,
364
+ moduleCondition
343
365
  } });
344
- activeGenerationWorkers++;
345
366
  const exit = new Promise((resolve) => worker.once("exit", resolve));
346
- lastGenerationWorkerExit = exit;
347
367
  try {
348
368
  return await new Promise((resolve, reject) => {
349
369
  let received = false;
@@ -365,19 +385,34 @@ async function generateCompiledArtifactsIsolated(file, options) {
365
385
  await worker.terminate();
366
386
  } finally {
367
387
  await exit;
368
- activeGenerationWorkers--;
369
388
  }
370
389
  }
371
390
  }
372
- function isStandardResponse(response) {
373
- if (response == null || typeof response !== "object") return false;
374
- if (isStandardSchema(response)) return true;
375
- if ("~kind" in response || "~elyAcl" in response) return false;
376
- const entries = Object.values(response);
377
- if (entries.length === 0) return false;
378
- return entries.every((v) => isStandardSchema(v));
391
+ const validatorSlotKey = ({ method, path, slot }) => `${method}\0${path}\0${slot}`;
392
+ /** @internal Exact logical-slot gate used by AOT mode selection. */
393
+ function validatorSlotSetsMatch(expected, captured) {
394
+ const expectedKeys = new Set(expected.map(validatorSlotKey));
395
+ const capturedKeys = new Set(captured.map(validatorSlotKey));
396
+ if (expectedKeys.size !== capturedKeys.size) return false;
397
+ for (const key of expectedKeys) if (!capturedKeys.has(key)) return false;
398
+ return true;
379
399
  }
380
- async function generateCompiledArtifacts(file, options) {
400
+ /**
401
+ * The manifest is one flat `method -> path` table with no per-app namespace,
402
+ * bound to whichever app builds a router first, so a mounted sub-app (a second
403
+ * Elysia building on its own schedule) is not representable
404
+ *
405
+ * refuse at build time rather than ship a coin flip
406
+ */
407
+ const assertNoMount = (app, entry) => {
408
+ const routes = app["~routes"];
409
+ const mounted = [];
410
+ for (const route of routes) if (route[2]?.["~mount"] && !mounted.includes(route[1])) mounted.push(route[1]);
411
+ if (!mounted.length) return;
412
+ throw new Error(`[elysia-aot] "${entry}" mounts a sub-app (${mounted.join(", ")}). AOT cannot compile a mounted sub-app. Compose with .use() instead of .mount(), or disable AOT plugin`);
413
+ };
414
+ async function generateCompiledArtifacts(file, options, moduleCondition = resolveEntryModuleKind(file)) {
415
+ if (moduleCondition !== loadedModuleCondition) throw new Error(`[elysia-aot] entry uses the ${moduleCondition === "cjs" ? "CommonJS \"require\"" : "ESM \"import\""} package condition, but the AOT build plugin was loaded through ${loadedModuleCondition === "cjs" ? "CommonJS \"require\"" : "ESM \"import\""}; entry: ${JSON.stringify(resolveEntry(file))}. Load the plugin through ${moduleCondition === "cjs" ? "require()" : "import"} so capture and generated registration share one Elysia module instance.`);
381
416
  const previousAotBuild = process.env.ELYSIA_AOT_BUILD;
382
417
  process.env.ELYSIA_AOT_BUILD = "1";
383
418
  const previousAotVerbose = process.env.ELYSIA_AOT_VERBOSE;
@@ -386,14 +421,15 @@ async function generateCompiledArtifacts(file, options) {
386
421
  try {
387
422
  const entry = resolveEntry(file);
388
423
  const entryReal = realPath(entry);
389
- if (_importedEntries.has(entryReal)) return generateCompiledArtifactsIsolated(file, options);
424
+ if (_importedEntries.has(entryReal)) return generateCompiledArtifactsIsolated(file, options, moduleCondition);
390
425
  _importedEntries.add(entryReal);
391
426
  const mod = await import(entry);
392
427
  const app = mod.app ?? mod.default;
393
428
  if (!app || typeof app.compile !== "function") throw new Error(`[elysia-aot] "${entry}" must export an Elysia app`);
394
429
  const typedApp = app;
430
+ assertNoMount(typedApp, entry);
395
431
  const sourceOptions = {
396
- register: true,
432
+ moduleCondition,
397
433
  registerFrom: options?.registerFrom,
398
434
  reconstructFrom: options?.reconstructFrom,
399
435
  lazy: options?.lazy,
@@ -402,10 +438,13 @@ async function generateCompiledArtifacts(file, options) {
402
438
  const strip = options?.strip ?? "auto";
403
439
  const adapterStub = options?.target === "bun" ? "bun" : options?.target === "node" || options?.target === "workerd" ? "web-standard" : false;
404
440
  const productionStub = options?.production !== false;
441
+ const exactMirror = resolveExactMirror(entry);
405
442
  if (strip === false) return {
406
443
  source: await compileToSource(typedApp, sourceOptions),
407
444
  stub: {
408
445
  ...NO_STUB,
446
+ typeboxValue: true,
447
+ exactMirror,
409
448
  adapter: adapterStub,
410
449
  isProduction: productionStub
411
450
  },
@@ -415,32 +454,51 @@ async function generateCompiledArtifacts(file, options) {
415
454
  const report = replayStubbability(typedApp, artifacts.handlers);
416
455
  const aliases = /* @__PURE__ */ new Set();
417
456
  for (const handler of artifacts.handlers) if (handler.alias) for (const name of handler.alias.split(",")) aliases.add(name);
418
- const hasWS = !!typedApp["~hasWS"] || !!typedApp["~routes"]?.some((route) => route?.[0] === "WS");
419
- const history = typedApp["~routes"] ?? [];
457
+ const history = typedApp["~routes"];
458
+ const hasWS = !!typedApp["~hasWS"] || history.some((route) => route[0] === "WS");
420
459
  const mayTrace = !!typedApp["~hasTrace"] || history.some((route) => (route?.[4])?.trace?.length || route?.[2]?.["~mount"]);
421
- let expectedSlots = 0;
460
+ const expectedSlots = [];
461
+ const declaredTypeBoxSlots = /* @__PURE__ */ new Set();
422
462
  let routesForbidSeal = false;
463
+ let wsCookie = false;
423
464
  for (const route of history) {
465
+ const method = route[0];
466
+ const path = route[1];
467
+ const expectTypeBoxSlot = (slot) => {
468
+ const identity = {
469
+ method,
470
+ path,
471
+ slot
472
+ };
473
+ const key = validatorSlotKey(identity);
474
+ if (declaredTypeBoxSlots.has(key)) routesForbidSeal = true;
475
+ else {
476
+ declaredTypeBoxSlots.add(key);
477
+ expectedSlots.push(identity);
478
+ }
479
+ };
424
480
  const [, , , instance, hook, appHook, inheritedChain, macroScope] = route;
425
481
  const hooks = composeRouteHook(instance, hook, appHook, inheritedChain, typedApp, macroScope);
482
+ if (method === "WS" && (hook?.cookie !== void 0 || hooks?.cookie !== void 0)) wsCookie = true;
426
483
  if (!hooks) continue;
427
484
  let routeHasTypeBoxDirectSlot = false;
428
- for (const slot of [
429
- "body",
430
- "query",
431
- "params",
432
- "headers",
433
- "cookie"
434
- ]) {
435
- const value = hooks[slot];
436
- if (value === void 0) continue;
437
- if (isStandardSchema(value)) continue;
485
+ const classify = (schema, slot) => {
486
+ if (schema === void 0) {
487
+ routesForbidSeal = true;
488
+ return;
489
+ }
490
+ if (isStandardSchema(schema)) return;
438
491
  routeHasTypeBoxDirectSlot = true;
439
- expectedSlots++;
492
+ expectTypeBoxSlot(slot);
493
+ };
494
+ for (const slot of REQUEST_SLOTS) {
495
+ const value = hooks[slot];
496
+ if (value !== void 0) classify(resolveModelRef(value, typedApp), slot);
440
497
  }
441
- if (hooks.response !== void 0 && !isStandardResponse(hooks.response)) {
442
- routeHasTypeBoxDirectSlot = true;
443
- expectedSlots++;
498
+ if (hooks.response !== void 0) {
499
+ const response = resolveModelRef(hooks.response, typedApp);
500
+ if (isResponseMap(response)) for (const status in response) classify(resolveModelRef(response[status], typedApp), `response:${status}`);
501
+ else classify(response, "response:200");
444
502
  }
445
503
  const mergeSchemas = hooks.schemas;
446
504
  if (Array.isArray(mergeSchemas) && mergeSchemas.length > 0) {
@@ -448,13 +506,13 @@ async function generateCompiledArtifacts(file, options) {
448
506
  }
449
507
  }
450
508
  if (typedApp["~config"]?.normalize === "typebox") routesForbidSeal = true;
451
- const frozenSlots = artifacts.validators.length;
452
- const { plan: stub, mode } = planFromReport(strip, report, hasWS, mayTrace, aliases, (artifacts.handlers.length > 0 || artifacts.validators.length > 0) && !routesForbidSeal && frozenSlots === expectedSlots && artifacts.validators.every((v) => v.bridgeFree === true), artifacts.handlers.length === 0 && artifacts.validators.length === 0, adapterStub, productionStub);
509
+ const validatorSlotsMatch = validatorSlotSetsMatch(expectedSlots, artifacts.validators);
510
+ const { plan: stub, mode } = planFromReport(strip, report, hasWS, mayTrace, aliases, (artifacts.handlers.length > 0 || artifacts.validators.length > 0) && !routesForbidSeal && validatorSlotsMatch && artifacts.validators.every((v) => v.bridgeFree === true), artifacts.handlers.length === 0 && artifacts.validators.length === 0, adapterStub, productionStub, wsCookie, exactMirror);
453
511
  if (options?.target === "workerd") {
454
512
  if (!report.jit) throw new Error(`[elysia-aot] target 'workerd' but handler JIT is still reachable (${report.reasons.join(", ") || "unknown"}). Every route must be captured into the AOT manifest.`);
455
- if (frozenSlots !== expectedSlots) console.warn(`[elysia-aot] target 'workerd': only ${frozenSlots}/${expectedSlots} validator slots were frozen unfrozen slots compile at runtime and will fail on workerd.`);
513
+ if (!validatorSlotsMatch) console.warn("[elysia-aot] target 'workerd': captured validator slots do not exactly match declared slots; unfrozen slots compile at runtime and will fail on workerd.");
456
514
  }
457
- const virtualType = mode === "off" ? void 0 : await generateVirtualType("elysia/type");
515
+ const virtualType = mode === "off" ? void 0 : await generateVirtualType(moduleCondition);
458
516
  return {
459
517
  source: artifacts.source,
460
518
  stub,
@@ -478,4 +536,4 @@ const realPath = (path) => {
478
536
  };
479
537
 
480
538
  //#endregion
481
- export { ADAPTER_BUN_FILTER, ADAPTER_CONSTANTS_FILTER, ELYSIA_MODULE_FILTER, IS_PRODUCTION_FILTER, NO_STUB, OVERRIDE_MAP, SOURCE_REGEX, STUB_SOURCES, adapterConstantsSource, alignStubExtensions, bunAdapterStubSource, generateCompiledArtifacts, generateCompiledArtifactsIsolated, generateVirtualType, getAotWorkerDiagnostics, makeElysiaModuleFilterRegex, makeIsElysiaModule, planFromReport, realPath, resolveElysiaRoot, resolveEntry, rewriteIsProductionCalls, siblingModuleExt };
539
+ export { ADAPTER_BUN_FILTER, ADAPTER_CONSTANTS_FILTER, ELYSIA_MODULE_FILTER, EXACT_MIRROR_REQUIRE_FILTER, IS_PRODUCTION_FILTER, NO_STUB, OVERRIDE_MAP, SOURCE_REGEX, STUB_SOURCES, TYPEBOX_REQUIRE_FILTER, TYPEBOX_SYSTEM_LITE_FILTER, TYPEBOX_TYPE_FILTER, adapterConstantsSource, alignStubExtensions, bunAdapterStubSource, generateCompiledArtifacts, generateCompiledArtifactsIsolated, generateVirtualType, makeIsElysiaModule, planFromReport, realPath, resolveElysiaRoot, resolveEntry, resolveEntryModuleKind, resolveExactMirror, rewriteIsProductionCalls, siblingModuleExt, validatorSlotSetsMatch };
@@ -28,7 +28,11 @@ let node_fs_promises = require("node:fs/promises");
28
28
  const aot = (entry, options) => ({
29
29
  name: "elysia-aot",
30
30
  async setup(build) {
31
- const hooks = require_plugin_aot_hooks.createAotPluginHooks(entry, options);
31
+ const entryPath = require_plugin_aot_core.resolveEntry(entry);
32
+ const moduleCondition = require_plugin_aot_core.resolveEntryModuleKind(entryPath);
33
+ if (build.initialOptions?.conditions?.includes("types")) throw new Error("[elysia-aot] esbuild conditions includes 'types'; this selects declaration files as runtime inputs. Remove the conflicting condition.");
34
+ if (moduleCondition === "cjs" && build.initialOptions?.conditions?.includes("import")) throw new Error("[elysia-aot] esbuild conditions includes 'import' for a CommonJS entry; this would load two Elysia module instances. Remove the conflicting condition.");
35
+ const hooks = require_plugin_aot_hooks.createAotPluginHooks(entry, options, moduleCondition);
32
36
  let initial = true;
33
37
  build.onStart(async () => {
34
38
  if (initial) {
@@ -37,10 +41,9 @@ const aot = (entry, options) => ({
37
41
  }
38
42
  await hooks.buildStart();
39
43
  });
40
- await require_plugin_aot_hooks.setupAotOnLoad(build, hooks, {
41
- readText: (path) => (0, node_fs_promises.readFile)(path, "utf8"),
42
- resolveDir: (0, node_path.dirname)(require_plugin_aot_core.resolveEntry(entry))
43
- });
44
+ await require_plugin_aot_hooks.setupAotOnLoad(build, hooks, (path) => (0, node_fs_promises.readFile)(path, "utf8"), (0, node_path.dirname)(entryPath));
45
+ const allowedKinds = moduleCondition === "cjs" ? new Set(["require-call", "require-resolve"]) : new Set(["import-statement", "dynamic-import"]);
46
+ build.onResolve({ filter: /^elysia(?:\/.*)?$/ }, (args) => allowedKinds.has(args.kind) ? void 0 : { errors: [{ text: `[elysia-aot] ${args.path} uses esbuild edge kind ${JSON.stringify(args.kind)}, which conflicts with the ${JSON.stringify(moduleCondition)} entry module condition. Use one consistent import/require condition for Elysia.` }] });
44
47
  }
45
48
  });
46
49
 
@@ -1,4 +1,4 @@
1
- import { resolveEntry } from "./core.mjs";
1
+ import { resolveEntry, resolveEntryModuleKind } from "./core.mjs";
2
2
  import { createAotPluginHooks, setupAotOnLoad } from "./hooks.mjs";
3
3
  import { dirname } from "node:path";
4
4
  import { readFile } from "node:fs/promises";
@@ -26,7 +26,11 @@ import { readFile } from "node:fs/promises";
26
26
  const aot = (entry, options) => ({
27
27
  name: "elysia-aot",
28
28
  async setup(build) {
29
- const hooks = createAotPluginHooks(entry, options);
29
+ const entryPath = resolveEntry(entry);
30
+ const moduleCondition = resolveEntryModuleKind(entryPath);
31
+ if (build.initialOptions?.conditions?.includes("types")) throw new Error("[elysia-aot] esbuild conditions includes 'types'; this selects declaration files as runtime inputs. Remove the conflicting condition.");
32
+ if (moduleCondition === "cjs" && build.initialOptions?.conditions?.includes("import")) throw new Error("[elysia-aot] esbuild conditions includes 'import' for a CommonJS entry; this would load two Elysia module instances. Remove the conflicting condition.");
33
+ const hooks = createAotPluginHooks(entry, options, moduleCondition);
30
34
  let initial = true;
31
35
  build.onStart(async () => {
32
36
  if (initial) {
@@ -35,10 +39,9 @@ const aot = (entry, options) => ({
35
39
  }
36
40
  await hooks.buildStart();
37
41
  });
38
- await setupAotOnLoad(build, hooks, {
39
- readText: (path) => readFile(path, "utf8"),
40
- resolveDir: dirname(resolveEntry(entry))
41
- });
42
+ await setupAotOnLoad(build, hooks, (path) => readFile(path, "utf8"), dirname(entryPath));
43
+ const allowedKinds = moduleCondition === "cjs" ? new Set(["require-call", "require-resolve"]) : new Set(["import-statement", "dynamic-import"]);
44
+ build.onResolve({ filter: /^elysia(?:\/.*)?$/ }, (args) => allowedKinds.has(args.kind) ? void 0 : { errors: [{ text: `[elysia-aot] ${args.path} uses esbuild edge kind ${JSON.stringify(args.kind)}, which conflicts with the ${JSON.stringify(moduleCondition)} entry module condition. Use one consistent import/require condition for Elysia.` }] });
42
45
  }
43
46
  });
44
47
 
@@ -1,3 +1,4 @@
1
+ import { AotModuleCondition } from "./source.js";
1
2
  import { ElysiaAotOptions } from "./core.js";
2
3
 
3
4
  //#region src/plugin/aot/hooks.d.ts
@@ -6,23 +7,11 @@ interface AotPluginHooks {
6
7
  buildEnd(): void;
7
8
  resolveId(id: string): string | undefined;
8
9
  load(id: string): string | undefined;
9
- transform(code: string, id: string): string | undefined | Promise<string | undefined>;
10
+ transform(code: string, id: string): string | undefined;
10
11
  isTransformCandidate(id: string): boolean;
11
12
  }
12
- declare const createAotPluginHooks: (entry: string, options?: ElysiaAotOptions) => AotPluginHooks;
13
- interface AotOnLoadAdapterOptions {
14
- /** Read a file's UTF-8 text (abstracted so Bun and esbuild can supply their own reader). */
15
- readText: (path: string) => Promise<string>;
16
- /**
17
- * resolveDir for the manifest/virtual-type module loads.
18
- * esbuild needs `dirname(entryPath)` so relative imports in the manifest
19
- * resolve correctly; Bun does not use it (pass undefined for Bun).
20
- */
21
- resolveDir?: string;
22
- }
23
- declare function setupAotOnLoad(build: any, hooks: AotPluginHooks, {
24
- readText,
25
- resolveDir
26
- }: AotOnLoadAdapterOptions): Promise<void>;
13
+ declare const createAotPluginHooks: (entry: string, options?: ElysiaAotOptions, moduleCondition?: AotModuleCondition) => AotPluginHooks;
14
+ declare const createTypeboxWiringHooks: () => AotPluginHooks;
15
+ declare function setupAotOnLoad(build: any, hooks: AotPluginHooks, readText: (path: string) => Promise<string>, resolveDir?: string): Promise<void>;
27
16
  //#endregion
28
- export { AotOnLoadAdapterOptions, AotPluginHooks, createAotPluginHooks, setupAotOnLoad };
17
+ export { AotPluginHooks, createAotPluginHooks, createTypeboxWiringHooks, setupAotOnLoad };