gemi 0.84.1 → 0.85.0

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 (269) hide show
  1. package/dist/ai/Agent.d.ts +41 -3
  2. package/dist/ai/Agent.d.ts.map +1 -1
  3. package/dist/ai/AgentController.d.ts +238 -0
  4. package/dist/ai/AgentController.d.ts.map +1 -1
  5. package/dist/ai/AgentProvider.d.ts +15 -0
  6. package/dist/ai/AgentProvider.d.ts.map +1 -1
  7. package/dist/ai/client/index.d.ts +2 -2
  8. package/dist/ai/client/index.d.ts.map +1 -1
  9. package/dist/ai/client/index.js +138 -35
  10. package/dist/ai/client/index.js.map +1 -1
  11. package/dist/ai/client/reducer.d.ts +7 -1
  12. package/dist/ai/client/reducer.d.ts.map +1 -1
  13. package/dist/ai/generate.d.ts.map +1 -1
  14. package/dist/ai/index.d.ts +4 -2
  15. package/dist/ai/index.d.ts.map +1 -1
  16. package/dist/ai/index.js +12 -12
  17. package/dist/ai/index.js.map +19 -16
  18. package/dist/ai/providers/call.d.ts +4 -0
  19. package/dist/ai/providers/call.d.ts.map +1 -1
  20. package/dist/ai/providers/fileRejection.d.ts +84 -0
  21. package/dist/ai/providers/fileRejection.d.ts.map +1 -0
  22. package/dist/ai/providers/request.d.ts.map +1 -1
  23. package/dist/ai/redact.d.ts +70 -0
  24. package/dist/ai/redact.d.ts.map +1 -0
  25. package/dist/ai/signing.d.ts +33 -4
  26. package/dist/ai/signing.d.ts.map +1 -1
  27. package/dist/ai/store/Attachments.d.ts +5 -3
  28. package/dist/ai/store/Attachments.d.ts.map +1 -1
  29. package/dist/ai/store/FileOwners.d.ts +59 -0
  30. package/dist/ai/store/FileOwners.d.ts.map +1 -0
  31. package/dist/ai/store/LiveRuns.d.ts +25 -0
  32. package/dist/ai/store/LiveRuns.d.ts.map +1 -1
  33. package/dist/ai/store/MemoryAgentStore.d.ts +1 -0
  34. package/dist/ai/store/MemoryAgentStore.d.ts.map +1 -1
  35. package/dist/ai/store/Nonces.d.ts +109 -0
  36. package/dist/ai/store/Nonces.d.ts.map +1 -0
  37. package/dist/ai/store/index.d.ts +2 -0
  38. package/dist/ai/store/index.d.ts.map +1 -1
  39. package/dist/ai/types.d.ts +30 -1
  40. package/dist/ai/types.d.ts.map +1 -1
  41. package/dist/ai/useChat.d.ts +62 -3
  42. package/dist/ai/useChat.d.ts.map +1 -1
  43. package/dist/app/index.js +1 -1
  44. package/dist/bun/plugin.js +1 -1
  45. package/dist/bun/preload.js +1 -1
  46. package/dist/{chunk-82nn71zs.js → chunk-09sr33ff.js} +2 -2
  47. package/dist/{chunk-82nn71zs.js.map → chunk-09sr33ff.js.map} +1 -1
  48. package/dist/chunk-174jkg6d.js +7 -0
  49. package/dist/{chunk-302mkqeq.js.map → chunk-174jkg6d.js.map} +9 -8
  50. package/dist/{chunk-87x692j7.js → chunk-1b5s4w5f.js} +2 -2
  51. package/dist/{chunk-87x692j7.js.map → chunk-1b5s4w5f.js.map} +1 -1
  52. package/dist/{chunk-rmv1jp9p.js → chunk-1jcp8m8h.js} +2 -2
  53. package/dist/{chunk-rmv1jp9p.js.map → chunk-1jcp8m8h.js.map} +1 -1
  54. package/dist/{chunk-g6qe6wyb.js → chunk-1w5a11cd.js} +2 -2
  55. package/dist/{chunk-g6qe6wyb.js.map → chunk-1w5a11cd.js.map} +1 -1
  56. package/dist/chunk-1wby1sr2.js +5 -0
  57. package/dist/{chunk-e43drft2.js.map → chunk-1wby1sr2.js.map} +3 -3
  58. package/dist/{chunk-vmpzg4z5.js → chunk-1yq1e6sb.js} +3 -3
  59. package/dist/{chunk-vmpzg4z5.js.map → chunk-1yq1e6sb.js.map} +1 -1
  60. package/dist/chunk-1yzdxv2a.js +5 -0
  61. package/dist/{chunk-tmwsvf02.js.map → chunk-1yzdxv2a.js.map} +1 -1
  62. package/dist/{chunk-ah9ajys0.js → chunk-2gdhcswa.js} +1 -1
  63. package/dist/chunk-2k5kyk0h.js +24 -0
  64. package/dist/chunk-2k5kyk0h.js.map +17 -0
  65. package/dist/{chunk-1evk2pma.js → chunk-2yw23zhn.js} +4 -4
  66. package/dist/{chunk-1evk2pma.js.map → chunk-2yw23zhn.js.map} +1 -1
  67. package/dist/{chunk-3z6wkvwj.js → chunk-4ysar3ev.js} +2 -2
  68. package/dist/{chunk-3z6wkvwj.js.map → chunk-4ysar3ev.js.map} +1 -1
  69. package/dist/{chunk-z409rk5j.js → chunk-4zj05vry.js} +2 -2
  70. package/dist/{chunk-z409rk5j.js.map → chunk-4zj05vry.js.map} +1 -1
  71. package/dist/{chunk-1cebv3h8.js → chunk-55x9kkdt.js} +2 -2
  72. package/dist/{chunk-1cebv3h8.js.map → chunk-55x9kkdt.js.map} +1 -1
  73. package/dist/{chunk-0agfx93f.js → chunk-5ktfpty1.js} +2 -2
  74. package/dist/{chunk-0agfx93f.js.map → chunk-5ktfpty1.js.map} +1 -1
  75. package/dist/chunk-6k2czkkh.js +55 -0
  76. package/dist/{chunk-rp5j1mgk.js.map → chunk-6k2czkkh.js.map} +3 -3
  77. package/dist/{chunk-3zb2ycxj.js → chunk-7c33ngqs.js} +2 -2
  78. package/dist/{chunk-3zb2ycxj.js.map → chunk-7c33ngqs.js.map} +1 -1
  79. package/dist/{chunk-en3mtnsg.js → chunk-7n5775qx.js} +2 -2
  80. package/dist/{chunk-en3mtnsg.js.map → chunk-7n5775qx.js.map} +1 -1
  81. package/dist/{chunk-bn9pzgww.js → chunk-7nj2t2gm.js} +2 -2
  82. package/dist/{chunk-bn9pzgww.js.map → chunk-7nj2t2gm.js.map} +1 -1
  83. package/dist/{chunk-kfavcgv2.js → chunk-81k26w39.js} +2 -2
  84. package/dist/{chunk-kfavcgv2.js.map → chunk-81k26w39.js.map} +1 -1
  85. package/dist/{chunk-cg4k40zy.js → chunk-81v4c4b1.js} +2 -2
  86. package/dist/{chunk-cg4k40zy.js.map → chunk-81v4c4b1.js.map} +1 -1
  87. package/dist/{chunk-wh728wd6.js → chunk-8gexb1gt.js} +2 -2
  88. package/dist/{chunk-wh728wd6.js.map → chunk-8gexb1gt.js.map} +1 -1
  89. package/dist/{chunk-zfch4da5.js → chunk-9tsw1bmt.js} +2 -2
  90. package/dist/{chunk-8mmfpqgs.js.map → chunk-9tsw1bmt.js.map} +1 -1
  91. package/dist/{chunk-m0zba09s.js → chunk-9tv5j3b2.js} +3 -3
  92. package/dist/{chunk-m0zba09s.js.map → chunk-9tv5j3b2.js.map} +1 -1
  93. package/dist/{chunk-jg9eqd3r.js → chunk-c3gzpjba.js} +1 -1
  94. package/dist/{chunk-r5e4vpa1.js → chunk-cbycz5z3.js} +2 -2
  95. package/dist/{chunk-r5e4vpa1.js.map → chunk-cbycz5z3.js.map} +1 -1
  96. package/dist/{chunk-cfvq30n4.js → chunk-cfykfnqx.js} +2 -2
  97. package/dist/{chunk-cfvq30n4.js.map → chunk-cfykfnqx.js.map} +1 -1
  98. package/dist/{chunk-eysexnqb.js → chunk-ct7wxm98.js} +2 -2
  99. package/dist/{chunk-eysexnqb.js.map → chunk-ct7wxm98.js.map} +1 -1
  100. package/dist/{chunk-v27a4se1.js → chunk-d3jkypc7.js} +3 -3
  101. package/dist/{chunk-v27a4se1.js.map → chunk-d3jkypc7.js.map} +1 -1
  102. package/dist/{chunk-vfrrzr10.js → chunk-dadygfkf.js} +2 -2
  103. package/dist/{chunk-vfrrzr10.js.map → chunk-dadygfkf.js.map} +1 -1
  104. package/dist/{chunk-m4xw99vm.js → chunk-dwqh79e5.js} +2 -2
  105. package/dist/{chunk-m4xw99vm.js.map → chunk-dwqh79e5.js.map} +1 -1
  106. package/dist/{chunk-ng8pp9k2.js → chunk-fbwe0agk.js} +2 -2
  107. package/dist/{chunk-ng8pp9k2.js.map → chunk-fbwe0agk.js.map} +1 -1
  108. package/dist/{chunk-495qwteq.js → chunk-fc2je244.js} +3 -3
  109. package/dist/{chunk-495qwteq.js.map → chunk-fc2je244.js.map} +1 -1
  110. package/dist/{chunk-gr61ymse.js → chunk-gx0x772p.js} +2 -2
  111. package/dist/{chunk-gr61ymse.js.map → chunk-gx0x772p.js.map} +1 -1
  112. package/dist/{chunk-tdnfhe7x.js → chunk-ha705bcz.js} +3 -3
  113. package/dist/{chunk-tdnfhe7x.js.map → chunk-ha705bcz.js.map} +1 -1
  114. package/dist/chunk-jhe0t7yj.js +5 -0
  115. package/dist/chunk-jhe0t7yj.js.map +11 -0
  116. package/dist/{chunk-d0qwdeza.js → chunk-k5j65f2c.js} +2 -2
  117. package/dist/{chunk-d0qwdeza.js.map → chunk-k5j65f2c.js.map} +1 -1
  118. package/dist/{chunk-pt59xjfc.js → chunk-kmsrzbx1.js} +2 -2
  119. package/dist/{chunk-pt59xjfc.js.map → chunk-kmsrzbx1.js.map} +1 -1
  120. package/dist/{chunk-v1nm4tcq.js → chunk-m7y8d3k7.js} +2 -2
  121. package/dist/{chunk-v1nm4tcq.js.map → chunk-m7y8d3k7.js.map} +1 -1
  122. package/dist/{chunk-k2qh3hvd.js → chunk-mk8m3ffx.js} +2 -2
  123. package/dist/{chunk-k2qh3hvd.js.map → chunk-mk8m3ffx.js.map} +1 -1
  124. package/dist/{chunk-z7442w3q.js → chunk-mszy6cfw.js} +2 -2
  125. package/dist/{chunk-z7442w3q.js.map → chunk-mszy6cfw.js.map} +1 -1
  126. package/dist/{chunk-kb3xk9r8.js → chunk-ndat0nf0.js} +2 -2
  127. package/dist/{chunk-kb3xk9r8.js.map → chunk-ndat0nf0.js.map} +1 -1
  128. package/dist/{chunk-j9wqzemf.js → chunk-p0m3qgs5.js} +2 -2
  129. package/dist/{chunk-j9wqzemf.js.map → chunk-p0m3qgs5.js.map} +1 -1
  130. package/dist/{chunk-8mmfpqgs.js → chunk-p7r3ecpk.js} +2 -2
  131. package/dist/{chunk-zfch4da5.js.map → chunk-p7r3ecpk.js.map} +1 -1
  132. package/dist/{chunk-zp971jp2.js → chunk-pmmrhak1.js} +3 -3
  133. package/dist/{chunk-zp971jp2.js.map → chunk-pmmrhak1.js.map} +1 -1
  134. package/dist/{chunk-nvj1z2rs.js → chunk-pzwyg474.js} +2 -2
  135. package/dist/{chunk-nvj1z2rs.js.map → chunk-pzwyg474.js.map} +1 -1
  136. package/dist/{chunk-73dk6k4p.js → chunk-qje4kdff.js} +3 -3
  137. package/dist/{chunk-73dk6k4p.js.map → chunk-qje4kdff.js.map} +1 -1
  138. package/dist/{chunk-yk8s5egf.js → chunk-rdnm6rem.js} +2 -2
  139. package/dist/{chunk-yk8s5egf.js.map → chunk-rdnm6rem.js.map} +1 -1
  140. package/dist/{chunk-enf9mdac.js → chunk-s046a984.js} +2 -2
  141. package/dist/{chunk-enf9mdac.js.map → chunk-s046a984.js.map} +1 -1
  142. package/dist/{chunk-1s914cdj.js → chunk-saqfc6vp.js} +3 -3
  143. package/dist/{chunk-1s914cdj.js.map → chunk-saqfc6vp.js.map} +1 -1
  144. package/dist/{chunk-pgpqsgzx.js → chunk-sejnmn1q.js} +1 -1
  145. package/dist/{chunk-xhha1gb3.js → chunk-sjckrbr2.js} +2 -2
  146. package/dist/{chunk-xhha1gb3.js.map → chunk-sjckrbr2.js.map} +1 -1
  147. package/dist/{chunk-r8nhndzb.js → chunk-swhyp0yw.js} +2 -2
  148. package/dist/{chunk-r8nhndzb.js.map → chunk-swhyp0yw.js.map} +1 -1
  149. package/dist/{chunk-wkdzz0rx.js → chunk-trdwxm5x.js} +3 -3
  150. package/dist/{chunk-wkdzz0rx.js.map → chunk-trdwxm5x.js.map} +1 -1
  151. package/dist/{chunk-aztkrzvf.js → chunk-v2hvnxsf.js} +2 -2
  152. package/dist/{chunk-aztkrzvf.js.map → chunk-v2hvnxsf.js.map} +1 -1
  153. package/dist/{chunk-57ryyhh3.js → chunk-v4ngf77f.js} +2 -2
  154. package/dist/{chunk-57ryyhh3.js.map → chunk-v4ngf77f.js.map} +1 -1
  155. package/dist/{chunk-159hyeng.js → chunk-v8nf45gt.js} +2 -2
  156. package/dist/{chunk-159hyeng.js.map → chunk-v8nf45gt.js.map} +1 -1
  157. package/dist/{chunk-ys4fejmx.js → chunk-vwp1g8wh.js} +2 -2
  158. package/dist/{chunk-ys4fejmx.js.map → chunk-vwp1g8wh.js.map} +1 -1
  159. package/dist/chunk-w312e9nx.js +5 -0
  160. package/dist/{chunk-ash9e6fn.js.map → chunk-w312e9nx.js.map} +4 -3
  161. package/dist/{chunk-wwdaswxh.js → chunk-wwzg4dmy.js} +3 -3
  162. package/dist/{chunk-wwdaswxh.js.map → chunk-wwzg4dmy.js.map} +1 -1
  163. package/dist/{chunk-wsx3j5ws.js → chunk-xckeyg3v.js} +2 -2
  164. package/dist/{chunk-wsx3j5ws.js.map → chunk-xckeyg3v.js.map} +1 -1
  165. package/dist/chunk-xx2zg6sk.js +17 -0
  166. package/dist/{chunk-49akdtfe.js.map → chunk-xx2zg6sk.js.map} +11 -12
  167. package/dist/{chunk-rqh2wdhb.js → chunk-y7qnx8vm.js} +2 -2
  168. package/dist/{chunk-rqh2wdhb.js.map → chunk-y7qnx8vm.js.map} +1 -1
  169. package/dist/{chunk-rv7da58g.js → chunk-z4k18gnp.js} +2 -2
  170. package/dist/{chunk-rv7da58g.js.map → chunk-z4k18gnp.js.map} +1 -1
  171. package/dist/{chunk-w099t7zj.js → chunk-zf4r4kat.js} +2 -2
  172. package/dist/{chunk-w099t7zj.js.map → chunk-zf4r4kat.js.map} +1 -1
  173. package/dist/{chunk-dvpxkzms.js → chunk-zs90w6ke.js} +2 -2
  174. package/dist/{chunk-dvpxkzms.js.map → chunk-zs90w6ke.js.map} +1 -1
  175. package/dist/chunks/{ThemeProvider-Dn3UREDn.js → ThemeProvider-D1kDfCwY.js} +59 -2
  176. package/dist/chunks/ThemeProvider-D1kDfCwY.js.map +1 -0
  177. package/dist/client/Link.d.ts.map +1 -1
  178. package/dist/client/MutationError.d.ts +60 -50
  179. package/dist/client/MutationError.d.ts.map +1 -1
  180. package/dist/client/ProgressManager.d.ts +1 -1
  181. package/dist/client/QueryResource.d.ts +20 -0
  182. package/dist/client/QueryResource.d.ts.map +1 -1
  183. package/dist/client/index.d.ts +2 -1
  184. package/dist/client/index.d.ts.map +1 -1
  185. package/dist/client/index.js +109 -35
  186. package/dist/client/index.js.map +1 -1
  187. package/dist/client/useMutation.d.ts.map +1 -1
  188. package/dist/client/useQuery.d.ts.map +1 -1
  189. package/dist/config/index.js +1 -1
  190. package/dist/console/run.js +2 -2
  191. package/dist/console/run.js.map +1 -1
  192. package/dist/container/index.js +2 -2
  193. package/dist/container/index.js.map +1 -1
  194. package/dist/database/index.js +2 -2
  195. package/dist/database/index.js.map +1 -1
  196. package/dist/email/Email.d.ts.map +1 -1
  197. package/dist/email/debugEmail.d.ts +40 -0
  198. package/dist/email/debugEmail.d.ts.map +1 -0
  199. package/dist/email/index.js +4 -3
  200. package/dist/email/index.js.map +6 -5
  201. package/dist/facades/index.js +2 -2
  202. package/dist/facades/index.js.map +1 -1
  203. package/dist/foundation/index.js +2 -2
  204. package/dist/foundation/index.js.map +1 -1
  205. package/dist/http/ApiRouter.d.ts +12 -0
  206. package/dist/http/ApiRouter.d.ts.map +1 -1
  207. package/dist/http/CSRFMiddleware.d.ts +1 -1
  208. package/dist/http/CSRFMiddleware.d.ts.map +1 -1
  209. package/dist/http/Error.d.ts +50 -0
  210. package/dist/http/Error.d.ts.map +1 -1
  211. package/dist/http/HttpRequest.d.ts +26 -0
  212. package/dist/http/HttpRequest.d.ts.map +1 -1
  213. package/dist/http/RateLimitMiddleware.d.ts +6 -3
  214. package/dist/http/RateLimitMiddleware.d.ts.map +1 -1
  215. package/dist/http/Router.d.ts.map +1 -1
  216. package/dist/http/errors.d.ts.map +1 -1
  217. package/dist/http/index.d.ts +2 -1
  218. package/dist/http/index.d.ts.map +1 -1
  219. package/dist/http/index.js +2 -2
  220. package/dist/http/index.js.map +1 -1
  221. package/dist/http/mediaType.d.ts +16 -0
  222. package/dist/http/mediaType.d.ts.map +1 -0
  223. package/dist/http/refusal.d.ts +52 -0
  224. package/dist/http/refusal.d.ts.map +1 -0
  225. package/dist/i18n/dictionaryRuntime.js +2 -2
  226. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  227. package/dist/i18n/index.js +2 -2
  228. package/dist/i18n/index.js.map +2 -2
  229. package/dist/kernel/index.js +2 -2
  230. package/dist/kernel/index.js.map +2 -2
  231. package/dist/orm/index.js +2 -2
  232. package/dist/orm/index.js.map +1 -1
  233. package/dist/server/devFetch.d.ts.map +1 -1
  234. package/dist/server/forwardedFor.d.ts +42 -0
  235. package/dist/server/forwardedFor.d.ts.map +1 -0
  236. package/dist/server/httpProd.d.ts.map +1 -1
  237. package/dist/server/index.js +2 -2
  238. package/dist/server/index.js.map +1 -1
  239. package/dist/server/staticFile.d.ts +33 -0
  240. package/dist/server/staticFile.d.ts.map +1 -0
  241. package/dist/server/unhandledError.d.ts.map +1 -1
  242. package/dist/services/index.js +2 -2
  243. package/dist/services/index.js.map +2 -2
  244. package/dist/services/mcp/McpRegistry.d.ts +2 -1
  245. package/dist/services/mcp/McpRegistry.d.ts.map +1 -1
  246. package/dist/services/mcp/toAgentTools.d.ts +1 -1
  247. package/dist/services/mcp/toAgentTools.d.ts.map +1 -1
  248. package/dist/services/queue/work.js +2 -2
  249. package/dist/services/queue/work.js.map +1 -1
  250. package/dist/services/router/notFound.d.ts.map +1 -1
  251. package/dist/services/router/policyDenied.d.ts.map +1 -1
  252. package/dist/services/router/serverQueryFetcher.d.ts.map +1 -1
  253. package/dist/support/index.js +2 -2
  254. package/dist/support/index.js.map +1 -1
  255. package/dist/testing/index.js +1 -1
  256. package/package.json +1 -1
  257. package/skills/gemi-react-best-practices/rules/controller-throw-framework-errors.md +5 -0
  258. package/dist/chunk-302mkqeq.js +0 -7
  259. package/dist/chunk-49akdtfe.js +0 -17
  260. package/dist/chunk-ash9e6fn.js +0 -5
  261. package/dist/chunk-e43drft2.js +0 -5
  262. package/dist/chunk-j5xcfeqx.js +0 -24
  263. package/dist/chunk-j5xcfeqx.js.map +0 -16
  264. package/dist/chunk-rp5j1mgk.js +0 -55
  265. package/dist/chunk-tmwsvf02.js +0 -5
  266. package/dist/chunks/ThemeProvider-Dn3UREDn.js.map +0 -1
  267. /package/dist/{chunk-ah9ajys0.js.map → chunk-2gdhcswa.js.map} +0 -0
  268. /package/dist/{chunk-jg9eqd3r.js.map → chunk-c3gzpjba.js.map} +0 -0
  269. /package/dist/{chunk-pgpqsgzx.js.map → chunk-sejnmn1q.js.map} +0 -0
@@ -26,10 +26,10 @@
26
26
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { RateLimiter } from \"./RateLimiter\";\nimport { rateLimiterConfigDefaults, type RateLimiterConfig } from \"./config\";\n\nexport class RateLimiterServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n RateLimiter,\n () =>\n new RateLimiter(\n withDefaults(\n rateLimiterConfigDefaults(),\n this.app.config.get<RateLimiterConfig>(\"ratelimiter\", {}),\n ),\n ),\n );\n }\n}\n",
27
27
  "import type { RedisOptions } from \"bun\";\n\n// Config key: `redis`. Derived from `RedisServiceProvider`.\nexport interface RedisConfig {\n // Connection URL for Bun's Redis client. Defaults to the `REDIS_URL`\n // environment variable (Bun itself falls back to `redis://localhost:6379`\n // when unset).\n url?: string;\n\n // Optional Bun Redis client options (TLS, timeouts, auto-reconnect, ...).\n options?: RedisOptions;\n}\n\nexport function defineRedisConfig(config: RedisConfig): RedisConfig {\n return config;\n}\n\nexport function redisConfigDefaults(): RedisConfig {\n return {\n url: process.env.REDIS_URL,\n options: undefined,\n };\n}\n",
