gemi 0.84.1 → 0.86.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 (280) 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-2dzqrf0z.js +55 -0
  63. package/dist/{chunk-rp5j1mgk.js.map → chunk-2dzqrf0z.js.map} +3 -3
  64. package/dist/{chunk-ah9ajys0.js → chunk-2gdhcswa.js} +1 -1
  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-3zb2ycxj.js → chunk-7c33ngqs.js} +2 -2
  74. package/dist/{chunk-3zb2ycxj.js.map → chunk-7c33ngqs.js.map} +1 -1
  75. package/dist/{chunk-en3mtnsg.js → chunk-7n5775qx.js} +2 -2
  76. package/dist/{chunk-en3mtnsg.js.map → chunk-7n5775qx.js.map} +1 -1
  77. package/dist/{chunk-bn9pzgww.js → chunk-7nj2t2gm.js} +2 -2
  78. package/dist/{chunk-bn9pzgww.js.map → chunk-7nj2t2gm.js.map} +1 -1
  79. package/dist/{chunk-kfavcgv2.js → chunk-81k26w39.js} +2 -2
  80. package/dist/{chunk-kfavcgv2.js.map → chunk-81k26w39.js.map} +1 -1
  81. package/dist/{chunk-cg4k40zy.js → chunk-81v4c4b1.js} +2 -2
  82. package/dist/{chunk-cg4k40zy.js.map → chunk-81v4c4b1.js.map} +1 -1
  83. package/dist/{chunk-wh728wd6.js → chunk-8gexb1gt.js} +2 -2
  84. package/dist/{chunk-wh728wd6.js.map → chunk-8gexb1gt.js.map} +1 -1
  85. package/dist/{chunk-zfch4da5.js → chunk-9tsw1bmt.js} +2 -2
  86. package/dist/{chunk-8mmfpqgs.js.map → chunk-9tsw1bmt.js.map} +1 -1
  87. package/dist/{chunk-m0zba09s.js → chunk-9tv5j3b2.js} +3 -3
  88. package/dist/{chunk-m0zba09s.js.map → chunk-9tv5j3b2.js.map} +1 -1
  89. package/dist/{chunk-jg9eqd3r.js → chunk-c3gzpjba.js} +1 -1
  90. package/dist/{chunk-r5e4vpa1.js → chunk-cbycz5z3.js} +2 -2
  91. package/dist/{chunk-r5e4vpa1.js.map → chunk-cbycz5z3.js.map} +1 -1
  92. package/dist/{chunk-cfvq30n4.js → chunk-cfykfnqx.js} +2 -2
  93. package/dist/{chunk-cfvq30n4.js.map → chunk-cfykfnqx.js.map} +1 -1
  94. package/dist/{chunk-eysexnqb.js → chunk-ct7wxm98.js} +2 -2
  95. package/dist/{chunk-eysexnqb.js.map → chunk-ct7wxm98.js.map} +1 -1
  96. package/dist/{chunk-v27a4se1.js → chunk-d3jkypc7.js} +3 -3
  97. package/dist/{chunk-v27a4se1.js.map → chunk-d3jkypc7.js.map} +1 -1
  98. package/dist/{chunk-vfrrzr10.js → chunk-dadygfkf.js} +2 -2
  99. package/dist/{chunk-vfrrzr10.js.map → chunk-dadygfkf.js.map} +1 -1
  100. package/dist/{chunk-m4xw99vm.js → chunk-dwqh79e5.js} +2 -2
  101. package/dist/{chunk-m4xw99vm.js.map → chunk-dwqh79e5.js.map} +1 -1
  102. package/dist/chunk-eptv0nvv.js +24 -0
  103. package/dist/chunk-eptv0nvv.js.map +17 -0
  104. package/dist/{chunk-ng8pp9k2.js → chunk-fbwe0agk.js} +2 -2
  105. package/dist/{chunk-ng8pp9k2.js.map → chunk-fbwe0agk.js.map} +1 -1
  106. package/dist/{chunk-495qwteq.js → chunk-fc2je244.js} +3 -3
  107. package/dist/{chunk-495qwteq.js.map → chunk-fc2je244.js.map} +1 -1
  108. package/dist/{chunk-gr61ymse.js → chunk-gx0x772p.js} +2 -2
  109. package/dist/{chunk-gr61ymse.js.map → chunk-gx0x772p.js.map} +1 -1
  110. package/dist/{chunk-tdnfhe7x.js → chunk-ha705bcz.js} +3 -3
  111. package/dist/{chunk-tdnfhe7x.js.map → chunk-ha705bcz.js.map} +1 -1
  112. package/dist/chunk-jhe0t7yj.js +5 -0
  113. package/dist/chunk-jhe0t7yj.js.map +11 -0
  114. package/dist/{chunk-d0qwdeza.js → chunk-k5j65f2c.js} +2 -2
  115. package/dist/{chunk-d0qwdeza.js.map → chunk-k5j65f2c.js.map} +1 -1
  116. package/dist/{chunk-pt59xjfc.js → chunk-kmsrzbx1.js} +2 -2
  117. package/dist/{chunk-pt59xjfc.js.map → chunk-kmsrzbx1.js.map} +1 -1
  118. package/dist/{chunk-v1nm4tcq.js → chunk-m7y8d3k7.js} +2 -2
  119. package/dist/{chunk-v1nm4tcq.js.map → chunk-m7y8d3k7.js.map} +1 -1
  120. package/dist/{chunk-k2qh3hvd.js → chunk-mk8m3ffx.js} +2 -2
  121. package/dist/{chunk-k2qh3hvd.js.map → chunk-mk8m3ffx.js.map} +1 -1
  122. package/dist/{chunk-z7442w3q.js → chunk-mszy6cfw.js} +2 -2
  123. package/dist/{chunk-z7442w3q.js.map → chunk-mszy6cfw.js.map} +1 -1
  124. package/dist/{chunk-kb3xk9r8.js → chunk-ndat0nf0.js} +2 -2
  125. package/dist/{chunk-kb3xk9r8.js.map → chunk-ndat0nf0.js.map} +1 -1
  126. package/dist/{chunk-j9wqzemf.js → chunk-p0m3qgs5.js} +2 -2
  127. package/dist/{chunk-j9wqzemf.js.map → chunk-p0m3qgs5.js.map} +1 -1
  128. package/dist/{chunk-8mmfpqgs.js → chunk-p7r3ecpk.js} +2 -2
  129. package/dist/{chunk-zfch4da5.js.map → chunk-p7r3ecpk.js.map} +1 -1
  130. package/dist/{chunk-zp971jp2.js → chunk-pmmrhak1.js} +3 -3
  131. package/dist/{chunk-zp971jp2.js.map → chunk-pmmrhak1.js.map} +1 -1
  132. package/dist/{chunk-0agfx93f.js → chunk-ptkt4h2j.js} +2 -2
  133. package/dist/{chunk-0agfx93f.js.map → chunk-ptkt4h2j.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/auth/useForgotPassword.d.ts +2 -1
  184. package/dist/client/auth/useForgotPassword.d.ts.map +1 -1
  185. package/dist/client/auth/useResetPassword.d.ts +2 -1
  186. package/dist/client/auth/useResetPassword.d.ts.map +1 -1
  187. package/dist/client/auth/useSignIn.d.ts +11 -1
  188. package/dist/client/auth/useSignIn.d.ts.map +1 -1
  189. package/dist/client/auth/useSignOut.d.ts +2 -1
  190. package/dist/client/auth/useSignOut.d.ts.map +1 -1
  191. package/dist/client/auth/useSignUp.d.ts +2 -1
  192. package/dist/client/auth/useSignUp.d.ts.map +1 -1
  193. package/dist/client/index.d.ts +3 -1
  194. package/dist/client/index.d.ts.map +1 -1
  195. package/dist/client/index.js +169 -65
  196. package/dist/client/index.js.map +1 -1
  197. package/dist/client/useMutation.d.ts +33 -6
  198. package/dist/client/useMutation.d.ts.map +1 -1
  199. package/dist/client/useQuery.d.ts.map +1 -1
  200. package/dist/config/index.js +1 -1
  201. package/dist/console/run.js +2 -2
  202. package/dist/console/run.js.map +1 -1
  203. package/dist/container/index.js +2 -2
  204. package/dist/container/index.js.map +1 -1
  205. package/dist/database/index.js +2 -2
  206. package/dist/database/index.js.map +1 -1
  207. package/dist/email/Email.d.ts.map +1 -1
  208. package/dist/email/debugEmail.d.ts +40 -0
  209. package/dist/email/debugEmail.d.ts.map +1 -0
  210. package/dist/email/index.js +4 -3
  211. package/dist/email/index.js.map +6 -5
  212. package/dist/facades/index.js +2 -2
  213. package/dist/facades/index.js.map +1 -1
  214. package/dist/foundation/index.js +2 -2
  215. package/dist/foundation/index.js.map +1 -1
  216. package/dist/http/ApiRouter.d.ts +12 -0
  217. package/dist/http/ApiRouter.d.ts.map +1 -1
  218. package/dist/http/CSRFMiddleware.d.ts +1 -1
  219. package/dist/http/CSRFMiddleware.d.ts.map +1 -1
  220. package/dist/http/Error.d.ts +50 -0
  221. package/dist/http/Error.d.ts.map +1 -1
  222. package/dist/http/HttpRequest.d.ts +26 -0
  223. package/dist/http/HttpRequest.d.ts.map +1 -1
  224. package/dist/http/RateLimitMiddleware.d.ts +6 -3
  225. package/dist/http/RateLimitMiddleware.d.ts.map +1 -1
  226. package/dist/http/Router.d.ts.map +1 -1
  227. package/dist/http/errors.d.ts.map +1 -1
  228. package/dist/http/index.d.ts +2 -1
  229. package/dist/http/index.d.ts.map +1 -1
  230. package/dist/http/index.js +2 -2
  231. package/dist/http/index.js.map +1 -1
  232. package/dist/http/mediaType.d.ts +16 -0
  233. package/dist/http/mediaType.d.ts.map +1 -0
  234. package/dist/http/refusal.d.ts +52 -0
  235. package/dist/http/refusal.d.ts.map +1 -0
  236. package/dist/i18n/dictionaryRuntime.js +2 -2
  237. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  238. package/dist/i18n/index.js +2 -2
  239. package/dist/i18n/index.js.map +2 -2
  240. package/dist/kernel/index.js +2 -2
  241. package/dist/kernel/index.js.map +2 -2
  242. package/dist/orm/index.js +2 -2
  243. package/dist/orm/index.js.map +1 -1
  244. package/dist/server/devFetch.d.ts.map +1 -1
  245. package/dist/server/forwardedFor.d.ts +42 -0
  246. package/dist/server/forwardedFor.d.ts.map +1 -0
  247. package/dist/server/httpProd.d.ts.map +1 -1
  248. package/dist/server/index.js +2 -2
  249. package/dist/server/index.js.map +1 -1
  250. package/dist/server/staticFile.d.ts +33 -0
  251. package/dist/server/staticFile.d.ts.map +1 -0
  252. package/dist/server/unhandledError.d.ts.map +1 -1
  253. package/dist/services/index.js +2 -2
  254. package/dist/services/index.js.map +2 -2
  255. package/dist/services/mcp/McpRegistry.d.ts +2 -1
  256. package/dist/services/mcp/McpRegistry.d.ts.map +1 -1
  257. package/dist/services/mcp/toAgentTools.d.ts +1 -1
  258. package/dist/services/mcp/toAgentTools.d.ts.map +1 -1
  259. package/dist/services/queue/work.js +2 -2
  260. package/dist/services/queue/work.js.map +1 -1
  261. package/dist/services/router/notFound.d.ts.map +1 -1
  262. package/dist/services/router/policyDenied.d.ts.map +1 -1
  263. package/dist/services/router/serverQueryFetcher.d.ts.map +1 -1
  264. package/dist/support/index.js +2 -2
  265. package/dist/support/index.js.map +1 -1
  266. package/dist/testing/index.js +1 -1
  267. package/package.json +1 -1
  268. package/skills/gemi-react-best-practices/rules/controller-throw-framework-errors.md +5 -0
  269. package/dist/chunk-302mkqeq.js +0 -7
  270. package/dist/chunk-49akdtfe.js +0 -17
  271. package/dist/chunk-ash9e6fn.js +0 -5
  272. package/dist/chunk-e43drft2.js +0 -5
  273. package/dist/chunk-j5xcfeqx.js +0 -24
  274. package/dist/chunk-j5xcfeqx.js.map +0 -16
  275. package/dist/chunk-rp5j1mgk.js +0 -55
  276. package/dist/chunk-tmwsvf02.js +0 -5
  277. package/dist/chunks/ThemeProvider-Dn3UREDn.js.map +0 -1
  278. /package/dist/{chunk-ah9ajys0.js.map → chunk-2gdhcswa.js.map} +0 -0
  279. /package/dist/{chunk-jg9eqd3r.js.map → chunk-c3gzpjba.js.map} +0 -0
  280. /package/dist/{chunk-pgpqsgzx.js.map → chunk-sejnmn1q.js.map} +0 -0
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../http/Controller.ts", "../http/getCookies.ts", "../http/range.ts", "../http/Error.ts", "../http/Router.ts", "../http/validate.ts", "../http/modelOriginated.ts", "../http/requestDomain.ts", "../http/HttpRequest.ts", "../http/errors.ts", "../facades/Facade.ts", "../services/file-storage/drivers/FileStorageDriver.ts", "../services/file-storage/drivers/abortableBody.ts", "../services/file-storage/drivers/FileSystemDriver.ts", "../services/file-storage/config.ts", "../services/file-storage/FilesystemManager.ts", "../facades/Storage.ts", "../support/sharp.ts", "../services/logging/LogManager.ts", "../facades/Log.ts"],
3
+ "sources": ["../http/Controller.ts", "../http/getCookies.ts", "../http/range.ts", "../http/Router.ts", "../http/validate.ts", "../http/mediaType.ts", "../http/modelOriginated.ts", "../http/requestDomain.ts", "../http/HttpRequest.ts", "../http/errors.ts", "../facades/Facade.ts", "../services/file-storage/drivers/FileStorageDriver.ts", "../services/file-storage/drivers/abortableBody.ts", "../services/file-storage/drivers/FileSystemDriver.ts", "../services/file-storage/config.ts", "../services/file-storage/FilesystemManager.ts", "../facades/Storage.ts", "../support/sharp.ts", "../services/logging/LogManager.ts", "../facades/Log.ts", "../services/redis/RedisManager.ts"],
4
4
  "sourcesContent": [
5
5
  "import type { HttpRequest } from \"./HttpRequest\";\n\nexport class Controller {\n static kind = \"controller\" as const;\n\n constructor() {}\n}\n\ntype PromiseOrData<T> = T | Promise<T>;\n\nexport abstract class ResourceController extends Controller {\n abstract store(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract update(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract delete(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract list(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract show(req: HttpRequest<any, any>): PromiseOrData<any>;\n}\n\nexport type ControllerMethods<\n T extends new () => Controller | ResourceController,\n> = {\n [K in keyof InstanceType<T>]: InstanceType<T>[K] extends Function ? K : never;\n}[keyof InstanceType<T>];\n",
6
6
  "/**\n * Parses a `Cookie` request header into name -> value.\n *\n * Splits each pair on its *first* `=`: base64 padding and JWTs put `=` inside\n * the value, and splitting on every one would cut them off. A segment with no\n * `=` or an empty name is skipped rather than thrown on, since browsers and\n * proxies do send `flag;`-style pairs and the client may not control them.\n * A repeated name keeps its last value.\n *\n * Values are not percent-decoded: server-written cookies (`createCookie`) are\n * unencoded, so decoding here would change any value that happens to contain\n * a `%`. A cookie the browser writes may be encoded — `useLocale` encodes\n * `i18n-locale` — and its reader decodes it if it needs to.\n */\nexport function parseCookieHeader(header: string | null | undefined): Map<string, string> {\n const cookies = new Map<string, string>();\n if (!header) {\n return cookies;\n }\n for (const pair of header.split(\";\")) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) continue;\n const name = pair.slice(0, eq).trim();\n if (!name) continue;\n cookies.set(name, pair.slice(eq + 1).trim());\n }\n return cookies;\n}\n\nexport function getCookies(req: Request): Map<string, string> {\n return parseCookieHeader(req.headers.get(\"cookie\"));\n}\n",
7
7
  "/**\n * RFC 7233 byte-range parsing and resolution.\n *\n * Deliberately dependency-free: the file storage drivers import `ByteRange`\n * from here, and drivers otherwise import nothing out of `http/`.\n */\n\n/**\n * A parsed but *unresolved* `Range` header. The suffix form carries no absolute\n * offsets — resolving it needs the total size of the object.\n */\nexport type ByteRange =\n | { kind: \"offset\"; start: number; end: number | null }\n | { kind: \"suffix\"; suffixLength: number };\n\n/** Absolute, inclusive, clamped-to-the-object byte offsets. */\nexport type ResolvedRange = { start: number; end: number; length: number };\n\n/** A parsed response `Content-Range` of the `bytes S-E/TOTAL` form. */\nexport type ContentRange = { start: number; end: number; total: number };\n\nfunction parseInteger(raw: string): number | null {\n // Reject anything that isn't a run of ASCII digits. `Number()` would happily\n // take \"0x10\", \" 5\", \"1e3\" and \"+5\", none of which are valid byte-pos.\n if (!/^\\d+$/.test(raw)) {\n return null;\n }\n const value = Number(raw);\n return Number.isSafeInteger(value) ? value : null;\n}\n\n/**\n * Parses a request `Range` header.\n *\n * Returns `null` for anything we cannot or will not serve as a partial\n * response. That is not an error path: RFC 7233 §3.1 requires a recipient to\n * ignore a `Range` it does not understand, and §4.1 lets a server ignore one it\n * does. Every `null` here means \"serve the complete representation with 200\".\n *\n * Only a single range is supported — we never emit `multipart/byteranges`, so a\n * multi-range request is ignored rather than partially honoured.\n */\nexport function parseRangeHeader(\n header: string | null | undefined,\n): ByteRange | null {\n if (!header) {\n return null;\n }\n\n const trimmed = header.trim();\n if (!/^bytes=/i.test(trimmed)) {\n return null;\n }\n\n const specs = trimmed\n .slice(\"bytes=\".length)\n .split(\",\")\n .map((spec) => spec.trim());\n\n // A single trailing comma is tolerated (\"bytes=0-9,\") because some clients\n // emit it. More than one *non-empty* spec is a genuine multi-range request.\n const present = specs.filter((spec) => spec !== \"\");\n if (present.length !== 1) {\n return null;\n }\n\n const spec = present[0];\n const separator = spec.indexOf(\"-\");\n if (separator === -1) {\n return null;\n }\n\n const rawStart = spec.slice(0, separator);\n const rawEnd = spec.slice(separator + 1);\n\n if (rawStart === \"\") {\n // Suffix form: `bytes=-N`, the last N bytes.\n const suffixLength = parseInteger(rawEnd);\n if (suffixLength === null) {\n return null;\n }\n // `bytes=-0` parses cleanly and resolves to unsatisfiable (416). Collapsing\n // it to `null` here would serve the whole file instead, which the spec does\n // not allow. Satisfiability is `resolveRange`'s job alone.\n return { kind: \"suffix\", suffixLength };\n }\n\n const start = parseInteger(rawStart);\n if (start === null) {\n return null;\n }\n\n if (rawEnd === \"\") {\n return { kind: \"offset\", start, end: null };\n }\n\n const end = parseInteger(rawEnd);\n if (end === null || end < start) {\n return null;\n }\n\n return { kind: \"offset\", start, end };\n}\n\n/**\n * Resolves a parsed range against a known total size.\n *\n * Returns `null` when the range is unsatisfiable, which the caller must turn\n * into a 416 rather than a full response.\n */\nexport function resolveRange(\n range: ByteRange,\n total: number,\n): ResolvedRange | null {\n // An empty (or unknown-length) representation has no satisfiable range at\n // all. Handling it here is what keeps `bytes 0--1/0` from ever being built.\n if (!Number.isFinite(total) || total <= 0) {\n return null;\n }\n\n let start: number;\n let end: number;\n\n if (range.kind === \"suffix\") {\n if (range.suffixLength <= 0) {\n return null;\n }\n start = Math.max(0, total - range.suffixLength);\n end = total - 1;\n } else {\n if (range.start >= total) {\n return null;\n }\n start = range.start;\n // An end past the last byte is clamped, not rejected — Chrome routinely\n // asks for `bytes=0-2147483647` when loading a <video>.\n end = range.end === null ? total - 1 : Math.min(range.end, total - 1);\n if (end < start) {\n return null;\n }\n }\n\n return { start, end, length: end - start + 1 };\n}\n\n/** Renders a range back into a `Range` request header for a storage backend. */\nexport function toRangeHeaderValue(range: ByteRange): string {\n if (range.kind === \"suffix\") {\n return `bytes=-${range.suffixLength}`;\n }\n return range.end === null\n ? `bytes=${range.start}-`\n : `bytes=${range.start}-${range.end}`;\n}\n\n/**\n * Parses a response `Content-Range`. Storage backends report the authoritative\n * total size of the object here on a ranged read, which is what lets a driver\n * answer a range without a second round trip for the size.\n *\n * The unsatisfied form used on a 416 has no offsets and returns `null`.\n */\nexport function parseContentRange(\n value: string | null | undefined,\n): ContentRange | null {\n if (!value) {\n return null;\n }\n const match = /^bytes\\s+(\\d+)-(\\d+)\\/(\\d+)$/i.exec(value.trim());\n if (!match) {\n return null;\n }\n const start = parseInteger(match[1]);\n const end = parseInteger(match[2]);\n const total = parseInteger(match[3]);\n if (start === null || end === null || total === null || end < start) {\n return null;\n }\n return { start, end, total };\n}\n\nexport function formatContentRange(\n start: number,\n end: number,\n total: number,\n): string {\n return `bytes ${start}-${end}/${total}`;\n}\n\n/** The `Content-Range` of a 416: no offsets, just the current total size. */\nexport function formatUnsatisfiedContentRange(total: number): string {\n return `bytes */${total}`;\n}\n",
8
- "export const GEMI_REQUEST_BREAKER_ERROR = \"GEMI_REQUEST_BREAKER_ERROR\";\n\nexport class RequestBreakerError extends Error {\n public kind = GEMI_REQUEST_BREAKER_ERROR;\n public payload: {\n api: Record<string, any>;\n view: Record<string, any>;\n /**\n * What a `.json` view navigation answers, when that differs from `api`.\n * Absent, it gets `api` — right for most breakers, but not for one that\n * must be a 401 to an API client and a redirect to the client router.\n */\n viewData?: Record<string, any>;\n } = { api: {}, view: {} };\n}\n",
9
- "import { RequestBreakerError } from \"./Error\";\nimport type { HttpRequest } from \"./HttpRequest\";\n\ntype MiddlewareResult = Partial<{\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}>;\n\nexport type MiddlewareReturnType =\n | void\n | Promise<MiddlewareResult>\n | MiddlewareResult;\n\nexport type RouterMiddleware = (\n req: HttpRequest,\n ctx: any,\n) => MiddlewareReturnType;\n\nexport class ValidationError extends RequestBreakerError {\n errors: Record<string, string[]> = {};\n constructor(errors: Record<string, string[]>) {\n super(\"Validation error\");\n this.name = \"ValidationError\";\n this.errors = errors;\n this.payload = {\n api: {\n status: 400,\n data: {\n error: {\n kind: \"validation_error\",\n messages: errors,\n },\n },\n headers: {\n \"Content-Type\": \"application/json\",\n },\n },\n view: {\n status: 400,\n },\n };\n }\n}\n",
8
+ "import { RequestBreakerError } from \"./Error\";\nimport type { HttpRequest } from \"./HttpRequest\";\n\ntype MiddlewareResult = Partial<{\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}>;\n\nexport type MiddlewareReturnType =\n | void\n | Promise<MiddlewareResult>\n | MiddlewareResult;\n\nexport type RouterMiddleware = (\n req: HttpRequest,\n ctx: any,\n) => MiddlewareReturnType;\n\nexport class ValidationError extends RequestBreakerError {\n errors: Record<string, string[]> = {};\n constructor(errors: Record<string, string[]>) {\n super(\"Validation error\");\n this.name = \"ValidationError\";\n this.errors = errors;\n this.payload = {\n api: {\n status: 400,\n data: {\n error: {\n kind: \"validation_error\",\n messages: errors,\n status: 400,\n },\n },\n headers: {\n \"Content-Type\": \"application/json\",\n },\n },\n view: {\n status: 400,\n },\n };\n }\n}\n",
10
9
  "/**\n * The validation rule table: a rule name in, a predicate out.\n *\n * ITS OWN MODULE SO THE TEST DOES NOT NEED A HOOK. This lived in\n * `HttpRequest.ts` and was reached from `validate.test.ts` through\n * `export const __validateForTests = validate`, which is a name that exists\n * only because the thing it aliases was in the wrong file. Two costs, and the\n * second is the one that bites:\n *\n * - `tsc` emits a declaration per source file, so `dist/http/HttpRequest.d.ts`\n * shipped `__validateForTests` to every installed copy of the framework. The\n * JS build bundles, so there is no `dist/http/HttpRequest.js` behind it —\n * the declaration announced an export the tarball could not produce.\n * - A test-only alias is a second name for the same function, so the test\n * reads as if it were poking at something private. It is not: this is the\n * code path every request body goes through. Importing `validate` says so.\n *\n * Nothing outside `HttpRequest` should build predicates by hand — rules are\n * named in a route's schema — but \"internal\" is what an unexported name in an\n * unexported module already means, and it does not need a warning label.\n */\n\n// Formats B KB MB GB TB\n// e.g parseFileSizeString(\"1MB\") => 1024 * 1024\nfunction parseFileSizeString(size: string) {\n const [number, unit] = size.match(/\\d+|\\D+/g) ?? [];\n if (!number || !unit) {\n return 0;\n }\n const fileSize = Number.parseInt(number);\n switch (unit) {\n case \"B\":\n return fileSize;\n case \"KB\":\n return fileSize * 1024;\n case \"MB\":\n return fileSize * 1024 * 1024;\n case \"GB\":\n return fileSize * 1024 * 1024 * 1024;\n case \"TB\":\n return fileSize * 1024 * 1024 * 1024 * 1024;\n default:\n return 0;\n }\n}\n\n// Formats png, jpg, ttf, excel, csv, word, pdf, json\n// Eg. png => image/png\nfunction parseFileTypeString(type: string) {\n switch (type) {\n case \"image\":\n return \"image\";\n case \"png\":\n return \"image/png\";\n case \"jpg\":\n return \"image/jpeg\";\n case \"jpeg\":\n return \"image/jpeg\";\n case \"ttf\":\n return \"font/ttf\";\n case \"excel\":\n return \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\";\n case \"csv\":\n return \"text/csv\";\n case \"word\":\n return \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\";\n case \"pdf\":\n return \"application/pdf\";\n case \"json\":\n return \"application/json\";\n default:\n return type;\n }\n}\n\n/** The length of the things that have one — `undefined` for everything else,\n * rather than the `undefined` that arithmetic silently turns into `false`. */\nfunction lengthOf(value: any): number | undefined {\n if (typeof value === \"string\" || Array.isArray(value)) return value.length;\n return undefined;\n}\n\nfunction isNumber(value: any): value is number {\n return typeof value === \"number\" && !Number.isNaN(value);\n}\n\n/** Every rule `validate` implements. `SchemaKey` in `HttpRequest.ts` offers\n * these and only these: `validate.test-d.ts` checks the two lists agree, and\n * `validate.test.ts` that each one has a case. */\nexport const RULES = [\n \"required\",\n \"string\",\n \"boolean\",\n \"number\",\n \"email\",\n \"password\",\n \"min\",\n \"max\",\n \"gte\",\n \"lte\",\n \"file\",\n \"fileType\",\n \"fileSize\",\n] as const;\n\n/**\n * A schema names a rule `validate` does not have, or gives one a parameter it\n * cannot use. Thrown when the request is validated, not when the body is bad:\n * it is a bug in the schema, so it is a 500 and not a 400.\n */\nexport class InvalidValidationRuleError extends Error {\n name = \"InvalidValidationRuleError\";\n}\n\n/** `min:3` → 3. A parameter that is not a number throws, instead of becoming\n * `NaN` and quietly failing every value. */\nfunction numericParam(rule: string, param: string | undefined): number {\n const n = param === undefined || param.trim() === \"\" ? Number.NaN : Number(param);\n if (Number.isNaN(n)) {\n throw new InvalidValidationRuleError(\n `Validation rule \"${rule}:${param ?? \"\"}\" needs a number, e.g. \"${rule}:3\"`,\n );\n }\n return n;\n}\n\nexport function validate(ruleName: string) {\n const [rule, param] = ruleName.split(\":\");\n switch (rule) {\n /**\n * Present. Not \"non-empty for the two types that happen to have `.length`\".\n *\n * This used to end in `value?.length > 0`, which is `undefined > 0` — so\n * `false` — for every value that is not a string, an array or a Blob. A\n * number failed it. A boolean failed it. A plain object failed it, which on\n * a typed `HttpRequest<{ theme: { … } }>` is the ordinary case, and the app\n * saw a 400 on a request that was correct.\n *\n * `0` and `false` PASS. They are values someone sent, and a rule called\n * `required` asks whether the field is there, not whether it is truthy —\n * conflating those is how a checkbox set to \"no\" and a quantity of zero get\n * rejected as missing. Emptiness is still emptiness where the concept\n * applies: `\"\"` and `[]` fail, as they did before, and so does a zero-byte\n * upload.\n *\n * `{}` passes. It is an object that was sent; whether its contents are\n * adequate is a question for the rules on its fields, not for this one.\n */\n case \"required\":\n return (value: any) => {\n if (value instanceof Blob) {\n return value.size > 0;\n }\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === \"string\" || Array.isArray(value)) {\n return value.length > 0;\n }\n return true;\n };\n /**\n * The JSON types, checked with `typeof` like `number`. No coercion: `\"true\"`\n * is not a boolean and `42` is not a string. A form-encoded or multipart\n * body only ever carries strings (and files), so `boolean` and `number` are\n * rules for JSON bodies.\n */\n case \"string\":\n return (value: any) => typeof value === \"string\";\n case \"boolean\":\n return (value: any) => typeof value === \"boolean\";\n case \"number\":\n return (value: any) => isNumber(value);\n /**\n * `RegExp.prototype.test` stringifies its argument, so without the `typeof`\n * check `[\"a@b.co\"]` passed `email` and an array holding a strong password\n * passed `password`.\n */\n case \"password\":\n return (value: any) => {\n // min 8 characters\n // at least one uppercase letter,\n // at least one lowercase letter and one number\n // at least one special character\n const passwordRegex = /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;\n return typeof value === \"string\" && passwordRegex.test(value);\n };\n /**\n * Length, and only length. `min:3` is \"at least three characters\", never\n * \"at least three\".\n *\n * ONE NAME, ONE COMPARISON, deliberately. The tempting fix was to overload\n * these by runtime type — length for a string, magnitude for a number — and\n * that is the shape `required` was already in: a rule whose meaning depends\n * on what it is handed, which reads fine until the value's type is not the\n * one the author pictured. `gte` / `lte` below say which comparison they\n * make in their names, so nothing has to be inferred.\n *\n * Written out rather than left as `value?.length >= n` so that a number\n * fails here for a stated reason instead of by arithmetic on `undefined`.\n */\n case \"min\": {\n const min = numericParam(rule, param);\n return (value: any) => {\n const length = lengthOf(value);\n return length !== undefined && length >= min;\n };\n }\n case \"max\": {\n const max = numericParam(rule, param);\n return (value: any) => {\n const length = lengthOf(value);\n return length !== undefined && length <= max;\n };\n }\n /** Magnitude, for numbers. The counterpart `min` / `max` deliberately are not. */\n case \"gte\": {\n const bound = numericParam(rule, param);\n return (value: any) => isNumber(value) && value >= bound;\n }\n case \"lte\": {\n const bound = numericParam(rule, param);\n return (value: any) => isNumber(value) && value <= bound;\n }\n case \"email\":\n return (value: any) => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return typeof value === \"string\" && emailRegex.test(value);\n };\n case \"file\":\n return (value: any) => {\n return value instanceof Blob;\n };\n case \"fileType\": {\n if (!param) {\n throw new InvalidValidationRuleError(\n `Validation rule \"fileType\" needs a type, e.g. \"fileType:png\" or \"fileType:image\"`,\n );\n }\n const parsedType = parseFileTypeString(param);\n return (value: any) => value instanceof Blob && value.type.startsWith(parsedType);\n }\n case \"fileSize\": {\n // `parseFileSizeString` answers 0 for anything it cannot read, and a\n // 0-byte ceiling rejects every upload — so `fileSize:5mb` or\n // `fileSize:1.5MB` looked like a limit and was a wall.\n const absoluteSize = parseFileSizeString(param ?? \"\");\n if (absoluteSize === 0 && !/^0+(B|KB|MB|GB|TB)$/.test(param ?? \"\")) {\n throw new InvalidValidationRuleError(\n `Validation rule \"fileSize:${param ?? \"\"}\" needs a whole size in B, KB, MB, GB or TB, e.g. \"fileSize:5MB\"`,\n );\n }\n return (value: any) => value instanceof Blob && value.size <= absoluteSize;\n }\n /**\n * Not `() => true`. That default is how `string` and `boolean` shipped in\n * `SchemaKey` checking nothing (#609): a rule the table does not\n * know looks, from the schema, exactly like one it does. A typo'd or\n * unimplemented rule is a bug in the schema, so it throws.\n */\n default:\n throw new InvalidValidationRuleError(\n `Unknown validation rule \"${ruleName}\". Known rules: ${RULES.join(\", \")}`,\n );\n }\n}\n",
10
+ "/**\n * The media type of a `Content-Type` header: lowercased, with its parameters\n * (`; charset=utf-8`, `; boundary=…`) cut off. `null` when there is no header\n * or nothing before the first `;`.\n *\n * Media types compare case-insensitively (RFC 9110 §8.3.1), so\n * `Application/JSON; charset=UTF-8` is `application/json`.\n */\nexport function mediaType(header: string | null | undefined): string | null {\n if (typeof header !== \"string\") return null;\n const [type] = header.split(\";\", 1);\n const normalized = type.trim().toLowerCase();\n return normalized === \"\" ? null : normalized;\n}\n\n/**\n * `application/json`, or a structured `+json` type such as\n * `application/vnd.api+json` or `application/merge-patch+json` (RFC 6839).\n * Not a prefix match: `application/json-seq` is not JSON.\n */\nexport function isJsonMediaType(type: string | null): boolean {\n if (type === null) return false;\n if (type === \"application/json\") return true;\n const slash = type.indexOf(\"/\");\n return slash > 0 && type.endsWith(\"+json\") && type.length > slash + 1 + \"+json\".length;\n}\n",
11
11
  "/**\n * The requests the api dispatcher built itself, on a model's behalf, rather\n * than received from a client.\n *\n * Keyed on the `Request` object, not carried in it. A header was the obvious\n * alternative and it is forgeable by construction: anything the synthetic\n * request can carry, a real client can send. Only a module holding this set can\n * add to it, and it is deliberately not re-exported from `http/index.ts`, so no\n * inbound request can put itself here. The only writer is\n * `ApiRouteDispatcher.dispatchAs`, and it marks only the requests it built.\n * App code can call `dispatchAs` — it is trusted — but cannot mark a request of\n * its own.\n *\n * The object, rather than a flag on the request context, because the two\n * places an app asks the question sit on either side of `RequestContext.run`:\n * `onRequestStart` fires before the dispatcher opens the request's store, and a\n * handler's `new SomeRequest()` builds a second `HttpRequest` from inside it.\n * Both wrap the same raw `Request`, so both get the same answer, and nothing has\n * to remember to copy a field from one to the other.\n *\n * A `WeakMap`, so a dispatched request is forgotten with the request. The\n * value is the initiator's client address; see `dispatchedClientAddress`.\n */\nconst dispatched = new WeakMap<Request, { clientAddress: string }>();\n\n/**\n * `clientAddress` is required so the one writer cannot mark a request without\n * saying whose rate-limit budget it spends.\n */\nexport function markModelOriginated(req: Request, clientAddress: string) {\n dispatched.set(req, { clientAddress });\n}\n\nexport function isModelOriginated(req: Request): boolean {\n return dispatched.has(req);\n}\n\n/**\n * The client address `clientIp` resolved from the initiator, for a request the\n * dispatcher built; `undefined` for any other.\n *\n * It rides here for the same reason the marker does. The synthetic request\n * carries credentials only, so it has no `x-forwarded-for`, and\n * `RateLimitMiddleware` would key every tool call from every user on\n * `unknown:<route>`: one budget, which one user's agent loop can spend for\n * everyone. Copying the initiator's `x-forwarded-for` instead would move a\n * client-written header onto a request the server built. Carrying the value\n * `clientIp` already derived from the initiator gives a tool call exactly the\n * address the user's own direct request gets, and nothing more.\n */\nexport function dispatchedClientAddress(req: Request): string | undefined {\n return dispatched.get(req)?.clientAddress;\n}\n",
12
12
  "// Type-only: `services/router` imports from `http`, so a runtime import here\n// would be circular.\nimport type { ResolvedDomain } from \"../services/router/DomainResolver\";\n\n// Keyed by the raw Request, so the domain `App.fetch` resolved reaches the\n// dispatcher, and every `HttpRequest` built over that Request, without a\n// second AsyncLocalStorage that a streaming render would step outside of.\nconst domains = new WeakMap<Request, ResolvedDomain>();\n\nexport function setRequestDomain(req: Request, domain: ResolvedDomain) {\n domains.set(req, domain);\n}\n\n/** The host group `req` was routed by, or `null` when `route.domains` is not configured. */\nexport function requestDomain(req: Request): ResolvedDomain | null {\n return domains.get(req) ?? null;\n}\n\n// Headers meant for this app alone — `route.domains.trustProxy.secret` — that\n// a `proxy()` route must not forward upstream with the rest of the client's.\nconst withheld = new WeakMap<Request, string[]>();\n\nexport function withholdFromUpstream(req: Request, header: string) {\n const headers = withheld.get(req) ?? [];\n if (!headers.includes(header)) {\n withheld.set(req, [...headers, header]);\n }\n}\n\n/** The lowercased header names a `proxy()` route drops from `req` before forwarding it. */\nexport function withheldFromUpstream(req: Request): readonly string[] {\n return withheld.get(req) ?? [];\n}\n",
13
- "import { parseCookieHeader } from \"./getCookies\";\nimport { isModelOriginated } from \"./modelOriginated\";\nimport { parseRangeHeader } from \"./range\";\nimport { RequestContext } from \"./requestContext\";\nimport { requestDomain } from \"./requestDomain\";\nimport { ValidationError } from \"./Router\";\nimport { InvalidValidationRuleError, validate } from \"./validate\";\nimport type { ResolvedDomain } from \"../services/router/DomainResolver\";\n\nclass Input<T> {\n constructor(private data: T) {}\n\n public get<K extends keyof T>(key: K): T[K] {\n return this.data[key];\n }\n\n public has(key: keyof T) {\n return this.data[key] !== undefined;\n }\n\n public toJSON(): T {\n return this.data;\n }\n}\n\ntype StringType = \"string\";\ntype NumberType = \"number\";\ntype BooleanType = \"boolean\";\ntype MinLengthType = `min:${number}`;\ntype MaxLengthType = `max:${number}`;\n/** Magnitude, for numbers — see `validate`'s `min` case for why these are not\n * the same rule wearing different names. */\ntype GreaterOrEqualType = `gte:${number}`;\ntype LessOrEqualType = `lte:${number}`;\ntype RequiredType = \"required\";\ntype FileType = \"file\";\n// Backticks, not quotes. These two were written with double quotes, which makes\n// them the *literal text* `fileType:${string}` rather than a template literal\n// type — so `fileType:image/png`, the only way anyone would ever write the rule,\n// did not typecheck, while the runtime handled it perfectly well.\ntype FileTypeType = `fileType:${string}`;\ntype FileSizeType = `fileSize:${string}`;\ntype EmailType = \"email\";\ntype PasswordType = \"password\";\n/** One entry per rule in `validate`'s `RULES`; `validate.test-d.ts` holds them\n * to each other, so an offered rule cannot go unimplemented again (#609). */\nexport type SchemaKey =\n | StringType\n | NumberType\n | BooleanType\n | MinLengthType\n | MaxLengthType\n | GreaterOrEqualType\n | LessOrEqualType\n | RequiredType\n | FileType\n | FileTypeType\n | FileSizeType\n | EmailType\n | PasswordType;\n\nexport type Schema<T extends Body> = Record<keyof T, Partial<Record<SchemaKey, string>>>;\n\nexport type Body = Record<string, any>;\nexport type HttpRequestKind = \"view\" | \"api\";\n\nexport class HttpRequest<T extends Body = Record<string, never>, Params = Record<string, never>> {\n kind: HttpRequestKind;\n rawRequest: Request;\n headers: Omit<Headers, \"set\" | \"delete\">;\n cookies: Omit<Map<string, string>, \"set\" | \"delete\">;\n search: Input<any>;\n schema: any = {};\n routePath: string;\n params: Params;\n /**\n * The `route.domains` group this request was routed by — `domain.params`\n * holds a `:param` subdomain's value, or what `custom.resolve` returned for\n * a custom domain. `null` when the app declares no `route.domains`.\n *\n * Kept apart from `params`, which are the path's alone.\n */\n domain: ResolvedDomain | null;\n\n constructor(req?: Request, params?: any, kind?: HttpRequestKind, routePath?: string) {\n if (!req) {\n const _req = RequestContext.getStore().req;\n this.params = _req.params as any;\n this.rawRequest = _req.rawRequest;\n this.kind = _req.kind;\n this.routePath = _req.routePath;\n this.domain = _req.domain ?? null;\n } else {\n this.params = params;\n this.rawRequest = req;\n this.routePath = routePath;\n this.kind = kind ?? \"api\";\n this.domain = requestDomain(req);\n }\n\n this.headers = this.rawRequest.headers;\n\n const cookies = parseCookieHeader(this.rawRequest.headers.get(\"Cookie\"));\n const url = new URL(this.rawRequest.url);\n const map = new Map<string, string | string[]>();\n for (const [key, value] of url.searchParams) {\n if (map.has(key)) {\n const currentValue = map.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n map.set(key, currentValue);\n } else {\n map.set(key, [currentValue, value]);\n }\n } else {\n map.set(key, value);\n }\n }\n const _params = Object.fromEntries(map.entries());\n this.search = new Input(_params);\n this.cookies = cookies;\n }\n\n locale() {\n return RequestContext.getStore().locale;\n }\n\n ctx() {\n return RequestContext.getStore();\n }\n\n /**\n * Whether the framework dispatched this request in-process for a model — a\n * tool call — rather than a client sending it. Readable in `onRequestStart`,\n * in middleware and in the handler alike.\n *\n * No header or cookie can make this true; see `http/modelOriginated.ts`.\n */\n isModelOriginated(): boolean {\n return isModelOriginated(this.rawRequest);\n }\n\n /**\n * The parsed `Range` header, or `null` when absent or unusable. Pass it to\n * `FileStorage.read(name, { range })` to range explicitly; inside a\n * `this.stream()` route `read()` already picks it up on its own.\n */\n range() {\n return parseRangeHeader(this.rawRequest.headers.get(\"Range\"));\n }\n\n refine(_input: any): any {\n return {};\n }\n\n private async parseBody() {\n let inputMap = new Input<T>({} as T);\n if (this.rawRequest.headers.get(\"Content-Type\") === \"application/json\") {\n const body = await this.rawRequest.json();\n inputMap = new Input<T>(body as T);\n }\n if (this.rawRequest.headers.get(\"Content-Type\") === \"application/x-www-form-urlencoded\") {\n const body = (await this.rawRequest.formData()) as any; // TODO: fix type\n inputMap = new Input<T>(body as T);\n }\n\n if (this.rawRequest.headers.get(\"Content-Type\")?.startsWith(\"multipart/form-data\")) {\n const body = (await this.rawRequest.formData()) as any; // TODO: fix type\n const _inputMap = new Map<string, any>();\n for (const [key, value] of body.entries()) {\n if (_inputMap.has(key)) {\n const currentValue = _inputMap.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n _inputMap.set(key, currentValue);\n } else {\n _inputMap.set(key, [currentValue, value] as any);\n }\n } else {\n _inputMap.set(key, value as T[keyof T]);\n }\n }\n inputMap = new Input<T>(Object.fromEntries(_inputMap.entries()) as T);\n }\n return inputMap;\n }\n\n private validateInput(input: Input<T>) {\n const errors: Record<string, string[]> = {};\n const fields = Object.entries(this.schema as Record<string, Record<string, unknown>>).map(\n ([key, rules]) => ({\n key,\n // Every rule is looked up before any value is checked, so a schema that\n // names an unknown rule throws on every request, whatever the body —\n // not only on the ones whose earlier rules happened to pass. A function\n // is its own validator: its key is a label, and is not looked up.\n rules: Object.entries(rules).map(([rule, message]) => ({\n rule,\n message,\n check: typeof message === \"function\" ? null : this.ruleFor(key, rule),\n })),\n }),\n );\n\n for (const { key, rules } of fields) {\n const value = input.get(key as keyof T);\n const isRequired = rules.some(({ rule }) => rule === \"required\");\n // Absent: skipped unless `required`. `0` and `false` are values, and are\n // checked like any other — skipping every falsy value let `0` and `false` through a\n // `string` rule and `0` through a `boolean` one.\n const isAbsent = value === undefined || value === null || (value as unknown) === \"\";\n const messages: string[] = [];\n\n for (const { rule, message, check } of rules) {\n let _message = message;\n let _isValid = false;\n if (typeof message === \"function\") {\n _message = message(value);\n _isValid = typeof _message === \"undefined\";\n } else {\n _isValid = check!(value);\n }\n\n if (_isValid) {\n continue;\n }\n\n if (isAbsent && !isRequired) {\n continue;\n }\n\n if (rule === \"required\") {\n // A missing field reports that it is missing, and only that — not\n // also that `undefined` is not a string. Wherever `required` sits\n // among the field's rules.\n messages.splice(0, messages.length, String(_message));\n break;\n }\n\n // Two rules can share a message (`string` and `email` both saying\n // \"Invalid email\"); the field reports it once (#675).\n if (!messages.includes(String(_message))) {\n messages.push(String(_message));\n }\n }\n\n if (messages.length > 0) {\n errors[key] = messages;\n }\n }\n\n for (const [key, value] of Object.entries(this.refine(input.toJSON()) ?? {})) {\n const messages = errors[key] ?? [];\n // A `refine` message the rules already reported is not repeated (#675).\n errors[key] = messages.includes(value as string) ? messages : [...messages, value as string];\n }\n\n if (Object.keys(errors).length > 0) {\n throw new ValidationError(errors);\n }\n\n return input;\n }\n\n private ruleFor(key: string, rule: string) {\n try {\n return validate(rule);\n } catch (err) {\n if (err instanceof InvalidValidationRuleError) {\n throw new InvalidValidationRuleError(\n `${this.constructor.name}.schema.${key}: ${err.message}`,\n );\n }\n throw err;\n }\n }\n\n async input(): Promise<Input<T>> {\n return this.validateInput(await this.parseBody());\n }\n\n async safeInput(): Promise<{\n isValid: boolean;\n errors: Record<string, string[]>;\n input: Input<T>;\n }> {\n const input = await this.parseBody();\n try {\n this.validateInput(input);\n return {\n isValid: true,\n errors: {},\n input,\n };\n } catch (err) {\n if (!(err instanceof ValidationError)) {\n throw err;\n }\n return {\n isValid: false,\n errors: err.errors,\n input,\n };\n }\n }\n}\n",
14
- "import { RequestBreakerError } from \"./Error\";\nimport { formatUnsatisfiedContentRange } from \"./range\";\n\nexport class AuthorizationError extends RequestBreakerError {\n private error: string;\n constructor(error: string = \"Not authorized\") {\n super(error);\n this.name = \"AuthorizationError\";\n this.error = error;\n this.payload = {\n api: {\n status: 401,\n data: { error: this.error },\n },\n view: {},\n };\n }\n}\n\n/**\n * A signed-in user who is not allowed to do this. Thrown by `Auth.guard()`.\n *\n * 403, not 401: a 401 tells the client to re-authenticate, so a client that\n * sends a 401 to the sign-in page would loop a signed-in user without the role\n * straight back to where they started. A request with no user at all is\n * `AuthenticationError`, which stays 401.\n */\nexport class InsufficientPermissionsError extends RequestBreakerError {\n /**\n * The status of `payload.api`, which answers API routes and `.json` view\n * navigations alike. Before 0.63 it was 401, and a shipped native client may\n * still branch on that — it cannot be rolled forward in the same deploy as\n * the server. Such an app sets this back to 401 once at boot, and removes the\n * line when its clients handle 403:\n *\n * ```ts\n * InsufficientPermissionsError.apiStatus = 401;\n * ```\n *\n * A full page load answers 403 either way; before 0.63 it fell through to\n * the view dispatcher's 400 default, which no client could have relied on.\n */\n static apiStatus: 401 | 403 = 403;\n\n private error: string;\n constructor(error: string = \"Insufficient permissions\") {\n super(error);\n this.name = \"InsufficientPermissionsError\";\n this.error = error;\n this.payload = {\n api: {\n status: InsufficientPermissionsError.apiStatus,\n data: { error: this.error },\n },\n // Without a status a view request would fall through to the\n // dispatcher's 400 default.\n view: { status: 403 },\n };\n }\n}\n\n/**\n * A `Range` that cannot be satisfied against the object's current size.\n *\n * Extends `RequestBreakerError` so a bare `FileStorage.read()` inside an\n * ordinary route still produces a correct 416 — and, importantly, so it does\n * not trip `onRequestFail`. A 416 is the client's header being wrong about the\n * object, not a server failure.\n */\nexport class RangeNotSatisfiableError extends RequestBreakerError {\n constructor(public total: number) {\n super(\"Range not satisfiable\");\n this.name = \"RangeNotSatisfiableError\";\n this.payload = {\n api: {\n status: 416,\n data: { error: { message: \"Range not satisfiable\" } },\n headers: {\n \"Content-Range\": formatUnsatisfiedContentRange(total),\n \"Accept-Ranges\": \"bytes\",\n // Decided by the client's own Range against the object's current\n // length, so it must never be replayed from a cache to a request\n // that did not ask for that window.\n \"Cache-Control\": \"no-store\",\n },\n },\n view: {},\n };\n }\n}\n\nexport class FileNotFoundError extends RequestBreakerError {\n constructor(public fileName: string) {\n super(\"File not found\");\n this.name = \"FileNotFoundError\";\n this.payload = {\n api: {\n status: 404,\n data: { error: { message: \"Not found\" } },\n headers: { \"Cache-Control\": \"no-store\" },\n },\n view: {},\n };\n }\n}\n\n/**\n * No signed-in user. A 401 to an API client; a view request is sent to\n * `redirectTo` instead — a 302 for a page load, and a `Redirect` directive for\n * a `.json` navigation, so the client router follows it rather than leaving\n * the previous page on screen.\n *\n * `redirectTo` is the whole location, intended-URL parameter included.\n * `AuthenticationMiddleware` and `Auth.user()` build it from the request and\n * the `auth.signInPath` config; code throwing this by hand can pass its own.\n */\nexport class AuthenticationError extends RequestBreakerError {\n constructor(options: { redirectTo?: string } = {}) {\n super(\"Authentication error\");\n this.name = \"AuthenticationError\";\n const location = options.redirectTo ?? \"/auth/sign-in\";\n this.payload = {\n api: {\n status: 401,\n data: { error: \"Authentication error\" },\n },\n viewData: {\n status: 200,\n data: {},\n // A refusal is per-visitor, and this one answers 200 so that\n // `loadRoutePayload` reads it at all — which makes it exactly the\n // shape a shared cache would happily store and replay to the next\n // visitor. The `view` payload below says the same thing.\n headers: {\n \"Cache-Control\": \"private, no-cache, no-store, max-age=0, must-revalidate\",\n },\n directive: { kind: \"Redirect\", path: location },\n },\n view: {\n status: 302,\n headers: {\n \"Cache-Control\":\n \"private, no-cache, no-store, max-age=0, must-revalidate\",\n Location: location,\n },\n },\n };\n }\n}\n",
13
+ "import { RequestBreakerError } from \"./Error\";\nimport { parseCookieHeader } from \"./getCookies\";\nimport { isJsonMediaType, mediaType } from \"./mediaType\";\nimport { isModelOriginated } from \"./modelOriginated\";\nimport { parseRangeHeader } from \"./range\";\nimport { RequestContext } from \"./requestContext\";\nimport { requestDomain } from \"./requestDomain\";\nimport { ValidationError } from \"./Router\";\nimport { InvalidValidationRuleError, validate } from \"./validate\";\nimport type { ResolvedDomain } from \"../services/router/DomainResolver\";\n\nclass Input<T> {\n constructor(private data: T) {}\n\n public get<K extends keyof T>(key: K): T[K] {\n return this.data[key];\n }\n\n public has(key: keyof T) {\n return this.data[key] !== undefined;\n }\n\n public toJSON(): T {\n return this.data;\n }\n}\n\ntype StringType = \"string\";\ntype NumberType = \"number\";\ntype BooleanType = \"boolean\";\ntype MinLengthType = `min:${number}`;\ntype MaxLengthType = `max:${number}`;\n/** Magnitude, for numbers — see `validate`'s `min` case for why these are not\n * the same rule wearing different names. */\ntype GreaterOrEqualType = `gte:${number}`;\ntype LessOrEqualType = `lte:${number}`;\ntype RequiredType = \"required\";\ntype FileType = \"file\";\n// Backticks, not quotes. These two were written with double quotes, which makes\n// them the *literal text* `fileType:${string}` rather than a template literal\n// type — so `fileType:image/png`, the only way anyone would ever write the rule,\n// did not typecheck, while the runtime handled it perfectly well.\ntype FileTypeType = `fileType:${string}`;\ntype FileSizeType = `fileSize:${string}`;\ntype EmailType = \"email\";\ntype PasswordType = \"password\";\n/** One entry per rule in `validate`'s `RULES`; `validate.test-d.ts` holds them\n * to each other, so an offered rule cannot go unimplemented again (#609). */\nexport type SchemaKey =\n | StringType\n | NumberType\n | BooleanType\n | MinLengthType\n | MaxLengthType\n | GreaterOrEqualType\n | LessOrEqualType\n | RequiredType\n | FileType\n | FileTypeType\n | FileSizeType\n | EmailType\n | PasswordType;\n\nexport type Schema<T extends Body> = Record<keyof T, Partial<Record<SchemaKey, string>>>;\n\nexport type Body = Record<string, any>;\nexport type HttpRequestKind = \"view\" | \"api\";\n\nexport class HttpRequest<T extends Body = Record<string, never>, Params = Record<string, never>> {\n kind: HttpRequestKind;\n rawRequest: Request;\n headers: Omit<Headers, \"set\" | \"delete\">;\n cookies: Omit<Map<string, string>, \"set\" | \"delete\">;\n search: Input<any>;\n schema: any = {};\n routePath: string;\n params: Params;\n /**\n * The `route.domains` group this request was routed by — `domain.params`\n * holds a `:param` subdomain's value, or what `custom.resolve` returned for\n * a custom domain. `null` when the app declares no `route.domains`.\n *\n * Kept apart from `params`, which are the path's alone.\n */\n domain: ResolvedDomain | null;\n\n constructor(req?: Request, params?: any, kind?: HttpRequestKind, routePath?: string) {\n if (!req) {\n const _req = RequestContext.getStore().req;\n this.params = _req.params as any;\n this.rawRequest = _req.rawRequest;\n this.kind = _req.kind;\n this.routePath = _req.routePath;\n this.domain = _req.domain ?? null;\n } else {\n this.params = params;\n this.rawRequest = req;\n this.routePath = routePath;\n this.kind = kind ?? \"api\";\n this.domain = requestDomain(req);\n }\n\n this.headers = this.rawRequest.headers;\n\n const cookies = parseCookieHeader(this.rawRequest.headers.get(\"Cookie\"));\n const url = new URL(this.rawRequest.url);\n const map = new Map<string, string | string[]>();\n for (const [key, value] of url.searchParams) {\n if (map.has(key)) {\n const currentValue = map.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n map.set(key, currentValue);\n } else {\n map.set(key, [currentValue, value]);\n }\n } else {\n map.set(key, value);\n }\n }\n const _params = Object.fromEntries(map.entries());\n this.search = new Input(_params);\n this.cookies = cookies;\n }\n\n locale() {\n return RequestContext.getStore().locale;\n }\n\n ctx() {\n return RequestContext.getStore();\n }\n\n /**\n * Whether the framework dispatched this request in-process for a model — a\n * tool call — rather than a client sending it. Readable in `onRequestStart`,\n * in middleware and in the handler alike.\n *\n * No header or cookie can make this true; see `http/modelOriginated.ts`.\n */\n isModelOriginated(): boolean {\n return isModelOriginated(this.rawRequest);\n }\n\n /**\n * Aborts when the client goes away before the response is sent: the\n * browser closed the connection, or `useQuery` gave up on a request nobody\n * renders any more (#659). Hand it to slow work — a model call, an upstream\n * `fetch` — so it stops instead of running to completion for no one:\n *\n * ```ts\n * const reply = await fetch(upstream, { signal: req.signal });\n * if (req.signal.aborted) return null;\n * ```\n *\n * During a server render, an in-process query shares the page request's\n * signal.\n */\n get signal(): AbortSignal {\n return this.rawRequest.signal;\n }\n\n /**\n * The parsed `Range` header, or `null` when absent or unusable. Pass it to\n * `FileStorage.read(name, { range })` to range explicitly; inside a\n * `this.stream()` route `read()` already picks it up on its own.\n */\n range() {\n return parseRangeHeader(this.rawRequest.headers.get(\"Range\"));\n }\n\n refine(_input: any): any {\n return {};\n }\n\n /**\n * The body, by its media type: JSON (`application/json` or any `+json`\n * type), a urlencoded form, or a multipart form. The type is read without\n * its parameters and case-insensitively, so `application/json;\n * charset=utf-8` is JSON (#699). Any other type, or none, reads as `{}`.\n *\n * An empty JSON body is no body, and reads as `{}` like a request without\n * one. A body that is not JSON, or is JSON but not an object, is the\n * client's mistake: a 400 refusal (`form_error`), never a 500 (#700).\n */\n private async parseBody() {\n const type = mediaType(this.rawRequest.headers.get(\"Content-Type\"));\n\n if (isJsonMediaType(type)) {\n return new Input<T>((await this.parseJsonBody()) as T);\n }\n\n if (type === \"application/x-www-form-urlencoded\" || type === \"multipart/form-data\") {\n let body: FormData;\n try {\n body = await this.rawRequest.formData();\n } catch {\n throw new RequestBreakerError(\"The request body could not be read as a form.\");\n }\n const _inputMap = new Map<string, any>();\n for (const [key, value] of body.entries()) {\n if (_inputMap.has(key)) {\n const currentValue = _inputMap.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n } else {\n _inputMap.set(key, [currentValue, value]);\n }\n } else {\n _inputMap.set(key, value);\n }\n }\n return new Input<T>(Object.fromEntries(_inputMap.entries()) as T);\n }\n\n return new Input<T>({} as T);\n }\n\n private async parseJsonBody(): Promise<Body> {\n if (!this.rawRequest.body) {\n return {};\n }\n let text: string;\n try {\n text = await this.rawRequest.text();\n } catch {\n throw new RequestBreakerError(\"The request body could not be read.\");\n }\n if (text.trim() === \"\") {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new RequestBreakerError(\"The request body is not valid JSON.\");\n }\n // `null`, a number, a string: nothing a field could be read from. An\n // array is left alone, as it was before.\n if (parsed === null || typeof parsed !== \"object\") {\n throw new RequestBreakerError(\"The request body must be a JSON object.\");\n }\n return parsed as Body;\n }\n\n private validateInput(input: Input<T>) {\n const errors: Record<string, string[]> = {};\n const fields = Object.entries(this.schema as Record<string, Record<string, unknown>>).map(\n ([key, rules]) => ({\n key,\n // Every rule is looked up before any value is checked, so a schema that\n // names an unknown rule throws on every request, whatever the body —\n // not only on the ones whose earlier rules happened to pass. A function\n // is its own validator: its key is a label, and is not looked up.\n rules: Object.entries(rules).map(([rule, message]) => ({\n rule,\n message,\n check: typeof message === \"function\" ? null : this.ruleFor(key, rule),\n })),\n }),\n );\n\n for (const { key, rules } of fields) {\n const value = input.get(key as keyof T);\n const isRequired = rules.some(({ rule }) => rule === \"required\");\n // Absent: skipped unless `required`. `0` and `false` are values, and are\n // checked like any other — skipping every falsy value let `0` and `false` through a\n // `string` rule and `0` through a `boolean` one.\n const isAbsent = value === undefined || value === null || (value as unknown) === \"\";\n const messages: string[] = [];\n\n for (const { rule, message, check } of rules) {\n let _message = message;\n let _isValid = false;\n if (typeof message === \"function\") {\n _message = message(value);\n _isValid = typeof _message === \"undefined\";\n } else {\n _isValid = check!(value);\n }\n\n if (_isValid) {\n continue;\n }\n\n if (isAbsent && !isRequired) {\n continue;\n }\n\n if (rule === \"required\") {\n // A missing field reports that it is missing, and only that — not\n // also that `undefined` is not a string. Wherever `required` sits\n // among the field's rules.\n messages.splice(0, messages.length, String(_message));\n break;\n }\n\n // Two rules can share a message (`string` and `email` both saying\n // \"Invalid email\"); the field reports it once (#675).\n if (!messages.includes(String(_message))) {\n messages.push(String(_message));\n }\n }\n\n if (messages.length > 0) {\n errors[key] = messages;\n }\n }\n\n for (const [key, value] of Object.entries(this.refine(input.toJSON()) ?? {})) {\n const messages = errors[key] ?? [];\n // A `refine` message the rules already reported is not repeated (#675).\n errors[key] = messages.includes(value as string) ? messages : [...messages, value as string];\n }\n\n if (Object.keys(errors).length > 0) {\n throw new ValidationError(errors);\n }\n\n return input;\n }\n\n private ruleFor(key: string, rule: string) {\n try {\n return validate(rule);\n } catch (err) {\n if (err instanceof InvalidValidationRuleError) {\n throw new InvalidValidationRuleError(\n `${this.constructor.name}.schema.${key}: ${err.message}`,\n );\n }\n throw err;\n }\n }\n\n async input(): Promise<Input<T>> {\n return this.validateInput(await this.parseBody());\n }\n\n async safeInput(): Promise<{\n isValid: boolean;\n errors: Record<string, string[]>;\n input: Input<T>;\n }> {\n const input = await this.parseBody();\n try {\n this.validateInput(input);\n return {\n isValid: true,\n errors: {},\n input,\n };\n } catch (err) {\n if (!(err instanceof ValidationError)) {\n throw err;\n }\n return {\n isValid: false,\n errors: err.errors,\n input,\n };\n }\n }\n}\n",
14
+ "import { refusal, RequestBreakerError, stringEraRefusal } from \"./Error\";\nimport { formatUnsatisfiedContentRange } from \"./range\";\n\nexport class AuthorizationError extends RequestBreakerError {\n private error: string;\n constructor(error: string = \"Not authorized\") {\n super(error);\n this.name = \"AuthorizationError\";\n this.error = error;\n this.payload = {\n api: {\n status: 401,\n data: { error: stringEraRefusal(\"authorization\", this.error, 401) },\n },\n view: {},\n };\n }\n}\n\n/**\n * A signed-in user who is not allowed to do this. Thrown by `Auth.guard()`.\n *\n * 403, not 401: a 401 tells the client to re-authenticate, so a client that\n * sends a 401 to the sign-in page would loop a signed-in user without the role\n * straight back to where they started. A request with no user at all is\n * `AuthenticationError`, which stays 401.\n */\nexport class InsufficientPermissionsError extends RequestBreakerError {\n /**\n * The status of `payload.api`, which answers API routes and `.json` view\n * navigations alike. Before 0.63 it was 401, and a shipped native client may\n * still branch on that — it cannot be rolled forward in the same deploy as\n * the server. Such an app sets this back to 401 once at boot, and removes the\n * line when its clients handle 403:\n *\n * ```ts\n * InsufficientPermissionsError.apiStatus = 401;\n * ```\n *\n * A full page load answers 403 either way; before 0.63 it fell through to\n * the view dispatcher's 400 default, which no client could have relied on.\n */\n static apiStatus: 401 | 403 = 403;\n\n private error: string;\n constructor(error: string = \"Insufficient permissions\") {\n super(error);\n this.name = \"InsufficientPermissionsError\";\n this.error = error;\n this.payload = {\n api: {\n status: InsufficientPermissionsError.apiStatus,\n data: {\n error: stringEraRefusal(\"permission\", this.error, InsufficientPermissionsError.apiStatus),\n },\n },\n // Without a status a view request would fall through to the\n // dispatcher's 400 default.\n view: { status: 403 },\n };\n }\n}\n\n/**\n * A `Range` that cannot be satisfied against the object's current size.\n *\n * Extends `RequestBreakerError` so a bare `FileStorage.read()` inside an\n * ordinary route still produces a correct 416 — and, importantly, so it does\n * not trip `onRequestFail`. A 416 is the client's header being wrong about the\n * object, not a server failure.\n */\nexport class RangeNotSatisfiableError extends RequestBreakerError {\n constructor(public total: number) {\n super(\"Range not satisfiable\");\n this.name = \"RangeNotSatisfiableError\";\n this.payload = {\n api: {\n status: 416,\n data: { error: refusal(\"range_not_satisfiable\", \"Range not satisfiable\", 416) },\n headers: {\n \"Content-Range\": formatUnsatisfiedContentRange(total),\n \"Accept-Ranges\": \"bytes\",\n // Decided by the client's own Range against the object's current\n // length, so it must never be replayed from a cache to a request\n // that did not ask for that window.\n \"Cache-Control\": \"no-store\",\n },\n },\n view: {},\n };\n }\n}\n\nexport class FileNotFoundError extends RequestBreakerError {\n constructor(public fileName: string) {\n super(\"File not found\");\n this.name = \"FileNotFoundError\";\n this.payload = {\n api: {\n status: 404,\n data: { error: refusal(\"not_found\", \"Not found\", 404) },\n headers: { \"Cache-Control\": \"no-store\" },\n },\n view: {},\n };\n }\n}\n\n/**\n * No signed-in user. A 401 to an API client; a view request is sent to\n * `redirectTo` instead — a 302 for a page load, and a `Redirect` directive for\n * a `.json` navigation, so the client router follows it rather than leaving\n * the previous page on screen.\n *\n * `redirectTo` is the whole location, intended-URL parameter included.\n * `AuthenticationMiddleware` and `Auth.user()` build it from the request and\n * the `auth.signInPath` config; code throwing this by hand can pass its own.\n */\nexport class AuthenticationError extends RequestBreakerError {\n constructor(options: { redirectTo?: string } = {}) {\n super(\"Authentication error\");\n this.name = \"AuthenticationError\";\n const location = options.redirectTo ?? \"/auth/sign-in\";\n this.payload = {\n api: {\n status: 401,\n data: { error: stringEraRefusal(\"authentication\", \"Authentication error\", 401) },\n },\n viewData: {\n status: 200,\n data: {},\n // A refusal is per-visitor, and this one answers 200 so that\n // `loadRoutePayload` reads it at all — which makes it exactly the\n // shape a shared cache would happily store and replay to the next\n // visitor. The `view` payload below says the same thing.\n headers: {\n \"Cache-Control\": \"private, no-cache, no-store, max-age=0, must-revalidate\",\n },\n directive: { kind: \"Redirect\", path: location },\n },\n view: {\n status: 302,\n headers: {\n \"Cache-Control\":\n \"private, no-cache, no-store, max-age=0, must-revalidate\",\n Location: location,\n },\n },\n };\n }\n}\n",
15
15
  "import type { ServiceToken } from \"../container/Container\";\nimport { app } from \"../foundation/app\";\n\n/**\n * Base for the facades that front a container binding. A subclass names the\n * service it proxies with `getFacadeAccessor()` and reaches the live instance\n * through `this.getFacadeRoot()`, so the binding is resolved per call against\n * the Application for the current async context — never captured at module\n * load, which is what makes a facade swappable in tests.\n *\n * Two deliberate divergences from `Illuminate\\Support\\Facades\\Facade`:\n *\n * 1. No `__callStatic`. TypeScript has no typed equivalent, and a Proxy would\n * erase the very signatures that make these facades worth having. Subclasses\n * therefore declare explicit statics that forward to `getFacadeRoot()`.\n *\n * 2. `getFacadeAccessor()` is public, not protected. `getFacadeRoot()` types\n * its `this` structurally in order to infer the service type from the\n * accessor's return, and a protected static is not structurally assignable\n * to that.\n *\n * Facades that resolve nothing from the container — Cookie, Redirect, Url,\n * Meta — do not extend this class.\n */\nexport abstract class Facade {\n static getFacadeAccessor(): ServiceToken<any> {\n throw new Error(\n `Facade [${this.name}] does not implement getFacadeAccessor().`,\n );\n }\n\n static getFacadeRoot<T>(this: {\n getFacadeAccessor(): ServiceToken<T>;\n }): T {\n return app(this.getFacadeAccessor());\n }\n}\n",
16
16
  "import { FileNotFoundError } from \"../../../http/errors\";\nimport type {\n DeleteFileParams,\n FetchFileOptions,\n IFileStorageDriver,\n PutFileOptions,\n PutFileParams,\n ReadFileParams,\n ReadResult,\n} from \"./types\";\n\nexport abstract class FileStorageDriver implements IFileStorageDriver {\n abstract fetch(\n params: ReadFileParams | string,\n options?: FetchFileOptions,\n ): Promise<Response>;\n abstract put(\n params: PutFileParams | Blob,\n options?: PutFileOptions,\n ): Promise<string>;\n abstract list(folder: string): Promise<any>;\n\n /**\n * Removes an object. A missing object is not an error: the promise resolves,\n * so cleanup can run twice, or after a write that never landed.\n *\n * Not abstract, for the same reason `read()` is not: a custom driver written\n * before `delete()` existed keeps compiling. It must not keep *working* as if\n * it deleted, though — silently resolving here is exactly the bug `delete()`\n * used to have (#608) — so the default throws and names the driver.\n */\n async delete(_params: DeleteFileParams | string): Promise<void> {\n throw new Error(\n `${this.constructor.name} does not implement delete(). Override it to remove objects from this backend.`,\n );\n }\n\n /**\n * Default `read()` for drivers that only implement `fetch()`.\n *\n * Deliberately not abstract: every driver written before `read()` existed\n * keeps compiling and gains working range support for free. It is not\n * *efficient* though — to serve a range it buffers the whole object so the\n * framework can slice it, which saves no bandwidth from the backend. Any\n * driver whose backend can range natively should override this.\n */\n async read(input: ReadFileParams | string): Promise<ReadResult> {\n const params = typeof input === \"string\" ? { name: input } : input;\n const response = await this.fetch({\n name: params.name,\n bucket: params.bucket,\n });\n\n if (!response.ok) {\n throw new FileNotFoundError(params.name);\n }\n\n const type =\n response.headers.get(\"Content-Type\") ?? \"application/octet-stream\";\n const etag = response.headers.get(\"ETag\") ?? undefined;\n const lastModifiedHeader = response.headers.get(\"Last-Modified\");\n const lastModified = lastModifiedHeader\n ? new Date(lastModifiedHeader)\n : undefined;\n\n if (params.range) {\n const blob = await response.blob();\n return {\n body: blob,\n start: 0,\n end: blob.size - 1,\n total: blob.size,\n // The range was not applied by the backend. Reporting `false` hands\n // the slicing to `createStreamResponse`, which has the total in hand.\n partial: false,\n type,\n etag,\n lastModified,\n name: params.name,\n };\n }\n\n const contentLength = Number(response.headers.get(\"Content-Length\"));\n const total = Number.isFinite(contentLength) ? contentLength : 0;\n\n return {\n body: response.body,\n start: 0,\n end: total - 1,\n total,\n partial: false,\n type,\n etag,\n lastModified,\n name: params.name,\n };\n }\n\n /**\n * Total size of an object. Used to resolve suffix ranges on backends without\n * native suffix support, and to report the total on a 416. Override with a\n * HEAD-style request wherever one is available.\n */\n async size(params: ReadFileParams | string): Promise<number> {\n const name = typeof params === \"string\" ? params : params.name;\n const bucket = typeof params === \"string\" ? undefined : params.bucket;\n const response = await this.fetch({ name, bucket });\n if (!response.ok) {\n throw new FileNotFoundError(name);\n }\n const contentLength = Number(response.headers.get(\"Content-Length\"));\n if (Number.isFinite(contentLength)) {\n await response.body?.cancel();\n return contentLength;\n }\n return (await response.blob()).size;\n }\n}\n",
17
17
  "/**\n * Ties a response body to an `AbortSignal`, so aborting after `fetch()` has\n * resolved still reaches a caller that is reading the body.\n *\n * Handing the signal to the SDK is not enough on its own: once the headers are\n * back, whether an abort also errors the body stream depends on the SDK and\n * the runtime, and a caller parked in `arrayBuffer()` must not hang. So on\n * abort the returned stream errors with the signal's reason, and the source\n * stream is cancelled, which releases the file handle or the connection.\n *\n * The abort listener is removed once the body finishes, errors or is\n * cancelled, so a long-lived signal (a request's, say) does not collect one\n * listener per read.\n */\nexport function abortableBody(\n body: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n): ReadableStream<Uint8Array> {\n if (!signal) {\n return body;\n }\n\n const reader = body.getReader();\n let settled = false;\n let onAbort: (() => void) | undefined;\n\n const detach = () => {\n settled = true;\n if (onAbort) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n\n return new ReadableStream<Uint8Array>(\n {\n start(controller) {\n onAbort = () => {\n if (settled) return;\n detach();\n controller.error(signal.reason);\n reader.cancel(signal.reason).catch(() => {});\n };\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n },\n async pull(controller) {\n let chunk: Awaited<ReturnType<typeof reader.read>>;\n try {\n chunk = await reader.read();\n } catch (err) {\n if (settled) return;\n detach();\n controller.error(err);\n return;\n }\n // An abort that landed while the read was pending has already\n // errored the stream, and a cancelled reader resolves `done`.\n if (settled) return;\n if (chunk.done) {\n detach();\n controller.close();\n return;\n }\n controller.enqueue(chunk.value);\n },\n cancel(reason) {\n detach();\n return reader.cancel(reason);\n },\n },\n // Pull only on demand, so nothing is read ahead of the consumer.\n { highWaterMark: 0 },\n );\n}\n",
@@ -21,9 +21,10 @@
21
21
  "//@ts-ignore - type-only; the module itself is loaded on first use by `metadata()`.\nimport type sharp from \"sharp\";\n\nimport { Buffer } from \"node:buffer\";\nimport { loadSharp } from \"../support/sharp\";\nimport type { Prettify } from \"../utils/type\";\n\nimport { RequestContext } from \"../http/requestContext\";\nimport type { ByteRange } from \"../http/range\";\nimport type {\n DeleteFileParams,\n FetchFileOptions,\n PutFileOptions,\n PutFileParams,\n ReadFileParams,\n ReadResult,\n} from \"../services/file-storage/drivers/types\";\nimport { FilesystemManager } from \"../services/file-storage/FilesystemManager\";\nimport { Facade } from \"./Facade\";\n\ntype Metadata = Prettify<sharp.Metadata>;\n\nexport class Storage extends Facade {\n static getFacadeAccessor() {\n return FilesystemManager;\n }\n\n /**\n * Stores a file and returns its object name. Pass `{ signal }` to cancel the\n * upload, e.g. with the incoming request's signal or `AbortSignal.timeout()`.\n */\n static async put(params: PutFileParams | Blob, options: PutFileOptions = {}) {\n return this.getFacadeRoot().driver.put(params, options);\n }\n\n static async metadata(obj: Blob | File): Promise<Partial<Metadata>> {\n const buffer = Buffer.from(await obj.arrayBuffer());\n // Outside the catch: the empty object below means \"this blob is not an\n // image sharp can read\", and a missing `sharp` install must not be able to\n // hide behind it.\n const sharp = await loadSharp(\"Storage.metadata()\");\n try {\n return await sharp(buffer).metadata();\n } catch {\n return {};\n }\n }\n\n /**\n * Reads an object as a streamed `Response`. Pass `{ signal }` to cancel the\n * read, e.g. with the incoming request's signal or `AbortSignal.timeout()`:\n * an abort rejects `fetch()` itself, or errors the body if it lands after\n * `fetch()` resolved.\n */\n static async fetch(\n params: ReadFileParams | string,\n options: FetchFileOptions = {},\n ) {\n // Checked here too, so a custom driver that predates the option still\n // refuses an already-aborted read.\n options.signal?.throwIfAborted();\n return this.getFacadeRoot().driver.fetch(params, options);\n }\n\n /**\n * Reads an object as bytes plus metadata, pushing any byte range down to the\n * storage backend so a seek transfers one window rather than the whole file.\n *\n * The range is resolved in this order: an explicit `options.range`, then a\n * `range` on `params`, then the in-flight request's `Range` header when this\n * is called inside a `this.stream()` route. Pass `{ range: null }` to force a\n * full read inside a stream route.\n */\n static async read(\n params: ReadFileParams | string,\n options: { range?: ByteRange | null } = {},\n ): Promise<ReadResult> {\n const base: ReadFileParams =\n typeof params === \"string\" ? { name: params } : { ...params };\n\n const range =\n \"range\" in options\n ? (options.range ?? null)\n : base.range !== undefined\n ? base.range\n : (RequestContext.getStore()?.rangeRequest ?? null);\n\n return this.getFacadeRoot().driver.read({\n ...base,\n range,\n });\n }\n static list(folder: string) {\n return this.getFacadeRoot().driver.list(folder);\n }\n\n /**\n * Removes a stored object. Deleting one that does not exist resolves without\n * throwing, so a cleanup path can retry safely.\n */\n static async delete(params: DeleteFileParams | string): Promise<void> {\n return this.getFacadeRoot().driver.delete(params);\n }\n}\n",
22
22
  "// @ts-ignore - `sharp` is a peer dependency; only its types are wanted here.\nimport type sharpNamespace from \"sharp\";\n\n/**\n * `sharp`, imported on first use rather than at module load.\n *\n * Three modules need it — the `Sharp` optimization driver, the `Storage` facade\n * and the OG-image branch of `ViewRouteDispatcher` — and all three are reachable\n * from the `gemi/services` and `gemi/facades` barrels, which are also the only\n * door an application has to `CronJob`, `Job`, `DB` and `Lang`. A static import\n * made every one of those imports load a native binary (#403).\n *\n * `sharp` is the only one of the four that can be genuinely absent — it is a\n * peer dependency, so an install can skip its platform binary — which is why\n * the failure gets a message naming the caller rather than a bare resolution\n * error. `usedBy` is that name, written as the caller reads in a stack trace.\n *\n * No memo: the module registry already caches a resolved `import()`, and\n * caching the *failure* would make every later call report the first call's\n * stack instead of its own.\n */\nexport async function loadSharp(usedBy: string): Promise<typeof sharpNamespace> {\n try {\n // @ts-ignore - peer dependency, resolved out of the application's own tree\n return (await import(\"sharp\")).default;\n } catch (error) {\n throw new Error(\n `${usedBy} requires the 'sharp' package. Install it with \\`bun add sharp\\`.`,\n { cause: error },\n );\n }\n}\n",
23
23
  "import type { FileSink } from \"bun\";\nimport { mkdir, readdir, access } from \"fs/promises\";\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\nimport { RequestContext } from \"../../http/requestContext\";\nimport { projectRoot } from \"../../support/discover\";\nimport type { LogConfig } from \"./config\";\nimport type { LogEntry, LogLevel } from \"./types\";\n\nexport class LogManager {\n static token = \"log\";\n\n writer: FileSink;\n isReady: boolean = false;\n\n private flushTimeout: Timer;\n private fileSize: number = 0;\n private writerSize: number = 0;\n private isCreatingFile: boolean = false;\n private bootPromise: Promise<void> | null = null;\n public currentLogFilePath: string;\n\n /**\n * Computed per read, not once in the constructor: `Server.start` awaits\n * `waitForBoot()` — where `LogServiceProvider.boot()` builds this directory —\n * and only *then* imports the http layer that sets `ROOT_DIR`. A field\n * initializer (or any `process.env.ROOT_DIR` read here) resolves to\n * `undefined/storage/logs` at boot, which is how every `Log.info()` ended up\n * throwing on an undefined writer. `projectRoot()` is the same rule\n * `httpProd` sets `ROOT_DIR` from, a moment later.\n */\n private get logsDirPath(): string {\n return `${projectRoot()}/storage/logs`;\n }\n\n constructor(public config: Required<LogConfig>) {}\n\n /**\n * Idempotent. `LogServiceProvider.boot()` calls this so the storage\n * directory exists before the first request; a lazy first `log()` triggers\n * it too, so the manager still works when it is resolved on its own.\n */\n boot(): Promise<void> {\n if (!this.bootPromise) {\n this.bootPromise = this.createStorage()\n .catch((err) => {\n // A logger that rejects turns every `Log.info()` into the caller's\n // error. Report the storage failure once and carry on without a file\n // sink — `log()` still feeds `onLogCreated`.\n console.error(\"Log storage unavailable, file logging disabled\", err);\n })\n .then(() => {\n this.isReady = true;\n });\n }\n return this.bootPromise;\n }\n\n private async createStorage() {\n const storageDirPath = `${projectRoot()}/storage`;\n if (!(await exists(storageDirPath))) {\n await mkdir(storageDirPath);\n }\n if (!(await exists(this.logsDirPath))) {\n await mkdir(this.logsDirPath);\n }\n await this.newLogFile();\n }\n\n async newLogFile() {\n if (!(await exists(this.logsDirPath))) {\n await mkdir(this.logsDirPath);\n }\n this.isCreatingFile = true;\n if (this.currentLogFilePath) {\n this.writer.flush();\n this.writer.end();\n this.writer = null;\n const file = new File(\n [await Bun.file(this.currentLogFilePath).arrayBuffer()],\n this.currentLogFilePath.split(\"/\").pop(),\n { type: \"text/plain\" },\n );\n this.config.onLogFileClosed(file);\n this.fileSize = 0;\n this.writerSize = 0;\n }\n\n const logFiles = await readdir(this.logsDirPath);\n\n const lastLogFile = logFiles.sort().reverse()[0];\n\n if (lastLogFile) {\n const _file = Bun.file(`${this.logsDirPath}/${lastLogFile}`);\n if (_file.size < this.config.maxFileSize) {\n this.currentLogFilePath = `${this.logsDirPath}/${lastLogFile}`;\n\n this.writer = _file.writer();\n this.writer.write(await _file.text());\n this.writer.write(\"\\n\");\n this.writer.flush();\n this.fileSize = _file.size;\n }\n }\n\n if (!this.writer) {\n const logFileName =\n `${new Date(Date.now()).toISOString()}.log`.replaceAll(\":\", \"-\");\n this.currentLogFilePath = `${this.logsDirPath}/${logFileName}`;\n const file = Bun.file(`${this.logsDirPath}/${logFileName}`);\n this.writer = file.writer();\n this.fileSize = 0;\n this.writerSize = 0;\n }\n this.isCreatingFile = false;\n }\n\n async log(\n level: LogLevel,\n message: string,\n metadata: Record<string, any> = {},\n ) {\n if (!this.isReady) {\n await this.boot();\n }\n\n const reqCtx = RequestContext.getStore();\n let requestMetadata = {};\n if (reqCtx) {\n requestMetadata = {\n url: reqCtx.req.rawRequest.url,\n method: reqCtx.req.rawRequest.method,\n headers: reqCtx.req.rawRequest.headers,\n body: reqCtx.req.rawRequest.body,\n };\n }\n\n const logObject: LogEntry = {\n timestamp: new Date(Date.now()).toISOString(),\n env: process.env.NODE_ENV,\n level,\n message,\n metadata: { ...requestMetadata, ...metadata },\n };\n\n let log = \"\";\n try {\n log = JSON.stringify(logObject);\n } catch (err) {\n console.log(\"Error parsing log object\", err);\n }\n // Contained, because this is an app-supplied hook and every facade method\n // calls `log()` without awaiting it: a hook that throws would otherwise\n // leave a floating `Log.info()` as an unhandled rejection, which is the\n // failure this method exists to not have. A rejected promise from an async\n // hook is the same thing arriving later, so it is caught too — what is not\n // done is *awaiting* it, which would put the app's transport in front of\n // the file write.\n try {\n const handled = this.config.onLogCreated(logObject);\n if (handled instanceof Promise) {\n handled.catch((err) => console.error(\"Error in onLogCreated\", err));\n }\n } catch (err) {\n console.error(\"Error in onLogCreated\", err);\n }\n\n // No writer means `createStorage` failed (or a rotation is mid-flight);\n // either way the entry has already been handed to `onLogCreated`, so drop\n // the file copy rather than throwing at the call site.\n if (!this.writer) {\n return;\n }\n\n this.writerSize += log.length;\n this.fileSize += log.length;\n\n try {\n this.writer.write(log);\n this.writer.write(\"\\n\");\n this.tryFlush();\n } catch (err) {\n console.error(\"Error writing log\", err);\n // Do something\n }\n }\n\n async tryFlush() {\n if (this.fileSize > this.config.maxFileSize) {\n if (!this.isCreatingFile) {\n await this.newLogFile();\n }\n }\n if (this.writerSize > this.config.maxFileSize / 2) {\n await this.writer.flush();\n this.writerSize = 0;\n await this.newLogFile();\n } else {\n clearTimeout(this.flushTimeout);\n this.flushTimeout = setTimeout(async () => {\n await this.writer.flush();\n this.writerSize = 0;\n }, 100);\n }\n }\n}\n",
24
- "import { LogManager } from \"../services/logging/LogManager\";\nimport { Facade } from \"./Facade\";\n\nexport class Log extends Facade {\n static getFacadeAccessor() {\n return LogManager;\n }\n\n static debug(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"debug\", message, metadata);\n }\n\n static info(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"info\", message, metadata);\n }\n\n static notice(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"notice\", message, metadata);\n }\n\n static warning(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"warning\", message, metadata);\n }\n\n static error(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"error\", message, metadata);\n }\n\n static critical(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"critical\", message, metadata);\n }\n\n static alert(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"alert\", message, metadata);\n }\n\n static emergency(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"emergency\", message, metadata);\n }\n}\n"
24
+ "import { LogManager } from \"../services/logging/LogManager\";\nimport { Facade } from \"./Facade\";\n\nexport class Log extends Facade {\n static getFacadeAccessor() {\n return LogManager;\n }\n\n static debug(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"debug\", message, metadata);\n }\n\n static info(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"info\", message, metadata);\n }\n\n static notice(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"notice\", message, metadata);\n }\n\n static warning(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"warning\", message, metadata);\n }\n\n static error(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"error\", message, metadata);\n }\n\n static critical(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"critical\", message, metadata);\n }\n\n static alert(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"alert\", message, metadata);\n }\n\n static emergency(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"emergency\", message, metadata);\n }\n}\n",
25
+ "import type { RedisClient, RedisOptions } from \"bun\";\nimport type { RedisConfig } from \"./config\";\n\n/**\n * The constructor `Bun.RedisClient` is, described structurally.\n *\n * Reached through the `Bun` global rather than `import { RedisClient } from\n * \"bun\"`, which is what this module used to do. That was a **value** import of\n * a specifier only the Bun runtime can resolve, and this class is re-exported\n * from `gemi/services` and reached from `gemi/facades` through the `Redis`\n * facade — the two barrels that are also the only door to `CronJob`, `Job`,\n * `DB` and `Lang`. So the specifier landed in the graph of every app and every\n * test that imported either one, and under a browser-targeted runner the whole\n * barrel simply failed to resolve (#396, #403).\n *\n * The global carries no specifier for a bundler or a test runner to resolve, so\n * the cost is paid only by code that actually asks for a client.\n */\ntype RedisClientConstructor = new (\n url?: string,\n options?: RedisOptions,\n) => RedisClient;\n\nexport class RedisManager {\n static token = \"redis\";\n\n private instance: RedisClient | null = null;\n\n constructor(public config: RedisConfig = {}) {}\n\n /**\n * Bun's Redis client. Built on first access and memoized.\n *\n * It connects lazily on the first command, so building it here is safe even\n * when Redis isn't running or configured — nothing connects until something\n * actually issues a command.\n */\n get client(): RedisClient {\n return (this.instance ??= new (redisClientConstructor())(\n this.config.url,\n this.config.options,\n ));\n }\n\n /**\n * `client` was a plain public property before it was a getter, and\n * overwriting a manager's client is how this repo fakes one —\n * `S3Driver.test.ts` does exactly that, and the `S3Driver` half of #403 kept\n * that seam working on purpose. An accessor with no setter would have turned\n * `manager.client = fake` into `TypeError: Attempted to assign to readonly\n * property` instead, which is not a change this was meant to make.\n */\n set client(client: RedisClient) {\n this.instance = client;\n }\n\n /**\n * Closes the client, when one was built; a later `client` builds a new one.\n * Does not build one to close it.\n */\n close(): void {\n const client = this.instance;\n this.instance = null;\n client?.close();\n }\n}\n\nfunction redisClientConstructor(): RedisClientConstructor {\n const ctor = (globalThis as any).Bun?.RedisClient as\n | RedisClientConstructor\n | undefined;\n\n if (typeof ctor !== \"function\") {\n throw new Error(\n \"Redis requires Bun's built-in Redis client, which this runtime does not provide. Run the app under Bun, or bind your own client for the 'redis' token.\",\n );\n }\n\n return ctor;\n}\n"
25
26
  ],
26
- "mappings": "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",
27
- "debugId": "402F43E221AB2F3A64756E2164756E21",
27
+ "mappings": "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",
28
+ "debugId": "A4BAD261A91D5FDC64756E2164756E21",
28
29
  "names": []
29
30
  }
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{V as C}from"./chunk-w099t7zj.js";import{$ as A}from"./chunk-cg4k40zy.js";import{Bg as _}from"./chunk-zfch4da5.js";var S=_(C(),1),p=_(A(),1),N="AWS_ACCESS_KEY_ID",a="AWS_SECRET_ACCESS_KEY",i="AWS_SESSION_TOKEN",I="AWS_CREDENTIAL_EXPIRATION",d="AWS_CREDENTIAL_SCOPE",v="AWS_ACCOUNT_ID",T=(e)=>async()=>{e?.logger?.debug("@aws-sdk/credential-provider-env - fromEnv");let o=process.env[N],r=process.env[a],n=process.env[i],s=process.env[I],t=process.env[d],E=process.env[v];if(o&&r){let c={accessKeyId:o,secretAccessKey:r,...n&&{sessionToken:n},...s&&{expiration:new Date(s)},...t&&{credentialScope:t},...E&&{accountId:E}};return S.setCredentialFeature(c,"CREDENTIALS_ENV_VARS","g"),c}throw new p.CredentialsProviderError("Unable to find environment variable credentials.",{logger:e?.logger})};export{N as a,a as b,i as c,I as d,d as e,v as f,T as g};
2
+ import{V as C}from"./chunk-zf4r4kat.js";import{$ as A}from"./chunk-81v4c4b1.js";import{Jg as _}from"./chunk-9tsw1bmt.js";var S=_(C(),1),p=_(A(),1),N="AWS_ACCESS_KEY_ID",a="AWS_SECRET_ACCESS_KEY",i="AWS_SESSION_TOKEN",I="AWS_CREDENTIAL_EXPIRATION",d="AWS_CREDENTIAL_SCOPE",v="AWS_ACCOUNT_ID",T=(e)=>async()=>{e?.logger?.debug("@aws-sdk/credential-provider-env - fromEnv");let o=process.env[N],r=process.env[a],n=process.env[i],s=process.env[I],t=process.env[d],E=process.env[v];if(o&&r){let c={accessKeyId:o,secretAccessKey:r,...n&&{sessionToken:n},...s&&{expiration:new Date(s)},...t&&{credentialScope:t},...E&&{accountId:E}};return S.setCredentialFeature(c,"CREDENTIALS_ENV_VARS","g"),c}throw new p.CredentialsProviderError("Unable to find environment variable credentials.",{logger:e?.logger})};export{N as a,a as b,i as c,I as d,d as e,v as f,T as g};
3
3
 
