@eventcatalog/core 5.0.0-beta.3 → 5.0.0-beta.31

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 (277) hide show
  1. package/LICENSE +234 -134
  2. package/README.md +5 -5
  3. package/dist/analytics/analytics.cjs +18 -3
  4. package/dist/analytics/analytics.d.cts +1 -1
  5. package/dist/analytics/analytics.d.ts +1 -1
  6. package/dist/analytics/analytics.js +3 -2
  7. package/dist/analytics/log-build.cjs +160 -77
  8. package/dist/analytics/log-build.d.cts +2 -2
  9. package/dist/analytics/log-build.d.ts +2 -2
  10. package/dist/analytics/log-build.js +7 -5
  11. package/dist/analytics/studio-usage.cjs +90 -0
  12. package/dist/analytics/studio-usage.d.cts +5 -0
  13. package/dist/analytics/studio-usage.d.ts +5 -0
  14. package/dist/analytics/studio-usage.js +10 -0
  15. package/dist/analytics/telemetry.cjs +42 -0
  16. package/dist/analytics/telemetry.d.cts +20 -0
  17. package/dist/analytics/telemetry.d.ts +20 -0
  18. package/dist/analytics/telemetry.js +8 -0
  19. package/dist/catalog-runtime.cjs +1 -1
  20. package/dist/{chunk-BH2F5WPN.js → chunk-2UCCTEIH.js} +1 -1
  21. package/dist/{chunk-RFIXKATC.js → chunk-4G7FSRPN.js} +35 -42
  22. package/dist/{chunk-TQLRG35T.js → chunk-AD7CL772.js} +78 -45
  23. package/dist/{chunk-NDJOAITI.js → chunk-BNSLGNQI.js} +9 -3
  24. package/dist/chunk-CA6WCQ2T.js +54 -0
  25. package/dist/chunk-CPW6G62V.js +17 -0
  26. package/dist/{chunk-MDWB5HLO.js → chunk-NKNOXQ62.js} +1 -1
  27. package/dist/{chunk-423S2KHN.js → chunk-OUEGYMBA.js} +4 -2
  28. package/dist/{chunk-3PKS2IIP.js → chunk-OX6TSVHY.js} +1 -1
  29. package/dist/{chunk-36RYTYT5.js → chunk-PD7KTSYN.js} +1 -1
  30. package/dist/chunk-S5GWAUG5.js +29 -0
  31. package/dist/{chunk-GYIVJXOJ.js → chunk-WADZVNCA.js} +1 -1
  32. package/dist/{chunk-6OC46WQJ.js → chunk-XRFL642Z.js} +66 -35
  33. package/dist/constants.cjs +1 -1
  34. package/dist/constants.js +1 -1
  35. package/dist/eventcatalog-config-file-utils.cjs +34 -41
  36. package/dist/eventcatalog-config-file-utils.d.cts +56 -58
  37. package/dist/eventcatalog-config-file-utils.d.ts +56 -58
  38. package/dist/eventcatalog-config-file-utils.js +1 -1
  39. package/dist/eventcatalog.cjs +531 -356
  40. package/dist/eventcatalog.config.d.cts +59 -1
  41. package/dist/eventcatalog.config.d.ts +59 -1
  42. package/dist/eventcatalog.js +63 -25
  43. package/dist/features.cjs +34 -41
  44. package/dist/features.js +2 -2
  45. package/dist/federation/federate.cjs +37 -44
  46. package/dist/federation/federate.js +2 -2
  47. package/dist/generate.cjs +37 -42
  48. package/dist/generate.js +4 -4
  49. package/dist/resolve-catalog-dependencies.cjs +34 -41
  50. package/dist/resolve-catalog-dependencies.js +2 -2
  51. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio-fonts.css.mjs +3 -0
  52. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.css.mjs +3 -0
  53. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.mjs +3 -0
  54. package/dist/runtime-dependencies/@hocuspocus__provider.mjs +3 -0
  55. package/dist/runtime-dependencies/@hocuspocus__server.mjs +3 -0
  56. package/dist/runtime-dependencies/@mcp-b__webmcp-local-relay.mjs +3 -0
  57. package/dist/runtime-dependencies/@mcp-b__webmcp-polyfill.mjs +3 -0
  58. package/dist/runtime-dependencies/htmlparser2.mjs +3 -0
  59. package/dist/runtime-dependencies/manifest.json +13 -1
  60. package/dist/runtime-dependencies/react-hotkeys-hook.mjs +3 -0
  61. package/dist/runtime-dependencies/react-syntax-highlighter__dist__cjs__create-element.js.mjs +3 -0
  62. package/dist/runtime-dependencies/y-protocols.mjs +3 -0
  63. package/dist/runtime-dependencies/y-protocols__awareness.mjs +3 -0
  64. package/dist/runtime-dependencies/yjs.mjs +3 -0
  65. package/dist/utils/child-process-signals.cjs +53 -0
  66. package/dist/utils/child-process-signals.d.cts +19 -0
  67. package/dist/utils/child-process-signals.d.ts +19 -0
  68. package/dist/utils/child-process-signals.js +6 -0
  69. package/dist/utils/cli-logger.cjs +1 -1
  70. package/dist/utils/cli-logger.js +2 -2
  71. package/dist/utils/license-status.cjs +78 -45
  72. package/dist/utils/license-status.d.cts +15 -5
  73. package/dist/utils/license-status.d.ts +15 -5
  74. package/dist/utils/license-status.js +1 -1
  75. package/eventcatalog/astro.config.mjs +23 -1
  76. package/eventcatalog/integrations/config-loader.mjs +56 -58
  77. package/eventcatalog/integrations/skip-startup-reload.mjs +31 -0
  78. package/eventcatalog/integrations/stable-dependency-order.mjs +29 -0
  79. package/eventcatalog/integrations/storage.mjs +20 -0
  80. package/eventcatalog/integrations/studio-server.mjs +32 -0
  81. package/eventcatalog/src/components/CatalogGraph/CatalogForceGraph.tsx +39 -0
  82. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +2 -0
  83. package/eventcatalog/src/components/Header.astro +3 -3
  84. package/eventcatalog/src/components/Homepage/CatalogDashboard.astro +342 -0
  85. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +60 -4
  86. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -1
  87. package/eventcatalog/src/components/NavigationProgress.astro +7 -0
  88. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +2 -0
  89. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +2 -0
  90. package/eventcatalog/src/components/SchemaExplorer/SchemaCodeModal.tsx +2 -0
  91. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -0
  92. package/eventcatalog/src/components/Search/SearchDataLoader.astro +16 -28
  93. package/eventcatalog/src/components/Search/SearchModal.tsx +2 -10
  94. package/eventcatalog/src/components/Search/search-utils.ts +26 -0
  95. package/eventcatalog/src/components/Seo.astro +5 -1
  96. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +53 -48
  97. package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +183 -178
  98. package/eventcatalog/src/components/Settings/LicenseSettings.tsx +140 -31
  99. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +40 -35
  100. package/eventcatalog/src/components/Settings/LogoUpload.tsx +1 -1
  101. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +9 -8
  102. package/eventcatalog/src/components/Settings/Row.tsx +7 -4
  103. package/eventcatalog/src/components/Settings/SettingsShared.tsx +3 -3
  104. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +53 -83
  105. package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +2 -0
  106. package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +131 -0
  107. package/eventcatalog/src/components/SideNav/SideNav.astro +9 -1
  108. package/eventcatalog/src/components/TrialBadge.astro +20 -9
  109. package/eventcatalog/src/content.config.ts +19 -2
  110. package/eventcatalog/src/features/auth/error.astro +4 -2
  111. package/eventcatalog/src/features/auth/login.astro +2 -1
  112. package/eventcatalog/src/features/auth/middleware/middleware-auth.ts +10 -0
  113. package/eventcatalog/src/features/auth/unauthorized.astro +1 -1
  114. package/eventcatalog/src/features/fields/pages/fields.astro +1 -1
  115. package/eventcatalog/src/features/integrations/eventcatalog-features.ts +34 -1
  116. package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +6 -45
  117. package/eventcatalog/src/features/mcp/apps/canvas/shared.ts +47 -0
  118. package/eventcatalog/src/features/mcp/apps/canvas/styles.css +24 -0
  119. package/eventcatalog/src/features/mcp/apps/canvas/view.tsx +278 -0
  120. package/eventcatalog/src/features/mcp/apps/generated/canvas.html +272 -0
  121. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +65 -65
  122. package/eventcatalog/src/features/mcp/apps/shared/app-view.tsx +2 -1
  123. package/eventcatalog/src/features/mcp/mcp-apps.ts +6 -3
  124. package/eventcatalog/src/features/mcp/mcp-server.ts +36 -5
  125. package/eventcatalog/src/features/server/start.ts +25 -0
  126. package/eventcatalog/src/features/storage/database.ts +88 -0
  127. package/eventcatalog/src/features/storage/migrations.ts +85 -0
  128. package/eventcatalog/src/features/storage/sql/database.sql +5 -0
  129. package/eventcatalog/src/features/storage/sql/migrations/0001-studio-canvases.sql +12 -0
  130. package/eventcatalog/src/features/storage/sql/migrations.sql +15 -0
  131. package/eventcatalog/src/features/storage/sql.ts +28 -0
  132. package/eventcatalog/src/features/studio/agent-choreography.ts +384 -0
  133. package/eventcatalog/src/features/studio/agents.ts +28 -0
  134. package/eventcatalog/src/features/studio/api/canvases-api.ts +219 -0
  135. package/eventcatalog/src/features/studio/api/canvases.ts +25 -0
  136. package/eventcatalog/src/features/studio/api/client.ts +40 -0
  137. package/eventcatalog/src/features/studio/canvas-actions.ts +540 -0
  138. package/eventcatalog/src/features/studio/canvas-preview.ts +52 -0
  139. package/eventcatalog/src/features/studio/catalog-resources.ts +155 -0
  140. package/eventcatalog/src/features/studio/catalog.ts +173 -0
  141. package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +518 -0
  142. package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +118 -0
  143. package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +434 -0
  144. package/eventcatalog/src/features/studio/components/ConnectionsChooser.tsx +143 -0
  145. package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +65 -0
  146. package/eventcatalog/src/features/studio/components/Dialog.tsx +60 -0
  147. package/eventcatalog/src/features/studio/components/JoinForm.tsx +109 -0
  148. package/eventcatalog/src/features/studio/components/LeftPanel.tsx +206 -0
  149. package/eventcatalog/src/features/studio/components/NodeDetails.tsx +183 -0
  150. package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +79 -0
  151. package/eventcatalog/src/features/studio/components/Presence.tsx +293 -0
  152. package/eventcatalog/src/features/studio/components/ShareDialog.tsx +396 -0
  153. package/eventcatalog/src/features/studio/components/ShortcutsDialog.tsx +41 -0
  154. package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +2091 -0
  155. package/eventcatalog/src/features/studio/components/StudioNotice.astro +24 -0
  156. package/eventcatalog/src/features/studio/document-name.ts +7 -0
  157. package/eventcatalog/src/features/studio/from-visualiser.ts +138 -0
  158. package/eventcatalog/src/features/studio/hooks/presence-sender.ts +63 -0
  159. package/eventcatalog/src/features/studio/hooks/presence-store.ts +119 -0
  160. package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +353 -0
  161. package/eventcatalog/src/features/studio/hooks/use-comments.ts +54 -0
  162. package/eventcatalog/src/features/studio/hooks/use-follow-camera.ts +109 -0
  163. package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +782 -0
  164. package/eventcatalog/src/features/studio/identity.ts +59 -0
  165. package/eventcatalog/src/features/studio/limits.ts +2 -0
  166. package/eventcatalog/src/features/studio/pages/[id].astro +69 -0
  167. package/eventcatalog/src/features/studio/pages/index.astro +784 -0
  168. package/eventcatalog/src/features/studio/pages/webmcp-relay.ts +27 -0
  169. package/eventcatalog/src/features/studio/server/canvas-mcp.ts +495 -0
  170. package/eventcatalog/src/features/studio/server/runtime.ts +498 -0
  171. package/eventcatalog/src/features/studio/server/sign-in.ts +18 -0
  172. package/eventcatalog/src/features/studio/server/sql/storage.sql +18 -0
  173. package/eventcatalog/src/features/studio/server/storage.ts +90 -0
  174. package/eventcatalog/src/features/studio/server/tool-icons.ts +30 -0
  175. package/eventcatalog/src/features/studio/tool-sync.ts +75 -0
  176. package/eventcatalog/src/layouts/BaseLayout.astro +4 -4
  177. package/eventcatalog/src/layouts/SettingsLayout.astro +2 -2
  178. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +13 -5
  179. package/eventcatalog/src/pages/_index.astro +5 -342
  180. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.spec.ts +2 -3
  181. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +0 -7
  182. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -1
  183. package/eventcatalog/src/pages/diagrams/[id]/[version]/_index.data.ts +0 -7
  184. package/eventcatalog/src/pages/diagrams/[id]/[version]/embed.astro +1 -0
  185. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +1 -0
  186. package/eventcatalog/src/pages/directory/[type]/_index.data.ts +5 -7
  187. package/eventcatalog/src/pages/directory/[type]/index.astro +3 -1
  188. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -7
  189. package/eventcatalog/src/pages/discover/[type]/index.astro +3 -1
  190. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +0 -7
  191. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -0
  192. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +0 -7
  193. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -0
  194. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +0 -7
  195. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +3 -1
  196. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/_[filename].data.ts +0 -7
  197. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +0 -7
  198. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +1 -0
  199. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +1 -0
  200. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/_[...filename].data.ts +0 -4
  201. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/_index.data.ts +0 -7
  202. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/index.astro +1 -0
  203. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +3 -1
  204. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/_[filename].data.ts +0 -7
  205. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +1 -0
  206. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.spec.ts +2 -3
  207. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +0 -7
  208. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +1 -0
  209. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +1 -0
  210. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/_[filename].data.ts +0 -7
  211. package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +0 -7
  212. package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +2 -1
  213. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/_index.data.ts +0 -7
  214. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +1 -0
  215. package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +0 -7
  216. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +1 -0
  217. package/eventcatalog/src/pages/docs/custom/[...path]/_index.data.ts +0 -7
  218. package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +1 -0
  219. package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +1 -1
  220. package/eventcatalog/src/pages/docs/services/[id]/[version]/resources/index.astro +1 -0
  221. package/eventcatalog/src/pages/docs/services/[id]/asyncapi/[filename].astro +1 -1
  222. package/eventcatalog/src/pages/docs/services/[id]/changelog/index.astro +1 -1
  223. package/eventcatalog/src/pages/docs/services/[id]/graphql/[filename].astro +1 -1
  224. package/eventcatalog/src/pages/docs/services/[id]/spec/[filename].astro +1 -1
  225. package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +0 -7
  226. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +1 -0
  227. package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +0 -7
  228. package/eventcatalog/src/pages/docs/users/[id]/index.astro +1 -0
  229. package/eventcatalog/src/pages/index.astro +4 -2
  230. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +0 -7
  231. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +1 -0
  232. package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +0 -7
  233. package/eventcatalog/src/pages/schemas/explorer/index.astro +4 -2
  234. package/eventcatalog/src/pages/settings/license.astro +9 -1
  235. package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/_index.data.ts +0 -7
  236. package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +1 -0
  237. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +0 -7
  238. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/_index.data.ts +0 -7
  239. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +1 -0
  240. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/_index.data.ts +0 -7
  241. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -0
  242. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -0
  243. package/eventcatalog/src/pages/visualiser/[type]/[id]/_index.data.ts +38 -0
  244. package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +18 -41
  245. package/eventcatalog/src/pages/visualiser/designs/[id]/_index.data.ts +0 -7
  246. package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -1
  247. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/_index.data.ts +0 -7
  248. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -0
  249. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +1 -0
  250. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +0 -7
  251. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +1 -0
  252. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +0 -7
  253. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +1 -0
  254. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +1 -0
  255. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +10 -0
  256. package/eventcatalog/src/utils/collections/util.ts +8 -4
  257. package/eventcatalog/src/utils/feature.ts +8 -0
  258. package/eventcatalog/src/utils/git.ts +22 -5
  259. package/eventcatalog/src/utils/homepage-dashboard.ts +143 -0
  260. package/eventcatalog/src/utils/license.ts +1 -1
  261. package/eventcatalog/src/utils/link-validation.ts +25 -19
  262. package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +3 -1
  263. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +3 -3
  264. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +0 -2
  265. package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +4 -2
  266. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +20 -1
  267. package/eventcatalog/src/utils/node-graphs/node-resource.ts +67 -0
  268. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +1 -1
  269. package/eventcatalog/src/utils/page-loaders/hybrid-page.ts +4 -15
  270. package/eventcatalog/src/utils/page-title.ts +15 -0
  271. package/eventcatalog/src/utils/syntax-highlighter-renderer.ts +64 -0
  272. package/eventcatalog/src/utils/trial.ts +14 -1
  273. package/package.json +19 -13
  274. package/dist/runtime-dependencies/shelljs.mjs +0 -3
  275. package/eventcatalog/public/studio-bg.png +0 -0
  276. package/eventcatalog/src/components/Studio/StudioPageModal.tsx +0 -150
  277. package/eventcatalog/src/pages/studio.astro +0 -316
