gemi 0.56.0 → 0.58.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 (257) hide show
  1. package/dist/app/index.js +1 -1
  2. package/dist/broadcasting/index.js +1 -1
  3. package/dist/bun/plugin.js +1 -1
  4. package/dist/bun/preload.js +1 -1
  5. package/dist/{chunk-jdj7k3r9.js → chunk-0a2xgcj3.js} +2 -2
  6. package/dist/{chunk-jdj7k3r9.js.map → chunk-0a2xgcj3.js.map} +1 -1
  7. package/dist/{chunk-3e88tyee.js → chunk-3337e5g0.js} +2 -2
  8. package/dist/{chunk-3e88tyee.js.map → chunk-3337e5g0.js.map} +1 -1
  9. package/dist/chunk-3aa287k7.js +6 -0
  10. package/dist/{chunk-cv9w5cmb.js.map → chunk-3aa287k7.js.map} +2 -2
  11. package/dist/{chunk-01am9k5v.js → chunk-3g5bjvdf.js} +2 -2
  12. package/dist/{chunk-01am9k5v.js.map → chunk-3g5bjvdf.js.map} +1 -1
  13. package/dist/{chunk-w9k9s4wh.js → chunk-3xadx444.js} +2 -2
  14. package/dist/{chunk-w9k9s4wh.js.map → chunk-3xadx444.js.map} +1 -1
  15. package/dist/{chunk-npg72mez.js → chunk-3zxwscmf.js} +2 -2
  16. package/dist/{chunk-kgmr9qxx.js.map → chunk-3zxwscmf.js.map} +1 -1
  17. package/dist/{chunk-64s1pzz1.js → chunk-437085pe.js} +2 -2
  18. package/dist/{chunk-64s1pzz1.js.map → chunk-437085pe.js.map} +1 -1
  19. package/dist/{chunk-eqrd31ye.js → chunk-4yt5x8s2.js} +2 -2
  20. package/dist/{chunk-eqrd31ye.js.map → chunk-4yt5x8s2.js.map} +1 -1
  21. package/dist/{chunk-9r0sb4zn.js → chunk-5athahgr.js} +2 -2
  22. package/dist/{chunk-9r0sb4zn.js.map → chunk-5athahgr.js.map} +1 -1
  23. package/dist/{chunk-g30q4n5y.js → chunk-5n2rvfh3.js} +2 -2
  24. package/dist/{chunk-g30q4n5y.js.map → chunk-5n2rvfh3.js.map} +1 -1
  25. package/dist/{chunk-1zfsgffv.js → chunk-6235kb30.js} +3 -3
  26. package/dist/{chunk-1zfsgffv.js.map → chunk-6235kb30.js.map} +1 -1
  27. package/dist/{chunk-javjeayw.js → chunk-7b0x860b.js} +2 -2
  28. package/dist/{chunk-javjeayw.js.map → chunk-7b0x860b.js.map} +1 -1
  29. package/dist/{chunk-4qwwy968.js → chunk-7ef5n8k2.js} +2 -2
  30. package/dist/{chunk-4qwwy968.js.map → chunk-7ef5n8k2.js.map} +1 -1
  31. package/dist/{chunk-q0waxxz5.js → chunk-7j6wbv12.js} +2 -2
  32. package/dist/{chunk-q0waxxz5.js.map → chunk-7j6wbv12.js.map} +1 -1
  33. package/dist/chunk-86jebsm4.js +9 -0
  34. package/dist/{chunk-kry5vwam.js.map → chunk-86jebsm4.js.map} +3 -3
  35. package/dist/chunk-87qab82w.js +5 -0
  36. package/dist/chunk-87qab82w.js.map +37 -0
  37. package/dist/{chunk-36pg61vt.js → chunk-8gew8b9a.js} +2 -2
  38. package/dist/{chunk-36pg61vt.js.map → chunk-8gew8b9a.js.map} +1 -1
  39. package/dist/{chunk-v6v6sem5.js → chunk-9m2tbf3n.js} +2 -2
  40. package/dist/{chunk-v6v6sem5.js.map → chunk-9m2tbf3n.js.map} +1 -1
  41. package/dist/{chunk-gzdf2025.js → chunk-a2sgjpvq.js} +2 -2
  42. package/dist/{chunk-gzdf2025.js.map → chunk-a2sgjpvq.js.map} +1 -1
  43. package/dist/chunk-b35e128b.js +5 -0
  44. package/dist/{chunk-b50zmz3t.js.map → chunk-b35e128b.js.map} +1 -1
  45. package/dist/{chunk-ct274qts.js → chunk-cyaz97p5.js} +2 -2
  46. package/dist/{chunk-ct274qts.js.map → chunk-cyaz97p5.js.map} +1 -1
  47. package/dist/{chunk-v06qcyj5.js → chunk-d125j8t0.js} +3 -3
  48. package/dist/{chunk-v06qcyj5.js.map → chunk-d125j8t0.js.map} +1 -1
  49. package/dist/{chunk-hs5v3eqj.js → chunk-dgsgjg53.js} +2 -2
  50. package/dist/{chunk-hs5v3eqj.js.map → chunk-dgsgjg53.js.map} +1 -1
  51. package/dist/{chunk-xjy5apyr.js → chunk-eejmhtnc.js} +2 -2
  52. package/dist/{chunk-xjy5apyr.js.map → chunk-eejmhtnc.js.map} +1 -1
  53. package/dist/{chunk-3y75q5a2.js → chunk-fjm4y8bn.js} +2 -2
  54. package/dist/{chunk-3y75q5a2.js.map → chunk-fjm4y8bn.js.map} +1 -1
  55. package/dist/{chunk-9c89q2mz.js → chunk-grdahng8.js} +2 -2
  56. package/dist/{chunk-9c89q2mz.js.map → chunk-grdahng8.js.map} +1 -1
  57. package/dist/{chunk-699z6d8y.js → chunk-gw6agevz.js} +3 -3
  58. package/dist/{chunk-699z6d8y.js.map → chunk-gw6agevz.js.map} +1 -1
  59. package/dist/{chunk-62ke19q4.js → chunk-hppagzz4.js} +4 -4
  60. package/dist/{chunk-62ke19q4.js.map → chunk-hppagzz4.js.map} +1 -1
  61. package/dist/chunk-hwa5sqw5.js +19 -0
  62. package/dist/{chunk-tmnhkphv.js.map → chunk-hwa5sqw5.js.map} +12 -6
  63. package/dist/chunk-hxf1re93.js +4 -0
  64. package/dist/{chunk-vkngcrzq.js.map → chunk-hxf1re93.js.map} +6 -5
  65. package/dist/{chunk-d36dfqxw.js → chunk-j0c6ytkj.js} +3 -3
  66. package/dist/{chunk-d36dfqxw.js.map → chunk-j0c6ytkj.js.map} +1 -1
  67. package/dist/{chunk-kgmr9qxx.js → chunk-jhkjz9jr.js} +2 -2
  68. package/dist/{chunk-npg72mez.js.map → chunk-jhkjz9jr.js.map} +1 -1
  69. package/dist/{chunk-62723jyy.js → chunk-k0fvsyeh.js} +1 -1
  70. package/dist/{chunk-31kcf7dq.js → chunk-keehyx51.js} +2 -2
  71. package/dist/{chunk-31kcf7dq.js.map → chunk-keehyx51.js.map} +1 -1
  72. package/dist/{chunk-enhkf60v.js → chunk-m3xy5xyf.js} +2 -2
  73. package/dist/{chunk-enhkf60v.js.map → chunk-m3xy5xyf.js.map} +1 -1
  74. package/dist/{chunk-c75mymmq.js → chunk-mkfpnymy.js} +1 -1
  75. package/dist/{chunk-rgb69nh1.js → chunk-mwpdp09e.js} +2 -2
  76. package/dist/{chunk-rgb69nh1.js.map → chunk-mwpdp09e.js.map} +1 -1
  77. package/dist/chunk-pmhd6zfc.js +37 -0
  78. package/dist/chunk-pmhd6zfc.js.map +20 -0
  79. package/dist/chunk-qb5mv6pj.js +5 -0
  80. package/dist/chunk-qb5mv6pj.js.map +12 -0
  81. package/dist/{chunk-1pwwrpa3.js → chunk-qgxr0g36.js} +2 -2
  82. package/dist/{chunk-1pwwrpa3.js.map → chunk-qgxr0g36.js.map} +1 -1
  83. package/dist/{chunk-4yafsffx.js → chunk-sy7jbdeb.js} +2 -2
  84. package/dist/{chunk-4yafsffx.js.map → chunk-sy7jbdeb.js.map} +1 -1
  85. package/dist/{chunk-gasdfwva.js → chunk-szss069z.js} +2 -2
  86. package/dist/{chunk-gasdfwva.js.map → chunk-szss069z.js.map} +1 -1
  87. package/dist/{chunk-m0ggfy1m.js → chunk-tss5svjr.js} +2 -2
  88. package/dist/{chunk-m0ggfy1m.js.map → chunk-tss5svjr.js.map} +1 -1
  89. package/dist/{chunk-dzzmqv0j.js → chunk-vr90r27j.js} +2 -2
  90. package/dist/{chunk-dzzmqv0j.js.map → chunk-vr90r27j.js.map} +1 -1
  91. package/dist/{chunk-pvdbrt4z.js → chunk-w62m5f0n.js} +3 -3
  92. package/dist/{chunk-pvdbrt4z.js.map → chunk-w62m5f0n.js.map} +1 -1
  93. package/dist/{chunk-cn2r5jfj.js → chunk-w7rf99w6.js} +2 -2
  94. package/dist/{chunk-cn2r5jfj.js.map → chunk-w7rf99w6.js.map} +1 -1
  95. package/dist/{chunk-tja0c815.js → chunk-wbrj0gya.js} +2 -2
  96. package/dist/{chunk-tja0c815.js.map → chunk-wbrj0gya.js.map} +1 -1
  97. package/dist/{chunk-rsdg619q.js → chunk-xdv1b8mr.js} +2 -2
  98. package/dist/{chunk-rsdg619q.js.map → chunk-xdv1b8mr.js.map} +1 -1
  99. package/dist/{chunk-h3mwgbg7.js → chunk-xey9cbap.js} +2 -2
  100. package/dist/{chunk-h3mwgbg7.js.map → chunk-xey9cbap.js.map} +1 -1
  101. package/dist/{chunk-wgpa04jb.js → chunk-xzk827r3.js} +2 -2
  102. package/dist/{chunk-wgpa04jb.js.map → chunk-xzk827r3.js.map} +1 -1
  103. package/dist/{chunk-x14sk95v.js → chunk-y6a8r2bn.js} +3 -3
  104. package/dist/{chunk-x14sk95v.js.map → chunk-y6a8r2bn.js.map} +1 -1
  105. package/dist/{chunk-33wjsw4r.js → chunk-yed5whgs.js} +3 -3
  106. package/dist/{chunk-33wjsw4r.js.map → chunk-yed5whgs.js.map} +1 -1
  107. package/dist/{chunk-02gdzs5t.js → chunk-yf7vz71n.js} +1 -1
  108. package/dist/{chunk-y9fp58bg.js → chunk-yjzs247s.js} +2 -2
  109. package/dist/{chunk-y9fp58bg.js.map → chunk-yjzs247s.js.map} +1 -1
  110. package/dist/{chunk-kgg1eqne.js → chunk-yy0eb9wn.js} +2 -2
  111. package/dist/{chunk-kgg1eqne.js.map → chunk-yy0eb9wn.js.map} +1 -1
  112. package/dist/{chunk-4xx78ba9.js → chunk-zbxgbr12.js} +2 -2
  113. package/dist/{chunk-4xx78ba9.js.map → chunk-zbxgbr12.js.map} +1 -1
  114. package/dist/{chunk-8k1zqrvh.js → chunk-zh2egcyb.js} +2 -2
  115. package/dist/{chunk-8k1zqrvh.js.map → chunk-zh2egcyb.js.map} +1 -1
  116. package/dist/chunks/ThemeProvider-li1J_igh.js.map +1 -1
  117. package/dist/client/ClientRouter.d.ts.map +1 -1
  118. package/dist/client/ProgressManager.d.ts +1 -1
  119. package/dist/client/RouteStateContext.d.ts +9 -0
  120. package/dist/client/RouteStateContext.d.ts.map +1 -1
  121. package/dist/client/ServerDataProvider.d.ts +7 -0
  122. package/dist/client/ServerDataProvider.d.ts.map +1 -1
  123. package/dist/client/index.d.ts +2 -1
  124. package/dist/client/index.d.ts.map +1 -1
  125. package/dist/client/index.js +68 -10
  126. package/dist/client/index.js.map +1 -1
  127. package/dist/client/rpc.d.ts +42 -0
  128. package/dist/client/rpc.d.ts.map +1 -1
  129. package/dist/client/useFeature.d.ts +40 -0
  130. package/dist/client/useFeature.d.ts.map +1 -0
  131. package/dist/config/index.js +1 -1
  132. package/dist/console/run.js +2 -2
  133. package/dist/console/run.js.map +1 -1
  134. package/dist/container/index.js +2 -2
  135. package/dist/container/index.js.map +1 -1
  136. package/dist/database/index.js +2 -2
  137. package/dist/database/index.js.map +1 -1
  138. package/dist/email/index.js +2 -2
  139. package/dist/email/index.js.map +1 -1
  140. package/dist/facades/Features.d.ts +57 -0
  141. package/dist/facades/Features.d.ts.map +1 -0
  142. package/dist/facades/index.d.ts +1 -0
  143. package/dist/facades/index.d.ts.map +1 -1
  144. package/dist/facades/index.js +2 -2
  145. package/dist/facades/index.js.map +1 -1
  146. package/dist/foundation/index.js +2 -2
  147. package/dist/foundation/index.js.map +1 -1
  148. package/dist/gemi.d.ts +13 -5
  149. package/dist/http/ApiRouter.d.ts +3 -2
  150. package/dist/http/ApiRouter.d.ts.map +1 -1
  151. package/dist/http/HttpRequest.d.ts +4 -0
  152. package/dist/http/HttpRequest.d.ts.map +1 -1
  153. package/dist/http/ViewRouter.d.ts +127 -4
  154. package/dist/http/ViewRouter.d.ts.map +1 -1
  155. package/dist/http/index.d.ts +1 -0
  156. package/dist/http/index.d.ts.map +1 -1
  157. package/dist/http/index.js +2 -2
  158. package/dist/http/index.js.map +1 -1
  159. package/dist/http/middlewareList.d.ts +25 -0
  160. package/dist/http/middlewareList.d.ts.map +1 -0
  161. package/dist/http/requestContext.d.ts +57 -0
  162. package/dist/http/requestContext.d.ts.map +1 -1
  163. package/dist/i18n/dictionaryRuntime.js +2 -2
  164. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  165. package/dist/i18n/index.js +2 -2
  166. package/dist/i18n/index.js.map +1 -1
  167. package/dist/ide/typescript-plugin/index.js +1206 -0
  168. package/dist/ide/typescript-plugin/index.js.map +17 -0
  169. package/dist/kernel/index.js +3 -3
  170. package/dist/kernel/index.js.map +3 -3
  171. package/dist/kernel/providers.d.ts +16 -4
  172. package/dist/kernel/providers.d.ts.map +1 -1
  173. package/dist/orm/context.d.ts +65 -0
  174. package/dist/orm/context.d.ts.map +1 -1
  175. package/dist/orm/index.js +2 -2
  176. package/dist/orm/index.js.map +1 -1
  177. package/dist/server/index.js +2 -2
  178. package/dist/server/index.js.map +1 -1
  179. package/dist/services/discovery.d.ts +27 -0
  180. package/dist/services/discovery.d.ts.map +1 -1
  181. package/dist/services/events/Event.d.ts +208 -0
  182. package/dist/services/events/Event.d.ts.map +1 -0
  183. package/dist/services/events/EventManager.d.ts +285 -0
  184. package/dist/services/events/EventManager.d.ts.map +1 -0
  185. package/dist/services/events/EventServiceProvider.d.ts +46 -0
  186. package/dist/services/events/EventServiceProvider.d.ts.map +1 -0
  187. package/dist/services/events/FakeEventManager.d.ts +155 -0
  188. package/dist/services/events/FakeEventManager.d.ts.map +1 -0
  189. package/dist/services/events/FakeEventManager.test-d.d.ts +2 -0
  190. package/dist/services/events/FakeEventManager.test-d.d.ts.map +1 -0
  191. package/dist/services/events/Listener.d.ts +189 -0
  192. package/dist/services/events/Listener.d.ts.map +1 -0
  193. package/dist/services/events/Listener.test-d.d.ts +2 -0
  194. package/dist/services/events/Listener.test-d.d.ts.map +1 -0
  195. package/dist/services/events/config.d.ts +55 -0
  196. package/dist/services/events/config.d.ts.map +1 -0
  197. package/dist/services/events/listenerJob.d.ts +43 -0
  198. package/dist/services/events/listenerJob.d.ts.map +1 -0
  199. package/dist/services/features/FeatureFlagStore.d.ts +60 -0
  200. package/dist/services/features/FeatureFlagStore.d.ts.map +1 -0
  201. package/dist/services/features/FeatureManager.d.ts +82 -0
  202. package/dist/services/features/FeatureManager.d.ts.map +1 -0
  203. package/dist/services/features/FeaturesServiceProvider.d.ts +6 -0
  204. package/dist/services/features/FeaturesServiceProvider.d.ts.map +1 -0
  205. package/dist/services/features/bucket.d.ts +57 -0
  206. package/dist/services/features/bucket.d.ts.map +1 -0
  207. package/dist/services/features/config.d.ts +57 -0
  208. package/dist/services/features/config.d.ts.map +1 -0
  209. package/dist/services/features/context.d.ts +31 -0
  210. package/dist/services/features/context.d.ts.map +1 -0
  211. package/dist/services/features/defineFeature.d.ts +145 -0
  212. package/dist/services/features/defineFeature.d.ts.map +1 -0
  213. package/dist/services/features/evaluate.d.ts +74 -0
  214. package/dist/services/features/evaluate.d.ts.map +1 -0
  215. package/dist/services/features/sources/DatabaseFeatureFlagSource.d.ts +19 -0
  216. package/dist/services/features/sources/DatabaseFeatureFlagSource.d.ts.map +1 -0
  217. package/dist/services/features/sources/FeatureFlagSource.d.ts +30 -0
  218. package/dist/services/features/sources/FeatureFlagSource.d.ts.map +1 -0
  219. package/dist/services/features/sources/StaticFeatureFlagSource.d.ts +24 -0
  220. package/dist/services/features/sources/StaticFeatureFlagSource.d.ts.map +1 -0
  221. package/dist/services/features/types.d.ts +63 -0
  222. package/dist/services/features/types.d.ts.map +1 -0
  223. package/dist/services/index.d.ts +18 -1
  224. package/dist/services/index.d.ts.map +1 -1
  225. package/dist/services/index.js +8 -8
  226. package/dist/services/index.js.map +8 -4
  227. package/dist/services/queue/QueueManager.d.ts +31 -0
  228. package/dist/services/queue/QueueManager.d.ts.map +1 -1
  229. package/dist/services/router/ViewRouteDispatcher.d.ts +8 -0
  230. package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
  231. package/dist/services/router/createFlatViewRoutes.d.ts +14 -0
  232. package/dist/services/router/createFlatViewRoutes.d.ts.map +1 -1
  233. package/dist/services/router/streamQueryInjection.d.ts.map +1 -1
  234. package/dist/support/index.js +2 -2
  235. package/dist/support/index.js.map +1 -1
  236. package/dist/testing/Page.d.ts +12 -0
  237. package/dist/testing/Page.d.ts.map +1 -1
  238. package/dist/testing/index.d.ts +24 -0
  239. package/dist/testing/index.d.ts.map +1 -1
  240. package/dist/testing/index.js +7 -3
  241. package/dist/testing/index.js.map +1 -1
  242. package/ide/typescript-plugin/package.json +5 -0
  243. package/package.json +4 -2
  244. package/dist/chunk-4t80js0n.js +0 -33
  245. package/dist/chunk-4t80js0n.js.map +0 -18
  246. package/dist/chunk-98a576s9.js +0 -5
  247. package/dist/chunk-98a576s9.js.map +0 -30
  248. package/dist/chunk-b50zmz3t.js +0 -5
  249. package/dist/chunk-cv9w5cmb.js +0 -6
  250. package/dist/chunk-f9mfw82d.js +0 -5
  251. package/dist/chunk-f9mfw82d.js.map +0 -12
  252. package/dist/chunk-kry5vwam.js +0 -9
  253. package/dist/chunk-tmnhkphv.js +0 -19
  254. package/dist/chunk-vkngcrzq.js +0 -4
  255. /package/dist/{chunk-62723jyy.js.map → chunk-k0fvsyeh.js.map} +0 -0
  256. /package/dist/{chunk-c75mymmq.js.map → chunk-mkfpnymy.js.map} +0 -0
  257. /package/dist/{chunk-02gdzs5t.js.map → chunk-yf7vz71n.js.map} +0 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../ide/typescript-plugin/ast.ts", "../../../ide/typescript-plugin/callSite.ts", "../../../ide/typescript-plugin/lookup.ts", "../../../ide/typescript-plugin/entryPoints.ts", "../../../ide/typescript-plugin/routePath.ts", "../../../ide/typescript-plugin/routeTable.ts", "../../../ide/typescript-plugin/plugin.ts", "../../../ide/typescript-plugin/index.ts"],