4
- //# debugId=72ED474CAFC5BCC064756E2164756E21
4
+ //# debugId=9D4E87716C22D39664756E2164756E21
@@ -5,6 +5,6 @@
5
5
  "import { setCredentialFeature } from \"@aws-sdk/core/client\";\nimport { CredentialsProviderError } from \"@smithy/property-provider\";\nexport const ENV_KEY = \"AWS_ACCESS_KEY_ID\";\nexport const ENV_SECRET = \"AWS_SECRET_ACCESS_KEY\";\nexport const ENV_SESSION = \"AWS_SESSION_TOKEN\";\nexport const ENV_EXPIRATION = \"AWS_CREDENTIAL_EXPIRATION\";\nexport const ENV_CREDENTIAL_SCOPE = \"AWS_CREDENTIAL_SCOPE\";\nexport const ENV_ACCOUNT_ID = \"AWS_ACCOUNT_ID\";\nexport const fromEnv = (init) => async () => {\n init?.logger?.debug(\"@aws-sdk/credential-provider-env - fromEnv\");\n const accessKeyId = process.env[ENV_KEY];\n const secretAccessKey = process.env[ENV_SECRET];\n const sessionToken = process.env[ENV_SESSION];\n const expiry = process.env[ENV_EXPIRATION];\n const credentialScope = process.env[ENV_CREDENTIAL_SCOPE];\n const accountId = process.env[ENV_ACCOUNT_ID];\n if (accessKeyId && secretAccessKey) {\n const credentials = {\n accessKeyId,\n secretAccessKey,\n ...(sessionToken && { sessionToken }),\n ...(expiry && { expiration: new Date(expiry) }),\n ...(credentialScope && { credentialScope }),\n ...(accountId && { accountId }),\n };\n setCredentialFeature(credentials, \"CREDENTIALS_ENV_VARS\", \"g\");\n return credentials;\n }\n throw new CredentialsProviderError(\"Unable to find environment variable credentials.\", { logger: init?.logger });\n};\n"
