gemi 0.122.0 → 0.124.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 (304) hide show
  1. package/dist/ai/index.js +2 -2
  2. package/dist/ai/index.js.map +1 -1
  3. package/dist/app/App.d.ts +9 -0
  4. package/dist/app/App.d.ts.map +1 -1
  5. package/dist/app/index.js +1 -1
  6. package/dist/auth/AuthController.d.ts.map +1 -1
  7. package/dist/bin/gemi.js +4 -1
  8. package/dist/bin/gemi.js.map +3 -3
  9. package/dist/bun/plugin.js +1 -1
  10. package/dist/bun/preload.js +1 -1
  11. package/dist/{chunk-7ftj43vp.js → chunk-019wz697.js} +2 -2
  12. package/dist/{chunk-7ftj43vp.js.map → chunk-019wz697.js.map} +1 -1
  13. package/dist/{chunk-s5k3yq6t.js → chunk-121p4g9j.js} +2 -2
  14. package/dist/{chunk-s5k3yq6t.js.map → chunk-121p4g9j.js.map} +1 -1
  15. package/dist/{chunk-tewhms9w.js → chunk-17dndh5z.js} +2 -2
  16. package/dist/{chunk-3gsv1vv1.js.map → chunk-17dndh5z.js.map} +1 -1
  17. package/dist/{chunk-r01aqf0q.js → chunk-1qwhty9p.js} +2 -2
  18. package/dist/{chunk-r01aqf0q.js.map → chunk-1qwhty9p.js.map} +1 -1
  19. package/dist/{chunk-471htqmz.js → chunk-1rnh9qrp.js} +2 -2
  20. package/dist/{chunk-471htqmz.js.map → chunk-1rnh9qrp.js.map} +1 -1
  21. package/dist/{chunk-dedqr5wb.js → chunk-2affxmkn.js} +2 -2
  22. package/dist/{chunk-dedqr5wb.js.map → chunk-2affxmkn.js.map} +1 -1
  23. package/dist/{chunk-19dpzp4y.js → chunk-2n4490pk.js} +3 -3
  24. package/dist/{chunk-19dpzp4y.js.map → chunk-2n4490pk.js.map} +1 -1
  25. package/dist/{chunk-9xyxbxgk.js → chunk-30xxc6r7.js} +2 -2
  26. package/dist/{chunk-9xyxbxgk.js.map → chunk-30xxc6r7.js.map} +1 -1
  27. package/dist/{chunk-vx7hvyvq.js → chunk-34fkx6kb.js} +2 -2
  28. package/dist/{chunk-vx7hvyvq.js.map → chunk-34fkx6kb.js.map} +1 -1
  29. package/dist/{chunk-5nj94s66.js → chunk-3hqwz48c.js} +4 -4
  30. package/dist/{chunk-5nj94s66.js.map → chunk-3hqwz48c.js.map} +1 -1
  31. package/dist/{chunk-dhbgrv58.js → chunk-3j6s5bmx.js} +1 -1
  32. package/dist/{chunk-cskqet01.js → chunk-3y294mb8.js} +2 -2
  33. package/dist/{chunk-cskqet01.js.map → chunk-3y294mb8.js.map} +1 -1
  34. package/dist/{chunk-qsz9241c.js → chunk-4drnyymm.js} +2 -2
  35. package/dist/{chunk-qsz9241c.js.map → chunk-4drnyymm.js.map} +1 -1
  36. package/dist/{chunk-zg6hmc48.js → chunk-5e22tm7m.js} +1 -1
  37. package/dist/chunk-5j50q4g8.js +57 -0
  38. package/dist/{chunk-3s21p9n2.js.map → chunk-5j50q4g8.js.map} +19 -9
  39. package/dist/{chunk-0k02tza1.js → chunk-65s834td.js} +1 -1
  40. package/dist/{chunk-7mmw0jr2.js → chunk-675kzd7z.js} +2 -2
  41. package/dist/{chunk-7mmw0jr2.js.map → chunk-675kzd7z.js.map} +1 -1
  42. package/dist/{chunk-gy81nd9a.js → chunk-6bgb1nhq.js} +2 -2
  43. package/dist/{chunk-gy81nd9a.js.map → chunk-6bgb1nhq.js.map} +1 -1
  44. package/dist/chunk-70nnh0y7.js +5 -0
  45. package/dist/{chunk-htgmy3x7.js.map → chunk-70nnh0y7.js.map} +1 -1
  46. package/dist/{chunk-er8acmch.js → chunk-75ewjc4a.js} +2 -2
  47. package/dist/{chunk-er8acmch.js.map → chunk-75ewjc4a.js.map} +1 -1
  48. package/dist/{chunk-2c0s0561.js → chunk-7gfdts60.js} +2 -2
  49. package/dist/{chunk-2c0s0561.js.map → chunk-7gfdts60.js.map} +1 -1
  50. package/dist/{chunk-zefs2b6h.js → chunk-8m2htvjn.js} +2 -2
  51. package/dist/{chunk-zefs2b6h.js.map → chunk-8m2htvjn.js.map} +1 -1
  52. package/dist/{chunk-dwedx1jb.js → chunk-92sk56n0.js} +3 -3
  53. package/dist/{chunk-dwedx1jb.js.map → chunk-92sk56n0.js.map} +1 -1
  54. package/dist/{chunk-yds7zwc3.js → chunk-96a1459v.js} +2 -2
  55. package/dist/{chunk-yds7zwc3.js.map → chunk-96a1459v.js.map} +1 -1
  56. package/dist/{chunk-c7qs1xp3.js → chunk-9tr92nwy.js} +2 -2
  57. package/dist/{chunk-c7qs1xp3.js.map → chunk-9tr92nwy.js.map} +1 -1
  58. package/dist/{chunk-1wnnkde0.js → chunk-a3g7y70h.js} +3 -3
  59. package/dist/{chunk-1wnnkde0.js.map → chunk-a3g7y70h.js.map} +1 -1
  60. package/dist/{chunk-zrcd9hxr.js → chunk-b5afy6k9.js} +2 -2
  61. package/dist/{chunk-zrcd9hxr.js.map → chunk-b5afy6k9.js.map} +1 -1
  62. package/dist/{chunk-c0v61fp5.js → chunk-bnt8kx6x.js} +2 -2
  63. package/dist/{chunk-c0v61fp5.js.map → chunk-bnt8kx6x.js.map} +1 -1
  64. package/dist/{chunk-5tdxbwzg.js → chunk-bt9qv2jj.js} +3 -3
  65. package/dist/{chunk-5tdxbwzg.js.map → chunk-bt9qv2jj.js.map} +1 -1
  66. package/dist/{chunk-y6wt5b6t.js → chunk-c4jnxmf2.js} +1 -1
  67. package/dist/{chunk-ep0baa9g.js → chunk-cfdwsvtx.js} +2 -2
  68. package/dist/{chunk-ep0baa9g.js.map → chunk-cfdwsvtx.js.map} +1 -1
  69. package/dist/{chunk-51w5ktv2.js → chunk-dxfhhw5h.js} +2 -2
  70. package/dist/{chunk-51w5ktv2.js.map → chunk-dxfhhw5h.js.map} +1 -1
  71. package/dist/{chunk-pn2x59ge.js → chunk-f29pktad.js} +3 -3
  72. package/dist/{chunk-pn2x59ge.js.map → chunk-f29pktad.js.map} +1 -1
  73. package/dist/chunk-f4cmz31h.js +58 -0
  74. package/dist/{chunk-3rvn9a76.js.map → chunk-f4cmz31h.js.map} +3 -3
  75. package/dist/{chunk-0ejjgzwc.js → chunk-fn2qfwgx.js} +2 -2
  76. package/dist/{chunk-0ejjgzwc.js.map → chunk-fn2qfwgx.js.map} +1 -1
  77. package/dist/{chunk-pemhmjzp.js → chunk-fvrmptd0.js} +3 -3
  78. package/dist/{chunk-pemhmjzp.js.map → chunk-fvrmptd0.js.map} +1 -1
  79. package/dist/{chunk-qy8c0gzr.js → chunk-fw7ds23a.js} +2 -2
  80. package/dist/{chunk-qy8c0gzr.js.map → chunk-fw7ds23a.js.map} +1 -1
  81. package/dist/{chunk-fenc5tpv.js → chunk-h3p8qzft.js} +2 -2
  82. package/dist/{chunk-fenc5tpv.js.map → chunk-h3p8qzft.js.map} +1 -1
  83. package/dist/{chunk-wjkh2gem.js → chunk-j7v7dft7.js} +1 -1
  84. package/dist/chunk-jctb7v53.js +4 -0
  85. package/dist/chunk-jctb7v53.js.map +10 -0
  86. package/dist/{chunk-wqe47c0j.js → chunk-jys8y39p.js} +2 -2
  87. package/dist/{chunk-wqe47c0j.js.map → chunk-jys8y39p.js.map} +1 -1
  88. package/dist/{chunk-m83zm86m.js → chunk-kc924zjz.js} +2 -2
  89. package/dist/{chunk-m83zm86m.js.map → chunk-kc924zjz.js.map} +1 -1
  90. package/dist/{chunk-32n8t8x6.js → chunk-kzsjyvvc.js} +2 -2
  91. package/dist/{chunk-32n8t8x6.js.map → chunk-kzsjyvvc.js.map} +1 -1
  92. package/dist/{chunk-meg8rtr6.js → chunk-mqtfaqx5.js} +2 -2
  93. package/dist/{chunk-meg8rtr6.js.map → chunk-mqtfaqx5.js.map} +1 -1
  94. package/dist/{chunk-7g649j8h.js → chunk-mrswc6qw.js} +2 -2
  95. package/dist/{chunk-7g649j8h.js.map → chunk-mrswc6qw.js.map} +1 -1
  96. package/dist/{chunk-gc2dz11k.js → chunk-mvkz22p4.js} +2 -2
  97. package/dist/{chunk-gc2dz11k.js.map → chunk-mvkz22p4.js.map} +1 -1
  98. package/dist/{chunk-4acpw92g.js → chunk-n0r5xyk2.js} +3 -3
  99. package/dist/{chunk-4acpw92g.js.map → chunk-n0r5xyk2.js.map} +1 -1
  100. package/dist/{chunk-cca0grq3.js → chunk-n1a2zj5z.js} +2 -2
  101. package/dist/{chunk-cca0grq3.js.map → chunk-n1a2zj5z.js.map} +1 -1
  102. package/dist/{chunk-d5f1m3d2.js → chunk-nkzmk7v3.js} +2 -2
  103. package/dist/{chunk-d5f1m3d2.js.map → chunk-nkzmk7v3.js.map} +1 -1
  104. package/dist/{chunk-3gsv1vv1.js → chunk-nn2jeat2.js} +2 -2
  105. package/dist/{chunk-tewhms9w.js.map → chunk-nn2jeat2.js.map} +1 -1
  106. package/dist/chunk-nnarmbjv.js +5 -0
  107. package/dist/chunk-nnarmbjv.js.map +10 -0
  108. package/dist/{chunk-h43jp8ws.js → chunk-pe46a5a5.js} +2 -2
  109. package/dist/{chunk-h43jp8ws.js.map → chunk-pe46a5a5.js.map} +1 -1
  110. package/dist/{chunk-6yhpprzs.js → chunk-pmyh33v5.js} +2 -2
  111. package/dist/{chunk-6yhpprzs.js.map → chunk-pmyh33v5.js.map} +1 -1
  112. package/dist/{chunk-mr94nfp1.js → chunk-pya4rqm2.js} +3 -3
  113. package/dist/{chunk-mr94nfp1.js.map → chunk-pya4rqm2.js.map} +1 -1
  114. package/dist/{chunk-jaa6xkeh.js → chunk-qdj8ek8z.js} +2 -2
  115. package/dist/{chunk-jaa6xkeh.js.map → chunk-qdj8ek8z.js.map} +1 -1
  116. package/dist/{chunk-0yj0s1pn.js → chunk-qhz0x97z.js} +2 -2
  117. package/dist/{chunk-0yj0s1pn.js.map → chunk-qhz0x97z.js.map} +1 -1
  118. package/dist/chunk-qycwjzsv.js +9 -0
  119. package/dist/chunk-qycwjzsv.js.map +10 -0
  120. package/dist/{chunk-nz8z8jr1.js → chunk-rpyczdta.js} +3 -3
  121. package/dist/{chunk-nz8z8jr1.js.map → chunk-rpyczdta.js.map} +1 -1
  122. package/dist/{chunk-9rr5h818.js → chunk-rtawbqec.js} +3 -3
  123. package/dist/{chunk-9rr5h818.js.map → chunk-rtawbqec.js.map} +1 -1
  124. package/dist/{chunk-3wnghdsx.js → chunk-rttrpjqk.js} +2 -2
  125. package/dist/{chunk-3wnghdsx.js.map → chunk-rttrpjqk.js.map} +1 -1
  126. package/dist/{chunk-m53fgf20.js → chunk-s5jxc63j.js} +3 -3
  127. package/dist/{chunk-m53fgf20.js.map → chunk-s5jxc63j.js.map} +1 -1
  128. package/dist/{chunk-48gmyaxc.js → chunk-sd0c2001.js} +2 -2
  129. package/dist/{chunk-48gmyaxc.js.map → chunk-sd0c2001.js.map} +1 -1
  130. package/dist/chunk-skf89vrv.js +5 -0
  131. package/dist/chunk-skf89vrv.js.map +10 -0
  132. package/dist/chunk-szn2n976.js +24 -0
  133. package/dist/{chunk-2yw4yezc.js.map → chunk-szn2n976.js.map} +3 -3
  134. package/dist/{chunk-gemzbw7f.js → chunk-v2ggafz1.js} +2 -2
  135. package/dist/{chunk-gemzbw7f.js.map → chunk-v2ggafz1.js.map} +1 -1
  136. package/dist/{chunk-rhek27sj.js → chunk-v8v5qfnh.js} +3 -3
  137. package/dist/{chunk-rhek27sj.js.map → chunk-v8v5qfnh.js.map} +1 -1
  138. package/dist/{chunk-d2c3947c.js → chunk-w3812s34.js} +2 -2
  139. package/dist/{chunk-d2c3947c.js.map → chunk-w3812s34.js.map} +1 -1
  140. package/dist/{chunk-tk135gmj.js → chunk-w4z6x54b.js} +3 -3
  141. package/dist/{chunk-tk135gmj.js.map → chunk-w4z6x54b.js.map} +1 -1
  142. package/dist/{chunk-65beps2q.js → chunk-w61sphn5.js} +3 -3
  143. package/dist/{chunk-65beps2q.js.map → chunk-w61sphn5.js.map} +1 -1
  144. package/dist/{chunk-cvr5624r.js → chunk-wbg2tza5.js} +1 -1
  145. package/dist/{chunk-9d2d08qm.js → chunk-y434jc1c.js} +2 -2
  146. package/dist/{chunk-9d2d08qm.js.map → chunk-y434jc1c.js.map} +1 -1
  147. package/dist/{chunk-shfe0b22.js → chunk-ykz38t0t.js} +2 -2
  148. package/dist/{chunk-shfe0b22.js.map → chunk-ykz38t0t.js.map} +1 -1
  149. package/dist/{chunk-krk7mcgm.js → chunk-yzhv93b0.js} +3 -3
  150. package/dist/{chunk-krk7mcgm.js.map → chunk-yzhv93b0.js.map} +1 -1
  151. package/dist/{chunk-rhvc1axc.js → chunk-z5jydj5r.js} +2 -2
  152. package/dist/{chunk-rhvc1axc.js.map → chunk-z5jydj5r.js.map} +1 -1
  153. package/dist/chunk-zmf3vhex.js +10 -0
  154. package/dist/{chunk-dyp0wg9e.js.map → chunk-zmf3vhex.js.map} +8 -4
  155. package/dist/{chunk-sx340k85.js → chunk-zsfwcdqn.js} +2 -2
  156. package/dist/{chunk-sx340k85.js.map → chunk-zsfwcdqn.js.map} +1 -1
  157. package/dist/{chunk-4fx8p02c.js → chunk-zsvav1dk.js} +2 -2
  158. package/dist/{chunk-4fx8p02c.js.map → chunk-zsvav1dk.js.map} +1 -1
  159. package/dist/chunks/{ThemeProvider-BLI4zpLu.js → ThemeProvider-CbOx8IRl.js} +581 -2
  160. package/dist/chunks/ThemeProvider-CbOx8IRl.js.map +1 -0
  161. package/dist/client/auth/useEmailCode.d.ts.map +1 -1
  162. package/dist/client/auth/useSignIn.d.ts.map +1 -1
  163. package/dist/client/auth/useSignOut.d.ts.map +1 -1
  164. package/dist/client/index.d.ts +5 -1
  165. package/dist/client/index.d.ts.map +1 -1
  166. package/dist/client/index.js +216 -8
  167. package/dist/client/index.js.map +1 -1
  168. package/dist/client/init.d.ts +8 -0
  169. package/dist/client/init.d.ts.map +1 -1
  170. package/dist/client/realtime/FakeSocket.d.ts +47 -0
  171. package/dist/client/realtime/FakeSocket.d.ts.map +1 -0
  172. package/dist/client/realtime/RealtimeClient.d.ts +169 -0
  173. package/dist/client/realtime/RealtimeClient.d.ts.map +1 -0
  174. package/dist/client/realtime/RealtimeContext.d.ts +8 -0
  175. package/dist/client/realtime/RealtimeContext.d.ts.map +1 -0
  176. package/dist/client/realtime/useChannelSubscription.d.ts +32 -0
  177. package/dist/client/realtime/useChannelSubscription.d.ts.map +1 -0
  178. package/dist/client/rpc.d.ts +11 -0
  179. package/dist/client/rpc.d.ts.map +1 -1
  180. package/dist/client/useChannel.d.ts +87 -0
  181. package/dist/client/useChannel.d.ts.map +1 -0
  182. package/dist/client/useMutation.d.ts.map +1 -1
  183. package/dist/client/useQuery.d.ts +13 -0
  184. package/dist/client/useQuery.d.ts.map +1 -1
  185. package/dist/config/index.js +1 -1
  186. package/dist/console/run.js +2 -2
  187. package/dist/console/run.js.map +1 -1
  188. package/dist/container/index.js +2 -2
  189. package/dist/container/index.js.map +1 -1
  190. package/dist/database/index.js +2 -2
  191. package/dist/database/index.js.map +1 -1
  192. package/dist/email/index.js +2 -2
  193. package/dist/email/index.js.map +1 -1
  194. package/dist/facades/Broadcast.d.ts +68 -0
  195. package/dist/facades/Broadcast.d.ts.map +1 -0
  196. package/dist/facades/index.d.ts +1 -0
  197. package/dist/facades/index.d.ts.map +1 -1
  198. package/dist/facades/index.js +2 -2
  199. package/dist/facades/index.js.map +1 -1
  200. package/dist/foundation/index.js +2 -2
  201. package/dist/foundation/index.js.map +1 -1
  202. package/dist/gemi.d.ts +19 -6
  203. package/dist/http/ChannelRouter.d.ts +171 -0
  204. package/dist/http/ChannelRouter.d.ts.map +1 -0
  205. package/dist/http/index.d.ts +1 -0
  206. package/dist/http/index.d.ts.map +1 -1
  207. package/dist/http/index.js +2 -2
  208. package/dist/http/index.js.map +1 -1
  209. package/dist/i18n/dictionaryRuntime.js +2 -2
  210. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  211. package/dist/i18n/index.js +2 -2
  212. package/dist/i18n/index.js.map +2 -2
  213. package/dist/kernel/Kernel.d.ts +6 -0
  214. package/dist/kernel/Kernel.d.ts.map +1 -1
  215. package/dist/kernel/index.js +3 -3
  216. package/dist/kernel/index.js.map +5 -6
  217. package/dist/kernel/providers.d.ts +2 -2
  218. package/dist/kernel/providers.d.ts.map +1 -1
  219. package/dist/orm/context.d.ts.map +1 -1
  220. package/dist/orm/index.js +2 -2
  221. package/dist/orm/index.js.map +1 -1
  222. package/dist/server/Server.d.ts.map +1 -1
  223. package/dist/server/httpDev.d.ts +1 -2
  224. package/dist/server/httpDev.d.ts.map +1 -1
  225. package/dist/server/httpProd.d.ts +1 -1
  226. package/dist/server/httpProd.d.ts.map +1 -1
  227. package/dist/server/index.js +2 -2
  228. package/dist/server/index.js.map +3 -3
  229. package/dist/server/shutdown.d.ts +9 -0
  230. package/dist/server/shutdown.d.ts.map +1 -1
  231. package/dist/services/broadcast/BroadcastDriver.d.ts +75 -0
  232. package/dist/services/broadcast/BroadcastDriver.d.ts.map +1 -0
  233. package/dist/services/broadcast/BroadcastEvent.d.ts +67 -0
  234. package/dist/services/broadcast/BroadcastEvent.d.ts.map +1 -0
  235. package/dist/services/broadcast/BroadcastManager.d.ts +148 -0
  236. package/dist/services/broadcast/BroadcastManager.d.ts.map +1 -0
  237. package/dist/services/broadcast/BroadcastServiceProvider.d.ts +26 -0
  238. package/dist/services/broadcast/BroadcastServiceProvider.d.ts.map +1 -0
  239. package/dist/services/broadcast/FakeBroadcastManager.d.ts +45 -0
  240. package/dist/services/broadcast/FakeBroadcastManager.d.ts.map +1 -0
  241. package/dist/services/broadcast/MemoryBroadcastDriver.d.ts +23 -0
  242. package/dist/services/broadcast/MemoryBroadcastDriver.d.ts.map +1 -0
  243. package/dist/services/broadcast/RedisBroadcastDriver.d.ts +155 -0
  244. package/dist/services/broadcast/RedisBroadcastDriver.d.ts.map +1 -0
  245. package/dist/services/broadcast/SocketHub.d.ts +201 -0
  246. package/dist/services/broadcast/SocketHub.d.ts.map +1 -0
  247. package/dist/services/broadcast/brand.d.ts +16 -0
  248. package/dist/services/broadcast/brand.d.ts.map +1 -0
  249. package/dist/services/broadcast/channels.d.ts +77 -0
  250. package/dist/services/broadcast/channels.d.ts.map +1 -0
  251. package/dist/services/broadcast/config.d.ts +106 -0
  252. package/dist/services/broadcast/config.d.ts.map +1 -0
  253. package/dist/services/broadcast/protocol.d.ts +123 -0
  254. package/dist/services/broadcast/protocol.d.ts.map +1 -0
  255. package/dist/services/broadcast/socketTag.d.ts +17 -0
  256. package/dist/services/broadcast/socketTag.d.ts.map +1 -0
  257. package/dist/services/broadcast/types.d.ts +27 -0
  258. package/dist/services/broadcast/types.d.ts.map +1 -0
  259. package/dist/services/broadcast/wire.d.ts +35 -0
  260. package/dist/services/broadcast/wire.d.ts.map +1 -0
  261. package/dist/services/broadcast/workerWarning.d.ts +10 -0
  262. package/dist/services/broadcast/workerWarning.d.ts.map +1 -0
  263. package/dist/services/events/EventManager.d.ts +6 -0
  264. package/dist/services/events/EventManager.d.ts.map +1 -1
  265. package/dist/services/index.d.ts +10 -0
  266. package/dist/services/index.d.ts.map +1 -1
  267. package/dist/services/index.js +9 -9
  268. package/dist/services/index.js.map +4 -3
  269. package/dist/services/queue/WorkerProcess.d.ts.map +1 -1
  270. package/dist/services/queue/work.js +2 -2
  271. package/dist/services/queue/work.js.map +5 -4
  272. package/dist/services/router/config.d.ts +7 -0
  273. package/dist/services/router/config.d.ts.map +1 -1
  274. package/dist/stats/route-table.js +1 -1
  275. package/dist/support/index.js +2 -2
  276. package/dist/support/index.js.map +1 -1
  277. package/dist/testing/Page.d.ts +8 -0
  278. package/dist/testing/Page.d.ts.map +1 -1
  279. package/dist/testing/index.d.ts +2 -0
  280. package/dist/testing/index.d.ts.map +1 -1
  281. package/dist/testing/index.js +174 -8
  282. package/dist/testing/index.js.map +1 -1
  283. package/dist/vitest/index.js +1 -1
  284. package/package.json +1 -1
  285. package/skills/gemi-react-best-practices/SKILL.md +3 -1
  286. package/skills/gemi-react-best-practices/rules/query-live-over-polling.md +56 -0
  287. package/dist/chunk-2n3pgfnb.js +0 -5
  288. package/dist/chunk-2n3pgfnb.js.map +0 -10
  289. package/dist/chunk-2yw4yezc.js +0 -24
  290. package/dist/chunk-3rvn9a76.js +0 -58
  291. package/dist/chunk-3s21p9n2.js +0 -57
  292. package/dist/chunk-dyp0wg9e.js +0 -10
  293. package/dist/chunk-htgmy3x7.js +0 -5
  294. package/dist/chunk-krtybgz1.js +0 -4
  295. package/dist/chunk-krtybgz1.js.map +0 -10
  296. package/dist/chunk-s07v65x6.js +0 -9
  297. package/dist/chunk-s07v65x6.js.map +0 -10
  298. package/dist/chunks/ThemeProvider-BLI4zpLu.js.map +0 -1
  299. /package/dist/{chunk-dhbgrv58.js.map → chunk-3j6s5bmx.js.map} +0 -0
  300. /package/dist/{chunk-zg6hmc48.js.map → chunk-5e22tm7m.js.map} +0 -0
  301. /package/dist/{chunk-0k02tza1.js.map → chunk-65s834td.js.map} +0 -0
  302. /package/dist/{chunk-y6wt5b6t.js.map → chunk-c4jnxmf2.js.map} +0 -0
  303. /package/dist/{chunk-wjkh2gem.js.map → chunk-j7v7dft7.js.map} +0 -0
  304. /package/dist/{chunk-cvr5624r.js.map → chunk-wbg2tza5.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../services/mcp/McpRegistry.ts", "../services/mcp/http/callers.ts", "../services/mcp/http/McpHttpServer.ts", "../services/mcp/http/limits.ts", "../services/mcp/http/protocol.ts", "../services/mcp/http/signedState.ts", "../services/cron/Scheduler.ts", "../services/queue/QueueServiceProvider.ts", "../services/change-feed/ChangeFeedServiceProvider.ts", "../auth/AuthServiceProvider.ts", "../services/cron/ScheduleServiceProvider.ts", "../services/features/sources/DatabaseFeatureFlagSource.ts", "../services/features/config.ts", "../services/features/FeaturesServiceProvider.ts", "../services/email/MailServiceProvider.ts", "../services/encryption/EncryptionServiceProvider.ts", "../services/events/listenerJob.ts", "../services/events/EventManager.ts", "../services/events/EventServiceProvider.ts", "../services/file-storage/FilesystemServiceProvider.ts", "../services/image-optimization/ImageServiceProvider.ts", "../services/kernel-id/KernelIdServiceProvider.ts", "../services/logging/config.ts", "../services/logging/LogServiceProvider.ts", "../services/middleware/MiddlewareServiceProvider.ts", "../services/rate-limiter/config.ts", "../services/rate-limiter/RateLimiterServiceProvider.ts", "../services/redis/config.ts", "../services/redis/RedisServiceProvider.ts", "../services/router/RouteServiceProvider.ts"],
3
+ "sources": ["../services/mcp/McpRegistry.ts", "../services/mcp/http/callers.ts", "../services/mcp/http/McpHttpServer.ts", "../services/mcp/http/limits.ts", "../services/mcp/http/protocol.ts", "../services/mcp/http/signedState.ts", "../services/cron/Scheduler.ts", "../services/queue/QueueServiceProvider.ts", "../services/router/globalMiddleware.ts", "../services/broadcast/SocketHub.ts", "../services/broadcast/BroadcastServiceProvider.ts", "../services/change-feed/ChangeFeedServiceProvider.ts", "../auth/AuthServiceProvider.ts", "../services/cron/ScheduleServiceProvider.ts", "../services/features/sources/DatabaseFeatureFlagSource.ts", "../services/features/config.ts", "../services/features/FeaturesServiceProvider.ts", "../services/email/MailServiceProvider.ts", "../services/encryption/EncryptionServiceProvider.ts", "../services/broadcast/brand.ts", "../services/events/listenerJob.ts", "../services/events/EventManager.ts", "../services/events/EventServiceProvider.ts", "../services/file-storage/FilesystemServiceProvider.ts", "../services/image-optimization/ImageServiceProvider.ts", "../services/kernel-id/KernelIdServiceProvider.ts", "../services/logging/config.ts", "../services/logging/LogServiceProvider.ts", "../services/middleware/MiddlewareServiceProvider.ts", "../services/rate-limiter/config.ts", "../services/rate-limiter/RateLimiterServiceProvider.ts", "../services/redis/config.ts", "../services/redis/RedisServiceProvider.ts", "../services/router/RouteServiceProvider.ts"],
4
4
  "sourcesContent": [
5
5
  "import type { ToolContext } from \"../../ai/Agent\";\nimport type { User } from \"../../auth/types\";\nimport type { ProgressSink } from \"../../http/modelOriginated\";\nimport { safeFetch, type SafeFetchOptions } from \"../../http/safeFetch\";\nimport { ToolError } from \"../../ai/redact\";\nimport { s, type AnySchema, type JSONSchema, type Schema } from \"../../ai/Schema\";\nimport type { RouteSource } from \"../../http/ApiRouter\";\nimport type { HttpRequest } from \"../../http/HttpRequest\";\nimport type {\n McpFileBinder,\n McpMethod,\n McpModelParam,\n McpParamBinder,\n McpResultProjection,\n McpRouteDeclaration,\n McpRouter,\n} from \"../../http/McpRouter\";\nimport type {\n ApiRouteDispatcher,\n DispatchAsOptions,\n DispatchCredentials,\n} from \"../router/ApiRouteDispatcher\";\n\n/**\n * Who a tool call runs as. Always an argument to the registry, never read from\n * ambient state by it.\n *\n * `local` is an agent running in this server, and `req` is the request that\n * started its run — read by `toAgentTools` at the moment the tool executes,\n * not when the tool was built, which is what lets one set of tools serve every\n * user's run.\n *\n * That producer *does* read ambient state, since a run no longer carries a\n * request (see `AgentContext`), and the boundary is what keeps that from\n * mattering here: the registry is handed a caller and dispatches as that\n * caller, so a second producer — a job, a test, the remote transport —\n * supplies one however it likes, and a run with no ambient request is refused\n * by `toAgentTools` before the registry is reached rather than dispatching as\n * nobody.\n * The call is dispatched with that request's credentials, so it runs as that\n * user, through that route's middleware.\n *\n * `remote` is an MCP client over HTTP (#762). `req` is its request to the MCP\n * endpoint, and `principal` is what a caller resolver made of the credential\n * it carried — an OAuth access token or an app API key — after verifying it.\n * Nothing of the request's own credentials is forwarded: the call is\n * dispatched as `principal.user`, set on the route's request context before\n * its middleware runs, so `auth`, policies and the route's own checks decide\n * exactly as they would for that user's direct request. See\n * `ApiRouteDispatcher.dispatchAs`'s `identity`.\n */\nexport type McpCaller =\n | { kind: \"local\"; req: HttpRequest<any, any> }\n | { kind: \"remote\"; req: HttpRequest<any, any>; principal: McpRemotePrincipal };\n\n/**\n * A remote caller, as a resolver verified it.\n *\n * Built only by a resolver, from a credential it checked — never from what a\n * client says about itself.\n */\nexport type McpRemotePrincipal = {\n /** The user every call runs as. */\n user: User;\n /** Which resolver vouched for the credential: `\"oauth\"`, `\"api-key\"`, or an app's own. */\n via: string;\n /**\n * A stable id for the credential: the OAuth grant, the API key. Not the\n * secret itself. Keys the rate-limit budget the caller's tool calls spend,\n * and is what a log line names.\n */\n id: string;\n /** The scopes the credential carries. Decides which tools the caller sees. */\n scopes: readonly string[];\n /** The OAuth client the token was issued to, when there is one. */\n clientId?: string;\n};\n\n/**\n * One scope a remote credential can carry, as an `McpRouter` declares it: the\n * tools it reaches, by tag and by name, and the sentence a consent screen\n * shows for it.\n */\nexport type McpScope = {\n /** What a user is agreeing to, in their words: \"Read and edit your site's pages\". */\n description: string;\n /** Every tool carrying one of these tags. */\n tags?: readonly string[];\n /** These tools, by name. */\n names?: readonly string[];\n};\n\n/**\n * The scope a router without `scopes` gets: every tool it declares. A router\n * that wants a credential to reach only some of them declares its own.\n */\nexport const DEFAULT_MCP_SCOPE = \"mcp\";\n\n/** RFC 6749's scope-token: printable ASCII, no space, `\"` or `\\`. */\nconst SCOPE_TOKEN = /^[\\x21\\x23-\\x5B\\x5D-\\x7E]+$/;\n\n/** How a remote caller's file arguments are read. */\nexport type McpRemoteFileOptions = {\n /** The largest file accepted, in bytes, decoded. Default 10 MiB. */\n maxBytes?: number;\n /**\n * Lets a remote caller name a file by an `https` URL, fetched through\n * `safeFetch` — public addresses only, no credentials sent, bounded in size\n * and time. Off by default: a URL argument makes the server fetch whatever\n * the model was steered to name. `true` takes `safeFetch`'s defaults; an\n * object is passed to it (`allow` a list of hosts, say), with `maxSize`\n * capped at `maxBytes`.\n */\n fetchUrls?: boolean | SafeFetchOptions;\n};\n\n/** What `McpRegistry` takes beside the router and the dispatcher. */\nexport type McpRegistryOptions = {\n /** Remote callers' file arguments. See `McpRemoteFileOptions`. */\n files?: McpRemoteFileOptions;\n};\n\n/** What `execute` takes beside the call itself. */\nexport type McpExecuteOptions = {\n /**\n * That the user approved this call, for a tool with `requiresApproval`.\n * The remote transport sets it after an elicitation the user accepted; a\n * remote call to such a tool without it is refused, so a transport that\n * forgot to ask fails closed. Local calls are approved by the agent loop\n * before `execute` is reached, and ignore it.\n */\n approved?: boolean;\n /** Aborts the dispatched route: its `req.signal`. The client went away, or cancelled. */\n signal?: AbortSignal;\n /** Receives the route's `req.reportProgress` reports. */\n progress?: ProgressSink;\n};\n\n/**\n * One tool call, as the app's hooks see it: who is calling, the request their\n * identity comes from, which tool, its parsed arguments, and — for a call an\n * agent run makes — the run's tool context.\n *\n * `req` is `caller.req`, repeated so a hook that only wants the request does\n * not have to narrow the caller. For a remote caller it is the request to the\n * MCP endpoint, run inside a request context whose user is\n * `caller.principal.user`, so `req.ctx().user` names the same user for both\n * callers. `ctx` is absent for a remote caller, and when `McpRegistry.execute`\n * is called without one (a test, a script dispatching a tool directly).\n */\nexport type McpCallContext = {\n caller: McpCaller;\n req: HttpRequest<any, any>;\n tool: McpToolDescriptor;\n input: Record<string, unknown>;\n ctx?: ToolContext;\n};\n\n/**\n * What `McpRouter.credentials` answers for a call: the app's own headers and\n * cookies, sent beside gemi's access token. See `DispatchCredentials`.\n */\nexport type McpCredentials = DispatchCredentials;\n\n/**\n * MCP's tool annotations. They drive confirmation prompts in remote clients,\n * which is why they are set from v1 on rather than when the remote caller\n * lands: every app would otherwise have to revisit its MCP file to get them.\n *\n * The verb sets the defaults, and only what it says: GET is read-only, DELETE\n * destructive, PUT idempotent. POST and PATCH carry nothing, and MCP's\n * defaults for an unannotated tool — not read-only, possibly destructive — are\n * the honest answer for them. A route meta's `annotations` overrides them hint\n * by hint (#760), `false` included.\n *\n * `destructiveHint` and `idempotentHint` only mean something for a tool that\n * is not read-only, so a tool left read-only with either set is refused at\n * boot: one of the two is a mistake, and a client would read the wrong one.\n */\nexport type McpToolAnnotations = {\n readOnlyHint?: boolean;\n destructiveHint?: boolean;\n idempotentHint?: boolean;\n /** Whether the tool reaches beyond the app's own data — a third-party API, the web. */\n openWorldHint?: boolean;\n};\n\n/**\n * One tool, described without committing to who consumes it.\n *\n * The registry's native output. An in-process agent projects it to an\n * `AgentTool` (`toAgentTools`); v2's `tools/list` will project it to JSON.\n * Emitting `AgentTool`s here instead would leave v2 reversing JSON Schema back\n * out of them.\n */\nexport interface McpToolDescriptor {\n /** The `routes` key, verbatim. See `McpRouter`. */\n readonly name: string;\n readonly description: string;\n readonly method: McpMethod;\n /** The route's path as declared, params unfilled. */\n readonly url: string;\n /**\n * What the model fills in: the declared `input`, plus a string for every\n * `\"input\"` path param and every `\"input\"` file field, and the model-facing\n * field of every `this.param(...)` (#767), under its own name and schema.\n * Bound params and bound files are not in it at all, and neither is the raw\n * name of a param the model names in its own terms.\n */\n readonly inputSchema: Schema<Record<string, unknown>>;\n /**\n * The route meta's `output`: the shape of what the tool answers, after\n * `result`. Absent when the meta declares none. v2's `tools/list` emits it\n * as `outputSchema`.\n */\n readonly outputSchema?: AnySchema;\n /** The meta's `title`: a name for a client to show. Absent when it declares none. */\n readonly title?: string;\n readonly annotations: Readonly<McpToolAnnotations>;\n readonly tags: readonly string[];\n readonly requiresApproval: boolean;\n /** The controller method mounted at the route, when there is one (#502). */\n readonly source?: RouteSource;\n}\n\n/**\n * Narrows `list`. Data rather than a predicate, because v2's per-token\n * visibility will come from a token's grants, which are data. Both fields\n * narrow: `names` keeps only those tools, `tags` keeps tools carrying at least\n * one of them.\n */\nexport type McpToolFilter = {\n names?: readonly string[];\n tags?: readonly string[];\n};\n\n/**\n * A failure the model is meant to read: a 4xx from the route, a missing file,\n * a bad argument. v2 turns it into `isError: true` rather than a protocol\n * error. Anything else thrown from `execute` is the caller's mistake or the\n * server's, not the model's.\n */\nexport class McpToolError extends ToolError {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"McpToolError\";\n }\n}\n\n/**\n * A remote call the transport must not run as asked: a tool the caller cannot\n * see, or one that needs the user's approval and does not have it. Not a\n * `ToolError` — it is the transport's to handle, not the model's to read.\n */\nexport class McpCallRefusedError extends Error {\n constructor(\n message: string,\n readonly reason: \"unknown-tool\" | \"approval-required\",\n ) {\n super(message);\n this.name = \"McpCallRefusedError\";\n }\n}\n\n/** Tool names as OpenAI's function tools and MCP clients both accept them. */\nconst TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;\n\n/** `:name`, with URLPattern's modifiers. */\nconst PATH_PARAM = /:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g;\n\n/**\n * A 4xx body goes to the model verbatim, so a validation error can be fixed on\n * the next step — but a route that answers a 4xx with a page of HTML should not\n * be able to fill the context window with it.\n */\nconst MAX_ERROR_BODY = 4000;\n\n/**\n * The same limit for a success, set higher: a list route answering every row,\n * or a route serving a large text file, would otherwise land in the context\n * window whole. Past it the model gets the text cut short and told so, rather\n * than an error — the route has already done what it does, and a model told it\n * failed would do it again.\n */\nconst MAX_RESULT_BODY = 100_000;\n\n/** A body a model can read. A missing content-type is read as text. */\nconst READABLE = /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml))/i;\n\ntype PathParam = { name: string; modifier: string };\n\ntype Plan = {\n descriptor: McpToolDescriptor;\n /**\n * The same tool as a remote caller sees it: its `\"input\"` files are a file\n * object (`name`, `mimeType`, and base64 `data` or a `url`) rather than an\n * attachment id, since a remote client has no attachment store. `null` when\n * the tool cannot be called remotely at all — it has a bound file, whose\n * binder needs the run's tool context.\n */\n remote: McpToolDescriptor | null;\n params: PathParam[];\n paramBinders: Map<string, McpParamBinder>;\n /** Params the model names in its own terms: the input key, and the resolver. */\n modelParams: Map<string, { key: string; param: McpModelParam<any, any> }>;\n fileFields: { name: string; binder: McpFileBinder | \"input\" }[];\n jsonKeys: string[];\n result?: McpResultProjection;\n};\n\n/**\n * The tools an app's `McpRouter` declares, resolved against the api route\n * table, and the one place a call to them is dispatched.\n *\n * Built once, at boot, from the dispatcher's flat route table — so a route\n * that was renamed or unmounted fails the boot here, and at compile time\n * before that, rather than the first model that calls it.\n *\n * THE INVARIANT: a tool call can do nothing its caller could not do with a\n * direct HTTP request. `execute` builds a request and hands it to\n * `ApiRouteDispatcher.dispatchAs`, which runs the route's middleware, auth and\n * policies exactly as for a client. It never reaches for a flat entry's\n * `exec`, which is the handler alone — no auth, no policies, no rate limit —\n * and is the shorter path for exactly that reason.\n */\nexport class McpRegistry<R extends McpRouter<any> = McpRouter<any>> {\n static token = \"router.mcp\";\n\n /**\n * Types only, never set: the app's router, which a typed `toAgentTools`\n * reads its tools' names, inputs and outputs from (#771). The container\n * answers an untyped registry; name the router where the tools are built:\n * `app(McpRegistry) as McpRegistry<SiteMcpRouter>`.\n */\n declare readonly __router?: R;\n\n private readonly plans = new Map<string, Plan>();\n /** Each scope, resolved to the names of the tools it reaches. */\n private readonly scopeTools = new Map<string, { description: string; tools: Set<string> }>();\n private readonly files: { maxBytes: number; fetch: SafeFetchOptions | null };\n\n constructor(\n private readonly router: McpRouter<any>,\n private readonly dispatcher: Pick<\n ApiRouteDispatcher,\n \"flatRoutes\" | \"dispatchAs\" | \"getRouteHandlerAndParams\"\n >,\n options: McpRegistryOptions = {},\n ) {\n this.files = remoteFileOptions(options.files);\n for (const [name, declaration] of Object.entries(router.routes ?? {})) {\n this.plans.set(name, this.plan(name, declaration));\n }\n this.resolveScopes();\n }\n\n /**\n * The tools `caller` may see, narrowed by `filter`.\n *\n * A local caller sees every declared tool. A remote one sees the tools a\n * scope it carries reaches, as it can call them (see `Plan.remote`): a\n * credential that carries no scope sees nothing, and a tool no scope reaches\n * is never listed remotely. Visibility is checked again by `execute`, so a\n * client naming a tool it was not shown gets what it would for a tool that\n * does not exist.\n */\n list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[] {\n assertCaller(caller);\n if (caller.kind === \"local\") return this.descriptors(filter);\n const out: McpToolDescriptor[] = [];\n for (const [name, plan] of this.plans) {\n if (!plan.remote || !this.grants(caller.principal, name)) continue;\n if (passes(plan.remote, filter)) out.push(plan.remote);\n }\n return out;\n }\n\n /**\n * The same listing without a caller, for a projection built once before any\n * caller exists — `toAgentTools`. It is not per-caller visibility, and a\n * remote listing must go through `list`.\n */\n descriptors(filter?: McpToolFilter): McpToolDescriptor[] {\n const out: McpToolDescriptor[] = [];\n for (const { descriptor } of this.plans.values()) {\n if (passes(descriptor, filter)) out.push(descriptor);\n }\n return out;\n }\n\n /** The largest file a remote caller may send, in bytes. */\n get maxFileBytes(): number {\n return this.files.maxBytes;\n }\n\n /**\n * The scopes a remote credential can carry, with what each one is for —\n * what a consent screen lists and the authorization server advertises. The\n * router's `scopes`, or `DEFAULT_MCP_SCOPE` reaching every tool when it\n * declares none.\n */\n scopes(): { name: string; description: string }[] {\n return [...this.scopeTools].map(([name, { description }]) => ({ name, description }));\n }\n\n /**\n * The scopes that reach the tool `name`: what a client missing all of them\n * has to ask for. Empty for a tool no scope reaches, or none by that name.\n */\n scopesFor(name: string): string[] {\n return [...this.scopeTools].filter(([, { tools }]) => tools.has(name)).map(([scope]) => scope);\n }\n\n /**\n * Calls the tool `name` as `caller`, and answers the route's JSON.\n *\n * Before dispatching, the router's `credentials` hook, when it has one, is\n * asked for the app's own headers and cookies for this call; they ride\n * beside the access token (see `McpRouter.credentials`). A throw from it is a\n * server failure, logged for the app, like a binder's.\n *\n * `ctx` is the tool context of the agent call, and only files need it:\n * `\"input\"` files resolve through `ctx.attachments`, the handle already\n * scoped to the caller, and bound files are chosen by a binder given `ctx`.\n * Nothing here reads an attachment any other way — the store has no\n * unscoped lookup, and this must not become one.\n *\n * A remote caller has neither a tool context nor attachments. It is held to\n * the tools its scopes reach, and to `requiresApproval` (see\n * `McpExecuteOptions.approved`): either refusal is an\n * `McpCallRefusedError`, for the transport. Its files arrive in the\n * arguments, as base64 or — when the app allows it — an `https` URL.\n *\n * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body\n * that is neither — a file a route serves — is described, not shown. A tool\n * whose meta has a `result` or an `output` answers its JSON put through\n * them instead, and is cut after that, not before (see `project`).\n * A 4xx throws an `McpToolError` carrying the route's body, so a validation\n * error reaches the model word for word. Anything else, or a route that\n * throws, throws an `McpToolError` that says only that the server failed.\n * The app gets the reason in its log, and a stack trace or a database\n * message is not something to hand a model that may be steered by whoever\n * wrote the document it is reading.\n */\n async execute(\n caller: McpCaller,\n name: string,\n args: unknown,\n ctx?: ToolContext,\n options: McpExecuteOptions = {},\n ): Promise<unknown> {\n assertCaller(caller);\n const found = this.plans.get(name);\n if (caller.kind === \"remote\") {\n // Worded like a tool that does not exist, so a client cannot tell a\n // tool it may not see from one there is none of.\n if (!found?.remote || !this.grants(caller.principal, name)) {\n throw new McpCallRefusedError(`There is no tool named \"${name}\".`, \"unknown-tool\");\n }\n if (found.descriptor.requiresApproval && options.approved !== true) {\n throw new McpCallRefusedError(\n `\"${name}\" needs the user's approval, and this call does not have it.`,\n \"approval-required\",\n );\n }\n // Never handed to a remote call, even if a transport passed one: its\n // attachments are scoped to somebody's run, not to this caller.\n ctx = undefined;\n }\n if (!found) {\n throw new Error(`McpRegistry: there is no tool named \"${name}\".`);\n }\n const plan = found;\n const descriptor = caller.kind === \"remote\" ? plan.remote! : plan.descriptor;\n\n const parsed = descriptor.inputSchema.safeParse(args);\n if (parsed.ok === false) {\n throw new McpToolError(`Invalid arguments for \"${name}\": ${parsed.errors.join(\", \")}`);\n }\n const input = parsed.value;\n\n const call: McpCallContext = { caller, req: caller.req, tool: descriptor, input, ctx };\n const path = await this.fillPath(plan, call);\n\n // The dispatcher routes `path` afresh and takes the first route that\n // matches it, so a model's \"archive-all\" for `/products/:id` would reach a\n // `/products/archive-all` declared above it — a route the app never\n // exposed, behind none of this tool's approval or annotations.\n const { path: matched } = this.dispatcher.getRouteHandlerAndParams(\n new Request(`http://gemi.internal/api${path}`),\n );\n if (matched !== descriptor.url) {\n throw new McpToolError(`\"${name}\" has nothing at ${path}.`, 404);\n }\n\n const json: Record<string, unknown> = {};\n for (const key of plan.jsonKeys) {\n if (input[key] !== undefined) json[key] = input[key];\n }\n\n let body: FormData | Record<string, unknown> | undefined;\n let query = \"\";\n if (plan.fileFields.length > 0) {\n body = await this.formData(plan, json, call);\n } else if (descriptor.method === \"GET\") {\n query = toQuery(json);\n } else if (plan.jsonKeys.length > 0) {\n body = json;\n }\n\n const credentials = this.router.credentials\n ? await this.bind(plan, \"the credentials\", () => this.router.credentials!(call))\n : undefined;\n\n // A remote caller is dispatched as the user its resolver verified, and\n // nothing of its own request's credentials crosses over: its bearer token\n // is for this server's MCP endpoint, and passing it on would be the token\n // passthrough the MCP authorization spec forbids.\n const dispatchOptions: DispatchAsOptions = {\n ...(credentials ? { credentials } : {}),\n ...(options.signal ? { signal: options.signal } : {}),\n ...(options.progress ? { progress: options.progress } : {}),\n ...(caller.kind === \"remote\"\n ? {\n identity: {\n user: caller.principal.user,\n grant: {\n via: caller.principal.via,\n id: caller.principal.id,\n scopes: caller.principal.scopes,\n ...(caller.principal.clientId ? { clientId: caller.principal.clientId } : {}),\n },\n },\n }\n : {}),\n };\n\n let response: Response;\n try {\n const target = query ? `${path}?${query}` : path;\n response =\n Object.keys(dispatchOptions).length > 0\n ? await this.dispatcher.dispatchAs(\n caller.req,\n descriptor.method,\n target,\n body,\n dispatchOptions,\n )\n : await this.dispatcher.dispatchAs(caller.req, descriptor.method, target, body);\n } catch (error) {\n // What a client would get as a 500. A handler's throw is logged by the\n // dispatcher too, but dispatchAs's own refusal of the path is not.\n console.error(`[gemi/mcp] Dispatching \"${name}\" failed:`, error);\n throw new McpToolError(`\"${name}\" failed on the server.`, 500);\n }\n if (!plan.result && !descriptor.outputSchema) {\n return await readResponse(name, response);\n }\n return await this.project(plan, call, response);\n }\n\n // --- building ------------------------------------------------------------\n\n private plan(name: string, declaration: McpRouteDeclaration): Plan {\n if (!TOOL_NAME.test(name)) {\n throw new Error(\n `McpRouter: \"${name}\" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim — letters, digits, \"_\" and \"-\", at most 64.`,\n );\n }\n const where = `McpRouter: \"${name}\" (${declaration?.method} ${declaration?.url})`;\n if (!(declaration instanceof Object) || declaration.__internal_brand !== \"McpRoute\") {\n throw new Error(\n `McpRouter: \"${name}\" is not a route. Declare it with this.fromApiRoute(...).`,\n );\n }\n const { method, url, meta } = declaration;\n if (url.startsWith(\"/__gemi__\")) {\n throw new Error(`${where} is a framework route, not an app route.`);\n }\n\n const entry = this.dispatcher.flatRoutes[url]?.[method];\n if (!entry) {\n throw new Error(\n `${where} names no route of this app. Expose a route by the path and verb it is mounted at.`,\n );\n }\n\n // Mirrors the compile-time check, for a router written in JavaScript or\n // behind a cast: a param left undeclared would otherwise be the model's.\n const params: PathParam[] = [...url.matchAll(PATH_PARAM)].map(([, param, modifier]) => ({\n name: param,\n modifier,\n }));\n const declared = meta.params ?? {};\n for (const param of params) {\n if (!(param.name in declared)) {\n throw new Error(\n `${where}: the path param \"${param.name}\" must be bound or declared \"input\".`,\n );\n }\n }\n for (const [key, binder] of Object.entries(declared)) {\n if (!params.some((param) => param.name === key)) {\n throw new Error(`${where}: \"${key}\" in params is not a param of the url.`);\n }\n if (isModelParam(binder)) {\n assertModelParam(where, `params.${key}`, binder);\n } else {\n assertBinder(where, `params.${key}`, binder);\n }\n }\n\n let jsonKeys: string[] = [];\n let base: JSONSchema | undefined;\n if (meta.input) {\n base = meta.input.toJSONSchema();\n if (base.type !== \"object\" || !base.properties) {\n throw new Error(\n `${where}: input must be an s.object(...), the fields of the request body.`,\n );\n }\n jsonKeys = Object.keys(base.properties);\n }\n\n const fileFields = Object.entries(meta.files ?? {}).map(([field, binder]) => ({\n name: field,\n binder,\n }));\n for (const file of fileFields) {\n assertBinder(where, `files.${file.name}`, file.binder);\n }\n if (meta.result !== undefined && typeof meta.result !== \"function\") {\n throw new Error(`${where}: result must be a function.`);\n }\n if (meta.output !== undefined && typeof meta.output?.safeParse !== \"function\") {\n throw new Error(`${where}: output must be a schema, built with s.`);\n }\n if (meta.title !== undefined && (typeof meta.title !== \"string\" || meta.title === \"\")) {\n throw new Error(`${where}: title must be a non-empty string.`);\n }\n const annotations = annotationsFor(where, method, meta.annotations);\n if (fileFields.length > 0 && method === \"GET\") {\n throw new Error(`${where}: a GET has no body to carry a file.`);\n }\n\n const extras: Record<string, AnySchema> = {};\n // Two params, or a param and a file, can name the same input key only by\n // a `this.param` `as`; the model could send one value for both.\n const addExtra = (key: string, schema: AnySchema) => {\n if (key in extras) {\n throw new Error(\n `${where}: \"${key}\" is the input key of two params or files, and the model can only send one.`,\n );\n }\n extras[key] = schema;\n };\n const paramBinders = new Map<string, McpParamBinder>();\n const modelParams = new Map<string, { key: string; param: McpModelParam<any, any> }>();\n for (const param of params) {\n const binder = declared[param.name];\n if (binder === \"input\") {\n const field = s.string().describe(`The \":${param.name}\" segment of the url.`);\n addExtra(\n param.name,\n param.modifier === \"?\" || param.modifier === \"*\" ? field.optional() : field,\n );\n } else if (isModelParam(binder)) {\n const key = binder.as ?? param.name;\n addExtra(key, binder.input);\n modelParams.set(param.name, { key, param: binder });\n } else {\n paramBinders.set(param.name, binder);\n }\n }\n // A remote caller sends what a local one sends, except for its files: it\n // has no attachments to name, so it sends the file itself.\n const remoteFiles: Record<string, AnySchema> = {};\n for (const file of fileFields) {\n if (file.binder === \"input\") {\n addExtra(\n file.name,\n s\n .string()\n .describe(\n \"The id of an attachment the user uploaded or a tool produced (gemi_att_…), whose file is sent as this field.\",\n ),\n );\n remoteFiles[file.name] = this.remoteFileSchema();\n }\n }\n // A bound file is not the model's, but it shares the form with the input,\n // so it collides all the same.\n const bodyKeys = [...Object.keys(extras), ...fileFields.map((file) => file.name)];\n for (const key of new Set(bodyKeys)) {\n if (jsonKeys.includes(key)) {\n throw new Error(\n `${where}: \"${key}\" is both an input field and a param or file, and the model can only send one.`,\n );\n }\n }\n\n const descriptor: McpToolDescriptor = Object.freeze({\n name,\n description: meta.description,\n method,\n url,\n inputSchema: combineSchemas(meta.input, base, s.object(extras)),\n ...(meta.output ? { outputSchema: meta.output } : {}),\n ...(meta.title ? { title: meta.title } : {}),\n annotations,\n tags: Object.freeze([...(meta.tags ?? [])]),\n requiresApproval: meta.requiresApproval === true,\n ...(entry.source ? { source: entry.source } : {}),\n });\n const remotelyCallable = fileFields.every((file) => file.binder === \"input\");\n const remote = !remotelyCallable\n ? null\n : fileFields.length === 0\n ? descriptor\n : Object.freeze({\n ...descriptor,\n inputSchema: combineSchemas(\n meta.input,\n base,\n s.object(withoutKeys(extras, Object.keys(remoteFiles))),\n remoteFiles,\n ),\n });\n\n return {\n descriptor,\n remote,\n params,\n paramBinders,\n modelParams,\n fileFields,\n jsonKeys,\n ...(meta.result ? { result: meta.result } : {}),\n };\n }\n\n /**\n * What a remote caller sends for a file field: `{ name, mimeType, data }`,\n * or `{ name, mimeType, url }` when the app fetches URLs.\n *\n * Built by hand, as `combineSchemas` is, rather than with `s`: `s` writes\n * the strict structured-output form, where an optional field is a required\n * one that may be `null`, and an MCP client validating its arguments\n * against that would demand `data` and `url` both. Exactly one of the two is\n * checked when the file is read (`remoteFile`), where the refusal can say\n * so.\n */\n private remoteFileSchema(): AnySchema {\n const { maxBytes, fetch } = this.files;\n // `contentEncoding` and `format` are JSON Schema 2020-12 keywords the\n // builder's own type does not name; they are hints for the client.\n const properties: Record<string, JSONSchema & Record<string, unknown>> = {\n name: { type: \"string\", description: \"The file's name, like report.pdf.\" },\n mimeType: { type: \"string\", description: \"The file's media type, like application/pdf.\" },\n data: {\n type: \"string\",\n contentEncoding: \"base64\",\n description: `The file's bytes, base64-encoded (RFC 4648, standard alphabet). At most ${maxBytes} bytes decoded.`,\n },\n };\n if (fetch) {\n properties.url = {\n type: \"string\",\n format: \"uri\",\n description: \"An https URL the server downloads the file from, instead of data.\",\n };\n }\n const json: JSONSchema = {\n type: \"object\",\n description: fetch\n ? \"A file, sent as base64 in data or fetched from url: exactly one of the two.\"\n : \"A file, sent as base64 in data.\",\n properties,\n required: [\"name\", \"mimeType\"],\n additionalProperties: false,\n };\n const keys = Object.keys(properties);\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"a file must be an object\"] };\n }\n const errors: string[] = [];\n const out: Record<string, string> = {};\n for (const key of Object.keys(value)) {\n if (!keys.includes(key)) errors.push(`a file has no field \"${key}\"`);\n }\n for (const key of keys) {\n const field = (value as Record<string, unknown>)[key];\n if (field === undefined || field === null) {\n if (key === \"name\" || key === \"mimeType\") errors.push(`a file needs \"${key}\"`);\n continue;\n }\n if (typeof field !== \"string\") errors.push(`a file's \"${key}\" must be a string`);\n else out[key] = field;\n }\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as AnySchema;\n }\n\n // --- calling -------------------------------------------------------------\n\n private async fillPath(plan: Plan, call: McpCallContext): Promise<string> {\n const { input, req } = call;\n let path = plan.descriptor.url;\n for (const param of plan.params) {\n const binder = plan.paramBinders.get(param.name);\n const modelParam = plan.modelParams.get(param.name);\n let value: unknown;\n if (binder || modelParam) {\n value = modelParam\n ? await this.bind(\n plan,\n `the param \"${param.name}\"`,\n () => modelParam.param.bind(input[modelParam.key], req, call),\n { refusals: true },\n )\n : await this.bind(plan, `the param \"${param.name}\"`, () => binder!(req, call));\n if (value === undefined || value === null || value === \"\") {\n console.error(\n `[gemi/mcp] The ${modelParam ? \"resolver\" : \"binder\"} for \"${param.name}\" of \"${plan.descriptor.name}\" returned ${JSON.stringify(value)}.`,\n );\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n } else {\n value = input[param.name];\n }\n\n const token = `:${param.name}${param.modifier}`;\n if (value === undefined || value === null || value === \"\") {\n if (param.modifier !== \"?\" && param.modifier !== \"*\") {\n throw new McpToolError(`\"${param.name}\" of \"${plan.descriptor.name}\" must not be empty.`);\n }\n path = path.replace(`/${token}`, \"\");\n continue;\n }\n path = path.replace(token, encodeSegment(plan.descriptor.name, param, String(value)));\n }\n return path;\n }\n\n private async formData(\n plan: Plan,\n json: Record<string, unknown>,\n call: McpCallContext,\n ): Promise<FormData> {\n const { input, ctx } = call;\n const name = plan.descriptor.name;\n if (call.caller.kind === \"remote\") {\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n form.append(field.name, await this.remoteFile(name, field.name, input[field.name]));\n }\n return form;\n }\n if (!ctx) {\n throw new Error(\n `McpRegistry: \"${name}\" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`,\n );\n }\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n const id =\n field.binder === \"input\"\n ? (input[field.name] as string)\n : await this.bind(plan, `the file \"${field.name}\"`, () =>\n (field.binder as McpFileBinder)(ctx, call),\n );\n if (typeof id !== \"string\" || id === \"\") {\n throw new McpToolError(\n `\"${name}\" needs a file for \"${field.name}\", and this turn has none. Ask the user to attach one.`,\n );\n }\n // Scoped to the caller: someone else's id is a not-found, worded like an\n // invented one, and that error is what the model reads.\n form.append(field.name, await ctx.attachments.file(id));\n }\n return form;\n }\n\n /**\n * A remote caller's file argument, as a `File`: its base64 `data` decoded,\n * or its `url` fetched through `safeFetch` when the app allows that. Every\n * refusal is the model's to read and correct — a file too large, data that\n * is not base64, a URL that is not `https` or not reachable — since it is\n * about what the model sent, not about the server.\n */\n private async remoteFile(tool: string, field: string, value: unknown): Promise<File> {\n const refuse = (why: string) =>\n new McpToolError(`\"${field}\" of \"${tool}\" ${why}`, 400);\n const file = value as { name: string; mimeType: string; data?: string; url?: string };\n const { maxBytes, fetch: fetchOptions } = this.files;\n if (!isSafeFileName(file.name)) {\n throw refuse(\"needs a name of 1 to 255 characters, without control characters or slashes.\");\n }\n if (!MEDIA_TYPE.test(file.mimeType)) {\n throw refuse(`has a mimeType that is not a media type: \"${file.mimeType.slice(0, 100)}\".`);\n }\n const hasData = typeof file.data === \"string\";\n const hasUrl = typeof file.url === \"string\";\n if (hasData === hasUrl) {\n throw refuse(\n fetchOptions ? \"needs exactly one of data or url.\" : \"needs its bytes, base64, in data.\",\n );\n }\n if (hasData) {\n const data = file.data!.replace(/\\s+/g, \"\");\n // Checked before decoding, so an oversized argument is never turned\n // into a buffer. `Buffer.from(…, \"base64\")` skips what it cannot read\n // rather than failing, so the alphabet is checked first too.\n if (Math.floor((data.length * 3) / 4) - padding(data) > maxBytes) {\n throw refuse(`is larger than the ${maxBytes} bytes a file may be.`);\n }\n if (data.length % 4 !== 0 || !BASE64.test(data)) {\n throw refuse(\"has data that is not base64 (RFC 4648, standard alphabet, padded).\");\n }\n return new File([Buffer.from(data, \"base64\")], file.name, { type: file.mimeType });\n }\n if (!fetchOptions) {\n throw refuse(\"cannot be fetched from a URL here. Send its bytes, base64, in data.\");\n }\n let url: URL;\n try {\n url = new URL(file.url!);\n } catch {\n throw refuse(\"has a url that is not a URL.\");\n }\n if (url.protocol !== \"https:\") {\n throw refuse(\"can only be fetched from an https URL.\");\n }\n try {\n const response = await safeFetch(url.href, {\n ...fetchOptions,\n maxSize: Math.min(fetchOptions.maxSize ?? maxBytes, maxBytes),\n redirect: \"follow\",\n });\n if (!response.ok) {\n throw refuse(`could not be fetched: ${url.host} answered ${response.status}.`);\n }\n const bytes = await response.arrayBuffer();\n return new File([bytes], file.name, { type: file.mimeType });\n } catch (error) {\n if (error instanceof McpToolError) throw error;\n // safeFetch's errors say what was refused (a private address, too large,\n // a timeout) without anything the model should not see.\n throw refuse(\n `could not be fetched from ${url.host}: ${error instanceof Error ? error.message : \"failed\"}.`,\n );\n }\n }\n\n /** Whether a remote principal carries a scope that reaches the tool `name`. */\n private grants(principal: McpRemotePrincipal, name: string): boolean {\n for (const scope of principal.scopes ?? []) {\n if (this.scopeTools.get(scope)?.tools.has(name)) return true;\n }\n return false;\n }\n\n /**\n * The router's `scopes`, each resolved to tool names once, at boot. A tag or\n * name no tool has is refused, since it is a typo that would leave a scope\n * reaching less than its description promises; so is a scope that reaches\n * nothing, and a name a scope token cannot be.\n */\n private resolveScopes() {\n const declared = this.router.scopes;\n if (declared === undefined) {\n this.scopeTools.set(DEFAULT_MCP_SCOPE, {\n description: \"Use this app's tools as you\",\n tools: new Set(this.plans.keys()),\n });\n return;\n }\n if (typeof declared !== \"object\" || declared === null) {\n throw new Error(\"McpRouter: scopes must be an object of scope names.\");\n }\n const tags = new Set([...this.plans.values()].flatMap(({ descriptor }) => descriptor.tags));\n for (const [scope, spec] of Object.entries(declared as Record<string, McpScope>)) {\n const where = `McpRouter: scope \"${scope}\"`;\n if (!SCOPE_TOKEN.test(scope)) {\n throw new Error(`${where} is not a valid OAuth scope: printable ASCII, no spaces or quotes.`);\n }\n if (typeof spec?.description !== \"string\" || spec.description === \"\") {\n throw new Error(`${where} needs a description: it is what a consent screen shows.`);\n }\n const tools = new Set<string>();\n for (const tag of spec.tags ?? []) {\n if (!tags.has(tag)) throw new Error(`${where} names the tag \"${tag}\", which no tool has.`);\n for (const [name, { descriptor }] of this.plans) {\n if (descriptor.tags.includes(tag)) tools.add(name);\n }\n }\n for (const name of spec.names ?? []) {\n if (!this.plans.has(name)) throw new Error(`${where} names \"${name}\", which is no tool.`);\n tools.add(name);\n }\n if (tools.size === 0) {\n throw new Error(`${where} reaches no tool. Give it tags or names.`);\n }\n this.scopeTools.set(scope, { description: spec.description, tools });\n }\n }\n\n /**\n * A 2xx put through the meta's `result` and `output`, for a tool that has\n * either.\n *\n * The whole body is parsed and projected before anything is cut: trimming a\n * large answer down is what a projection is for, and cutting first would\n * hand `result` half a JSON document. The projected value is then held to\n * `MAX_RESULT_BODY` the way any answer is.\n *\n * Every failure here is the app's, not the model's — a route that answered\n * something other than JSON, a `result` that threw, an answer `output` does\n * not describe — so each is logged and the model is told only that the\n * tool failed. Telling it more would invite a retry of a call that already\n * did what it does.\n */\n private async project(plan: Plan, call: McpCallContext, response: Response): Promise<unknown> {\n const { name, outputSchema } = plan.descriptor;\n if (response.status < 200 || response.status >= 300) {\n return await readResponse(name, response);\n }\n const failed = (why: string, error?: unknown) => {\n if (error === undefined) console.error(`[gemi/mcp] \"${name}\" ${why}`);\n else console.error(`[gemi/mcp] \"${name}\" ${why}`, error);\n return new McpToolError(`\"${name}\" failed on the server.`, 500);\n };\n\n const type = response.headers.get(\"Content-Type\");\n const text = await response.text();\n let data: unknown = null;\n if (text !== \"\") {\n try {\n data = JSON.parse(text);\n } catch {\n throw failed(\n `answered ${type ?? \"a body with no content-type\"} that is not JSON, and its result or output needs JSON.`,\n );\n }\n }\n\n let value = data;\n if (plan.result) {\n try {\n value = await plan.result(data, call);\n } catch (error) {\n throw failed(\"failed in its result projection:\", error);\n }\n }\n if (outputSchema) {\n const parsed = outputSchema.safeParse(value);\n if (parsed.ok === false) {\n throw failed(`answered what its output schema refuses: ${parsed.errors.join(\", \")}`);\n }\n value = parsed.value;\n }\n\n if (value === undefined) return null;\n const serialised = JSON.stringify(value);\n if (serialised !== undefined && serialised.length > MAX_RESULT_BODY) {\n return `${serialised.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${serialised.length} characters]`;\n }\n return value;\n }\n\n /**\n * Runs an app's binder. Its failure is the server's, not the model's, so the\n * model is told only that; the app gets the error in its log.\n *\n * With `refusals`, a `ToolError` (an `McpToolError` is one) is the app\n * refusing what the model sent, and is passed on for the model to read. Only\n * a model-facing param's resolver gets that: it is translating the model's\n * own words, so \"there is no such page\" is something the model can fix. A\n * plain binder reads nothing of the model's, and its throw stays the\n * server's.\n */\n private async bind<T>(\n plan: Plan,\n what: string,\n fn: () => T | Promise<T>,\n options: { refusals?: boolean } = {},\n ): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (options.refusals && error instanceof ToolError) throw error;\n console.error(`[gemi/mcp] Binding ${what} of \"${plan.descriptor.name}\" failed:`, error);\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n }\n}\n\n/**\n * A caller is one of the two shapes, and a remote one carries a principal a\n * resolver built. Checked because the registry is reachable from app code and\n * JavaScript: a remote caller without a user would be dispatched as nobody.\n */\nfunction assertCaller(caller: McpCaller) {\n if (caller?.kind === \"local\" && caller.req) return;\n if (\n caller?.kind === \"remote\" &&\n caller.req &&\n caller.principal?.user &&\n typeof caller.principal.id === \"string\" &&\n Array.isArray(caller.principal.scopes)\n ) {\n return;\n }\n throw new Error(\n 'McpRegistry: a caller is { kind: \"local\", req } or { kind: \"remote\", req, principal }, with the principal a caller resolver verified.',\n );\n}\n\nfunction passes(descriptor: McpToolDescriptor, filter?: McpToolFilter): boolean {\n if (filter?.names && !filter.names.includes(descriptor.name)) return false;\n if (filter?.tags && !descriptor.tags.some((tag) => filter.tags!.includes(tag))) return false;\n return true;\n}\n\nconst DEFAULT_MAX_FILE_BYTES = 10 * 1024 * 1024;\n\nfunction remoteFileOptions(options: McpRemoteFileOptions | undefined) {\n const maxBytes = options?.maxBytes ?? DEFAULT_MAX_FILE_BYTES;\n if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {\n throw new Error(\"McpRegistry: files.maxBytes must be a positive whole number of bytes.\");\n }\n const fetch =\n options?.fetchUrls === true\n ? {}\n : typeof options?.fetchUrls === \"object\" && options.fetchUrls !== null\n ? options.fetchUrls\n : null;\n return { maxBytes, fetch };\n}\n\n/** 1 to 255 characters, no control characters and no path separators. */\nfunction isSafeFileName(name: string): boolean {\n if (name.length === 0 || name.length > 255) return false;\n for (const char of name) {\n const code = char.codePointAt(0)!;\n if (code < 0x20 || code === 0x7f || char === \"/\" || char === \"\\\\\") return false;\n }\n return true;\n}\n\n/** `type/subtype`, with parameters, as RFC 6838 restricts the names. */\nconst MEDIA_TYPE = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(\\s*;.{0,200})?$/;\n\nconst BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;\n\nfunction padding(data: string): number {\n return data.endsWith(\"==\") ? 2 : data.endsWith(\"=\") ? 1 : 0;\n}\n\n/** A binder is a function or `\"input\"`; anything else would leave the value to nobody. */\nfunction assertBinder(where: string, at: string, binder: unknown) {\n if (binder !== \"input\" && typeof binder !== \"function\") {\n throw new Error(`${where}: ${at} must be a function or \"input\".`);\n }\n}\n\n/**\n * By brand, as a declaration is, rather than `instanceof`: an app that ends up\n * with two copies of gemi would otherwise see its params as broken binders.\n */\nfunction isModelParam(value: unknown): value is McpModelParam<any, any> {\n return value instanceof Object && (value as McpModelParam).__internal_brand === \"McpModelParam\";\n}\n\n/** A `this.param(...)`, checked for a router written in JavaScript or behind a cast. */\nfunction assertModelParam(where: string, at: string, param: McpModelParam<any, any>) {\n if (param.as !== undefined && (typeof param.as !== \"string\" || param.as === \"\")) {\n throw new Error(`${where}: ${at}.as must be a non-empty string.`);\n }\n const schema = param.input;\n if (typeof schema?.safeParse !== \"function\" || typeof schema.toJSONSchema !== \"function\") {\n throw new Error(`${where}: ${at}.input must be a schema, built with s.`);\n }\n if (typeof param.bind !== \"function\") {\n throw new Error(`${where}: ${at}.bind must be a function.`);\n }\n}\n\nconst ANNOTATION_KEYS = new Set<string>([\n \"readOnlyHint\",\n \"destructiveHint\",\n \"idempotentHint\",\n \"openWorldHint\",\n]);\n\n/** What the verb says, before the meta's overrides. */\nfunction verbAnnotations(method: McpMethod): McpToolAnnotations {\n switch (method) {\n case \"GET\":\n return { readOnlyHint: true };\n case \"DELETE\":\n return { destructiveHint: true };\n case \"PUT\":\n return { idempotentHint: true };\n default:\n return {};\n }\n}\n\n/**\n * The verb's hints with the meta's laid over them, hint by hint. Checked for a\n * router written in JavaScript or behind a cast: an unknown key is a typo that\n * would silently leave the verb's default standing, and a non-boolean is not a\n * hint a client can read.\n */\nfunction annotationsFor(\n where: string,\n method: McpMethod,\n overrides: McpToolAnnotations | undefined,\n): Readonly<McpToolAnnotations> {\n if (overrides !== undefined && (typeof overrides !== \"object\" || overrides === null)) {\n throw new Error(`${where}: annotations must be an object of hints.`);\n }\n const merged: McpToolAnnotations = verbAnnotations(method);\n for (const [key, value] of Object.entries(overrides ?? {})) {\n if (!ANNOTATION_KEYS.has(key)) {\n throw new Error(\n `${where}: \"${key}\" is not a tool annotation. Use readOnlyHint, destructiveHint, idempotentHint or openWorldHint.`,\n );\n }\n if (value === undefined) continue;\n if (typeof value !== \"boolean\") {\n throw new Error(`${where}: annotations.${key} must be true or false.`);\n }\n (merged as Record<string, boolean>)[key] = value;\n }\n if (merged.readOnlyHint === true && (merged.destructiveHint || merged.idempotentHint)) {\n throw new Error(\n `${where} is read-only${overrides?.readOnlyHint ? \"\" : ` (a ${method})`} and also ${merged.destructiveHint ? \"destructive\" : \"idempotent\"}, which only a tool that is not read-only can be. Set readOnlyHint: false if it changes something.`,\n );\n }\n return Object.freeze(merged);\n}\n\n/**\n * One schema out of two: the app's `input`, and the strings for `\"input\"`\n * params and files.\n *\n * Built by hand, like `questionSchema` in `ai/Agent.ts`, rather than by\n * widening `s` with a merge: `Schema.ts` is deliberately the strict\n * structured-output subset and owns no operation on a finished schema. Both\n * halves are real `s` schemas, each parses the whole value and drops the keys\n * that are not its own — which is also where a bound param the model sent\n * anyway disappears, since neither half declares it.\n */\nfunction combineSchemas(\n input: AnySchema | undefined,\n base: JSONSchema | undefined,\n extras: AnySchema,\n /**\n * Required fields whose schemas are not `s`'s — a remote caller's files —\n * each parsing its own value. `s.object` refuses a schema it did not build.\n */\n handBuilt: Record<string, AnySchema> = {},\n): Schema<Record<string, unknown>> {\n const extra = extras.toJSONSchema();\n const handBuiltJson = Object.fromEntries(\n Object.entries(handBuilt).map(([key, schema]) => [key, schema.toJSONSchema()]),\n );\n const json: JSONSchema = {\n ...(base ?? {}),\n type: \"object\",\n properties: { ...(base?.properties ?? {}), ...extra.properties, ...handBuiltJson },\n required: [...(base?.required ?? []), ...(extra.required ?? []), ...Object.keys(handBuilt)],\n additionalProperties: false,\n };\n\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"expected an object\"] };\n }\n const errors: string[] = [];\n let out: Record<string, unknown> = {};\n if (input) {\n const own = input.safeParse(value);\n if (own.ok === false) errors.push(...own.errors);\n else out = { ...own.value };\n }\n const more = extras.safeParse(value);\n if (more.ok === false) errors.push(...more.errors);\n else out = { ...out, ...more.value };\n for (const [key, schema] of Object.entries(handBuilt)) {\n const field = (value as Record<string, unknown>)[key];\n if (field === undefined) {\n errors.push(`\"${key}\" is required`);\n continue;\n }\n const own = schema.safeParse(field);\n if (own.ok === false) errors.push(...own.errors.map((error) => `${key}: ${error}`));\n else out[key] = own.value;\n }\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as Schema<Record<string, unknown>>;\n}\n\nfunction withoutKeys<T>(record: Record<string, T>, keys: string[]): Record<string, T> {\n return Object.fromEntries(Object.entries(record).filter(([key]) => !keys.includes(key)));\n}\n\n/**\n * A model-supplied param, as one encoded path segment. `.` and `..` are\n * refused rather than encoded: they encode to themselves, and URL parsing\n * would walk them out of the route.\n */\nfunction encodeSegment(tool: string, param: PathParam, value: string): string {\n const parts = param.modifier === \"*\" || param.modifier === \"+\" ? value.split(\"/\") : [value];\n if (parts.some((part) => part === \".\" || part === \"..\")) {\n throw new McpToolError(`\"${value}\" is not a valid value for \"${param.name}\" of \"${tool}\".`);\n }\n return parts.map(encodeURIComponent).join(\"/\");\n}\n\n/**\n * A JSON field as a multipart form field. A form has only strings, so the\n * route reads `\"12\"` where a JSON body would have carried `12` — what a\n * browser form sends the same route. An array becomes the key repeated, which\n * `HttpRequest` reads back as an array.\n */\nfunction appendField(form: FormData, key: string, value: unknown) {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendField(form, key, item);\n return;\n }\n form.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\n\n/** A GET's input, as the query string `HttpRequest.search` reads. */\nfunction toQuery(json: Record<string, unknown>): string {\n const search = new URLSearchParams();\n const add = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) add(key, item);\n return;\n }\n search.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n };\n for (const [key, value] of Object.entries(json)) add(key, value);\n return search.toString();\n}\n\nasync function readResponse(name: string, response: Response): Promise<unknown> {\n if (response.status >= 200 && response.status < 300) {\n const type = response.headers.get(\"Content-Type\");\n if (type && !READABLE.test(type)) {\n const size = (await response.arrayBuffer()).byteLength;\n return `\"${name}\" answered with ${size} bytes of ${type}, which is not shown.`;\n }\n const text = await response.text();\n if (text === \"\") return null;\n if (text.length > MAX_RESULT_BODY) {\n return `${text.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${text.length} characters]`;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n const text = await response.text();\n if (response.status >= 400 && response.status < 500) {\n const shown = text.length > MAX_ERROR_BODY ? `${text.slice(0, MAX_ERROR_BODY)}…` : text;\n throw new McpToolError(\n `\"${name}\" was refused with ${response.status}${shown ? `: ${shown}` : \".\"}`,\n response.status,\n );\n }\n if (response.status < 500) {\n // A redirect, or a 1xx: nothing the model can follow, and nothing the\n // dispatcher logged.\n console.error(\n `[gemi/mcp] \"${name}\" answered ${response.status}${response.headers.get(\"Location\") ? ` to ${response.headers.get(\"Location\")}` : \"\"}, which a tool call cannot follow.`,\n );\n }\n throw new McpToolError(`\"${name}\" failed on the server.`, response.status);\n}\n",
6
6
  "import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nimport type { User } from \"../../../auth/types\";\nimport type { McpRegistry, McpRemotePrincipal } from \"../McpRegistry\";\n\n/**\n * What a caller resolver is told about the server it resolves for.\n */\nexport type McpResolveContext = {\n /**\n * The MCP endpoint's canonical URL, from config — the OAuth `resource` and\n * the audience a token must have been issued for. Never read off the\n * request: a `Host` header is the client's to write.\n */\n resource: string;\n /** The tools, and the scopes that reach them. */\n registry: McpRegistry;\n};\n\n/**\n * What a resolver made of a request's credential.\n *\n * `invalid_token` answers 401: missing, malformed, expired, revoked, or\n * issued for another audience. The description is sent to the client in the\n * `WWW-Authenticate` header, so it says what is wrong with the credential and\n * never anything about the user or the store.\n */\nexport type McpResolution =\n | { ok: true; principal: McpRemotePrincipal }\n | { ok: false; error: \"invalid_token\"; description: string };\n\n/**\n * Turns the credential on a request to the MCP endpoint into a principal: the\n * user every tool call runs as, and the scopes that decide which tools they\n * see. The transport refuses to start without one, and the request is\n * answered 401 unless one of them resolves it.\n *\n * Resolvers are asked in order. One that answers `null` does not recognise the\n * credential (or there is none) and the next is asked; one that answers a\n * refusal ends the request, so a token one resolver issued and revoked cannot\n * be retried against another.\n *\n * A resolver builds the principal from a credential it *verified* — looked up,\n * checked against its audience and expiry — and never from anything else the\n * request says. The principal's user is put on every dispatched route's\n * request context as a signed-in user would be; a resolver that believed a\n * header would sign anybody in as anybody.\n */\nexport interface McpCallerResolver {\n /** Recorded as `principal.via`, and `req.mcpGrant().via`. */\n readonly name: string;\n resolve(req: Request, context: McpResolveContext): Promise<McpResolution | null>;\n /**\n * The `WWW-Authenticate` value for a request no resolver claimed, so a\n * client knows how to get a credential. The first resolver that has one is\n * used.\n */\n challenge?(context: McpResolveContext, options?: { scope?: string[] }): string | null;\n /**\n * HTTP endpoints of the resolver's own — an OAuth authorization server's\n * metadata, registration, authorize and token endpoints. Asked before the\n * MCP endpoint, for every request to the configured origin. `null` passes.\n */\n handle?(req: Request, context: McpResolveContext): Promise<Response | null>;\n /** Called once, when the transport is built: a place to refuse a bad config at boot. */\n boot?(context: McpResolveContext): void;\n}\n\n/** The bearer token on a request, or `null`. Never anything from the query string. */\nexport function bearerToken(req: Request): string | null {\n const header = req.headers.get(\"authorization\");\n if (!header) return null;\n const match = /^Bearer[ ]+([\\x21-\\x7e]+)$/i.exec(header.trim());\n return match ? match[1] : null;\n}\n\n/** What `McpApiKeyResolver`'s `verify` answers for a key it knows. */\nexport type McpApiKey = {\n /** The user the key acts as. */\n user: User;\n /** The key's own id (a row id), never the key: it keys rate limits and logs. */\n id: string;\n /** The scopes the key carries; see `McpRouter.scopes`. */\n scopes: readonly string[];\n};\n\nexport type McpApiKeyResolverOptions = {\n /**\n * The prefix every key of this app starts with, like `\"kyte_mcp_\"`.\n * Required: a bearer token without it is left for the next resolver (an\n * OAuth access token), and a key is never looked up by a resolver that did\n * not issue it. Also what makes a leaked key recognisable to a secret\n * scanner.\n */\n prefix: string;\n /**\n * Looks the key up. Store keys hashed — `McpApiKeyResolver.hash(key)` — and\n * look up by the hash, so a database read is not a list of working keys.\n * Answer `null` for an unknown, expired or revoked key.\n */\n verify(key: string, req: Request): Promise<McpApiKey | null>;\n};\n\n/**\n * Remote callers authenticated by an API key the app issued: a user creates\n * one in the app's settings and pastes it into an MCP client as a bearer\n * token. Simpler than OAuth, for clients configured by hand (Claude Code,\n * scripts); a hosted client such as Claude.ai's connectors uses OAuth.\n *\n * ```ts\n * remote: {\n * enabled: true,\n * url: \"https://example.com/mcp\",\n * resolvers: [\n * new McpApiKeyResolver({\n * prefix: \"ex_mcp_\",\n * verify: async (key) => {\n * const row = await ApiKey.findFirst({ where: { hash: McpApiKeyResolver.hash(key), revokedAt: null }, include: { user: true } });\n * return row && { user: row.user, id: row.publicId, scopes: row.scopes };\n * },\n * }),\n * ],\n * }\n * ```\n */\nexport class McpApiKeyResolver implements McpCallerResolver {\n readonly name = \"api-key\";\n\n constructor(private readonly options: McpApiKeyResolverOptions) {\n if (typeof options?.prefix !== \"string\" || !/^[A-Za-z0-9_-]{3,32}$/.test(options.prefix)) {\n throw new Error(\n \"McpApiKeyResolver: prefix is required: 3 to 32 letters, digits, _ or -, like \\\"myapp_mcp_\\\".\",\n );\n }\n if (typeof options.verify !== \"function\") {\n throw new Error(\"McpApiKeyResolver: verify must be a function that looks a key up.\");\n }\n }\n\n /** A new key: the prefix and 32 random bytes, base64url. Show it once, store its hash. */\n static generate(prefix: string): string {\n return `${prefix}${randomBytes(32).toString(\"base64url\")}`;\n }\n\n /** What to store for a key and look it up by: SHA-256, hex. */\n static hash(key: string): string {\n return createHash(\"sha256\").update(key).digest(\"hex\");\n }\n\n /** Compares two hashes without leaking where they differ. */\n static hashesMatch(a: string, b: string): boolean {\n const left = Buffer.from(a);\n const right = Buffer.from(b);\n return left.length === right.length && timingSafeEqual(left, right);\n }\n\n async resolve(req: Request): Promise<McpResolution | null> {\n const token = bearerToken(req);\n if (!token?.startsWith(this.options.prefix)) return null;\n const key = await this.options.verify(token, req);\n if (!key) {\n return { ok: false, error: \"invalid_token\", description: \"The API key is not valid.\" };\n }\n if (!key.user || typeof key.id !== \"string\" || key.id === \"\" || !Array.isArray(key.scopes)) {\n throw new Error(\n \"McpApiKeyResolver: verify must answer { user, id, scopes } for a key it knows, or null.\",\n );\n }\n return {\n ok: true,\n principal: { user: key.user, via: this.name, id: key.id, scopes: [...key.scopes] },\n };\n }\n}\n",
@@ -10,6 +10,9 @@
10
10
  "import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nimport { purposeKey } from \"../../../ai/signing\";\n\n/**\n * State the transport hands a client and takes back: a legacy session id, an\n * elicitation's `requestState`. Both pass through the client, so both are\n * attacker-controlled on the way back in, and both are signed.\n *\n * `<tag>.<payload>.<mac>`: the payload is base64url JSON, the MAC is\n * HMAC-SHA256 over the tag and the payload under a key HKDF-derived from the\n * app's `SECRET` for this purpose alone (`purposeKey`), so a value signed for\n * one use can never verify as another — a session id is not a request state.\n * It is signed, not encrypted: nothing in it is a secret, and the client may\n * read it.\n *\n * Expiry is in the payload and checked here. Anything else a value is bound\n * to — the principal, the tool, the arguments — is the caller's to compare.\n */\nexport function sign(purpose: string, tag: string, payload: Record<string, unknown>): string {\n const body = Buffer.from(JSON.stringify(payload)).toString(\"base64url\");\n return `${tag}.${body}.${mac(purpose, tag, body).toString(\"base64url\")}`;\n}\n\n/**\n * The payload of a value `sign` made for `purpose` and `tag`, or `null` when\n * it is malformed, forged, signed for something else, or expired (`exp`, in\n * epoch milliseconds, is required).\n */\nexport function verify<T extends { exp: number }>(\n purpose: string,\n tag: string,\n value: unknown,\n now = Date.now(),\n): T | null {\n if (typeof value !== \"string\" || value.length > 8192) return null;\n const parts = value.split(\".\");\n if (parts.length !== 3 || parts[0] !== tag) return null;\n const [, body, signature] = parts;\n const presented = Buffer.from(signature, \"base64url\");\n const expected = mac(purpose, tag, body);\n if (presented.length !== expected.length || !timingSafeEqual(presented, expected)) return null;\n let payload: T;\n try {\n payload = JSON.parse(Buffer.from(body, \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n if (typeof payload !== \"object\" || payload === null) return null;\n if (typeof payload.exp !== \"number\" || payload.exp <= now) return null;\n return payload;\n}\n\nfunction mac(purpose: string, tag: string, body: string): Buffer {\n return createHmac(\"sha256\", purposeKey(purpose)).update(`${tag}.${body}`).digest();\n}\n",
11
11
  "import { type HeldLock, LockManager } from \"../lock/LockManager\";\nimport { LockLostError } from \"../lock/LockStore\";\nimport { MemoryLockStore } from \"../lock/MemoryLockStore\";\nimport type { CronJob } from \"./CronJob\";\nimport type { ScheduleConfig } from \"./config\";\n\n// The handle the in-process `Bun.cron(schedule, callback)` overload returns\n// (has `.stop()`). `ReturnType<typeof Bun.cron>` can't be used — it resolves to\n// the module-path overload's `Promise<void>` instead.\ntype BunCronHandle = Bun.CronJob;\n\n// Runs a tick inside whatever async context the framework needs, so a job body\n// can resolve services exactly like a request handler can.\nexport type ScheduleRunner = <T>(cb: () => T | Promise<T>) => Promise<T> | T;\n\ndeclare global {\n // Registered cron jobs keyed by name, kept on `globalThis` so it survives\n // `bun --hot` reloads. Re-registering a name stops the previous schedule\n // first, so a reload *updates* the job in place instead of stacking a\n // duplicate. (Bun also stops all in-process cron jobs before re-evaluating on\n // hot reload; this makes the intent explicit and covers any re-construction.)\n var __gemiCronJobs: Map<string, BunCronHandle> | undefined;\n}\n\n/**\n * One tick of one job: the gate, then the three hooks in order.\n *\n * Named and exported rather than left inline in `start()` because otherwise the\n * only way to reach it is to wait — the tightest schedule `Bun.cron` accepts is\n * once a minute, which is not a thing a test can honestly sit through. What a\n * caller gives up by calling this directly is Bun's clock; what it keeps is\n * everything the scheduler puts between the clock and the job, which is the\n * part that has behaviour.\n *\n * The three hooks each catch and log, so one throwing does not stop the next —\n * `onComplete` in particular runs whether `callback` returned or threw, closer\n * to a `finally` than to a success handler.\n */\nexport async function runTick(job: CronJob, options: TickOptions = {}): Promise<void> {\n try {\n // Plain truthiness, not `!== false`. The sloppy gate an app writes is\n // `if (!isProduction) return false;`, which returns `undefined` on the path\n // that was meant to run — and between the two readings of that, the one\n // that skips a recurring tick is recoverable and the one that mails a\n // customer from a developer's laptop is not. The declared return type makes\n // that method a compile error anyway, so the type system catches it while\n // it is still being written and the runtime stays on the safe side.\n if (!(await job.shouldRun.call(job))) {\n return;\n }\n } catch (error) {\n // Fail closed, for the same reason. A gate that throws has told us nothing\n // about whether the job may run, and the framework already refuses to\n // schedule a job whose name or expression it cannot read rather than run\n // something half-declared. The throw is logged, so this is loud; the missed\n // tick comes back on the next one.\n console.error(\n `Error evaluating shouldRun for cron job ${job.name}:`,\n error,\n );\n return;\n }\n\n const overlap = overlapLease(job.withoutOverlapping);\n if (!job.onOneServer && overlap === undefined) {\n await runHooks(job);\n return;\n }\n\n // Fail closed, like the gate: a tick that cannot find out whether it may\n // run is skipped, and the next one tries again.\n let locks: LockManager;\n try {\n locks = options.locks?.() ?? processLocks();\n if (job.onOneServer) {\n const minute = Math.floor((options.now ?? Date.now()) / 60_000);\n if (!(await locks.store.advance(`gemi:cron-tick:${job.name}`, minute))) return;\n }\n } catch (error) {\n console.error(`Could not claim the tick of cron job ${job.name}; skipped it:`, error);\n return;\n }\n if (overlap === undefined) {\n await runHooks(job);\n return;\n }\n\n try {\n await locks.run(`gemi:cron:${job.name}`, { ttl: overlap }, (lock) => runHooks(job, lock));\n } catch (error) {\n if (error instanceof LockLostError) {\n console.error(\n `Cron job ${job.name} lost its withoutOverlapping lock while running: ` +\n `another tick may have started alongside it.`,\n error,\n );\n } else {\n console.error(`Could not take the withoutOverlapping lock of cron job ${job.name}:`, error);\n }\n }\n}\n\n/** What `runTick` needs beyond the job. */\nexport interface TickOptions {\n /**\n * The locks `withoutOverlapping` and `onOneServer` take. The scheduler\n * passes the queue's, so they hold across instances sharing its storage;\n * without one they hold within this process only.\n */\n locks?: () => LockManager;\n /** The tick's time, for `onOneServer`. Default now. */\n now?: number;\n}\n\nconst DEFAULT_OVERLAP_LEASE = 5 * 60_000;\n\nfunction overlapLease(option: CronJob[\"withoutOverlapping\"]): number | undefined {\n if (!option) return undefined;\n if (option === true) return DEFAULT_OVERLAP_LEASE;\n return option.expiresAfter ?? DEFAULT_OVERLAP_LEASE;\n}\n\nlet fallbackLocks: LockManager | undefined;\nfunction processLocks() {\n fallbackLocks ??= new LockManager(new MemoryLockStore());\n return fallbackLocks;\n}\n\nasync function runHooks(job: CronJob, lock?: HeldLock) {\n try {\n await job.onTick.call(job);\n } catch (error) {\n console.error(`Error executing cron job ${job.name}:`, error);\n }\n try {\n await job.callback.call(job, lock);\n } catch (error) {\n console.error(`Error in cron job ${job.name}:`, error);\n }\n try {\n await job.onComplete.call(job);\n } catch (error) {\n console.error(`Error completing cron job ${job.name}:`, error);\n }\n}\n\n/** A tick `drain` could not wait out. */\nexport interface UnfinishedTick {\n /** The job's `name`. */\n name: string;\n /**\n * When this tick started. A job whose tick outlasts its own interval has\n * two ticks running at once, and the name alone would list it twice with\n * nothing to tell the two apart.\n */\n startedAt: Date;\n}\n\n/** What `drain` could not wait out. */\nexport interface ScheduleDrainResult {\n /**\n * Ticks still running when the timeout elapsed. They keep running — a tick\n * has no way to be told to stop — until they finish or the process exits.\n */\n unfinished: UnfinishedTick[];\n}\n\nexport class Scheduler {\n static token = \"scheduler\";\n\n private handles: BunCronHandle[] = [];\n private resolved: Array<new () => CronJob>;\n\n /**\n * Every tick this scheduler has started and not seen settle, keyed by an\n * object of its own so two overlapping ticks of one job are two entries.\n * Without this there is nothing for a shutdown to wait on, and a tick the\n * process exits under is cut off halfway through its `callback`.\n */\n private readonly inFlight = new Map<object, { tick: UnfinishedTick; done: Promise<unknown> }>();\n\n /**\n * Set by `stop()`, cleared by `start()`. `handle.stop()` is what keeps Bun\n * from firing again, and this is the second lock on the same door: a\n * callback Bun had already dispatched when `stop()` ran, or a handle some\n * other scheduler left in the hot-reload registry, still finds nothing to\n * start once the drain has begun.\n */\n private stopped = false;\n\n private locks: (() => LockManager) | undefined;\n\n constructor(config: Required<ScheduleConfig>) {\n this.resolved = config.jobs;\n }\n\n /**\n * The jobs this scheduler will run, or ran — declared in the config slice or\n * discovered under `app/cron`, whichever the slice asked for.\n *\n * #323 turned an application's schedule from an array it could import into a\n * directory it cannot, and an app that had a test walking that array —\n * asserting every report has an owner, that no two share an expression — was\n * about to lose it. This is where that test goes instead, and it is the\n * better question anyway: the config slice says what was asked for, this says\n * what the scheduler took.\n *\n * It lists what `start()` iterates, not what `Bun.cron` accepted. A job with\n * no name, no expression, or a name another job already claimed is logged and\n * skipped, and still appears here — a test walking this should see the\n * problem rather than have it tidied away.\n *\n * A copy, so that walk cannot edit the set the scheduler is running from.\n */\n get jobs(): ReadonlyArray<new () => CronJob> {\n return [...this.resolved];\n }\n\n /**\n * Replaces the job set, for the provider to hand over what it found under\n * `app/cron` before it calls `start()`.\n *\n * The scheduler is constructed in `register()`, where reading a directory and\n * importing what is in it is not allowed to happen — that phase is\n * synchronous and resolves nothing. So it is built from whatever the slice\n * declared and corrected in `boot()`, one line before it starts. Calling this\n * after `start()` changes what `jobs` reports and nothing else; the schedules\n * are already registered.\n */\n useJobs(jobs: Array<new () => CronJob>) {\n this.resolved = jobs;\n }\n\n /**\n * Where `withoutOverlapping` and `onOneServer` take their locks. The\n * provider hands over the queue's, resolved only when a tick needs them.\n */\n useLocks(locks: () => LockManager) {\n this.locks = locks;\n }\n\n /**\n * Schedules every configured job. Called from `ScheduleServiceProvider.boot()`\n * — never from the constructor — so a job body may resolve any service the\n * container holds by the time it first ticks. That ordering is what replaced\n * the old `kernel.waitForBoot()` handshake.\n */\n start(run: ScheduleRunner = (cb) => cb()) {\n this.stopped = false;\n if (this.resolved.length === 0) {\n return;\n }\n\n const registry = (globalThis.__gemiCronJobs ??= new Map());\n\n // Names claimed during *this* pass, which is a different question from what\n // `registry` holds. `registry` spans hot reloads and is supposed to already\n // contain the previous reload's handle under the same name; this starts\n // empty every time and is how a name claimed twice in one schedule is told\n // apart from the same job coming back after an edit.\n const claimed = new Map<string, string>();\n\n for (const Job of this.resolved) {\n const job = new Job();\n if (!job.name) {\n // Named by its class, because under discovery nobody wrote this job\n // down anywhere and `JSON.stringify(job)` on a nameless one prints\n // `{}`. The overwhelmingly common cause is the second sentence: a\n // shared base class sitting in the walked directory. `abstract` is\n // erased before this code runs, so there is nothing here that could\n // tell a base class from a job — only the message can.\n console.error(\n `Cron job must have a name — ${Job.name || \"an anonymous class\"} ` +\n `has none, so it is not scheduled. If this is a base class that ` +\n `other jobs extend, move it out of the discovered directory: ` +\n `\\`abstract\\` does not survive to runtime, so a class under ` +\n `app/cron is indistinguishable from a job.`,\n );\n continue;\n }\n if (!job.cron) {\n console.error(`Cron job must have an expression. Job: ${job.name}`);\n continue;\n }\n const taken = claimed.get(job.name);\n if (taken !== undefined) {\n // Refusing the second one, rather than letting it through to the\n // `registry.get(...).stop()` below — which is what used to happen, and\n // it stopped the *first* job's schedule while leaving both classes in\n // `jobs`. That is the failure #323 exists to remove wearing a disguise:\n // a report that silently stops arriving, and a test walking `jobs` that\n // sees two healthy entries and passes.\n console.error(\n `Two cron jobs claim the name \"${job.name}\" — ${taken} is ` +\n `scheduled and ${Job.name || \"an anonymous class\"} is not. A name ` +\n `is the scheduler's key, so only one job can hold it. Rename one.`,\n );\n continue;\n }\n claimed.set(job.name, Job.name || \"an anonymous class\");\n\n // Update in place: stop any schedule previously registered under this name\n // before re-registering, so a hot reload replaces rather than duplicates.\n registry.get(job.name)?.stop();\n\n // Inside `run`, gate included: a `shouldRun` that resolves a service to\n // decide is the ordinary case, and evaluating it out here would leave it\n // without the application context every other line of the tick has.\n const handle = Bun.cron(job.cron, () => {\n if (this.stopped) return;\n const locks = this.locks;\n return this.track(job.name, () => run(() => runTick(job, { locks })));\n });\n\n registry.set(job.name, handle);\n this.handles.push(handle);\n }\n }\n\n /**\n * Stops every schedule, so no new tick starts. A tick already running is\n * left alone — `drain` is how to wait for it.\n */\n stop() {\n this.stopped = true;\n for (const handle of this.handles) {\n handle.stop();\n }\n this.handles = [];\n }\n\n /**\n * Stops every schedule, waits up to `timeoutMs` for the ticks already\n * running, and reports the ones that did not finish.\n *\n * Stopping comes first, so a tick that falls due while this waits does not\n * start: a drain that kept the clock running would never be sure it had\n * waited for everything. Nothing is cancelled — a job has no way to be told\n * — so an unfinished tick keeps running after this resolves, until it ends\n * or the process does.\n *\n * A later `start()` schedules again.\n */\n async drain(timeoutMs = Infinity): Promise<ScheduleDrainResult> {\n this.stop();\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<void>((resolve) => {\n if (timeoutMs !== Infinity) timer = setTimeout(resolve, timeoutMs);\n });\n await Promise.race([\n Promise.allSettled([...this.inFlight.values()].map((e) => e.done)),\n deadline,\n ]);\n clearTimeout(timer);\n\n return {\n unfinished: [...this.inFlight.values()].map((e) => ({ ...e.tick })),\n };\n }\n\n /** How many ticks this scheduler is running right now. */\n get running(): number {\n return this.inFlight.size;\n }\n\n private track(name: string, tick: () => unknown): Promise<unknown> {\n const key = {};\n // `Promise.resolve().then(...)` rather than calling `tick` directly, so a\n // runner that throws synchronously lands in the same promise as one that\n // rejects, and the entry below is removed either way.\n const done = Promise.resolve()\n .then(tick)\n .finally(() => this.inFlight.delete(key));\n this.inFlight.set(key, { tick: { name, startedAt: new Date() }, done });\n return done;\n }\n}\n",
12
12
  "import { isMainThread } from \"node:worker_threads\";\n\nimport type { Application } from \"../../foundation/Application\";\nimport { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { discoverJobs, discoverWorkflows } from \"../discovery\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { queueConfigDefaults, type QueueConfig } from \"./config\";\nimport { LockManager } from \"../lock/LockManager\";\nimport { MemoryQueueDriver } from \"./MemoryQueueDriver\";\nimport {\n claimingTurnedOff,\n claimsInThisProcess,\n isQueueWorker,\n QueueManager,\n} from \"./QueueManager\";\n\n/**\n * How far inside the provider deadline the drain stops, so there is time left\n * to write the list of jobs it abandoned before `Application` stops waiting\n * for this provider and the process exits. A tenth of the budget, capped, so\n * that a deadline of a few milliseconds still spends most of itself waiting\n * rather than handing the whole of it to the margin.\n */\nconst REPORT_MARGIN_MS = 100;\n\nconst reportMargin = (timeoutMs: number) =>\n Math.min(REPORT_MARGIN_MS, Math.floor(timeoutMs / 10));\n\nexport class QueueServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n QueueManager,\n () =>\n new QueueManager(this.app.config.get<QueueConfig>(\"queue\", {}), {\n application: this.app,\n }),\n );\n // The `Lock` facade's binding: the queue's locks, over its storage.\n this.app.singleton(LockManager, () => this.app.make(QueueManager).locks);\n }\n\n /**\n * Fills in the job registry when the app did not declare one.\n *\n * ### Why the raw slice and not the manager's config\n *\n * The decision here is whether the app said anything, and by the time the\n * manager holds a config it can no longer tell: `withDefaults` treats an\n * absent key and an `undefined` one alike and substitutes the default `[]`,\n * which is the same value an app writes when it means \"no jobs, and I mean\n * it\". Reading the slice before defaults are applied is the only place the\n * difference still exists.\n *\n * So: `jobs` present, including `jobs: []`, is used verbatim and no directory\n * is read. Absent or `undefined`, the classes under `jobsDir` are.\n *\n * ### Why phase two\n *\n * Discovery imports every file it walks, which is asynchronous, and\n * `register()` is not. It also has to happen before the first dispatch rather\n * than before the first tick — there is no equivalent of the scheduler's\n * `start()` to hang it off, so the registry has to be complete by the end of\n * boot.\n */\n async boot() {\n const slice = this.app.config.get<QueueConfig>(\"queue\", {});\n const { jobsDir, workflowsDir } = withDefaults(queueConfigDefaults(), slice);\n if (slice.jobs === undefined) {\n this.app.make(QueueManager).useJobs(await discoverJobs(jobsDir));\n }\n // Workflows by the same rule, under `app/workflows`. An app with none\n // has no such directory, and discovery says nothing about that.\n if (slice.workflows === undefined) {\n const workflows = await discoverWorkflows(workflowsDir);\n if (workflows.length > 0) this.app.make(QueueManager).useWorkflows(workflows);\n }\n }\n\n /**\n * Stops claiming and waits for the jobs this process is running, on the way\n * out of a server told to stop. Runs after the request drain, and before the\n * database provider's, so the jobs still have their connection.\n *\n * A job still running at the deadline is abandoned with the process. With\n * the memory driver that job is lost; with one that outlives the process it\n * is claimed again elsewhere once its lease runs out. With such a driver\n * claiming already stopped when the signal arrived, so the jobs here are\n * only the ones that were running then; the memory driver kept claiming\n * until now, so a job dispatched by a request still draining ran here too.\n *\n * The drain is bounded by a little less than what is left of the shared\n * provider deadline, so that this is the thing that names the jobs it gave\n * up on. Draining without a timeout of its own read better but could not\n * work: `drain()` then resolves only once every job has finished, by which\n * point nothing is unfinished and the list below is always empty — and the\n * operator who needed it got `Application`'s generic \"did not finish within\n * the provider shutdown deadline\" instead, which names no job at all. *\n * A drain that left jobs running resolves `{ abandoned: true }`, so\n * `Application` reports this provider in `timedOut` and the process exits 1:\n * the jobs are named in the log, and the exit code shows the stop was not\n * clean (#580).\n */\n async shutdown(options?: { timeoutMs: number }) {\n // Resolving the manager now would build a driver only to stop it.\n if (!this.app.resolved(QueueManager)) return;\n const queue = this.app.make(QueueManager);\n if (queue.running > 0) {\n console.log(\n `[gemi] Shutting down: waiting for ${queue.running} running queued job(s).`,\n );\n }\n const budget = options?.timeoutMs;\n const { unfinished } = await queue.drain(\n budget === undefined ? Infinity : Math.max(0, budget - reportMargin(budget)),\n );\n if (unfinished.length > 0) {\n console.error(\n `[gemi] Queued jobs still running at shutdown: ` +\n unfinished.map((job) => `${job.name} (${job.id})`).join(\", \"),\n );\n return { abandoned: true };\n }\n }\n}\n\n/**\n * Starts claiming once the application has booted, in a production server\n * whose driver keeps jobs outside the process, rather than at its first\n * dispatch. That is the recovery half of a durable driver: the jobs a previous\n * process left behind are claimed by whichever one is up, and a replica that\n * serves no dispatch of its own would otherwise never look.\n *\n * Called by the kernel after every provider has booted, not from `boot()`\n * above: queued listeners are registered as jobs by the event provider, which\n * boots after this one, and a job claimed before its name is registered is\n * dead-lettered for it.\n *\n * Not the memory driver, which never has anything left behind. Not a console\n * command or a migration, which boot the same providers and would claim jobs\n * only to exit under them — `ROOT_DIR` is set by `Server.start()` and the\n * `gemi queue:work` worker alone. Not a server started with\n * `GEMI_QUEUE_CLAIM=off`, which leaves its jobs to workers. Not\n * a `worker` job's thread, which clones the application. And not development,\n * where `bun --hot` boots a fresh application on every save: there the queue\n * starts at the first dispatch, and a reload hands a running loop over — see\n * `takeOverDevQueue`.\n */\nexport function startClaimingIfServing(application: Application) {\n warnAboutClaimSwitch(application);\n if (process.env.NODE_ENV !== \"production\") return takeOverDevQueue(application);\n if (configuresMemory(application)) return;\n if (!claimsInThisProcess()) return;\n if (!application.bound(QueueManager)) return;\n application.make(QueueManager).start();\n}\n\nfunction configuresMemory(application: Application) {\n const driver = application.config.get<QueueConfig>(\"queue\", {}).driver ?? \"memory\";\n return driver === \"memory\" || driver instanceof MemoryQueueDriver;\n}\n\n/**\n * Whether the queue's jobs live only in this process, for the warning below.\n * The config says so for `\"memory\"` or a `MemoryQueueDriver`, but a factory\n * only says once it has run, so for one the manager is built — which is the\n * same driver `durable` and `push()` go by. A factory that throws here is\n * left to throw at the first dispatch, as it would have without the switch,\n * rather than failing the boot over a warning.\n */\nfunction keepsJobsInProcess(application: Application) {\n if (configuresMemory(application)) return true;\n const driver = application.config.get<QueueConfig>(\"queue\", {}).driver;\n if (typeof driver !== \"function\" || !application.bound(QueueManager)) return false;\n try {\n return !application.make(QueueManager).durable;\n } catch {\n return false;\n }\n}\n\n/**\n * Says so at boot when a server's `GEMI_QUEUE_CLAIM` will not do what it\n * reads as. Only in a server's main thread: a console command or a `worker`\n * job's thread shares the server's environment and claims nothing anyway.\n *\n * - `off` with the memory driver is ignored, because a memory queue's jobs\n * exist only in the process that dispatched them. Honoured, it would leave\n * every dispatch waiting in a `Map` that no worker can see, for good.\n * - Any value but `off` or `on` claims. `false` or `0` read as \"off\" and are\n * not it, and a web process that quietly keeps claiming is the failure a\n * deploy that set one would never notice.\n */\nfunction warnAboutClaimSwitch(application: Application) {\n const value = process.env.GEMI_QUEUE_CLAIM;\n if (value === undefined || isQueueWorker()) return;\n if (process.env.ROOT_DIR === undefined || !isMainThread) return;\n if (claimingTurnedOff()) {\n if (!keepsJobsInProcess(application)) return;\n console.warn(\n `[gemi] GEMI_QUEUE_CLAIM=off is ignored: the memory queue driver keeps ` +\n `jobs in the process that dispatched them, so no worker could run ` +\n `them. This server runs its own jobs. Use a driver other processes ` +\n `can read, such as \"database\", to hand jobs to \\`gemi queue:work\\`.`,\n );\n } else if (value.trim().toLowerCase() !== \"on\") {\n console.warn(\n `[gemi] GEMI_QUEUE_CLAIM=\"${value}\" is not \"off\" or \"on\", so this ` +\n `server claims jobs. Set it to \"off\" to leave them to \\`gemi queue:work\\`.`,\n );\n }\n}\n\n/**\n * Under `gemi dev`, stops the loop the previous application started over a\n * shared driver, and starts this application's in its place.\n *\n * A `bun --hot` reload boots a new application in the same process, and the\n * old application's loop — started lazily by a dispatch — is a live closure\n * that nothing stopped. Over the database driver it went on claiming rows\n * from the table and running them with the code from before the save, and\n * after a few saves several generations of it were doing so side by side.\n *\n * Stopped rather than drained: `stop()` claims nothing more and returns, and\n * a job the old loop is running finishes on its old code and reports as\n * usual, where waiting for it would hold up the reload behind a job. Its row\n * stays claimed until then, so the new loop cannot take it twice.\n *\n * The new loop is started only when an old one was running, which keeps the\n * rule that development claims nothing until something is dispatched, while\n * a job waiting out a retry when the file was saved still gets its retry —\n * on the new code, which is the point of the reload. A memory queue is never\n * recorded, so it is never handed over: only its own application feeds it,\n * and stopping it would drop whatever was still waiting there.\n *\n * Runs from every boot. `waitForBoot` twice on one application stops its own\n * loop and starts it again at once, which changes nothing. The `bound` guard\n * is for an application built without the queue provider, which still stops\n * the stale loop.\n */\nfunction takeOverDevQueue(application: Application) {\n const previous = globalThis.__gemiDevQueue;\n if (!previous) return;\n globalThis.__gemiDevQueue = undefined;\n void previous.stop();\n if (application.bound(QueueManager)) application.make(QueueManager).start();\n}\n",
13
+ "import { app } from \"../../foundation/app\";\nimport { GEMI_REQUEST_BREAKER_ERROR } from \"../../http/Error\";\nimport { HttpRequest } from \"../../http/HttpRequest\";\nimport { type CarriedContext, RequestContext } from \"../../http/requestContext\";\nimport { isPolicyDeniedError, isRecordNotFoundError } from \"../../orm/errors\";\nimport { MiddlewareRegistry } from \"../middleware/MiddlewareRegistry\";\nimport { breakResponse, mergeContextIntoResponse } from \"./ApiRouteDispatcher\";\nimport { isApiPath } from \"./apiPath\";\nimport { notFoundResponse } from \"./notFound\";\nimport { policyDeniedResponse, policyDeniedView } from \"./policyDenied\";\nimport { viewBreakResponse, viewDataBreakResponse } from \"./ViewRouteDispatcher\";\n\nexport interface GlobalMiddlewareOutcome {\n /** The response that ends the request, when a global middleware refused it. */\n refusal: Response | null;\n /**\n * Puts the headers and cookies the global middleware set on the request\n * context onto the response the request ends with. The response's own\n * headers win; the context only fills gaps, as it does for route middleware.\n * Cookies are left off a response a shared cache may store (see\n * `sharedCacheable`).\n */\n apply(response: Response): Response;\n /**\n * The user the list left on its context, for the route's context to start\n * from. `null` when there is no list, or it refused.\n */\n carried: CarriedContext | null;\n}\n\n/**\n * Whether a shared cache may store this response: `public` or `s-maxage` in\n * its Cache-Control, as the static `dist/client` files carry\n * (`public, max-age=31536000`). A per-visitor cookie a global middleware set\n * would otherwise be stored with the asset, and a CDN that caches responses\n * with Set-Cookie would hand it to every visitor who gets that copy.\n */\nfunction sharedCacheable(response: Response) {\n const cacheControl = response.headers.get(\"Cache-Control\")?.toLowerCase() ?? \"\";\n return /(^|[\\s,])(public|s-maxage)\\b/.test(cacheControl);\n}\n\nconst noCookies = new Set<string>();\n\nconst passThrough: GlobalMiddlewareOutcome = {\n refusal: null,\n apply: (response) => response,\n carried: null,\n};\n\n/**\n * Runs the `global` middleware list for one incoming request, before anything\n * is routed and before a static file is served. Called from `App`, once per\n * request (see `App.withGlobalMiddleware`), inside the kernel scope.\n *\n * It opens a request scope of its own. The router has not run, so the\n * `HttpRequest` a global middleware gets has no params and an empty\n * `routePath`, and its `kind` is read off the url the way `App.fetch` picks a\n * dispatcher. The scope is not the one the route later runs in: the route's\n * dispatcher opens a fresh one, as it always has. Two things cross over.\n * Headers and cookies reach the response through `apply`, and the user is\n * `carried` into the route's context, so a gate that looked the user up does\n * not make `auth` or `Auth.user()` look them up again. Both trust a user they\n * find on the context without checking it against a session or asking for a\n * token, so whatever a global middleware sets is treated as authenticated by\n * the route — which is what lets one sign a user in by SSO header or API key\n * (#577), and why it must set only a user it has verified. The rest stays\n * behind:\n * the locale, because the dispatchers decide it for the route, from its url,\n * and the feature evaluations, made against a request with no route and maybe\n * before a user was known.\n *\n * A break answers the way the same break from a route middleware would for\n * that url: the api's JSON for `/api`, the `.json` navigation's body for view\n * data, and the page response otherwise, static files included. A policy\n * denial is the same 403 the dispatchers give. Anything else is thrown, and\n * the caller answers it as the server's 500.\n */\nexport async function runGlobalMiddleware(req: Request): Promise<GlobalMiddlewareOutcome> {\n const registry = app(MiddlewareRegistry);\n if (registry.config.global.length === 0) {\n return passThrough;\n }\n\n const { pathname } = new URL(req.url);\n const isApi = isApiPath(pathname);\n const httpRequest = new HttpRequest(req, {}, isApi ? \"api\" : \"view\", \"\");\n\n return await RequestContext.run(httpRequest, async () => {\n const ctx = RequestContext.getStore();\n // Held past `destroy()` below, which only drops the store's references.\n const { headers, cookies } = ctx;\n const apply = (response: Response) => {\n if (!sharedCacheable(response)) {\n return mergeContextIntoResponse(response, headers, cookies);\n }\n const withoutCookies = new Headers(headers);\n withoutCookies.delete(\"Set-Cookie\");\n return mergeContextIntoResponse(response, withoutCookies, noCookies);\n };\n\n try {\n await registry.runGlobalMiddleware();\n return { refusal: null, apply, carried: { user: ctx.user } };\n } catch (err) {\n const isViewData = !isApi && pathname.endsWith(\".json\");\n if (err?.kind === GEMI_REQUEST_BREAKER_ERROR) {\n const refusal = isApi\n ? breakResponse(err.payload.api)\n : isViewData\n ? viewDataBreakResponse(err.payload.viewData ?? err.payload.api)\n : viewBreakResponse(err.payload.view);\n return { refusal: apply(refusal), apply, carried: null };\n }\n // A global middleware that resolves the request's tenant or workspace by\n // an id from the url asks the same question a route handler does, and a\n // miss is the same 404. Only for the two json-shaped requests here: a\n // full page load should render the application's `404` view rather than\n // a bare body, and that is #614's to do.\n if (isRecordNotFoundError(err) && (isApi || isViewData)) {\n return { refusal: apply(notFoundResponse()), apply, carried: null };\n }\n if (isPolicyDeniedError(err)) {\n console.error(err);\n const refusal =\n isApi || isViewData ? policyDeniedResponse() : viewBreakResponse(policyDeniedView());\n return { refusal: apply(refusal), apply, carried: null };\n }\n throw err;\n } finally {\n ctx.destroy();\n }\n });\n}\n",
14
+ "import type { Server, ServerWebSocket, WebSocketHandler } from \"bun\";\n\nimport type { Application } from \"../../foundation/Application\";\nimport { signedInUser } from \"../../http/ChannelRouter\";\nimport { HttpRequest } from \"../../http/HttpRequest\";\nimport { type CarriedContext, RequestContext } from \"../../http/requestContext\";\nimport { kernelContext } from \"../../kernel/context\";\nimport { isShuttingDown } from \"../../server/shutdown\";\nimport { runGlobalMiddleware } from \"../router/globalMiddleware\";\nimport type { BroadcastRevocation } from \"./BroadcastDriver\";\nimport type { BroadcastManager } from \"./BroadcastManager\";\nimport {\n BROADCAST_PROTOCOL,\n CloseCode,\n SUBSCRIPTION_ID,\n type DeniedCode,\n type ServerFrame,\n} from \"./protocol\";\nimport { newSocketId, socketTag } from \"./socketTag\";\n\n/** What the hub keeps on each of its sockets (`ws.data`). */\nexport interface GemiSocketData {\n /** Marks a broadcast socket, as opposed to the dev server's HMR relay. */\n readonly gemiSocket: true;\n /** The hub that accepted it. After a dev reload that may not be the current one. */\n readonly hub: SocketHub;\n readonly socketId: string;\n readonly tag: string;\n /** The upgrade request, kept to rebuild a request context for every `sub`. */\n readonly request: { url: string; headers: [string, string][] };\n /** What the global middleware resolved for the upgrade: its user. */\n readonly carried: CarriedContext | null;\n /** The signed-in user's id at the upgrade, for limits and `revoke({ user })`. */\n readonly userId: string | null;\n readonly ip: string | null;\n /** Subscription id → its topic, `null` while it is being authorized. */\n readonly subs: Map<string, Subscription>;\n /** Topic → how many of this socket's subscriptions are on it. */\n readonly topics: Map<string, number>;\n rate: { windowStart: number; subs: number; pings: number };\n /**\n * The process, IP and user connection counts this socket holds. Taken\n * before the upgrade's first `await`, so concurrent upgrades cannot\n * overshoot the caps, and given back exactly once.\n */\n reservation: Reservation | null;\n /** The hub has closed it (backpressure, revoke, bye); its close is on the way. */\n closing: boolean;\n closed: boolean;\n}\n\ninterface Subscription {\n pattern: string;\n params: Record<string, string | number>;\n topic: string | null;\n}\n\ninterface Reservation {\n ip: string | null;\n userId: string | null;\n}\n\n/** Pings a socket may send per `subscribeRate` window before it is closed (1008). */\nconst PING_LIMIT_PER_WINDOW = 120;\n/** Over how long the re-authorizations after a `gap` are spread. */\nconst GAP_REAUTHORIZE_SPREAD_MS = 2_000;\n/** How often a subscription is authorized again when revocations keep landing. */\nconst MAX_AUTHORIZE_ATTEMPTS = 3;\n\ntype GemiSocket = ServerWebSocket<GemiSocketData>;\n\n/**\n * The WebSocket side of broadcasting, one per HTTP server process: accepts\n * upgrades on the configured path, speaks the `gemi.v1` protocol (see\n * `protocol.ts`), authorizes every subscription through the app's\n * `ChannelRouter`, and delivers what the driver hands it with\n * `server.publish`.\n *\n * Nothing here keeps a queue or a log. A socket that falls behind is closed\n * (`1013`), one whose user signs out is closed (`4001`), and a server that\n * stops says `bye` (`1012`); in every case the client reconnects and\n * refetches what it shows.\n */\nexport class SocketHub {\n static token = \"broadcast.sockets\";\n\n private server: Server<GemiSocketData> | null = null;\n private readonly sockets = new Set<GemiSocket>();\n private readonly byTopic = new Map<string, Set<GemiSocket>>();\n private readonly topicReady = new Map<string, Promise<void>>();\n private readonly perIp = new Map<string, number>();\n private readonly perUser = new Map<string, number>();\n /** Sockets held or being upgraded: the process cap's count. */\n private connections = 0;\n /** Bumped by every topic revocation; see `revokedAt`. */\n private revocationSeq = 0;\n /** Topic → the `revocationSeq` of its last revocation. */\n private readonly revokedAt = new Map<string, number>();\n private closing = false;\n /** Resolves once every socket `shutdown` closed is gone, or was cut. */\n private closed: Promise<void> | null = null;\n private onAllClosed: (() => void) | null = null;\n private startPromise: Promise<void> | null = null;\n\n constructor(\n private readonly manager: BroadcastManager,\n private readonly application: Application,\n ) {}\n\n private get config() {\n return this.manager.config;\n }\n\n /** Whether `req` is for the socket endpoint (an upgrade or not). */\n matches(req: Request): boolean {\n try {\n return new URL(req.url).pathname === this.config.path;\n } catch {\n return false;\n }\n }\n\n /** Sockets open on this process. */\n get size(): number {\n return this.sockets.size;\n }\n\n /**\n * Starts delivering: the driver's frames for this process go out with\n * `server.publish`. Call once the server is listening.\n */\n start(server: Server<any>): Promise<void> {\n this.server = server as Server<GemiSocketData>;\n this.startPromise ??= this.manager\n .start((topic, frame) => this.deliver(topic, frame), {\n onGap: () => this.onGap(),\n onRevoke: (revocation) => this.applyRevocation(revocation),\n })\n .catch((error) => {\n this.startPromise = null;\n console.error(\"[gemi] The broadcast driver could not start; events reach no socket.\", error);\n });\n return this.startPromise;\n }\n\n /**\n * Answers a request for the socket endpoint: upgrades it, or refuses it\n * with a status saying why. `undefined` once Bun has taken it over.\n */\n upgrade(req: Request, server: Server<any>): Promise<Response | undefined> {\n return this.run(() => this.tryUpgrade(req, server as Server<GemiSocketData>));\n }\n\n private async tryUpgrade(\n req: Request,\n server: Server<GemiSocketData>,\n ): Promise<Response | undefined> {\n if (this.closing || isShuttingDown()) {\n return refuse(503, \"The server is restarting.\", { \"Retry-After\": \"5\" });\n }\n if (req.method !== \"GET\" || req.headers.get(\"upgrade\")?.toLowerCase() !== \"websocket\") {\n return refuse(426, \"This endpoint only accepts WebSocket upgrades.\", {\n Upgrade: \"websocket\",\n });\n }\n const protocols = (req.headers.get(\"sec-websocket-protocol\") ?? \"\")\n .split(\",\")\n .map((protocol) => protocol.trim());\n if (!protocols.includes(BROADCAST_PROTOCOL)) {\n return refuse(400, `Open the socket with the \"${BROADCAST_PROTOCOL}\" subprotocol.`);\n }\n const origin = this.checkOrigin(req);\n if (origin !== true) return refuse(403, origin);\n if (this.connections >= this.config.maxConnectionsPerProcess) {\n return refuse(503, \"Too many connections.\", { \"Retry-After\": \"10\" });\n }\n const ip = clientIp(req, server);\n if (ip && (this.perIp.get(ip) ?? 0) >= this.config.maxConnectionsPerIp) {\n return refuse(429, \"Too many connections from this address.\", { \"Retry-After\": \"30\" });\n }\n // Counted now, before the first `await`: checks made while another\n // upgrade's middleware or session lookup is pending see it.\n const reservation = this.reserve(ip);\n let handedOver = false;\n try {\n const response = await this.authenticate(req, server, reservation);\n handedOver = response === undefined;\n return response;\n } finally {\n if (!handedOver) this.release(reservation);\n }\n }\n\n private async authenticate(\n req: Request,\n server: Server<GemiSocketData>,\n reservation: Reservation,\n ): Promise<Response | undefined> {\n // The global middleware covers the endpoint as it covers every route: a\n // gate that refuses a request refuses its socket.\n const outcome = await runGlobalMiddleware(req);\n if (outcome.refusal) return outcome.refusal;\n const carried = outcome.carried;\n if (this.closing || isShuttingDown()) {\n return refuse(503, \"The server is restarting.\", { \"Retry-After\": \"5\" });\n }\n\n let user: unknown;\n try {\n const httpRequest = new HttpRequest(req, {}, \"api\", this.config.path);\n user = await RequestContext.run(\n httpRequest,\n async () => {\n const ctx = RequestContext.getStore();\n try {\n return await signedInUser(httpRequest);\n } finally {\n ctx.destroy();\n }\n },\n carried,\n );\n } catch (error) {\n console.error(\"[gemi] Resolving the session of a socket upgrade failed.\", error);\n return refuse(503, \"The session could not be checked.\", { \"Retry-After\": \"5\" });\n }\n const userId = userIdOf(user);\n if (userId && (this.perUser.get(userId) ?? 0) >= this.config.maxConnectionsPerUser) {\n return refuse(429, \"Too many connections for this user.\", { \"Retry-After\": \"30\" });\n }\n if (userId) {\n reservation.userId = userId;\n this.perUser.set(userId, (this.perUser.get(userId) ?? 0) + 1);\n }\n\n const socketId = newSocketId();\n const data: GemiSocketData = {\n gemiSocket: true,\n hub: this,\n socketId,\n tag: socketTag(socketId),\n request: { url: req.url, headers: [...req.headers] },\n carried,\n userId,\n ip: reservation.ip,\n subs: new Map(),\n topics: new Map(),\n rate: { windowStart: Date.now(), subs: 0, pings: 0 },\n reservation,\n closing: false,\n closed: false,\n };\n const upgraded = server.upgrade(req, {\n headers: { \"Sec-WebSocket-Protocol\": BROADCAST_PROTOCOL },\n data,\n });\n if (!upgraded) return refuse(400, \"The WebSocket upgrade failed.\");\n return undefined;\n }\n\n /**\n * `true`, or why the upgrade is refused. A browser always sends `Origin` on\n * a WebSocket upgrade, and cookies ride along with it whatever the page\n * that opened it, so an upgrade carrying cookies must come from an allowed\n * origin and one without `Origin` is refused. A native client sends its\n * token in a header and no cookies, and may leave `Origin` out.\n */\n private checkOrigin(req: Request): true | string {\n const origin = req.headers.get(\"origin\");\n const hasCookies = Boolean(req.headers.get(\"cookie\"));\n if (!origin) {\n return hasCookies ? \"A socket that carries cookies must send an Origin header.\" : true;\n }\n return this.originAllowed(origin, req) ? true : \"This origin may not open a socket.\";\n }\n\n /** Whether `origin` may open a socket. */\n originAllowed(origin: string, req: Request): boolean {\n let url: URL;\n try {\n url = new URL(origin);\n } catch {\n return false;\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") return false;\n // The request's own host: the page and the socket share an origin.\n const host = req.headers.get(\"host\");\n if (host && url.host.toLowerCase() === host.toLowerCase()) return true;\n // Subdomains are never implied, `route.domains` ones included: those\n // serve tenant content, are same-site with the app (so its cookies ride\n // along), and a WebSocket has no CORS. A wildcard entry opts in.\n for (const allowed of [\n process.env.APP_URL,\n process.env.HOST_NAME,\n ...this.config.allowedOrigins,\n ]) {\n if (allowed && originMatches(allowed.trim(), url)) return true;\n }\n return false;\n }\n\n private reserve(ip: string | null): Reservation {\n this.connections++;\n if (ip) this.perIp.set(ip, (this.perIp.get(ip) ?? 0) + 1);\n return { ip, userId: null };\n }\n\n private release(reservation: Reservation) {\n this.connections--;\n decrement(this.perIp, reservation.ip);\n decrement(this.perUser, reservation.userId);\n }\n\n /** `Bun.serve`'s `websocket` option. */\n get websocket(): WebSocketHandler<GemiSocketData> {\n return {\n open: (ws) => ws.data.hub.onOpen(ws),\n message: (ws, message) => ws.data.hub.onMessage(ws, message),\n close: (ws) => ws.data.hub.onClose(ws),\n ...this.socketOptions(),\n };\n }\n\n /** The server-wide socket settings, also for a handler shared with HMR in dev. */\n socketOptions() {\n return {\n maxPayloadLength: this.config.maxInboundMessageBytes,\n idleTimeout: this.config.idleTimeout,\n // The hub closes a socket over `backpressureLimit` with 1013 at its\n // next delivery; Bun's own limit, at twice that, is the backstop for a\n // burst between two deliveries (Bun closes with 1006).\n backpressureLimit: this.config.backpressureLimit * 2,\n closeOnBackpressureLimit: true,\n sendPings: true,\n perMessageDeflate: false,\n } as const;\n }\n\n onOpen(ws: GemiSocket) {\n const data = ws.data;\n if (this.closing) {\n this.sayBye(ws);\n return;\n }\n this.sockets.add(ws);\n send(ws, {\n op: \"hello\",\n socketId: data.socketId,\n tag: data.tag,\n heartbeatMs: this.config.heartbeatMs,\n });\n }\n\n onMessage(ws: GemiSocket, message: string | Buffer) {\n if (typeof message !== \"string\") {\n ws.close(CloseCode.UnsupportedData, \"Frames are JSON text.\");\n return;\n }\n if (message.length > this.config.maxInboundMessageBytes) {\n ws.close(CloseCode.PolicyViolation, \"Frame too large.\");\n return;\n }\n let frame: any;\n try {\n frame = JSON.parse(message);\n } catch {\n ws.close(CloseCode.UnsupportedData, \"Frames are JSON text.\");\n return;\n }\n switch (frame?.op) {\n case \"ping\":\n if (this.countPing(ws)) send(ws, { op: \"pong\" });\n return;\n case \"sub\":\n this.subscribe(ws, frame).catch((error) => {\n console.error(\"[gemi] A socket subscription failed.\", error);\n if (typeof frame.id === \"string\" && ws.data.subs.has(frame.id)) {\n const sub = ws.data.subs.get(frame.id)!;\n ws.data.subs.delete(frame.id);\n if (sub.topic && !ws.data.closed) this.leave(ws, sub.topic);\n if (!ws.data.closed) deny(ws, frame.id, \"error\");\n }\n });\n return;\n case \"unsub\":\n this.unsubscribeFrame(ws, frame);\n return;\n default:\n ws.close(CloseCode.UnsupportedData, \"Unknown op.\");\n }\n }\n\n onClose(ws: GemiSocket) {\n const data = ws.data;\n if (data.closed) return;\n data.closed = true;\n for (const [, sub] of data.subs) {\n if (sub.topic) this.leave(ws, sub.topic);\n }\n data.subs.clear();\n this.sockets.delete(ws);\n if (data.reservation) {\n this.release(data.reservation);\n data.reservation = null;\n }\n if (this.closing && this.sockets.size === 0) this.onAllClosed?.();\n }\n\n private rateWindow(ws: GemiSocket) {\n const rate = ws.data.rate;\n const now = Date.now();\n if (now - rate.windowStart >= this.config.subscribeRate.windowMs) {\n rate.windowStart = now;\n rate.subs = 0;\n rate.pings = 0;\n }\n return rate;\n }\n\n /**\n * Counts a `sub`. Only `sub` frames count: an `unsub` costs the server\n * nothing to speak of, and counting it would charge a component's every\n * mount and unmount twice.\n */\n private countSub(ws: GemiSocket): \"ok\" | \"limited\" | \"closed\" {\n const { limit } = this.config.subscribeRate;\n const rate = this.rateWindow(ws);\n rate.subs++;\n if (rate.subs > limit * 2) {\n console.warn(`[gemi] Socket closed for sending too many subscribe frames (1008).`);\n ws.close(CloseCode.PolicyViolation, \"Too many subscribe frames.\");\n return \"closed\";\n }\n return rate.subs > limit ? \"limited\" : \"ok\";\n }\n\n /** `false` when the socket was closed for pinging too often. */\n private countPing(ws: GemiSocket): boolean {\n const rate = this.rateWindow(ws);\n rate.pings++;\n if (rate.pings <= PING_LIMIT_PER_WINDOW) return true;\n ws.close(CloseCode.PolicyViolation, \"Too many pings.\");\n return false;\n }\n\n private async subscribe(ws: GemiSocket, frame: Record<string, unknown>) {\n const data = ws.data;\n const id = frame.id;\n if (typeof id !== \"string\" || !SUBSCRIPTION_ID.test(id)) {\n ws.close(CloseCode.UnsupportedData, \"A sub needs an id.\");\n return;\n }\n const rate = this.countSub(ws);\n if (rate === \"closed\") return;\n if (rate === \"limited\") return deny(ws, id, \"rate_limited\");\n const pattern = frame.ch;\n const params = frame.p ?? {};\n if (typeof pattern !== \"string\" || !isParams(params)) return deny(ws, id, \"invalid\");\n if (data.subs.has(id)) return deny(ws, id, \"invalid\");\n if (data.subs.size >= this.config.maxChannelsPerSocket) return deny(ws, id, \"limit\");\n\n const sub: Subscription = { pattern, params, topic: null };\n data.subs.set(id, sub);\n if (!this.manager.channels) {\n data.subs.delete(id);\n return deny(ws, id, \"unknown_channel\");\n }\n\n // A revocation of the topic committed while the authorization ran may\n // not have been seen by it: authorize again until none has.\n let result: AuthorizeResult;\n for (let attempt = 1; ; attempt++) {\n const seq = this.revocationSeq;\n result = await this.authorize(ws, sub);\n // Unsubscribed, or the socket closed, while it was being authorized.\n if (data.closed || data.subs.get(id) !== sub) return;\n if (result.ok !== true) break;\n if ((this.revokedAt.get(result.topic) ?? 0) <= seq) break;\n if (attempt >= MAX_AUTHORIZE_ATTEMPTS) {\n data.subs.delete(id);\n return deny(ws, id, \"error\");\n }\n }\n if (result.ok !== true) {\n data.subs.delete(id);\n return deny(ws, id, (result as { code: DeniedCode }).code);\n }\n\n sub.topic = result.topic;\n try {\n await this.join(ws, result.topic);\n } catch (error) {\n console.error(\n `[gemi] The broadcast driver could not subscribe to \"${result.topic}\".`,\n error,\n );\n if (data.subs.get(id) === sub) {\n data.subs.delete(id);\n if (!data.closed) this.leave(ws, result.topic);\n deny(ws, id, \"error\");\n }\n return;\n }\n if (data.closed || data.subs.get(id) !== sub) return;\n // Only now: the driver delivers this topic to this process, so the\n // resync the client runs on this ack cannot miss an event.\n send(ws, { op: \"subscribed\", id, t: result.topic });\n }\n\n /** Runs the channel's authorization for `sub`, as the socket's upgrade request. */\n private authorize(ws: GemiSocket, sub: Subscription): Promise<AuthorizeResult> {\n const data = ws.data;\n const channels = this.manager.channels;\n if (!channels) return Promise.resolve({ ok: false, code: \"unknown_channel\" });\n return this.run(() =>\n channels.authorize(\n new Request(data.request.url, { headers: data.request.headers }),\n sub.pattern,\n sub.params,\n { carried: data.carried },\n ),\n ) as Promise<AuthorizeResult>;\n }\n\n private unsubscribeFrame(ws: GemiSocket, frame: Record<string, unknown>) {\n const id = frame.id;\n if (typeof id !== \"string\" || !SUBSCRIPTION_ID.test(id)) {\n ws.close(CloseCode.UnsupportedData, \"An unsub needs an id.\");\n return;\n }\n const sub = ws.data.subs.get(id);\n if (!sub) return;\n ws.data.subs.delete(id);\n if (sub.topic) this.leave(ws, sub.topic);\n }\n\n /** Puts `ws` on `topic`, and resolves once the driver delivers the topic here. */\n private join(ws: GemiSocket, topic: string): Promise<void> {\n const data = ws.data;\n const count = data.topics.get(topic) ?? 0;\n data.topics.set(topic, count + 1);\n if (count === 0) {\n ws.subscribe(topic);\n let set = this.byTopic.get(topic);\n if (!set) {\n set = new Set();\n this.byTopic.set(topic, set);\n const ready = Promise.resolve().then(() => this.manager.topicAdded(topic));\n this.topicReady.set(topic, ready);\n // A failed `topicAdded` is not cached: the next join tries again.\n ready.catch(() => {\n if (this.topicReady.get(topic) === ready) this.topicReady.delete(topic);\n });\n }\n set.add(ws);\n }\n return this.topicReady.get(topic) ?? Promise.resolve();\n }\n\n private leave(ws: GemiSocket, topic: string) {\n const data = ws.data;\n const count = data.topics.get(topic) ?? 0;\n if (count > 1) {\n data.topics.set(topic, count - 1);\n return;\n }\n data.topics.delete(topic);\n if (!data.closed) ws.unsubscribe(topic);\n const set = this.byTopic.get(topic);\n if (!set) return;\n set.delete(ws);\n if (set.size > 0) return;\n this.byTopic.delete(topic);\n this.topicReady.delete(topic);\n Promise.resolve()\n .then(() => this.manager.topicRemoved(topic))\n .catch((error) =>\n console.error(`[gemi] The broadcast driver could not unsubscribe from \"${topic}\".`, error),\n );\n }\n\n /**\n * The driver's delivery for this process. A socket already over the\n * backpressure limit is closed first (1013): it would only fall further\n * behind, and its client recovers by reconnecting and refetching.\n */\n deliver(topic: string, frame: string) {\n const set = this.byTopic.get(topic);\n if (!set || !this.server) return;\n const limit = this.config.backpressureLimit;\n for (const ws of set) {\n if (!ws.data.closing && ws.getBufferedAmount() > limit) {\n console.warn(`[gemi] Socket closed for backpressure (1013) on \"${topic}\".`);\n closeSocket(ws, CloseCode.TryAgainLater, \"Too far behind; reconnect.\");\n }\n }\n this.server.publish(topic, frame);\n }\n\n /**\n * The driver may have lost frames, revocations included (a Redis\n * subscriber that reconnected). Clients are told to resync, and every\n * subscription is authorized again, as after `revoke({ channel })`, so\n * one whose access a missed revocation ended is denied. Spread over\n * `GAP_REAUTHORIZE_SPREAD_MS`, so a Redis blip does not send every\n * authorization to the database at once.\n */\n private onGap() {\n this.sendAll({ op: \"gap\" });\n for (const topic of this.byTopic.keys()) {\n const delay = Math.floor(Math.random() * GAP_REAUTHORIZE_SPREAD_MS);\n const timer = setTimeout(() => {\n if (!this.closing) this.applyRevocation({ topic });\n }, delay);\n (timer as { unref?: () => void }).unref?.();\n }\n }\n\n /** Applies a revocation that reached this process. */\n applyRevocation(revocation: BroadcastRevocation) {\n if (\"user\" in revocation) {\n for (const ws of this.sockets) {\n if (ws.data.userId === revocation.user && !ws.data.closing) {\n closeSocket(ws, CloseCode.Revoked, \"Revoked.\");\n }\n }\n return;\n }\n const topic = revocation.topic;\n const seq = ++this.revocationSeq;\n this.revokedAt.set(topic, seq);\n const set = this.byTopic.get(topic);\n if (!set) return;\n for (const ws of set) void this.reauthorize(ws, topic, seq);\n }\n\n /**\n * After `revoke({ channel })`: every subscription `ws` has on `topic` is\n * authorized again, as the socket's upgrade request. The ones refused are\n * denied with `revoked`; the others stay, and get a fresh `subscribed` so\n * the client resyncs whatever was published while the topic was paused.\n * The socket receives nothing on the topic until the answers are in.\n */\n private async reauthorize(ws: GemiSocket, topic: string, seq: number) {\n const data = ws.data;\n const subs = [...data.subs].filter(([, sub]) => sub.topic === topic);\n if (subs.length === 0) return;\n ws.unsubscribe(topic);\n const results = await Promise.all(\n subs.map(([, sub]) =>\n this.authorize(ws, sub).catch((error) => {\n console.error(`[gemi] Authorizing \"${topic}\" again after a revoke failed.`, error);\n return { ok: false, code: \"revoked\" } as AuthorizeResult;\n }),\n ),\n );\n if (data.closed) return;\n // A later revocation of the topic runs its own pass, and decides.\n if (this.revokedAt.get(topic) !== seq) return;\n subs.forEach(([id, sub], index) => {\n const result = results[index];\n if (data.subs.get(id) !== sub) return;\n if (result.ok === true && result.topic === topic) return;\n data.subs.delete(id);\n this.leave(ws, topic);\n deny(ws, id, \"revoked\");\n });\n if (!data.topics.has(topic)) return;\n ws.subscribe(topic);\n for (const [id, sub] of data.subs) {\n if (sub.topic === topic) send(ws, { op: \"subscribed\", id, t: topic });\n }\n }\n\n private sendAll(frame: ServerFrame) {\n const text = JSON.stringify(frame);\n for (const ws of this.sockets) ws.send(text);\n }\n\n /**\n * Stops accepting sockets and says `bye` to every open one, with a\n * jittered `retryAfter` (1–5 s) so a restart's reconnects do not arrive at\n * once, then closes them (1012). Sockets that have not closed after\n * `terminateAfterMs` are cut. Idempotent.\n *\n * Resolves once every socket has closed, or at `terminateAfterMs` when the\n * rest were cut: by the hub's own count, which the drain waits on instead\n * of Bun's (on a loaded CI runner, Bun's graceful `stop()` was seen to wait\n * on terminated sockets for good).\n */\n shutdown(options: { terminateAfterMs?: number } = {}): Promise<void> {\n if (this.closed) return this.closed;\n this.closing = true;\n this.closed = new Promise<void>((resolve) => {\n this.onAllClosed = resolve;\n });\n const sockets = [...this.sockets];\n if (sockets.length === 0) this.onAllClosed?.();\n if (sockets.length > 0) {\n console.log(`[gemi] Closing ${sockets.length} broadcast socket(s) (1012).`);\n }\n for (const ws of sockets) this.sayBye(ws);\n // Every one of them, closed or not: a socket whose close frame was\n // answered can still hold the connection open, and a graceful\n // `server.stop()` waits on it.\n const timer = setTimeout(() => {\n for (const ws of sockets) {\n try {\n ws.terminate();\n } catch {\n // Already gone.\n }\n }\n this.onAllClosed?.();\n }, options.terminateAfterMs ?? 2_000);\n (timer as { unref?: () => void }).unref?.();\n return this.closed;\n }\n\n /** Whether `shutdown` ran. */\n get isClosing(): boolean {\n return this.closing;\n }\n\n private sayBye(ws: GemiSocket) {\n send(ws, {\n op: \"bye\",\n code: CloseCode.Restart,\n retryAfter: 1_000 + Math.floor(Math.random() * 4_000),\n });\n closeSocket(ws, CloseCode.Restart, \"Server restarting.\");\n }\n\n /** In the application's scope, as a request is: facades resolve from it. */\n private run<T>(fn: () => T): T {\n return kernelContext.run(this.application, fn);\n }\n}\n\ntype AuthorizeResult = { ok: true; topic: string } | { ok: false; code: DeniedCode };\n\n/**\n * Whether an `allowedOrigins` entry (or `APP_URL` / `HOST_NAME`) admits\n * `url`. An entry is an origin (`https://app.example.com`), a bare host\n * (`app.example.com`), or a wildcard for the subdomains of a host\n * (`*.example.com`, `https://*.example.com`), which does not admit the host\n * itself.\n */\nexport function originMatches(allowed: string, url: URL): boolean {\n const wildcard = /^(?:(https?):\\/\\/)?\\*\\.([^/:]+)(?::(\\d+))?\\/?$/i.exec(allowed);\n if (wildcard) {\n const [, scheme, base, port] = wildcard;\n if (scheme && `${scheme.toLowerCase()}:` !== url.protocol) return false;\n if ((port ?? \"\") !== url.port) return false;\n return url.hostname.toLowerCase().endsWith(`.${base.toLowerCase().replace(/\\.$/, \"\")}`);\n }\n if (/^https?:\\/\\//i.test(allowed)) {\n try {\n return new URL(allowed).origin === url.origin;\n } catch {\n return false;\n }\n }\n // A bare host.\n return allowed.toLowerCase().replace(/\\/$/, \"\") === url.host.toLowerCase();\n}\n\nfunction closeSocket(ws: GemiSocket, code: number, reason: string) {\n ws.data.closing = true;\n ws.close(code, reason);\n}\n\nfunction send(ws: GemiSocket, frame: ServerFrame) {\n ws.send(JSON.stringify(frame));\n}\n\nfunction deny(ws: GemiSocket, id: string, code: DeniedCode) {\n send(ws, { op: \"denied\", id, code });\n}\n\nfunction refuse(status: number, message: string, headers: Record<string, string> = {}) {\n return new Response(message, {\n status,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\", ...headers },\n });\n}\n\nfunction isParams(value: unknown): value is Record<string, string | number> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n return Object.values(value).every((v) => typeof v === \"string\" || typeof v === \"number\");\n}\n\nfunction userIdOf(user: unknown): string | null {\n const id = (user as { id?: unknown } | null)?.id;\n return typeof id === \"string\" || typeof id === \"number\" ? String(id) : null;\n}\n\n/**\n * The client address: what the production server left in `X-Forwarded-For`\n * (see `forwardedFor.ts`), or the socket's peer.\n */\nfunction clientIp(req: Request, server: Server<any>): string | null {\n const forwarded = req.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim();\n if (forwarded) return forwarded;\n try {\n return server.requestIP(req)?.address ?? null;\n } catch {\n return null;\n }\n}\n\nfunction decrement(map: Map<string, number>, key: string | null) {\n if (!key) return;\n const count = (map.get(key) ?? 0) - 1;\n if (count <= 0) map.delete(key);\n else map.set(key, count);\n}\n",
15
+ "import { assertChannelPatterns, type ChannelRouterClass } from \"../../http/ChannelRouter\";\nimport { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { BroadcastDriver } from \"./BroadcastDriver\";\nimport { BroadcastManager } from \"./BroadcastManager\";\nimport { RedisBroadcastDriver } from \"./RedisBroadcastDriver\";\nimport type { BroadcastConfig } from \"./config\";\nimport { SocketHub } from \"./SocketHub\";\n\nexport class BroadcastServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n BroadcastManager,\n () =>\n new BroadcastManager(this.app.config.get<BroadcastConfig>(\"broadcast\", {}), {\n application: this.app,\n channels: this.app.config.get<ChannelRouterClass | undefined>(\"route.channels\"),\n }),\n );\n // The WebSocket transport, built by the HTTP server (`Kernel.sockets()`)\n // when the app declares `route.channels`.\n this.app.singleton(SocketHub, () => new SocketHub(this.app.make(BroadcastManager), this.app));\n }\n\n /**\n * Fails the boot on a malformed channel pattern, rather than refusing every\n * subscription to it at runtime.\n */\n boot() {\n const Channels = this.app.config.get<ChannelRouterClass | undefined>(\"route.channels\");\n if (Channels) assertChannelPatterns(new Channels());\n const config = this.app.config.get<BroadcastConfig>(\"broadcast\", {});\n // A driver the app builds (an instance, or a factory) may be the redis\n // one too: build the manager to see. A name needs no manager.\n const built =\n typeof config.driver === \"function\" || typeof config.driver === \"object\"\n ? this.app.make(BroadcastManager).driver\n : undefined;\n assertSharedSecret(config, process.env, built);\n }\n\n /**\n * Says `bye` to the sockets (the server's drain did already, in\n * production; a dev reload retiring this application did not), then stops\n * receiving and closes the driver's connections.\n */\n async shutdown() {\n if (this.app.resolved(SocketHub)) this.app.make(SocketHub).shutdown();\n if (!this.app.resolved(BroadcastManager)) return;\n await this.app.make(BroadcastManager).close();\n }\n}\n\n/**\n * The redis driver carries one frame to every instance, and a `toOthers`\n * frame names the socket to skip by a tag keyed from `SECRET` (`socketTag`).\n * Without `SECRET` each process keys it at random, so the sender's own socket\n * on another instance would not recognise its tag and would get its own\n * emit back. Fails the boot in production; warns elsewhere.\n */\nexport function assertSharedSecret(\n config: BroadcastConfig,\n env: Record<string, string | undefined> = process.env,\n driver?: BroadcastDriver,\n): void {\n const redis = config.driver === \"redis\" || driver instanceof RedisBroadcastDriver;\n if (!redis || env.SECRET) return;\n const message =\n `[gemi] The \"redis\" broadcast driver needs SECRET set, the same on every ` +\n `instance: Broadcast.toOthers tags the sender's socket with a key derived ` +\n `from it, and every instance must derive the same one.`;\n if (env.NODE_ENV === \"production\") throw new Error(message);\n console.warn(message);\n}\n",
13
16
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { ChangeFeedConfig } from \"./config\";\nimport { ChangeFeedManager } from \"./ChangeFeedManager\";\n\nexport class ChangeFeedServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n ChangeFeedManager,\n () =>\n new ChangeFeedManager(this.app.config.get<ChangeFeedConfig>(\"changeFeed\", {}), {\n application: this.app,\n }),\n );\n }\n\n /**\n * Ends every subscription and closes the `LISTEN` connection. Streams have\n * already ended by then: each stops at its next keepalive once the server\n * starts shutting down, so the request drain does not wait on them.\n */\n async shutdown() {\n if (!this.app.resolved(ChangeFeedManager)) return;\n await this.app.make(ChangeFeedManager).close();\n }\n}\n",
14
17
  "import { ServiceProvider } from \"../support/ServiceProvider\";\nimport type { AuthConfig } from \"./config\";\nimport { AuthManager } from \"./AuthManager\";\nimport { ConnectionManager } from \"./connections/ConnectionManager\";\n\nexport class AuthServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n AuthManager,\n () => new AuthManager(this.app.config.get<AuthConfig>(\"auth\", {})),\n );\n this.app.singleton(ConnectionManager, () => {\n const config = this.app.config.get<AuthConfig>(\"auth\", {});\n return new ConnectionManager({\n providers: config.connections ?? {},\n store: config.connectionStore ?? undefined,\n });\n });\n }\n}\n",
15
18
  "import { kernelContext } from \"../../kernel/context\";\nimport { LockManager } from \"../lock/LockManager\";\nimport { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { discoverCronJobs } from \"../discovery\";\nimport { scheduleConfigDefaults, type ScheduleConfig } from \"./config\";\nimport { Scheduler } from \"./Scheduler\";\n\n/**\n * How far inside the provider deadline the drain stops, so there is time left\n * to name the ticks it abandoned before `Application` stops waiting for this\n * provider. The same margin as the queue's drain, for the same reason: a\n * tenth of the budget, capped, so a deadline of a few milliseconds still\n * spends most of itself waiting.\n */\nconst REPORT_MARGIN_MS = 100;\n\nconst reportMargin = (timeoutMs: number) => Math.min(REPORT_MARGIN_MS, Math.floor(timeoutMs / 10));\n\nexport class ScheduleServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n Scheduler,\n () =>\n new Scheduler(\n withDefaults(\n scheduleConfigDefaults(),\n this.app.config.get<ScheduleConfig>(\"schedule\", {}),\n ),\n ),\n );\n }\n\n /**\n * Resolves the schedule, then starts it.\n *\n * Cron jobs are scheduled in phase two, not in `register()`: a job body is\n * free to resolve any service, and by the time `boot()` runs every provider\n * has registered. Each tick re-enters the application context so the job sees\n * the same container a request handler would.\n *\n * ### Why the raw slice and not the scheduler's config\n *\n * The decision here is whether the app said anything, and by the time the\n * scheduler holds a config it can no longer tell: `withDefaults` treats an\n * absent key and an `undefined` one alike and substitutes the default `[]`,\n * which is the same value an app writes when it means \"nothing scheduled, and\n * I mean it\". Reading the slice before defaults are applied is the only place\n * that difference still exists.\n *\n * So: `jobs` present, including `jobs: []`, is used verbatim and no directory\n * is read. Absent or `undefined` — which includes an app with no `schedule`\n * slice at all — the classes under `jobsDir` are, which is the case #323 is\n * about: a cron job that is written and never listed fires never, and nothing\n * downstream is waiting to notice.\n */\n async boot() {\n const scheduler = this.app.make(Scheduler);\n const slice = this.app.config.get<ScheduleConfig>(\"schedule\", {});\n\n if (slice.jobs === undefined) {\n const { jobsDir } = withDefaults(scheduleConfigDefaults(), slice);\n scheduler.useJobs(await discoverCronJobs(jobsDir));\n }\n\n // Resolved, listed, and not started.\n //\n // `gemi run` sets this on the process it spawns. Booting the application is\n // how a console command reaches the container, and starting the schedule is\n // a side effect of that which nobody asked for: a `gemi run backfill` that\n // takes four minutes would otherwise fire the application's whole cron\n // schedule in a process no operator is watching, and `Bun.cron` handles hold\n // the loop open besides.\n //\n // Deliberately above `start` and below `useJobs`, so `app(Scheduler).jobs`\n // still answers honestly — a command that wants to fire a tick by hand can,\n // and a test asking what this application schedules gets the same answer\n // either way.\n //\n // An environment variable rather than a config field, because this is a\n // property of *this process* and not of the application: the same variable\n // is how a deploy runs one cron dyno beside several web ones, and a config\n // slice would have to know which command started it.\n if (process.env.GEMI_NO_SCHEDULE === \"1\") return;\n\n const app = this.app;\n // The queue's locks, so `withoutOverlapping` and `onOneServer` hold across\n // the instances sharing its storage. Resolved per tick that asks.\n if (app.bound(LockManager)) scheduler.useLocks(() => app.make(LockManager));\n scheduler.start((cb) => kernelContext.run(app, cb));\n }\n\n /**\n * Stops the schedule and waits for the ticks already running, on the way out\n * of a server told to stop.\n *\n * Stopping first is the point. Without it `Bun.cron` kept firing for the\n * whole drain window, starting ticks the process was about to exit under,\n * and a tick already running when the process exited was cut off halfway\n * through its `callback` — on a platform that recycles replicas on every\n * release, that is every release.\n *\n * The wait is bounded a little inside what is left of the shared provider\n * deadline, like the queue's, so that this is what names the ticks it gave\n * up on rather than `Application`'s generic \"did not finish within the\n * provider shutdown deadline\", which names no job at all. *\n * Ticks left running resolve `{ abandoned: true }`, so `Application`\n * reports this provider in `timedOut` and the process exits 1, as it does\n * for a queued job cut off at the deadline (#580).\n */\n async shutdown(options?: { timeoutMs: number }) {\n // `boot()` always resolves it; this is for an application that shuts down\n // without having booted, where building a scheduler would be pointless.\n if (!this.app.resolved(Scheduler)) return;\n const scheduler = this.app.make(Scheduler);\n if (scheduler.running > 0) {\n console.log(`[gemi] Shutting down: waiting for ${scheduler.running} running cron tick(s).`);\n }\n const budget = options?.timeoutMs;\n const { unfinished } = await scheduler.drain(\n budget === undefined ? Infinity : Math.max(0, budget - reportMargin(budget)),\n );\n if (unfinished.length > 0) {\n console.error(\n `[gemi] Cron jobs still running at shutdown: ` +\n unfinished\n .map((tick) => `${tick.name} (started ${tick.startedAt.toISOString()})`)\n .join(\", \"),\n );\n return { abandoned: true };\n }\n }\n}\n",
@@ -18,8 +21,9 @@
18
21
  "import { Log } from \"../../facades/Log\";\nimport { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { featuresConfigDefaults, type FeaturesConfig } from \"./config\";\nimport { FeatureManager } from \"./FeatureManager\";\nimport { DatabaseFeatureFlagSource } from \"./sources/DatabaseFeatureFlagSource\";\n\nexport class FeaturesServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(FeatureManager, () => {\n const declared = this.app.config.get<FeaturesConfig>(\"features\", {});\n const config = withDefaults(featuresConfigDefaults(), declared);\n\n // The default source is constructed by `featuresConfigDefaults()` with the\n // default model name, so a `model` override would otherwise be ignored\n // unless the app also replaced the source. Rebuild it here instead of\n // making every app that renames the table also know about the source.\n //\n // Keyed on what the *application* wrote, not on the merged values. The\n // merged `model` is always set — it defaults to `\"FeatureFlag\"` — so\n // comparing it against the source's name would fire for an app that\n // configured only `source: new DatabaseFeatureFlagSource(\"Flags\")`,\n // throwing that source away and pointing the replacement at a table the\n // app never mentioned. Every feature would then read off with nothing to\n // explain why.\n //\n // An explicit `source` always wins: it is the more specific statement, and\n // it is the only one of the two that can name something other than the\n // local table.\n if (declared?.model !== undefined && declared?.source === undefined) {\n config.source = new DatabaseFeatureFlagSource(declared.model);\n } else if (\n declared?.model !== undefined &&\n declared.source instanceof DatabaseFeatureFlagSource &&\n declared.source.modelName !== declared.model\n ) {\n Log.warning(\n `app/config/features.ts sets \\`model: \"${declared.model}\"\\` and a source reading \"${declared.source.modelName}\". The source wins; drop \\`model\\` to silence this.`,\n );\n }\n\n return new FeatureManager(config, (message) => Log.warning(message));\n });\n }\n\n async boot() {\n const features = this.app.make(FeatureManager);\n if (!features.config.enabled) return;\n\n // Warmed at boot so the first request is served from memory rather than\n // paying for the cold load. Wrapped because a database that is not up yet\n // must not fail the boot — the store fails closed, every feature reads off,\n // and it recovers on its own once the next TTL elapses.\n try {\n await features.refresh();\n } catch (error) {\n Log.error(\n `Could not warm the feature flag cache at boot. ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n}\n",
19
22
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { MailConfig } from \"./config\";\nimport { MailManager } from \"./MailManager\";\n\nexport class MailServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n MailManager,\n () => new MailManager(this.app.config.get<MailConfig>(\"mail\", {})),\n );\n }\n}\n",
20
23
  "import { encryptedColumnsInRegistry } from \"../../orm/encryption\";\nimport { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { EncryptionConfig } from \"./config\";\nimport { Encrypter, EncryptionKeyError } from \"./Encrypter\";\n\nexport class EncryptionServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n Encrypter,\n () => new Encrypter(this.app.config.get<EncryptionConfig>(\"encryption\", {})),\n );\n }\n\n /**\n * A bad key fails the boot, not the first request that reads an encrypted\n * column: constructing the `Encrypter` validates every key, and an app whose\n * models have encrypted columns, or that configures OAuth connections,\n * must have one configured. An app with\n * neither pays for nothing but this check.\n */\n boot() {\n const encrypter = this.app.make(Encrypter);\n if (encrypter.configured) return;\n\n // OAuth connections (#845) keep their tokens encrypted in gemi's table.\n const auth = this.app.config.get<{ connections?: Record<string, unknown>; connectionStore?: unknown }>(\"auth\", {});\n const connections = Object.keys(auth?.connections ?? {});\n if (connections.length > 0 && !auth?.connectionStore) {\n throw new EncryptionKeyError(\n `auth.connections (${connections.join(\", \")}) keeps OAuth tokens encrypted, ` +\n \"but no encryption key is configured. Add app/config/encryption.ts \" +\n \"(defineEncryptionConfig({ keys: { k1: process.env.APP_ENCRYPTION_KEY } })) \" +\n \"and list it as `encryption` in your Kernel's config. Generate a key \" +\n \"with `openssl rand -base64 32`.\",\n );\n }\n\n const columns = encryptedColumnsInRegistry();\n if (columns.length === 0) return;\n\n throw new EncryptionKeyError(\n `${columns.join(\", \")} ${columns.length === 1 ? \"is an encrypted column\" : \"are encrypted columns\"}, ` +\n \"but no encryption key is configured. Add app/config/encryption.ts \" +\n \"(defineEncryptionConfig({ keys: { k1: process.env.APP_ENCRYPTION_KEY } })) \" +\n \"and list it as `encryption` in your Kernel's config. Generate a key \" +\n \"with `openssl rand -base64 32`.\",\n );\n }\n}\n",
24
+ "import type { ChannelTarget } from \"./channels\";\n\n// Kept apart from `BroadcastEvent.ts` so `EventManager` can recognise a\n// broadcast event without importing a subclass of `Event`, which would close\n// the import cycle `Event` -> `EventManager` -> `BroadcastEvent` -> `Event`.\n\n/**\n * Marks a `BroadcastEvent` instance. A symbol in the global registry rather\n * than `instanceof`, for the reason `Event` gives: a production build can hold\n * two copies of an event class, and `instanceof` would tell them apart.\n */\nexport const BROADCAST_EVENT = Symbol.for(\"gemi.broadcastEvent\");\n\n/** What `EventManager` needs of an event to broadcast it. */\nexport interface BroadcastableEvent {\n broadcastOn(): ChannelTarget | string | ReadonlyArray<ChannelTarget | string>;\n broadcastAs(): string;\n broadcastWith(): unknown;\n}\n\n/** Whether `event` is a `BroadcastEvent`, from any copy of gemi. */\nexport function isBroadcastEvent(event: unknown): event is BroadcastableEvent {\n return (\n typeof event === \"object\" &&\n event !== null &&\n (event as Record<symbol, unknown>)[BROADCAST_EVENT] === true\n );\n}\n",
21
25
  "import { app } from \"../../foundation/app\";\nimport { Job } from \"../queue/Job\";\nimport { EventManager } from \"./EventManager\";\nimport type { Listener, ListenerClass } from \"./Listener\";\n\n/**\n * The adapter that lets `queued = true` be one line: a `Job` subclass, built at\n * registration, that runs exactly one listener.\n *\n * Retries, `maxAttempts`, dead-lettering, `concurrency` and worker-thread\n * execution are four features the queue already has, already documents for\n * applications, and is already tested on. A second queue for listeners would be\n * four features that are almost the same as those, differing in ways nobody\n * decided. So a queued listener is not queued by anything written here — it is\n * a job, and everything after `push` is the queue's.\n */\n\n/**\n * The name a listener's synthetic job is registered under.\n *\n * Prefixed, and visibly so. The synthetic jobs land in\n * `QueueManager.registeredJobs` alongside the app's own, because that getter is\n * documented as reporting what the manager was handed and a queued listener\n * genuinely is something the queue will run — hiding them would make a queue\n * introspection tool lie about what is about to execute. The prefix is what\n * keeps an author from reading `SendWelcomeEmail` there and looking for a job\n * file they never wrote.\n */\nexport function listenerJobName(listenerName: string): string {\n return `listener:${listenerName}`;\n}\n\n/**\n * Builds the `Job` subclass that runs one queued listener.\n *\n * `instance` is the listener the caller already constructed to read `queued`\n * off; the fields that decide how and where the work runs are read from that one\n * instance rather than from a fresh one per attempt, so a listener's\n * constructor runs once at boot instead of once per retry.\n *\n * What crosses the queue is `[eventName, constructorArguments]` as JSON — a\n * name and the arguments, never the event instance and never the classes. That\n * is invariant 1 at its second boundary: the class objects on the pushing side\n * and the running side can come from two different module graphs (a minified\n * bundle and a source-side discovery walk), so a name declared as a string\n * literal is the only thing both ends agree on. `EventManager.rehydrate` turns\n * it back into an event.\n */\nexport function jobForListener(\n listener: ListenerClass,\n instance: Listener,\n): new () => Job {\n refuseImplicitName(listener);\n\n const attempts = instance.maxAttempts;\n const delays = instance.backoff;\n const inWorker = instance.worker;\n const boundTo = listener.event.name;\n\n const job = class extends Job {\n maxAttempts = attempts;\n backoff = delays;\n worker = inWorker;\n\n async run(...payload: unknown[]) {\n const [eventName, args] = readPayload(payload);\n const event = app(EventManager).rehydrate(eventName, args);\n await new listener().handle(event);\n }\n\n // The queue's failure path is silent unless a job writes to it: `onFail`\n // and `onDeadletter` on `Job` are empty bodies, and `QueueManager.run`\n // routes every rejection into exactly those two. Without these overrides a\n // queued listener that throws produces no output anywhere — `dispatch`\n // returned long ago, the sync path's \"the listener X threw while handling\n // Y\" line is on a branch this listener never takes, and the last thing that\n // happens is the entry leaving the queue. A welcome email that stopped\n // being sent in production would look exactly like one that was never\n // dispatched.\n //\n // That is also what makes `rehydrate`'s throw the informative failure it is\n // documented as: a payload naming an event this process does not know is\n // the shape a `worker = true` listener hits when its thread booted a\n // different build of the application, and it is unreachable from the\n // dispatcher's stack.\n //\n // Both hooks, not one. `onFail` carries the error and fires per attempt, so\n // a listener failing differently on each is visible; `onDeadletter` fires\n // once and reports the fact no attempt is left, which is a different thing\n // to know and the only line that means the work is gone. The final attempt\n // logs both, deliberately.\n //\n // The event is named from `static event` rather than from the payload:\n // reading the payload here means parsing it, and a throw out of either hook\n // would escape through `QueueManager.run`'s `catch` into a `run()` nobody\n // awaits.\n onFail(error: Error) {\n console.error(\n `The listener ${listener.name} threw while handling ${boundTo} off ` +\n `the queue. The queue will retry it up to ${attempts} times in ` +\n `total; nothing the dispatcher did is waiting on it.`,\n error,\n );\n }\n\n onDeadletter(error: Error) {\n console.error(\n `The listener ${listener.name} failed every one of its ${attempts} ` +\n `attempts at ${boundTo} and has been dead-lettered, so this side ` +\n `effect did not happen and will not be retried.`,\n error,\n );\n }\n };\n\n // The `value` is load-bearing: the queue keys its registry off `job.name`,\n // so without it the entry would be named after whatever binding this class\n // expression picked up. `writable: true` is the other half, and nothing\n // reads it today — it is here so the descriptor matches the one a declared\n // `static name = \"...\"` field produces. Every \"was this name declared?\"\n // check in the framework is a descriptor read rather than a value read\n // (`discovery.ts`, and `refuseImplicitName` below), because in development\n // the declared and the implicit spelling read the same string; and\n // redefining `name` without the flag leaves the class's own non-writable\n // descriptor in place. So a check later pointed at a *registered* job rather\n // than a discovered one — the queue's registry is the obvious place to move\n // one — would report every synthetic entry as a job the author never wrote,\n // under a fix they cannot apply. Cheap to keep, wrong to drop.\n Object.defineProperty(job, \"name\", {\n value: listenerJobName(listener.name),\n writable: true,\n });\n\n return job;\n}\n\n/**\n * Refuses to queue a listener whose name is the implicit class binding.\n *\n * A sync listener's name is only ever read inside one module graph, so\n * discovery warns about this and moves on. A queued one puts the name on the\n * wire: the push side looks the job up by `listener:<name>` in its registry and\n * the running side looks it up in *its* registry, and those two can be\n * different builds of the same application — the main process discovering\n * `app/listeners` from source while a `worker = true` listener runs in a thread\n * that imported `dist/server/bootstrap.mjs`, where minification renamed the\n * class. The names then disagree, `dispatchJob` resolves nothing, the worker\n * reports success, and the side effect silently stops happening in production.\n *\n * A throw rather than a warning because the failure is invisible from every\n * side once it happens, and because the fix is one line the author can read in\n * the message.\n */\nfunction refuseImplicitName(listener: ListenerClass): void {\n if (Object.getOwnPropertyDescriptor(listener, \"name\")?.writable) return;\n\n throw new Error(\n `The listener ${listener.name} sets \\`queued = true\\` but does not ` +\n `declare \\`static name\\`, so it would be registered with the queue ` +\n `under its class name — which a production build renames while the ` +\n `payload that names it does not. Add: static name = \"${listener.name}\";`,\n );\n}\n\n/**\n * The payload, whichever of the two shapes the queue handed it over in.\n *\n * The queue calls `run` two different ways and this is the only place that has\n * to know. In-process, `QueueManager.run` spreads the parsed arguments:\n * `run(\"UserRegistered\", [7, \"ada@example.com\"])`. Through a worker thread the\n * far side is `QueueManager.dispatchJob`, which passes the parsed array whole:\n * `run([\"UserRegistered\", [7, \"ada@example.com\"]])`. Reading only the first\n * shape would make `worker = true` a listener that receives an event named\n * `undefined` — a throw out of `rehydrate`, in a worker thread, retried to\n * dead-letter.\n *\n * The two are told apart by what is in the first slot rather than by counting\n * arguments, because the payload's own first element is always the event name\n * and a name is always a string.\n */\nfunction readPayload(payload: unknown[]): [string, unknown[]] {\n return (typeof payload[0] === \"string\" ? payload : payload[0]) as [\n string,\n unknown[],\n ];\n}\n",
22
- "import { app } from \"../../foundation/app\";\nimport { deferUntilCommit } from \"../../orm/context\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport type { Job } from \"../queue/Job\";\nimport { QueueManager } from \"../queue/QueueManager\";\nimport { eventConfigDefaults, type EventConfig } from \"./config\";\nimport type { Event, EventClass } from \"./Event\";\nimport { jobForListener } from \"./listenerJob\";\nimport type { ListenerClass } from \"./Listener\";\n\n/**\n * One listener, and where it runs.\n *\n * `queued` is an instance field, so answering \"does this one go on the queue?\"\n * means constructing the listener — done once here, at registration, rather\n * than once per dispatch. The synthetic job is built at the same moment for the\n * same reason: `EventServiceProvider.boot()` has to hand it to the queue before\n * the first dispatch, and a job built per dispatch would be a different class\n * object each time under the same registry key.\n */\ntype Registration = {\n listener: ListenerClass;\n /** The job a queued listener is pushed as, or `null` when it runs inline. */\n job: (new () => Job) | null;\n};\n\n/**\n * The registry a dispatch fans out through: event name -> the listeners bound\n * to it.\n *\n * Shaped after `QueueManager` deliberately — constructed in `register()` from\n * whatever the config slice declared, handed the discovered set in `boot()`,\n * and reporting through a `registered*` getter what it was *given* rather than\n * what it accepted, so a test can see a collision instead of having it tidied\n * away.\n *\n * Three things are not `QueueManager`'s, and each is a decision rather than a\n * detail:\n *\n * **Many listeners per key.** Two listeners for one event is the normal case\n * here, where two jobs for one name is the pathological one. So the map holds\n * arrays and `useListeners` appends. The collision it does refuse is two\n * *listener classes* claiming one `static name`.\n *\n * **Registration order is the walk's order, and means nothing.** It is stable —\n * `discoverClasses` sorts per directory and the module namespace sorts by name\n * — so it is reproducible, but no listener may depend on running before\n * another, because nothing about a filesystem layout was chosen to express\n * that. What makes it safe to say is the rule below: nothing a listener does\n * can stop the next one.\n *\n * **A dispatch nobody handles warns.** That is the entire early-warning system\n * for the subsystem, and it is why it is not optional; see `dispatchAndWait`.\n *\n * A `queued` listener is not run here at all. It is registered with the\n * `QueueManager` as a synthetic job and pushed to it on dispatch, so retries,\n * `maxAttempts`, dead-lettering and worker threads are the queue's rather than\n * a second implementation of the queue's — and nothing the request had (the\n * current actor, the ambient transaction) is still promised by the time it\n * runs. See `Listener.queued`.\n *\n * **A dispatch does not always fan out at the dispatch.** An event declaring\n * `static afterCommit` has the whole of it — queued listeners included — held\n * on the ORM's transaction scope and drained when that transaction commits, or\n * dropped when it rolls back. That is the only thing in this file that reads\n * ambient state, and `deferToCommit` is where it happens.\n */\nexport class EventManager {\n static token = \"events\";\n\n /** Event name -> every listener bound to it, in registration order. */\n private listeners: Record<string, Registration[]> = {};\n\n /**\n * Event name -> the class to rebuild it from, for a listener coming back off\n * the queue.\n *\n * Read from each listener's `static event` at registration, which is the one\n * place in the subsystem an event class is dereferenced. An event nobody\n * listens for is never in here, and that is exactly right: nothing can have\n * been queued for it.\n */\n private events: Record<string, EventClass> = {};\n\n /**\n * Event names already warned about. Per-manager, and the manager is per\n * application, so a test that builds a fresh kernel gets a fresh set.\n */\n private warnedFor = new Set<string>();\n\n /**\n * Event names already warned about for the `dispatchAndWait` + `afterCommit`\n * pairing. A second set rather than a second entry in the one above: the two\n * warnings are about different mistakes, and sharing the set would mean a\n * dispatch that legitimately has no listeners silences the one that says a\n * caller is awaiting nothing.\n */\n private warnedAboutWaiting = new Set<string>();\n\n readonly config: Required<EventConfig>;\n\n constructor(config: EventConfig = {}) {\n this.config = withDefaults(eventConfigDefaults(), config);\n this.useListeners(this.config.listeners);\n }\n\n /**\n * Replaces the registered set, for the provider to hand over what it found\n * under `app/listeners`.\n *\n * Two phases, for the reason `QueueManager.useJobs` documents: the manager is\n * constructed in `register()`, which is synchronous and must resolve nothing,\n * while reading a directory and importing what is in it is neither. So the\n * manager is built from whatever the config slice declared — nothing, when\n * the app left `listeners` out — and the discovered set arrives in `boot()`.\n *\n * The consequence worth knowing: anything that constructs an application and\n * skips phase two dispatches into an empty registry, and an empty registry is\n * a legal steady state rather than an error. The development-only warning\n * below is the only thing that says so.\n *\n * Every listener is **constructed once here**, to read the fields that decide\n * where it runs — `queued`, and through it `maxAttempts` and `worker`. A\n * listener's constructor therefore runs at boot as well as on every dispatch,\n * so it wants to assign fields and nothing else. A queued one also has its\n * synthetic job built here; `EventServiceProvider` hands those to the queue\n * once boot reaches it, so calling this again *after* boot would leave the\n * queue holding jobs for listeners this registry no longer has.\n */\n useListeners(listeners: ListenerClass[]) {\n this.config.listeners = listeners;\n\n this.listeners = {};\n this.events = {};\n const claimed = new Set<string>();\n\n for (const listener of listeners) {\n // Declared as required on the base class and still checked here: every\n // subclass inherits the declaration whether or not it assigns to it, so\n // `typeof SomeListener` satisfies `ListenerClass` either way and the\n // compiler cannot see the omission. Refused rather than registered under\n // some fallback, because there is no fallback — a listener with no event\n // is a file the author wrote that nothing will ever call.\n if (!listener.event) {\n console.error(\n `Listener ${listener.name} does not declare \\`static event\\`, so ` +\n `there is no event name to register it under and its handle will ` +\n `never run. Add: static event = SomeEvent;`,\n );\n continue;\n }\n\n // Two classes with one name, refused here and nowhere else — which is\n // what keeps the queue from being handed two jobs called\n // `listener:NotifyAdmins` and having to decide between them one layer\n // down, where the loser is a side effect that reports success. A\n // directory walk is what makes the clash ordinary, since nothing forces\n // the import alias a hand-written list would have demanded.\n if (claimed.has(listener.name)) {\n console.error(\n `Two event listeners are named \"${listener.name}\" — the first is ` +\n `registered and this one is not. A listener's name identifies it ` +\n `across the framework, so only one class can hold it. Rename one.`,\n );\n continue;\n }\n claimed.add(listener.name);\n\n // The one place the event class is dereferenced, and deliberately the\n // only one: this runs in the module graph that declared the class, so the\n // name it yields is the source-side one that discovery and a minified\n // dispatcher both agree on. Nothing downstream keeps the class object —\n // except `this.events`, which keeps it under that same string so a\n // listener coming back off the queue has something to rebuild from. First\n // claim wins there too: a name is what identifies an event to everything\n // downstream, so two classes declaring one are one event already.\n const name = listener.event.name;\n const instance = new listener();\n\n this.events[name] ??= listener.event;\n (this.listeners[name] ??= []).push({\n listener,\n job: instance.queued ? jobForListener(listener, instance) : null,\n });\n }\n }\n\n /**\n * The synthetic jobs the queue has to be told about — one per queued\n * listener, named `listener:<name>`.\n *\n * `EventServiceProvider.boot()` is the only caller. It reads this rather than\n * having the manager reach for the `QueueManager` itself, because\n * registration happens in `register()`, where resolving another service is\n * exactly what a provider must not do. A copy, so the caller cannot edit what\n * a dispatch pushes.\n */\n get queuedListenerJobs(): ReadonlyArray<new () => Job> {\n return Object.values(this.listeners)\n .flat()\n .flatMap(({ job }) => (job ? [job] : []));\n }\n\n /**\n * What the manager was handed, discovered or declared.\n *\n * \"Is this listener registered?\" is a question with a silent wrong answer —\n * an unregistered listener is a side effect that does not happen, and nothing\n * is waiting on it to notice. This is where a test asks it out loud.\n *\n * It reports what came in, not what the registry accepted, so a name claimed\n * twice appears twice here — deliberately, the same way `QueueManager` and\n * `Scheduler` do. A copy, so a walk over it cannot edit what dispatch reads.\n */\n get registeredListeners(): ReadonlyArray<ListenerClass> {\n return [...this.config.listeners];\n }\n\n /**\n * Fires the event and returns. The sync listeners run to completion after the\n * caller has moved on.\n *\n * Nothing is awaited and nothing can reject: `runListeners` catches every\n * listener's failure itself, so the floating promise here has no rejection to\n * float.\n *\n * `args` is the event's constructor arguments; see `dispatchAndWait`.\n *\n * On an `afterCommit` event inside a transaction, \"after the caller has moved\n * on\" becomes \"after that transaction commits\" — see `deferToCommit`.\n */\n dispatch(event: Event, args?: readonly unknown[]): void {\n if (this.deferToCommit(event, args, false)) return;\n void this.runListeners(event, args);\n }\n\n /**\n * Fires the event and resolves once every **sync** listener has settled.\n *\n * On an `afterCommit` event inside an open transaction it resolves\n * **immediately, having run nothing** — there is no listener to wait for yet,\n * and the transaction it would be waiting on is the caller's own. That is the\n * sharp edge `Event.afterCommit` documents and the reason the flag ships\n * opt-in; it warns once per event name in development, because nothing else\n * about the call site can show it.\n */\n async dispatchAndWait(\n event: Event,\n args?: readonly unknown[],\n ): Promise<void> {\n if (this.deferToCommit(event, args, true)) return;\n return this.runListeners(event, args);\n }\n\n /**\n * Queues the fan-out on the open transaction when the event asked for that,\n * and reports whether it did — `false` means the caller runs it now.\n *\n * Three cases, and only the third defers: an event without\n * `static afterCommit` behaves exactly as it did before this existed; one\n * with it, dispatched outside a transaction, has nothing to wait for; one\n * with it, inside a transaction, runs when that transaction commits and not\n * at all if it rolls back.\n *\n * `currentTransaction()` is not consulted directly, and the difference\n * matters: `deferUntilCommit` also answers `false` for a scope carrying a\n * handle that `withTransaction` did not open, which has no commit hook and\n * therefore no list that will ever be drained. Reading the handle alone would\n * queue the dispatch onto nothing and lose it silently.\n *\n * The whole fan-out is deferred, sync listeners and queued ones alike. A\n * queued listener is *pushed* at commit rather than at dispatch, which is the\n * only correct reading of `afterCommit`: the queue drains in-process and\n * often synchronously from `push`, so pushing early is running early.\n */\n private deferToCommit(\n event: Event,\n args: readonly unknown[] | undefined,\n awaited: boolean,\n ): boolean {\n // Read off the constructor, the same way the registry key is, and typed\n // structurally for the same reason: `Event` arrives here as a type-only\n // import, and the class object an application dispatches may have come from\n // a different module graph than the one this file was compiled against.\n const { name, afterCommit } = event.constructor as {\n name: string;\n afterCommit?: boolean;\n };\n if (!afterCommit) return false;\n\n const deferred = deferUntilCommit(() => this.runListeners(event, args));\n if (deferred && awaited) this.warnNothingIsWaitedFor(name);\n return deferred;\n }\n\n /**\n * Runs every **sync** listener bound to this event, in registration order,\n * and resolves when the last of them has settled. Every queued one is handed\n * to the `QueueManager` on the way past and is not waited for.\n *\n * The dispatch itself is `dispatch` and `dispatchAndWait` above; this is what\n * they run, and what an `afterCommit` event's transaction runs later. Split\n * out so that \"when does the fan-out happen\" is decided in exactly one place\n * rather than in each entry point.\n *\n * ### Sync and queued in one pass\n *\n * A queued listener is pushed at the point in the order it occupies, so its\n * *dispatch* is ordered with the rest and its *execution* is not: the queue\n * decides when. What that costs is worth knowing — `dispatchAndWait`\n * resolving says every sync listener has finished and says nothing at all\n * about a queued one, which may not have started or may already have failed\n * twice. Whether a listener is queued is therefore a decision about what the\n * caller can rely on having happened, not only about latency.\n *\n * @param args the arguments the event's constructor was called with, which\n * `Event.dispatch` forwards. Only a queued listener needs them: the event\n * instance itself never crosses the queue, and what is rebuilt on the other\n * side is `new EventClass(...args)`. Dispatching a hand-built instance\n * straight at the manager therefore cannot queue, and says so on stderr\n * rather than pushing a payload that would rehydrate into an event with\n * `undefined` fields.\n *\n * ### One at a time, deliberately\n *\n * Each listener is awaited before the next one starts, rather than started\n * together under a `Promise.allSettled`. Concurrency would make \"registration\n * order\" a claim about start order only, and the order it is a claim about is\n * the one `registeredListeners` reports and the discovery tests assert on.\n *\n * What it costs is worth knowing, because it is the one way listener\n * independence is not total: a listener that *hangs* — an un-timed-out\n * `fetch` to a host that never answers — delays every listener after it for\n * as long as it hangs, and under `dispatch` the caller has already moved on,\n * so an audit row a later listener writes simply is not there yet. A throw is\n * not this: that is caught below and the next listener runs immediately. A\n * listener that can block indefinitely is a listener that wants its own\n * timeout, or a `Job`.\n *\n * ### Errors\n *\n * Each listener runs inside its own `try`. A throw is logged with the event\n * name, the listener name, and the error, and the loop continues — listeners\n * are independent side effects, and letting listener 2 cancel 3 through 5\n * would make a filesystem walk's order load-bearing. Neither this nor\n * `dispatch` ever rejects, for the same reason from the caller's side: a\n * rejection would make listener 1's failure the dispatcher's problem while\n * listener 5's silently is not.\n *\n * ### Why zero listeners is worth a line on stderr\n *\n * A registry keyed by the wrong string, a `static name` that does not survive\n * a production build, a typo, and a listener directory that was never walked\n * all produce the same single symptom: nobody handled it. Zero listeners is\n * also a perfectly legal steady state, so the warning is development-only and\n * fires once per event name — a dispatch in a loop would otherwise bury the\n * terminal.\n */\n protected async runListeners(\n event: Event,\n args?: readonly unknown[],\n ): Promise<void> {\n const name = (event.constructor as { name: string }).name;\n const handlers = this.listeners[name];\n\n if (!handlers?.length) {\n this.warnNothingIsListening(name);\n return;\n }\n\n for (const { listener: Listener, job } of handlers) {\n if (job) {\n this.enqueue(job, Listener, name, args);\n continue;\n }\n\n try {\n await new Listener().handle(event);\n } catch (error) {\n console.error(\n `The listener ${Listener.name} threw while handling ${name}. The ` +\n `listeners after it still ran — a listener's failure is its own.`,\n error,\n );\n }\n }\n }\n\n /**\n * Rebuilds an event from what crossed the queue.\n *\n * The queue carries a name and an argument array, because that is all JSON\n * can carry: **the constructor arguments are what is serialized, not the\n * instance** — the same bargain `Job.dispatch` makes. So an event whose\n * constructor does work beyond assigning fields does that work a second time\n * here, in the worker, with none of the dispatching request around it.\n *\n * A name that resolves to nothing throws, and is the one place in this file\n * that does. The payload is already off the queue by the time this runs and\n * the listener is one line away from being handed `undefined`, so the\n * alternative is a `handle` reading `event.email` off nothing, several frames\n * further on, with the name that would have explained it no longer in scope.\n * A throw here is caught by `QueueManager.run` and takes the queue's ordinary\n * retry-then-dead-letter path.\n */\n rehydrate(eventName: string, args: readonly unknown[] = []): Event {\n const EventClass = this.events[eventName];\n\n if (!EventClass) {\n throw new Error(\n `Cannot rebuild the event \"${eventName}\" that came off the queue: no ` +\n `registered listener binds to an event of that name, so there is no ` +\n `class to construct. A queued listener runs in an application that ` +\n `discovered its own listeners — check that this process sees the ` +\n `same app/listeners as the one that dispatched, and that the event ` +\n `declares \\`static name = \"${eventName}\"\\`.`,\n );\n }\n\n return new EventClass(...args);\n }\n\n /**\n * Hands one queued listener to the queue, as `[eventName, args]`.\n *\n * Nothing is awaited: `push` is not waited on even to record the entry,\n * which is the whole of what `queued = true` buys. The event instance the\n * sync listeners share does not go with it — only the name and the arguments\n * do, so nothing that was resolved from the request's context can be smuggled\n * across into an application that does not have it.\n *\n * Failing to queue is caught for the same reason a listener's throw is: it is\n * one listener's problem, and the listeners after it in the walk did not do\n * anything to deserve it. Two things reach that catch — an argument JSON\n * cannot serialise, and an application with no queue bound — and both would\n * otherwise reject `dispatchAndWait`, which is documented never to.\n */\n private enqueue(\n job: new () => Job,\n listener: ListenerClass,\n eventName: string,\n args?: readonly unknown[],\n ) {\n if (args === undefined) {\n console.error(\n `The listener ${listener.name} is queued, but ${eventName} reached ` +\n `the dispatcher without its constructor arguments, so there is ` +\n `nothing for the queue to rebuild it from and the listener was ` +\n `skipped. Dispatch through ${eventName}.dispatch(...) or ` +\n `${eventName}.dispatchAndWait(...), which carry them.`,\n );\n return;\n }\n\n const failed = (error: unknown) =>\n console.error(\n `The listener ${listener.name} could not be queued for ${eventName}, ` +\n `so it did not run and will not be retried. The listeners after it ` +\n `still ran.`,\n error,\n );\n\n // Both halves: the two failures above throw here, and a driver that\n // cannot record the job rejects later — unawaited, so without the `catch`\n // that rejection would be an unhandled one.\n try {\n // `reportFailure: false`: the queue's own line would say only which job\n // could not be recorded, and `failed` names the event, the listener and\n // what it means for the listeners after it.\n app(QueueManager)\n .push(job, JSON.stringify([eventName, args]), { reportFailure: false })\n .catch(failed);\n } catch (error) {\n failed(error);\n }\n }\n\n /**\n * The one warning for the pairing that reads as doing something and does not.\n *\n * `await UserRegistered.dispatchAndWait(...)` inside a transaction, on an\n * event that defers to commit, resolves with nothing having run — the\n * listeners are queued on a transaction the caller has not finished. There is\n * no other symptom: the promise resolves, the listeners do run later, and the\n * only thing that is wrong is that the caller's `await` bought it nothing.\n * Code that reads what a listener wrote on the next line finds it missing,\n * and nothing connects the two.\n *\n * Development only and once per event name, on the same terms as the\n * zero-listener warning: both are legal steady states that are usually a\n * mistake, and a dispatch in a loop must not bury the terminal.\n */\n private warnNothingIsWaitedFor(name: string) {\n if (process.env.NODE_ENV === \"production\") return;\n if (this.warnedAboutWaiting.has(name)) return;\n this.warnedAboutWaiting.add(name);\n\n console.warn(\n `[gemi] ${name}.dispatchAndWait() was called inside a transaction and ` +\n `${name} declares \\`static afterCommit = true\\`, so it resolved ` +\n `immediately with no listener having run — they run when the ` +\n `transaction commits. Await the transaction instead, or drop ` +\n `afterCommit if the caller needs the side effects first. Development ` +\n `only.`,\n );\n }\n\n private warnNothingIsListening(name: string) {\n if (process.env.NODE_ENV === \"production\") return;\n if (this.warnedFor.has(name)) return;\n this.warnedFor.add(name);\n\n console.warn(\n `[gemi] ${name} was dispatched and nothing is listening for it. A ` +\n `listener registers under the name its event declares, so check that ` +\n `app/listeners holds a Listener with \\`static event = ${name}\\` and ` +\n `that ${name} declares \\`static name = \"${name}\"\\`. Development only.`,\n );\n }\n}\n",
26
+ "import { app } from \"../../foundation/app\";\nimport { deferUntilCommit } from \"../../orm/context\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport type { Job } from \"../queue/Job\";\nimport { QueueManager } from \"../queue/QueueManager\";\nimport { BroadcastManager } from \"../broadcast/BroadcastManager\";\nimport { isBroadcastEvent, type BroadcastableEvent } from \"../broadcast/brand\";\nimport { eventConfigDefaults, type EventConfig } from \"./config\";\nimport type { Event, EventClass } from \"./Event\";\nimport { jobForListener } from \"./listenerJob\";\nimport type { ListenerClass } from \"./Listener\";\n\n/**\n * One listener, and where it runs.\n *\n * `queued` is an instance field, so answering \"does this one go on the queue?\"\n * means constructing the listener — done once here, at registration, rather\n * than once per dispatch. The synthetic job is built at the same moment for the\n * same reason: `EventServiceProvider.boot()` has to hand it to the queue before\n * the first dispatch, and a job built per dispatch would be a different class\n * object each time under the same registry key.\n */\ntype Registration = {\n listener: ListenerClass;\n /** The job a queued listener is pushed as, or `null` when it runs inline. */\n job: (new () => Job) | null;\n};\n\n/**\n * The registry a dispatch fans out through: event name -> the listeners bound\n * to it.\n *\n * Shaped after `QueueManager` deliberately — constructed in `register()` from\n * whatever the config slice declared, handed the discovered set in `boot()`,\n * and reporting through a `registered*` getter what it was *given* rather than\n * what it accepted, so a test can see a collision instead of having it tidied\n * away.\n *\n * Three things are not `QueueManager`'s, and each is a decision rather than a\n * detail:\n *\n * **Many listeners per key.** Two listeners for one event is the normal case\n * here, where two jobs for one name is the pathological one. So the map holds\n * arrays and `useListeners` appends. The collision it does refuse is two\n * *listener classes* claiming one `static name`.\n *\n * **Registration order is the walk's order, and means nothing.** It is stable —\n * `discoverClasses` sorts per directory and the module namespace sorts by name\n * — so it is reproducible, but no listener may depend on running before\n * another, because nothing about a filesystem layout was chosen to express\n * that. What makes it safe to say is the rule below: nothing a listener does\n * can stop the next one.\n *\n * **A dispatch nobody handles warns.** That is the entire early-warning system\n * for the subsystem, and it is why it is not optional; see `dispatchAndWait`.\n *\n * A `queued` listener is not run here at all. It is registered with the\n * `QueueManager` as a synthetic job and pushed to it on dispatch, so retries,\n * `maxAttempts`, dead-lettering and worker threads are the queue's rather than\n * a second implementation of the queue's — and nothing the request had (the\n * current actor, the ambient transaction) is still promised by the time it\n * runs. See `Listener.queued`.\n *\n * **A dispatch does not always fan out at the dispatch.** An event declaring\n * `static afterCommit` has the whole of it — queued listeners included — held\n * on the ORM's transaction scope and drained when that transaction commits, or\n * dropped when it rolls back. That is the only thing in this file that reads\n * ambient state, and `deferToCommit` is where it happens.\n */\nexport class EventManager {\n static token = \"events\";\n\n /** Event name -> every listener bound to it, in registration order. */\n private listeners: Record<string, Registration[]> = {};\n\n /**\n * Event name -> the class to rebuild it from, for a listener coming back off\n * the queue.\n *\n * Read from each listener's `static event` at registration, which is the one\n * place in the subsystem an event class is dereferenced. An event nobody\n * listens for is never in here, and that is exactly right: nothing can have\n * been queued for it.\n */\n private events: Record<string, EventClass> = {};\n\n /**\n * Event names already warned about. Per-manager, and the manager is per\n * application, so a test that builds a fresh kernel gets a fresh set.\n */\n private warnedFor = new Set<string>();\n\n /**\n * Event names already warned about for the `dispatchAndWait` + `afterCommit`\n * pairing. A second set rather than a second entry in the one above: the two\n * warnings are about different mistakes, and sharing the set would mean a\n * dispatch that legitimately has no listeners silences the one that says a\n * caller is awaiting nothing.\n */\n private warnedAboutWaiting = new Set<string>();\n\n readonly config: Required<EventConfig>;\n\n constructor(config: EventConfig = {}) {\n this.config = withDefaults(eventConfigDefaults(), config);\n this.useListeners(this.config.listeners);\n }\n\n /**\n * Replaces the registered set, for the provider to hand over what it found\n * under `app/listeners`.\n *\n * Two phases, for the reason `QueueManager.useJobs` documents: the manager is\n * constructed in `register()`, which is synchronous and must resolve nothing,\n * while reading a directory and importing what is in it is neither. So the\n * manager is built from whatever the config slice declared — nothing, when\n * the app left `listeners` out — and the discovered set arrives in `boot()`.\n *\n * The consequence worth knowing: anything that constructs an application and\n * skips phase two dispatches into an empty registry, and an empty registry is\n * a legal steady state rather than an error. The development-only warning\n * below is the only thing that says so.\n *\n * Every listener is **constructed once here**, to read the fields that decide\n * where it runs — `queued`, and through it `maxAttempts` and `worker`. A\n * listener's constructor therefore runs at boot as well as on every dispatch,\n * so it wants to assign fields and nothing else. A queued one also has its\n * synthetic job built here; `EventServiceProvider` hands those to the queue\n * once boot reaches it, so calling this again *after* boot would leave the\n * queue holding jobs for listeners this registry no longer has.\n */\n useListeners(listeners: ListenerClass[]) {\n this.config.listeners = listeners;\n\n this.listeners = {};\n this.events = {};\n const claimed = new Set<string>();\n\n for (const listener of listeners) {\n // Declared as required on the base class and still checked here: every\n // subclass inherits the declaration whether or not it assigns to it, so\n // `typeof SomeListener` satisfies `ListenerClass` either way and the\n // compiler cannot see the omission. Refused rather than registered under\n // some fallback, because there is no fallback — a listener with no event\n // is a file the author wrote that nothing will ever call.\n if (!listener.event) {\n console.error(\n `Listener ${listener.name} does not declare \\`static event\\`, so ` +\n `there is no event name to register it under and its handle will ` +\n `never run. Add: static event = SomeEvent;`,\n );\n continue;\n }\n\n // Two classes with one name, refused here and nowhere else — which is\n // what keeps the queue from being handed two jobs called\n // `listener:NotifyAdmins` and having to decide between them one layer\n // down, where the loser is a side effect that reports success. A\n // directory walk is what makes the clash ordinary, since nothing forces\n // the import alias a hand-written list would have demanded.\n if (claimed.has(listener.name)) {\n console.error(\n `Two event listeners are named \"${listener.name}\" — the first is ` +\n `registered and this one is not. A listener's name identifies it ` +\n `across the framework, so only one class can hold it. Rename one.`,\n );\n continue;\n }\n claimed.add(listener.name);\n\n // The one place the event class is dereferenced, and deliberately the\n // only one: this runs in the module graph that declared the class, so the\n // name it yields is the source-side one that discovery and a minified\n // dispatcher both agree on. Nothing downstream keeps the class object —\n // except `this.events`, which keeps it under that same string so a\n // listener coming back off the queue has something to rebuild from. First\n // claim wins there too: a name is what identifies an event to everything\n // downstream, so two classes declaring one are one event already.\n const name = listener.event.name;\n const instance = new listener();\n\n this.events[name] ??= listener.event;\n (this.listeners[name] ??= []).push({\n listener,\n job: instance.queued ? jobForListener(listener, instance) : null,\n });\n }\n }\n\n /**\n * The synthetic jobs the queue has to be told about — one per queued\n * listener, named `listener:<name>`.\n *\n * `EventServiceProvider.boot()` is the only caller. It reads this rather than\n * having the manager reach for the `QueueManager` itself, because\n * registration happens in `register()`, where resolving another service is\n * exactly what a provider must not do. A copy, so the caller cannot edit what\n * a dispatch pushes.\n */\n get queuedListenerJobs(): ReadonlyArray<new () => Job> {\n return Object.values(this.listeners)\n .flat()\n .flatMap(({ job }) => (job ? [job] : []));\n }\n\n /**\n * What the manager was handed, discovered or declared.\n *\n * \"Is this listener registered?\" is a question with a silent wrong answer —\n * an unregistered listener is a side effect that does not happen, and nothing\n * is waiting on it to notice. This is where a test asks it out loud.\n *\n * It reports what came in, not what the registry accepted, so a name claimed\n * twice appears twice here — deliberately, the same way `QueueManager` and\n * `Scheduler` do. A copy, so a walk over it cannot edit what dispatch reads.\n */\n get registeredListeners(): ReadonlyArray<ListenerClass> {\n return [...this.config.listeners];\n }\n\n /**\n * Fires the event and returns. The sync listeners run to completion after the\n * caller has moved on.\n *\n * Nothing is awaited and nothing can reject: `runListeners` catches every\n * listener's failure itself, so the floating promise here has no rejection to\n * float.\n *\n * `args` is the event's constructor arguments; see `dispatchAndWait`.\n *\n * On an `afterCommit` event inside a transaction, \"after the caller has moved\n * on\" becomes \"after that transaction commits\" — see `deferToCommit`.\n */\n dispatch(event: Event, args?: readonly unknown[]): void {\n if (this.deferToCommit(event, args, false)) return;\n void this.runListeners(event, args);\n }\n\n /**\n * Fires the event and resolves once every **sync** listener has settled.\n *\n * On an `afterCommit` event inside an open transaction it resolves\n * **immediately, having run nothing** — there is no listener to wait for yet,\n * and the transaction it would be waiting on is the caller's own. That is the\n * sharp edge `Event.afterCommit` documents and the reason the flag ships\n * opt-in; it warns once per event name in development, because nothing else\n * about the call site can show it.\n */\n async dispatchAndWait(\n event: Event,\n args?: readonly unknown[],\n ): Promise<void> {\n if (this.deferToCommit(event, args, true)) return;\n return this.runListeners(event, args);\n }\n\n /**\n * Queues the fan-out on the open transaction when the event asked for that,\n * and reports whether it did — `false` means the caller runs it now.\n *\n * Three cases, and only the third defers: an event without\n * `static afterCommit` behaves exactly as it did before this existed; one\n * with it, dispatched outside a transaction, has nothing to wait for; one\n * with it, inside a transaction, runs when that transaction commits and not\n * at all if it rolls back.\n *\n * `currentTransaction()` is not consulted directly, and the difference\n * matters: `deferUntilCommit` also answers `false` for a scope carrying a\n * handle that `withTransaction` did not open, which has no commit hook and\n * therefore no list that will ever be drained. Reading the handle alone would\n * queue the dispatch onto nothing and lose it silently.\n *\n * The whole fan-out is deferred, sync listeners and queued ones alike. A\n * queued listener is *pushed* at commit rather than at dispatch, which is the\n * only correct reading of `afterCommit`: the queue drains in-process and\n * often synchronously from `push`, so pushing early is running early.\n */\n private deferToCommit(\n event: Event,\n args: readonly unknown[] | undefined,\n awaited: boolean,\n ): boolean {\n // Read off the constructor, the same way the registry key is, and typed\n // structurally for the same reason: `Event` arrives here as a type-only\n // import, and the class object an application dispatches may have come from\n // a different module graph than the one this file was compiled against.\n const { name, afterCommit } = event.constructor as {\n name: string;\n afterCommit?: boolean;\n };\n if (!afterCommit) return false;\n\n const deferred = deferUntilCommit(() => this.runListeners(event, args));\n if (deferred && awaited) this.warnNothingIsWaitedFor(name);\n return deferred;\n }\n\n /**\n * Runs every **sync** listener bound to this event, in registration order,\n * and resolves when the last of them has settled. Every queued one is handed\n * to the `QueueManager` on the way past and is not waited for.\n *\n * The dispatch itself is `dispatch` and `dispatchAndWait` above; this is what\n * they run, and what an `afterCommit` event's transaction runs later. Split\n * out so that \"when does the fan-out happen\" is decided in exactly one place\n * rather than in each entry point.\n *\n * ### Sync and queued in one pass\n *\n * A queued listener is pushed at the point in the order it occupies, so its\n * *dispatch* is ordered with the rest and its *execution* is not: the queue\n * decides when. What that costs is worth knowing — `dispatchAndWait`\n * resolving says every sync listener has finished and says nothing at all\n * about a queued one, which may not have started or may already have failed\n * twice. Whether a listener is queued is therefore a decision about what the\n * caller can rely on having happened, not only about latency.\n *\n * @param args the arguments the event's constructor was called with, which\n * `Event.dispatch` forwards. Only a queued listener needs them: the event\n * instance itself never crosses the queue, and what is rebuilt on the other\n * side is `new EventClass(...args)`. Dispatching a hand-built instance\n * straight at the manager therefore cannot queue, and says so on stderr\n * rather than pushing a payload that would rehydrate into an event with\n * `undefined` fields.\n *\n * ### One at a time, deliberately\n *\n * Each listener is awaited before the next one starts, rather than started\n * together under a `Promise.allSettled`. Concurrency would make \"registration\n * order\" a claim about start order only, and the order it is a claim about is\n * the one `registeredListeners` reports and the discovery tests assert on.\n *\n * What it costs is worth knowing, because it is the one way listener\n * independence is not total: a listener that *hangs* — an un-timed-out\n * `fetch` to a host that never answers — delays every listener after it for\n * as long as it hangs, and under `dispatch` the caller has already moved on,\n * so an audit row a later listener writes simply is not there yet. A throw is\n * not this: that is caught below and the next listener runs immediately. A\n * listener that can block indefinitely is a listener that wants its own\n * timeout, or a `Job`.\n *\n * ### Errors\n *\n * Each listener runs inside its own `try`. A throw is logged with the event\n * name, the listener name, and the error, and the loop continues — listeners\n * are independent side effects, and letting listener 2 cancel 3 through 5\n * would make a filesystem walk's order load-bearing. Neither this nor\n * `dispatch` ever rejects, for the same reason from the caller's side: a\n * rejection would make listener 1's failure the dispatcher's problem while\n * listener 5's silently is not.\n *\n * ### Why zero listeners is worth a line on stderr\n *\n * A registry keyed by the wrong string, a `static name` that does not survive\n * a production build, a typo, and a listener directory that was never walked\n * all produce the same single symptom: nobody handled it. Zero listeners is\n * also a perfectly legal steady state, so the warning is development-only and\n * fires once per event name — a dispatch in a loop would otherwise bury the\n * terminal.\n */\n protected async runListeners(\n event: Event,\n args?: readonly unknown[],\n ): Promise<void> {\n const name = (event.constructor as { name: string }).name;\n const handlers = this.listeners[name] ?? [];\n const broadcast = isBroadcastEvent(event);\n\n // A broadcast event is often dispatched only to be broadcast, so having\n // no listener is normal for it.\n if (handlers.length === 0 && !broadcast) {\n this.warnNothingIsListening(name);\n return;\n }\n\n for (const { listener: Listener, job } of handlers) {\n if (job) {\n this.enqueue(job, Listener, name, args);\n continue;\n }\n\n try {\n await new Listener().handle(event);\n } catch (error) {\n console.error(\n `The listener ${Listener.name} threw while handling ${name}. The ` +\n `listeners after it still ran — a listener's failure is its own.`,\n error,\n );\n }\n }\n\n if (broadcast) this.broadcast(event, name);\n }\n\n /**\n * Sends a `BroadcastEvent` to its channels, once its sync listeners have\n * run. Not under `Event.fake()`, which never gets here. A refused channel or\n * payload is logged: the dispatch has already returned to its caller.\n */\n private broadcast(event: BroadcastableEvent, name: string) {\n try {\n app(BroadcastManager).broadcastEvent(event);\n } catch (error) {\n console.error(`The event ${name} could not be broadcast.`, error);\n }\n }\n\n /**\n * Rebuilds an event from what crossed the queue.\n *\n * The queue carries a name and an argument array, because that is all JSON\n * can carry: **the constructor arguments are what is serialized, not the\n * instance** — the same bargain `Job.dispatch` makes. So an event whose\n * constructor does work beyond assigning fields does that work a second time\n * here, in the worker, with none of the dispatching request around it.\n *\n * A name that resolves to nothing throws, and is the one place in this file\n * that does. The payload is already off the queue by the time this runs and\n * the listener is one line away from being handed `undefined`, so the\n * alternative is a `handle` reading `event.email` off nothing, several frames\n * further on, with the name that would have explained it no longer in scope.\n * A throw here is caught by `QueueManager.run` and takes the queue's ordinary\n * retry-then-dead-letter path.\n */\n rehydrate(eventName: string, args: readonly unknown[] = []): Event {\n const EventClass = this.events[eventName];\n\n if (!EventClass) {\n throw new Error(\n `Cannot rebuild the event \"${eventName}\" that came off the queue: no ` +\n `registered listener binds to an event of that name, so there is no ` +\n `class to construct. A queued listener runs in an application that ` +\n `discovered its own listeners — check that this process sees the ` +\n `same app/listeners as the one that dispatched, and that the event ` +\n `declares \\`static name = \"${eventName}\"\\`.`,\n );\n }\n\n return new EventClass(...args);\n }\n\n /**\n * Hands one queued listener to the queue, as `[eventName, args]`.\n *\n * Nothing is awaited: `push` is not waited on even to record the entry,\n * which is the whole of what `queued = true` buys. The event instance the\n * sync listeners share does not go with it — only the name and the arguments\n * do, so nothing that was resolved from the request's context can be smuggled\n * across into an application that does not have it.\n *\n * Failing to queue is caught for the same reason a listener's throw is: it is\n * one listener's problem, and the listeners after it in the walk did not do\n * anything to deserve it. Two things reach that catch — an argument JSON\n * cannot serialise, and an application with no queue bound — and both would\n * otherwise reject `dispatchAndWait`, which is documented never to.\n */\n private enqueue(\n job: new () => Job,\n listener: ListenerClass,\n eventName: string,\n args?: readonly unknown[],\n ) {\n if (args === undefined) {\n console.error(\n `The listener ${listener.name} is queued, but ${eventName} reached ` +\n `the dispatcher without its constructor arguments, so there is ` +\n `nothing for the queue to rebuild it from and the listener was ` +\n `skipped. Dispatch through ${eventName}.dispatch(...) or ` +\n `${eventName}.dispatchAndWait(...), which carry them.`,\n );\n return;\n }\n\n const failed = (error: unknown) =>\n console.error(\n `The listener ${listener.name} could not be queued for ${eventName}, ` +\n `so it did not run and will not be retried. The listeners after it ` +\n `still ran.`,\n error,\n );\n\n // Both halves: the two failures above throw here, and a driver that\n // cannot record the job rejects later — unawaited, so without the `catch`\n // that rejection would be an unhandled one.\n try {\n // `reportFailure: false`: the queue's own line would say only which job\n // could not be recorded, and `failed` names the event, the listener and\n // what it means for the listeners after it.\n app(QueueManager)\n .push(job, JSON.stringify([eventName, args]), { reportFailure: false })\n .catch(failed);\n } catch (error) {\n failed(error);\n }\n }\n\n /**\n * The one warning for the pairing that reads as doing something and does not.\n *\n * `await UserRegistered.dispatchAndWait(...)` inside a transaction, on an\n * event that defers to commit, resolves with nothing having run — the\n * listeners are queued on a transaction the caller has not finished. There is\n * no other symptom: the promise resolves, the listeners do run later, and the\n * only thing that is wrong is that the caller's `await` bought it nothing.\n * Code that reads what a listener wrote on the next line finds it missing,\n * and nothing connects the two.\n *\n * Development only and once per event name, on the same terms as the\n * zero-listener warning: both are legal steady states that are usually a\n * mistake, and a dispatch in a loop must not bury the terminal.\n */\n private warnNothingIsWaitedFor(name: string) {\n if (process.env.NODE_ENV === \"production\") return;\n if (this.warnedAboutWaiting.has(name)) return;\n this.warnedAboutWaiting.add(name);\n\n console.warn(\n `[gemi] ${name}.dispatchAndWait() was called inside a transaction and ` +\n `${name} declares \\`static afterCommit = true\\`, so it resolved ` +\n `immediately with no listener having run — they run when the ` +\n `transaction commits. Await the transaction instead, or drop ` +\n `afterCommit if the caller needs the side effects first. Development ` +\n `only.`,\n );\n }\n\n private warnNothingIsListening(name: string) {\n if (process.env.NODE_ENV === \"production\") return;\n if (this.warnedFor.has(name)) return;\n this.warnedFor.add(name);\n\n console.warn(\n `[gemi] ${name} was dispatched and nothing is listening for it. A ` +\n `listener registers under the name its event declares, so check that ` +\n `app/listeners holds a Listener with \\`static event = ${name}\\` and ` +\n `that ${name} declares \\`static name = \"${name}\"\\`. Development only.`,\n );\n }\n}\n",
23
27
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { discoverListeners } from \"../discovery\";\nimport { QueueManager } from \"../queue/QueueManager\";\nimport { eventConfigDefaults, type EventConfig } from \"./config\";\nimport { EventManager } from \"./EventManager\";\n\nexport class EventServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n EventManager,\n () => new EventManager(this.app.config.get<EventConfig>(\"events\", {})),\n );\n }\n\n /**\n * Fills in the listener registry when the app did not declare one.\n *\n * ### Why the raw slice and not the manager's config\n *\n * The decision here is whether the app said anything, and by the time the\n * manager holds a config it can no longer tell: `withDefaults` treats an\n * absent key and an `undefined` one alike and substitutes the default `[]`,\n * which is the same value an app writes when it means \"no listeners, and I\n * mean it\". Reading the slice before defaults are applied is the only place\n * the difference still exists.\n *\n * So: `listeners` present, including `listeners: []`, is used verbatim and no\n * directory is read. Absent or `undefined`, the classes under `listenersDir`\n * are.\n *\n * ### Why phase two\n *\n * Discovery imports every file it walks, which is asynchronous, and\n * `register()` is not. It also has to finish before the first dispatch rather\n * than before the first request — a dispatch against an empty registry is not\n * an error, it is a side effect that quietly does not happen — so the\n * registry has to be complete by the end of boot.\n *\n * ### Why the queue is handed the listener jobs from here\n *\n * A queued listener is registered with the `QueueManager` as a synthetic job,\n * and that registration cannot happen in `register()`: resolving another\n * service is the one thing a `register()` must not do, and the jobs are not\n * known until discovery has run anyway. It also cannot happen before\n * `QueueServiceProvider.boot()` fills the queue's registry, which is why this\n * provider sits after it in `frameworkProviders` — `useJobs` replaces that\n * registry wholesale, so the queue has to be finished with it before\n * `registerJob` starts adding to it.\n *\n * The declared-listeners path falls through to it rather than returning\n * early: an app that lists its listeners in `app/config/events.ts` still has\n * queued ones, and skipping the queue for them would make `queued = true` a\n * field that silently does nothing depending on how the app registers.\n */\n async boot() {\n const manager = this.app.make(EventManager);\n const slice = this.app.config.get<EventConfig>(\"events\", {});\n\n if (slice.listeners === undefined) {\n const { listenersDir } = withDefaults(eventConfigDefaults(), slice);\n manager.useListeners(await discoverListeners(listenersDir));\n }\n\n // Nothing queued, nothing to resolve. An application assembled out of this\n // provider alone — a test, a script — has no `QueueManager` bound, and\n // asking for one it has no use for would turn that into a boot failure.\n const jobs = manager.queuedListenerJobs;\n if (jobs.length === 0) return;\n\n const queue = this.app.make(QueueManager);\n for (const job of jobs) {\n queue.registerJob(job);\n }\n }\n}\n",
24
28
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { FilesystemConfig } from \"./config\";\nimport { FilesystemManager } from \"./FilesystemManager\";\n\nexport class FilesystemServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n FilesystemManager,\n () =>\n new FilesystemManager(\n this.app.config.get<FilesystemConfig>(\"filesystem\", {}),\n ),\n );\n }\n}\n",
25
29
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport type { ImageConfig } from \"./config\";\nimport { ImageManager } from \"./ImageManager\";\n\nexport class ImageServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n ImageManager,\n () => new ImageManager(this.app.config.get<ImageConfig>(\"image\", {})),\n );\n }\n}\n",
@@ -33,7 +37,7 @@
33
37
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { redisConfigDefaults, type RedisConfig } from \"./config\";\nimport { RedisManager } from \"./RedisManager\";\n\nexport class RedisServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n RedisManager,\n () =>\n new RedisManager(\n withDefaults(\n redisConfigDefaults(),\n this.app.config.get<RedisConfig>(\"redis\", {}),\n ),\n ),\n );\n }\n\n /**\n * Closes the client, if anything built one. Under `gemi dev` this is what\n * keeps each `bun --hot` reload from leaving a Redis connection behind; see\n * `DatabaseServiceProvider.shutdown`.\n */\n shutdown() {\n if (!this.app.resolved(RedisManager)) return;\n this.app.make(RedisManager).close();\n }\n}\n",
34
38
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { McpRegistry } from \"../mcp/McpRegistry\";\nimport { McpHttpServer } from \"../mcp/http/McpHttpServer\";\nimport { ApiRouteDispatcher } from \"./ApiRouteDispatcher\";\nimport { DomainRouter } from \"./DomainRouter\";\nimport { ViewRouteDispatcher } from \"./ViewRouteDispatcher\";\nimport type { ApiRouteConfig, DomainsConfig, McpRouteConfig, ViewRouteConfig } from \"./config\";\nimport type { Repository } from \"../../support/Repository\";\n\nfunction readConfig<T>(config: Repository, key: string): T {\n const slice = config.get<T>(key);\n if (!slice) {\n throw new Error(\n `Missing \"${key}\" configuration. Route dispatching needs a root router — declare it in \"app/config/route.ts\".`,\n );\n }\n return slice;\n}\n\n/**\n * Owns both route dispatchers. Laravel ships a single RouteServiceProvider for\n * every route file it loads; the api/view split is a config slice, not a\n * separate provider.\n */\nexport class RouteServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n ApiRouteDispatcher,\n () =>\n new ApiRouteDispatcher(\n readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n ),\n );\n\n this.app.singleton(\n ViewRouteDispatcher,\n () =>\n new ViewRouteDispatcher(\n readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n ),\n );\n\n // The root pair above is the root group's; the other `route.domains`\n // groups get their own only when they bring their own routers.\n this.app.singleton(\n DomainRouter,\n () =>\n new DomainRouter(\n { api: this.app.make(ApiRouteDispatcher), view: this.app.make(ViewRouteDispatcher) },\n {\n api: readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n view: readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n domains: this.app.config.get<DomainsConfig | undefined>(\"route.domains\"),\n },\n ),\n );\n\n // Bound whether or not the app declares one, so asking for it without\n // `route.mcp` fails with a sentence rather than an unbound token.\n this.app.singleton(McpRegistry, () => {\n const config = this.app.config.get<McpRouteConfig | undefined>(\"route.mcp\");\n if (!config?.router) {\n throw new Error(\n 'No MCP router is configured. Declare one as `mcp: { router }` in \"app/config/route.ts\".',\n );\n }\n return new McpRegistry(new config.router(), this.app.make(ApiRouteDispatcher), {\n files: config.remote?.files,\n });\n });\n this.registerMcpHttp();\n }\n\n /**\n * Bound here and built at boot when `route.mcp.remote.enabled`, so a\n * misconfigured endpoint — no resolver, no url, no SECRET — fails the boot,\n * not the first client that connects.\n */\n private registerMcpHttp() {\n this.app.singleton(McpHttpServer, () => {\n const config = this.app.config.get<McpRouteConfig | undefined>(\"route.mcp\");\n if (!config?.remote?.enabled) {\n throw new Error(\"The MCP endpoint is not enabled: set route.mcp.remote.enabled.\");\n }\n return new McpHttpServer(this.app.make(McpRegistry), config.remote);\n });\n }\n\n /**\n * The dispatchers of every host group, and the MCP registry when an app declares one, must\n * not be built lazily: constructing the dispatchers flattens the route\n * tables and runs `assertNoReservedRoutePaths`, and constructing the registry\n * resolves every tool against those tables. A missing `route` config, a\n * route under a reserved prefix or a tool naming a route that is gone has to\n * fail the boot rather than the first request, or the first tool call, that\n * happens to hit it.\n */\n boot() {\n this.app.make(ApiRouteDispatcher);\n this.app.make(ViewRouteDispatcher);\n // Builds every host group's dispatchers and validates `route.domains`.\n this.app.make(DomainRouter);\n if (this.app.config.get(\"route.mcp\")) {\n this.app.make(McpRegistry);\n }\n const remote = this.app.config.get<McpRouteConfig[\"remote\"]>(\"route.mcp.remote\");\n if (remote?.enabled === true) {\n this.app.make(McpHttpServer);\n } else if (remote?.enabled !== undefined && remote.enabled !== false) {\n throw new Error(\"route.mcp.remote.enabled must be true or false.\");\n }\n }\n}\n"
35
39
  ],
36
- "mappings": "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",
37
- "debugId": "3192256C4AFE9F0A64756E2164756E21",
40
+ "mappings": "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",
41
+ "debugId": "611A6EA8F973D2E764756E2164756E21",
38
42
  "names": []
39
43
  }