4
+ "sourcesContent": [
5
+ "import type ts from \"typescript\";\n\nimport type { Span, TargetKind } from \"./types\";\n\n/**\n * The `typescript` module, as tsserver hands it to a plugin.\n *\n * A language service plugin must never `require(\"typescript\")` itself — the\n * editor may be running a different copy than the one resolvable from the\n * plugin's own `node_modules`, and two copies means enums with different\n * numeric values and `instanceof`-style identity checks that quietly fail. Every\n * function here takes the injected module instead.\n */\nexport type TS = typeof ts;\n\n/** Strips the wrappers that carry no meaning for what an expression *is*. */\nexport function unwrapExpression(ts: TS, node: ts.Expression): ts.Expression {\n let current = node;\n for (;;) {\n if (ts.isParenthesizedExpression(current)) current = current.expression;\n else if (ts.isAsExpression(current)) current = current.expression;\n else if (ts.isSatisfiesExpression(current)) current = current.expression;\n else if (ts.isNonNullExpression(current)) current = current.expression;\n else if (ts.isTypeAssertionExpression(current)) current = current.expression;\n else return current;\n }\n}\n\n/**\n * Peels the fluent builders a route entry can be wrapped in —\n * `this.get(...).middleware([...])`, `this.layout(...).alwaysRun()` — down to\n * the `this.<method>(...)` call that decides what the route is.\n */\nexport function unwrapBuilderChain(ts: TS, node: ts.Expression): ts.Expression {\n const chainable = new Set([\"middleware\", \"alwaysRun\"]);\n let current = unwrapExpression(ts, node);\n while (\n ts.isCallExpression(current) &&\n ts.isPropertyAccessExpression(current.expression) &&\n chainable.has(current.expression.name.text)\n ) {\n current = unwrapExpression(ts, current.expression.expression);\n }\n return current;\n}\n\nexport interface ThisCall {\n method: string;\n args: readonly ts.Expression[];\n node: ts.CallExpression;\n}\n\n/** Matches `this.<method>(...)`, the shape every route builder takes. */\nexport function getThisCall(ts: TS, node: ts.Expression): ThisCall | undefined {\n if (!ts.isCallExpression(node)) return undefined;\n const callee = node.expression;\n if (!ts.isPropertyAccessExpression(callee)) return undefined;\n if (callee.expression.kind !== ts.SyntaxKind.ThisKeyword) return undefined;\n return { method: callee.name.text, args: node.arguments, node };\n}\n\n/**\n * The string an expression denotes, whether it is spelled inline or reached\n * through a constant. The checker answers the second case for free, so\n * `this.get(Controller, METHOD)` resolves as well as `this.get(Controller, \"x\")`.\n */\nexport function getStringValue(\n ts: TS,\n checker: ts.TypeChecker,\n node: ts.Expression | undefined,\n): string | undefined {\n if (!node) return undefined;\n const expression = unwrapExpression(ts, node);\n if (ts.isStringLiteralLike(expression)) return expression.text;\n const type = checker.getTypeAtLocation(expression);\n if (type.isStringLiteral()) return type.value;\n return undefined;\n}\n\n/** The key of a `routes` entry, including `[SOME_CONST]: ...` computed keys. */\nexport function getPropertyKeyText(\n ts: TS,\n checker: ts.TypeChecker,\n name: ts.PropertyName,\n): string | undefined {\n if (ts.isStringLiteralLike(name)) return name.text;\n if (ts.isIdentifier(name)) return name.text;\n if (ts.isNumericLiteral(name)) return name.text;\n if (ts.isComputedPropertyName(name)) return getStringValue(ts, checker, name.expression);\n return undefined;\n}\n\n/** Follows imports and aliases to the class an expression names. */\nexport function resolveClassDeclaration(\n ts: TS,\n checker: ts.TypeChecker,\n node: ts.Expression,\n): ts.ClassLikeDeclaration | undefined {\n if (ts.isClassExpression(node)) return node;\n let symbol = checker.getSymbolAtLocation(node);\n if (!symbol) return undefined;\n if (symbol.flags & ts.SymbolFlags.Alias) symbol = checker.getAliasedSymbol(symbol);\n const declaration = symbol.valueDeclaration ?? symbol.declarations?.[0];\n return declaration && ts.isClassLike(declaration) ? declaration : undefined;\n}\n\n/**\n * The object literal assigned to a class's `routes` property.\n *\n * A router that assigns `routes` anywhere but its own initializer — in a\n * constructor, behind a helper — is invisible here, and that is a deliberate\n * floor rather than a gap to close: those shapes are invisible to `CreateRPC`\n * too, so a route declared that way has no typed call site to jump from.\n *\n * A spread *inside* the initializer is the one case where the two disagree.\n * `RouteParser` reads the declared type of `routes` and so keeps it; the walk\n * reads syntax and drops it. `RouteTableBuilder.noteUnreadableEntry` logs each\n * one it meets, because a route that autocompletes and does not jump is\n * otherwise indistinguishable from a bug in this plugin.\n */\nexport function getRoutesObjectLiteral(\n ts: TS,\n classDeclaration: ts.ClassLikeDeclaration,\n): ts.ObjectLiteralExpression | undefined {\n for (const member of classDeclaration.members) {\n if (!ts.isPropertyDeclaration(member)) continue;\n if (!member.name || !ts.isIdentifier(member.name) || member.name.text !== \"routes\") continue;\n if (!member.initializer) continue;\n const initializer = unwrapExpression(ts, member.initializer);\n if (ts.isObjectLiteralExpression(initializer)) return initializer;\n }\n return undefined;\n}\n\nexport function spanOf(node: ts.Node): Span {\n const start = node.getStart(node.getSourceFile());\n return { start, length: node.getEnd() - start };\n}\n\n/** The identifier a declaration is named by, which is where a jump should land. */\nexport function nameNodeOf(ts: TS, declaration: ts.Declaration): ts.Node {\n const named = declaration as ts.NamedDeclaration;\n return named.name && !ts.isComputedPropertyName(named.name) ? named.name : declaration;\n}\n\nexport function targetFromDeclaration(\n ts: TS,\n declaration: ts.Declaration,\n name: string,\n containerName: string,\n kind: TargetKind,\n): {\n fileName: string;\n span: Span;\n contextSpan: Span;\n name: string;\n containerName: string;\n kind: TargetKind;\n} {\n return {\n fileName: declaration.getSourceFile().fileName,\n span: spanOf(nameNodeOf(ts, declaration)),\n contextSpan: spanOf(declaration),\n name,\n containerName,\n kind,\n };\n}\n\n/** The class name to show alongside a handler, skipping `export default class`'s `\"default\"`. */\nexport function displayNameOfClass(\n ts: TS,\n checker: ts.TypeChecker,\n expression: ts.Expression,\n): string {\n const declaration = resolveClassDeclaration(ts, checker, expression);\n if (declaration?.name) return declaration.name.text;\n return expression.getText();\n}\n",
6
+ "import type ts from \"typescript\";\n\nimport { getStringValue, type TS } from \"./ast\";\nimport type { HttpVerb } from \"./types\";\n\nconst HTTP_VERBS = new Set<string>([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\n/** Attributes that name a page to navigate to rather than an endpoint to call. */\nconst VIEW_ATTRIBUTES = new Set([\"href\", \"to\"]);\n/** Attributes that name an endpoint to submit to. `<Form action=… method=…>`. */\nconst ACTION_ATTRIBUTES = new Set([\"action\"]);\n\nexport interface RouteQuery {\n node: ts.StringLiteralLike;\n /** The literal's text — the route path as the user typed it. */\n path: string;\n /**\n * The paths this position is allowed to hold, when the signature says so.\n *\n * `useQuery(url: T)` declares `T extends keyof GetRPC`, so the constraint of\n * the parameter this argument fills *is* the GET route set — which is how a\n * `useQuery` call is told apart from a `useMutation` one without either name\n * appearing here. Any wrapper an app writes over these hooks carries the same\n * constraint through, and is understood for free.\n */\n allowedPaths?: ReadonlySet<string>;\n /** A verb the call site names outright, e.g. `useMutation(\"PUT\", …)`. */\n verb?: HttpVerb;\n /** Whether the surrounding syntax means a page or an endpoint. */\n prefer?: \"api\" | \"view\";\n}\n\n/**\n * Decides whether the string literal at `position` is naming a route, and\n * gathers whatever the surrounding code says about *which* route.\n *\n * Nothing here confirms the path exists — that is the route table's job. This\n * only answers \"could this be a route reference, and what narrows it\".\n */\nexport function findRouteQuery(\n ts: TS,\n checker: ts.TypeChecker,\n sourceFile: ts.SourceFile,\n position: number,\n): RouteQuery | undefined {\n const node = findStringLiteral(ts, sourceFile, position);\n if (!node) return undefined;\n if (!isRouteReferencePosition(ts, node)) return undefined;\n\n return {\n node,\n path: node.text,\n allowedPaths: allowedPathsAt(ts, checker, node),\n ...contextHints(ts, checker, node),\n };\n}\n\nfunction findStringLiteral(\n ts: TS,\n sourceFile: ts.SourceFile,\n position: number,\n): ts.StringLiteralLike | undefined {\n let found: ts.StringLiteralLike | undefined;\n const visit = (node: ts.Node): void => {\n if (position < node.getFullStart() || position > node.getEnd()) return;\n if (ts.isStringLiteralLike(node)) {\n // Inside the quotes only: at the closing quote the request belongs to\n // whatever follows, and hijacking it there would be surprising.\n const start = node.getStart(sourceFile);\n if (position > start && position < node.getEnd()) found = node;\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(sourceFile, visit);\n return found;\n}\n\n/**\n * Rejects the string positions that already mean something else, so the plugin\n * never shadows a definition TypeScript can answer better itself.\n */\nfunction isRouteReferencePosition(ts: TS, node: ts.StringLiteralLike): boolean {\n const parent = node.parent;\n if (!parent) return false;\n\n // Module specifiers already go to definition — the module.\n if (ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent)) return false;\n if (ts.isImportTypeNode(parent) || ts.isExternalModuleReference(parent)) return false;\n if (ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent)) return false;\n\n // A key, not a value.\n if (\n (ts.isPropertyAssignment(parent) ||\n ts.isPropertySignature(parent) ||\n ts.isMethodDeclaration(parent) ||\n ts.isPropertyDeclaration(parent) ||\n ts.isEnumMember(parent)) &&\n parent.name === node\n ) {\n return false;\n }\n\n // A type, where the definition is the type declaration.\n if (ts.isLiteralTypeNode(parent)) return false;\n\n // `config[\"/home\"]` — TypeScript resolves this to the property, and that is\n // the better answer.\n if (ts.isElementAccessExpression(parent) && parent.argumentExpression === node) return false;\n\n return true;\n}\n\nfunction allowedPathsAt(\n ts: TS,\n checker: ts.TypeChecker,\n node: ts.StringLiteralLike,\n): ReadonlySet<string> | undefined {\n const site = argumentSite(ts, node);\n if (!site) return undefined;\n\n const declaration = checker.getResolvedSignature(site.call)?.getDeclaration();\n if (!declaration || !ts.isFunctionLike(declaration)) return undefined;\n\n const parameter = declaration.parameters[site.index];\n // A rest parameter's elements are not this simple to index into, and no route\n // argument is declared that way.\n if (!parameter || parameter.dotDotDotToken) return undefined;\n\n // The *declared* type, not the contextual one: by the time inference has run,\n // the contextual type of `\"/reports\"` is `\"/reports\"`, which says nothing\n // about what else was allowed there.\n let type = checker.getTypeAtLocation(parameter);\n if (site.property !== undefined) {\n const symbol = type.getProperty(site.property);\n if (!symbol) return undefined;\n type = checker.getTypeOfSymbolAtLocation(symbol, parameter);\n }\n\n const constraint = checker.getBaseConstraintOfType(type) ?? type;\n return stringLiteralSet(constraint);\n}\n\ninterface ArgumentSite {\n call: ts.CallExpression | ts.NewExpression;\n index: number;\n /** Set when the path is a property of an options object rather than the argument. */\n property?: string;\n}\n\n/**\n * The call an argument belongs to, and where in it.\n *\n * A path is usually an argument outright — `useQuery(\"/reports\")` — but\n * `useMutate`'s is a property of an options object: `mutate({ path: \"/reports\" })`\n * (`client/useMutate.ts`). Both are declared the same way, `T extends keyof\n * GetRPC`, one on the parameter and one on a property of it, so both are located\n * here and read through the same constraint afterwards. Any other hook that\n * takes its path in an options object is covered by the same rule.\n */\nfunction argumentSite(ts: TS, node: ts.StringLiteralLike): ArgumentSite | undefined {\n const parent = node.parent;\n if (!parent) return undefined;\n\n if (ts.isCallExpression(parent) || ts.isNewExpression(parent)) {\n const index = [...(parent.arguments ?? [])].indexOf(node);\n return index < 0 ? undefined : { call: parent, index };\n }\n\n if (!ts.isPropertyAssignment(parent) || parent.initializer !== node) return undefined;\n const property =\n ts.isIdentifier(parent.name) || ts.isStringLiteralLike(parent.name)\n ? parent.name.text\n : undefined;\n if (property === undefined) return undefined;\n\n const object = parent.parent;\n if (!ts.isObjectLiteralExpression(object)) return undefined;\n const call = object.parent;\n if (!call || (!ts.isCallExpression(call) && !ts.isNewExpression(call))) return undefined;\n const index = [...(call.arguments ?? [])].indexOf(object);\n return index < 0 ? undefined : { call, index, property };\n}\n\n/** The set a type denotes, or `undefined` if it is anything but string literals. */\nfunction stringLiteralSet(type: ts.Type): ReadonlySet<string> | undefined {\n const members = type.isUnion() ? type.types : [type];\n const paths = new Set<string>();\n for (const member of members) {\n if (!member.isStringLiteral()) return undefined;\n paths.add(member.value);\n }\n return paths.size > 0 ? paths : undefined;\n}\n\nfunction contextHints(\n ts: TS,\n checker: ts.TypeChecker,\n node: ts.StringLiteralLike,\n): { verb?: HttpVerb; prefer?: \"api\" | \"view\" } {\n const attribute = enclosingJsxAttribute(ts, node);\n if (attribute) {\n const name = ts.isIdentifier(attribute.name) ? attribute.name.text : attribute.name.getText();\n if (VIEW_ATTRIBUTES.has(name)) return { prefer: \"view\" };\n if (ACTION_ATTRIBUTES.has(name)) {\n return { prefer: \"api\", verb: siblingMethodVerb(ts, checker, attribute) ?? \"POST\" };\n }\n return {};\n }\n\n // `useMutation(\"PUT\", \"/products/:id\")`: the verb sits in the argument\n // before the path. Keyed off the shape rather than the callee's name, so a\n // wrapper that forwards both arguments is understood too.\n const call = node.parent;\n if (call && ts.isCallExpression(call)) {\n const index = call.arguments.indexOf(node);\n const previous = index > 0 ? call.arguments[index - 1] : undefined;\n const value = getStringValue(ts, checker, previous)?.toUpperCase();\n if (value && HTTP_VERBS.has(value)) return { verb: value as HttpVerb, prefer: \"api\" };\n }\n\n return {};\n}\n\nfunction enclosingJsxAttribute(ts: TS, node: ts.StringLiteralLike): ts.JsxAttribute | undefined {\n const parent = node.parent;\n if (!parent) return undefined;\n if (ts.isJsxAttribute(parent)) return parent;\n if (ts.isJsxExpression(parent) && parent.parent && ts.isJsxAttribute(parent.parent)) {\n return parent.parent;\n }\n return undefined;\n}\n\nfunction siblingMethodVerb(\n ts: TS,\n checker: ts.TypeChecker,\n attribute: ts.JsxAttribute,\n): HttpVerb | undefined {\n const attributes = attribute.parent;\n if (!attributes || !ts.isJsxAttributes(attributes)) return undefined;\n for (const sibling of attributes.properties) {\n if (!ts.isJsxAttribute(sibling)) continue;\n const name = ts.isIdentifier(sibling.name) ? sibling.name.text : sibling.name.getText();\n if (name !== \"method\" || !sibling.initializer) continue;\n const initializer = ts.isJsxExpression(sibling.initializer)\n ? sibling.initializer.expression\n : sibling.initializer;\n const value = getStringValue(ts, checker, initializer)?.toUpperCase();\n if (value && HTTP_VERBS.has(value)) return value as HttpVerb;\n }\n return undefined;\n}\n",
7
+ "import type { RouteQuery } from \"./callSite\";\nimport type { ApiRouteEntry, HttpVerb, RouteTable, RouteTarget, ViewRouteEntry } from \"./types\";\n\nexport type RouteCandidate =\n | { kind: \"api\"; entry: ApiRouteEntry }\n | { kind: \"view\"; entry: ViewRouteEntry };\n\nexport interface RouteMatch {\n candidate: RouteCandidate;\n targets: RouteTarget[];\n}\n\nconst VERB_ORDER: HttpVerb[] = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"];\n\ninterface RouteIndex {\n pathsByVerb: Map<HttpVerb, Set<string>>;\n viewPaths: Set<string>;\n /** Every path the walk found, of any verb or kind. */\n knownPaths: Set<string>;\n}\n\nconst indexes = new WeakMap<RouteTable, RouteIndex>();\n\nfunction indexOf(table: RouteTable): RouteIndex {\n const cached = indexes.get(table);\n if (cached) return cached;\n\n const knownPaths = new Set<string>();\n const pathsByVerb = new Map<HttpVerb, Set<string>>();\n for (const entries of table.api.values()) {\n for (const entry of entries) {\n let paths = pathsByVerb.get(entry.verb);\n if (!paths) pathsByVerb.set(entry.verb, (paths = new Set()));\n paths.add(entry.path);\n knownPaths.add(entry.path);\n }\n }\n const viewPaths = new Set<string>();\n for (const entries of table.views.values()) {\n for (const entry of entries) {\n viewPaths.add(entry.path);\n knownPaths.add(entry.path);\n }\n }\n\n const index = { pathsByVerb, viewPaths, knownPaths };\n indexes.set(table, index);\n return index;\n}\n\n/**\n * The routes a call site could mean, best first.\n *\n * Each signal narrows only when narrowing leaves something — a `href` pointing\n * at what turns out to be an API route, or a `method=\"PUT\"` on a path with no\n * PUT handler, still gets the jump it can rather than none. When more than one\n * route survives, all of them are returned and the editor offers the choice;\n * that is the honest answer for a path that genuinely carries two handlers.\n */\nexport function lookupRoute(table: RouteTable, query: RouteQuery): RouteMatch[] {\n let candidates: RouteCandidate[] = [\n ...(table.api.get(query.path) ?? []).map((entry) => ({ kind: \"api\", entry }) as const),\n ...(table.views.get(query.path) ?? []).map((entry) => ({ kind: \"view\", entry }) as const),\n ];\n if (candidates.length === 0) return [];\n\n if (query.prefer) {\n candidates = narrow(candidates, (candidate) => candidate.kind === query.prefer);\n }\n if (query.verb) {\n candidates = narrow(\n candidates,\n (candidate) => candidate.kind === \"api\" && candidate.entry.verb === query.verb,\n );\n }\n if (query.allowedPaths) {\n const { pathsByVerb, viewPaths, knownPaths } = indexOf(table);\n const allowed = intersect(query.allowedPaths, knownPaths);\n if (allowed.size > 0) {\n candidates = narrow(candidates, (candidate) =>\n candidate.kind === \"api\"\n ? isSubset(allowed, pathsByVerb.get(candidate.entry.verb))\n : isSubset(allowed, viewPaths),\n );\n }\n }\n\n candidates.sort(compareCandidates);\n return candidates.map((candidate) => ({ candidate, targets: candidate.entry.targets }));\n}\n\n/** Applies a filter, unless doing so would leave nothing to jump to. */\nfunction narrow(\n candidates: RouteCandidate[],\n predicate: (candidate: RouteCandidate) => boolean,\n): RouteCandidate[] {\n const kept = candidates.filter(predicate);\n return kept.length > 0 ? kept : candidates;\n}\n\n/**\n * Whether every path the call site accepts is served by this verb.\n *\n * The direction matters. A `useQuery` argument accepts exactly the GET paths,\n * so testing the *accepted set* against each verb's paths identifies the verb;\n * testing one path against the set would not, because a path with both a GET\n * and a POST handler belongs to both.\n */\nfunction isSubset(subset: ReadonlySet<string>, superset: Set<string> | undefined): boolean {\n if (!superset) return false;\n for (const value of subset) {\n if (!superset.has(value)) return false;\n }\n return true;\n}\n\n/**\n * The accepted paths, minus the ones the walk never saw.\n *\n * Without this the containment test is all-or-nothing across the whole project.\n * `keyof GetRPC` comes from the declared type of `routes` and so includes shapes\n * the walk drops — a spread entry, say (`routeTable.ts` logs one when it meets\n * one). A single such path is not in *any* verb's set, so every verb fails the\n * subset test at once, every candidate survives, and disambiguation stops\n * working at call sites nowhere near the route that was missed.\n *\n * A path the walk never saw has no row to jump to either way, so dropping it\n * from the comparison costs nothing and keeps the damage where it belongs.\n */\nfunction intersect(\n subset: ReadonlySet<string>,\n universe: ReadonlySet<string>,\n): ReadonlySet<string> {\n const kept = new Set<string>();\n for (const value of subset) {\n if (universe.has(value)) kept.add(value);\n }\n return kept;\n}\n\nfunction compareCandidates(a: RouteCandidate, b: RouteCandidate): number {\n if (a.kind !== b.kind) return a.kind === \"api\" ? -1 : 1;\n if (a.kind === \"api\" && b.kind === \"api\") {\n return VERB_ORDER.indexOf(a.entry.verb) - VERB_ORDER.indexOf(b.entry.verb);\n }\n // A path's view comes before the layout wrapping it.\n const rank = (kind: \"view\" | \"layout\") => (kind === \"view\" ? 0 : 1);\n return rank((a.entry as ViewRouteEntry).kind) - rank((b.entry as ViewRouteEntry).kind);\n}\n\n/** `GET /products`, `view /reports` — the heading a hover leads with. */\nexport function describeCandidate(candidate: RouteCandidate): string {\n return candidate.kind === \"api\"\n ? `${candidate.entry.verb} ${candidate.entry.path}`\n : `${candidate.entry.kind} ${candidate.entry.path}`;\n}\n\nexport function describeTarget(target: RouteTarget): string {\n switch (target.kind) {\n case \"controller-method\":\n return `${target.containerName}.${target.name}()`;\n case \"inline-handler\":\n return \"inline handler\";\n case \"view-component\":\n return `${target.name} component`;\n case \"route-entry\":\n return `${target.containerName} routes entry`;\n }\n}\n",
8
+ "import type ts from \"typescript\";\n\nimport { resolveClassDeclaration, unwrapExpression, type TS } from \"./ast\";\n\n/** A router class and the path prefix it is mounted under. */\nexport interface RouterMount {\n declaration: ts.ClassLikeDeclaration;\n prefix: string;\n}\n\nexport interface RootRouters {\n api: RouterMount[];\n view: RouterMount[];\n /** Files consulted to get here — part of the table's cache key. */\n dependencies: string[];\n diagnostics: string[];\n}\n\nconst RPC_INTERFACES = {\n api: { interfaceName: \"RPC\" },\n view: { interfaceName: \"ViewRPC\" },\n} as const;\n\nconst CONFIG_HELPER = \"defineRouteConfig\";\nconst CONFIG_MODULE = \"gemi/services\";\n/** The module `RPC` and `ViewRPC` are declared in and augmented into. */\nconst CLIENT_MODULE = \"gemi/client\";\n\n/** Conventional locations, tried only when nothing more authoritative is readable. */\nconst FALLBACK_API_ROUTER = \"app/http/routes/api\";\nconst FALLBACK_VIEW_ROUTER = \"app/http/routes/view\";\n\n/**\n * Finds every router whose routes a client call site can name, and the prefix\n * each is mounted under.\n *\n * The authority is the `RPC` and `ViewRPC` interfaces, because they are what\n * the call site is typed against. An app declares its own routers by augmenting\n * them:\n *\n * ```ts\n * declare module \"gemi/client\" {\n * export interface RPC extends CreateRPC<Api> {}\n * }\n * ```\n *\n * and the framework's base declaration in `client/rpc.ts` adds its own —\n * `CreateRPC<AuthApiRouter, \"/auth\">`. Reading the interfaces therefore picks up\n * both, with the right prefixes, and picks up exactly the routes `useQuery`\n * will accept. Reading the app's route config instead would find the app's\n * routers and miss `/auth/me`, which is as jumpable as any other route.\n *\n * The route config and then convention are the fallbacks, for a project whose\n * routers the augmentation does not name. They are chosen on whether the app's\n * *own* routers were found, not on whether anything was: `client/rpc.ts` mounts\n * `/auth/*` unconditionally, so \"some mount exists\" is true of every gemi\n * project and would make total discovery failure silent.\n */\nexport function findRootRouters(ts: TS, program: ts.Program, projectRoot: string): RootRouters {\n const checker = program.getTypeChecker();\n const result: RootRouters = { api: [], view: [], dependencies: [], diagnostics: [] };\n // One router can be reached through more than one declaration in the merge\n // group — the package's own augmentation and an app's leftover `gemi.d.ts`\n // name the same `Api`. Walking it twice would double every route it holds.\n const seen = new Set<string>();\n\n for (const kind of [\"api\", \"view\"] as const) {\n const { interfaceName } = RPC_INTERFACES[kind];\n for (const declaration of findInterfaceDeclarations(ts, checker, program, interfaceName)) {\n result.dependencies.push(declaration.getSourceFile().fileName);\n for (const mount of readMounts(ts, checker, declaration)) {\n const fileName = mount.declaration.getSourceFile().fileName;\n const key = `${kind}\\0${mount.prefix}\\0${fileName}\\0${mount.declaration.pos}`;\n if (seen.has(key)) continue;\n seen.add(key);\n result[kind].push(mount);\n result.dependencies.push(fileName);\n }\n }\n }\n\n const hasAppMount = (kind: \"api\" | \"view\") =>\n result[kind].some((mount) =>\n isApplicationFile(mount.declaration.getSourceFile().fileName, projectRoot),\n );\n\n if (hasAppMount(\"api\") || hasAppMount(\"view\")) return result;\n\n result.diagnostics.push(\n \"the RPC / ViewRPC augmentation names none of this project's routers — falling back \" +\n \"to the app's route config. Check that gemi/client is imported and that \" +\n `${projectRoot}/${FALLBACK_API_ROUTER}.ts typechecks, so route types and route jumps agree.`,\n );\n\n const config = findRouteConfigCall(ts, program);\n if (config) {\n result.dependencies.push(config.getSourceFile().fileName);\n const object = unwrapExpression(ts, config.arguments[0] ?? config);\n if (ts.isObjectLiteralExpression(object)) {\n for (const kind of [\"api\", \"view\"] as const) {\n const declaration = readRootRouter(ts, checker, object, kind);\n if (!declaration) continue;\n result[kind].push({ declaration, prefix: \"\" });\n result.dependencies.push(declaration.getSourceFile().fileName);\n }\n }\n }\n\n if (!hasAppMount(\"api\")) {\n const declaration = findConventionalRouter(ts, program, projectRoot, FALLBACK_API_ROUTER);\n if (declaration) {\n result.api.push({ declaration, prefix: \"\" });\n result.dependencies.push(declaration.getSourceFile().fileName);\n }\n }\n if (!hasAppMount(\"view\")) {\n const declaration = findConventionalRouter(ts, program, projectRoot, FALLBACK_VIEW_ROUTER);\n if (declaration) {\n result.view.push({ declaration, prefix: \"\" });\n result.dependencies.push(declaration.getSourceFile().fileName);\n }\n }\n\n if (!hasAppMount(\"api\") && !hasAppMount(\"view\")) {\n result.diagnostics.push(\n `no application routers found: no ${CONFIG_HELPER}() call and nothing at ${projectRoot}/${FALLBACK_API_ROUTER}`,\n );\n }\n return result;\n}\n\n/** Whether a file belongs to the application rather than to a package it installs. */\nfunction isApplicationFile(fileName: string, projectRoot: string): boolean {\n return fileName.startsWith(`${projectRoot}/`) && !fileName.includes(\"/node_modules/\");\n}\n\n/**\n * Every declaration of an interface by this name, merged ones included.\n *\n * The interfaces are asked for through the `gemi/client` module symbol rather\n * than found by walking files, because since 0.56 the augmentation ships inside\n * the package: in an installed app the only file declaring `RPC` is\n * `node_modules/gemi/dist/gemi.d.ts`, which a file walk that skips\n * `node_modules` — as it must, to stay cheap — will never see. The module symbol\n * has no such blind spot. Reaching it costs one scan of the top-level statements\n * of the app's own files, looking for an `import … from \"gemi/client\"` or a\n * `declare module \"gemi/client\"`; from there the checker supplies the whole\n * merge group, package and application declarations alike.\n */\nfunction findInterfaceDeclarations(\n ts: TS,\n checker: ts.TypeChecker,\n program: ts.Program,\n name: string,\n): ts.InterfaceDeclaration[] {\n const fromModule = findClientModuleSymbol(ts, checker, program);\n if (fromModule) {\n const exported = checker.getExportsOfModule(fromModule).find((symbol) => symbol.name === name);\n const resolved =\n exported && exported.flags & ts.SymbolFlags.Alias\n ? checker.getAliasedSymbol(exported)\n : exported;\n const declarations = resolved?.declarations?.filter((declaration) =>\n ts.isInterfaceDeclaration(declaration),\n );\n if (declarations && declarations.length > 0) return declarations;\n }\n\n // No file names `gemi/client` — a project that has not imported it yet. Fall\n // back to finding one declaration by hand and letting the checker merge.\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.fileName.includes(\"/node_modules/\")) continue;\n\n const local = findInterfaceIn(ts, sourceFile, name);\n if (!local) continue;\n\n const symbol = checker.getSymbolAtLocation(local.name);\n const declarations = symbol?.declarations?.filter((declaration) =>\n ts.isInterfaceDeclaration(declaration),\n );\n return declarations && declarations.length > 0 ? declarations : [local];\n }\n return [];\n}\n\n/** The symbol for the `gemi/client` module, reached through any reference to it. */\nfunction findClientModuleSymbol(\n ts: TS,\n checker: ts.TypeChecker,\n program: ts.Program,\n): ts.Symbol | undefined {\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.fileName.includes(\"/node_modules/\")) continue;\n\n for (const statement of sourceFile.statements) {\n const reference = clientModuleReference(ts, statement);\n if (!reference) continue;\n const symbol = checker.getSymbolAtLocation(reference);\n if (symbol) return symbol;\n }\n }\n return undefined;\n}\n\n/** The node naming `gemi/client` in a statement, if the statement names it. */\nfunction clientModuleReference(ts: TS, statement: ts.Statement): ts.Node | undefined {\n if (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) {\n const specifier = statement.moduleSpecifier;\n if (specifier && ts.isStringLiteralLike(specifier) && specifier.text === CLIENT_MODULE) {\n return specifier;\n }\n return undefined;\n }\n if (\n ts.isModuleDeclaration(statement) &&\n ts.isStringLiteralLike(statement.name) &&\n statement.name.text === CLIENT_MODULE\n ) {\n return statement.name;\n }\n return undefined;\n}\n\nfunction findInterfaceIn(\n ts: TS,\n sourceFile: ts.SourceFile,\n name: string,\n): ts.InterfaceDeclaration | undefined {\n let found: ts.InterfaceDeclaration | undefined;\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (ts.isInterfaceDeclaration(node) && node.name.text === name) {\n found = node;\n return;\n }\n // Interfaces live at the top level or inside `declare module \"…\" { … }`;\n // nothing deeper needs visiting.\n if (ts.isSourceFile(node) || ts.isModuleDeclaration(node) || ts.isModuleBlock(node)) {\n ts.forEachChild(node, visit);\n }\n };\n visit(sourceFile);\n return found;\n}\n\n/**\n * Reads `extends CreateRPC<Router, \"/prefix\">` off an interface declaration.\n *\n * The helper's name is deliberately not read. `CreateRPC` is only the direct\n * spelling; the package's own augmentation goes through an alias —\n * `extends AppRPC<Api>`, where `AppRPC` guards an unresolved `@/app/*` before it\n * can instantiate `CreateRPC` and blow the instantiation depth. Matching the\n * name `CreateRPC` rejected that, which since 0.56 is every application's own\n * routers. So the type arguments are what is read: whichever resolves to a class\n * is the router, and a string literal beside it is its prefix. Any wrapper —\n * the package's, or one an application writes — is understood the same way.\n */\nfunction readMounts(\n ts: TS,\n checker: ts.TypeChecker,\n declaration: ts.InterfaceDeclaration,\n): RouterMount[] {\n const mounts: RouterMount[] = [];\n for (const clause of declaration.heritageClauses ?? []) {\n for (const type of clause.types) {\n let router: ts.ClassLikeDeclaration | undefined;\n let prefix = \"\";\n for (const argument of type.typeArguments ?? []) {\n if (!router) {\n const resolved = resolveClassFromTypeNode(ts, checker, argument);\n if (resolved) {\n router = resolved;\n continue;\n }\n }\n if (!prefix) prefix = readPrefix(ts, checker, argument);\n }\n if (router) mounts.push({ declaration: router, prefix });\n }\n }\n return mounts;\n}\n\nfunction resolveClassFromTypeNode(\n ts: TS,\n checker: ts.TypeChecker,\n node: ts.TypeNode,\n): ts.ClassLikeDeclaration | undefined {\n if (!ts.isTypeReferenceNode(node)) return undefined;\n const name = ts.isQualifiedName(node.typeName) ? node.typeName.right : node.typeName;\n return resolveClassDeclaration(ts, checker, name as unknown as ts.Expression);\n}\n\nfunction readPrefix(ts: TS, checker: ts.TypeChecker, node: ts.TypeNode | undefined): string {\n if (!node) return \"\";\n if (ts.isLiteralTypeNode(node) && ts.isStringLiteral(node.literal)) return node.literal.text;\n const type = checker.getTypeFromTypeNode(node);\n return type.isStringLiteral() ? type.value : \"\";\n}\n\nfunction findRouteConfigCall(ts: TS, program: ts.Program): ts.CallExpression | undefined {\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n if (sourceFile.fileName.includes(\"/node_modules/\")) continue;\n\n // Cheap gate: only files that import the helper get walked. Import\n // statements are always at the top, so this scans a handful of nodes per\n // file rather than every node in the project.\n const localName = importedNameOf(ts, sourceFile);\n if (!localName) continue;\n\n let found: ts.CallExpression | undefined;\n const visit = (node: ts.Node): void => {\n if (found) return;\n if (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === localName\n ) {\n found = node;\n return;\n }\n ts.forEachChild(node, visit);\n };\n ts.forEachChild(sourceFile, visit);\n if (found) return found;\n }\n return undefined;\n}\n\n/** The local name `defineRouteConfig` is imported under, if this file imports it. */\nfunction importedNameOf(ts: TS, sourceFile: ts.SourceFile): string | undefined {\n for (const statement of sourceFile.statements) {\n if (!ts.isImportDeclaration(statement)) continue;\n const specifier = statement.moduleSpecifier;\n if (!ts.isStringLiteralLike(specifier) || specifier.text !== CONFIG_MODULE) continue;\n const bindings = statement.importClause?.namedBindings;\n if (!bindings || !ts.isNamedImports(bindings)) continue;\n for (const element of bindings.elements) {\n const imported = element.propertyName?.text ?? element.name.text;\n if (imported === CONFIG_HELPER) return element.name.text;\n }\n }\n return undefined;\n}\n\nfunction readRootRouter(\n ts: TS,\n checker: ts.TypeChecker,\n config: ts.ObjectLiteralExpression,\n section: \"api\" | \"view\",\n): ts.ClassLikeDeclaration | undefined {\n const sectionValue = getPropertyValue(ts, config, section);\n if (!sectionValue || !ts.isObjectLiteralExpression(sectionValue)) return undefined;\n const rootRouter = getPropertyValue(ts, sectionValue, \"rootRouter\");\n return rootRouter ? resolveClassDeclaration(ts, checker, rootRouter) : undefined;\n}\n\nfunction getPropertyValue(\n ts: TS,\n object: ts.ObjectLiteralExpression,\n name: string,\n): ts.Expression | undefined {\n for (const property of object.properties) {\n if (ts.isPropertyAssignment(property)) {\n const key = property.name;\n const text = ts.isIdentifier(key) || ts.isStringLiteralLike(key) ? key.text : undefined;\n if (text === name) return unwrapExpression(ts, property.initializer);\n } else if (ts.isShorthandPropertyAssignment(property) && property.name.text === name) {\n return property.name;\n }\n }\n return undefined;\n}\n\nfunction findConventionalRouter(\n ts: TS,\n program: ts.Program,\n projectRoot: string,\n relativePath: string,\n): ts.ClassLikeDeclaration | undefined {\n const checker = program.getTypeChecker();\n for (const extension of [\".ts\", \".tsx\"]) {\n const sourceFile = program.getSourceFile(`${projectRoot}/${relativePath}${extension}`);\n if (!sourceFile) continue;\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) continue;\n for (const exported of checker.getExportsOfModule(moduleSymbol)) {\n if (exported.name !== \"default\") continue;\n const resolved =\n exported.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported;\n const declaration = resolved.valueDeclaration ?? resolved.declarations?.[0];\n if (declaration && ts.isClassLike(declaration)) return declaration;\n }\n }\n return undefined;\n}\n",
9
+ "/**\n * Value-level mirrors of the template-literal types that build RPC keys.\n *\n * The plugin has to arrive at exactly the same strings `CreateRPC` and\n * `CreateViewRPC` produce — a route the type system spells `/org/:orgId/products`\n * and the plugin spells `/org/:orgId/products/` is a route the plugin can never\n * be asked about, because the string the user typed came from the types.\n *\n * So each function here is a transcription of one conditional type in\n * `http/ApiRouter.ts` / `http/ViewRouter.ts` / `client/types.ts`, quirks\n * included: `removeGroupPrefix` strips one group and not all of them,\n * `parsePrefixAndKey` collapses one double slash and not all of them. Where the\n * behaviour looks wrong, it is wrong in the same direction as the types, which\n * is the only property that matters. `routePath.test.ts` pins the pairs, and\n * `http/ApiRouter.test-d.ts` pins the type side.\n */\n\n/** Mirrors `RemoveDoubleSlash` in `client/types.ts` — recursive, unlike its callers. */\nexport function removeDoubleSlash(input: string): string {\n const at = input.indexOf(\"//\");\n if (at === -1) return input;\n return removeDoubleSlash(`${input.slice(0, at)}/${input.slice(at + 2)}`);\n}\n\n/**\n * Mirrors `RemoveGroupPrefix` in `client/types.ts`.\n *\n * Strips the *first* `(group)` — a route folder that organises the tree without\n * appearing in the URL — and then collapses the double slash that removal\n * leaves behind. A second group in the same segment survives, exactly as it\n * does in the type.\n */\nexport function removeGroupPrefix(input: string): string {\n const open = input.indexOf(\"(\");\n if (open === -1) return input;\n const close = input.indexOf(\")\", open + 1);\n if (close === -1) return input;\n return removeDoubleSlash(`${input.slice(0, open)}${input.slice(close + 1)}`);\n}\n\n/**\n * Mirrors `ParsePrefixAndKey`, which both routers declare identically: join a\n * parent prefix to a child key and normalise the seam.\n *\n * The `${infer T1}//${infer T2}` and `${infer T1}/${infer T2}/` patterns infer\n * the leftmost-shortest `T1`, so both branches split at the *first* slash that\n * satisfies the pattern — not the last, and not every one.\n */\nexport function parsePrefixAndKey(prefix: string, key: string): string {\n const joined = `${prefix}${key}`;\n if (joined === \"//\") return \"/\";\n\n const doubleSlash = joined.indexOf(\"//\");\n if (doubleSlash !== -1) {\n return `${removeGroupPrefix(joined.slice(0, doubleSlash))}/${removeGroupPrefix(\n joined.slice(doubleSlash + 2),\n )}`;\n }\n\n if (joined.endsWith(\"/\")) {\n // `${T1}/${T2}/` needs two distinct slashes, so a bare \"health/\" falls\n // through to the default branch keeping its trailing slash — as it does in\n // the type.\n const first = joined.indexOf(\"/\");\n if (first !== -1 && first < joined.length - 1) {\n return `${removeGroupPrefix(joined.slice(0, first))}/${removeGroupPrefix(\n joined.slice(first + 1, -1),\n )}`;\n }\n }\n\n return removeGroupPrefix(joined);\n}\n\n/**\n * Mirrors `RemoveTrailingId` in `http/ApiRouter.ts` — drops the last `:param`\n * segment, which is how a resource's collection routes (`list`, `store`) get\n * their path from the same key the member routes (`show`, `update`, `delete`)\n * use.\n *\n * `\"/:orgId/products/:productId\"` → `\"/:orgId/products\"`. A key that is nothing\n * but an id segment empties out, which is not a reachable route — reproducing\n * that rather than \"correcting\" it to `\"/\"` keeps the plugin from claiming a\n * route the types never emitted.\n *\n * The type's `\"X\"` branch is transcribed for fidelity even though no input\n * reaches it: `Head` is everything before the first `/:`, so it cannot itself\n * begin with `/:`.\n */\nexport function removeTrailingId(input: string): string {\n const at = input.indexOf(\"/:\");\n if (at === -1) return input;\n const head = input.slice(0, at);\n const tail = input.slice(at + 2);\n if (tail.includes(\"/:\")) return `${head}/:${removeTrailingId(tail)}`;\n if (head.startsWith(\"/:\")) return \"X\";\n return head;\n}\n\n/**\n * Mirrors the `RouteHandlers` branch of `RouteParser`, which — unlike every\n * other branch — concatenates raw instead of going through `ParsePrefixAndKey`.\n * A verb-map value therefore keeps any group parentheses in its prefix.\n */\nexport function joinHandlerMapKey(prefix: string, key: string): string {\n return `${prefix}${key === \"/\" ? \"\" : key}`;\n}\n",
10
+ "import type ts from \"typescript\";\n\nimport {\n displayNameOfClass,\n getPropertyKeyText,\n getRoutesObjectLiteral,\n getStringValue,\n getThisCall,\n resolveClassDeclaration,\n spanOf,\n targetFromDeclaration,\n unwrapBuilderChain,\n unwrapExpression,\n type TS,\n} from \"./ast\";\nimport { findRootRouters } from \"./entryPoints\";\nimport { joinHandlerMapKey, parsePrefixAndKey, removeTrailingId } from \"./routePath\";\nimport type { ApiRouteEntry, HttpVerb, RouteTable, RouteTarget, ViewRouteEntry } from \"./types\";\n\nexport interface BuildOptions {\n /** Directory the app's `app/` folder sits in. */\n projectRoot: string;\n /** Where `this.view(\"auth/SignIn\")` looks for `auth/SignIn.tsx`. */\n viewsDir: string;\n fileExists: (fileName: string) => boolean;\n}\n\nconst VERBS: Record<string, HttpVerb> = {\n get: \"GET\",\n post: \"POST\",\n put: \"PUT\",\n patch: \"PATCH\",\n delete: \"DELETE\",\n};\n\n/**\n * The five routes `this.resource(C)` expands to, and where each lands.\n *\n * `list` and `store` sit on the collection — the route key with its trailing\n * `:id` segment removed — and the other three on the member. That split is\n * `ResourceRoutes`' `first`/`second` in `http/ApiRouter.ts`.\n */\nconst RESOURCE_ROUTES: ReadonlyArray<{\n method: string;\n verb: HttpVerb;\n scope: \"collection\" | \"member\";\n}> = [\n { method: \"list\", verb: \"GET\", scope: \"collection\" },\n { method: \"store\", verb: \"POST\", scope: \"collection\" },\n { method: \"show\", verb: \"GET\", scope: \"member\" },\n { method: \"update\", verb: \"PUT\", scope: \"member\" },\n { method: \"delete\", verb: \"DELETE\", scope: \"member\" },\n];\n\nconst VIEW_EXTENSIONS = [\".tsx\", \".jsx\", \".ts\", \".js\"];\n\n/**\n * Walks an app's router tree and records, for every route the client can name,\n * where its handler is written.\n *\n * The walk mirrors `RouteParser`/`RoutesParser` rather than the runtime: those\n * conditional types are what turn a `routes` object into the string literals a\n * `useQuery` call site is constrained to, so matching them is what makes a\n * lookup by that literal possible. Everything the types reach, this reaches;\n * everything they drop (`file`, `stream`, `proxy`) is still indexed, marked\n * `inRpc: false`, because a hardcoded URL elsewhere in the app may still name it.\n */\nexport function buildRouteTable(ts: TS, program: ts.Program, options: BuildOptions): RouteTable {\n return new RouteTableBuilder(ts, program, options).build();\n}\n\nclass RouteTableBuilder {\n private readonly checker: ts.TypeChecker;\n private readonly api = new Map<string, ApiRouteEntry[]>();\n private readonly views = new Map<string, ViewRouteEntry[]>();\n private readonly dependencies = new Set<string>();\n private readonly diagnostics: string[] = [];\n\n constructor(\n private readonly ts: TS,\n private readonly program: ts.Program,\n private readonly options: BuildOptions,\n ) {\n this.checker = program.getTypeChecker();\n }\n\n build(): RouteTable {\n const roots = findRootRouters(this.ts, this.program, this.options.projectRoot);\n for (const dependency of roots.dependencies) this.dependencies.add(dependency);\n this.diagnostics.push(...roots.diagnostics);\n\n for (const mount of roots.api) this.walkApiRouter(mount.declaration, mount.prefix, []);\n for (const mount of roots.view) this.walkViewRouter(mount.declaration, mount.prefix, []);\n\n return {\n api: this.api,\n views: this.views,\n dependencies: [...this.dependencies],\n diagnostics: this.diagnostics,\n };\n }\n\n // -- API routers ---------------------------------------------------------\n\n private walkApiRouter(\n classDeclaration: ts.ClassLikeDeclaration,\n prefix: string,\n stack: ts.ClassLikeDeclaration[],\n ): void {\n const ts = this.ts;\n const routes = getRoutesObjectLiteral(ts, classDeclaration);\n if (!routes) return;\n this.dependencies.add(classDeclaration.getSourceFile().fileName);\n\n for (const property of routes.properties) {\n if (!ts.isPropertyAssignment(property)) {\n this.noteUnreadableEntry(property, prefix, classDeclaration);\n continue;\n }\n const key = getPropertyKeyText(ts, this.checker, property.name);\n if (key === undefined) continue;\n const value = unwrapExpression(ts, property.initializer);\n\n // A bare class reference mounts another router under this key.\n const nested = resolveClassDeclaration(ts, this.checker, value);\n if (nested && getRoutesObjectLiteral(ts, nested)) {\n // Guard the current chain, not every router seen: mounting the same\n // router at two prefixes is legitimate, mounting it inside itself is not.\n if (stack.includes(nested)) {\n this.diagnostics.push(\n `router cycle at ${parsePrefixAndKey(prefix, key)}; stopped descending`,\n );\n continue;\n }\n this.walkApiRouter(nested, parsePrefixAndKey(prefix, key), [...stack, nested]);\n continue;\n }\n\n // A verb map — `{ get: this.get(...), post: this.post(...) }` — puts\n // several verbs on one path. `RouteHandlersParser` concatenates its\n // prefix raw, so this key does not go through `parsePrefixAndKey`.\n if (ts.isObjectLiteralExpression(value)) {\n const path = joinHandlerMapKey(prefix, key);\n for (const inner of value.properties) {\n if (!ts.isPropertyAssignment(inner)) continue;\n this.addApiRoute(path, unwrapExpression(ts, inner.initializer), inner, classDeclaration);\n }\n continue;\n }\n\n this.addApiRoute(parsePrefixAndKey(prefix, key), value, property, classDeclaration);\n }\n }\n\n private addApiRoute(\n path: string,\n value: ts.Expression,\n entryNode: ts.PropertyAssignment,\n router: ts.ClassLikeDeclaration,\n ): void {\n const call = getThisCall(this.ts, unwrapBuilderChain(this.ts, value));\n if (!call) return;\n const fallback = this.routeEntryTarget(entryNode, router);\n\n if (call.method === \"resource\") {\n const controller = call.args[0];\n const collection = removeTrailingId(path);\n for (const { method, verb, scope } of RESOURCE_ROUTES) {\n const target = controller ? this.controllerMethodTarget(controller, method) : undefined;\n this.pushApi({\n path: scope === \"collection\" ? collection : path,\n verb,\n inRpc: true,\n targets: [target ?? fallback],\n });\n }\n return;\n }\n\n const verb = VERBS[call.method];\n if (verb) {\n this.pushApi({ path, verb, inRpc: true, targets: this.handlerTargets(call.args, fallback) });\n return;\n }\n\n // `file` and `stream` are GET routes that `CreateRPC` drops; `proxy`\n // forwards elsewhere and has no local handler to jump to.\n if (call.method === \"file\" || call.method === \"stream\") {\n this.pushApi({\n path,\n verb: \"GET\",\n inRpc: false,\n targets: this.handlerTargets(call.args, fallback),\n });\n return;\n }\n if (call.method === \"proxy\") {\n this.pushApi({ path, verb: \"GET\", inRpc: false, targets: [fallback] });\n }\n }\n\n private pushApi(entry: ApiRouteEntry): void {\n const existing = this.api.get(entry.path);\n if (existing) existing.push(entry);\n else this.api.set(entry.path, [entry]);\n }\n\n // -- View routers --------------------------------------------------------\n\n private walkViewRouter(\n classDeclaration: ts.ClassLikeDeclaration,\n prefix: string,\n stack: ts.ClassLikeDeclaration[],\n ): void {\n const routes = getRoutesObjectLiteral(this.ts, classDeclaration);\n if (!routes) return;\n this.dependencies.add(classDeclaration.getSourceFile().fileName);\n this.walkViewRoutes(routes, prefix, stack, classDeclaration);\n }\n\n private walkViewRoutes(\n routes: ts.ObjectLiteralExpression,\n prefix: string,\n stack: ts.ClassLikeDeclaration[],\n router: ts.ClassLikeDeclaration,\n ): void {\n const ts = this.ts;\n for (const property of routes.properties) {\n if (!ts.isPropertyAssignment(property)) {\n this.noteUnreadableEntry(property, prefix, router);\n continue;\n }\n const key = getPropertyKeyText(ts, this.checker, property.name);\n if (key === undefined) continue;\n const value = unwrapExpression(ts, property.initializer);\n const path = parsePrefixAndKey(prefix, key);\n\n const nested = resolveClassDeclaration(ts, this.checker, value);\n if (nested && getRoutesObjectLiteral(ts, nested)) {\n if (stack.includes(nested)) {\n this.diagnostics.push(`view router cycle at ${path}; stopped descending`);\n continue;\n }\n this.walkViewRouter(nested, path, [...stack, nested]);\n continue;\n }\n\n const call = getThisCall(ts, unwrapBuilderChain(ts, value));\n if (!call) continue;\n const fallback = this.routeEntryTarget(property, router);\n\n switch (call.method) {\n case \"view\":\n this.pushView({\n path,\n kind: \"view\",\n inRpc: true,\n targets: this.viewTargets(call.args[0], call.args[1], fallback),\n });\n break;\n\n case \"redirect\":\n this.pushView({\n path,\n kind: \"view\",\n inRpc: true,\n targets: this.viewTargets(undefined, call.args[0], fallback),\n });\n break;\n\n case \"file\":\n // `RoutesParser` maps `FileRoute` to `never`, so no typed call site\n // names this path — indexed for hardcoded URLs only.\n this.pushView({\n path,\n kind: \"view\",\n inRpc: false,\n targets: this.viewTargets(undefined, call.args[0], fallback),\n });\n break;\n\n case \"layout\": {\n // `layout(viewPath, handler, routes)` and `layout(viewPath, routes)`\n // are both legal; the children are whichever argument is an object.\n const second = call.args[1] ? unwrapExpression(ts, call.args[1]) : undefined;\n const third = call.args[2] ? unwrapExpression(ts, call.args[2]) : undefined;\n const children =\n third && ts.isObjectLiteralExpression(third)\n ? third\n : second && ts.isObjectLiteralExpression(second)\n ? second\n : undefined;\n const handler = children === second ? undefined : second;\n\n this.pushView({\n path,\n kind: \"layout\",\n inRpc: true,\n targets: this.viewTargets(call.args[0], handler, fallback),\n });\n if (children) this.walkViewRoutes(children, path, stack, router);\n break;\n }\n }\n }\n }\n\n private pushView(entry: ViewRouteEntry): void {\n const existing = this.views.get(entry.path);\n if (existing) existing.push(entry);\n else this.views.set(entry.path, [entry]);\n }\n\n /**\n * A view route has up to two places worth going: the component it renders and\n * the controller method that feeds it. Both are offered, component first —\n * editors show a picker when a definition resolves to more than one place.\n */\n private viewTargets(\n viewPath: ts.Expression | undefined,\n handler: ts.Expression | undefined,\n fallback: RouteTarget,\n ): RouteTarget[] {\n const targets: RouteTarget[] = [];\n const component = viewPath ? this.viewComponentTarget(viewPath) : undefined;\n if (component) targets.push(component);\n if (handler) targets.push(...this.handlerTargets([handler], fallback, { silent: true }));\n return targets.length > 0 ? targets : [fallback];\n }\n\n private viewComponentTarget(viewPath: ts.Expression): RouteTarget | undefined {\n const ts = this.ts;\n const relative = getStringValue(ts, this.checker, viewPath);\n if (!relative) return undefined;\n\n for (const extension of VIEW_EXTENSIONS) {\n const fileName = `${this.options.viewsDir}/${relative}${extension}`;\n const sourceFile = this.program.getSourceFile(fileName);\n if (sourceFile) {\n this.dependencies.add(fileName);\n const exported = this.defaultExportDeclaration(sourceFile);\n if (exported) {\n return targetFromDeclaration(ts, exported, relative, \"view\", \"view-component\");\n }\n return {\n fileName,\n span: { start: 0, length: 0 },\n name: relative,\n containerName: \"view\",\n kind: \"view-component\",\n };\n }\n // A view nothing imports is absent from the program even though it is on\n // disk — the whole point of the views directory is that the framework\n // loads it, not the app. Jumping to the file still works.\n if (this.options.fileExists(fileName)) {\n return {\n fileName,\n span: { start: 0, length: 0 },\n name: relative,\n containerName: \"view\",\n kind: \"view-component\",\n };\n }\n }\n return undefined;\n }\n\n private defaultExportDeclaration(sourceFile: ts.SourceFile): ts.Declaration | undefined {\n const moduleSymbol = this.checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return undefined;\n for (const exported of this.checker.getExportsOfModule(moduleSymbol)) {\n if (exported.name !== \"default\") continue;\n const resolved =\n exported.flags & this.ts.SymbolFlags.Alias\n ? this.checker.getAliasedSymbol(exported)\n : exported;\n const declaration = resolved.valueDeclaration ?? resolved.declarations?.[0];\n if (declaration) return declaration;\n }\n return undefined;\n }\n\n // -- Handlers ------------------------------------------------------------\n\n /**\n * Where a route's arguments say its work happens.\n *\n * `(Controller, \"method\")` and `[Controller, \"method\"]` — the API and view\n * spellings of the same thing — resolve to the method. An inline callback\n * resolves to itself. Anything else falls back to the `routes` entry, so a\n * shape this does not understand degrades to a jump into the router rather\n * than to no jump at all.\n */\n private handlerTargets(\n args: readonly ts.Expression[],\n fallback: RouteTarget,\n options: { silent?: boolean } = {},\n ): RouteTarget[] {\n const ts = this.ts;\n const first = args[0] ? unwrapExpression(ts, args[0]) : undefined;\n if (!first) return options.silent ? [] : [fallback];\n\n if (ts.isArrayLiteralExpression(first)) {\n const [controller, method] = first.elements;\n const name = getStringValue(ts, this.checker, method);\n const target = controller && name ? this.controllerMethodTarget(controller, name) : undefined;\n return [target ?? fallback];\n }\n\n if (ts.isFunctionExpression(first) || ts.isArrowFunction(first)) {\n return [\n {\n fileName: first.getSourceFile().fileName,\n span: spanOf(first),\n contextSpan: spanOf(first),\n name: \"handler\",\n containerName: \"\",\n kind: \"inline-handler\",\n },\n ];\n }\n\n const methodName = getStringValue(ts, this.checker, args[1]);\n if (methodName) {\n const target = this.controllerMethodTarget(first, methodName);\n if (target) return [target];\n }\n\n return options.silent ? [] : [fallback];\n }\n\n /**\n * The declaration of `methodName` on the class an expression names.\n *\n * Resolved through the instance type rather than the class body, so a method\n * inherited from a base controller — or reached through an import alias, or a\n * re-export — is found the same way the compiler finds it.\n */\n private controllerMethodTarget(\n controller: ts.Expression,\n methodName: string,\n ): RouteTarget | undefined {\n const type = this.checker.getTypeAtLocation(controller);\n const instance = type.getConstructSignatures()[0]?.getReturnType();\n const property = instance?.getProperty(methodName);\n const declaration = property?.declarations?.[0];\n if (!declaration) return undefined;\n\n this.dependencies.add(declaration.getSourceFile().fileName);\n return targetFromDeclaration(\n this.ts,\n declaration,\n methodName,\n displayNameOfClass(this.ts, this.checker, controller),\n \"controller-method\",\n );\n }\n\n /**\n * A `routes` entry the walk cannot read, recorded rather than dropped in silence.\n *\n * `RouteParser` works from the *declared type* of `routes`, so a spread —\n * `...sharedRoutes` — contributes its paths to `keyof RPC` and to autocomplete\n * while the walk, which reads syntax, has no row for any of them. The result is\n * a path that typechecks and offers no jump, and (see `intersect` in\n * `lookup.ts`) a hole that used to cost verb narrowing project-wide. The\n * tsserver log is the only place that can say which route went missing.\n */\n private noteUnreadableEntry(\n property: ts.ObjectLiteralElementLike,\n prefix: string,\n router: ts.ClassLikeDeclaration,\n ): void {\n const ts = this.ts;\n const what = ts.isSpreadAssignment(property)\n ? `the spread \\`...${property.expression.getText()}\\``\n : ts.isShorthandPropertyAssignment(property)\n ? `the shorthand entry \\`${property.name.text}\\``\n : \"an entry\";\n this.diagnostics.push(\n `${router.name?.text ?? \"router\"} mounted at ${prefix || \"/\"}: ${what} in \\`routes\\` ` +\n `cannot be read statically — the routes it holds are typed but not jumpable`,\n );\n }\n\n private routeEntryTarget(\n property: ts.PropertyAssignment,\n router: ts.ClassLikeDeclaration,\n ): RouteTarget {\n return {\n fileName: property.getSourceFile().fileName,\n span: spanOf(property.name),\n contextSpan: spanOf(property),\n name: getPropertyKeyText(this.ts, this.checker, property.name) ?? \"route\",\n containerName: router.name?.text ?? \"router\",\n kind: \"route-entry\",\n };\n }\n}\n",
11
+ "import type ts from \"typescript\";\n\nimport type { TS } from \"./ast\";\nimport { findRouteQuery } from \"./callSite\";\nimport { describeCandidate, describeTarget, lookupRoute, type RouteMatch } from \"./lookup\";\nimport { buildRouteTable } from \"./routeTable\";\nimport type { RouteTable, RouteTarget, Span, TargetKind } from \"./types\";\n\nexport interface PluginHost {\n ts: TS;\n languageService: ts.LanguageService;\n /** Directory holding the app's `app/` folder. */\n projectRoot: string;\n /** Where `this.view(\"auth/SignIn\")` resolves `auth/SignIn.tsx`. */\n viewsDir: string;\n fileExists(fileName: string): boolean;\n /** Opaque token that changes when a file's contents do. */\n getScriptVersion(fileName: string): string;\n log(message: string): void;\n}\n\n/**\n * Wraps a language service so that a route path behaves like a reference to the\n * code that serves it.\n *\n * `useQuery(\"/reports\")` names its handler as precisely as a function call names\n * a function — the string is checked against the router at compile time — but\n * TypeScript has no way to know that, because the connection is made by\n * conditional types rather than by a symbol. So go-to-definition stops at the\n * literal, and reading one call site means opening the router, finding the\n * entry, and following it to the controller by hand.\n *\n * Everything else is delegated untouched. The two methods below answer only when\n * the position really is a route path that really is in the table; in every\n * other case the wrapped service replies, so nothing TypeScript already does\n * well gets worse.\n */\nexport function decorateLanguageService(host: PluginHost): ts.LanguageService {\n const { ts, languageService } = host;\n const routes = createRouteTableCache(host);\n\n // Forward every method by hand rather than subclassing or spreading: the\n // interface grows with each TypeScript release, and a proxy built from the\n // instance's own keys picks up whatever this copy actually has.\n const forwarded: Record<string, unknown> = Object.create(null);\n const source = languageService as unknown as Record<string, unknown>;\n for (const key of Object.keys(source)) {\n const member = source[key];\n if (typeof member !== \"function\") continue;\n forwarded[key] = (...args: unknown[]) =>\n (member as (...a: unknown[]) => unknown).apply(languageService, args);\n }\n const proxy = forwarded as unknown as ts.LanguageService;\n\n proxy.getDefinitionAndBoundSpan = (fileName, position) => {\n const matched = match(fileName, position);\n if (!matched) return languageService.getDefinitionAndBoundSpan(fileName, position);\n\n const definitions = toDefinitions(ts, matched.matches);\n if (definitions.length === 0) {\n return languageService.getDefinitionAndBoundSpan(fileName, position);\n }\n return { textSpan: matched.textSpan, definitions };\n };\n\n // `getDefinitionAtPosition` is the older entry point; some editors still call\n // it, and Neovim's built-in LSP client reaches it through tsserver's\n // `definition` command. Answering both keeps behaviour identical across them.\n proxy.getDefinitionAtPosition = (fileName, position) => {\n const matched = match(fileName, position);\n if (!matched) return languageService.getDefinitionAtPosition(fileName, position);\n const definitions = toDefinitions(ts, matched.matches);\n return definitions.length > 0\n ? definitions\n : languageService.getDefinitionAtPosition(fileName, position);\n };\n\n proxy.getQuickInfoAtPosition = (fileName, position) => {\n const original = languageService.getQuickInfoAtPosition(fileName, position);\n const matched = match(fileName, position);\n if (!matched) return original;\n\n const { heading, documentation } = describeMatches(host, matched.matches);\n // TypeScript has nothing to say about a string literal in argument\n // position, so there is usually no original to preserve — but when there\n // is, it is the parameter's type, which is worth keeping above the route.\n if (original) {\n return {\n ...original,\n documentation: [...(original.documentation ?? []), ...documentation],\n };\n }\n return {\n kind: ts.ScriptElementKind.string,\n kindModifiers: \"\",\n textSpan: matched.textSpan,\n displayParts: heading,\n documentation,\n };\n };\n\n return proxy;\n\n /**\n * Nothing here is allowed to throw. A language service plugin that raises\n * takes the editor's IntelliSense down with it, and a broken jump is a far\n * better failure than a dead language server — so any surprise degrades to\n * \"not a route\" and the wrapped service answers instead.\n */\n function match(\n fileName: string,\n position: number,\n ): { matches: RouteMatch[]; textSpan: ts.TextSpan } | undefined {\n try {\n const program = languageService.getProgram();\n const sourceFile = program?.getSourceFile(fileName);\n if (!program || !sourceFile) return undefined;\n\n const query = findRouteQuery(ts, program.getTypeChecker(), sourceFile, position);\n if (!query) return undefined;\n\n const matches = lookupRoute(routes.get(program), query);\n if (matches.length === 0) return undefined;\n\n // The span the editor underlines: the path itself, not its quotes.\n const start = query.node.getStart(sourceFile) + 1;\n return { matches, textSpan: { start, length: query.node.text.length } };\n } catch (error) {\n host.log(`route lookup failed at ${fileName}:${position} — ${describeError(error)}`);\n return undefined;\n }\n }\n}\n\nexport function describeError(error: unknown): string {\n return error instanceof Error ? `${error.message}\\n${error.stack ?? \"\"}` : String(error);\n}\n\nfunction toDefinitions(ts: TS, matches: RouteMatch[]): ts.DefinitionInfo[] {\n const definitions: ts.DefinitionInfo[] = [];\n const seen = new Set<string>();\n for (const { candidate, targets } of matches) {\n for (const target of targets) {\n const key = `${target.fileName}:${target.span.start}`;\n if (seen.has(key)) continue;\n seen.add(key);\n definitions.push({\n fileName: target.fileName,\n textSpan: toTextSpan(target.span),\n contextSpan: target.contextSpan ? toTextSpan(target.contextSpan) : undefined,\n kind: scriptElementKind(ts, target.kind),\n name: target.name,\n containerName: target.containerName || describeCandidate(candidate),\n containerKind: ts.ScriptElementKind.unknown,\n });\n }\n }\n return definitions;\n}\n\nfunction describeMatches(\n host: PluginHost,\n matches: RouteMatch[],\n): { heading: ts.SymbolDisplayPart[]; documentation: ts.SymbolDisplayPart[] } {\n const lines: string[] = [];\n for (const { candidate, targets } of matches) {\n lines.push(describeCandidate(candidate));\n for (const target of targets) {\n lines.push(` → ${describeTarget(target)} · ${location(host, target)}`);\n }\n }\n return {\n heading: [\n {\n text: matches.map(({ candidate }) => describeCandidate(candidate)).join(\", \"),\n kind: \"text\",\n },\n ],\n documentation: [{ text: lines.join(\"\\n\"), kind: \"text\" }],\n };\n}\n\nfunction location(host: PluginHost, target: RouteTarget): string {\n const relative = target.fileName.startsWith(`${host.projectRoot}/`)\n ? target.fileName.slice(host.projectRoot.length + 1)\n : target.fileName;\n const sourceFile = host.languageService.getProgram()?.getSourceFile(target.fileName);\n if (!sourceFile) return relative;\n const { line } = sourceFile.getLineAndCharacterOfPosition(target.span.start);\n return `${relative}:${line + 1}`;\n}\n\nfunction toTextSpan(span: Span): ts.TextSpan {\n return { start: span.start, length: span.length };\n}\n\nfunction scriptElementKind(ts: TS, kind: TargetKind): ts.ScriptElementKind {\n switch (kind) {\n case \"controller-method\":\n return ts.ScriptElementKind.memberFunctionElement;\n case \"inline-handler\":\n return ts.ScriptElementKind.functionElement;\n case \"view-component\":\n return ts.ScriptElementKind.functionElement;\n case \"route-entry\":\n return ts.ScriptElementKind.memberVariableElement;\n }\n}\n\ninterface RouteTableCache {\n get(program: ts.Program): RouteTable;\n}\n\n/**\n * Keeps the route table across edits that cannot have changed it.\n *\n * A definition request arrives on a keystroke, and the program object is new\n * every time — so program identity alone would mean rebuilding the table on\n * every character typed anywhere in the project. The table records which files\n * it was derived from, and those are re-read only when one of their versions\n * moves. The file count is part of the key too, because a route can also appear\n * by a file being created, which no existing version reflects.\n */\nfunction createRouteTableCache(host: PluginHost): RouteTableCache {\n let cached: { table: RouteTable; versions: Map<string, string>; fileCount: number } | undefined;\n\n return {\n get(program) {\n const fileCount = program.getSourceFiles().length;\n if (cached && cached.fileCount === fileCount && isUnchanged(cached.versions)) {\n return cached.table;\n }\n\n const started = Date.now();\n const table = buildRouteTable(host.ts, program, {\n projectRoot: host.projectRoot,\n viewsDir: host.viewsDir,\n fileExists: host.fileExists,\n });\n const versions = new Map<string, string>();\n for (const fileName of table.dependencies) {\n versions.set(fileName, host.getScriptVersion(fileName));\n }\n cached = { table, versions, fileCount };\n\n host.log(\n `built route table in ${Date.now() - started}ms: ${table.api.size} api paths, ` +\n `${table.views.size} view paths, from ${table.dependencies.length} files`,\n );\n for (const diagnostic of table.diagnostics) host.log(diagnostic);\n return table;\n },\n };\n\n function isUnchanged(versions: Map<string, string>): boolean {\n for (const [fileName, version] of versions) {\n if (host.getScriptVersion(fileName) !== version) return false;\n }\n return true;\n }\n}\n",
12
+ "import type ts from \"typescript\";\n\nimport { decorateLanguageService, describeError } from \"./plugin\";\nimport type { GemiPluginConfig } from \"./types\";\n\n/**\n * gemi's TypeScript language service plugin.\n *\n * Enable it in the app's `tsconfig.json`:\n *\n * ```json\n * {\n * \"compilerOptions\": {\n * \"plugins\": [{ \"name\": \"gemi/ide/typescript-plugin\" }]\n * }\n * }\n * ```\n *\n * VS Code ships its own copy of TypeScript and ignores `plugins` unless told to\n * use the workspace's — run **TypeScript: Select TypeScript Version → Use\n * Workspace Version** once per project. Editors that drive tsserver over LSP\n * (Neovim, Emacs, Helix, JetBrains) read `tsconfig.json` directly and need\n * nothing extra.\n *\n * See `README.md` in this directory for what it does and how it decides.\n *\n * The module's only export is the initializer tsserver calls — `export =` admits\n * no others — so the config shape lives in `./types` as `GemiPluginConfig`.\n */\nfunction init(modules: { typescript: typeof ts }): ts.server.PluginModule {\n const tsModule = modules.typescript;\n\n return {\n create(info: ts.server.PluginCreateInfo): ts.LanguageService {\n const log = (message: string) => info.project.projectService.logger.info(`[gemi] ${message}`);\n\n try {\n const config = (info.config ?? {}) as GemiPluginConfig;\n if (config.enable === false) {\n log(\"disabled by config\");\n return info.languageService;\n }\n\n const projectRoot = trimTrailingSlash(\n config.projectRoot\n ? absolute(config.projectRoot, info.project.getCurrentDirectory())\n : info.project.getCurrentDirectory(),\n );\n const viewsDir = trimTrailingSlash(\n config.viewsDir ? absolute(config.viewsDir, projectRoot) : `${projectRoot}/app/views`,\n );\n\n log(`activated for ${projectRoot} (views: ${viewsDir})`);\n\n return decorateLanguageService({\n ts: tsModule,\n languageService: info.languageService,\n projectRoot,\n viewsDir,\n fileExists: (fileName) => info.serverHost.fileExists(fileName),\n getScriptVersion: (fileName) => info.project.getScriptVersion(fileName),\n log,\n });\n } catch (error) {\n // Returning the undecorated service is the difference between \"route\n // jumps do not work\" and \"the editor has no language features\".\n log(\n `failed to activate, falling back to the plain language service — ${describeError(error)}`,\n );\n return info.languageService;\n }\n },\n };\n}\n\nfunction absolute(path: string, base: string): string {\n const normalized = path.replace(/\\\\/g, \"/\");\n if (normalized.startsWith(\"/\") || /^[a-zA-Z]:\\//.test(normalized)) return normalized;\n return `${trimTrailingSlash(base)}/${normalized.replace(/^\\.\\//, \"\")}`;\n}\n\nfunction trimTrailingSlash(path: string): string {\n return path.length > 1 && path.endsWith(\"/\") ? path.slice(0, -1) : path;\n}\n\nexport = init;\n"
13
+ ],
14
+ "mappings": "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",
15
+ "debugId": "3EB5BA7A2D4DD49664756E2164756E21",
16
+ "names": []
17
+ }
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{sa as X}from"../chunk-rsdg619q.js";import{Pa as m}from"../chunk-enhkf60v.js";import{Qa as Y}from"../chunk-b50zmz3t.js";import{Ta as H,Ua as W,Va as Z,Wa as _,Xa as $,Ya as F,Za as T,ab as V,bb as y,eb as K,fb as L,mb as Q,pb as U,qb as B}from"../chunk-98a576s9.js";import{tb as k}from"../chunk-4t80js0n.js";import"../chunk-3y75q5a2.js";import"../chunk-64s1pzz1.js";import"../chunk-eqrd31ye.js";import{Ob as I,kc as b,lc as f}from"../chunk-tmnhkphv.js";import"../chunk-kry5vwam.js";import"../chunk-x14sk95v.js";import"../chunk-q0waxxz5.js";import{fe as w}from"../chunk-vkngcrzq.js";import{ve as D}from"../chunk-f9mfw82d.js";import"../chunk-01am9k5v.js";import"../chunk-4yafsffx.js";import"../chunk-pvdbrt4z.js";import"../chunk-ct274qts.js";import{_e as G,af as x}from"../chunk-v06qcyj5.js";import"../chunk-hs5v3eqj.js";import"../chunk-kgmr9qxx.js";var E=[T,y,X,B,W,_,V,$,L,U,K,F,Y,Q,Z];class M{config={};providers=[];services=[];serviceInstances=[];serviceTokens=new Set;servicesBooted=!1;models=[];app=new x;boot(){if(this.models.length>0)m(...this.models);else R();this.app.config.merge(this.config),x.setInstance(this.app),this.app.registerMany([...E,...this.providers]),this.registerServices()}registerServices(){let q=this.serviceTokens;this.serviceInstances=[],this.serviceTokens=new Set,this.servicesBooted=!1;let J=new Map;for(let z of this.services){let C=typeof z==="function"?new z:z,j=C.constructor;if(!j.token)throw Error(`Service [${j.name}] is listed in \`services\` but does not declare a \`static token\`.`);let N=J.get(j.token);if(N)throw Error(`Services [${N}] and [${j.name}] both declare the token "${j.token}". Tokens are the container's keys, so they must be unique.`);J.set(j.token,j.name);let O=j;if(!q.has(j.token)&&this.app.bound(O))throw Error(`Service [${j.name}] declares the token "${j.token}", which is already bound in the container by the framework or a provider. Binding it would replace that service everywhere, so pick a token nothing else owns.`);this.app.instance(O,C),this.serviceInstances.push(C),this.serviceTokens.add(j.token)}}async waitForBoot(){await this.app.boot(),await this.bootServices()}async bootServices(){if(this.servicesBooted)return;for(let q of this.serviceInstances)await q.boot();this.servicesBooted=!0}run(q){return G.run(this.app,q)}resolve(q){return this.app.make(q)}apiRoutes(){return this.app.make(f)}viewRoutes(){return this.app.make(b)}broadcast(){return this.app.make(I)}queue(){return this.app.make(k)}destroy(){if(this.app.resolved(H))this.app.make(H).stop();if(this.app.flush(),x.getInstance()===this.app)x.setInstance(void 0);G.disable()}}function R(){if(Bun.env.NODE_ENV==="production")return;let q=D();if(q.length===0)return;console.warn(`[gemi] ${q.length} model${q.length===1?" is":"s are"} registered, but Kernel.models is empty.
2
+ import{sa as Y}from"../chunk-xdv1b8mr.js";import{Pa as M}from"../chunk-m3xy5xyf.js";import{Qa as Z}from"../chunk-b35e128b.js";import{$a as $,Ta as J,Ua as X,Va as _,ab as E,cb as T,db as V,eb as y,fb as F,ib as K,jb as L,mb as Q,nb as U,ub as B,xb as D,yb as I}from"../chunk-87qab82w.js";import{Bb as R}from"../chunk-pmhd6zfc.js";import"../chunk-fjm4y8bn.js";import"../chunk-437085pe.js";import"../chunk-4yt5x8s2.js";import{Ec as m,Fc as k,_b as f}from"../chunk-hwa5sqw5.js";import"../chunk-86jebsm4.js";import"../chunk-y6a8r2bn.js";import"../chunk-7j6wbv12.js";import{Ce as h}from"../chunk-hxf1re93.js";import{Ue as b}from"../chunk-qb5mv6pj.js";import"../chunk-3g5bjvdf.js";import"../chunk-sy7jbdeb.js";import"../chunk-w62m5f0n.js";import"../chunk-cyaz97p5.js";import{xf as H,zf as x}from"../chunk-d125j8t0.js";import"../chunk-dgsgjg53.js";import"../chunk-jhkjz9jr.js";var G=[F,L,Y,$,I,X,E,K,V,U,T,D,Q,y,Z,B,_];class w{config={};providers=[];services=[];serviceInstances=[];serviceTokens=new Set;servicesBooted=!1;models=[];app=new x;boot(){if(this.models.length>0)M(...this.models);else A();this.app.config.merge(this.config),x.setInstance(this.app),this.app.registerMany([...G,...this.providers]),this.registerServices()}registerServices(){let q=this.serviceTokens;this.serviceInstances=[],this.serviceTokens=new Set,this.servicesBooted=!1;let N=new Map;for(let z of this.services){let C=typeof z==="function"?new z:z,j=C.constructor;if(!j.token)throw Error(`Service [${j.name}] is listed in \`services\` but does not declare a \`static token\`.`);let O=N.get(j.token);if(O)throw Error(`Services [${O}] and [${j.name}] both declare the token "${j.token}". Tokens are the container's keys, so they must be unique.`);N.set(j.token,j.name);let W=j;if(!q.has(j.token)&&this.app.bound(W))throw Error(`Service [${j.name}] declares the token "${j.token}", which is already bound in the container by the framework or a provider. Binding it would replace that service everywhere, so pick a token nothing else owns.`);this.app.instance(W,C),this.serviceInstances.push(C),this.serviceTokens.add(j.token)}}async waitForBoot(){await this.app.boot(),await this.bootServices()}async bootServices(){if(this.servicesBooted)return;for(let q of this.serviceInstances)await q.boot();this.servicesBooted=!0}run(q){return H.run(this.app,q)}resolve(q){return this.app.make(q)}apiRoutes(){return this.app.make(k)}viewRoutes(){return this.app.make(m)}broadcast(){return this.app.make(f)}queue(){return this.app.make(R)}destroy(){if(this.app.resolved(J))this.app.make(J).stop();if(this.app.flush(),x.getInstance()===this.app)x.setInstance(void 0);H.disable()}}function A(){if(Bun.env.NODE_ENV==="production")return;let q=b();if(q.length===0)return;console.warn(`[gemi] ${q.length} model${q.length===1?" is":"s are"} registered, but Kernel.models is empty.
3
3
  Nested relation reads resolve a model by name, so a policy on a subclass that does not own its
4
4
  `+" name is skipped inside every include \u2014 scoped at the root, "+`unscoped in an include, with nothing
5
5
  to notice it. Declaring the modules registers each class under its own name and audits the set:
@@ -11,6 +11,6 @@ import{sa as X}from"../chunk-rsdg619q.js";import{Pa as m}from"../chunk-enhkf60v.
11
11
  models = [generated, models]
12
12
  }
13
13
 
14
- See docs/orm.md#your-model-class. Development only; this never prints in production.`)}export{E as frameworkProviders,w as UserProvider,M as Kernel};
14
+ See docs/orm.md#your-model-class. Development only; this never prints in production.`)}export{G as frameworkProviders,h as UserProvider,w as Kernel};
15
15
 
16
- //# debugId=8DF2BA614315E92364756E2164756E21
16
+ //# debugId=45648151B30677FB64756E2164756E21
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../kernel/providers.ts", "../kernel/Kernel.ts"],
4
4
  "sourcesContent": [
5
- "import type { ServiceProviderConstructor } from \"../foundation/Application\";\nimport { AuthServiceProvider } from \"../auth/AuthServiceProvider\";\nimport { DatabaseServiceProvider } from \"../database/DatabaseServiceProvider\";\nimport { TranslationServiceProvider } from \"../i18n/TranslationServiceProvider\";\nimport { ScheduleServiceProvider } from \"../services/cron/ScheduleServiceProvider\";\nimport { MailServiceProvider } from \"../services/email/MailServiceProvider\";\nimport { FilesystemServiceProvider } from \"../services/file-storage/FilesystemServiceProvider\";\nimport { ImageServiceProvider } from \"../services/image-optimization/ImageServiceProvider\";\nimport { KernelIdServiceProvider } from \"../services/kernel-id/KernelIdServiceProvider\";\nimport { LogServiceProvider } from \"../services/logging/LogServiceProvider\";\nimport { MiddlewareServiceProvider } from \"../services/middleware/MiddlewareServiceProvider\";\nimport { BroadcastServiceProvider } from \"../services/pubsub/BroadcastServiceProvider\";\nimport { QueueServiceProvider } from \"../services/queue/QueueServiceProvider\";\nimport { RateLimiterServiceProvider } from \"../services/rate-limiter/RateLimiterServiceProvider\";\nimport { RedisServiceProvider } from \"../services/redis/RedisServiceProvider\";\nimport { RouteServiceProvider } from \"../services/router/RouteServiceProvider\";\n\n/**\n * The providers every gemi app boots with, in registration order. Fifteen\n * providers for sixteen services — `RouteServiceProvider` owns both the api and\n * the view dispatcher, the way Laravel's does.\n *\n * Order only matters for `boot()`; `register()` binds factories and resolves\n * nothing, so no provider here depends on an earlier one having run.\n */\nexport const frameworkProviders: ServiceProviderConstructor[] = [\n KernelIdServiceProvider,\n MiddlewareServiceProvider,\n DatabaseServiceProvider,\n RouteServiceProvider,\n AuthServiceProvider,\n MailServiceProvider,\n LogServiceProvider,\n FilesystemServiceProvider,\n QueueServiceProvider,\n RedisServiceProvider,\n BroadcastServiceProvider,\n ImageServiceProvider,\n TranslationServiceProvider,\n RateLimiterServiceProvider,\n ScheduleServiceProvider,\n];\n",
5
+ "import type { ServiceProviderConstructor } from \"../foundation/Application\";\nimport { AuthServiceProvider } from \"../auth/AuthServiceProvider\";\nimport { DatabaseServiceProvider } from \"../database/DatabaseServiceProvider\";\nimport { TranslationServiceProvider } from \"../i18n/TranslationServiceProvider\";\nimport { ScheduleServiceProvider } from \"../services/cron/ScheduleServiceProvider\";\nimport { FeaturesServiceProvider } from \"../services/features/FeaturesServiceProvider\";\nimport { MailServiceProvider } from \"../services/email/MailServiceProvider\";\nimport { EventServiceProvider } from \"../services/events/EventServiceProvider\";\nimport { FilesystemServiceProvider } from \"../services/file-storage/FilesystemServiceProvider\";\nimport { ImageServiceProvider } from \"../services/image-optimization/ImageServiceProvider\";\nimport { KernelIdServiceProvider } from \"../services/kernel-id/KernelIdServiceProvider\";\nimport { LogServiceProvider } from \"../services/logging/LogServiceProvider\";\nimport { MiddlewareServiceProvider } from \"../services/middleware/MiddlewareServiceProvider\";\nimport { BroadcastServiceProvider } from \"../services/pubsub/BroadcastServiceProvider\";\nimport { QueueServiceProvider } from \"../services/queue/QueueServiceProvider\";\nimport { RateLimiterServiceProvider } from \"../services/rate-limiter/RateLimiterServiceProvider\";\nimport { RedisServiceProvider } from \"../services/redis/RedisServiceProvider\";\nimport { RouteServiceProvider } from \"../services/router/RouteServiceProvider\";\n\n/**\n * The providers every gemi app boots with, in registration order. Seventeen\n * providers for eighteen services — `RouteServiceProvider` owns both the api\n * and the view dispatcher, the way Laravel's does.\n *\n * Order only matters for `boot()`; `register()` binds factories and resolves\n * nothing, so no provider here depends on an earlier one having run — with one\n * exception, which is the reason to read this before reordering anything.\n *\n * **`EventServiceProvider` must stay after `QueueServiceProvider`.** A queued\n * listener is registered with the queue as a synthetic job, and\n * `EventServiceProvider.boot()` is what hands those over. `QueueManager.useJobs`\n * — which `QueueServiceProvider.boot()` calls with whatever it discovered under\n * `app/jobs` — *replaces* the registry (`this.jobs = {}`). Move the events\n * provider up and the two boots run in the order that discards: every\n * `listener:*` entry is registered and then thrown away. Nothing errors, boot\n * succeeds, and each queued dispatch afterwards lands on `next()`'s \"Dropped a\n * queued job: nothing is registered under the name listener:SendWelcomeEmail\",\n * long after `dispatch` returned to a caller that cannot hear it.\n */\nexport const frameworkProviders: ServiceProviderConstructor[] = [\n KernelIdServiceProvider,\n MiddlewareServiceProvider,\n DatabaseServiceProvider,\n // After the database, whose `boot()` its cache warm-up depends on, and before\n // the route dispatchers, which evaluate flags on every view request.\n FeaturesServiceProvider,\n RouteServiceProvider,\n AuthServiceProvider,\n MailServiceProvider,\n LogServiceProvider,\n FilesystemServiceProvider,\n QueueServiceProvider,\n EventServiceProvider,\n RedisServiceProvider,\n BroadcastServiceProvider,\n ImageServiceProvider,\n TranslationServiceProvider,\n RateLimiterServiceProvider,\n ScheduleServiceProvider,\n];\n",
6
6
  "import { Application } from \"../foundation/Application\";\nimport type { ServiceProviderConstructor } from \"../foundation/Application\";\nimport type { ServiceToken } from \"../container/Container\";\nimport type { ConfigItems } from \"../support/Repository\";\nimport type { Service, ServiceConstructor } from \"../support/Service\";\nimport { registerModels } from \"../orm/registration\";\nimport { registeredNames } from \"../orm/registry\";\nimport { Scheduler } from \"../services/cron/Scheduler\";\nimport { BroadcastManager } from \"../services/pubsub/BroadcastManager\";\nimport { QueueManager } from \"../services/queue/QueueManager\";\nimport { ApiRouteDispatcher } from \"../services/router/ApiRouteDispatcher\";\nimport { ViewRouteDispatcher } from \"../services/router/ViewRouteDispatcher\";\nimport { kernelContext } from \"./context\";\nimport { frameworkProviders } from \"./providers\";\n\n/**\n * The app's entry point into the framework. A Kernel subclass declares what the\n * app adds — its `config` slices and any extra `providers` — and everything\n * else lives in the Application container it owns.\n */\nexport class Kernel {\n /**\n * App-level config, merged over the framework defaults. Each key is a config\n * slice: `{ mail: { ... }, route: { ... } }`, normally the modules under\n * `app/config`.\n */\n protected config: ConfigItems = {};\n\n /**\n * App-level providers, registered after the framework's own so they can\n * rebind anything the framework bound.\n */\n protected providers: ServiceProviderConstructor[] = [];\n\n /**\n * The app's own singleton services. Each is constructed during the\n * synchronous boot phase and its `boot()` awaited during the asynchronous\n * one, in the order listed — so a service whose `boot()` depends on another\n * goes after it.\n *\n * An entry is either the class itself or a configured instance from\n * `Service.with({ ... })`. Listing is explicit rather than discovered because\n * the order is load-bearing here, and because a service is always imported by\n * whatever injects it — there is no file the import graph would miss.\n */\n protected services: Array<ServiceConstructor | Service> = [];\n\n private serviceInstances: Service[] = [];\n private serviceTokens = new Set<string>();\n private servicesBooted = false;\n\n /**\n * The modules holding the app's model classes — normally\n * `[generated, models]`, the generated namespace and the barrel of subclasses\n * written over it. Every model class they export is registered under the name\n * its schema carries, later modules winning, and the whole set is audited\n * before anything else boots.\n *\n * ### Why this is a Kernel field and not a line in a file somewhere\n *\n * Registration used to be `register(\"User\", User)` next to each subclass, and\n * the failure mode of forgetting it is an authorization hole that nothing\n * reports: a relation read resolves its target by name, so an unregistered\n * policied subclass leaves the generated base owning the name and every\n * nested `include` of that model comes back unscoped. No error at the root\n * either, because `$exec`'s divergence guard begins `registered !== this` and\n * the base it is running on *is* the registered one. A model only ever read\n * through an include — a membership, a pivot, the kind that carries a tenant\n * scope — never trips anything.\n *\n * Listing the modules here says it once, in the same place the app already\n * declares its config slices and providers, and turns the mistake into a\n * failure to boot rather than a quiet cross-tenant read.\n *\n * It sees the modules it is given, so a model class in a file that no barrel\n * re-exports is still invisible. That is the residual, and it is a smaller\n * one: a barrel is a place to notice an omission, and thirteen `register`\n * lines scattered across thirteen files is not.\n */\n protected models: Array<Record<string, unknown>> = [];\n\n readonly app = new Application();\n\n /**\n * Phase one, synchronous: every provider is constructed and its `register()`\n * runs. Only bindings are recorded here — no service is instantiated, so this\n * is safe to call from a synchronous constructor (`new App({ kernel })`).\n * Phase two is `waitForBoot()`.\n */\n boot() {\n // Before the container, deliberately. This throws on a model whose policies\n // would be skipped, and the useful moment for that is the one where nothing\n // has been constructed and no request can be in flight.\n if (this.models.length > 0) registerModels(...this.models);\n else warnIfModelsAreRegisteredButUndeclared();\n\n this.app.config.merge(this.config);\n Application.setInstance(this.app);\n this.app.registerMany([...frameworkProviders, ...this.providers]);\n this.registerServices();\n }\n\n /**\n * Constructs every listed service and binds it into the container. Runs after\n * the providers have registered, so a provider's `boot()` can `inject()` one;\n * a `Service` constructor does no I/O, so doing this synchronously costs\n * nothing beyond the field initializers.\n */\n private registerServices() {\n // What a previous pass bound, so re-running this on the same kernel is not\n // mistaken for a collision with something else.\n const ours = this.serviceTokens;\n\n this.serviceInstances = [];\n this.serviceTokens = new Set();\n this.servicesBooted = false;\n\n const owners = new Map<string, string>();\n\n for (const declaration of this.services) {\n const instance =\n typeof declaration === \"function\" ? new declaration() : declaration;\n const ctor = instance.constructor as ServiceConstructor;\n\n if (!ctor.token) {\n throw new Error(\n `Service [${ctor.name}] is listed in \\`services\\` but does not declare a \\`static token\\`.`,\n );\n }\n\n // Two services under one token is the failure this refuses to have\n // silently: the second would replace the first in the container, and\n // every `inject()` written against either would hand back whichever was\n // listed last.\n const owner = owners.get(ctor.token);\n if (owner) {\n throw new Error(\n `Services [${owner}] and [${ctor.name}] both declare the token \"${ctor.token}\". Tokens are the container's keys, so they must be unique.`,\n );\n }\n owners.set(ctor.token, ctor.name);\n\n // The same failure one level out. `Container.instance()` writes into\n // `instances`, which `make()` consults before `bindings`, so a token that\n // is already spoken for is not shared with its owner — it replaces it, for\n // every `app()` and `inject()` in the process. An app service that named\n // itself \"mail\" would leave `Mail.send()` resolving to an object with no\n // `send`, and the boot that caused it would report nothing. Providers have\n // all registered by now, so anything bound here belongs to somebody else.\n const token = ctor as unknown as ServiceToken<Service>;\n if (!ours.has(ctor.token) && this.app.bound(token)) {\n throw new Error(\n `Service [${ctor.name}] declares the token \"${ctor.token}\", which is already bound in the container by the framework or a provider. Binding it would replace that service everywhere, so pick a token nothing else owns.`,\n );\n }\n\n this.app.instance(token, instance);\n this.serviceInstances.push(instance);\n this.serviceTokens.add(ctor.token);\n }\n }\n\n /**\n * Phase two, asynchronous: every provider's `boot()` runs, in registration\n * order, after all of them have registered. Idempotent.\n */\n async waitForBoot() {\n await this.app.boot();\n await this.bootServices();\n }\n\n /**\n * Phase two for services, after every provider's `boot()` — so a service may\n * use the facades and anything else a provider owns. Idempotent, like the\n * provider phase it follows.\n */\n private async bootServices() {\n if (this.servicesBooted) {\n return;\n }\n for (const service of this.serviceInstances) {\n await service.boot();\n }\n this.servicesBooted = true;\n }\n\n run<T>(cb: () => T) {\n return kernelContext.run(this.app, cb);\n }\n\n /**\n * Resolve a service by token. Callers outside this module should prefer the\n * named accessors below or `app()`; this exists for tooling that holds a\n * Kernel but no ambient context.\n */\n resolve<T>(token: ServiceToken<T>): T {\n return this.app.make(token);\n }\n\n // Named accessors. `app/App.ts` goes through these rather than importing the\n // service classes itself — see the note in that file about the two copies of\n // gemi that coexist at build time.\n apiRoutes(): ApiRouteDispatcher {\n return this.app.make(ApiRouteDispatcher);\n }\n\n viewRoutes(): ViewRouteDispatcher {\n return this.app.make(ViewRouteDispatcher);\n }\n\n broadcast(): BroadcastManager {\n return this.app.make(BroadcastManager);\n }\n\n queue(): QueueManager {\n return this.app.make(QueueManager);\n }\n\n destroy() {\n // Only touch services that were actually resolved — resolving one here\n // would construct it purely to tear it down.\n if (this.app.resolved(Scheduler)) {\n this.app.make(Scheduler).stop();\n }\n\n this.app.flush();\n\n if (Application.getInstance() === this.app) {\n Application.setInstance(undefined);\n }\n\n kernelContext.disable();\n }\n}\n\n/**\n * Says something to an application that has models and has not declared them.\n *\n * Without this the fix for #316 defaults to off. `models` is `[]`, `boot()`\n * no-ops, and an app upgrading from 0.48 is in exactly the state the issue\n * describes until somebody edits their Kernel by hand — while the only place\n * that says to is the **Setup** section of `docs/orm.md`, which an existing app\n * read once and will not read again. #316 was filed by an app mid-migration\n * with a 79-model schema, which is precisely the reader who never sees it.\n *\n * The condition is what makes this worth printing. A populated registry with an\n * empty `models` means the generated `index.ts` was imported and its bases are\n * what every nested read resolves to — so if any policy lives on a subclass, it\n * is being skipped inside includes right now. A Kernel with no ORM at all has\n * an empty registry and hears nothing.\n *\n * Development only, and a warning rather than a throw: an app in this state is\n * running today, and turning a working deploy into a failure to start over an\n * arrangement that *might* be fine is not a patch-level thing to do. The\n * failure it points at is silent, so the fix for it has to be noisy somewhere,\n * and the terminal an author is already looking at is the cheapest somewhere\n * there is.\n */\nfunction warnIfModelsAreRegisteredButUndeclared(): void {\n if (process.env.NODE_ENV === \"production\") return;\n\n const registered = registeredNames();\n if (registered.length === 0) return;\n\n console.warn(\n `[gemi] ${registered.length} model${registered.length === 1 ? \" is\" : \"s are\"} ` +\n `registered, but Kernel.models is empty.\\n` +\n ` Nested relation reads resolve a model by name, so a policy on a ` +\n `subclass that does not own its\\n` +\n ` name is skipped inside every include — scoped at the root, ` +\n `unscoped in an include, with nothing\\n` +\n ` to notice it. Declaring the modules registers each class under ` +\n `its own name and audits the set:\\n\\n` +\n ` import * as generated from \"../models/generated\"\\n` +\n ` import * as models from \"../models\"\\n\\n` +\n ` export default class extends Kernel {\\n` +\n ` models = [generated, models]\\n` +\n ` }\\n\\n` +\n ` See docs/orm.md#your-model-class. Development only; this never ` +\n `prints in production.`,\n );\n}\n"
7
7
  ],
8
- "mappings": ";07BAyBO,DAAM,HAAmD,JAC9D,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,JACF,HCrBO,CAAM,CAAO,CAMR,OAAsB,CAAC,EAMvB,UAA0C,CAAC,EAa3C,SAAgD,CAAC,EAEnD,iBAA8B,CAAC,EAC/B,cAAgB,IAAI,IACpB,eAAiB,GA8Bf,OAAyC,CAAC,EAE3C,IAAM,IAAI,EAQnB,IAAI,EAAG,CAIL,GAAI,KAAK,OAAO,OAAS,EAAG,EAAe,GAAG,KAAK,MAAM,EACpD,OAAuC,EAE5C,KAAK,IAAI,OAAO,MAAM,KAAK,MAAM,EACjC,EAAY,YAAY,KAAK,GAAG,EAChC,KAAK,IAAI,aAAa,CAAC,GAAG,EAAoB,GAAG,KAAK,SAAS,CAAC,EAChE,KAAK,iBAAiB,EAShB,gBAAgB,EAAG,CAGzB,IAAM,EAAO,KAAK,cAElB,KAAK,iBAAmB,CAAC,EACzB,KAAK,cAAgB,IAAI,IACzB,KAAK,eAAiB,GAEtB,IAAM,EAAS,IAAI,IAEnB,QAAW,KAAe,KAAK,SAAU,CACvC,IAAM,EACJ,OAAO,IAAgB,WAAa,IAAI,EAAgB,EACpD,EAAO,EAAS,YAEtB,GAAI,CAAC,EAAK,MACR,MAAU,MACR,YAAY,EAAK,0EACnB,EAOF,IAAM,EAAQ,EAAO,IAAI,EAAK,KAAK,EACnC,GAAI,EACF,MAAU,MACR,aAAa,WAAe,EAAK,iCAAiC,EAAK,kEACzE,EAEF,EAAO,IAAI,EAAK,MAAO,EAAK,IAAI,EAShC,IAAM,EAAQ,EACd,GAAI,CAAC,EAAK,IAAI,EAAK,KAAK,GAAK,KAAK,IAAI,MAAM,CAAK,EAC/C,MAAU,MACR,YAAY,EAAK,6BAA6B,EAAK,sKACrD,EAGF,KAAK,IAAI,SAAS,EAAO,CAAQ,EACjC,KAAK,iBAAiB,KAAK,CAAQ,EACnC,KAAK,cAAc,IAAI,EAAK,KAAK,QAQ/B,YAAW,EAAG,CAClB,MAAM,KAAK,IAAI,KAAK,EACpB,MAAM,KAAK,aAAa,OAQZ,aAAY,EAAG,CAC3B,GAAI,KAAK,eACP,OAEF,QAAW,KAAW,KAAK,iBACzB,MAAM,EAAQ,KAAK,EAErB,KAAK,eAAiB,GAGxB,GAAM,CAAC,EAAa,CAClB,OAAO,EAAc,IAAI,KAAK,IAAK,CAAE,EAQvC,OAAU,CAAC,EAA2B,CACpC,OAAO,KAAK,IAAI,KAAK,CAAK,EAM5B,SAAS,EAAuB,CAC9B,OAAO,KAAK,IAAI,KAAK,CAAkB,EAGzC,UAAU,EAAwB,CAChC,OAAO,KAAK,IAAI,KAAK,CAAmB,EAG1C,SAAS,EAAqB,CAC5B,OAAO,KAAK,IAAI,KAAK,CAAgB,EAGvC,KAAK,EAAiB,CACpB,OAAO,KAAK,IAAI,KAAK,CAAY,EAGnC,OAAO,EAAG,CAGR,GAAI,KAAK,IAAI,SAAS,CAAS,EAC7B,KAAK,IAAI,KAAK,CAAS,EAAE,KAAK,EAKhC,GAFA,KAAK,IAAI,MAAM,EAEX,EAAY,YAAY,IAAM,KAAK,IACrC,EAAY,YAAY,MAAS,EAGnC,EAAc,QAAQ,EAE1B,CAyBA,SAAS,CAAsC,EAAS,CACtD,GAAI,mBAAyB,aAAc,OAE3C,IAAM,EAAa,EAAgB,EACnC,GAAI,EAAW,SAAW,EAAG,OAE7B,QAAQ,KACN,UAAU,EAAW,eAAe,EAAW,SAAW,EAAI,MAAQ;AAAA;AAAA,EAIpE,2EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6FAUJ",
9
- "debugId": "8DF2BA614315E92364756E2164756E21",
8
+ "mappings": ";08BAuCO,DAAM,HAAmD,JAC9D,HACA,HACA,HAGA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,HACA,JACF,ECvCO,MAAM,CAAO,CAMR,OAAsB,CAAC,EAMvB,UAA0C,CAAC,EAa3C,SAAgD,CAAC,EAEnD,iBAA8B,CAAC,EAC/B,cAAgB,IAAI,IACpB,eAAiB,GA8Bf,OAAyC,CAAC,EAE3C,IAAM,IAAI,EAQnB,IAAI,EAAG,CAIL,GAAI,KAAK,OAAO,OAAS,EAAG,EAAe,GAAG,KAAK,MAAM,EACpD,OAAuC,EAE5C,KAAK,IAAI,OAAO,MAAM,KAAK,MAAM,EACjC,EAAY,YAAY,KAAK,GAAG,EAChC,KAAK,IAAI,aAAa,CAAC,GAAG,EAAoB,GAAG,KAAK,SAAS,CAAC,EAChE,KAAK,iBAAiB,EAShB,gBAAgB,EAAG,CAGzB,IAAM,EAAO,KAAK,cAElB,KAAK,iBAAmB,CAAC,EACzB,KAAK,cAAgB,IAAI,IACzB,KAAK,eAAiB,GAEtB,IAAM,EAAS,IAAI,IAEnB,QAAW,KAAe,KAAK,SAAU,CACvC,IAAM,EACJ,OAAO,IAAgB,WAAa,IAAI,EAAgB,EACpD,EAAO,EAAS,YAEtB,GAAI,CAAC,EAAK,MACR,MAAU,MACR,YAAY,EAAK,0EACnB,EAOF,IAAM,EAAQ,EAAO,IAAI,EAAK,KAAK,EACnC,GAAI,EACF,MAAU,MACR,aAAa,WAAe,EAAK,iCAAiC,EAAK,kEACzE,EAEF,EAAO,IAAI,EAAK,MAAO,EAAK,IAAI,EAShC,IAAM,EAAQ,EACd,GAAI,CAAC,EAAK,IAAI,EAAK,KAAK,GAAK,KAAK,IAAI,MAAM,CAAK,EAC/C,MAAU,MACR,YAAY,EAAK,6BAA6B,EAAK,sKACrD,EAGF,KAAK,IAAI,SAAS,EAAO,CAAQ,EACjC,KAAK,iBAAiB,KAAK,CAAQ,EACnC,KAAK,cAAc,IAAI,EAAK,KAAK,QAQ/B,YAAW,EAAG,CAClB,MAAM,KAAK,IAAI,KAAK,EACpB,MAAM,KAAK,aAAa,OAQZ,aAAY,EAAG,CAC3B,GAAI,KAAK,eACP,OAEF,QAAW,KAAW,KAAK,iBACzB,MAAM,EAAQ,KAAK,EAErB,KAAK,eAAiB,GAGxB,GAAM,CAAC,EAAa,CAClB,OAAO,EAAc,IAAI,KAAK,IAAK,CAAE,EAQvC,OAAU,CAAC,EAA2B,CACpC,OAAO,KAAK,IAAI,KAAK,CAAK,EAM5B,SAAS,EAAuB,CAC9B,OAAO,KAAK,IAAI,KAAK,CAAkB,EAGzC,UAAU,EAAwB,CAChC,OAAO,KAAK,IAAI,KAAK,CAAmB,EAG1C,SAAS,EAAqB,CAC5B,OAAO,KAAK,IAAI,KAAK,CAAgB,EAGvC,KAAK,EAAiB,CACpB,OAAO,KAAK,IAAI,KAAK,CAAY,EAGnC,OAAO,EAAG,CAGR,GAAI,KAAK,IAAI,SAAS,CAAS,EAC7B,KAAK,IAAI,KAAK,CAAS,EAAE,KAAK,EAKhC,GAFA,KAAK,IAAI,MAAM,EAEX,EAAY,YAAY,IAAM,KAAK,IACrC,EAAY,YAAY,MAAS,EAGnC,EAAc,QAAQ,EAE1B,CAyBA,SAAS,CAAsC,EAAS,CACtD,GAAI,mBAAyB,aAAc,OAE3C,IAAM,EAAa,EAAgB,EACnC,GAAI,EAAW,SAAW,EAAG,OAE7B,QAAQ,KACN,UAAU,EAAW,eAAe,EAAW,SAAW,EAAI,MAAQ;AAAA;AAAA,EAIpE,2EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6FAUJ",
9
+ "debugId": "45648151B30677FB64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -1,11 +1,23 @@
1
1
  import type { ServiceProviderConstructor } from "../foundation/Application";
2
2
  /**
3
- * The providers every gemi app boots with, in registration order. Fifteen
4
- * providers for sixteen services — `RouteServiceProvider` owns both the api and
5
- * the view dispatcher, the way Laravel's does.
3
+ * The providers every gemi app boots with, in registration order. Seventeen
4
+ * providers for eighteen services — `RouteServiceProvider` owns both the api
5
+ * and the view dispatcher, the way Laravel's does.
6
6
  *
7
7
  * Order only matters for `boot()`; `register()` binds factories and resolves
8
- * nothing, so no provider here depends on an earlier one having run.
8
+ * nothing, so no provider here depends on an earlier one having run — with one
9
+ * exception, which is the reason to read this before reordering anything.
10
+ *
11
+ * **`EventServiceProvider` must stay after `QueueServiceProvider`.** A queued
12
+ * listener is registered with the queue as a synthetic job, and
13
+ * `EventServiceProvider.boot()` is what hands those over. `QueueManager.useJobs`
14
+ * — which `QueueServiceProvider.boot()` calls with whatever it discovered under
15
+ * `app/jobs` — *replaces* the registry (`this.jobs = {}`). Move the events
16
+ * provider up and the two boots run in the order that discards: every
17
+ * `listener:*` entry is registered and then thrown away. Nothing errors, boot
18
+ * succeeds, and each queued dispatch afterwards lands on `next()`'s "Dropped a
19
+ * queued job: nothing is registered under the name listener:SendWelcomeEmail",
20
+ * long after `dispatch` returned to a caller that cannot hear it.
9
21
  */
10
22
  export declare const frameworkProviders: ServiceProviderConstructor[];
11
23
  //# sourceMappingURL=providers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../kernel/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAiB5E;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,0BAA0B,EAgB1D,CAAC"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../kernel/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAmB5E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,EAAE,0BAA0B,EAoB1D,CAAC"}
@@ -67,7 +67,45 @@ export interface OrmScope {
67
67
  actor?: {
68
68
  user: unknown;
69
69
  };
70
+ /**
71
+ * Work that must not happen unless this transaction commits — an event whose
72
+ * `static afterCommit` is set, today, and nothing else.
73
+ *
74
+ * **Created by the outermost `withTransaction` and never by a savepoint.** A
75
+ * savepoint's scope is a spread of its parent's (`{ ...current, tx: nested }`),
76
+ * so the array arrives here already shared by reference with the transaction
77
+ * that opened it — which is the behaviour wanted rather than a leak. A
78
+ * dispatch made inside a savepoint that commits, in a transaction that then
79
+ * rolls back, must not run: rolling back the outermost transaction discards
80
+ * the list whole, savepoint entries included, because nothing ever drains it.
81
+ *
82
+ * The inverse — a savepoint that rolls back under a transaction that commits
83
+ * — is the case sharing gets wrong on its own, and `withTransaction`'s
84
+ * savepoint branch is where it is put right.
85
+ *
86
+ * Absent, rather than an empty array, on every scope that is not a
87
+ * transaction: `runAsSystem`, `runAsUser` and `runOnConnection` spread
88
+ * whatever they are given, so "there is a list here" and "there is an open
89
+ * transaction here" have to stay the same question. `deferUntilCommit`
90
+ * answers `false` when either half is missing and the caller runs the work
91
+ * now, which is what keeps a hand-built scope carrying a `tx` — the shape
92
+ * tests write — from swallowing a dispatch into a list nothing drains.
93
+ */
94
+ afterCommit?: AfterCommitCallback[];
70
95
  }
96
+ /**
97
+ * Work deferred to a transaction's commit.
98
+ *
99
+ * Awaited when it is drained, and its rejection is caught there: a callback is
100
+ * a side effect that the transaction is not waiting on and cannot be told
101
+ * about, so the only thing left to do with a failure is report it.
102
+ *
103
+ * Not exported: a caller passes a lambda and never names this, and an export
104
+ * nothing outside this file uses is what `orm/architecture.test.ts` is pointed
105
+ * at. The declaration emit carries it along regardless, so `OrmScope` stays
106
+ * readable from a `.d.ts`.
107
+ */
108
+ type AfterCommitCallback = () => void | Promise<void>;
71
109
  /**
72
110
  * One ambient scope for the ORM, not one per feature.
73
111
  *
@@ -127,6 +165,26 @@ export declare function runOnConnection<T>(name: string, fn: () => Promise<T>):
127
165
  * resolves to the ambient name, which is the transaction's own.
128
166
  */
129
167
  export declare function assertConnectionUsable(name: string): void;
168
+ /**
169
+ * Hold `callback` until the open transaction commits, and say whether that
170
+ * happened.
171
+ *
172
+ * `false` means there was nothing to wait for — no transaction is open, or the
173
+ * scope was entered by hand rather than by `withTransaction` — and the caller
174
+ * must run the work itself, now. That return value is the whole contract: a
175
+ * caller that ignores it turns "no transaction here" into a side effect queued
176
+ * on a list nothing will ever drain, which is a dispatch that silently never
177
+ * happens.
178
+ *
179
+ * `true` means the callback is on the outermost scope's list and will run after
180
+ * `begin` resolves, outside the transaction, whatever the caller does next. It
181
+ * will not run at all if the transaction rolls back, or if a savepoint it was
182
+ * registered inside rolls back — both of which are the point.
183
+ *
184
+ * Nothing here is ordered against anything but the other deferred callbacks:
185
+ * they run in registration order, one at a time, after the commit round-trip.
186
+ */
187
+ export declare function deferUntilCommit(callback: AfterCommitCallback): boolean;
130
188
  /** How deeply nested the current transaction is; `null` outside one. */
131
189
  export declare function transactionDepth(): number | null;
132
190
  /** Whether policies are suspended for the current async scope. */
@@ -216,6 +274,12 @@ export declare function slowTransactionThreshold(configured?: number | false): n
216
274
  * it — while the runtime object does carry the method, which is what makes
217
275
  * three levels of nesting work.
218
276
  *
277
+ * Anything `deferUntilCommit` queued is drained once `begin` resolves, outside
278
+ * the transaction and only on the outermost call — a savepoint has committed
279
+ * nothing durable, so draining there would run work that a later rollback of
280
+ * the enclosing transaction was meant to have prevented. See `drainAfterCommit`
281
+ * for what that costs the caller.
282
+ *
219
283
  * In development, an outermost transaction that stays open past
220
284
  * `options.slowTransactionThreshold` (2s by default, `false` to disable) warns
221
285
  * — see `watchForSlowTransaction`. Nothing here *prevents* a long transaction;
@@ -243,4 +307,5 @@ export declare function withTransaction<T>(pool: SQL, fn: (tx: TransactionSQL) =
243
307
  slowTransactionThreshold?: number | false;
244
308
  connection?: string;
245
309
  }): Promise<T>;
310
+ export {};
246
311
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../orm/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAOrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,6BAAoC,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,GAAG,SAAS,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAGhD;AAED,kEAAkE;AAClE,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAG/D;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAE5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAW5E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAC1B,MAAM,GAAG,IAAI,CAgBf;AAwDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,CAAC,EAAE;IAAE,wBAAwB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3E,OAAO,CAAC,CAAC,CAAC,CAsFZ"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../orm/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAOrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,mBAAmB,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,6BAAoC,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,GAAG,SAAS,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAMvE;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAGhD;AAED,kEAAkE;AAClE,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAG/D;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAE5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAW5E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAC1B,MAAM,GAAG,IAAI,CAgBf;AAiHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,GAAG,EACT,EAAE,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,CAAC,EAAE;IAAE,wBAAwB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3E,OAAO,CAAC,CAAC,CAAC,CAuIZ"}