28
28
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { redisConfigDefaults, type RedisConfig } from \"./config\";\nimport { RedisManager } from \"./RedisManager\";\n\nexport class RedisServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n RedisManager,\n () =>\n new RedisManager(\n withDefaults(\n redisConfigDefaults(),\n this.app.config.get<RedisConfig>(\"redis\", {}),\n ),\n ),\n );\n }\n\n /**\n * Closes the client, if anything built one. Under `gemi dev` this is what\n * keeps each `bun --hot` reload from leaving a Redis connection behind; see\n * `DatabaseServiceProvider.shutdown`.\n */\n shutdown() {\n if (!this.app.resolved(RedisManager)) return;\n this.app.make(RedisManager).close();\n }\n}\n",
29
- "import type { ToolContext } from \"../../ai/Agent\";\nimport { s, type AnySchema, type JSONSchema, type Schema } from \"../../ai/Schema\";\nimport type { RouteSource } from \"../../http/ApiRouter\";\nimport type { HttpRequest } from \"../../http/HttpRequest\";\nimport type {\n McpFileBinder,\n McpMethod,\n McpParamBinder,\n McpRouteDeclaration,\n McpRouter,\n} from \"../../http/McpRouter\";\nimport type { ApiRouteDispatcher } from \"../router/ApiRouteDispatcher\";\n\n/**\n * Who a tool call runs as. Always an argument to the registry, never read from\n * ambient state by it.\n *\n * `local` is an agent running in this server, and `req` is the request that\n * started its run — read by `toAgentTools` at the moment the tool executes,\n * not when the tool was built, which is what lets one set of tools serve every\n * user's run.\n *\n * That producer *does* read ambient state, since a run no longer carries a\n * request (see `AgentContext`), and the boundary is what keeps that from\n * mattering here: the registry is handed a caller and dispatches as that\n * caller, so a second producer — a job, a test, v2's remote client — supplies\n * one however it likes, and a run with no ambient request is refused by\n * `toAgentTools` before the registry is reached rather than dispatching as\n * nobody.\n * The call is dispatched with that request's credentials, so it runs as that\n * user, through that route's middleware.\n *\n * `remote` is v2's MCP client with a bearer token. It is typed so the seam\n * exists and every entry point already takes it; each of them refuses it,\n * because a token resolver is what makes it safe and there is none yet.\n * Reading the caller from `RequestContext` instead would have been shorter,\n * and would have left v2 a registry that only works inside a gemi request.\n */\nexport type McpCaller =\n | { kind: \"local\"; req: HttpRequest<any, any> }\n | { kind: \"remote\"; token: string };\n\n/**\n * MCP's tool annotations, from the verb. They drive confirmation prompts in\n * remote clients, which is why they are set now rather than when v2 lands:\n * every app would otherwise have to revisit its MCP file to get them.\n *\n * Only what the verb says is set. POST and PATCH carry nothing, and MCP's\n * defaults for an unannotated tool — not read-only, possibly destructive — are\n * the honest answer for them.\n */\nexport type McpToolAnnotations = {\n readOnlyHint?: true;\n destructiveHint?: true;\n idempotentHint?: true;\n};\n\n/**\n * One tool, described without committing to who consumes it.\n *\n * The registry's native output. An in-process agent projects it to an\n * `AgentTool` (`toAgentTools`); v2's `tools/list` will project it to JSON.\n * Emitting `AgentTool`s here instead would leave v2 reversing JSON Schema back\n * out of them.\n */\nexport interface McpToolDescriptor {\n /** The `routes` key, verbatim. See `McpRouter`. */\n readonly name: string;\n readonly description: string;\n readonly method: McpMethod;\n /** The route's path as declared, params unfilled. */\n readonly url: string;\n /**\n * What the model fills in: the declared `input`, plus a string for every\n * `\"input\"` path param and every `\"input\"` file field. Bound params and\n * bound files are not in it at all.\n */\n readonly inputSchema: Schema<Record<string, unknown>>;\n readonly annotations: McpToolAnnotations;\n readonly tags: readonly string[];\n readonly requiresApproval: boolean;\n /** The controller method mounted at the route, when there is one (#502). */\n readonly source?: RouteSource;\n}\n\n/**\n * Narrows `list`. Data rather than a predicate, because v2's per-token\n * visibility will come from a token's grants, which are data. Both fields\n * narrow: `names` keeps only those tools, `tags` keeps tools carrying at least\n * one of them.\n */\nexport type McpToolFilter = {\n names?: readonly string[];\n tags?: readonly string[];\n};\n\n/**\n * A failure the model is meant to read: a 4xx from the route, a missing file,\n * a bad argument. v2 turns it into `isError: true` rather than a protocol\n * error. Anything else thrown from `execute` is the caller's mistake or the\n * server's, not the model's.\n */\nexport class McpToolError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"McpToolError\";\n }\n}\n\n/** Tool names as OpenAI's function tools and MCP clients both accept them. */\nconst TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;\n\n/** `:name`, with URLPattern's modifiers. */\nconst PATH_PARAM = /:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g;\n\n/**\n * A 4xx body goes to the model verbatim, so a validation error can be fixed on\n * the next step — but a route that answers a 4xx with a page of HTML should not\n * be able to fill the context window with it.\n */\nconst MAX_ERROR_BODY = 4000;\n\n/**\n * The same limit for a success, set higher: a list route answering every row,\n * or a route serving a large text file, would otherwise land in the context\n * window whole. Past it the model gets the text cut short and told so, rather\n * than an error — the route has already done what it does, and a model told it\n * failed would do it again.\n */\nconst MAX_RESULT_BODY = 100_000;\n\n/** A body a model can read. A missing content-type is read as text. */\nconst READABLE = /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml))/i;\n\ntype PathParam = { name: string; modifier: string };\n\ntype Plan = {\n descriptor: McpToolDescriptor;\n params: PathParam[];\n paramBinders: Map<string, McpParamBinder>;\n fileFields: { name: string; binder: McpFileBinder | \"input\" }[];\n jsonKeys: string[];\n};\n\n/**\n * The tools an app's `McpRouter` declares, resolved against the api route\n * table, and the one place a call to them is dispatched.\n *\n * Built once, at boot, from the dispatcher's flat route table — so a route\n * that was renamed or unmounted fails the boot here, and at compile time\n * before that, rather than the first model that calls it.\n *\n * THE INVARIANT: a tool call can do nothing its caller could not do with a\n * direct HTTP request. `execute` builds a request and hands it to\n * `ApiRouteDispatcher.dispatchAs`, which runs the route's middleware, auth and\n * policies exactly as for a client. It never reaches for a flat entry's\n * `exec`, which is the handler alone — no auth, no policies, no rate limit —\n * and is the shorter path for exactly that reason.\n */\nexport class McpRegistry {\n static token = \"router.mcp\";\n\n private readonly plans = new Map<string, Plan>();\n\n constructor(\n router: McpRouter<any>,\n private readonly dispatcher: Pick<\n ApiRouteDispatcher,\n \"flatRoutes\" | \"dispatchAs\" | \"getRouteHandlerAndParams\"\n >,\n ) {\n for (const [name, declaration] of Object.entries(router.routes ?? {})) {\n this.plans.set(name, this.plan(name, declaration));\n }\n }\n\n /**\n * The tools `caller` may see. v1 has only local callers, and every declared\n * tool is visible to every one of them; `filter` is taken now so the shape\n * v2's per-token visibility needs is the shape callers already use.\n */\n list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[] {\n assertLocal(caller);\n return this.descriptors(filter);\n }\n\n /**\n * The same listing without a caller, for a projection built once before any\n * caller exists — `toAgentTools`. It is not per-caller visibility, and a v2\n * remote listing must go through `list`.\n */\n descriptors(filter?: McpToolFilter): McpToolDescriptor[] {\n const out: McpToolDescriptor[] = [];\n for (const { descriptor } of this.plans.values()) {\n if (filter?.names && !filter.names.includes(descriptor.name)) continue;\n if (filter?.tags && !descriptor.tags.some((tag) => filter.tags.includes(tag))) continue;\n out.push(descriptor);\n }\n return out;\n }\n\n /**\n * Calls the tool `name` as `caller`, and answers the route's JSON.\n *\n * `ctx` is the tool context of the agent call, and only files need it:\n * `\"input\"` files resolve through `ctx.attachments`, the handle already\n * scoped to the caller, and bound files are chosen by a binder given `ctx`.\n * Nothing here reads an attachment any other way — the store has no\n * unscoped lookup, and this must not become one.\n *\n * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body\n * that is neither — a file a route serves — is described, not shown.\n * A 4xx throws an `McpToolError` carrying the route's body, so a validation\n * error reaches the model word for word. Anything else, or a route that\n * throws, throws an `McpToolError` that says only that the server failed.\n * The app gets the reason in its log, and a stack trace or a database\n * message is not something to hand a model that may be steered by whoever\n * wrote the document it is reading.\n */\n async execute(\n caller: McpCaller,\n name: string,\n args: unknown,\n ctx?: ToolContext,\n ): Promise<unknown> {\n assertLocal(caller);\n const plan = this.plans.get(name);\n if (!plan) {\n throw new Error(`McpRegistry: there is no tool named \"${name}\".`);\n }\n const { descriptor } = plan;\n\n const parsed = descriptor.inputSchema.safeParse(args);\n if (parsed.ok === false) {\n throw new McpToolError(`Invalid arguments for \"${name}\": ${parsed.errors.join(\", \")}`);\n }\n const input = parsed.value;\n\n const path = await this.fillPath(plan, input, caller.req);\n\n // The dispatcher routes `path` afresh and takes the first route that\n // matches it, so a model's \"archive-all\" for `/products/:id` would reach a\n // `/products/archive-all` declared above it — a route the app never\n // exposed, behind none of this tool's approval or annotations.\n const { path: matched } = this.dispatcher.getRouteHandlerAndParams(\n new Request(`http://gemi.internal/api${path}`),\n );\n if (matched !== descriptor.url) {\n throw new McpToolError(`\"${name}\" has nothing at ${path}.`, 404);\n }\n\n const json: Record<string, unknown> = {};\n for (const key of plan.jsonKeys) {\n if (input[key] !== undefined) json[key] = input[key];\n }\n\n let body: FormData | Record<string, unknown> | undefined;\n let query = \"\";\n if (plan.fileFields.length > 0) {\n body = await this.formData(plan, input, json, ctx);\n } else if (descriptor.method === \"GET\") {\n query = toQuery(json);\n } else if (plan.jsonKeys.length > 0) {\n body = json;\n }\n\n let response: Response;\n try {\n response = await this.dispatcher.dispatchAs(\n caller.req,\n descriptor.method,\n query ? `${path}?${query}` : path,\n body,\n );\n } catch (error) {\n // What a client would get as a 500. A handler's throw is logged by the\n // dispatcher too, but dispatchAs's own refusal of the path is not.\n console.error(`[gemi/mcp] Dispatching \"${name}\" failed:`, error);\n throw new McpToolError(`\"${name}\" failed on the server.`, 500);\n }\n return await readResponse(name, response);\n }\n\n // --- building ------------------------------------------------------------\n\n private plan(name: string, declaration: McpRouteDeclaration): Plan {\n if (!TOOL_NAME.test(name)) {\n throw new Error(\n `McpRouter: \"${name}\" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim — letters, digits, \"_\" and \"-\", at most 64.`,\n );\n }\n const where = `McpRouter: \"${name}\" (${declaration?.method} ${declaration?.url})`;\n if (!(declaration instanceof Object) || declaration.__internal_brand !== \"McpRoute\") {\n throw new Error(\n `McpRouter: \"${name}\" is not a route. Declare it with this.fromApiRoute(...).`,\n );\n }\n const { method, url, meta } = declaration;\n if (url.startsWith(\"/__gemi__\")) {\n throw new Error(`${where} is a framework route, not an app route.`);\n }\n\n const entry = this.dispatcher.flatRoutes[url]?.[method];\n if (!entry) {\n throw new Error(\n `${where} names no route of this app. Expose a route by the path and verb it is mounted at.`,\n );\n }\n\n // Mirrors the compile-time check, for a router written in JavaScript or\n // behind a cast: a param left undeclared would otherwise be the model's.\n const params: PathParam[] = [...url.matchAll(PATH_PARAM)].map(([, param, modifier]) => ({\n name: param,\n modifier,\n }));\n const declared = meta.params ?? {};\n for (const param of params) {\n if (!(param.name in declared)) {\n throw new Error(\n `${where}: the path param \"${param.name}\" must be bound or declared \"input\".`,\n );\n }\n }\n for (const [key, binder] of Object.entries(declared)) {\n if (!params.some((param) => param.name === key)) {\n throw new Error(`${where}: \"${key}\" in params is not a param of the url.`);\n }\n assertBinder(where, `params.${key}`, binder);\n }\n\n let jsonKeys: string[] = [];\n let base: JSONSchema | undefined;\n if (meta.input) {\n base = meta.input.toJSONSchema();\n if (base.type !== \"object\" || !base.properties) {\n throw new Error(\n `${where}: input must be an s.object(...), the fields of the request body.`,\n );\n }\n jsonKeys = Object.keys(base.properties);\n }\n\n const fileFields = Object.entries(meta.files ?? {}).map(([field, binder]) => ({\n name: field,\n binder,\n }));\n for (const file of fileFields) {\n assertBinder(where, `files.${file.name}`, file.binder);\n }\n if (fileFields.length > 0 && method === \"GET\") {\n throw new Error(`${where}: a GET has no body to carry a file.`);\n }\n\n const extras: Record<string, AnySchema> = {};\n const paramBinders = new Map<string, McpParamBinder>();\n for (const param of params) {\n const binder = declared[param.name];\n if (binder === \"input\") {\n const field = s.string().describe(`The \":${param.name}\" segment of the url.`);\n extras[param.name] =\n param.modifier === \"?\" || param.modifier === \"*\" ? field.optional() : field;\n } else {\n paramBinders.set(param.name, binder);\n }\n }\n for (const file of fileFields) {\n if (file.binder === \"input\") {\n extras[file.name] = s\n .string()\n .describe(\n \"The id of an attachment the user uploaded or a tool produced (gemi_att_…), whose file is sent as this field.\",\n );\n }\n }\n // A bound file is not the model's, but it shares the form with the input,\n // so it collides all the same.\n const bodyKeys = [...Object.keys(extras), ...fileFields.map((file) => file.name)];\n for (const key of new Set(bodyKeys)) {\n if (jsonKeys.includes(key)) {\n throw new Error(\n `${where}: \"${key}\" is both an input field and a param or file, and the model can only send one.`,\n );\n }\n }\n\n return {\n descriptor: Object.freeze({\n name,\n description: meta.description,\n method,\n url,\n inputSchema: combineSchemas(meta.input, base, s.object(extras)),\n annotations: annotationsFor(method),\n tags: Object.freeze([...(meta.tags ?? [])]),\n requiresApproval: meta.requiresApproval === true,\n ...(entry.source ? { source: entry.source } : {}),\n }),\n params,\n paramBinders,\n fileFields,\n jsonKeys,\n };\n }\n\n // --- calling -------------------------------------------------------------\n\n private async fillPath(\n plan: Plan,\n input: Record<string, unknown>,\n req: HttpRequest<any, any>,\n ): Promise<string> {\n let path = plan.descriptor.url;\n for (const param of plan.params) {\n const binder = plan.paramBinders.get(param.name);\n let value: unknown;\n if (binder) {\n value = await this.bind(plan, `the param \"${param.name}\"`, () => binder(req));\n if (value === undefined || value === null || value === \"\") {\n console.error(\n `[gemi/mcp] The binder for \"${param.name}\" of \"${plan.descriptor.name}\" returned ${JSON.stringify(value)}.`,\n );\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n } else {\n value = input[param.name];\n }\n\n const token = `:${param.name}${param.modifier}`;\n if (value === undefined || value === null || value === \"\") {\n if (param.modifier !== \"?\" && param.modifier !== \"*\") {\n throw new McpToolError(`\"${param.name}\" of \"${plan.descriptor.name}\" must not be empty.`);\n }\n path = path.replace(`/${token}`, \"\");\n continue;\n }\n path = path.replace(token, encodeSegment(plan.descriptor.name, param, String(value)));\n }\n return path;\n }\n\n private async formData(\n plan: Plan,\n input: Record<string, unknown>,\n json: Record<string, unknown>,\n ctx: ToolContext | undefined,\n ): Promise<FormData> {\n const name = plan.descriptor.name;\n if (!ctx) {\n throw new Error(\n `McpRegistry: \"${name}\" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`,\n );\n }\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n const id =\n field.binder === \"input\"\n ? (input[field.name] as string)\n : await this.bind(plan, `the file \"${field.name}\"`, () =>\n (field.binder as McpFileBinder)(ctx),\n );\n if (typeof id !== \"string\" || id === \"\") {\n throw new McpToolError(\n `\"${name}\" needs a file for \"${field.name}\", and this turn has none. Ask the user to attach one.`,\n );\n }\n // Scoped to the caller: someone else's id is a not-found, worded like an\n // invented one, and that error is what the model reads.\n form.append(field.name, await ctx.attachments.file(id));\n }\n return form;\n }\n\n /**\n * Runs an app's binder. Its failure is the server's, not the model's, so the\n * model is told only that; the app gets the error in its log.\n */\n private async bind<T>(plan: Plan, what: string, fn: () => T | Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n console.error(`[gemi/mcp] Binding ${what} of \"${plan.descriptor.name}\" failed:`, error);\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n }\n}\n\nfunction assertLocal(caller: McpCaller): asserts caller is Extract<McpCaller, { kind: \"local\" }> {\n if (caller?.kind !== \"local\") {\n throw new Error(\n \"McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have — and until it does there is no remote surface to call from.\",\n );\n }\n}\n\n/** A binder is a function or `\"input\"`; anything else would leave the value to nobody. */\nfunction assertBinder(where: string, at: string, binder: unknown) {\n if (binder !== \"input\" && typeof binder !== \"function\") {\n throw new Error(`${where}: ${at} must be a function or \"input\".`);\n }\n}\n\nfunction annotationsFor(method: McpMethod): McpToolAnnotations {\n switch (method) {\n case \"GET\":\n return Object.freeze({ readOnlyHint: true as const });\n case \"DELETE\":\n return Object.freeze({ destructiveHint: true as const });\n case \"PUT\":\n return Object.freeze({ idempotentHint: true as const });\n default:\n return Object.freeze({});\n }\n}\n\n/**\n * One schema out of two: the app's `input`, and the strings for `\"input\"`\n * params and files.\n *\n * Built by hand, like `questionSchema` in `ai/Agent.ts`, rather than by\n * widening `s` with a merge: `Schema.ts` is deliberately the strict\n * structured-output subset and owns no operation on a finished schema. Both\n * halves are real `s` schemas, each parses the whole value and drops the keys\n * that are not its own — which is also where a bound param the model sent\n * anyway disappears, since neither half declares it.\n */\nfunction combineSchemas(\n input: AnySchema | undefined,\n base: JSONSchema | undefined,\n extras: AnySchema,\n): Schema<Record<string, unknown>> {\n const extra = extras.toJSONSchema();\n const json: JSONSchema = {\n ...(base ?? {}),\n type: \"object\",\n properties: { ...(base?.properties ?? {}), ...extra.properties },\n required: [...(base?.required ?? []), ...(extra.required ?? [])],\n additionalProperties: false,\n };\n\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"expected an object\"] };\n }\n const errors: string[] = [];\n let out: Record<string, unknown> = {};\n if (input) {\n const own = input.safeParse(value);\n if (own.ok === false) errors.push(...own.errors);\n else out = { ...own.value };\n }\n const more = extras.safeParse(value);\n if (more.ok === false) errors.push(...more.errors);\n else out = { ...out, ...more.value };\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as Schema<Record<string, unknown>>;\n}\n\n/**\n * A model-supplied param, as one encoded path segment. `.` and `..` are\n * refused rather than encoded: they encode to themselves, and URL parsing\n * would walk them out of the route.\n */\nfunction encodeSegment(tool: string, param: PathParam, value: string): string {\n const parts = param.modifier === \"*\" || param.modifier === \"+\" ? value.split(\"/\") : [value];\n if (parts.some((part) => part === \".\" || part === \"..\")) {\n throw new McpToolError(`\"${value}\" is not a valid value for \"${param.name}\" of \"${tool}\".`);\n }\n return parts.map(encodeURIComponent).join(\"/\");\n}\n\n/**\n * A JSON field as a multipart form field. A form has only strings, so the\n * route reads `\"12\"` where a JSON body would have carried `12` — what a\n * browser form sends the same route. An array becomes the key repeated, which\n * `HttpRequest` reads back as an array.\n */\nfunction appendField(form: FormData, key: string, value: unknown) {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendField(form, key, item);\n return;\n }\n form.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\n\n/** A GET's input, as the query string `HttpRequest.search` reads. */\nfunction toQuery(json: Record<string, unknown>): string {\n const search = new URLSearchParams();\n const add = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) add(key, item);\n return;\n }\n search.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n };\n for (const [key, value] of Object.entries(json)) add(key, value);\n return search.toString();\n}\n\nasync function readResponse(name: string, response: Response): Promise<unknown> {\n if (response.status >= 200 && response.status < 300) {\n const type = response.headers.get(\"Content-Type\");\n if (type && !READABLE.test(type)) {\n const size = (await response.arrayBuffer()).byteLength;\n return `\"${name}\" answered with ${size} bytes of ${type}, which is not shown.`;\n }\n const text = await response.text();\n if (text === \"\") return null;\n if (text.length > MAX_RESULT_BODY) {\n return `${text.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${text.length} characters]`;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n const text = await response.text();\n if (response.status >= 400 && response.status < 500) {\n const shown = text.length > MAX_ERROR_BODY ? `${text.slice(0, MAX_ERROR_BODY)}…` : text;\n throw new McpToolError(\n `\"${name}\" was refused with ${response.status}${shown ? `: ${shown}` : \".\"}`,\n response.status,\n );\n }\n if (response.status < 500) {\n // A redirect, or a 1xx: nothing the model can follow, and nothing the\n // dispatcher logged.\n console.error(\n `[gemi/mcp] \"${name}\" answered ${response.status}${response.headers.get(\"Location\") ? ` to ${response.headers.get(\"Location\")}` : \"\"}, which a tool call cannot follow.`,\n );\n }\n throw new McpToolError(`\"${name}\" failed on the server.`, response.status);\n}\n",
29
+ "import type { ToolContext } from \"../../ai/Agent\";\nimport { ToolError } from \"../../ai/redact\";\nimport { s, type AnySchema, type JSONSchema, type Schema } from \"../../ai/Schema\";\nimport type { RouteSource } from \"../../http/ApiRouter\";\nimport type { HttpRequest } from \"../../http/HttpRequest\";\nimport type {\n McpFileBinder,\n McpMethod,\n McpParamBinder,\n McpRouteDeclaration,\n McpRouter,\n} from \"../../http/McpRouter\";\nimport type { ApiRouteDispatcher } from \"../router/ApiRouteDispatcher\";\n\n/**\n * Who a tool call runs as. Always an argument to the registry, never read from\n * ambient state by it.\n *\n * `local` is an agent running in this server, and `req` is the request that\n * started its run — read by `toAgentTools` at the moment the tool executes,\n * not when the tool was built, which is what lets one set of tools serve every\n * user's run.\n *\n * That producer *does* read ambient state, since a run no longer carries a\n * request (see `AgentContext`), and the boundary is what keeps that from\n * mattering here: the registry is handed a caller and dispatches as that\n * caller, so a second producer — a job, a test, v2's remote client — supplies\n * one however it likes, and a run with no ambient request is refused by\n * `toAgentTools` before the registry is reached rather than dispatching as\n * nobody.\n * The call is dispatched with that request's credentials, so it runs as that\n * user, through that route's middleware.\n *\n * `remote` is v2's MCP client with a bearer token. It is typed so the seam\n * exists and every entry point already takes it; each of them refuses it,\n * because a token resolver is what makes it safe and there is none yet.\n * Reading the caller from `RequestContext` instead would have been shorter,\n * and would have left v2 a registry that only works inside a gemi request.\n */\nexport type McpCaller =\n | { kind: \"local\"; req: HttpRequest<any, any> }\n | { kind: \"remote\"; token: string };\n\n/**\n * MCP's tool annotations, from the verb. They drive confirmation prompts in\n * remote clients, which is why they are set now rather than when v2 lands:\n * every app would otherwise have to revisit its MCP file to get them.\n *\n * Only what the verb says is set. POST and PATCH carry nothing, and MCP's\n * defaults for an unannotated tool — not read-only, possibly destructive — are\n * the honest answer for them.\n */\nexport type McpToolAnnotations = {\n readOnlyHint?: true;\n destructiveHint?: true;\n idempotentHint?: true;\n};\n\n/**\n * One tool, described without committing to who consumes it.\n *\n * The registry's native output. An in-process agent projects it to an\n * `AgentTool` (`toAgentTools`); v2's `tools/list` will project it to JSON.\n * Emitting `AgentTool`s here instead would leave v2 reversing JSON Schema back\n * out of them.\n */\nexport interface McpToolDescriptor {\n /** The `routes` key, verbatim. See `McpRouter`. */\n readonly name: string;\n readonly description: string;\n readonly method: McpMethod;\n /** The route's path as declared, params unfilled. */\n readonly url: string;\n /**\n * What the model fills in: the declared `input`, plus a string for every\n * `\"input\"` path param and every `\"input\"` file field. Bound params and\n * bound files are not in it at all.\n */\n readonly inputSchema: Schema<Record<string, unknown>>;\n readonly annotations: McpToolAnnotations;\n readonly tags: readonly string[];\n readonly requiresApproval: boolean;\n /** The controller method mounted at the route, when there is one (#502). */\n readonly source?: RouteSource;\n}\n\n/**\n * Narrows `list`. Data rather than a predicate, because v2's per-token\n * visibility will come from a token's grants, which are data. Both fields\n * narrow: `names` keeps only those tools, `tags` keeps tools carrying at least\n * one of them.\n */\nexport type McpToolFilter = {\n names?: readonly string[];\n tags?: readonly string[];\n};\n\n/**\n * A failure the model is meant to read: a 4xx from the route, a missing file,\n * a bad argument. v2 turns it into `isError: true` rather than a protocol\n * error. Anything else thrown from `execute` is the caller's mistake or the\n * server's, not the model's.\n */\nexport class McpToolError extends ToolError {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"McpToolError\";\n }\n}\n\n/** Tool names as OpenAI's function tools and MCP clients both accept them. */\nconst TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;\n\n/** `:name`, with URLPattern's modifiers. */\nconst PATH_PARAM = /:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g;\n\n/**\n * A 4xx body goes to the model verbatim, so a validation error can be fixed on\n * the next step — but a route that answers a 4xx with a page of HTML should not\n * be able to fill the context window with it.\n */\nconst MAX_ERROR_BODY = 4000;\n\n/**\n * The same limit for a success, set higher: a list route answering every row,\n * or a route serving a large text file, would otherwise land in the context\n * window whole. Past it the model gets the text cut short and told so, rather\n * than an error — the route has already done what it does, and a model told it\n * failed would do it again.\n */\nconst MAX_RESULT_BODY = 100_000;\n\n/** A body a model can read. A missing content-type is read as text. */\nconst READABLE = /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml))/i;\n\ntype PathParam = { name: string; modifier: string };\n\ntype Plan = {\n descriptor: McpToolDescriptor;\n params: PathParam[];\n paramBinders: Map<string, McpParamBinder>;\n fileFields: { name: string; binder: McpFileBinder | \"input\" }[];\n jsonKeys: string[];\n};\n\n/**\n * The tools an app's `McpRouter` declares, resolved against the api route\n * table, and the one place a call to them is dispatched.\n *\n * Built once, at boot, from the dispatcher's flat route table — so a route\n * that was renamed or unmounted fails the boot here, and at compile time\n * before that, rather than the first model that calls it.\n *\n * THE INVARIANT: a tool call can do nothing its caller could not do with a\n * direct HTTP request. `execute` builds a request and hands it to\n * `ApiRouteDispatcher.dispatchAs`, which runs the route's middleware, auth and\n * policies exactly as for a client. It never reaches for a flat entry's\n * `exec`, which is the handler alone — no auth, no policies, no rate limit —\n * and is the shorter path for exactly that reason.\n */\nexport class McpRegistry {\n static token = \"router.mcp\";\n\n private readonly plans = new Map<string, Plan>();\n\n constructor(\n router: McpRouter<any>,\n private readonly dispatcher: Pick<\n ApiRouteDispatcher,\n \"flatRoutes\" | \"dispatchAs\" | \"getRouteHandlerAndParams\"\n >,\n ) {\n for (const [name, declaration] of Object.entries(router.routes ?? {})) {\n this.plans.set(name, this.plan(name, declaration));\n }\n }\n\n /**\n * The tools `caller` may see. v1 has only local callers, and every declared\n * tool is visible to every one of them; `filter` is taken now so the shape\n * v2's per-token visibility needs is the shape callers already use.\n */\n list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[] {\n assertLocal(caller);\n return this.descriptors(filter);\n }\n\n /**\n * The same listing without a caller, for a projection built once before any\n * caller exists — `toAgentTools`. It is not per-caller visibility, and a v2\n * remote listing must go through `list`.\n */\n descriptors(filter?: McpToolFilter): McpToolDescriptor[] {\n const out: McpToolDescriptor[] = [];\n for (const { descriptor } of this.plans.values()) {\n if (filter?.names && !filter.names.includes(descriptor.name)) continue;\n if (filter?.tags && !descriptor.tags.some((tag) => filter.tags.includes(tag))) continue;\n out.push(descriptor);\n }\n return out;\n }\n\n /**\n * Calls the tool `name` as `caller`, and answers the route's JSON.\n *\n * `ctx` is the tool context of the agent call, and only files need it:\n * `\"input\"` files resolve through `ctx.attachments`, the handle already\n * scoped to the caller, and bound files are chosen by a binder given `ctx`.\n * Nothing here reads an attachment any other way — the store has no\n * unscoped lookup, and this must not become one.\n *\n * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body\n * that is neither — a file a route serves — is described, not shown.\n * A 4xx throws an `McpToolError` carrying the route's body, so a validation\n * error reaches the model word for word. Anything else, or a route that\n * throws, throws an `McpToolError` that says only that the server failed.\n * The app gets the reason in its log, and a stack trace or a database\n * message is not something to hand a model that may be steered by whoever\n * wrote the document it is reading.\n */\n async execute(\n caller: McpCaller,\n name: string,\n args: unknown,\n ctx?: ToolContext,\n ): Promise<unknown> {\n assertLocal(caller);\n const plan = this.plans.get(name);\n if (!plan) {\n throw new Error(`McpRegistry: there is no tool named \"${name}\".`);\n }\n const { descriptor } = plan;\n\n const parsed = descriptor.inputSchema.safeParse(args);\n if (parsed.ok === false) {\n throw new McpToolError(`Invalid arguments for \"${name}\": ${parsed.errors.join(\", \")}`);\n }\n const input = parsed.value;\n\n const path = await this.fillPath(plan, input, caller.req);\n\n // The dispatcher routes `path` afresh and takes the first route that\n // matches it, so a model's \"archive-all\" for `/products/:id` would reach a\n // `/products/archive-all` declared above it — a route the app never\n // exposed, behind none of this tool's approval or annotations.\n const { path: matched } = this.dispatcher.getRouteHandlerAndParams(\n new Request(`http://gemi.internal/api${path}`),\n );\n if (matched !== descriptor.url) {\n throw new McpToolError(`\"${name}\" has nothing at ${path}.`, 404);\n }\n\n const json: Record<string, unknown> = {};\n for (const key of plan.jsonKeys) {\n if (input[key] !== undefined) json[key] = input[key];\n }\n\n let body: FormData | Record<string, unknown> | undefined;\n let query = \"\";\n if (plan.fileFields.length > 0) {\n body = await this.formData(plan, input, json, ctx);\n } else if (descriptor.method === \"GET\") {\n query = toQuery(json);\n } else if (plan.jsonKeys.length > 0) {\n body = json;\n }\n\n let response: Response;\n try {\n response = await this.dispatcher.dispatchAs(\n caller.req,\n descriptor.method,\n query ? `${path}?${query}` : path,\n body,\n );\n } catch (error) {\n // What a client would get as a 500. A handler's throw is logged by the\n // dispatcher too, but dispatchAs's own refusal of the path is not.\n console.error(`[gemi/mcp] Dispatching \"${name}\" failed:`, error);\n throw new McpToolError(`\"${name}\" failed on the server.`, 500);\n }\n return await readResponse(name, response);\n }\n\n // --- building ------------------------------------------------------------\n\n private plan(name: string, declaration: McpRouteDeclaration): Plan {\n if (!TOOL_NAME.test(name)) {\n throw new Error(\n `McpRouter: \"${name}\" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim — letters, digits, \"_\" and \"-\", at most 64.`,\n );\n }\n const where = `McpRouter: \"${name}\" (${declaration?.method} ${declaration?.url})`;\n if (!(declaration instanceof Object) || declaration.__internal_brand !== \"McpRoute\") {\n throw new Error(\n `McpRouter: \"${name}\" is not a route. Declare it with this.fromApiRoute(...).`,\n );\n }\n const { method, url, meta } = declaration;\n if (url.startsWith(\"/__gemi__\")) {\n throw new Error(`${where} is a framework route, not an app route.`);\n }\n\n const entry = this.dispatcher.flatRoutes[url]?.[method];\n if (!entry) {\n throw new Error(\n `${where} names no route of this app. Expose a route by the path and verb it is mounted at.`,\n );\n }\n\n // Mirrors the compile-time check, for a router written in JavaScript or\n // behind a cast: a param left undeclared would otherwise be the model's.\n const params: PathParam[] = [...url.matchAll(PATH_PARAM)].map(([, param, modifier]) => ({\n name: param,\n modifier,\n }));\n const declared = meta.params ?? {};\n for (const param of params) {\n if (!(param.name in declared)) {\n throw new Error(\n `${where}: the path param \"${param.name}\" must be bound or declared \"input\".`,\n );\n }\n }\n for (const [key, binder] of Object.entries(declared)) {\n if (!params.some((param) => param.name === key)) {\n throw new Error(`${where}: \"${key}\" in params is not a param of the url.`);\n }\n assertBinder(where, `params.${key}`, binder);\n }\n\n let jsonKeys: string[] = [];\n let base: JSONSchema | undefined;\n if (meta.input) {\n base = meta.input.toJSONSchema();\n if (base.type !== \"object\" || !base.properties) {\n throw new Error(\n `${where}: input must be an s.object(...), the fields of the request body.`,\n );\n }\n jsonKeys = Object.keys(base.properties);\n }\n\n const fileFields = Object.entries(meta.files ?? {}).map(([field, binder]) => ({\n name: field,\n binder,\n }));\n for (const file of fileFields) {\n assertBinder(where, `files.${file.name}`, file.binder);\n }\n if (fileFields.length > 0 && method === \"GET\") {\n throw new Error(`${where}: a GET has no body to carry a file.`);\n }\n\n const extras: Record<string, AnySchema> = {};\n const paramBinders = new Map<string, McpParamBinder>();\n for (const param of params) {\n const binder = declared[param.name];\n if (binder === \"input\") {\n const field = s.string().describe(`The \":${param.name}\" segment of the url.`);\n extras[param.name] =\n param.modifier === \"?\" || param.modifier === \"*\" ? field.optional() : field;\n } else {\n paramBinders.set(param.name, binder);\n }\n }\n for (const file of fileFields) {\n if (file.binder === \"input\") {\n extras[file.name] = s\n .string()\n .describe(\n \"The id of an attachment the user uploaded or a tool produced (gemi_att_…), whose file is sent as this field.\",\n );\n }\n }\n // A bound file is not the model's, but it shares the form with the input,\n // so it collides all the same.\n const bodyKeys = [...Object.keys(extras), ...fileFields.map((file) => file.name)];\n for (const key of new Set(bodyKeys)) {\n if (jsonKeys.includes(key)) {\n throw new Error(\n `${where}: \"${key}\" is both an input field and a param or file, and the model can only send one.`,\n );\n }\n }\n\n return {\n descriptor: Object.freeze({\n name,\n description: meta.description,\n method,\n url,\n inputSchema: combineSchemas(meta.input, base, s.object(extras)),\n annotations: annotationsFor(method),\n tags: Object.freeze([...(meta.tags ?? [])]),\n requiresApproval: meta.requiresApproval === true,\n ...(entry.source ? { source: entry.source } : {}),\n }),\n params,\n paramBinders,\n fileFields,\n jsonKeys,\n };\n }\n\n // --- calling -------------------------------------------------------------\n\n private async fillPath(\n plan: Plan,\n input: Record<string, unknown>,\n req: HttpRequest<any, any>,\n ): Promise<string> {\n let path = plan.descriptor.url;\n for (const param of plan.params) {\n const binder = plan.paramBinders.get(param.name);\n let value: unknown;\n if (binder) {\n value = await this.bind(plan, `the param \"${param.name}\"`, () => binder(req));\n if (value === undefined || value === null || value === \"\") {\n console.error(\n `[gemi/mcp] The binder for \"${param.name}\" of \"${plan.descriptor.name}\" returned ${JSON.stringify(value)}.`,\n );\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n } else {\n value = input[param.name];\n }\n\n const token = `:${param.name}${param.modifier}`;\n if (value === undefined || value === null || value === \"\") {\n if (param.modifier !== \"?\" && param.modifier !== \"*\") {\n throw new McpToolError(`\"${param.name}\" of \"${plan.descriptor.name}\" must not be empty.`);\n }\n path = path.replace(`/${token}`, \"\");\n continue;\n }\n path = path.replace(token, encodeSegment(plan.descriptor.name, param, String(value)));\n }\n return path;\n }\n\n private async formData(\n plan: Plan,\n input: Record<string, unknown>,\n json: Record<string, unknown>,\n ctx: ToolContext | undefined,\n ): Promise<FormData> {\n const name = plan.descriptor.name;\n if (!ctx) {\n throw new Error(\n `McpRegistry: \"${name}\" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`,\n );\n }\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n const id =\n field.binder === \"input\"\n ? (input[field.name] as string)\n : await this.bind(plan, `the file \"${field.name}\"`, () =>\n (field.binder as McpFileBinder)(ctx),\n );\n if (typeof id !== \"string\" || id === \"\") {\n throw new McpToolError(\n `\"${name}\" needs a file for \"${field.name}\", and this turn has none. Ask the user to attach one.`,\n );\n }\n // Scoped to the caller: someone else's id is a not-found, worded like an\n // invented one, and that error is what the model reads.\n form.append(field.name, await ctx.attachments.file(id));\n }\n return form;\n }\n\n /**\n * Runs an app's binder. Its failure is the server's, not the model's, so the\n * model is told only that; the app gets the error in its log.\n */\n private async bind<T>(plan: Plan, what: string, fn: () => T | Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n console.error(`[gemi/mcp] Binding ${what} of \"${plan.descriptor.name}\" failed:`, error);\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n }\n}\n\nfunction assertLocal(caller: McpCaller): asserts caller is Extract<McpCaller, { kind: \"local\" }> {\n if (caller?.kind !== \"local\") {\n throw new Error(\n \"McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have — and until it does there is no remote surface to call from.\",\n );\n }\n}\n\n/** A binder is a function or `\"input\"`; anything else would leave the value to nobody. */\nfunction assertBinder(where: string, at: string, binder: unknown) {\n if (binder !== \"input\" && typeof binder !== \"function\") {\n throw new Error(`${where}: ${at} must be a function or \"input\".`);\n }\n}\n\nfunction annotationsFor(method: McpMethod): McpToolAnnotations {\n switch (method) {\n case \"GET\":\n return Object.freeze({ readOnlyHint: true as const });\n case \"DELETE\":\n return Object.freeze({ destructiveHint: true as const });\n case \"PUT\":\n return Object.freeze({ idempotentHint: true as const });\n default:\n return Object.freeze({});\n }\n}\n\n/**\n * One schema out of two: the app's `input`, and the strings for `\"input\"`\n * params and files.\n *\n * Built by hand, like `questionSchema` in `ai/Agent.ts`, rather than by\n * widening `s` with a merge: `Schema.ts` is deliberately the strict\n * structured-output subset and owns no operation on a finished schema. Both\n * halves are real `s` schemas, each parses the whole value and drops the keys\n * that are not its own — which is also where a bound param the model sent\n * anyway disappears, since neither half declares it.\n */\nfunction combineSchemas(\n input: AnySchema | undefined,\n base: JSONSchema | undefined,\n extras: AnySchema,\n): Schema<Record<string, unknown>> {\n const extra = extras.toJSONSchema();\n const json: JSONSchema = {\n ...(base ?? {}),\n type: \"object\",\n properties: { ...(base?.properties ?? {}), ...extra.properties },\n required: [...(base?.required ?? []), ...(extra.required ?? [])],\n additionalProperties: false,\n };\n\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"expected an object\"] };\n }\n const errors: string[] = [];\n let out: Record<string, unknown> = {};\n if (input) {\n const own = input.safeParse(value);\n if (own.ok === false) errors.push(...own.errors);\n else out = { ...own.value };\n }\n const more = extras.safeParse(value);\n if (more.ok === false) errors.push(...more.errors);\n else out = { ...out, ...more.value };\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as Schema<Record<string, unknown>>;\n}\n\n/**\n * A model-supplied param, as one encoded path segment. `.` and `..` are\n * refused rather than encoded: they encode to themselves, and URL parsing\n * would walk them out of the route.\n */\nfunction encodeSegment(tool: string, param: PathParam, value: string): string {\n const parts = param.modifier === \"*\" || param.modifier === \"+\" ? value.split(\"/\") : [value];\n if (parts.some((part) => part === \".\" || part === \"..\")) {\n throw new McpToolError(`\"${value}\" is not a valid value for \"${param.name}\" of \"${tool}\".`);\n }\n return parts.map(encodeURIComponent).join(\"/\");\n}\n\n/**\n * A JSON field as a multipart form field. A form has only strings, so the\n * route reads `\"12\"` where a JSON body would have carried `12` — what a\n * browser form sends the same route. An array becomes the key repeated, which\n * `HttpRequest` reads back as an array.\n */\nfunction appendField(form: FormData, key: string, value: unknown) {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendField(form, key, item);\n return;\n }\n form.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\n\n/** A GET's input, as the query string `HttpRequest.search` reads. */\nfunction toQuery(json: Record<string, unknown>): string {\n const search = new URLSearchParams();\n const add = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) add(key, item);\n return;\n }\n search.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n };\n for (const [key, value] of Object.entries(json)) add(key, value);\n return search.toString();\n}\n\nasync function readResponse(name: string, response: Response): Promise<unknown> {\n if (response.status >= 200 && response.status < 300) {\n const type = response.headers.get(\"Content-Type\");\n if (type && !READABLE.test(type)) {\n const size = (await response.arrayBuffer()).byteLength;\n return `\"${name}\" answered with ${size} bytes of ${type}, which is not shown.`;\n }\n const text = await response.text();\n if (text === \"\") return null;\n if (text.length > MAX_RESULT_BODY) {\n return `${text.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${text.length} characters]`;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n const text = await response.text();\n if (response.status >= 400 && response.status < 500) {\n const shown = text.length > MAX_ERROR_BODY ? `${text.slice(0, MAX_ERROR_BODY)}…` : text;\n throw new McpToolError(\n `\"${name}\" was refused with ${response.status}${shown ? `: ${shown}` : \".\"}`,\n response.status,\n );\n }\n if (response.status < 500) {\n // A redirect, or a 1xx: nothing the model can follow, and nothing the\n // dispatcher logged.\n console.error(\n `[gemi/mcp] \"${name}\" answered ${response.status}${response.headers.get(\"Location\") ? ` to ${response.headers.get(\"Location\")}` : \"\"}, which a tool call cannot follow.`,\n );\n }\n throw new McpToolError(`\"${name}\" failed on the server.`, response.status);\n}\n",
30
30
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { McpRegistry } from \"../mcp/McpRegistry\";\nimport { ApiRouteDispatcher } from \"./ApiRouteDispatcher\";\nimport { DomainRouter } from \"./DomainRouter\";\nimport { ViewRouteDispatcher } from \"./ViewRouteDispatcher\";\nimport type { ApiRouteConfig, DomainsConfig, McpRouteConfig, ViewRouteConfig } from \"./config\";\nimport type { Repository } from \"../../support/Repository\";\n\nfunction readConfig<T>(config: Repository, key: string): T {\n const slice = config.get<T>(key);\n if (!slice) {\n throw new Error(\n `Missing \"${key}\" configuration. Route dispatching needs a root router — declare it in \"app/config/route.ts\".`,\n );\n }\n return slice;\n}\n\n/**\n * Owns both route dispatchers. Laravel ships a single RouteServiceProvider for\n * every route file it loads; the api/view split is a config slice, not a\n * separate provider.\n */\nexport class RouteServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n ApiRouteDispatcher,\n () =>\n new ApiRouteDispatcher(\n readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n ),\n );\n\n this.app.singleton(\n ViewRouteDispatcher,\n () =>\n new ViewRouteDispatcher(\n readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n ),\n );\n\n // The root pair above is the root group's; the other `route.domains`\n // groups get their own only when they bring their own routers.\n this.app.singleton(\n DomainRouter,\n () =>\n new DomainRouter(\n { api: this.app.make(ApiRouteDispatcher), view: this.app.make(ViewRouteDispatcher) },\n {\n api: readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n view: readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n domains: this.app.config.get<DomainsConfig | undefined>(\"route.domains\"),\n },\n ),\n );\n\n // Bound whether or not the app declares one, so asking for it without\n // `route.mcp` fails with a sentence rather than an unbound token.\n this.app.singleton(McpRegistry, () => {\n const config = this.app.config.get<McpRouteConfig | undefined>(\"route.mcp\");\n if (!config?.router) {\n throw new Error(\n 'No MCP router is configured. Declare one as `mcp: { router }` in \"app/config/route.ts\".',\n );\n }\n return new McpRegistry(new config.router(), this.app.make(ApiRouteDispatcher));\n });\n }\n\n /**\n * The dispatchers of every host group, and the MCP registry when an app declares one, must\n * not be built lazily: constructing the dispatchers flattens the route\n * tables and runs `assertNoReservedRoutePaths`, and constructing the registry\n * resolves every tool against those tables. A missing `route` config, a\n * route under a reserved prefix or a tool naming a route that is gone has to\n * fail the boot rather than the first request, or the first tool call, that\n * happens to hit it.\n */\n boot() {\n this.app.make(ApiRouteDispatcher);\n this.app.make(ViewRouteDispatcher);\n // Builds every host group's dispatchers and validates `route.domains`.\n this.app.make(DomainRouter);\n if (this.app.config.get(\"route.mcp\")) {\n this.app.make(McpRegistry);\n }\n }\n}\n"
31
31
  ],