@@ -84,7 +84,8 @@ export function useMcpAppView<Payload>(options: McpAppViewOptions<Payload>) {
84
84
  setHostContext(context);
85
85
  }, [app]);
86
86
 
87
- return { app, payload, error: connectionError?.message ?? error, hostContext };
87
+ // setPayload: views that switch what they show themselves (e.g. picking a canvas) without a new tool result
88
+ return { app, payload, setPayload, error: connectionError?.message ?? error, hostContext };
88
89
  }
89
90
 
90
91
  /** Adds the view's styles and renders it */
@@ -12,7 +12,7 @@ const mcpAppViews = import.meta.glob<string>('./apps/generated/*.html', { query:
12
12
  export const getMcpAppViewLoader = (name: string) => mcpAppViews[`./apps/generated/${name}.html`];
13
13
 
14
14
  /** Tool `_meta` telling MCP hosts that support MCP Apps to show the tool's result in a view */
15
- const appViewMeta = (resourceUri: string, visibility?: Array<'model' | 'app'>) => ({
15
+ export const appViewMeta = (resourceUri: string, visibility?: Array<'model' | 'app'>) => ({
16
16
  ui: { resourceUri, ...(visibility && { visibility }) },
17
17
  [RESOURCE_URI_META_KEY]: resourceUri,
18
18
  });
@@ -38,6 +38,8 @@ type ToolDefinition<Shape extends z.ZodRawShape> = {
38
38
  description: string;
39
39
  /** The tool's arguments, as a Zod shape */
40
40
  input: Shape;
41
+ /** More `_meta` for the tool, e.g. host extensions such as ChatGPT's `openai/ui` entrypoints */
42
+ meta?: Record<string, unknown>;
41
43
  };
42
44
 
43
45
  export type McpAppDefinition<Shape extends z.ZodRawShape, ViewShape extends z.ZodRawShape, Payload> = {
@@ -47,7 +49,8 @@ export type McpAppDefinition<Shape extends z.ZodRawShape, ViewShape extends z.Zo
47
49
  name: string;
48
50
  uri: string;
49
51
  description: string;
50
- csp?: { resourceDomains: string[] };
52
+ /** Origins the view may load from (resourceDomains) and connect to with fetch or WebSockets (connectDomains) */
53
+ csp?: { resourceDomains?: string[]; connectDomains?: string[] };
51
54
  /** How hosts open the view: ChatGPT reads these before loading it, so it can open straight in that mode */
52
55
  displayModes?: { preferred: McpUiDisplayMode; available: McpUiDisplayMode[] };
53
56
  };
@@ -110,7 +113,7 @@ export function registerMcpApp<Shape extends z.ZodRawShape, ViewShape extends z.
110
113
  description: app.tool.description,
111
114
  inputSchema: toolInput,
112
115
  annotations: app.annotations,
113
- _meta: loadView ? appViewMeta(app.resource.uri) : undefined,
116
+ _meta: loadView ? { ...appViewMeta(app.resource.uri), ...app.tool.meta } : undefined,
114
117
  },
115
118
  showInView
116
119
  );
@@ -22,6 +22,9 @@ import { RESOURCE_VIEWS, VIEWER_META_KEY, VIEWER_RESOURCE_URI, VIEWER_VIEW_TOOL,
22
22
  import { toSchemaViewerSchemas } from './schema-viewer';
23
23
  import { getMcpAppViewLoader, mcpAppNote, registerMcpApp } from './mcp-apps';
24
24
  import { buildUrl } from '@utils/url-builder';
25
+ import { isCanvasEnabled } from '@utils/feature';
26
+ import { CANVAS_TOOL_NAMES, registerCanvasTools } from '@features/studio/server/canvas-mcp';
27
+ import { startStudio } from '@features/studio/server/runtime';
25
28
 
26
29
  const loadViewerView = getMcpAppViewLoader('viewer');
27
30
 
@@ -36,6 +39,10 @@ const SHOW_RESOURCE_DESCRIPTION = [
36
39
  type McpServerOptions = {
37
40
  /** Where this EventCatalog is served, for links from MCP App views back to it */
38
41
  catalogUrl: string;
42
+ /** The MCP client's user agent, to name agents that join a canvas */
43
+ userAgent?: string;
44
+ /** Offer the canvas tools (by default when Studio is on, for the whole catalog) */
45
+ canvases?: boolean;
39
46
  };
40
47
 
41
48
  const catalogDirectory = process.env.PROJECT_DIR || process.cwd();
@@ -115,7 +122,10 @@ function getServerInstructions(scope?: McpScope) {
115
122
  }
116
123
 
117
124
  // Create MCP Server with tools that access Astro collections
118
- function createMcpServer(scope: McpScope | undefined, { catalogUrl }: McpServerOptions) {
125
+ function createMcpServer(
126
+ scope: McpScope | undefined,
127
+ { catalogUrl, userAgent, canvases = !scope && isCanvasEnabled() }: McpServerOptions
128
+ ) {
119
129
  const server = new McpServer(
120
130
  {
121
131
  name: scope ? `EventCatalog MCP Server — ${scope.name} ${scope.ref.kind}` : 'EventCatalog MCP Server',
@@ -396,7 +406,7 @@ function createMcpServer(scope: McpScope | undefined, { catalogUrl }: McpServerO
396
406
  if (resource.error !== undefined) return { error: resource.error };
397
407
 
398
408
  const schemas = await tools.getSchemaForResource({ ...params, resourceVersion: resource.version });
399
- if ('error' in schemas) return schemas;
409
+ if ('error' in schemas && schemas.error !== undefined) return { error: schemas.error };
400
410
 
401
411
  return {
402
412
  resource: {
@@ -831,6 +841,9 @@ function createMcpServer(scope: McpScope | undefined, { catalogUrl }: McpServerO
831
841
  );
832
842
  }
833
843
 
844
+ // Collaborative canvases (when the collaboration server runs in this process)
845
+ if (canvases) registerCanvasTools(server, { catalogUrl, userAgent });
846
+
834
847
  return server;
835
848
  }
836
849
 
@@ -964,7 +977,9 @@ const handleGetRequest = async (c: Context, kind?: McpScopeKind) => {
964
977
  version: MCP_SERVER_VERSION,
965
978
  status: 'running',
966
979
  ...(scope && { scope: scope.ref }),
967
- tools: scope ? getScopedBuiltInTools(scope) : [...globalBuiltInTools, ...extendedToolNames],
980
+ tools: scope
981
+ ? getScopedBuiltInTools(scope)
982
+ : [...globalBuiltInTools, ...(isCanvasEnabled() ? CANVAS_TOOL_NAMES : []), ...extendedToolNames],
968
983
  extendedTools: !scope && extendedToolNames.length > 0 ? extendedToolNames : undefined,
969
984
  resources: getMcpResourceUris(scope),
970
985
  });
@@ -983,7 +998,23 @@ const handleMcpRequest = async (c: Context, kind?: McpScopeKind) => {
983
998
  }
984
999
 
985
1000
  const scope = await resolveRequestScope(c, kind);
986
- const server = createMcpServer(scope, { catalogUrl: new URL(c.req.url).origin });
1001
+ // Canvas tools work on Studio's canvases: started (storage loaded) before they're listed, and left out when
1002
+ // Studio isn't available (the rest of the catalog's tools still work)
1003
+ const canvases =
1004
+ !scope &&
1005
+ isCanvasEnabled() &&
1006
+ (await startStudio().then(
1007
+ () => true,
1008
+ (error) => {
1009
+ console.error(`[studio] Canvas tools are off: ${(error as Error).message}`);
1010
+ return false;
1011
+ }
1012
+ ));
1013
+ const server = createMcpServer(scope, {
1014
+ catalogUrl: new URL(c.req.url).origin,
1015
+ userAgent: c.req.header('user-agent'),
1016
+ canvases,
1017
+ });
987
1018
  const transport = new WebStandardStreamableHTTPServerTransport({
988
1019
  sessionIdGenerator: undefined,
989
1020
  });
@@ -1023,7 +1054,7 @@ app.post('/', (c: Context) => handleMcpRequest(c));
1023
1054
 
1024
1055
  // Astro API route handler - delegates all requests to Hono
1025
1056
  // Note: SSR checks are handled at build time by the integration
1026
- // This route is only injected when isEventCatalogMCPEnabled() returns true
1057
+ // This route is only injected when isEventCatalogMCPEnabled() or isCanvasEnabled() returns true
1027
1058
  export const ALL: APIRoute = async ({ request }) => {
1028
1059
  return app.fetch(request);
1029
1060
  };
@@ -0,0 +1,25 @@
1
+ import type { APIRoute } from 'astro';
2
+ import { isCanvasEnabled } from '@utils/feature';
3
+ import { startStorage } from '../storage/database';
4
+ import { startStudio } from '../studio/server/runtime';
5
+ import { isSignedIn } from '../studio/server/sign-in';
6
+
7
+ /**
8
+ * What the server starts before anyone asks for it: `eventcatalog start` calls this once the server listens. Each
9
+ * feature that needs starting has its own start function, called here in order: the storage configured is opened and
10
+ * migrated first (features keep their state in it), then Studio (so tabs reconnecting after a restart find it
11
+ * ready). Under /_eventcatalog, which sign-in lets through (the server calls it without a session); it says nothing
12
+ * about what's stored.
13
+ */
14
+ export const GET: APIRoute = async () => {
15
+ try {
16
+ await startStorage();
17
+ } catch (error) {
18
+ console.error(`[eventcatalog] Could not open the database: ${(error as Error).message}`);
19
+ }
20
+ // Studio says why if it can't start
21
+ if (isCanvasEnabled()) await startStudio({ isSignedIn }).catch(() => {});
22
+ return new Response(null, { status: 204 });
23
+ };
24
+
25
+ export const prerender = false;
@@ -0,0 +1,88 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import config from '../../utils/eventcatalog-config/source';
4
+ import type { Config } from '../../../../src/eventcatalog.config';
5
+ import { migrate, type Database } from './migrations';
6
+ import { namedStatements } from './sql';
7
+ import databaseSql from './sql/database.sql?raw';
8
+
9
+ /** `storage` in eventcatalog.config.js: memory (the default), or one SQLite database for the whole catalog */
10
+ export type StorageConfig = NonNullable<Config['storage']>;
11
+ export type StorageType = StorageConfig['type'];
12
+ export type { Database };
13
+
14
+ export const DEFAULT_STORAGE: StorageConfig = { type: 'memory' };
15
+ const DEFAULT_DATABASE_PATH = '.eventcatalog/eventcatalog.db';
16
+
17
+ const SQL = namedStatements(databaseSql, ['useWriteAheadLog']);
18
+
19
+ /** The database file a config asks for (relative to the catalog), or undefined when state is kept in memory */
20
+ export const getDatabasePath = (storage: StorageConfig | undefined, projectDirectory: string) => {
21
+ const chosen = storage ?? DEFAULT_STORAGE;
22
+ switch (chosen.type) {
23
+ case 'memory':
24
+ return undefined;
25
+ case 'sqlite':
26
+ return path.resolve(projectDirectory, chosen.path ?? DEFAULT_DATABASE_PATH);
27
+ default:
28
+ throw new Error(`Unknown storage type "${(chosen as { type?: string }).type}": use "memory" or "sqlite"`);
29
+ }
30
+ };
31
+
32
+ const open = async (file: string): Promise<Database> => {
33
+ // Node's built-in SQLite (no native package to install), asked of Node itself: the dev server loads this through
34
+ // Vite, which doesn't know node:sqlite and fails to import it
35
+ type Sqlite = { DatabaseSync: new (file: string) => Database };
36
+ const getBuiltinModule = (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule;
37
+ let sqlite: Sqlite | undefined;
38
+ try {
39
+ sqlite = getBuiltinModule
40
+ ? (getBuiltinModule('node:sqlite') as Sqlite | undefined)
41
+ : await import(/* @vite-ignore */ ['node', 'sqlite'].join(':'));
42
+ } catch (error) {
43
+ throw new Error(`Could not load node:sqlite (${(error as Error).message})`);
44
+ }
45
+ if (!sqlite?.DatabaseSync) {
46
+ throw new Error(
47
+ `SQLite storage needs Node.js 22.13 or later (it uses node:sqlite); this is Node.js ${process.versions.node}`
48
+ );
49
+ }
50
+ fs.mkdirSync(path.dirname(file), { recursive: true });
51
+ const database = new sqlite.DatabaseSync(file);
52
+ database.exec(SQL.useWriteAheadLog);
53
+ migrate(database);
54
+ return database;
55
+ };
56
+
57
+ // Opened once per process, by file (kept on globalThis: the dev server's integrations and the app load this module
58
+ // separately, and code reloads in dev keep globalThis)
59
+ const DATABASES = Symbol.for('eventcatalog.databases');
60
+ const store = globalThis as typeof globalThis & { [DATABASES]?: Map<string, Promise<Database>> };
61
+
62
+ /**
63
+ * The database in `file`, brought up to date by the migrations: opened the first time it's asked for, then shared by
64
+ * every feature. Rejects (every time) if it can't be opened or migrated, e.g. when a newer EventCatalog updated it.
65
+ */
66
+ export const openDatabase = (file: string): Promise<Database> => {
67
+ const databases = (store[DATABASES] ??= new Map());
68
+ let database = databases.get(file);
69
+ if (!database) {
70
+ database = open(file);
71
+ databases.set(file, database);
72
+ }
73
+ return database;
74
+ };
75
+
76
+ /**
77
+ * Opens the storage configured, running the migrations it needs. Called as the dev server and `eventcatalog start`
78
+ * start (not on build: builds often run somewhere other than where the database lives), so it's ready before any
79
+ * feature uses it. Returns the database file, or undefined when state is kept in memory.
80
+ */
81
+ export const startStorage = async (projectDirectory = process.env.PROJECT_DIR || process.cwd()) => {
82
+ if ((config as { studio?: { storage?: unknown } }).studio?.storage) {
83
+ console.warn('[eventcatalog] studio.storage is no longer used: set storage in eventcatalog.config.js instead');
84
+ }
85
+ const file = getDatabasePath(config.storage, projectDirectory);
86
+ if (file) await openDatabase(file);
87
+ return file;
88
+ };
@@ -0,0 +1,85 @@
1
+ import { namedStatements } from './sql';
2
+ import runnerSql from './sql/migrations.sql?raw';
3
+
4
+ /**
5
+ * Changes to the database's schema, for every feature that keeps state, as .sql files in ./sql/migrations named
6
+ * `NNNN-what-it-does.sql` (one numbered order for the whole catalog; tables are named for their feature, e.g.
7
+ * `studio_canvases`). They run in order when the database opens, each once, recorded in its `migrations` table. To
8
+ * change the schema, add a file with the next number: never change one that has shipped, since databases out there have
9
+ * already run it.
10
+ */
11
+ export type Migration = { version: number; name: string; sql: string };
12
+
13
+ /** The parts of node:sqlite's DatabaseSync EventCatalog uses */
14
+ export type Database = {
15
+ exec: (sql: string) => void;
16
+ prepare: (sql: string) => { run: (...values: unknown[]) => unknown; all: () => unknown[] };
17
+ };
18
+
19
+ // Built into the server code (no files to find at runtime, wherever it's deployed)
20
+ const files = import.meta.glob<string>('./sql/migrations/*.sql', { query: '?raw', import: 'default', eager: true });
21
+ const SQL = namedStatements(runnerSql, ['createMigrationsTable', 'appliedVersions', 'recordMigration']);
22
+
23
+ /** Migrations from their files, in order (an error if a file is misnamed or two have the same number) */
24
+ export const toMigrations = (sources: Record<string, string>): Migration[] => {
25
+ const migrations = Object.entries(sources).map(([file, sql]) => {
26
+ const name = file
27
+ .split('/')
28
+ .pop()!
29
+ .replace(/\.sql$/, '');
30
+ const version = Number(/^(\d{4})-[a-z0-9-]+$/.exec(name)?.[1]);
31
+ if (!version) throw new Error(`Migration "${file}" should be named like 0003-what-it-does.sql`);
32
+ return { version, name, sql };
33
+ });
34
+ migrations.sort((a, b) => a.version - b.version);
35
+ migrations.forEach((migration, index) => {
36
+ if (migration.version !== index + 1) {
37
+ throw new Error(`Migrations should be numbered 1, 2, 3...: expected ${index + 1} before ${migration.name}`);
38
+ }
39
+ });
40
+ return migrations;
41
+ };
42
+
43
+ export const MIGRATIONS = toMigrations(files);
44
+
45
+ /**
46
+ * The database was updated by a newer EventCatalog. Features don't fall back to memory for this (changes would quietly
47
+ * stop being saved): they aren't available until EventCatalog is updated. Told by its code, as the dev server's
48
+ * integrations and the app load this module separately.
49
+ */
50
+ const DATABASE_TOO_NEW = 'EVENTCATALOG_DATABASE_TOO_NEW';
51
+ export const isDatabaseTooNew = (error: unknown) => (error as { code?: unknown } | null)?.code === DATABASE_TOO_NEW;
52
+
53
+ /**
54
+ * Brings a database up to date: runs the migrations it hasn't run yet, each in a transaction (all of it or none).
55
+ * Refuses a database that has run migrations this version doesn't know (made by a newer EventCatalog).
56
+ */
57
+ export const migrate = (database: Database, migrations: Migration[] = MIGRATIONS) => {
58
+ database.exec(SQL.createMigrationsTable);
59
+ const applied = new Set(
60
+ (database.prepare(SQL.appliedVersions).all() as { version: number }[]).map((row) => Number(row.version))
61
+ );
62
+ const latest = migrations.at(-1)?.version ?? 0;
63
+ const newer = [...applied].filter((version) => version > latest);
64
+ if (newer.length) {
65
+ throw Object.assign(
66
+ new Error(
67
+ `The EventCatalog database has been updated by a newer EventCatalog (migration ${Math.max(...newer)}; this version knows up to ${latest}). Update EventCatalog to use it.`
68
+ ),
69
+ { code: DATABASE_TOO_NEW }
70
+ );
71
+ }
72
+ const record = database.prepare(SQL.recordMigration);
73
+ for (const migration of migrations) {
74
+ if (applied.has(migration.version)) continue;
75
+ database.exec('BEGIN');
76
+ try {
77
+ database.exec(migration.sql);
78
+ record.run(migration.version, migration.name, Date.now());
79
+ database.exec('COMMIT');
80
+ } catch (error) {
81
+ database.exec('ROLLBACK');
82
+ throw new Error(`Could not run migration ${migration.name}: ${(error as Error).message}`);
83
+ }
84
+ }
85
+ };
@@ -0,0 +1,5 @@
1
+ -- Statements run as the database opens (see database.ts), each named by the `-- name:` line above it.
2
+
3
+ -- name: useWriteAheadLog
4
+ -- Readers don't wait for writers (set as the database opens: it can't be changed inside a migration's transaction)
5
+ PRAGMA journal_mode = WAL;
@@ -0,0 +1,12 @@
1
+ -- Studio's canvases: each one's whole Yjs document (Y.encodeStateAsUpdate), and when it last changed.
2
+ CREATE TABLE studio_canvases (
3
+ name TEXT PRIMARY KEY,
4
+ state BLOB NOT NULL,
5
+ updated_at INTEGER NOT NULL
6
+ );
7
+
8
+ -- Studio canvases that were deleted, so a browser that still has one open can't bring it back.
9
+ CREATE TABLE studio_deleted_canvases (
10
+ name TEXT PRIMARY KEY,
11
+ deleted_at INTEGER NOT NULL
12
+ );
@@ -0,0 +1,15 @@
1
+ -- The statements the migration runner runs (see migrations.ts), each named by the `-- name:` line above it. Its own
2
+ -- table is made here rather than in a migration: it records which migrations have run, so it's needed before any do.
3
+
4
+ -- name: createMigrationsTable
5
+ CREATE TABLE IF NOT EXISTS migrations (
6
+ version INTEGER PRIMARY KEY,
7
+ name TEXT NOT NULL,
8
+ applied_at INTEGER NOT NULL
9
+ );
10
+
11
+ -- name: appliedVersions
12
+ SELECT version FROM migrations;
13
+
14
+ -- name: recordMigration
15
+ INSERT INTO migrations (version, name, applied_at) VALUES (?, ?, ?);
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Statements kept in .sql files (./sql), each named by a `-- name: <name>` line above it. A file's statements are
3
+ * looked up by the names the code expects: a missing one is an error when the module loads, not when it's first run.
4
+ */
5
+ export const namedStatements = <Name extends string>(source: string, names: readonly Name[]): Record<Name, string> => {
6
+ const statements = new Map<string, string>();
7
+ let current: { name: string; lines: string[] } | undefined;
8
+ const finish = () => {
9
+ if (current) statements.set(current.name, current.lines.join('\n').trim());
10
+ };
11
+ for (const line of source.split('\n')) {
12
+ const name = /^--\s*name:\s*(\S+)\s*$/.exec(line)?.[1];
13
+ if (name) {
14
+ finish();
15
+ current = { name, lines: [] };
16
+ } else {
17
+ current?.lines.push(line);
18
+ }
19
+ }
20
+ finish();
21
+ return Object.fromEntries(
22
+ names.map((name) => {
23
+ const statement = statements.get(name);
24
+ if (!statement) throw new Error(`No SQL statement named "${name}"`);
25
+ return [name, statement];
26
+ })
27
+ ) as Record<Name, string>;
28
+ };