6
6
  ],
7
7
  "mappings": ";qIAAA,SACA,KACa,EAAU,oBACV,EAAa,wBACb,EAAc,oBACd,EAAiB,4BACjB,EAAuB,uBACvB,EAAiB,iBACjB,EAAU,CAAC,IAAS,SAAY,CACzC,GAAM,QAAQ,MAAM,4CAA4C,EAChE,IAAM,EAAc,QAAQ,IAAI,GAC1B,EAAkB,QAAQ,IAAI,GAC9B,EAAe,QAAQ,IAAI,GAC3B,EAAS,QAAQ,IAAI,GACrB,EAAkB,QAAQ,IAAI,GAC9B,EAAY,QAAQ,IAAI,GAC9B,GAAI,GAAe,EAAiB,CAChC,IAAM,EAAc,CAChB,cACA,qBACI,GAAgB,CAAE,cAAa,KAC/B,GAAU,CAAE,WAAY,IAAI,KAAK,CAAM,CAAE,KACzC,GAAmB,CAAE,iBAAgB,KACrC,GAAa,CAAE,WAAU,CACjC,EAEA,OADA,uBAAqB,EAAa,uBAAwB,GAAG,EACtD,EAEX,MAAM,IAAI,2BAAyB,mDAAoD,CAAE,OAAQ,GAAM,MAAO,CAAC",