32
- "mappings": ";iwBAmCA,SAAsB,JAAO,LAAC,JAA6B,LACzD,HAAI,LAQF,HAAI,LAAE,AAAM,JAAI,UAAU,KAAK,CAAG,EAChC,OAEF,MAAO,EAAO,CAMd,QAAQ,MACN,2CAA2C,EAAI,QAC/C,CACF,EACA,OAGF,GAAI,CACF,MAAM,EAAI,OAAO,KAAK,CAAG,EACzB,MAAO,EAAO,CACd,QAAQ,MAAM,4BAA4B,EAAI,QAAS,CAAK,EAE9D,GAAI,CACF,MAAM,EAAI,SAAS,KAAK,CAAG,EAC3B,MAAO,EAAO,CACd,QAAQ,MAAM,qBAAqB,EAAI,QAAS,CAAK,EAEvD,GAAI,CACF,MAAM,EAAI,WAAW,KAAK,CAAG,EAC7B,MAAO,EAAO,CACd,QAAQ,MAAM,6BAA6B,EAAI,QAAS,CAAK,GAyB1D,MAAM,CAAU,OACd,OAAQ,YAEP,QAA2B,CAAC,EAC5B,SAQS,SAAW,IAAI,IASxB,QAAU,GAElB,WAAW,CAAC,EAAkC,CAC5C,KAAK,SAAW,EAAO,QAqBrB,KAAI,EAAqC,CAC3C,MAAO,CAAC,GAAG,KAAK,QAAQ,EAc1B,OAAO,CAAC,EAAgC,CACtC,KAAK,SAAW,EASlB,KAAK,CAAC,EAAsB,CAAC,IAAO,EAAG,EAAG,CAExC,GADA,KAAK,QAAU,GACX,KAAK,SAAS,SAAW,EAC3B,OAGF,IAAM,EAAY,WAAW,iBAAmB,IAAI,IAO9C,EAAU,IAAI,IAEpB,QAAW,KAAO,KAAK,SAAU,CAC/B,IAAM,EAAM,IAAI,EAChB,GAAI,CAAC,EAAI,KAAM,CAOb,QAAQ,MACN,oCAA8B,EAAI,MAAQ,sPAK5C,EACA,SAEF,GAAI,CAAC,EAAI,KAAM,CACb,QAAQ,MAAM,0CAA0C,EAAI,MAAM,EAClE,SAEF,IAAM,EAAQ,EAAQ,IAAI,EAAI,IAAI,EAClC,GAAI,IAAU,OAAW,CAOvB,QAAQ,MACN,iCAAiC,EAAI,gBAAU,sBAC5B,EAAI,MAAQ,sGAEjC,EACA,SAEF,EAAQ,IAAI,EAAI,KAAM,EAAI,MAAQ,oBAAoB,EAItD,EAAS,IAAI,EAAI,IAAI,GAAG,KAAK,EAK7B,IAAM,EAAS,IAAI,KAAK,EAAI,KAAM,IAAM,CACtC,GAAI,KAAK,QAAS,OAClB,OAAO,KAAK,MAAM,EAAI,KAAM,IAAM,EAAI,IAAM,GAAQ,CAAG,CAAC,CAAC,EAC1D,EAED,EAAS,IAAI,EAAI,KAAM,CAAM,EAC7B,KAAK,QAAQ,KAAK,CAAM,GAQ5B,IAAI,EAAG,CACL,KAAK,QAAU,GACf,QAAW,KAAU,KAAK,QACxB,EAAO,KAAK,EAEd,KAAK,QAAU,CAAC,OAeZ,MAAK,CAAC,EAAY,IAAwC,CAC9D,KAAK,KAAK,EAEV,IAAI,EACE,EAAW,IAAI,QAAc,CAAC,IAAY,CAC9C,GAAI,IAAc,IAAU,EAAQ,WAAW,EAAS,CAAS,EAClE,EAOD,OANA,MAAM,QAAQ,KAAK,CACjB,QAAQ,WAAW,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,IAAM,EAAE,IAAI,CAAC,EACjE,CACF,CAAC,EACD,aAAa,CAAK,EAEX,CACL,WAAY,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,KAAO,IAAK,EAAE,IAAK,EAAE,CACpE,KAIE,QAAO,EAAW,CACpB,OAAO,KAAK,SAAS,KAGf,KAAK,CAAC,EAAc,EAAuC,CACjE,IAAM,EAAM,CAAC,EAIP,EAAO,QAAQ,QAAQ,EAC1B,KAAK,CAAI,EACT,QAAQ,IAAM,KAAK,SAAS,OAAO,CAAG,CAAC,EAE1C,OADA,KAAK,SAAS,IAAI,EAAK,CAAE,KAAM,CAAE,OAAM,UAAW,IAAI,IAAO,EAAG,MAAK,CAAC,EAC/D,EAEX,CCzSA,uBAAS,wBAsBT,IAAM,GAAmB,IAEnB,GAAe,CAAC,IACpB,KAAK,IAAI,GAAkB,KAAK,MAAM,EAAY,EAAE,CAAC,EAEhD,MAAM,WAA6B,CAAgB,CACxD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EAAa,KAAK,IAAI,OAAO,IAAiB,QAAS,CAAC,CAAC,EAAG,CAC9D,YAAa,KAAK,GACpB,CAAC,CACL,OA0BI,KAAI,EAAG,CACX,IAAM,EAAQ,KAAK,IAAI,OAAO,IAAiB,QAAS,CAAC,CAAC,EAC1D,GAAI,EAAM,OAAS,OAAW,OAE9B,IAAQ,WAAY,EAAa,EAAoB,EAAG,CAAK,EAC7D,KAAK,IAAI,KAAK,CAAY,EAAE,QAAQ,MAAM,GAAa,CAAO,CAAC,OA2B3D,SAAQ,CAAC,EAAiC,CAE9C,GAAI,CAAC,KAAK,IAAI,SAAS,CAAY,EAAG,OACtC,IAAM,EAAQ,KAAK,IAAI,KAAK,CAAY,EACxC,GAAI,EAAM,QAAU,EAClB,QAAQ,IACN,qCAAqC,EAAM,gCAC7C,EAEF,IAAM,EAAS,GAAS,WAChB,cAAe,MAAM,EAAM,MACjC,IAAW,OAAY,IAAW,KAAK,IAAI,EAAG,EAAS,GAAa,CAAM,CAAC,CAC7E,EACA,GAAI,EAAW,OAAS,EAKtB,OAJA,QAAQ,MACN,iDACE,EAAW,IAAI,CAAC,IAAQ,GAAG,EAAI,SAAS,EAAI,KAAK,EAAE,KAAK,IAAI,CAChE,EACO,CAAE,UAAW,EAAK,EAG/B,CAwBO,SAAS,EAAsB,CAAC,EAA0B,CAE/D,GADA,GAAqB,CAAW,EAC5B,mBAAyB,aAAc,OAAO,GAAiB,CAAW,EAC9E,GAAI,GAAiB,CAAW,EAAG,OACnC,GAAI,CAAC,EAAoB,EAAG,OAC5B,GAAI,CAAC,EAAY,MAAM,CAAY,EAAG,OACtC,EAAY,KAAK,CAAY,EAAE,MAAM,EAGvC,SAAS,EAAgB,CAAC,EAA0B,CAClD,IAAM,EAAS,EAAY,OAAO,IAAiB,QAAS,CAAC,CAAC,EAAE,QAAU,SAC1E,OAAO,IAAW,UAAY,aAAkB,EAWlD,SAAS,EAAkB,CAAC,EAA0B,CACpD,GAAI,GAAiB,CAAW,EAAG,MAAO,GAE1C,GAAI,OADW,EAAY,OAAO,IAAiB,QAAS,CAAC,CAAC,EAAE,SAC1C,YAAc,CAAC,EAAY,MAAM,CAAY,EAAG,MAAO,GAC7E,GAAI,CACF,MAAO,CAAC,EAAY,KAAK,CAAY,EAAE,QACvC,KAAM,CACN,MAAO,IAgBX,SAAS,EAAoB,CAAC,EAA0B,CACtD,IAAM,EAAQ,QAAQ,IAAI,iBAC1B,GAAI,IAAU,QAAa,GAAc,EAAG,OAC5C,GAAI,QAAQ,IAAI,WAAa,QAAa,CAAC,GAAc,OACzD,GAAI,GAAkB,EAAG,CACvB,GAAI,CAAC,GAAmB,CAAW,EAAG,OACtC,QAAQ,KACN,2QAIF,EACK,QAAI,EAAM,KAAK,EAAE,YAAY,IAAM,KACxC,QAAQ,KACN,4BAA4B,4GAE9B,EA+BJ,SAAS,EAAgB,CAAC,EAA0B,CAClD,IAAM,EAAW,WAAW,eAC5B,GAAI,CAAC,EAAU,OAGf,GAFA,WAAW,eAAiB,OACvB,EAAS,KAAK,EACf,EAAY,MAAM,CAAY,EAAG,EAAY,KAAK,CAAY,EAAE,MAAM,ECvOrE,MAAM,WAA4B,CAAgB,CACvD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IAAM,IAAI,EAAY,KAAK,IAAI,OAAO,IAAgB,OAAQ,CAAC,CAAC,CAAC,CACnE,EAEJ,CCGA,IAAM,GAAmB,IAEnB,GAAe,CAAC,IAAsB,KAAK,IAAI,GAAkB,KAAK,MAAM,EAAY,EAAE,CAAC,EAE1F,MAAM,WAAgC,CAAgB,CAC3D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,EAAuB,EACvB,KAAK,IAAI,OAAO,IAAoB,WAAY,CAAC,CAAC,CACpD,CACF,CACJ,OA0BI,KAAI,EAAG,CACX,IAAM,EAAY,KAAK,IAAI,KAAK,CAAS,EACnC,EAAQ,KAAK,IAAI,OAAO,IAAoB,WAAY,CAAC,CAAC,EAEhE,GAAI,EAAM,OAAS,OAAW,CAC5B,IAAQ,WAAY,EAAa,EAAuB,EAAG,CAAK,EAChE,EAAU,QAAQ,MAAM,GAAiB,CAAO,CAAC,EAqBnD,GAAI,QAAQ,IAAI,mBAAqB,IAAK,OAE1C,IAAM,EAAM,KAAK,IACjB,EAAU,MAAM,CAAC,IAAO,GAAc,IAAI,EAAK,CAAE,CAAC,OAqB9C,SAAQ,CAAC,EAAiC,CAG9C,GAAI,CAAC,KAAK,IAAI,SAAS,CAAS,EAAG,OACnC,IAAM,EAAY,KAAK,IAAI,KAAK,CAAS,EACzC,GAAI,EAAU,QAAU,EACtB,QAAQ,IAAI,qCAAqC,EAAU,+BAA+B,EAE5F,IAAM,EAAS,GAAS,WAChB,cAAe,MAAM,EAAU,MACrC,IAAW,OAAY,IAAW,KAAK,IAAI,EAAG,EAAS,GAAa,CAAM,CAAC,CAC7E,EACA,GAAI,EAAW,OAAS,EAOtB,OANA,QAAQ,MACN,+CACE,EACG,IAAI,CAAC,IAAS,GAAG,EAAK,iBAAiB,EAAK,UAAU,YAAY,IAAI,EACtE,KAAK,IAAI,CAChB,EACO,CAAE,UAAW,EAAK,EAG/B,CC9GO,MAAM,UAAkC,EAAkB,CAC1C,UAArB,WAAW,CAAU,EAAoB,cAAe,CACtD,MAAM,EADa,oBAKjB,UAAS,EAAY,CACvB,OAAgB,GAAI,KAAK,SAAS,OAG9B,KAAI,EAAuC,CAC/C,GAAI,CAAC,KAAK,UACR,MAAM,IAAI,EAAyB,KAAK,SAAS,EAGnD,IAAM,EAAiB,EAAS,KAAK,SAAS,EAM9C,OAAO,MAAM,EAAM,SAAS,IAAM,EAAM,SAAS,CAAC,OAiB9C,MAAK,CAAC,EAAa,EAAiB,EAAqD,CAC7F,GAAI,CAAC,KAAK,UACR,MAAM,IAAI,EAAyB,KAAK,SAAS,EAGnD,IAAM,EAAiB,EAAS,KAAK,SAAS,EACxC,EAAgB,KAAK,eAAe,CAAK,EACzC,EAAgC,CAAE,QAAO,EAC/C,GAAI,EAAe,EAAK,UAAY,EAAK,MAazC,OARA,MAAM,EAAM,SAAS,IACnB,EAAM,OAAO,CACX,MAAO,CAAE,KAAI,EACb,OAAQ,CAAE,SAAQ,CAAK,EACvB,OAAQ,CACV,CAAC,CACH,EAEO,CAAE,eAAc,EAGjB,cAAc,CAAC,EAAqB,CAC1C,IAAM,EAAQ,GAAO,SAAS,QAAQ,UACtC,OAAO,IAAU,QAAa,EAAM,OAAS,SAEjD,CCxBO,SAAS,EAAoB,CAAC,EAAwC,CAC3E,OAAO,EAGF,SAAS,EAAsB,EAMpC,CACA,MAAO,CACL,SAAU,OACV,QAAS,GACT,OAAQ,IAAI,EACZ,MAAO,cACP,IAAK,GACL,QAAS,OACT,WAAY,OACZ,eAAgB,GAClB,ECzEK,MAAM,WAAgC,CAAgB,CAC3D,QAAQ,EAAG,CACT,KAAK,IAAI,UAAU,EAAgB,IAAM,CACvC,IAAM,EAAW,KAAK,IAAI,OAAO,IAAoB,WAAY,CAAC,CAAC,EAC7D,EAAS,EAAa,GAAuB,EAAG,CAAQ,EAkB9D,GAAI,GAAU,QAAU,QAAa,GAAU,SAAW,OACxD,EAAO,OAAS,IAAI,EAA0B,EAAS,KAAK,EACvD,QACL,GAAU,QAAU,QACpB,EAAS,kBAAkB,GAC3B,EAAS,OAAO,YAAc,EAAS,MAEvC,EAAI,QACF,yCAAyC,EAAS,kCAAkC,EAAS,OAAO,8DACtG,EAGF,OAAO,IAAI,EAAe,EAAQ,CAAC,IAAY,EAAI,QAAQ,CAAO,CAAC,EACpE,OAGG,KAAI,EAAG,CACX,IAAM,EAAW,KAAK,IAAI,KAAK,CAAc,EAC7C,GAAI,CAAC,EAAS,OAAO,QAAS,OAM9B,GAAI,CACF,MAAM,EAAS,QAAQ,EACvB,MAAO,EAAO,CACd,EAAI,MACF,kDACE,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GAEzD,GAGN,CC3DO,MAAM,WAA4B,CAAgB,CACvD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IAAM,IAAI,EAAY,KAAK,IAAI,OAAO,IAAgB,OAAQ,CAAC,CAAC,CAAC,CACnE,EAEJ,CCiBO,SAAS,EAAe,CAAC,EAA8B,CAC5D,MAAO,YAAY,IAmBd,SAAS,EAAc,CAC5B,EACA,EACe,CACf,GAAmB,CAAQ,EAE3B,IAA0B,YAApB,EACkB,QAAlB,EACoB,OAApB,GADS,EAET,EAAU,EAAS,MAAM,KAEzB,EAAM,cAAc,EAAI,CAC5B,YAAc,EACd,QAAU,EACV,OAAS,OAEH,IAAG,IAAI,EAAoB,CAC/B,IAAO,EAAW,GAAQ,GAAY,CAAO,EACvC,EAAQ,EAAI,CAAY,EAAE,UAAU,EAAW,CAAI,EACzD,MAAM,IAAI,EAAS,EAAE,OAAO,CAAK,EA6BnC,MAAM,CAAC,EAAc,CACnB,QAAQ,MACN,gBAAgB,EAAS,6BAA6B,kDACR,iEAE9C,CACF,EAGF,YAAY,CAAC,EAAc,CACzB,QAAQ,MACN,gBAAgB,EAAS,gCAAgC,iBACxC,4FAEjB,CACF,EAEJ,EAoBA,OALA,OAAO,eAAe,EAAK,OAAQ,CACjC,MAAO,GAAgB,EAAS,IAAI,EACpC,SAAU,EACZ,CAAC,EAEM,EAoBT,SAAS,EAAkB,CAAC,EAA+B,CACzD,GAAI,OAAO,yBAAyB,EAAU,MAAM,GAAG,SAAU,OAEjE,MAAU,MACR,gBAAgB,EAAS,8GAEvB,0EACA,uDAAuD,EAAS,QACpE,EAmBF,SAAS,EAAW,CAAC,EAAyC,CAC5D,OAAQ,OAAO,EAAQ,KAAO,SAAW,EAAU,EAAQ,GClHtD,MAAM,CAAa,OACjB,OAAQ,SAGP,UAA4C,CAAC,EAW7C,OAAqC,CAAC,EAMtC,UAAY,IAAI,IAShB,mBAAqB,IAAI,IAExB,OAET,WAAW,CAAC,EAAsB,CAAC,EAAG,CACpC,KAAK,OAAS,EAAa,EAAoB,EAAG,CAAM,EACxD,KAAK,aAAa,KAAK,OAAO,SAAS,EA0BzC,YAAY,CAAC,EAA4B,CACvC,KAAK,OAAO,UAAY,EAExB,KAAK,UAAY,CAAC,EAClB,KAAK,OAAS,CAAC,EACf,IAAM,EAAU,IAAI,IAEpB,QAAW,KAAY,EAAW,CAOhC,GAAI,CAAC,EAAS,MAAO,CACnB,QAAQ,MACN,YAAY,EAAS,sJAGvB,EACA,SASF,GAAI,EAAQ,IAAI,EAAS,IAAI,EAAG,CAC9B,QAAQ,MACN,kCAAkC,EAAS,6BACzC,kIAEJ,EACA,SAEF,EAAQ,IAAI,EAAS,IAAI,EAUzB,IAAM,EAAO,EAAS,MAAM,KACtB,EAAW,IAAI,EAErB,KAAK,OAAO,KAAU,EAAS,OAC9B,KAAK,UAAU,KAAU,CAAC,GAAG,KAAK,CACjC,WACA,IAAK,EAAS,OAAS,GAAe,EAAU,CAAQ,EAAI,IAC9D,CAAC,MAcD,mBAAkB,EAAiC,CACrD,OAAO,OAAO,OAAO,KAAK,SAAS,EAChC,KAAK,EACL,QAAQ,EAAG,SAAW,EAAM,CAAC,CAAG,EAAI,CAAC,CAAE,KAcxC,oBAAmB,EAAiC,CACtD,MAAO,CAAC,GAAG,KAAK,OAAO,SAAS,EAgBlC,QAAQ,CAAC,EAAc,EAAiC,CACtD,GAAI,KAAK,cAAc,EAAO,EAAM,EAAK,EAAG,OACvC,KAAK,aAAa,EAAO,CAAI,OAa9B,gBAAe,CACnB,EACA,EACe,CACf,GAAI,KAAK,cAAc,EAAO,EAAM,EAAI,EAAG,OAC3C,OAAO,KAAK,aAAa,EAAO,CAAI,EAwB9B,aAAa,CACnB,EACA,EACA,EACS,CAKT,IAAQ,OAAM,eAAgB,EAAM,YAIpC,GAAI,CAAC,EAAa,MAAO,GAEzB,IAAM,EAAW,GAAiB,IAAM,KAAK,aAAa,EAAO,CAAI,CAAC,EACtE,GAAI,GAAY,EAAS,KAAK,uBAAuB,CAAI,EACzD,OAAO,OAkEO,aAAY,CAC1B,EACA,EACe,CACf,IAAM,EAAQ,EAAM,YAAiC,KAC/C,EAAW,KAAK,UAAU,GAEhC,GAAI,CAAC,GAAU,OAAQ,CACrB,KAAK,uBAAuB,CAAI,EAChC,OAGF,QAAa,SAAU,EAAU,SAAS,EAAU,CAClD,GAAI,EAAK,CACP,KAAK,QAAQ,EAAK,EAAU,EAAM,CAAI,EACtC,SAGF,GAAI,CACF,MAAM,IAAI,EAAS,EAAE,OAAO,CAAK,EACjC,MAAO,EAAO,CACd,QAAQ,MACN,gBAAgB,EAAS,6BAA6B,UACpD,uEACF,CACF,IAsBN,SAAS,CAAC,EAAmB,EAA2B,CAAC,EAAU,CACjE,IAAM,EAAa,KAAK,OAAO,GAE/B,GAAI,CAAC,EACH,MAAU,MACR,6BAA6B,uKAG3B,wEACA,+FAC6B,OACjC,EAGF,OAAO,IAAI,EAAW,GAAG,CAAI,EAkBvB,OAAO,CACb,EACA,EACA,EACA,EACA,CACA,GAAI,IAAS,OAAW,CACtB,QAAQ,MACN,gBAAgB,EAAS,uBAAuB,mKAGjB,sBAC1B,2CACP,EACA,OAGF,IAAM,EAAS,CAAC,IACd,QAAQ,MACN,gBAAgB,EAAS,gCAAgC,kFAGzD,CACF,EAKF,GAAI,CAIF,EAAI,CAAY,EACb,KAAK,EAAK,KAAK,UAAU,CAAC,EAAW,CAAI,CAAC,EAAG,CAAE,cAAe,EAAM,CAAC,EACrE,MAAM,CAAM,EACf,MAAO,EAAO,CACd,EAAO,CAAK,GAmBR,sBAAsB,CAAC,EAAc,CAC3C,GAAI,mBAAyB,aAAc,OAC3C,GAAI,KAAK,mBAAmB,IAAI,CAAI,EAAG,OACvC,KAAK,mBAAmB,IAAI,CAAI,EAEhC,QAAQ,KACN,UAAU,2DACL,4DACH,oEACA,uIAGJ,EAGM,sBAAsB,CAAC,EAAc,CAC3C,GAAI,mBAAyB,aAAc,OAC3C,GAAI,KAAK,UAAU,IAAI,CAAI,EAAG,OAC9B,KAAK,UAAU,IAAI,CAAI,EAEvB,QAAQ,KACN,UAAU,gLAEgD,gBAChD,+BAAkC,yBAC9C,EAEJ,CChgBO,MAAM,WAA6B,CAAgB,CACxD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IAAM,IAAI,EAAa,KAAK,IAAI,OAAO,IAAiB,SAAU,CAAC,CAAC,CAAC,CACvE,OA2CI,KAAI,EAAG,CACX,IAAM,EAAU,KAAK,IAAI,KAAK,CAAY,EACpC,EAAQ,KAAK,IAAI,OAAO,IAAiB,SAAU,CAAC,CAAC,EAE3D,GAAI,EAAM,YAAc,OAAW,CACjC,IAAQ,gBAAiB,EAAa,EAAoB,EAAG,CAAK,EAClE,EAAQ,aAAa,MAAM,GAAkB,CAAY,CAAC,EAM5D,IAAM,EAAO,EAAQ,mBACrB,GAAI,EAAK,SAAW,EAAG,OAEvB,IAAM,EAAQ,KAAK,IAAI,KAAK,CAAY,EACxC,QAAW,KAAO,EAChB,EAAM,YAAY,CAAG,EAG3B,CCvEO,MAAM,WAAkC,CAAgB,CAC7D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,KAAK,IAAI,OAAO,IAAsB,aAAc,CAAC,CAAC,CACxD,CACJ,EAEJ,CCVO,MAAM,WAA6B,CAAgB,CACxD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IAAM,IAAI,EAAa,KAAK,IAAI,OAAO,IAAiB,QAAS,CAAC,CAAC,CAAC,CACtE,EAEJ,CCPO,MAAM,WAAgC,CAAgB,CAC3D,QAAQ,EAAG,CACT,KAAK,IAAI,SAAS,EAAU,IAAI,CAAU,EAE9C,CCEO,SAAS,EAAe,CAAC,EAA8B,CAC5D,OAAO,EAGF,SAAS,EAAiB,EAAwB,CACvD,MAAO,CACL,YAAa,SACb,gBAAiB,IAAM,GACvB,aAAc,IAAM,EACtB,ECdK,MAAM,WAA2B,CAAgB,CACtD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,GAAkB,EAClB,KAAK,IAAI,OAAO,IAAe,MAAO,CAAC,CAAC,CAC1C,CACF,CACJ,OAoBI,KAAI,EAAG,CACX,GAAI,CAAC,QAAQ,IAAI,SACf,OAEF,MAAM,KAAK,IAAI,KAAK,CAAU,EAAE,KAAK,EAEzC,CClCO,MAAM,WAAkC,CAAgB,CAC7D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,GAAyB,EACzB,KAAK,IAAI,OAAO,IAAsB,aAAc,CAAC,CAAC,CACxD,CACF,CACJ,EAGF,IAAI,EAAG,CAGL,KAAK,IAAI,KAAK,CAAkB,EAAE,uBAAuB,EAE7D,CCzBO,MAAe,CAAkB,CAaxC,CCMO,SAAS,EAAc,CAAC,EAAa,EAAgB,CAC1D,OAAO,KAAK,MAAM,EAAM,CAAM,EAAI,EAI7B,SAAS,EAAc,CAAC,EAAiB,EAAgB,CAC9D,GAAI,GAAU,EAAG,MAAO,GACxB,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,EAAS,GAAW,CAAM,CAAC,EAItD,SAAS,CAAa,CAC3B,EACA,EACA,EACA,EACA,CACA,OAAO,EAAW,GAAe,EAAS,CAAM,EAAI,EAU/C,SAAS,EAAgB,CAAC,EAO9B,CACD,IAAQ,UAAS,WAAU,UAAS,SAAQ,QAAO,QAAS,EAEtD,EAAS,EAAQ,EAIvB,GAAI,EAAS,EAAG,OAAO,EAEvB,IAAM,EAAkB,KAAK,IAAI,EAAG,EAAS,CAAO,EAGpD,GAAI,EAAW,EAAG,CAEhB,IAAM,EAAS,GAAU,GAAK,EAAS,GAAW,GAClD,GAAI,GAAU,EACZ,OAAO,KAAK,IAAI,EAAG,KAAK,KAAK,EAAS,CAAO,CAAC,EAMlD,GAAI,GAAW,EAAQ,OAAO,EAC9B,GAAI,GAAW,EAAG,OAAO,EAEzB,IAAM,EAAS,GAAU,EAAI,EAAS,GACtC,OAAO,EAAkB,KAAK,IAAI,EAAG,KAAK,KAAK,CAAM,CAAC,EAQjD,SAAS,EAAW,CAAC,EASR,CAClB,IAAQ,UAAS,UAAS,WAAU,MAAK,UAAS,SAAQ,QAAO,QAC/D,EAEF,GAAI,EAAS,CACX,IAAM,EAAQ,EAAc,EAAS,EAAU,EAAS,CAAM,EAC9D,MAAO,CACL,QAAS,GACT,QACA,UAAW,KAAK,IAAI,EAAG,KAAK,MAAM,EAAQ,CAAK,CAAC,EAChD,QAAS,EAAM,EAAU,EACzB,WAAY,CACd,EAGF,IAAM,EAAa,GAAiB,CAClC,UACA,WACA,UACA,SACA,QACA,MACF,CAAC,EAED,MAAO,CACL,QAAS,GACT,QACA,UAAW,EACX,QAAS,EAAM,EACf,YACF,EChGK,MAAM,UAA4B,CAAkB,CACjD,QAAU,IAAI,IACd,QAER,WAAW,CAAC,EAAsC,CAAC,EAAG,CACpD,MAAM,EACN,KAAK,QAAU,KAAK,IAAI,EAAG,EAAQ,SAAW,GAAO,EAGvD,OAAO,CAAC,EAAwC,CAC9C,IAAQ,MAAK,QAAO,UAAW,EACzB,EAAO,EAAO,MAAQ,EACtB,EAAM,KAAK,IAAI,EACf,EAAc,GAAe,EAAK,CAAM,EACxC,EAAU,EAAM,EAEhB,EAAS,KAAK,KAAK,EAAK,EAAQ,CAAW,EAO3C,EANQ,EACZ,EAAO,QACP,EAAO,SACP,EACA,CACF,EACwB,GAAQ,EAEhC,GAAI,EACF,EAAO,SAAW,EAOpB,GAFA,KAAK,QAAQ,OAAO,CAAG,EACvB,KAAK,QAAQ,IAAI,EAAK,CAAM,EACxB,KAAK,QAAQ,KAAO,KAAK,QAC3B,KAAK,MAAM,CAAG,EAGhB,OAAO,GAAY,CACjB,UACA,QAAS,EAAO,QAChB,SAAU,EAAO,SACjB,MACA,UACA,SACA,QACA,MACF,CAAC,EAIH,KAAK,EAAG,CACN,KAAK,QAAQ,MAAM,KAIjB,KAAI,EAAG,CACT,OAAO,KAAK,QAAQ,KAId,IAAI,CAAC,EAAa,EAAgB,EAA6B,CACrE,IAAM,EAAS,KAAK,QAAQ,IAAI,CAAG,EAEnC,GAAI,CAAC,GAAU,EAAO,SAAW,EAC/B,MAAO,CAAE,SAAQ,cAAa,QAAS,EAAG,SAAU,CAAE,EAGxD,GAAI,EAAO,cAAgB,EACzB,OAAO,EAGT,GAAI,EAAO,YAAc,IAAW,EAIlC,OAHA,EAAO,SAAW,EAAO,QACzB,EAAO,QAAU,EACjB,EAAO,YAAc,EACd,EAOT,OAHA,EAAO,SAAW,EAClB,EAAO,QAAU,EACjB,EAAO,YAAc,EACd,EAGD,KAAK,CAAC,EAAa,CACzB,QAAY,EAAK,KAAW,KAAK,QAE/B,GAAI,EAAM,EAAO,aAAe,EAAO,OAAS,EAC9C,KAAK,QAAQ,OAAO,CAAG,EAO3B,QAAW,KAAO,KAAK,QAAQ,KAAK,EAAG,CACrC,GAAI,KAAK,QAAQ,MAAQ,KAAK,QAAS,MACvC,KAAK,QAAQ,OAAO,CAAG,GAG7B,CCnHO,SAAS,EAAuB,CACrC,EACmB,CACnB,OAAO,EAGF,SAAS,EAAyB,EAAgC,CACvE,MAAO,CACL,OAAQ,IAAI,EACZ,MAAO,KACP,OAAQ,EACV,ECxBK,MAAM,WAAmC,CAAgB,CAC9D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,GAA0B,EAC1B,KAAK,IAAI,OAAO,IAAuB,cAAe,CAAC,CAAC,CAC1D,CACF,CACJ,EAEJ,CCLO,SAAS,EAAiB,CAAC,EAAkC,CAClE,OAAO,EAGF,SAAS,EAAmB,EAAgB,CACjD,MAAO,CACL,IAAK,QAAQ,IAAI,UACjB,QAAS,MACX,EChBK,MAAM,WAA6B,CAAgB,CACxD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,GAAoB,EACpB,KAAK,IAAI,OAAO,IAAiB,QAAS,CAAC,CAAC,CAC9C,CACF,CACJ,EAQF,QAAQ,EAAG,CACT,GAAI,CAAC,KAAK,IAAI,SAAS,CAAY,EAAG,OACtC,KAAK,IAAI,KAAK,CAAY,EAAE,MAAM,EAEtC,CC0EO,MAAM,UAAqB,KAAM,CAG3B,OAFX,WAAW,CACT,EACS,EACT,CACA,MAAM,CAAO,EAFJ,cAGT,KAAK,KAAO,eAEhB,CAGA,IAAM,GAAY,wBAGZ,GAAa,qCAOb,GAAiB,KASjB,EAAkB,IAGlB,GAAW,kDA2BV,MAAM,CAAY,CAOJ,iBANZ,OAAQ,aAEE,MAAQ,IAAI,IAE7B,WAAW,CACT,EACiB,EAIjB,CAJiB,kBAKjB,QAAY,EAAM,KAAgB,OAAO,QAAQ,EAAO,QAAU,CAAC,CAAC,EAClE,KAAK,MAAM,IAAI,EAAM,KAAK,KAAK,EAAM,CAAW,CAAC,EASrD,IAAI,CAAC,EAAmB,EAA6C,CAEnE,OADA,GAAY,CAAM,EACX,KAAK,YAAY,CAAM,EAQhC,WAAW,CAAC,EAA6C,CACvD,IAAM,EAA2B,CAAC,EAClC,QAAa,gBAAgB,KAAK,MAAM,OAAO,EAAG,CAChD,GAAI,GAAQ,OAAS,CAAC,EAAO,MAAM,SAAS,EAAW,IAAI,EAAG,SAC9D,GAAI,GAAQ,MAAQ,CAAC,EAAW,KAAK,KAAK,CAAC,IAAQ,EAAO,KAAK,SAAS,CAAG,CAAC,EAAG,SAC/E,EAAI,KAAK,CAAU,EAErB,OAAO,OAqBH,QAAO,CACX,EACA,EACA,EACA,EACkB,CAClB,GAAY,CAAM,EAClB,IAAM,EAAO,KAAK,MAAM,IAAI,CAAI,EAChC,GAAI,CAAC,EACH,MAAU,MAAM,wCAAwC,KAAQ,EAElE,IAAQ,cAAe,EAEjB,EAAS,EAAW,YAAY,UAAU,CAAI,EACpD,GAAI,EAAO,KAAO,GAChB,MAAM,IAAI,EAAa,0BAA0B,OAAU,EAAO,OAAO,KAAK,IAAI,GAAG,EAEvF,IAAM,EAAQ,EAAO,MAEf,EAAO,MAAM,KAAK,SAAS,EAAM,EAAO,EAAO,GAAG,GAMhD,KAAM,GAAY,KAAK,WAAW,yBACxC,IAAI,QAAQ,2BAA2B,GAAM,CAC/C,EACA,GAAI,IAAY,EAAW,IACzB,MAAM,IAAI,EAAa,IAAI,qBAAwB,KAAS,GAAG,EAGjE,IAAM,EAAgC,CAAC,EACvC,QAAW,KAAO,EAAK,SACrB,GAAI,EAAM,KAAS,OAAW,EAAK,GAAO,EAAM,GAGlD,IAAI,EACA,EAAQ,GACZ,GAAI,EAAK,WAAW,OAAS,EAC3B,EAAO,MAAM,KAAK,SAAS,EAAM,EAAO,EAAM,CAAG,EAC5C,QAAI,EAAW,SAAW,MAC/B,EAAQ,GAAQ,CAAI,EACf,QAAI,EAAK,SAAS,OAAS,EAChC,EAAO,EAGT,IAAI,EACJ,GAAI,CACF,EAAW,MAAM,KAAK,WAAW,WAC/B,EAAO,IACP,EAAW,OACX,EAAQ,GAAG,KAAQ,IAAU,EAC7B,CACF,EACA,MAAO,EAAO,CAId,MADA,QAAQ,MAAM,2BAA2B,aAAiB,CAAK,EACzD,IAAI,EAAa,IAAI,2BAA+B,GAAG,EAE/D,OAAO,MAAM,GAAa,EAAM,CAAQ,EAKlC,IAAI,CAAC,EAAc,EAAwC,CACjE,GAAI,CAAC,GAAU,KAAK,CAAI,EACtB,MAAU,MACR,eAAe,kKACjB,EAEF,IAAM,EAAQ,eAAe,OAAU,GAAa,UAAU,GAAa,OAC3E,GAAI,EAAE,aAAuB,SAAW,EAAY,mBAAqB,WACvE,MAAU,MACR,eAAe,4DACjB,EAEF,IAAQ,SAAQ,MAAK,QAAS,EAC9B,GAAI,EAAI,WAAW,WAAW,EAC5B,MAAU,MAAM,GAAG,2CAA+C,EAGpE,IAAM,EAAQ,KAAK,WAAW,WAAW,KAAO,GAChD,GAAI,CAAC,EACH,MAAU,MACR,GAAG,qFACL,EAKF,IAAM,EAAsB,CAAC,GAAG,EAAI,SAAS,EAAU,CAAC,EAAE,IAAI,GAAI,EAAO,MAAe,CACtF,KAAM,EACN,UACF,EAAE,EACI,EAAW,EAAK,QAAU,CAAC,EACjC,QAAW,KAAS,EAClB,GAAI,EAAE,EAAM,QAAQ,GAClB,MAAU,MACR,GAAG,sBAA0B,EAAM,0CACrC,EAGJ,QAAY,EAAK,KAAW,OAAO,QAAQ,CAAQ,EAAG,CACpD,GAAI,CAAC,EAAO,KAAK,CAAC,IAAU,EAAM,OAAS,CAAG,EAC5C,MAAU,MAAM,GAAG,OAAW,yCAA2C,EAE3E,GAAa,EAAO,UAAU,IAAO,CAAM,EAG7C,IAAI,EAAqB,CAAC,EACtB,EACJ,GAAI,EAAK,MAAO,CAEd,GADA,EAAO,EAAK,MAAM,aAAa,EAC3B,EAAK,OAAS,UAAY,CAAC,EAAK,WAClC,MAAU,MACR,GAAG,oEACL,EAEF,EAAW,OAAO,KAAK,EAAK,UAAU,EAGxC,IAAM,EAAa,OAAO,QAAQ,EAAK,OAAS,CAAC,CAAC,EAAE,IAAI,EAAE,EAAO,MAAa,CAC5E,KAAM,EACN,QACF,EAAE,EACF,QAAW,KAAQ,EACjB,GAAa,EAAO,SAAS,EAAK,OAAQ,EAAK,MAAM,EAEvD,GAAI,EAAW,OAAS,GAAK,IAAW,MACtC,MAAU,MAAM,GAAG,uCAA2C,EAGhE,IAAM,EAAoC,CAAC,EACrC,EAAe,IAAI,IACzB,QAAW,KAAS,EAAQ,CAC1B,IAAM,EAAS,EAAS,EAAM,MAC9B,GAAI,IAAW,QAAS,CACtB,IAAM,EAAQ,EAAE,OAAO,EAAE,SAAS,SAAS,EAAM,2BAA2B,EAC5E,EAAO,EAAM,MACX,EAAM,WAAa,KAAO,EAAM,WAAa,IAAM,EAAM,SAAS,EAAI,EAExE,OAAa,IAAI,EAAM,KAAM,CAAM,EAGvC,QAAW,KAAQ,EACjB,GAAI,EAAK,SAAW,QAClB,EAAO,EAAK,MAAQ,EACjB,OAAO,EACP,SACC,mHACF,EAKN,IAAM,EAAW,CAAC,GAAG,OAAO,KAAK,CAAM,EAAG,GAAG,EAAW,IAAI,CAAC,IAAS,EAAK,IAAI,CAAC,EAChF,QAAW,KAAO,IAAI,IAAI,CAAQ,EAChC,GAAI,EAAS,SAAS,CAAG,EACvB,MAAU,MACR,GAAG,OAAW,iFAChB,EAIJ,MAAO,CACL,WAAY,OAAO,OAAO,CACxB,OACA,YAAa,EAAK,YAClB,SACA,MACA,YAAa,GAAe,EAAK,MAAO,EAAM,EAAE,OAAO,CAAM,CAAC,EAC9D,YAAa,GAAe,CAAM,EAClC,KAAM,OAAO,OAAO,CAAC,GAAI,EAAK,MAAQ,CAAC,CAAE,CAAC,EAC1C,iBAAkB,EAAK,mBAAqB,MACxC,EAAM,OAAS,CAAE,OAAQ,EAAM,MAAO,EAAI,CAAC,CACjD,CAAC,EACD,SACA,eACA,aACA,UACF,OAKY,SAAQ,CACpB,EACA,EACA,EACiB,CACjB,IAAI,EAAO,EAAK,WAAW,IAC3B,QAAW,KAAS,EAAK,OAAQ,CAC/B,IAAM,EAAS,EAAK,aAAa,IAAI,EAAM,IAAI,EAC3C,EACJ,GAAI,GAEF,GADA,EAAQ,MAAM,KAAK,KAAK,EAAM,cAAc,EAAM,QAAS,IAAM,EAAO,CAAG,CAAC,EACxE,IAAU,QAAa,IAAU,MAAQ,IAAU,GAIrD,MAHA,QAAQ,MACN,8BAA8B,EAAM,aAAa,EAAK,WAAW,kBAAkB,KAAK,UAAU,CAAK,IACzG,EACM,IAAI,EAAa,IAAI,EAAK,WAAW,8BAA+B,GAAG,EAG/E,OAAQ,EAAM,EAAM,MAGtB,IAAM,EAAQ,IAAI,EAAM,OAAO,EAAM,WACrC,GAAI,IAAU,QAAa,IAAU,MAAQ,IAAU,GAAI,CACzD,GAAI,EAAM,WAAa,KAAO,EAAM,WAAa,IAC/C,MAAM,IAAI,EAAa,IAAI,EAAM,aAAa,EAAK,WAAW,0BAA0B,EAE1F,EAAO,EAAK,QAAQ,IAAI,IAAS,EAAE,EACnC,SAEF,EAAO,EAAK,QAAQ,EAAO,GAAc,EAAK,WAAW,KAAM,EAAO,OAAO,CAAK,CAAC,CAAC,EAEtF,OAAO,OAGK,SAAQ,CACpB,EACA,EACA,EACA,EACmB,CACnB,IAAM,EAAO,EAAK,WAAW,KAC7B,GAAI,CAAC,EACH,MAAU,MACR,iBAAiB,8GACnB,EAEF,IAAM,EAAO,IAAI,SACjB,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAI,EAC5C,GAAY,EAAM,EAAK,CAAK,EAE9B,QAAW,KAAS,EAAK,WAAY,CACnC,IAAM,EACJ,EAAM,SAAW,QACZ,EAAM,EAAM,MACb,MAAM,KAAK,KAAK,EAAM,aAAa,EAAM,QAAS,IAC/C,EAAM,OAAyB,CAAG,CACrC,EACN,GAAI,OAAO,IAAO,UAAY,IAAO,GACnC,MAAM,IAAI,EACR,IAAI,wBAA2B,EAAM,4DACvC,EAIF,EAAK,OAAO,EAAM,KAAM,MAAM,EAAI,YAAY,KAAK,CAAE,CAAC,EAExD,OAAO,OAOK,KAAO,CAAC,EAAY,EAAc,EAAsC,CACpF,GAAI,CACF,OAAO,MAAM,EAAG,EAChB,MAAO,EAAO,CAEd,MADA,QAAQ,MAAM,sBAAsB,SAAY,EAAK,WAAW,gBAAiB,CAAK,EAChF,IAAI,EAAa,IAAI,EAAK,WAAW,8BAA+B,GAAG,GAGnF,CAEA,SAAS,EAAW,CAAC,EAA4E,CAC/F,GAAI,GAAQ,OAAS,QACnB,MAAU,MACR,0LACF,EAKJ,SAAS,EAAY,CAAC,EAAe,EAAY,EAAiB,CAChE,GAAI,IAAW,SAAW,OAAO,IAAW,WAC1C,MAAU,MAAM,GAAG,MAAU,kCAAmC,EAIpE,SAAS,EAAc,CAAC,EAAuC,CAC7D,OAAQ,OACD,MACH,OAAO,OAAO,OAAO,CAAE,aAAc,EAAc,CAAC,MACjD,SACH,OAAO,OAAO,OAAO,CAAE,gBAAiB,EAAc,CAAC,MACpD,MACH,OAAO,OAAO,OAAO,CAAE,eAAgB,EAAc,CAAC,UAEtD,OAAO,OAAO,OAAO,CAAC,CAAC,GAe7B,SAAS,EAAc,CACrB,EACA,EACA,EACiC,CACjC,IAAM,EAAQ,EAAO,aAAa,EAC5B,EAAmB,IACnB,GAAQ,CAAC,EACb,KAAM,SACN,WAAY,IAAM,GAAM,YAAc,CAAC,KAAO,EAAM,UAAW,EAC/D,SAAU,CAAC,GAAI,GAAM,UAAY,CAAC,EAAI,GAAI,EAAM,UAAY,CAAC,CAAE,EAC/D,qBAAsB,EACxB,EAEM,EAAY,CAAC,IAAmB,CACpC,GAAI,OAAO,IAAU,UAAY,IAAU,MAAQ,MAAM,QAAQ,CAAK,EACpE,MAAO,CAAE,GAAI,GAAgB,OAAQ,CAAC,oBAAoB,CAAE,EAE9D,IAAM,EAAmB,CAAC,EACtB,EAA+B,CAAC,EACpC,GAAI,EAAO,CACT,IAAM,EAAM,EAAM,UAAU,CAAK,EACjC,GAAI,EAAI,KAAO,GAAO,EAAO,KAAK,GAAG,EAAI,MAAM,EAC1C,OAAM,IAAK,EAAI,KAAM,EAE5B,IAAM,EAAO,EAAO,UAAU,CAAK,EACnC,GAAI,EAAK,KAAO,GAAO,EAAO,KAAK,GAAG,EAAK,MAAM,EAC5C,OAAM,IAAK,KAAQ,EAAK,KAAM,EACnC,OAAO,EAAO,OAAS,EAAI,CAAE,GAAI,GAAgB,QAAO,EAAI,CAAE,GAAI,GAAe,MAAO,CAAI,GAG9F,MAAO,CACL,aAAc,IAAM,EACpB,YACA,KAAK,CAAC,EAAgB,CACpB,IAAM,EAAS,EAAU,CAAK,EAC9B,GAAI,EAAO,KAAO,GAAO,MAAU,MAAM,EAAO,OAAO,KAAK,IAAI,CAAC,EACjE,OAAO,EAAO,MAElB,EAQF,SAAS,EAAa,CAAC,EAAc,EAAkB,EAAuB,CAC5E,IAAM,EAAQ,EAAM,WAAa,KAAO,EAAM,WAAa,IAAM,EAAM,MAAM,GAAG,EAAI,CAAC,CAAK,EAC1F,GAAI,EAAM,KAAK,CAAC,IAAS,IAAS,KAAO,IAAS,IAAI,EACpD,MAAM,IAAI,EAAa,IAAI,gCAAoC,EAAM,aAAa,KAAQ,EAE5F,OAAO,EAAM,IAAI,kBAAkB,EAAE,KAAK,GAAG,EAS/C,SAAS,EAAW,CAAC,EAAgB,EAAa,EAAgB,CAChE,GAAI,IAAU,QAAa,IAAU,KAAM,OAC3C,GAAI,MAAM,QAAQ,CAAK,EAAG,CACxB,QAAW,KAAQ,EAAO,GAAY,EAAM,EAAK,CAAI,EACrD,OAEF,EAAK,OAAO,EAAK,OAAO,IAAU,SAAW,KAAK,UAAU,CAAK,EAAI,OAAO,CAAK,CAAC,EAIpF,SAAS,EAAO,CAAC,EAAuC,CACtD,IAAM,EAAS,IAAI,gBACb,EAAM,CAAC,EAAa,IAAmB,CAC3C,GAAI,IAAU,QAAa,IAAU,KAAM,OAC3C,GAAI,MAAM,QAAQ,CAAK,EAAG,CACxB,QAAW,KAAQ,EAAO,EAAI,EAAK,CAAI,EACvC,OAEF,EAAO,OAAO,EAAK,OAAO,IAAU,SAAW,KAAK,UAAU,CAAK,EAAI,OAAO,CAAK,CAAC,GAEtF,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAI,EAAG,EAAI,EAAK,CAAK,EAC/D,OAAO,EAAO,SAAS,EAGzB,eAAe,EAAY,CAAC,EAAc,EAAsC,CAC9E,GAAI,EAAS,QAAU,KAAO,EAAS,OAAS,IAAK,CACnD,IAAM,EAAO,EAAS,QAAQ,IAAI,cAAc,EAChD,GAAI,GAAQ,CAAC,GAAS,KAAK,CAAI,EAAG,CAChC,IAAM,GAAQ,MAAM,EAAS,YAAY,GAAG,WAC5C,MAAO,IAAI,oBAAuB,cAAiB,yBAErD,IAAM,EAAO,MAAM,EAAS,KAAK,EACjC,GAAI,IAAS,GAAI,OAAO,KACxB,GAAI,EAAK,OAAS,EAChB,MAAO,GAAG,EAAK,MAAM,EAAG,CAAe,mBAAa,QAAsB,EAAK,qBAEjF,GAAI,CACF,OAAO,KAAK,MAAM,CAAI,EACtB,KAAM,CACN,OAAO,GAGX,IAAM,EAAO,MAAM,EAAS,KAAK,EACjC,GAAI,EAAS,QAAU,KAAO,EAAS,OAAS,IAAK,CACnD,IAAM,EAAQ,EAAK,OAAS,GAAiB,GAAG,EAAK,MAAM,EAAG,EAAc,UAAM,EAClF,MAAM,IAAI,EACR,IAAI,uBAA0B,EAAS,SAAS,EAAQ,KAAK,IAAU,MACvE,EAAS,MACX,EAEF,GAAI,EAAS,OAAS,IAGpB,QAAQ,MACN,eAAe,eAAkB,EAAS,SAAS,EAAS,QAAQ,IAAI,UAAU,EAAI,OAAO,EAAS,QAAQ,IAAI,UAAU,IAAM,sCACpI,EAEF,MAAM,IAAI,EAAa,IAAI,2BAA+B,EAAS,MAAM,ECjoB3E,SAAS,CAAa,CAAC,EAAoB,EAAgB,CACzD,IAAM,EAAQ,EAAO,IAAO,CAAG,EAC/B,GAAI,CAAC,EACH,MAAU,MACR,YAAY,qGACd,EAEF,OAAO,EAQF,MAAM,WAA6B,CAAgB,CACxD,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EAA2B,KAAK,IAAI,OAAQ,WAAW,CACzD,CACJ,EAEA,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EAA4B,KAAK,IAAI,OAAQ,YAAY,CAC3D,CACJ,EAIA,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,CAAE,IAAK,KAAK,IAAI,KAAK,CAAkB,EAAG,KAAM,KAAK,IAAI,KAAK,CAAmB,CAAE,EACnF,CACE,IAAK,EAA2B,KAAK,IAAI,OAAQ,WAAW,EAC5D,KAAM,EAA4B,KAAK,IAAI,OAAQ,YAAY,EAC/D,QAAS,KAAK,IAAI,OAAO,IAA+B,eAAe,CACzE,CACF,CACJ,EAIA,KAAK,IAAI,UAAU,EAAa,IAAM,CACpC,IAAM,EAAS,KAAK,IAAI,OAAO,IAAgC,WAAW,EAC1E,GAAI,CAAC,GAAQ,OACX,MAAU,MACR,yFACF,EAEF,OAAO,IAAI,EAAY,IAAI,EAAO,OAAU,KAAK,IAAI,KAAK,CAAkB,CAAC,EAC9E,EAYH,IAAI,EAAG,CAKL,GAJA,KAAK,IAAI,KAAK,CAAkB,EAChC,KAAK,IAAI,KAAK,CAAmB,EAEjC,KAAK,IAAI,KAAK,CAAY,EACtB,KAAK,IAAI,OAAO,IAAI,WAAW,EACjC,KAAK,IAAI,KAAK,CAAW,EAG/B",
33
- "debugId": "3E596CFE4FBC3FEB64756E2164756E21",
32
+ "mappings": "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",
33
+ "debugId": "1CA4FF91BC3E8F2964756E2164756E21",
34
34
  "names": []