8
- "debugId": "72ED474CAFC5BCC064756E2164756E21",
8
+ "debugId": "9D4E87716C22D39664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  // @bun
2
2
  import{AsyncLocalStorage as E}from"async_hooks";class Q{content={title:"Gemi App",description:null,openGraph:null};touched=!1;render(){return{title:this.content.title,description:this.content.description,openGraph:this.content.openGraph}}title(j){this.touched=!0,this.content.title=j}description(j){this.touched=!0,this.content.description=j}openGraph({title:j,description:B,type:z,url:G,image:J,imageAlt:U,imageWidth:V,imageHeight:X,twitterImage:Y=J,twitterImageAlt:D=U,twitterImageWidth:K=V,twitterImageHeight:M=X}){this.touched=!0;let Z=J,$=Y;if(J&&!J.startsWith("http"))Z=`${process.env.HOST_NAME}${J}`,$=`${process.env.HOST_NAME}${Y}`;this.content.openGraph=Object.fromEntries(Object.entries({title:j,description:B,type:z,url:G,image:Z,imageAlt:U,imageWidth:V,imageHeight:X,twitterImage:$,twitterImageAlt:D,twitterImageWidth:K,twitterImageHeight:M}).filter(([O,N])=>N!==void 0))}}function b(j,B,z={}){return[`${j}=${B}`,z.maxAge?`Max-Age=${z.maxAge}`:"",z.httpOnly?"HttpOnly":"",z.secure?"Secure":"",z.sameSite?`SameSite=${z.sameSite}`:"SameSite=Strict",z.path?`Path=${z.path}`:"Path=/",z.domain?`Domain=${z.domain}`:"",z.expires?`Expires=${z.expires.toUTCString()}`:"",z.partitioned?"Partitioned":""].filter((G)=>G!=="").join("; ")}var P=new E;class F{req;cookies=new Set;headers=new Headers;serverQueries=null;user=null;csrfHmac=null;locale=null;metadata=new Q;rangeRequest=null;sessionId=null;featureEvaluations=null;featureContext=null;featureBuckets=null;pendingWork=new Set;ended=!1;constructor(j){this.req=j}waitUntil(j){if(this.ended)return;let B=Promise.resolve(j).then(()=>{},()=>{});this.pendingWork.add(B),B.then(()=>this.pendingWork.delete(B))}hasPendingWork(){return this.pendingWork.size>0}async whenIdle(){while(this.pendingWork.size>0)await Promise.all(Array.from(this.pendingWork))}setLocale(j){this.locale=j}renderMeta(){return this.metadata.render()}setCSRFHmac(j){this.csrfHmac=j}setCookie(j,B,z={}){this.cookies.add(b(j,B,z))}deleteCookie(j,B={}){this.cookies.add(b(j,"",{...B,maxAge:-1}))}setHeaders(j,B){this.headers.set(j,B)}setUser(j){this.user=j}setRequest(j){this.req=j}destroy(){this.ended=!0,delete this.cookies,delete this.headers,this.serverQueries=null,this.sessionId=null,this.featureEvaluations=null,this.featureContext=null,this.featureBuckets=null,delete this.user}}var L="session_id";function H(){let j=T.getStore();if(!j)return null;if(j.sessionId)return j.sessionId;let B=j.req?.cookies?.get(L);if(B)j.sessionId=B;return j.sessionId}function W(){let j=T.getStore();if(!j)return null;let B=H();if(B)return B;let z=Bun.randomUUIDv7();return j.sessionId=z,j.setCookie(L,z,{httpOnly:!0,secure:Bun.env.NODE_ENV==="production",sameSite:"Lax",expires:new Date(Date.now()+31536000000)}),z}class T{static getStore(){return P.getStore()}static setRequest(j){P.getStore().req=j}static run(j,B,z){let G=new F(j);if(z)G.user=z.user;return P.run(G,B)}static runWith(j,B){return P.run(j,B)}static exit(j){return P.exit(j)}}