35
35
  }
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{Xb as T,Zb as D}from"./chunk-1s914cdj.js";import{lg as C}from"./chunk-v27a4se1.js";import{wg as I,xg as Z,yg as A}from"./chunk-r5e4vpa1.js";class R extends Error{code;constructor(G,H=1){super(G);this.code=H;this.name="CommandFailed"}}class K{static commandName="unset";static description="";static args=[];static options=[];run(G){}}function p(G){return G}function S(){return{commands:[],commandsDir:"app/commands"}}var Q=Symbol.for("gemi.console.builder");function x(G){if(G.trim()==="")throw Error("A command name cannot be empty.");if(/[{}]/.test(G)||/\s/.test(G))throw Error(`Invalid command name ${JSON.stringify(G)}. gemi does not parse a signature string; the name is the whole of it. Declare arguments with .arg() and flags with .option():
2
+ import{ac as T,cc as D}from"./chunk-saqfc6vp.js";import{tg as C}from"./chunk-d3jkypc7.js";import{Eg as I,Fg as Z,Gg as A}from"./chunk-cbycz5z3.js";class R extends Error{code;constructor(G,H=1){super(G);this.code=H;this.name="CommandFailed"}}class K{static commandName="unset";static description="";static args=[];static options=[];run(G){}}function p(G){return G}function S(){return{commands:[],commandsDir:"app/commands"}}var Q=Symbol.for("gemi.console.builder");function x(G){if(G.trim()==="")throw Error("A command name cannot be empty.");if(/[{}]/.test(G)||/\s/.test(G))throw Error(`Invalid command name ${JSON.stringify(G)}. gemi does not parse a signature string; the name is the whole of it. Declare arguments with .arg() and flags with .option():
3
3
 
4
4
  defineCommand("mail:send")
5
5
  .arg("user", { required: true })
@@ -14,6 +14,6 @@ import{Xb as T,Zb as D}from"./chunk-1s914cdj.js";import{lg as C}from"./chunk-v27
14
14
  static event = UserRegistered;
15
15
 
16
16
  If this is an abstract base its subclasses extend, move it out of the `+"listeners directory \u2014 the walk excludes gemi's `Listener` and "+"nothing else, so a base sitting beside its subclasses is registered and run like one of them.")}function v(G){for(let H of G){if(Object.getOwnPropertyDescriptor(H,"name")?.writable)continue;console.warn(`Event listener ${H.name} does not declare \`static name\`, so it is registered under its class name, which a production build renames. Nothing reads that name across a build boundary while the `+"listener is sync, which is why this is a warning \u2014 but adding "+`\`queued = true\` to it is refused at boot for the same reason, because the queue's key is that string. Add: static name = "${H.name}";`)}}function b(G){let H=new Set;for(let{event:P}of G){if(H.has(P))continue;if(Object.getOwnPropertyDescriptor(P,"name")?.writable)continue;H.add(P),console.warn(`Event ${P.name} does not declare \`static name\`, so it is dispatched under its class name. A production build minifies the code that dispatches it and renames the class, while discovery reads `+"the listener's copy from source and does not \u2014 so the dispatch would "+`reach no listener in production and nowhere else. Add: static name = "${P.name}";`)}}