3
- export{H as nf,W as of,T as pf};
3
+ export{H as vf,W as wf,T as xf};
4
4
 
5
- //# debugId=E7A6630919DFB40164756E2164756E21
5
+ //# debugId=45CBAA06E7640EDE64756E2164756E21
@@ -6,6 +6,6 @@
6
6
  "export type OpenGraphParams = {\n title: string;\n description?: string;\n type: string;\n url: string;\n image: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n twitterImage?: string;\n twitterImageAlt?: string;\n twitterImageWidth?: number;\n twitterImageHeight?: number;\n};\nexport class Metadata {\n content: any = {\n title: \"Gemi App\",\n description: null,\n openGraph: null,\n };\n\n /**\n * Whether a handler set anything, as opposed to `content` still being the\n * defaults. A partially rendered response that touched no metadata sends\n * none, so the client keeps what the skipped segments put there.\n */\n touched = false;\n\n render() {\n return {\n title: this.content.title,\n description: this.content.description,\n openGraph: this.content.openGraph,\n };\n }\n\n title(title: string) {\n this.touched = true;\n this.content.title = title;\n }\n\n description(description: string) {\n this.touched = true;\n this.content.description = description;\n }\n\n openGraph({\n title,\n description,\n type,\n url,\n image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage = image,\n twitterImageAlt = imageAlt,\n twitterImageWidth = imageWidth,\n twitterImageHeight = imageHeight,\n }: OpenGraphParams) {\n this.touched = true;\n let _image = image;\n let _twitterImage = twitterImage;\n if (image && !image.startsWith(\"http\")) {\n _image = `${process.env.HOST_NAME}${image}`;\n _twitterImage = `${process.env.HOST_NAME}${twitterImage}`;\n }\n this.content.openGraph = Object.fromEntries(\n Object.entries({\n title,\n description,\n type,\n url,\n image: _image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage: _twitterImage,\n twitterImageAlt,\n twitterImageWidth,\n twitterImageHeight,\n }).filter(([_, value]) => value !== undefined),\n );\n }\n}\n"