17
- export{R as Fb,K as Gb,p as Hb,S as Ib,c as Jb,_ as Kb,o as Lb,W as Mb,i as Nb,B as Ob,M as Pb,U as Qb,JG as Rb,OG as Sb,QG as Tb,_G as Ub};
17
+ export{R as Kb,K as Lb,p as Mb,S as Nb,c as Ob,_ as Pb,o as Qb,W as Rb,i as Sb,B as Tb,M as Ub,U as Vb,JG as Wb,OG as Xb,QG as Yb,_G as Zb};
18
18
 
19
- //# debugId=2A30FD6D9FE103E764756E2164756E21
19
+ //# debugId=049BB65C0E77316F64756E2164756E21
@@ -13,6 +13,6 @@
13
13
  "import { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join } from \"node:path\";\n\nimport {\n discoverClasses,\n DiscoveryError,\n projectRoot,\n} from \"../support/discover\";\nimport { Command, type CommandClass } from \"../console/Command\";\nimport { commandConfigDefaults } from \"../console/config\";\nimport { isUnfinishedBuilder } from \"../console/builder\";\nimport { CronJob } from \"./cron/CronJob\";\nimport { scheduleConfigDefaults } from \"./cron/config\";\nimport { eventConfigDefaults } from \"./events/config\";\nimport type { EventClass } from \"./events/Event\";\nimport { Listener, type ListenerClass } from \"./events/Listener\";\nimport { Job } from \"./queue/Job\";\nimport { queueConfigDefaults } from \"./queue/config\";\n\n/**\n * Reading an application's jobs off the filesystem, for the two subsystems that\n * were asking every app to write its job list twice.\n *\n * Both functions here are the same call to `discoverClasses` with a different\n * base class, which is deliberate: one walk, one set of skip rules, one answer\n * to \"what does this app have\". They are exported from `gemi/services` rather\n * than kept private to the providers because the list stopped being something\n * an app could import — a test that used to walk the exported `jobs` array\n * needs somewhere to ask the same question, and so does a script.\n *\n * What the providers add on top of these is the decision of *whether* to ask,\n * which is the config's to make and not this file's.\n */\n\n/**\n * A directory the app named, resolved the way the app meant it.\n *\n * Relative paths hang off the project root rather than `process.cwd()` at the\n * moment of the call, because a config slice saying `app/jobs` means the app's\n * `app/jobs` and not whatever directory somebody happened to launch a script\n * from. Absolute paths are taken as given, which is what makes these callable\n * from a test that has no project around it.\n */\nfunction resolveDir(dir: string): string {\n return isAbsolute(dir) ? dir : join(projectRoot(), dir);\n}\n\n/**\n * Says something when the directory is missing *and so is the tree it lives in*.\n *\n * A missing directory has two readings and they want opposite responses. An app\n * that has never written a cron job has no `app/cron`, and warning about that on\n * every boot for the rest of its life is noise — the answer \"you have no cron\n * jobs\" is correct and uninteresting. But a deploy that ships `dist/` and\n * `node_modules/` without the source has no `app/cron` *and no `app/`*, and\n * there discovery quietly returns nothing while the app very much does have\n * jobs: the exact silence #322 and #323 exist to remove, reintroduced one layer\n * down and in production only.\n *\n * The parent directory is what tells them apart. If neither the directory nor\n * the one above it is there, the tree this was pointed into is not there\n * either, and that is worth a sentence.\n */\nfunction warnIfSourceIsMissing(\n resolved: string,\n subject: string,\n slice: string,\n) {\n if (existsSync(resolved) || existsSync(dirname(resolved))) return;\n\n console.warn(\n `No ${subject} were discovered: neither ${resolved} nor the directory ` +\n `above it exists, so this process cannot see the application's source. ` +\n `If this is a deploy that ships only the build output, list the classes ` +\n `explicitly in app/config/${slice}.ts so they travel with it.`,\n );\n}\n\n/**\n * The `Job` subclasses under `dir`, defaulting to the config slice's `app/jobs`.\n *\n * This is what a `queue` config slice with no `jobs` key resolves to. Call it\n * directly to ask the question a test used to answer by importing the array:\n * every job this application would register, in the order it would register\n * them.\n *\n * Every file underneath is imported, so calling this runs the app's job modules\n * — the cost `discoverClasses` documents at length, paid once per call.\n */\nexport async function discoverJobs(\n dir: string = queueConfigDefaults().jobsDir,\n): Promise<Array<new () => Job>> {\n const resolved = resolveDir(dir);\n warnIfSourceIsMissing(resolved, \"queue jobs\", \"queue\");\n const jobs = await discoverClasses(resolved, Job);\n warnIfNameWillNotSurviveTheBuild(jobs);\n return jobs;\n}\n\n/**\n * Says something about a discovered job that never declared `static name`.\n *\n * This is the one hazard discovery introduces rather than removes, and it is\n * production-only. `gemi build` minifies the server entry, and app code\n * reachable from it — a controller, and every job class that controller\n * imports to dispatch — is bundled and minified with it. Minification renames\n * the class binding, and a class's implicit `.name` is that binding: a\n * `TestJob` in the bundle reports `\"D\"`. Discovery, meanwhile, imports\n * `app/jobs/TestJob.ts` from source at runtime, where it is still `\"TestJob\"`.\n * The queue is keyed by that name, so the two halves stop agreeing and the\n * dispatch is dropped — in production, and only there.\n *\n * A declared `static name = \"TestJob\"` is a string literal, which survives\n * minification intact, and the two halves agree again. `docs/jobs-and-queues.md`\n * has always called it required; before discovery an app could get away without\n * it, because the explicit `jobs` array was bundled too and both sides were\n * wrong in the same way.\n *\n * The check is exact rather than a guess: a `static name = \"...\"` class field\n * defines a *writable* own property, while the implicit class name is\n * non-writable. Cron is unaffected — `CronJob.name` is an instance field\n * holding a string literal, not the class binding.\n */\nfunction warnIfNameWillNotSurviveTheBuild(jobs: Array<new () => Job>) {\n for (const job of jobs) {\n if (Object.getOwnPropertyDescriptor(job, \"name\")?.writable) continue;\n\n console.warn(\n `Queued job ${job.name} does not declare \\`static name\\`, so it is ` +\n `registered under its class name. A production build minifies the ` +\n `class that dispatches it and renames it, while discovery reads this ` +\n `file from source and does not — so the dispatch would be dropped in ` +\n `production and nowhere else. Add: static name = \"${job.name}\";`,\n );\n }\n}\n\n/**\n * The `CronJob` subclasses under `dir`, defaulting to the config slice's\n * `app/cron`.\n *\n * This is what a `schedule` config slice with no `jobs` key resolves to. Call it\n * directly to ask the question a test used to answer by importing the array —\n * though after boot `app(Scheduler).jobs` is the better one, because it is what\n * the scheduler actually took rather than what this would find if asked again.\n *\n * Every file underneath is imported, so calling this runs the app's cron\n * modules — the cost `discoverClasses` documents at length, paid once per call.\n */\nexport async function discoverCronJobs(\n dir: string = scheduleConfigDefaults().jobsDir,\n): Promise<Array<new () => CronJob>> {\n const resolved = resolveDir(dir);\n warnIfSourceIsMissing(resolved, \"cron jobs\", \"schedule\");\n return await discoverClasses(resolved, CronJob);\n}\n\n/**\n * The `Command` subclasses under `dir`, defaulting to the config slice's\n * `app/commands`.\n *\n * This is what a `commands`-less `command` slice resolves to, and what\n * `gemi run` lists. Unlike the two above it is not called during boot — a\n * command registry has one consumer, and importing every file under\n * `app/commands` into every server process would be a cost paid on every start\n * for code no request reaches.\n *\n * Every file underneath is imported, so calling this runs the app's command\n * modules — the cost `discoverClasses` documents at length, paid once per call.\n */\nexport async function discoverCommands(\n dir: string = commandConfigDefaults().commandsDir,\n): Promise<CommandClass[]> {\n const resolved = resolveDir(dir);\n warnIfSourceIsMissing(resolved, \"commands\", \"command\");\n\n const unfinished: string[] = [];\n\n const commands = await discoverClasses(\n resolved,\n Command,\n [],\n (value, file) => {\n if (isUnfinishedBuilder(value)) unfinished.push(file);\n },\n );\n\n refuseUnfinishedBuilders(unfinished);\n\n return commands as CommandClass[];\n}\n\n/**\n * Stops the walk for a builder chain that was never finished.\n *\n * This is the one silence the builder introduces, and it is the exact shape\n * #322 and #323 exist to remove. `defineCommand(...).arg(...)` without a\n * trailing `.handle(...)` is a plain object rather than a class, so\n * `discoverClasses` discards it along with every constant and helper a command\n * file happens to export — and the command disappears from `gemi run` with\n * nothing raised. The author sees a listing containing every command except the\n * one they just wrote.\n *\n * A throw rather than a warning, because there is no reading of an unfinished\n * builder under which the author meant it: the chain builds a description of a\n * command and then discards it.\n *\n * \"Unfinished\" is decided by `.handle()` clearing the brand, not by the export\n * still being a builder object. Those differ for the natural way to share\n * declarations —\n *\n * export const base = defineCommand(\"reindex\").option(\"verbose\", …);\n * export default base.handle(async () => {});\n *\n * — where `base` is a builder that *did* produce a command. Keying off the shape\n * alone made that file abort the whole of `gemi run`, taking every other command\n * in the project down with it, under a message that was untrue for it.\n */\nfunction refuseUnfinishedBuilders(files: string[]): void {\n if (files.length === 0) return;\n\n const subject =\n files.length === 1\n ? `${files[0]} exports a command builder that never called \\`.handle()\\``\n : `${files.length} files export a command builder that never called ` +\n `\\`.handle()\\`:\\n ${files.join(\"\\n \")}`;\n\n throw new DiscoveryError(\n `${subject}, so there is no command to run. \\`.handle()\\` is what turns ` +\n `the chain into a command — finish it:\\n\\n` +\n ` export default defineCommand(\"my-command\")\\n` +\n ` .handle(async ({ line }) => { line(\"hello\") })`,\n );\n}\n\n/**\n * The `Listener` subclasses under `dir`, defaulting to the config slice's\n * `app/listeners`.\n *\n * This is what an `events` config slice with no `listeners` key resolves to.\n * Call it directly to ask what an application would register: every listener,\n * in the order it would register them.\n *\n * Only listeners are walked. Event classes are never discovered — each is\n * imported by the listener that binds to it and by the code that dispatches it,\n * so there is nothing a walk over them would find that is not already in the\n * module graph.\n *\n * **Known residual, matching jobs and cron.** `discoverClasses` excludes the\n * `base` it is handed and not intermediates, so an abstract listener base\n * written in `listenersDir` and extended by its siblings is discovered and\n * registered alongside them — constructed, with its `handle` called, on every\n * dispatch of whatever event it declares. Keep shared bases outside the\n * directory.\n *\n * Every file underneath is imported, so calling this runs the app's listener\n * modules — the cost `discoverClasses` documents at length, paid once per call.\n *\n * @throws DiscoveryError if a discovered listener declares no `static event`.\n */\nexport async function discoverListeners(\n dir: string = eventConfigDefaults().listenersDir,\n): Promise<ListenerClass[]> {\n const resolved = resolveDir(dir);\n warnIfSourceIsMissing(resolved, \"event listeners\", \"events\");\n\n const listeners = (await discoverClasses(\n resolved,\n Listener,\n )) as ListenerClass[];\n\n refuseListenersWithNoEvent(listeners);\n warnIfListenerNameWillNotSurviveTheBuild(listeners);\n warnIfEventNameWillNotSurviveTheBuild(listeners);\n\n return listeners;\n}\n\n/**\n * Stops the walk for a listener that binds to nothing.\n *\n * `static event` is declared as required on the base and the compiler still\n * cannot see it missing: every subclass inherits the declaration whether or not\n * it assigns to one, so `typeof SomeListener` type-checks either way. What the\n * author gets instead is a file that is imported, registered under no name, and\n * never called — the silence this whole module is arranged against.\n *\n * A throw rather than a warning, because there is no reading of a listener with\n * no event under which the author meant it. The usual cause is the residual\n * above: an abstract base sharing a gate between two listeners, sitting in\n * `listenersDir` where the walk finds it. Moving it out is the fix, and the\n * message says so — the alternative, excluding it by some guess about\n * abstractness, is how a discovery pass ends up quietly covering less than the\n * directory holds.\n */\nfunction refuseListenersWithNoEvent(listeners: ListenerClass[]): void {\n const orphans = listeners.filter((listener) => !listener.event);\n if (orphans.length === 0) return;\n\n throw new DiscoveryError(\n `${orphans\n .map((listener) => listener.name)\n .join(\", \")} declare no \\`static event\\`, so there is no event name to ` +\n `register them under and their \\`handle\\` would never run. Every ` +\n `listener binds to exactly one event:\\n\\n` +\n ` static event = UserRegistered;\\n\\n` +\n `If this is an abstract base its subclasses extend, move it out of the ` +\n `listeners directory — the walk excludes gemi's \\`Listener\\` and ` +\n `nothing else, so a base sitting beside its subclasses is registered ` +\n `and run like one of them.`,\n );\n}\n\n/**\n * Says something about a discovered listener that never declared `static name`.\n *\n * The hazard is `warnIfNameWillNotSurviveTheBuild`'s, one subsystem over: a\n * `static name = \"...\"` class field defines a *writable* own property while the\n * implicit class binding does not, and a minifier renames the binding while\n * leaving the string literal alone. The two spellings are indistinguishable by\n * value — both read `\"SendWelcomeEmail\"` in development — so the descriptor is\n * the only thing that tells them apart, and the difference only becomes visible\n * in a production build.\n *\n * A warning rather than a refusal, because a *sync* listener's name has no\n * second half to disagree with: every reader of it comes from this same\n * source-side walk, so a minified build and this walk cannot produce two\n * different strings for it. A **queued** listener does have one — the name is\n * the queue's key and it crosses a JSON boundary — and that case is refused\n * outright, by `jobForListener`, at the point the listener is registered with\n * the queue rather than here. This walk cannot tell the two apart without\n * constructing every listener it found; the registry constructs them anyway.\n */\nfunction warnIfListenerNameWillNotSurviveTheBuild(listeners: ListenerClass[]) {\n for (const listener of listeners) {\n if (Object.getOwnPropertyDescriptor(listener, \"name\")?.writable) continue;\n\n console.warn(\n `Event listener ${listener.name} does not declare \\`static name\\`, so ` +\n `it is registered under its class name, which a production build ` +\n `renames. Nothing reads that name across a build boundary while the ` +\n `listener is sync, which is why this is a warning — but adding ` +\n `\\`queued = true\\` to it is refused at boot for the same reason, ` +\n `because the queue's key is that string. Add: static name = ` +\n `\"${listener.name}\";`,\n );\n }\n}\n\n/**\n * Says something about the *event* a discovered listener binds to, when that\n * event's name is the implicit class binding.\n *\n * This is the check that matters from the first dispatch, and it is the reason\n * `discoverListeners` reads `static event` at all. The registry is keyed by the\n * event's name; the dispatcher supplies that name from the class it constructs.\n * A production build minifies the server entry and the app code reachable from\n * it — the controller, and the event class it imports in order to dispatch —\n * while discovery imports `app/listeners/*.ts` from source, and those files\n * import `app/events/*.ts` from source too. Two module graphs, two class\n * objects, and an implicit `.name` that reads `\"UserRegistered\"` on one side\n * and `\"D\"` on the other. The dispatch then finds no listeners, which is legal,\n * normal, and completely silent.\n *\n * A declared `static name` is a string literal, which survives minification\n * intact, and the two halves agree again.\n *\n * Checked through the descriptor rather than the string, and not by comparing\n * `event.name` to anything: in development the two spellings produce the same\n * value, so a check on the string would be a tautology that passes forever.\n */\nfunction warnIfEventNameWillNotSurviveTheBuild(listeners: ListenerClass[]) {\n const warned = new Set<EventClass>();\n\n for (const { event } of listeners) {\n if (warned.has(event)) continue;\n if (Object.getOwnPropertyDescriptor(event, \"name\")?.writable) continue;\n warned.add(event);\n\n console.warn(\n `Event ${event.name} does not declare \\`static name\\`, so it is ` +\n `dispatched under its class name. A production build minifies the ` +\n `code that dispatches it and renames the class, while discovery reads ` +\n `the listener's copy from source and does not — so the dispatch would ` +\n `reach no listener in production and nowhere else. Add: ` +\n `static name = \"${event.name}\";`,\n );\n }\n}\n"
14
14
  ],
15
15
  "mappings": "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",
16
- "debugId": "2A30FD6D9FE103E764756E2164756E21",
16
+ "debugId": "049BB65C0E77316F64756E2164756E21",
17
17
  "names": []
18
18
  }
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ import{ic as o}from"./chunk-p0m3qgs5.js";import{jc as i}from"./chunk-z4k18gnp.js";import{jg as t}from"./chunk-dwqh79e5.js";import{qg as r}from"./chunk-7n5775qx.js";class n extends i{register(){this.app.singleton(r,()=>new r(t(o(),this.app.config.get("translation",{}))))}}
3
+ export{n as Wa};
4
+
5
+ //# debugId=C7F9A362F4A7A46664756E2164756E21
@@ -5,6 +5,6 @@
5
5
  "import { ServiceProvider } from \"../support/ServiceProvider\";\nimport { withDefaults } from \"../support/withDefaults\";\nimport { Translator } from \"./Translator\";\nimport { translationConfigDefaults, type TranslationConfig } from \"./config\";\n\nexport class TranslationServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n Translator,\n () =>\n new Translator(\n withDefaults(\n translationConfigDefaults(),\n this.app.config.get<TranslationConfig>(\"translation\", {}),\n ),\n ),\n );\n }\n}\n"
6
6
  ],
7
7
  "mappings": ";sLAKO,AAAM,IAAmC,LAAgB,CAC9D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IACE,IAAI,EACF,EACE,EAA0B,EAC1B,KAAK,IAAI,OAAO,IAAuB,cAAe,CAAC,CAAC,CAC1D,CACF,CACJ,EAEJ",
8
- "debugId": "A3DC7B3D536610D064756E2164756E21",
8
+ "debugId": "C7F9A362F4A7A46664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{a,b,c,d,e,f,g}from"./chunk-87x692j7.js";import"./chunk-w099t7zj.js";import"./chunk-cg4k40zy.js";import"./chunk-zfch4da5.js";export{g as fromEnv,c as ENV_SESSION,b as ENV_SECRET,a as ENV_KEY,d as ENV_EXPIRATION,e as ENV_CREDENTIAL_SCOPE,f as ENV_ACCOUNT_ID};
2
+ import{a,b,c,d,e,f,g}from"./chunk-1b5s4w5f.js";import"./chunk-zf4r4kat.js";import"./chunk-81v4c4b1.js";import"./chunk-9tsw1bmt.js";export{g as fromEnv,c as ENV_SESSION,b as ENV_SECRET,a as ENV_KEY,d as ENV_EXPIRATION,e as ENV_CREDENTIAL_SCOPE,f as ENV_ACCOUNT_ID};
3
3
 
4
4
  //# debugId=30E142423ED216F064756E2164756E21