7
7
  ],
8
8
  "mappings": "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",
9
- "debugId": "E7A6630919DFB40164756E2164756E21",
9
+ "debugId": "45CBAA06E7640EDE64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -1,5 +1,5 @@
1
1
  // @bun
2
2
  function E(z){return z}function f(){return{url:process.env.DATABASE_URL,dialect:void 0,options:void 0,slowTransactionThreshold:b,connections:void 0}}var b=2000;class Q extends Error{constructor(z){super(`Could not infer a database dialect from "${z}". Expected a URL starting with postgres://, postgresql://, mysql://, mariadb://, `+"sqlite://, or file: \u2014 or a SQLite path such as ./dev.db or :memory:.");this.name="UnknownDatabaseUrlError"}}class j extends Error{constructor(z){super(z===void 0||z==="default"?"No database URL configured. Set the DATABASE_URL environment variable, or set `url` in app/config/database.ts.":`The "${z}" database connection has no \`url\`. Set one under \`connections.${z}\` in app/config/database.ts.`);this.name="MissingDatabaseUrlError"}}var L={"postgres:":"postgres","postgresql:":"postgres","mysql:":"mysql","mariadb:":"mariadb","sqlite:":"sqlite","file:":"sqlite"},D=[".db",".sqlite",".sqlite3"];function F(z){let B=z.trim();if(B==="")throw new Q(z);if(B===":memory:")return"sqlite";let G=B.indexOf(":");if(G!==-1){let J=B.slice(0,G+1).toLowerCase(),K=L[J];if(K)return K}if(S(B))return"sqlite";throw new Q(z)}function S(z){if(z.startsWith("./")||z.startsWith("../")||z.startsWith("/"))return!0;let B=z.toLowerCase();return D.some((G)=>B.endsWith(G))}function p(z){return z==="sqlite"}function m(z){return z==="mysql"||z==="mariadb"}import{existsSync as g,readFileSync as y,realpathSync as I,statSync as U}from"fs";import{isAbsolute as w,join as H,resolve as q}from"path";var O=H("prisma","schema.prisma");class R extends Error{constructor(z,B,G){super(`"${z}" now resolves to ${B}, which is where Prisma migrates it. gemi used to open ${G} instead, and that file holds data \u2014 so `+`opening the resolved one would quietly leave it behind. gemi will not choose. Move ${G} onto ${B} if it is the database you want, or point DATABASE_URL at an absolute path to say so explicitly.`);this.name="AmbiguousSqlitePathError"}}function C(z){let B=z.trim(),G="",J=B;for(let K of["file://","file:","sqlite://","sqlite:"])if(B.slice(0,K.length).toLowerCase()===K){G=B.slice(0,K.length),J=B.slice(K.length);break}if(J===":memory:"||J.startsWith(":memory:?"))return null;return{prefix:G,file:J}}function _(z,B,G=process.cwd()){if(B!=="sqlite")return{url:z};let J=C(z);if(!J||J.file==="")return{url:z};if(w(J.file))return{url:z};let K=J.file.indexOf("?"),Z=K===-1?J.file:J.file.slice(0,K),$=K===-1?"":J.file.slice(K),X=H(G,"prisma");if(!T(G,z))return{url:z};let W=q(G,Z),Y=q(X,Z);if(W===Y)return{url:z};return{url:`${J.prefix}${Y}${$}`,moved:{from:W,to:Y}}}function T(z,B){let G=H(z,O);if(!g(G))return!1;let J;try{J=y(G,"utf8")}catch{return!1}let Z=J.replace(/^\s*\/\/.*$/gm,"").match(/datasource\s+\w+\s*\{([\s\S]*?)\}/);if(!Z)return!1;let $=Z[1];if(!/provider\s*=\s*["']sqlite["']/.test($))return!1;let X=$.match(/url\s*=\s*env\(\s*["']([^"']+)["']\s*\)/);if(X){let Y=process.env[X[1]];return typeof Y==="string"&&Y.trim()===B.trim()}let W=$.match(/url\s*=\s*["']([^"']+)["']/);return W?W[1].trim()===B.trim():!1}function k(z){try{if(I(z.from)===I(z.to))return null}catch{}try{let B=U(z.from);return B.isFile()&&B.size>0?z.from:null}catch{return null}}var{SQL:A}=globalThis.Bun;var V="default";class P extends Error{constructor(z,B){super(`No database connection named "${z}". Configured: ${B.map((G)=>`"${G}"`).join(", ")}. Declare it under \`connections\` in app/config/database.ts.`);this.name="UnknownConnectionError"}}class x extends Error{constructor(z){super(`"${z}" is the name of the connection declared by the top-level \`url\` and \`options\`, so it cannot also appear under \`connections\`. Rename it, or move its settings up to the top level.`);this.name="ReservedConnectionNameError"}}class N extends Error{open;requested;constructor(z,B){super(`A transaction is open on the "${z}" connection, and this statement names "${B}". A transaction cannot span two connections: the statement would run outside it and stay committed when the transaction rolls back. Move this query outside the transaction, or run the whole unit on one connection.`);this.open=z;this.requested=B;this.name="CrossConnectionTransactionError"}}class M{name;config;sql;dialect;url;ready;constructor(z,B={}){this.name=z;this.config=B;let G=B.url;if(!G)throw new j(z);this.dialect=B.dialect??F(G);let J=_(G,this.dialect);if(J.moved){let K=k(J.moved);if(K)throw new R(G,J.moved.to,K)}this.url=J.url,this.sql=B.options?new A(this.url,B.options):new A(this.url),this.ready=this.configure()}async configure(){if(this.dialect!=="sqlite")return;await this.sql.unsafe("pragma foreign_keys = ON")}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await this.sql.close()}}class h{config;static token="database";name=V;pools=new Map;ready;constructor(z={}){this.config=z;let{connections:B={},...G}=z;this.pools.set(V,new M(V,G));try{this.build(B,G.slowTransactionThreshold)}catch(J){for(let K of this.pools.values())K.ready.catch(()=>{}),K.close().catch(()=>{});throw J}this.ready=Promise.all([...this.pools.values()].map((J)=>J.ready)).then(()=>{return})}build(z,B){for(let[G,J]of Object.entries(z)){if(G===V)throw new x(G);this.pools.set(G,new M(G,{slowTransactionThreshold:B,...J}))}}connection(z=V){if(z===V)return this;let B=this.pools.get(z);if(!B)throw new P(z,this.connectionNames);return B}get connectionNames(){return[...this.pools.keys()]}get sql(){return this.default.sql}get dialect(){return this.default.dialect}get url(){return this.default.url}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await Promise.all([...this.pools.values()].map((z)=>z.close()))}get default(){return this.pools.get(V)}}
3
- export{E as Ef,f as Ff,b as Gf,Q as Hf,j as If,F as Jf,p as Kf,m as Lf,R as Mf,V as Nf,P as Of,x as Pf,N as Qf,M as Rf,h as Sf};
3
+ export{E as Mf,f as Nf,b as Of,Q as Pf,j as Qf,F as Rf,p as Sf,m as Tf,R as Uf,V as Vf,P as Wf,x as Xf,N as Yf,M as Zf,h as _f};
4
4
 
5
- //# debugId=229A1DDAFC1C047664756E2164756E21
5
+ //# debugId=6A214A44E59F865964756E2164756E21
@@ -9,6 +9,6 @@
9
9
  "import type { SQL } from \"bun\";\nimport type { ConnectionConfig, DatabaseConfig } from \"./config\";\nimport {\n Connection,\n DEFAULT_CONNECTION,\n ReservedConnectionNameError,\n UnknownConnectionError,\n type DatabaseConnection,\n} from \"./Connection\";\nimport type { Dialect } from \"./dialect\";\n\n// Wraps Bun's `SQL` client. Bun ships one client that speaks SQLite, Postgres,\n// MySQL and MariaDB, so gemi does not need a driver per database — it needs to\n// know *which* one is in use, which is what `dialect` carries.\n//\n// Safe to build eagerly: Bun's client connects on the first query, not at\n// construction. (`RedisManager` used to be cited here as the parallel case. As\n// of #403 it builds its client in a memoizing getter instead — not because\n// eager construction was unsafe, but because naming Bun's `RedisClient` at\n// module scope is what made `gemi/services` unloadable off Bun. `Connection`\n// still imports `SQL` as a value for the same reason, which is the remaining\n// half of #396.) It is still bound as a lazy singleton,\n// so an app that never touches the database never resolves it and never has to\n// have DATABASE_URL set.\n//\n// Since #327 it holds *connections*, plural: the top-level `url` and `options`\n// build the one called `\"default\"`, and each key under `connections` builds\n// another. What it does not do is decide which one a query uses — that is the\n// ORM's ambient scope and the `DB` facade, because the choice is per query\n// rather than per application. See `connection` below.\nexport class DatabaseManager implements DatabaseConnection {\n static token = \"database\";\n\n /**\n * This object *is* the default connection, so it answers to the name.\n *\n * Not a formality: `connection(\"default\")` returns `this` rather than the\n * `Connection` in the map, which is what keeps every existing reader —\n * `DB.sql`, `db.dialect`, and the test harnesses that wrap the manager in a\n * Proxy to count statements — looking at the same object the ORM executes\n * through. A second object for the default pool would have quietly bypassed\n * all of them while every test still passed.\n */\n public readonly name = DEFAULT_CONNECTION;\n\n /**\n * Every pool this manager owns, keyed by name and including the default one.\n *\n * Private because the map is the manager's bookkeeping — `connection()` is\n * the way in, and it is the only path that knows the default is `this`.\n */\n private readonly pools = new Map<string, Connection>();\n\n /**\n * Resolves once **every** connection has been configured, or rejects if one\n * could not be. Only SQLite has anything to do; elsewhere it is already\n * resolved.\n *\n * All of them rather than the default alone, because the thing a caller waits\n * on this for — SQLite's `pragma foreign_keys` — is per client, so a second\n * SQLite connection has its own and a caller awaiting one manager-level\n * promise means all of them.\n */\n public readonly ready: Promise<void>;\n\n constructor(public config: DatabaseConfig = {}) {\n const { connections = {}, ...primary } = config;\n\n // The default first, so a `MissingDatabaseUrlError` from a missing\n // `DATABASE_URL` still comes out of construction the way it always has,\n // rather than after a named connection has already opened a client.\n this.pools.set(\n DEFAULT_CONNECTION,\n new Connection(DEFAULT_CONNECTION, primary),\n );\n\n // A connection that is built before the one whose config is wrong is still\n // a live client with an open handle, and on the throwing path nothing else\n // will ever hold it: the manager never becomes a value, so nobody can call\n // `close`. Left alone, the pragma this constructor issues for a SQLite\n // connection settles against a client being torn down and surfaces as an\n // unhandled rejection with no configuration error anywhere near it.\n try {\n this.build(connections, primary.slowTransactionThreshold);\n } catch (error) {\n for (const pool of this.pools.values()) {\n // The in-flight configuration first: it is what rejects when the client\n // under it goes away, and this is the only place that can say the\n // rejection was expected.\n pool.ready.catch(() => {});\n pool.close().catch(() => {});\n }\n throw error;\n }\n\n // Built once here rather than derived per read, so that a connection whose\n // configuration rejects produces one unhandled rejection at most instead of\n // a fresh one per access.\n this.ready = Promise.all(\n [...this.pools.values()].map((pool) => pool.ready),\n ).then(() => undefined);\n }\n\n private build(\n connections: Record<string, ConnectionConfig>,\n slowTransactionThreshold: number | false | undefined,\n ): void {\n for (const [name, connection] of Object.entries(connections)) {\n if (name === DEFAULT_CONNECTION)\n throw new ReservedConnectionNameError(name);\n\n this.pools.set(\n name,\n new Connection(name, {\n // The threshold is the one setting a named connection is likely to\n // want *unchanged*: it is a development diagnostic about holding a\n // pooled connection, and that concern does not stop applying because\n // the pool has a name. `url`, `options` and `dialect` are deliberately\n // not inherited — a connection that borrowed the default's URL by\n // omission would be a second pool onto the same database created by a\n // typo in a key.\n slowTransactionThreshold,\n ...connection,\n }),\n );\n }\n }\n\n /**\n * The connection called `name`, or the default one when called with nothing.\n *\n * Throws rather than falling back to the default for an unknown name, and\n * that is the important half. A fallback would make `Model.on(\"analitycs\")`\n * run on the hot path — the exact pool the caller was trying to stay off —\n * and the only symptom would be the incident it was meant to prevent,\n * arriving weeks later with nothing pointing back at the typo.\n */\n connection(name: string = DEFAULT_CONNECTION): DatabaseConnection {\n // `this`, not `pools.get(DEFAULT_CONNECTION)` — see `name` above.\n if (name === DEFAULT_CONNECTION) return this;\n\n const found = this.pools.get(name);\n if (!found) throw new UnknownConnectionError(name, this.connectionNames);\n return found;\n }\n\n /** Every configured name, default first. For error messages and diagnostics. */\n get connectionNames(): string[] {\n return [...this.pools.keys()];\n }\n\n /**\n * The default connection's client. Unchanged in meaning: an application that\n * never names a connection sees exactly what it saw before #327.\n */\n get sql(): SQL {\n return this.default.sql;\n }\n\n get dialect(): Dialect {\n return this.default.dialect;\n }\n\n get url(): string {\n return this.default.url;\n }\n\n // Escape hatch matching Bun's own API, so `db.query` reads like `sql` does in\n // Bun's docs: db.query`select * from users where id = ${id}`\n get query(): SQL {\n return this.sql;\n }\n\n /** Closes every connection, not only the default one. */\n async close(): Promise<void> {\n // The aggregate promise needs the same treatment each connection's own\n // `ready` gets in `Connection.close` — it is derived from them, so a\n // rejection there arrives here as a second, separately unhandled one.\n this.ready.catch(() => {});\n await Promise.all([...this.pools.values()].map((pool) => pool.close()));\n }\n\n private get default(): Connection {\n return this.pools.get(DEFAULT_CONNECTION)!;\n }\n}\n"
10
10
  ],
11
11
  "mappings": "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",
12
- "debugId": "229A1DDAFC1C047664756E2164756E21",
12
+ "debugId": "6A214A44E59F865964756E2164756E21",
13
13
  "names": []
14
14
  }
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ import{Db as NZ,Ib as b}from"./chunk-w312e9nx.js";import{Rb as m,Tb as k,Vb as WZ,Wb as HZ,Xb as XZ,Zb as UZ}from"./chunk-1yq1e6sb.js";import{ac as r,bc as a,cc as C,dc as e,ec as ZZ,gc as $Z}from"./chunk-saqfc6vp.js";import{jc as I}from"./chunk-z4k18gnp.js";import{Ad as w,Lc as o,Uc as zZ,Vc as c,Zc as j,fd as d,gd as f,kd as l,rd as S,wc as CZ,yd as F,zd as v}from"./chunk-xx2zg6sk.js";import{Id as YZ,Jd as h}from"./chunk-ha705bcz.js";import{lf as u,nf as y,of as D,pf as E}from"./chunk-174jkg6d.js";import{Df as JZ}from"./chunk-trdwxm5x.js";import{jg as U}from"./chunk-dwqh79e5.js";import{og as p}from"./chunk-pmmrhak1.js";import{tg as M}from"./chunk-d3jkypc7.js";import{ug as VZ}from"./chunk-8gexb1gt.js";async function xZ(Z){try{if(!await Z.shouldRun.call(Z))return}catch($){console.error(`Error evaluating shouldRun for cron job ${Z.name}:`,$);return}try{await Z.onTick.call(Z)}catch($){console.error(`Error executing cron job ${Z.name}:`,$)}try{await Z.callback.call(Z)}catch($){console.error(`Error in cron job ${Z.name}:`,$)}try{await Z.onComplete.call(Z)}catch($){console.error(`Error completing cron job ${Z.name}:`,$)}}class A{static token="scheduler";handles=[];resolved;inFlight=new Map;stopped=!1;constructor(Z){this.resolved=Z.jobs}get jobs(){return[...this.resolved]}useJobs(Z){this.resolved=Z}start(Z=($)=>$()){if(this.stopped=!1,this.resolved.length===0)return;let $=globalThis.__gemiCronJobs??=new Map,H=new Map;for(let G of this.resolved){let V=new G;if(!V.name){console.error(`Cron job must have a name \u2014 ${G.name||"an anonymous class"} has none, so it is not scheduled. If this is a base class that other jobs extend, move it out of the discovered directory: \`abstract\` does not survive to runtime, so a class under app/cron is indistinguishable from a job.`);continue}if(!V.cron){console.error(`Cron job must have an expression. Job: ${V.name}`);continue}let X=H.get(V.name);if(X!==void 0){console.error(`Two cron jobs claim the name "${V.name}" \u2014 ${X} is scheduled and ${G.name||"an anonymous class"} is not. A name is the scheduler's key, so only one job can hold it. Rename one.`);continue}H.set(V.name,G.name||"an anonymous class"),$.get(V.name)?.stop();let Y=Bun.cron(V.cron,()=>{if(this.stopped)return;return this.track(V.name,()=>Z(()=>xZ(V)))});$.set(V.name,Y),this.handles.push(Y)}}stop(){this.stopped=!0;for(let Z of this.handles)Z.stop();this.handles=[]}async drain(Z=1/0){this.stop();let $,H=new Promise((G)=>{if(Z!==1/0)$=setTimeout(G,Z)});return await Promise.race([Promise.allSettled([...this.inFlight.values()].map((G)=>G.done)),H]),clearTimeout($),{unfinished:[...this.inFlight.values()].map((G)=>({...G.tick}))}}get running(){return this.inFlight.size}track(Z,$){let H={},G=Promise.resolve().then($).finally(()=>this.inFlight.delete(H));return this.inFlight.set(H,{tick:{name:Z,startedAt:new Date},done:G}),G}}import{isMainThread as EZ}from"worker_threads";var TZ=100,SZ=(Z)=>Math.min(TZ,Math.floor(Z/10));class RZ extends I{register(){this.app.singleton(C,()=>new C(this.app.config.get("queue",{}),{application:this.app}))}async boot(){let Z=this.app.config.get("queue",{});if(Z.jobs!==void 0)return;let{jobsDir:$}=U(r(),Z);this.app.make(C).useJobs(await HZ($))}async shutdown(Z){if(!this.app.resolved(C))return;let $=this.app.make(C);if($.running>0)console.log(`[gemi] Shutting down: waiting for ${$.running} running queued job(s).`);let H=Z?.timeoutMs,{unfinished:G}=await $.drain(H===void 0?1/0:Math.max(0,H-SZ(H)));if(G.length>0)return console.error("[gemi] Queued jobs still running at shutdown: "+G.map((V)=>`${V.name} (${V.id})`).join(", ")),{abandoned:!0}}}function C3(Z){if(jZ(Z),Bun.env.NODE_ENV!=="production")return MZ(Z);if(GZ(Z))return;if(!e())return;if(!Z.bound(C))return;Z.make(C).start()}function GZ(Z){let $=Z.config.get("queue",{}).driver??"memory";return $==="memory"||$ instanceof a}function DZ(Z){if(GZ(Z))return!0;if(typeof Z.config.get("queue",{}).driver!=="function"||!Z.bound(C))return!1;try{return!Z.make(C).durable}catch{return!1}}function jZ(Z){let $=process.env.GEMI_QUEUE_CLAIM;if($===void 0||$Z())return;if(process.env.ROOT_DIR===void 0||!EZ)return;if(ZZ()){if(!DZ(Z))return;console.warn('[gemi] GEMI_QUEUE_CLAIM=off is ignored: the memory queue driver keeps jobs in the process that dispatched them, so no worker could run them. This server runs its own jobs. Use a driver other processes can read, such as "database", to hand jobs to `gemi queue:work`.')}else if($.trim().toLowerCase()!=="on")console.warn(`[gemi] GEMI_QUEUE_CLAIM="${$}" is not "off" or "on", so this server claims jobs. Set it to "off" to leave them to \`gemi queue:work\`.`)}function MZ(Z){let $=globalThis.__gemiDevQueue;if(!$)return;if(globalThis.__gemiDevQueue=void 0,$.stop(),Z.bound(C))Z.make(C).start()}class kZ extends I{register(){this.app.singleton(w,()=>new w(this.app.config.get("auth",{})))}}var yZ=100,fZ=(Z)=>Math.min(yZ,Math.floor(Z/10));class bZ extends I{register(){this.app.singleton(A,()=>new A(U(m(),this.app.config.get("schedule",{}))))}async boot(){let Z=this.app.make(A),$=this.app.config.get("schedule",{});if($.jobs===void 0){let{jobsDir:G}=U(m(),$);Z.useJobs(await XZ(G))}if(process.env.GEMI_NO_SCHEDULE==="1")return;let H=this.app;Z.start((G)=>VZ.run(H,G))}async shutdown(Z){if(!this.app.resolved(A))return;let $=this.app.make(A);if($.running>0)console.log(`[gemi] Shutting down: waiting for ${$.running} running cron tick(s).`);let H=Z?.timeoutMs,{unfinished:G}=await $.drain(H===void 0?1/0:Math.max(0,H-fZ(H)));if(G.length>0)return console.error("[gemi] Cron jobs still running at shutdown: "+G.map((V)=>`${V.name} (started ${V.startedAt.toISOString()})`).join(", ")),{abandoned:!0}}}class N extends zZ{modelName;constructor(Z="FeatureFlag"){super();this.modelName=Z}get available(){return YZ(this.modelName)}async load(){if(!this.available)throw new c(this.modelName);let Z=h(this.modelName);return await Z.asSystem(()=>Z.findMany())}async write(Z,$,H){if(!this.available)throw new c(this.modelName);let G=h(this.modelName),V=this.hasActorColumn(G),X={active:$};if(V)X.updatedBy=H.actor;return await G.asSystem(()=>G.upsert({where:{key:Z},create:{key:Z,...X},update:X})),{actorRecorded:V}}hasActorColumn(Z){let $=Z?.$schema?.fields?.updatedBy;return $!==void 0&&$.type==="String"}}function j3(Z){return Z}function KZ(){return{features:void 0,enabled:!0,source:new N,model:"FeatureFlag",ttl:30,context:void 0,onEvaluate:void 0,maxClientFlags:200}}class gZ extends I{register(){this.app.singleton(j,()=>{let Z=this.app.config.get("features",{}),$=U(KZ(),Z);if(Z?.model!==void 0&&Z?.source===void 0)$.source=new N(Z.model);else if(Z?.model!==void 0&&Z.source instanceof N&&Z.source.modelName!==Z.model)D.warning(`app/config/features.ts sets \`model: "${Z.model}"\` and a source reading "${Z.source.modelName}". The source wins; drop \`model\` to silence this.`);return new j($,(H)=>D.warning(H))})}async boot(){let Z=this.app.make(j);if(!Z.config.enabled)return;try{await Z.refresh()}catch($){D.error(`Could not warm the feature flag cache at boot. ${$ instanceof Error?$.message:String($)}`)}}}class vZ extends I{register(){this.app.singleton(p,()=>new p(this.app.config.get("mail",{})))}}function wZ(Z){return`listener:${Z}`}function IZ(Z,$){mZ(Z);let{maxAttempts:H,backoff:G,worker:V}=$,X=Z.event.name,Y=class extends WZ{maxAttempts=H;backoff=G;worker=V;async run(...z){let[K,B]=hZ(z),J=M(Q).rehydrate(K,B);await new Z().handle(J)}onFail(z){console.error(`The listener ${Z.name} threw while handling ${X} off the queue. The queue will retry it up to ${H} times in total; nothing the dispatcher did is waiting on it.`,z)}onDeadletter(z){console.error(`The listener ${Z.name} failed every one of its ${H} attempts at ${X} and has been dead-lettered, so this side effect did not happen and will not be retried.`,z)}};return Object.defineProperty(Y,"name",{value:wZ(Z.name),writable:!0}),Y}function mZ(Z){if(Object.getOwnPropertyDescriptor(Z,"name")?.writable)return;throw Error(`The listener ${Z.name} sets \`queued = true\` but does not declare \`static name\`, so it would be registered with the queue `+"under its class name \u2014 which a production build renames while the "+`payload that names it does not. Add: static name = "${Z.name}";`)}function hZ(Z){return typeof Z[0]==="string"?Z:Z[0]}class Q{static token="events";listeners={};events={};warnedFor=new Set;warnedAboutWaiting=new Set;config;constructor(Z={}){this.config=U(k(),Z),this.useListeners(this.config.listeners)}useListeners(Z){this.config.listeners=Z,this.listeners={},this.events={};let $=new Set;for(let H of Z){if(!H.event){console.error(`Listener ${H.name} does not declare \`static event\`, so there is no event name to register it under and its handle will never run. Add: static event = SomeEvent;`);continue}if($.has(H.name)){console.error(`Two event listeners are named "${H.name}" \u2014 the first is `+"registered and this one is not. A listener's name identifies it across the framework, so only one class can hold it. Rename one.");continue}$.add(H.name);let G=H.event.name,V=new H;this.events[G]??=H.event,(this.listeners[G]??=[]).push({listener:H,job:V.queued?IZ(H,V):null})}}get queuedListenerJobs(){return Object.values(this.listeners).flat().flatMap(({job:Z})=>Z?[Z]:[])}get registeredListeners(){return[...this.config.listeners]}dispatch(Z,$){if(this.deferToCommit(Z,$,!1))return;this.runListeners(Z,$)}async dispatchAndWait(Z,$){if(this.deferToCommit(Z,$,!0))return;return this.runListeners(Z,$)}deferToCommit(Z,$,H){let{name:G,afterCommit:V}=Z.constructor;if(!V)return!1;let X=JZ(()=>this.runListeners(Z,$));if(X&&H)this.warnNothingIsWaitedFor(G);return X}async runListeners(Z,$){let H=Z.constructor.name,G=this.listeners[H];if(!G?.length){this.warnNothingIsListening(H);return}for(let{listener:V,job:X}of G){if(X){this.enqueue(X,V,H,$);continue}try{await new V().handle(Z)}catch(Y){console.error(`The listener ${V.name} threw while handling ${H}. The `+"listeners after it still ran \u2014 a listener's failure is its own.",Y)}}}rehydrate(Z,$=[]){let H=this.events[Z];if(!H)throw Error(`Cannot rebuild the event "${Z}" that came off the queue: no registered listener binds to an event of that name, so there is no class to construct. A queued listener runs in an application that `+"discovered its own listeners \u2014 check that this process sees the "+`same app/listeners as the one that dispatched, and that the event declares \`static name = "${Z}"\`.`);return new H(...$)}enqueue(Z,$,H,G){if(G===void 0){console.error(`The listener ${$.name} is queued, but ${H} reached the dispatcher without its constructor arguments, so there is nothing for the queue to rebuild it from and the listener was skipped. Dispatch through ${H}.dispatch(...) or ${H}.dispatchAndWait(...), which carry them.`);return}let V=(X)=>console.error(`The listener ${$.name} could not be queued for ${H}, so it did not run and will not be retried. The listeners after it still ran.`,X);try{M(C).push(Z,JSON.stringify([H,G]),{reportFailure:!1}).catch(V)}catch(X){V(X)}}warnNothingIsWaitedFor(Z){if(Bun.env.NODE_ENV==="production")return;if(this.warnedAboutWaiting.has(Z))return;this.warnedAboutWaiting.add(Z),console.warn(`[gemi] ${Z}.dispatchAndWait() was called inside a transaction and ${Z} declares \`static afterCommit = true\`, so it resolved `+"immediately with no listener having run \u2014 they run when the "+"transaction commits. Await the transaction instead, or drop afterCommit if the caller needs the side effects first. Development only.")}warnNothingIsListening(Z){if(Bun.env.NODE_ENV==="production")return;if(this.warnedFor.has(Z))return;this.warnedFor.add(Z),console.warn(`[gemi] ${Z} was dispatched and nothing is listening for it. A listener registers under the name its event declares, so check that app/listeners holds a Listener with \`static event = ${Z}\` and that ${Z} declares \`static name = "${Z}"\`. Development only.`)}}class cZ extends I{register(){this.app.singleton(Q,()=>new Q(this.app.config.get("events",{})))}async boot(){let Z=this.app.make(Q),$=this.app.config.get("events",{});if($.listeners===void 0){let{listenersDir:V}=U(k(),$);Z.useListeners(await UZ(V))}let H=Z.queuedListenerJobs;if(H.length===0)return;let G=this.app.make(C);for(let V of H)G.registerJob(V)}}class pZ extends I{register(){this.app.singleton(u,()=>new u(this.app.config.get("filesystem",{})))}}class uZ extends I{register(){this.app.singleton(d,()=>new d(this.app.config.get("image",{})))}}class dZ extends I{register(){this.app.instance(l,new l)}}function _4(Z){return Z}function BZ(){return{maxFileSize:10485760,onLogFileClosed:()=>{},onLogCreated:()=>{}}}class lZ extends I{register(){this.app.singleton(y,()=>new y(U(BZ(),this.app.config.get("log",{}))))}async boot(){if(!process.env.ROOT_DIR)return;await this.app.make(y).boot()}}class sZ extends I{register(){this.app.singleton(f,()=>new f(U(CZ(),this.app.config.get("middleware",{}))))}boot(){this.app.make(f).assertGlobalMiddleware()}}class s{}function PZ(Z,$){return Math.floor(Z/$)*$}function iZ(Z,$){if($<=0)return 0;return Math.min(1,Math.max(0,($-Z)/$))}function i(Z,$,H,G){return $*iZ(H,G)+Z}function nZ(Z){let{current:$,previous:H,elapsed:G,window:V,limit:X,cost:Y}=Z,z=X-Y;if(z<0)return V;let K=Math.max(0,V-G);if(H>0){let J=V*(1-(z-$)/H);if(J<=V)return Math.max(0,Math.ceil(J-G))}if($<=z)return K;if($<=0)return K;let B=V*(1-z/$);return K+Math.max(0,Math.ceil(B))}function _Z(Z){let{allowed:$,current:H,previous:G,now:V,elapsed:X,window:Y,limit:z,cost:K}=Z;if($){let J=i(H,G,X,Y);return{allowed:!0,limit:z,remaining:Math.max(0,Math.floor(z-J)),resetAt:V-X+Y,retryAfter:0}}let B=nZ({current:H,previous:G,elapsed:X,window:Y,limit:z,cost:K});return{allowed:!1,limit:z,remaining:0,resetAt:V+B,retryAfter:B}}class n extends s{buckets=new Map;maxKeys;constructor(Z={}){super();this.maxKeys=Math.max(1,Z.maxKeys??1e5)}consume(Z){let{key:$,limit:H,window:G}=Z,V=Z.cost??1,X=Date.now(),Y=PZ(X,G),z=X-Y,K=this.roll($,G,Y),J=i(K.current,K.previous,z,G)+V<=H;if(J)K.current+=V;if(this.buckets.delete($),this.buckets.set($,K),this.buckets.size>this.maxKeys)this.evict(X);return _Z({allowed:J,current:K.current,previous:K.previous,now:X,elapsed:z,window:G,limit:H,cost:V})}clear(){this.buckets.clear()}get size(){return this.buckets.size}roll(Z,$,H){let G=this.buckets.get(Z);if(!G||G.window!==$)return{window:$,windowStart:H,current:0,previous:0};if(G.windowStart===H)return G;if(G.windowStart+$===H)return G.previous=G.current,G.current=0,G.windowStart=H,G;return G.previous=0,G.current=0,G.windowStart=H,G}evict(Z){for(let[$,H]of this.buckets)if(Z-H.windowStart>=H.window*2)this.buckets.delete($);for(let $ of this.buckets.keys()){if(this.buckets.size<=this.maxKeys)break;this.buckets.delete($)}}}function f4(Z){return Z}function OZ(){return{driver:new n,limit:1000,window:60}}class oZ extends I{register(){this.app.singleton(o,()=>new o(U(OZ(),this.app.config.get("ratelimiter",{}))))}}function c4(Z){return Z}function qZ(){return{url:process.env.REDIS_URL,options:void 0}}class tZ extends I{register(){this.app.singleton(E,()=>new E(U(qZ(),this.app.config.get("redis",{}))))}shutdown(){if(!this.app.resolved(E))return;this.app.make(E).close()}}class P extends NZ{status;constructor(Z,$){super(Z);this.status=$;this.name="McpToolError"}}var rZ=/^[A-Za-z0-9_-]{1,64}$/,aZ=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,LZ=4000,t=1e5,eZ=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i;class T{dispatcher;static token="router.mcp";plans=new Map;constructor(Z,$){this.dispatcher=$;for(let[H,G]of Object.entries(Z.routes??{}))this.plans.set(H,this.plan(H,G))}list(Z,$){return AZ(Z),this.descriptors($)}descriptors(Z){let $=[];for(let{descriptor:H}of this.plans.values()){if(Z?.names&&!Z.names.includes(H.name))continue;if(Z?.tags&&!H.tags.some((G)=>Z.tags.includes(G)))continue;$.push(H)}return $}async execute(Z,$,H,G){AZ(Z);let V=this.plans.get($);if(!V)throw Error(`McpRegistry: there is no tool named "${$}".`);let{descriptor:X}=V,Y=X.inputSchema.safeParse(H);if(Y.ok===!1)throw new P(`Invalid arguments for "${$}": ${Y.errors.join(", ")}`);let z=Y.value,K=await this.fillPath(V,z,Z.req),{path:B}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${K}`));if(B!==X.url)throw new P(`"${$}" has nothing at ${K}.`,404);let J={};for(let L of V.jsonKeys)if(z[L]!==void 0)J[L]=z[L];let _,O="";if(V.fileFields.length>0)_=await this.formData(V,z,J,G);else if(X.method==="GET")O=G3(J);else if(V.jsonKeys.length>0)_=J;let x;try{x=await this.dispatcher.dispatchAs(Z.req,X.method,O?`${K}?${O}`:K,_)}catch(L){throw console.error(`[gemi/mcp] Dispatching "${$}" failed:`,L),new P(`"${$}" failed on the server.`,500)}return await V3($,x)}plan(Z,$){if(!rZ.test(Z))throw Error(`McpRouter: "${Z}" 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 \u2014 letters, digits, "_" and "-", at most 64.`);let H=`McpRouter: "${Z}" (${$?.method} ${$?.url})`;if(!($ instanceof Object)||$.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${Z}" is not a route. Declare it with this.fromApiRoute(...).`);let{method:G,url:V,meta:X}=$;if(V.startsWith("/__gemi__"))throw Error(`${H} is a framework route, not an app route.`);let Y=this.dispatcher.flatRoutes[V]?.[G];if(!Y)throw Error(`${H} names no route of this app. Expose a route by the path and verb it is mounted at.`);let z=[...V.matchAll(aZ)].map(([,W,q])=>({name:W,modifier:q})),K=X.params??{};for(let W of z)if(!(W.name in K))throw Error(`${H}: the path param "${W.name}" must be bound or declared "input".`);for(let[W,q]of Object.entries(K)){if(!z.some((R)=>R.name===W))throw Error(`${H}: "${W}" in params is not a param of the url.`);QZ(H,`params.${W}`,q)}let B=[],J;if(X.input){if(J=X.input.toJSONSchema(),J.type!=="object"||!J.properties)throw Error(`${H}: input must be an s.object(...), the fields of the request body.`);B=Object.keys(J.properties)}let _=Object.entries(X.files??{}).map(([W,q])=>({name:W,binder:q}));for(let W of _)QZ(H,`files.${W.name}`,W.binder);if(_.length>0&&G==="GET")throw Error(`${H}: a GET has no body to carry a file.`);let O={},x=new Map;for(let W of z){let q=K[W.name];if(q==="input"){let R=b.string().describe(`The ":${W.name}" segment of the url.`);O[W.name]=W.modifier==="?"||W.modifier==="*"?R.optional():R}else x.set(W.name,q)}for(let W of _)if(W.binder==="input")O[W.name]=b.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.");let L=[...Object.keys(O),..._.map((W)=>W.name)];for(let W of new Set(L))if(B.includes(W))throw Error(`${H}: "${W}" is both an input field and a param or file, and the model can only send one.`);return{descriptor:Object.freeze({name:Z,description:X.description,method:G,url:V,inputSchema:$3(X.input,J,b.object(O)),annotations:Z3(G),tags:Object.freeze([...X.tags??[]]),requiresApproval:X.requiresApproval===!0,...Y.source?{source:Y.source}:{}}),params:z,paramBinders:x,fileFields:_,jsonKeys:B}}async fillPath(Z,$,H){let G=Z.descriptor.url;for(let V of Z.params){let X=Z.paramBinders.get(V.name),Y;if(X){if(Y=await this.bind(Z,`the param "${V.name}"`,()=>X(H)),Y===void 0||Y===null||Y==="")throw console.error(`[gemi/mcp] The binder for "${V.name}" of "${Z.descriptor.name}" returned ${JSON.stringify(Y)}.`),new P(`"${Z.descriptor.name}" failed on the server.`,500)}else Y=$[V.name];let z=`:${V.name}${V.modifier}`;if(Y===void 0||Y===null||Y===""){if(V.modifier!=="?"&&V.modifier!=="*")throw new P(`"${V.name}" of "${Z.descriptor.name}" must not be empty.`);G=G.replace(`/${z}`,"");continue}G=G.replace(z,H3(Z.descriptor.name,V,String(Y)))}return G}async formData(Z,$,H,G){let V=Z.descriptor.name;if(!G)throw Error(`McpRegistry: "${V}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let X=new FormData;for(let[Y,z]of Object.entries(H))FZ(X,Y,z);for(let Y of Z.fileFields){let z=Y.binder==="input"?$[Y.name]:await this.bind(Z,`the file "${Y.name}"`,()=>Y.binder(G));if(typeof z!=="string"||z==="")throw new P(`"${V}" needs a file for "${Y.name}", and this turn has none. Ask the user to attach one.`);X.append(Y.name,await G.attachments.file(z))}return X}async bind(Z,$,H){try{return await H()}catch(G){throw console.error(`[gemi/mcp] Binding ${$} of "${Z.descriptor.name}" failed:`,G),new P(`"${Z.descriptor.name}" failed on the server.`,500)}}}function AZ(Z){if(Z?.kind!=="local")throw Error("McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have \u2014 and until it does there is no remote surface to call from.")}function QZ(Z,$,H){if(H!=="input"&&typeof H!=="function")throw Error(`${Z}: ${$} must be a function or "input".`)}function Z3(Z){switch(Z){case"GET":return Object.freeze({readOnlyHint:!0});case"DELETE":return Object.freeze({destructiveHint:!0});case"PUT":return Object.freeze({idempotentHint:!0});default:return Object.freeze({})}}function $3(Z,$,H){let G=H.toJSONSchema(),V={...$??{},type:"object",properties:{...$?.properties??{},...G.properties},required:[...$?.required??[],...G.required??[]],additionalProperties:!1},X=(Y)=>{if(typeof Y!=="object"||Y===null||Array.isArray(Y))return{ok:!1,errors:["expected an object"]};let z=[],K={};if(Z){let J=Z.safeParse(Y);if(J.ok===!1)z.push(...J.errors);else K={...J.value}}let B=H.safeParse(Y);if(B.ok===!1)z.push(...B.errors);else K={...K,...B.value};return z.length>0?{ok:!1,errors:z}:{ok:!0,value:K}};return{toJSONSchema:()=>V,safeParse:X,parse(Y){let z=X(Y);if(z.ok===!1)throw Error(z.errors.join(", "));return z.value}}}function H3(Z,$,H){let G=$.modifier==="*"||$.modifier==="+"?H.split("/"):[H];if(G.some((V)=>V==="."||V===".."))throw new P(`"${H}" is not a valid value for "${$.name}" of "${Z}".`);return G.map(encodeURIComponent).join("/")}function FZ(Z,$,H){if(H===void 0||H===null)return;if(Array.isArray(H)){for(let G of H)FZ(Z,$,G);return}Z.append($,typeof H==="object"?JSON.stringify(H):String(H))}function G3(Z){let $=new URLSearchParams,H=(G,V)=>{if(V===void 0||V===null)return;if(Array.isArray(V)){for(let X of V)H(G,X);return}$.append(G,typeof V==="object"?JSON.stringify(V):String(V))};for(let[G,V]of Object.entries(Z))H(G,V);return $.toString()}async function V3(Z,$){if($.status>=200&&$.status<300){let G=$.headers.get("Content-Type");if(G&&!eZ.test(G)){let X=(await $.arrayBuffer()).byteLength;return`"${Z}" answered with ${X} bytes of ${G}, which is not shown.`}let V=await $.text();if(V==="")return null;if(V.length>t)return`${V.slice(0,t)}\u2026 [cut at ${t} of ${V.length} characters]`;try{return JSON.parse(V)}catch{return V}}let H=await $.text();if($.status>=400&&$.status<500){let G=H.length>LZ?`${H.slice(0,LZ)}\u2026`:H;throw new P(`"${Z}" was refused with ${$.status}${G?`: ${G}`:"."}`,$.status)}if($.status<500)console.error(`[gemi/mcp] "${Z}" answered ${$.status}${$.headers.get("Location")?` to ${$.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new P(`"${Z}" failed on the server.`,$.status)}function g(Z,$){let H=Z.get($);if(!H)throw Error(`Missing "${$}" configuration. Route dispatching needs a root router \u2014 declare it in "app/config/route.ts".`);return H}class X3 extends I{register(){this.app.singleton(F,()=>new F(g(this.app.config,"route.api"))),this.app.singleton(S,()=>new S(g(this.app.config,"route.view"))),this.app.singleton(v,()=>new v({api:this.app.make(F),view:this.app.make(S)},{api:g(this.app.config,"route.api"),view:g(this.app.config,"route.view"),domains:this.app.config.get("route.domains")})),this.app.singleton(T,()=>{let Z=this.app.config.get("route.mcp");if(!Z?.router)throw Error('No MCP router is configured. Declare one as `mcp: { router }` in "app/config/route.ts".');return new T(new Z.router,this.app.make(F))})}boot(){if(this.app.make(F),this.app.make(S),this.app.make(v),this.app.config.get("route.mcp"))this.app.make(T)}}
3
+ export{A as Za,RZ as _a,C3 as $a,kZ as ab,bZ as bb,N as cb,j3 as db,KZ as eb,gZ as fb,vZ as gb,Q as hb,cZ as ib,pZ as jb,uZ as kb,dZ as lb,_4 as mb,BZ as nb,lZ as ob,sZ as pb,PZ as qb,_Z as rb,s as sb,n as tb,f4 as ub,OZ as vb,oZ as wb,c4 as xb,qZ as yb,tZ as zb,P as Ab,T as Bb,X3 as Cb};
4
+
5
+ //# debugId=1CA4FF91BC3E8F2964756E2164756E21