@@ -0,0 +1,24 @@
1
+ // @bun
2
+ import{i as N,j as r}from"./chunk-5ktfpty1.js";import{ka as P,oa as C,pa as s}from"./chunk-zq5m4scz.js";import"./chunk-8z37k28d.js";import{lc as c,nd as l,od as b}from"./chunk-xx2zg6sk.js";import"./chunk-ha705bcz.js";import"./chunk-k5j65f2c.js";import{Oe as f,Pe as u,Se as m}from"./chunk-174jkg6d.js";import{uf as n}from"./chunk-jhe0t7yj.js";import"./chunk-1jcp8m8h.js";import"./chunk-trdwxm5x.js";import"./chunk-1w5a11cd.js";import"./chunk-4ysar3ev.js";import"./chunk-dwqh79e5.js";import"./chunk-7n5775qx.js";import"./chunk-d3jkypc7.js";import"./chunk-8gexb1gt.js";import"./chunk-swhyp0yw.js";import{Gg as t}from"./chunk-cbycz5z3.js";import{Hg as A}from"./chunk-ndat0nf0.js";import"./chunk-9tsw1bmt.js";import{join as F,resolve as qJ,sep as yJ}from"path";import{Duplex as HJ}from"stream";import{constants as L,createBrotliCompress as KJ,createGzip as OJ}from"zlib";var YJ=["br","gzip"],xJ=1024,UJ=5,VJ=19,CJ=6;function IJ($){if($===void 0)return 1;if(!/^\d+(\.\d{0,3})?$/.test($.trim()))return 1;let J=Number($.trim());return Number.isFinite(J)?Math.min(J,1):1}function LJ($){if($===null||$===void 0)return null;let J=new Map;for(let X of $.split(",")){let[Z,...G]=X.split(";"),W=Z.trim().toLowerCase();if(W==="")continue;let Q=1;for(let j of G){let Y=j.indexOf("=");if(Y===-1)continue;if(j.slice(0,Y).trim().toLowerCase()==="q"){Q=IJ(j.slice(Y+1));break}}J.set(W,Q)}return J}function SJ($,J=YJ){let X=LJ($);if(!X)return null;let Z=X.get("*"),G=null,W=0;for(let Q of J){let j=X.get(Q)??Z??0;if(j>W)G=Q,W=j}return G}function bJ($,J){if(!$)return!1;return $.split(",").some((X)=>X.trim().toLowerCase().split("=")[0].trim()===J)}function AJ($,J){if($==="HEAD")return!1;if(!J.body)return!1;if(J.status<200||J.status===204||J.status===206||J.status===304)return!1;if(J.headers.has("Content-Range"))return!1;let X=J.headers.get("Content-Type");if(!X||!/^\s*text\/html\s*(;|$)/i.test(X))return!1;let Z=J.headers.get("Content-Encoding");if(Z&&Z.trim().toLowerCase()!=="identity")return!1;if(bJ(J.headers.get("Cache-Control"),"no-transform"))return!1;let G=J.headers.get("Content-Length");if(G!==null&&Number(G)<xJ)return!1;return!0}function MJ($){let J=$==="br"?KJ({params:{[L.BROTLI_PARAM_QUALITY]:UJ,[L.BROTLI_PARAM_LGWIN]:VJ},flush:L.BROTLI_OPERATION_FLUSH}):OJ({level:CJ,flush:L.Z_SYNC_FLUSH});return HJ.toWeb(J)}function _J($){let J=$.get("Vary");if(!J){$.set("Vary","Accept-Encoding");return}let X=J.split(",").map((Z)=>Z.trim().toLowerCase());if(X.includes("*")||X.includes("accept-encoding"))return;$.append("Vary","Accept-Encoding")}function v($,J){if(!AJ($.method,J))return J;let X=new Headers(J.headers);_J(X);let Z=SJ($.headers.get("Accept-Encoding"));if(!Z)return new Response(J.body,{status:J.status,statusText:J.statusText,headers:X});let G;try{G=MJ(Z)}catch{return new Response(J.body,{status:J.status,statusText:J.statusText,headers:X})}return X.set("Content-Encoding",Z),X.delete("Content-Length"),new Response(J.body.pipeThrough(G),{status:J.status,statusText:J.statusText,headers:X})}import{readdir as PJ,stat as TJ}from"fs/promises";import{join as DJ}from"path";function E($){let J=$.toString(),X=new Bun.CryptoHasher("sha1");return X.update(J),X.digest("hex")}async function h($){let J=new Set;async function X(Z,G){let W;try{W=await PJ(Z,{withFileTypes:!0})}catch{return}for(let Q of W){if(Q.name.startsWith("."))continue;if(G&&Q.name==="assets")continue;let j=DJ(Z,Q.name),Y=Q.isDirectory(),V=Q.isFile();if(Q.isSymbolicLink())try{let I=await TJ(j);Y=I.isDirectory(),V=I.isFile()}catch{continue}if(V)J.add(j);else if(Y&&!Q.isSymbolicLink())await X(j,!1)}}return await X($,!0),J}var NJ="public, max-age=31536000, must-revalidate";function p($,J){let X=Bun.file(J),Z=X.size,G=E(X.lastModified),W={"Content-Type":X.type||"application/octet-stream","Cache-Control":NJ,"Accept-Ranges":"bytes",ETag:G},Q=f($.headers.get("Range"));if(Q){let j=u(Q,Z);if(!j)return c(Z);return new Response(X.slice(j.start,j.end+1).stream(),{status:206,headers:{...W,"Content-Range":m(j.start,j.end,Z),"Content-Length":String(j.length)}})}return new Response(X.stream(),{headers:{...W,"Content-Length":String(Z)}})}import{stat as wJ}from"fs/promises";var S="app/client.tsx";function d($,J=P){let X=$[S]?.file;if(!X)return;return{module:C(X,J),preload:T($,S,J)}}function T($,J,X=P){let Z=[],G=new Set,W=(Q)=>{if(G.has(Q))return;G.add(Q);let j=$[Q];if(!j?.file)return;Z.push(C(j.file,X));for(let Y of j.imports??[])W(Y)};return W(J),Z}var BJ=new RegExp(`^${l}/.+\\.m?js$`);function FJ($){return BJ.test($)}function o($){if(FJ($))return new Response("window.location.reload();export {}",{headers:{"Content-Type":"application/javascript","Cache-Control":"no-store"}});if(b($))return new Response("Not found",{status:404});return}var kJ=`<!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Internal Server Error</title>
8
+ <style>
9
+ body { font-family: system-ui, sans-serif; margin: 0; min-height: 100vh; display: grid; place-items: center; }
10
+ main { text-align: center; padding: 16px; }
11
+ h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }
12
+ p { margin: 0; opacity: 0.7; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <main>
17
+ <h1>Something went wrong</h1>
18
+ <p>Please try again later.</p>
19
+ </main>
20
+ </body>
21
+ </html>`;function D($,J,X){if(!X)console.error($);else try{X($ instanceof Error?$:Error(String($),{cause:$}))}catch(Z){console.error($),console.error(Z)}if(A(J))return new Response(JSON.stringify({error:n("server_error","Internal Server Error",500)}),{status:500,headers:{"Content-Type":"application/json"}});return new Response(kJ,{status:500,headers:{"Content-Type":"text/html; charset=utf-8"}})}var RJ={kind:"none"};function i($){let J=($??"").trim().toLowerCase();if(J===""||J==="false"||J==="off"||J==="0")return RJ;if(J==="true")return{kind:"all"};if(/^[1-9]\d*$/.test(J))return{kind:"hops",hops:Number(J)};throw Error(`GEMI_TRUST_PROXY must be "false", "true" or the number of proxies in front of the app (e.g. 1). Got ${JSON.stringify($)}.`)}function a($,J,X){if(X.kind==="all"){if(!$.get("x-forwarded-for")&&J)$.set("x-forwarded-for",J);return}$.delete("x-real-ip");let Z=J;if(X.kind==="hops"){let G=($.get("x-forwarded-for")??"").split(",").map((Q)=>Q.trim()).filter(Boolean),W=G.length-X.hops;Z=W>=0?G[W]:G[0]??J}if(Z)$.set("x-forwarded-for",Z);else $.delete("x-forwarded-for")}var M=t(),gJ=F(M,"app"),U=F(M,"dist"),B=F(U,"client");function vJ($){let J;try{J=decodeURIComponent($)}catch{return null}let X=qJ(B,"."+J.replace("/assets/assets","/assets"));return X.startsWith(B+yJ)?X:null}async function EJ($){try{return(await wJ($)).isFile()}catch{return!1}}async function V3($,J){let X=await import(`${U}/client/.vite/manifest.json`),Z=await import(`${U}/server/.vite/manifest.json`),G=await s(`${U}/client`);process.env.ROOT_DIR=M,process.env.APP_DIR=gJ,process.env.DIST_DIR=U;let W={},Q={},j={},Y={},V={},I=(z,H)=>`"${z}": () => import("${H}")`,k=[];for(let z of["404",...$.getFlatComponentTree.call($)]){let H=Z[`app/views/${z}.tsx`];if(!H?.file){console.log(`Server file not found for ${z}`),console.log(H);let x=Object.keys(Z),y=`app/views/${z}.tsx`;console.log(`${y} not found in server manifest`),console.log(x)}let O=await import(`${process.env.DIST_DIR}/server/${H?.file}`);W[z]=O.default,Q[z]=O.OpenGraph,j[z]=O;let K=X[`app/views/${z}.tsx`];if(K?.css&&K?.css.length>0)Y[z]=K?.css;if(K)k.push(I(z,C(K?.file,G))),V[z]=T(X,`app/views/${z}.tsx`,G)}let e=`{${k.join(",")}}`,R=d(X,G);if(!R)console.error(`Client manifest has no "${S}" entry \u2014 dist/client is incomplete, so documents will render but never hydrate.`);let JJ=X["app/client.tsx"]?.css??[],$J=(await Promise.all(JJ.map((z)=>Bun.file(`${U}/client/${z}`).text()))).join(`
22
+ `),XJ=await h(B);async function ZJ(z){let{pathname:H}=new URL(z.url);if(A(H))return await _(z,H);let O=vJ(H);if(b(H)||H.startsWith("/.well-known")||O!==null&&XJ.has(O)){if(!O||!await EJ(O))return o(H)??await _(z,H);try{return p(z,O)}catch(x){return $.onException?.(x),new Response("Not found",{status:404})}}return await _(z,H)}async function _(z,H){let O=$.fetch.bind($);try{let K=await O(z);if(K instanceof Response)return K;else{let x=[];return x.push({content:$J}),await K({getStyles:async(w)=>{if(!w)return N([]);for(let QJ of w){let jJ=X[`app/views/${QJ}.tsx`];for(let g of jJ?.css??[]){let WJ=Bun.file(`${process.env.DIST_DIR}/client/${g}`);x.push({id:g,content:await WJ.text()})}}return N(x)},clientEntry:R,modulePreloadManifest:V,loaders:e,viewImportMap:W,viewModules:j,ogMap:Q,cssManifest:Y,assetBase:G})}}catch(K){return D(K,H,$.onException)}}let zJ=(process.env.GEMI_COMPRESSION??"auto").toLowerCase()!=="off",GJ=i(process.env.GEMI_TRUST_PROXY),q=Bun.serve({maxRequestBodySize:10737418240,fetch:async(z,H)=>{a(z.headers,H.requestIP(z)?.address??null,GJ);let O=await J(z,(K)=>$.withGlobalMiddleware(K,ZJ,(x)=>D(x,new URL(K.url).pathname,$.onException)));return zJ?v(z,O):O},idleTimeout:Number(process.env.SERVER_IDLE_TIMEOUT??10),port:process.env.PORT||5173});return r({port:q.port,rootDir:M}),q}export{V3 as httpProd};
23
+
24
+ //# debugId=A5122197D3BF6AEC64756E2164756E21
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../server/httpProd.ts", "../server/compression.ts", "../server/staticFile.ts", "../server/generateEtag.ts", "../server/modulePreloads.ts", "../server/staticAssetMiss.ts", "../server/unhandledError.ts", "../server/forwardedFor.ts"],
4
+ "sourcesContent": [
5
+ "import { join, resolve, sep } from \"node:path\";\nimport { compressResponse } from \"./compression\";\nimport { listPublicFiles, staticFileResponse } from \"./staticFile\";\nimport { stat } from \"node:fs/promises\";\nimport { createStyles } from \"./styles\";\nimport { CLIENT_ENTRY_KEY, collectModulePreloads, createClientEntry } from \"./modulePreloads\";\nimport type { App } from \"../app\";\nimport { Instrumentation } from \"./types\";\nimport { printStartupBanner } from \"./banner\";\nimport { isReservedAssetPath, staticAssetMiss } from \"./staticAssetMiss\";\nimport { assetUrl, readBuiltAssetBase } from \"../config/assetBase\";\nimport { isApiPath } from \"../services/router/apiPath\";\nimport { projectRoot } from \"../support/discover\";\nimport { unhandledErrorResponse } from \"./unhandledError\";\nimport { applyForwardedTrust, parseTrustProxy } from \"./forwardedFor\";\n\n// The rule this file used to spell out itself. It moved to `projectRoot`\n// because discovery needs the same answer during `waitForBoot()`, which is\n// before `ROOT_DIR` below exists — and two spellings of \"where is the project\"\n// is how a job gets looked for in one directory and served from another.\nconst rootDir = projectRoot();\n\nconst appDir = join(rootDir, \"app\");\nconst distDir = join(rootDir, \"dist\");\n\nconst clientDir = join(distDir, \"client\");\n\n// The file in `dist/client` a static-looking pathname names, or `null` when\n// it names nothing there. The pathname is still percent-encoded, and Vite\n// writes files whose names need encoding (a public `my font.woff2`), so it is\n// decoded first. Decoding also turns `%2F` into a separator, which the URL\n// parser's own `..` normalization never saw — so the resolved path is checked\n// to still be inside `dist/client`. A malformed escape is a miss, not a 500.\nfunction clientFilePath(pathname: string): string | null {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return null;\n }\n const path = resolve(clientDir, \".\" + decoded.replace(\"/assets/assets\", \"/assets\"));\n return path.startsWith(clientDir + sep) ? path : null;\n}\n\nasync function isFile(path: string) {\n try {\n return (await stat(path)).isFile();\n } catch {\n return false;\n }\n}\n\n// `app` is built by `Server.start` (from the kernel) and passed in — same as\n// `httpDev` — so prod and dev share one construction path. What differs here is\n// that views/styles are served from the built `dist/` manifests instead of\n// Vite's dev SSR graph.\nexport async function httpProd(app: App, instrumentation: Instrumentation) {\n const manifest = await import(`${distDir}/client/.vite/manifest.json`);\n const serverManifest = await import(`${distDir}/server/.vite/manifest.json`);\n // What the client build was built with, not `GEMI_ASSET_BASE` as it reads\n // now — see `readBuiltAssetBase`. Every URL below that names a chunk goes\n // through it, so the document links exactly what the bundle imports.\n const assetBase = await readBuiltAssetBase(`${distDir}/client`);\n\n process.env.ROOT_DIR = rootDir;\n process.env.APP_DIR = appDir;\n process.env.DIST_DIR = distDir;\n\n const viewImportMap = {};\n const ogMap = {};\n const viewModules = {};\n const cssManifest = {};\n // Which chunks a route's views pull in, so the shell can preload the chain\n // the client would otherwise discover one round trip at a time (#352).\n const modulePreloadManifest: Record<string, string[]> = {};\n const template = (viewName: string, path: string) => `\"${viewName}\": () => import(\"${path}\")`;\n const templates = [];\n\n for (const fileName of [\"404\", ...app.getFlatComponentTree.call(app)]) {\n const serverFile = serverManifest[`app/views/${fileName}.tsx`];\n if (!serverFile?.file) {\n console.log(`Server file not found for ${fileName}`);\n console.log(serverFile);\n const files = Object.keys(serverManifest);\n const path = `app/views/${fileName}.tsx`;\n console.log(`${path} not found in server manifest`);\n console.log(files);\n }\n const mod = await import(`${process.env.DIST_DIR}/server/${serverFile?.file}`);\n viewImportMap[fileName] = mod.default;\n ogMap[fileName] = mod.OpenGraph;\n // The whole module, so a streaming render can put the view's\n // `Loading`/`Error` exports into the shell it sends.\n viewModules[fileName] = mod;\n const clientFile = manifest[`app/views/${fileName}.tsx`];\n\n if (clientFile?.css && clientFile?.css.length > 0) {\n cssManifest[fileName] = clientFile?.css;\n }\n if (clientFile) {\n templates.push(template(fileName, assetUrl(clientFile?.file, assetBase)));\n modulePreloadManifest[fileName] = collectModulePreloads(\n manifest,\n `app/views/${fileName}.tsx`,\n assetBase,\n );\n }\n }\n\n const loaders = `{${templates.join(\",\")}}`;\n\n // Booted from the bootstrap script rather than through React's\n // `bootstrapModules`, which would preload it at `fetchPriority=\"low\"` — see\n // `clientEntry` in `ViewRouteDispatcher`.\n const clientEntry = createClientEntry(manifest, assetBase);\n if (!clientEntry) {\n // Loudly, but without dying: this is boot, and an incomplete `dist/` must\n // not cost the API routes and static assets too.\n console.error(\n `Client manifest has no \"${CLIENT_ENTRY_KEY}\" entry — dist/client is incomplete, so documents will render but never hydrate.`,\n );\n }\n\n // Vite's manifest `css` field is a `string[]` — a client entry can emit more\n // than one CSS chunk. Read and concatenate them all instead of interpolating\n // the array into a single path (which only works for a one-element array).\n const appCssFiles: string[] = manifest[\"app/client.tsx\"]?.css ?? [];\n const appCSSContent = (\n await Promise.all(appCssFiles.map((cssFile) => Bun.file(`${distDir}/client/${cssFile}`).text()))\n ).join(\"\\n\");\n\n // Which requests are answered from `dist/client` rather than the app:\n //\n // - `/assets` and everything under it, whatever the extension. Vite writes\n // fonts, GIFs, video and `?url` JSON there too, and an allowlist of\n // extensions always trailed the build — a `.woff2` went to the router\n // and paid for an SSR attempt. The router refuses routes under `/assets`\n // at boot, so there is no app answer to lose, and `staticAssetMiss`\n // turns a miss into the reload stub or a 404.\n // - `/.well-known/*`.\n // - Any other path that names a file the build copied out of `public/`,\n // whatever its extension (#583). Any other path may be an app route, so\n // it is static only when that exact file exists — read once here, since\n // the build output does not change under a running server. A view at\n // `/manifest` keeps its data URL (`/manifest.json`) unless the app also\n // ships `public/manifest.json`, and then the file wins. View data is\n // never a file in `dist/client`, so a client-side navigation pays for no\n // filesystem lookup.\n const publicFiles = await listPublicFiles(clientDir);\n\n async function requestHandler(req: Request) {\n const { pathname } = new URL(req.url);\n\n if (isApiPath(pathname)) {\n return await handleWithApp(req, pathname);\n }\n\n const distPath = clientFilePath(pathname);\n const isFileRequest =\n isReservedAssetPath(pathname) ||\n pathname.startsWith(\"/.well-known\") ||\n (distPath !== null && publicFiles.has(distPath));\n\n if (isFileRequest) {\n // Served from here whatever the asset base is: a CDN in front of the\n // app uses this origin as the source it fills from. A file, not merely\n // a path that exists: `/assets` itself is `dist/client/assets`, a\n // directory, and streaming one would answer 200 and then fail mid-body.\n //\n // `Bun.file(path).stream()` is lazy — a missing file only throws ENOENT\n // once the body is streamed, which is *after* this handler has returned,\n // with the response already committed as 200. So existence is checked\n // here, per request, even for a path `publicFiles` lists.\n if (!distPath || !(await isFile(distPath))) {\n return staticAssetMiss(pathname) ?? (await handleWithApp(req, pathname));\n }\n\n try {\n return staticFileResponse(req, distPath);\n } catch (error) {\n app.onException?.(error);\n return new Response(\"Not found\", { status: 404 });\n }\n }\n\n return await handleWithApp(req, pathname);\n }\n\n async function handleWithApp(req: Request, pathname: string) {\n const handler = app.fetch.bind(app);\n\n try {\n const result = await handler(req);\n if (result instanceof Response) {\n return result;\n } else {\n const styles = [];\n\n styles.push({\n content: appCSSContent,\n });\n\n const getStyles = async (currentViews: string[]) => {\n if (!currentViews) {\n return createStyles([]);\n }\n for (const view of currentViews) {\n const clientFile = manifest[`app/views/${view}.tsx`];\n for (const cssFile of clientFile?.css ?? []) {\n const css = Bun.file(`${process.env.DIST_DIR}/client/${cssFile}`);\n styles.push({\n id: cssFile,\n content: await css.text(),\n });\n }\n }\n return createStyles(styles);\n };\n\n return await result({\n getStyles,\n clientEntry,\n modulePreloadManifest,\n loaders,\n viewImportMap,\n viewModules,\n ogMap,\n cssManifest,\n assetBase,\n });\n }\n } catch (err) {\n return unhandledErrorResponse(err, pathname, app.onException);\n }\n }\n\n // Compression is on unless the deployment opts out — set `GEMI_COMPRESSION=off`\n // when a layer in front of the origin already compresses HTML and you would\n // rather not spend origin CPU on it.\n const compressionEnabled = (process.env.GEMI_COMPRESSION ?? \"auto\").toLowerCase() !== \"off\";\n\n // Which `X-Forwarded-For` entries to believe — see `forwardedFor.ts`. Parsed\n // before `Bun.serve` so a bad value fails the boot, not every request.\n const forwardedTrust = parseTrustProxy(process.env.GEMI_TRUST_PROXY);\n\n const server = Bun.serve({\n maxRequestBodySize: 10 * 1024 * 1024 * 1024, // 10 GB\n fetch: async (req, server) => {\n // `requestIP` is null for closed/unix sockets — guard so it never\n // throws before the request is handled.\n applyForwardedTrust(req.headers, server.requestIP(req)?.address ?? null, forwardedTrust);\n // The app's global middleware goes in front of the static handler as well\n // as the router, so it can refuse `/assets/*` too.\n const res = await instrumentation(req, (req) =>\n app.withGlobalMiddleware(req, requestHandler, (err) =>\n unhandledErrorResponse(err, new URL(req.url).pathname, app.onException),\n ),\n );\n // Applied at the very edge, after instrumentation, so every HTML response\n // goes through the same negotiation — including the ones an app's\n // instrumentation produced itself. Anything that isn't HTML comes back\n // untouched.\n return compressionEnabled ? compressResponse(req, res) : res;\n },\n idleTimeout: Number(process.env.SERVER_IDLE_TIMEOUT ?? 10),\n port: process.env.PORT || 5173,\n });\n\n printStartupBanner({ port: server.port, rootDir });\n\n return server;\n}\n",
6
+ "/**\n * Transport-level compression for SSR HTML responses.\n *\n * This lives in the runtime rather than in an app, because every gemi app\n * serves the same shape of response: a streamed `text/html` document whose\n * bulk is critical CSS, markup and the `window.__GEMI_DATA__` hydration\n * payload. Compressing it here means the win is portable across deployments —\n * it does not depend on a CDN being configured to compress on the origin's\n * behalf — and it also cuts origin→edge bandwidth, which edge compression\n * cannot.\n *\n * Compression stays strictly at the transport layer: what the client decodes\n * is byte-for-byte the HTML React rendered, so hydration is unaffected.\n *\n * Deliberately dependency-free apart from `node:zlib`/`node:stream` so it can\n * be unit tested without booting a server.\n */\n\nimport { Duplex } from \"node:stream\";\nimport { constants, createBrotliCompress, createGzip } from \"node:zlib\";\n\n/** The content codings we can produce, in the order we prefer them. */\nexport type ContentEncoding = \"br\" | \"gzip\";\n\n/**\n * Server preference, used to break q-value ties. Brotli comes first: at the\n * quality we use it is both smaller *and* no more expensive than gzip on a\n * representative SSR document (~177 kB → 28.0 kB in ~2.0 ms, versus 31.6 kB in\n * ~2.0 ms for gzip).\n */\nconst SERVER_PREFERENCE: ContentEncoding[] = [\"br\", \"gzip\"];\n\n/**\n * Below this, an encoded body plus its framing overhead is not worth the CPU.\n * Only applied when the response declares a `Content-Length` — a streamed SSR\n * response does not, and buffering one just to measure it would defeat the\n * streaming render.\n */\nconst MIN_COMPRESSIBLE_BYTES = 1024;\n\n/**\n * Brotli quality 5 (of 11). The default, 11, is meant for static assets\n * compressed once at build time — on a streamed document it costs ~175 ms,\n * two orders of magnitude more than quality 5 for ~12% more savings. Quality 5\n * is the usual choice for dynamic content.\n *\n * `LGWIN` 19 caps the window at 512 kB rather than the default 16 MB. An SSR\n * document is far smaller than that, so the ratio is unchanged, and the bound\n * matters under concurrency: the window is allocated per in-flight response.\n */\nconst BROTLI_QUALITY = 5;\nconst BROTLI_WINDOW_BITS = 19;\n\n/** zlib's default level. Level 9 costs measurably more for ~1% on HTML. */\nconst GZIP_LEVEL = 6;\n\nfunction parseQValue(raw: string | undefined): number {\n if (raw === undefined) {\n return 1;\n }\n // `q` is a fixed-point number with at most three decimals (RFC 9110 §12.4.2).\n // Anything else is malformed; treat it as an unqualified \"acceptable\" rather\n // than dropping the encoding, matching what tolerant servers do.\n if (!/^\\d+(\\.\\d{0,3})?$/.test(raw.trim())) {\n return 1;\n }\n const value = Number(raw.trim());\n return Number.isFinite(value) ? Math.min(value, 1) : 1;\n}\n\n/**\n * Parses a request `Accept-Encoding` into `coding -> qvalue`.\n *\n * Returns `null` when the header is *absent*, which is distinct from an empty\n * one. RFC 9110 §12.5.3 says an absent header means any coding is acceptable,\n * but a client that cannot decode and forgets to say so is a broken page, not\n * a slow one — so we treat \"absent\" as \"identity\" and only encode when a\n * client has explicitly opted in. An empty header (`Accept-Encoding:`) is a\n * deliberate \"identity only\" and parses to an empty map.\n */\nexport function parseAcceptEncoding(header: string | null | undefined): Map<string, number> | null {\n if (header === null || header === undefined) {\n return null;\n }\n\n const accepted = new Map<string, number>();\n for (const part of header.split(\",\")) {\n const [rawCoding, ...params] = part.split(\";\");\n const coding = rawCoding.trim().toLowerCase();\n if (coding === \"\") {\n continue;\n }\n\n let q = 1;\n for (const param of params) {\n const separator = param.indexOf(\"=\");\n if (separator === -1) {\n continue;\n }\n if (param.slice(0, separator).trim().toLowerCase() === \"q\") {\n q = parseQValue(param.slice(separator + 1));\n break;\n }\n }\n\n accepted.set(coding, q);\n }\n\n return accepted;\n}\n\n/**\n * Picks the coding to use, or `null` for identity.\n *\n * A `q=0` is a refusal, `*` covers codings the client did not name, and ties\n * fall back to `available`'s order — so a plain `Accept-Encoding: gzip, br`\n * (equal q of 1) resolves to our preference rather than the client's.\n */\nexport function negotiateEncoding(\n header: string | null | undefined,\n available: ContentEncoding[] = SERVER_PREFERENCE,\n): ContentEncoding | null {\n const accepted = parseAcceptEncoding(header);\n if (!accepted) {\n return null;\n }\n\n const wildcard = accepted.get(\"*\");\n let best: ContentEncoding | null = null;\n let bestQ = 0;\n\n for (const coding of available) {\n const q = accepted.get(coding) ?? wildcard ?? 0;\n if (q > bestQ) {\n best = coding;\n bestQ = q;\n }\n }\n\n return best;\n}\n\nfunction hasDirective(headerValue: string | null, directive: string): boolean {\n if (!headerValue) {\n return false;\n }\n // Token match, not substring: `no-transform` must not be found inside\n // something like `x-no-transform`.\n return headerValue\n .split(\",\")\n .some((token) => token.trim().toLowerCase().split(\"=\")[0].trim() === directive);\n}\n\n/**\n * Whether this response's representation is one we may encode — and therefore\n * one that varies by `Accept-Encoding`, even on the requests where we end up\n * sending identity.\n *\n * HTML only, on purpose. JSON view-data and API responses are left alone so\n * that this change cannot alter how they are produced, framed or cached;\n * widening the set is a separate decision.\n */\nexport function isCompressible(method: string, res: Response): boolean {\n // A HEAD response carries no body to encode, and emitting `Content-Encoding`\n // without one would describe a body the client never receives.\n if (method === \"HEAD\") {\n return false;\n }\n\n if (!res.body) {\n return false;\n }\n\n // 204/304 are bodyless; 206 is a byte range of an already-committed\n // representation and re-encoding it would invalidate its `Content-Range`.\n if (res.status < 200 || res.status === 204 || res.status === 206 || res.status === 304) {\n return false;\n }\n\n if (res.headers.has(\"Content-Range\")) {\n return false;\n }\n\n const contentType = res.headers.get(\"Content-Type\");\n if (!contentType || !/^\\s*text\\/html\\s*(;|$)/i.test(contentType)) {\n return false;\n }\n\n // Already encoded upstream — `identity` is the one value that means \"not\n // encoded\" and is safe to replace.\n const contentEncoding = res.headers.get(\"Content-Encoding\");\n if (contentEncoding && contentEncoding.trim().toLowerCase() !== \"identity\") {\n return false;\n }\n\n // RFC 9110 §5.2.2.6: `no-transform` forbids intermediaries *and* us from\n // changing the representation's encoding.\n if (hasDirective(res.headers.get(\"Cache-Control\"), \"no-transform\")) {\n return false;\n }\n\n const contentLength = res.headers.get(\"Content-Length\");\n if (contentLength !== null && Number(contentLength) < MIN_COMPRESSIBLE_BYTES) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Builds the encoder as a web `TransformStream`-shaped pair.\n *\n * Both codings are driven through `node:zlib` with an explicit per-write flush.\n * Without it the compressor holds output until its internal buffer fills,\n * which would sit on React's shell flush and turn a streamed render into a\n * buffered one — the compression win would be paid for in time to first byte.\n */\nexport function createEncoderStream(encoding: ContentEncoding) {\n const compressor =\n encoding === \"br\"\n ? createBrotliCompress({\n params: {\n [constants.BROTLI_PARAM_QUALITY]: BROTLI_QUALITY,\n [constants.BROTLI_PARAM_LGWIN]: BROTLI_WINDOW_BITS,\n },\n flush: constants.BROTLI_OPERATION_FLUSH,\n })\n : createGzip({ level: GZIP_LEVEL, flush: constants.Z_SYNC_FLUSH });\n\n return Duplex.toWeb(compressor) as unknown as ReadableWritablePair<Uint8Array, Uint8Array>;\n}\n\nfunction withVaryAcceptEncoding(headers: Headers) {\n const vary = headers.get(\"Vary\");\n if (!vary) {\n headers.set(\"Vary\", \"Accept-Encoding\");\n return;\n }\n const tokens = vary.split(\",\").map((token) => token.trim().toLowerCase());\n // `Vary: *` already means \"never reuse for another request\"; narrowing it\n // would be a downgrade.\n if (tokens.includes(\"*\") || tokens.includes(\"accept-encoding\")) {\n return;\n }\n headers.append(\"Vary\", \"Accept-Encoding\");\n}\n\n/**\n * Compresses an SSR HTML response when the client asked for it.\n *\n * Non-HTML responses are returned untouched — same object, same body, so this\n * is safe to apply at the edge of the server for every request.\n *\n * HTML responses always gain `Vary: Accept-Encoding`, whether or not this\n * particular request got an encoded body: without it a shared cache could\n * serve a stored encoded variant to a client that cannot decode it.\n */\nexport function compressResponse(req: Request, res: Response): Response {\n if (!isCompressible(req.method, res)) {\n return res;\n }\n\n const headers = new Headers(res.headers);\n withVaryAcceptEncoding(headers);\n\n const encoding = negotiateEncoding(req.headers.get(\"Accept-Encoding\"));\n if (!encoding) {\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n\n let encoder: ReadableWritablePair<Uint8Array, Uint8Array>;\n try {\n encoder = createEncoderStream(encoding);\n } catch {\n // A compressor we cannot construct is not worth failing a page render\n // over. Serve identity — with the `Vary` we already added.\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n\n headers.set(\"Content-Encoding\", encoding);\n // The length of the identity representation says nothing about the encoded\n // body, and a stale one would truncate the response.\n headers.delete(\"Content-Length\");\n\n return new Response(res.body!.pipeThrough(encoder), {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n}\n",
7
+ "import { readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { createUnsatisfiableResponse } from \"../http/createStreamResponse\";\nimport { formatContentRange, parseRangeHeader, resolveRange } from \"../http/range\";\nimport { generateETag } from \"./generateEtag\";\n\n/**\n * Every file in `dist/client` outside `/assets`, as absolute paths — what\n * Vite copied out of `public/` (#583).\n *\n * A root-level path may be an app route, so the static handler may only take\n * one that names a file the app really ships. This used to be guessed from the\n * extension, and every extension the list missed (`.mp4` on 0.58, `.wasm`,\n * `.csv` …) was answered by the router with a rendered 404 page. The build\n * output is fixed for the life of the process, so the exact set is read once\n * at boot instead.\n *\n * `assets/` is left out because the static handler takes everything under it\n * anyway. A name starting with a dot is left out at any depth: `.vite/` is\n * build metadata (both manifests and the asset base record), and a stray\n * `.DS_Store` or `.env` copied in from `public/` is nothing a request should\n * reach. `/.well-known` is served by its own rule.\n */\nexport async function listPublicFiles(clientDir: string): Promise<Set<string>> {\n const files = new Set<string>();\n\n async function walk(dir: string, topLevel: boolean) {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (topLevel && entry.name === \"assets\") continue;\n const path = join(dir, entry.name);\n let isDir = entry.isDirectory();\n let isFile = entry.isFile();\n if (entry.isSymbolicLink()) {\n try {\n const target = await stat(path);\n isDir = target.isDirectory();\n isFile = target.isFile();\n } catch {\n continue;\n }\n }\n if (isFile) files.add(path);\n // A symlinked directory is not followed: a link back up the tree would\n // never end, and `clientFilePath` only names paths inside `dist/client`.\n else if (isDir && !entry.isSymbolicLink()) await walk(path, false);\n }\n }\n\n await walk(clientDir, true);\n return files;\n}\n\nconst LONG_LIVED = \"public, max-age=31536000, must-revalidate\";\n\n/**\n * The response for a file in `dist/client` that is known to exist.\n *\n * Honours a single byte `Range`, so a `<video>` pointed at a public `.mp4`\n * can seek — Safari will not play one at all from a server that answers its\n * `bytes=0-1` probe with the whole file. Recent Bun releases slice a\n * file-backed 200 themselves; doing it here keeps that from depending on the\n * Bun version a deployment runs, and answers an unsatisfiable range with the\n * same 416 the `stream()` responses use.\n *\n * `Bun.file().type` is the mime lookup, and is `application/octet-stream` for\n * an extension it does not know.\n */\nexport function staticFileResponse(req: Request, path: string): Response {\n const file = Bun.file(path);\n const total = file.size;\n const etag = generateETag(file.lastModified);\n\n const headers: Record<string, string> = {\n \"Content-Type\": file.type || \"application/octet-stream\",\n \"Cache-Control\": LONG_LIVED,\n \"Accept-Ranges\": \"bytes\",\n ETag: etag,\n };\n\n const range = parseRangeHeader(req.headers.get(\"Range\"));\n\n if (range) {\n const resolved = resolveRange(range, total);\n if (!resolved) {\n return createUnsatisfiableResponse(total);\n }\n return new Response(file.slice(resolved.start, resolved.end + 1).stream(), {\n status: 206,\n headers: {\n ...headers,\n \"Content-Range\": formatContentRange(resolved.start, resolved.end, total),\n \"Content-Length\": String(resolved.length),\n },\n });\n }\n\n return new Response(file.stream(), {\n headers: { ...headers, \"Content-Length\": String(total) },\n });\n}\n",
8
+ "export function generateETag(lastModified: number): string {\n // Assuming the last modified timestamp is in milliseconds\n const lastModifiedStr = lastModified.toString();\n\n const hasher = new Bun.CryptoHasher(\"sha1\");\n hasher.update(lastModifiedStr);\n const hash = hasher.digest(\"hex\");\n\n return hash;\n}\n",
9
+ "import { DEFAULT_ASSET_BASE, assetUrl } from \"../config/assetBase\";\n\n/** The subset of a Vite manifest entry this module reads. */\nexport interface ViteManifestChunk {\n file: string;\n imports?: string[];\n dynamicImports?: string[];\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>;\n\n/** Vite's manifest key for the module that boots hydration. */\nexport const CLIENT_ENTRY_KEY = \"app/client.tsx\";\n\n/**\n * How the shell boots hydration in production: `module` is imported from the\n * bootstrap script, `preload` is every chunk that import pulls in — see\n * `clientEntry` in `ViewRouteDispatcher` for why the entry does not go through\n * React's `bootstrapModules`.\n *\n * `undefined` when the manifest has no client entry, which means a `dist/`\n * interrupted between the server and client build passes. Degrading beats\n * throwing here: this runs at boot, so a deref would take down API routes,\n * static assets and health checks over what is only a document concern, and\n * the dispatcher already renders a shell that simply does not hydrate.\n *\n * `assetBase` is the base the client build recorded — see `readBuiltAssetBase`.\n */\nexport function createClientEntry(\n manifest: ViteManifest,\n assetBase: string = DEFAULT_ASSET_BASE,\n): { module: string; preload: string[] } | undefined {\n const file = manifest[CLIENT_ENTRY_KEY]?.file;\n if (!file) {\n return undefined;\n }\n return {\n module: assetUrl(file, assetBase),\n preload: collectModulePreloads(manifest, CLIENT_ENTRY_KEY, assetBase),\n };\n}\n\n/**\n * Every chunk URL that importing `entryKey` pulls in, itself first.\n *\n * The browser can only discover these one parse at a time — it learns about a\n * chunk's static imports after the chunk has arrived and been parsed — so a\n * `layout -> view -> child component` graph costs one round trip per level.\n * Handing the whole list to the shell as `modulepreload` hints turns that\n * chain into one parallel fetch (#352).\n *\n * `dynamicImports` are deliberately left out: those are the pieces the app\n * asked to load lazily, and preloading them would download code the current\n * route may never render.\n */\nexport function collectModulePreloads(\n manifest: ViteManifest,\n entryKey: string,\n assetBase: string = DEFAULT_ASSET_BASE,\n): string[] {\n const urls: string[] = [];\n // Chunk graphs are cyclic often enough (two chunks importing each other\n // through a shared module) that walking them without a visited set hangs.\n const visited = new Set<string>();\n\n const walk = (key: string) => {\n if (visited.has(key)) return;\n visited.add(key);\n const chunk = manifest[key];\n if (!chunk?.file) return;\n urls.push(assetUrl(chunk.file, assetBase));\n for (const imported of chunk.imports ?? []) {\n walk(imported);\n }\n };\n\n walk(entryKey);\n\n return urls;\n}\n",
10
+ "import { isReservedAssetPath, RESERVED_ROUTE_PREFIX } from \"../services/router/ViewRouteDispatcher\";\n\n/**\n * A JavaScript module under `/assets/` — the only shape a client build chunk\n * has. Vite writes every chunk into `assets/` with a `.js` extension (`.mjs`\n * is accepted for a build configured to emit it).\n *\n * The extension is matched at the end of the path, not anywhere in it:\n * `includes(\".js\")` also matched `app.js.map` and `data.json`, so a missing\n * source map was answered with a script that reloads the page.\n */\nconst BUILD_CHUNK = new RegExp(`^${RESERVED_ROUTE_PREFIX}/.+\\\\.m?js$`);\n\nexport function isBuildChunkPath(pathname: string): boolean {\n return BUILD_CHUNK.test(pathname);\n}\n\n/**\n * `/assets` or anything under it — the prefix the router refuses to mount a\n * route on at boot, so nothing there is ever the app's to answer. Defined\n * beside that check so the two cannot drift apart.\n */\nexport { isReservedAssetPath };\n\n/**\n * The answer to a static-looking request with no file behind it in\n * `dist/client`, or `undefined` to hand the request to the app.\n *\n * A missing build chunk is almost always a document rendered by another\n * release asking for its own chunks — a deploy between page load and a lazy\n * `import()`, or two releases serving at once. The page cannot continue with\n * the chunk it wanted, so it gets a module that reloads it onto this release's\n * document. Only for build chunks: outside `/assets/` a `.js` path may be an\n * app route, and a classic `<script src>` answered with a reload reloads\n * forever.\n *\n * `no-store` because the stub is a stand-in for one release's chunk, served\n * under that chunk's URL. Cached — by the browser or by an edge in front of\n * the origin — it would outlive the deploy that caused it and answer the\n * request after the real chunk is back.\n *\n * The body is only the reload. An earlier version opened with\n * `if(caches){caches?.delete(distPath)}`, which was wrong three times over:\n * `CacheStorage.delete` takes a cache *name*, not a URL, so a filesystem path\n * matched nothing; that path told anyone who asked for a missing chunk where\n * the server keeps its files; and `caches` is `[SecureContext]`, so on a\n * plain-http origin the bare identifier is not defined at all and reading it\n * threw a `ReferenceError` before the reload below could run — the recovery\n * failing exactly where it was needed.\n */\nexport function staticAssetMiss(pathname: string): Response | undefined {\n if (isBuildChunkPath(pathname)) {\n return new Response(`window.location.reload();export {}`, {\n headers: {\n \"Content-Type\": \"application/javascript\",\n \"Cache-Control\": \"no-store\",\n },\n });\n }\n\n // `/assets` is reserved for build output (the router rejects routes there\n // at boot), so a miss is a miss — 404 without paying for an SSR render.\n if (isReservedAssetPath(pathname)) {\n return new Response(\"Not found\", { status: 404 });\n }\n\n // Anywhere else the public-file pattern matched on extension alone, so this\n // may well be an app route — a file route like\n // `this.file(() => Bun.file(...))` mounted at `/files/logo.svg` lands here\n // too. The app answers it rather than a 404 on its behalf.\n return undefined;\n}\n",
11
+ "import { stringEraRefusal } from \"../http/Error\";\nimport { isApiPath } from \"../services/router/apiPath\";\n\n// The production server's last resort: an error nothing on the way here turned\n// into a response. Request breakers (auth, 404s, 416s) are answered by the\n// dispatchers before this, so what arrives is a genuine failure — and its\n// message and stack are for the developer, not for whoever triggered it. They\n// can carry absolute paths, dependency versions, SQL fragments and column\n// names. The dev server renders them on purpose (`httpDev.ts`); this does not.\n\nconst GENERIC_500_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Internal Server Error</title>\n <style>\n body { font-family: system-ui, sans-serif; margin: 0; min-height: 100vh; display: grid; place-items: center; }\n main { text-align: center; padding: 16px; }\n h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }\n p { margin: 0; opacity: 0.7; }\n </style>\n </head>\n <body>\n <main>\n <h1>Something went wrong</h1>\n <p>Please try again later.</p>\n </main>\n </body>\n</html>`;\n\nexport function unhandledErrorResponse(\n err: unknown,\n pathname: string,\n onException?: (error: Error) => void,\n): Response {\n // `onException` is the report, and the default one `App` installs is a\n // `console.error`, so logging here as well printed every failure twice\n // (three times for `/api`, whose dispatcher logs before rethrowing). Only\n // without a reporter does this log itself.\n //\n // Reported for `/api` too: an app's error tracking should see an API failure\n // that got this far, not only a page one. `onRequestFail` is a different\n // hook (route config, called by the dispatchers), so this is not a second\n // report through the same channel.\n if (!onException) {\n console.error(err);\n } else {\n try {\n // The hook is typed to receive an `Error`; a thrown string or object is\n // wrapped so a reporter reading `.stack` or `.name` gets one.\n onException(err instanceof Error ? err : new Error(String(err), { cause: err }));\n } catch (reportError) {\n // A broken reporter must not turn a 500 into a leaked stack either.\n console.error(err);\n console.error(reportError);\n }\n }\n\n if (isApiPath(pathname)) {\n return new Response(\n JSON.stringify({ error: stringEraRefusal(\"server_error\", \"Internal Server Error\", 500) }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n return new Response(GENERIC_500_HTML, {\n status: 500,\n headers: { \"Content-Type\": \"text/html; charset=utf-8\" },\n });\n}\n",
12
+ "/**\n * Which `X-Forwarded-For` entries the production server believes (#8).\n *\n * `X-Forwarded-For` is written by whoever sends the request. A client talking\n * to the app directly — or through a proxy that appends to the header rather\n * than replacing it — picks any address it likes, and `clientIp` (the rate\n * limiter's default key) used to read the left-most entry, which is exactly\n * the one the client wrote. So the server decides here, once, at the edge,\n * and hands the app a single address it can rely on:\n *\n * - `none` (the default): no proxy is trusted. The header is replaced with the\n * socket's peer address, and `X-Real-IP` is dropped.\n * - `hops` (`GEMI_TRUST_PROXY=<n>`): the `n` proxies nearest the app are\n * trusted. Each appends the address it was reached from, so the client is\n * the `n`-th entry from the right of `X-Forwarded-For`. Anything\n * further left was written by someone the app does not trust and is dropped.\n * - `all` (`GEMI_TRUST_PROXY=true`): the inbound header is passed through\n * unchanged, as before 0.85. Only sound behind a proxy that overwrites\n * `X-Forwarded-For` (and `X-Real-IP`) rather than appending to it.\n */\nexport type ForwardedTrust =\n | { kind: \"none\" }\n | { kind: \"all\" }\n | { kind: \"hops\"; hops: number };\n\nconst NONE: ForwardedTrust = { kind: \"none\" };\n\n/**\n * `GEMI_TRUST_PROXY` as a policy. Unset, empty, `false`, `off` and `0` trust\n * nothing; `true` trusts everything; a positive integer is a hop count.\n * Anything else throws, so a typo fails the boot instead of silently trusting\n * nothing (every client sharing the proxy's address) or everything.\n */\nexport function parseTrustProxy(value: string | undefined): ForwardedTrust {\n const raw = (value ?? \"\").trim().toLowerCase();\n if (raw === \"\" || raw === \"false\" || raw === \"off\" || raw === \"0\") {\n return NONE;\n }\n if (raw === \"true\") {\n return { kind: \"all\" };\n }\n if (/^[1-9]\\d*$/.test(raw)) {\n return { kind: \"hops\", hops: Number(raw) };\n }\n throw new Error(\n `GEMI_TRUST_PROXY must be \"false\", \"true\" or the number of proxies in front of the app (e.g. 1). Got ${JSON.stringify(value)}.`,\n );\n}\n\n/**\n * Rewrites `headers` so `X-Forwarded-For` holds what `trust` says the client\n * address is. `peer` is the socket's remote address — `null` for a unix\n * socket, where the immediate hop is still counted as one proxy.\n */\nexport function applyForwardedTrust(\n headers: Headers,\n peer: string | null,\n trust: ForwardedTrust,\n): void {\n if (trust.kind === \"all\") {\n if (!headers.get(\"x-forwarded-for\") && peer) {\n headers.set(\"x-forwarded-for\", peer);\n }\n return;\n }\n\n // Under any other policy `X-Real-IP` is as client-written as the rest; the\n // address the app should use is the one left in `X-Forwarded-For`.\n headers.delete(\"x-real-ip\");\n\n let client: string | null = peer;\n if (trust.kind === \"hops\") {\n const entries = (headers.get(\"x-forwarded-for\") ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n // The chain is `entries` + `peer`; the client sits `hops` places left of\n // its end, i.e. `entries[entries.length - hops]`. A shorter chain than\n // expected means the request skipped a proxy, so its left-most hop is the\n // furthest thing seen — never anything further left than that.\n const index = entries.length - trust.hops;\n client = index >= 0 ? entries[index]! : (entries[0] ?? peer);\n }\n\n if (client) {\n headers.set(\"x-forwarded-for\", client);\n } else {\n headers.delete(\"x-forwarded-for\");\n }\n}\n"
13
+ ],
14
+ "mappings": "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",
15
+ "debugId": "A5122197D3BF6AEC64756E2164756E21",
16
+ "names": []
17
+ }