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

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-RFIXKATC.js → chunk-4G7FSRPN.js} +35 -42
  21. package/dist/{chunk-6OC46WQJ.js → chunk-55QETQZ3.js} +66 -35
  22. package/dist/{chunk-TQLRG35T.js → chunk-AD7CL772.js} +78 -45
  23. package/dist/chunk-CA6WCQ2T.js +54 -0
  24. package/dist/chunk-CPW6G62V.js +17 -0
  25. package/dist/{chunk-423S2KHN.js → chunk-FLAZ2JVN.js} +4 -2
  26. package/dist/{chunk-BH2F5WPN.js → chunk-GQI5UYXZ.js} +1 -1
  27. package/dist/{chunk-GYIVJXOJ.js → chunk-NA7OTBWW.js} +1 -1
  28. package/dist/{chunk-MDWB5HLO.js → chunk-NKNOXQ62.js} +1 -1
  29. package/dist/{chunk-3PKS2IIP.js → chunk-OX6TSVHY.js} +1 -1
  30. package/dist/{chunk-36RYTYT5.js → chunk-PD7KTSYN.js} +1 -1
  31. package/dist/chunk-S5GWAUG5.js +29 -0
  32. package/dist/{chunk-NDJOAITI.js → chunk-T3OROMAU.js} +9 -3
  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
@@ -0,0 +1,155 @@
1
+ import { getDomains } from '@utils/collections/domains';
2
+ import { getSystems } from '@utils/collections/systems';
3
+ import { getServices } from '@utils/collections/services';
4
+ import { getEvents } from '@utils/collections/events';
5
+ import { getCommands } from '@utils/collections/commands';
6
+ import { getQueries } from '@utils/collections/queries';
7
+ import { getChannels } from '@utils/collections/channels';
8
+ import { getContainers } from '@utils/collections/containers';
9
+ import { buildUrl } from '@utils/url-builder';
10
+
11
+ /** A catalog resource that can be dropped onto the canvas (latest version only) */
12
+ export type CatalogResource = {
13
+ /** `${collection}:${id}`, stored on the canvas node so relationships can be found */
14
+ key: string;
15
+ collection: string;
16
+ id: string;
17
+ version: string;
18
+ name: string;
19
+ summary?: string;
20
+ url: string;
21
+ node: { type: string; data: Record<string, unknown> };
22
+ };
23
+
24
+ /** A relationship between two catalog resources, by key */
25
+ export type CatalogRelation = { source: string; target: string; label?: string };
26
+
27
+ const keyOf = (collection: string, id: string) => `${collection}:${id}`;
28
+
29
+ /** The collection helpers hydrate references (e.g. a domain's services) into entries; their types describe references */
30
+ type HydratedEntry = { data: { id: string } };
31
+ const isHydratedEntry = (value: unknown): value is HydratedEntry => {
32
+ if (typeof value !== 'object' || value === null || !('data' in value)) return false;
33
+ const { data } = value;
34
+ return typeof data === 'object' && data !== null && 'id' in data && typeof data.id === 'string';
35
+ };
36
+ const entries = (value: unknown): HydratedEntry[] => (Array.isArray(value) ? value.filter(isHydratedEntry) : []);
37
+ const idsOf = (value: unknown) => entries(value).map((entry) => entry.data.id);
38
+
39
+ const toResource = (
40
+ collection: string,
41
+ entry: { data: { id: string; version: string; name?: string; summary?: string } },
42
+ node: CatalogResource['node']
43
+ ): CatalogResource => ({
44
+ key: keyOf(collection, entry.data.id),
45
+ collection,
46
+ id: entry.data.id,
47
+ version: entry.data.version,
48
+ name: entry.data.name ?? entry.data.id,
49
+ summary: entry.data.summary,
50
+ url: buildUrl(`/docs/${collection}/${entry.data.id}/${entry.data.version}`),
51
+ node,
52
+ });
53
+
54
+ // Visualiser node data needs plain fields (not collection entries)
55
+ const basics = ({ data }: { data: { id: string; version: string; name?: string; summary?: string } }) => ({
56
+ id: data.id,
57
+ version: data.version,
58
+ name: data.name ?? data.id,
59
+ summary: data.summary ?? '',
60
+ });
61
+
62
+ export const getCatalogResources = async (): Promise<{ resources: CatalogResource[]; relations: CatalogRelation[] }> => {
63
+ const [domains, systems, services, events, commands, queries, channels, containers] = await Promise.all([
64
+ getDomains({ getAllVersions: false }),
65
+ getSystems({ getAllVersions: false }),
66
+ getServices({ getAllVersions: false }),
67
+ getEvents({ getAllVersions: false, hydrateServices: false }),
68
+ getCommands({ getAllVersions: false, hydrateServices: false }),
69
+ getQueries({ getAllVersions: false, hydrateServices: false }),
70
+ getChannels({ getAllVersions: false }),
71
+ getContainers({ getAllVersions: false }),
72
+ ]);
73
+
74
+ const messages = [
75
+ ...events.map((entry) => ({ entry, collection: 'events', type: 'event' })),
76
+ ...commands.map((entry) => ({ entry, collection: 'commands', type: 'command' })),
77
+ ...queries.map((entry) => ({ entry, collection: 'queries', type: 'query' })),
78
+ ];
79
+ const messageCollection = new Map(messages.map(({ entry, collection }) => [entry.data.id, collection]));
80
+
81
+ const resources: CatalogResource[] = [
82
+ ...domains.map((domain) =>
83
+ toResource('domains', domain, {
84
+ type: 'context-domain',
85
+ data: {
86
+ mode: 'full',
87
+ navigable: false,
88
+ domain: basics(domain),
89
+ systemsCount: idsOf(domain.data.systems).length,
90
+ servicesCount: idsOf(domain.data.services).length,
91
+ entitiesCount: idsOf(domain.data.entities).length,
92
+ },
93
+ })
94
+ ),
95
+ ...systems.map((system) =>
96
+ toResource('systems', system, {
97
+ type: 'system',
98
+ data: {
99
+ mode: 'full',
100
+ navigable: false,
101
+ system: { ...basics(system), scope: system.data.scope },
102
+ servicesCount: idsOf(system.data.services).length,
103
+ containersCount: idsOf(system.data.containers).length,
104
+ },
105
+ })
106
+ ),
107
+ ...services.map((service) =>
108
+ toResource('services', service, { type: 'service', data: { mode: 'full', service: basics(service) } })
109
+ ),
110
+ ...messages.map(({ entry, collection, type }) =>
111
+ toResource(collection, entry, { type, data: { mode: 'full', message: basics(entry) } })
112
+ ),
113
+ ...channels.map((channel) =>
114
+ toResource('channels', channel, {
115
+ type: 'channel',
116
+ data: { mode: 'full', channel: { ...basics(channel), protocols: channel.data.protocols ?? [] } },
117
+ })
118
+ ),
119
+ ...containers.map((container) =>
120
+ toResource('containers', container, {
121
+ type: 'data',
122
+ data: { mode: 'full', data: { ...basics(container), container_type: container.data.container_type } },
123
+ })
124
+ ),
125
+ ];
126
+
127
+ const relations: CatalogRelation[] = [];
128
+ const relate = (source: string, target: string, label?: string) => relations.push({ source, target, label });
129
+
130
+ for (const domain of domains) {
131
+ for (const id of idsOf(domain.data.systems)) relate(keyOf('domains', domain.data.id), keyOf('systems', id), 'contains');
132
+ for (const id of idsOf(domain.data.services)) relate(keyOf('domains', domain.data.id), keyOf('services', id), 'contains');
133
+ }
134
+ for (const system of systems) {
135
+ for (const id of idsOf(system.data.services)) relate(keyOf('systems', system.data.id), keyOf('services', id), 'contains');
136
+ }
137
+ for (const service of services) {
138
+ const serviceKey = keyOf('services', service.data.id);
139
+ for (const id of idsOf(service.data.sends)) {
140
+ const collection = messageCollection.get(id);
141
+ if (collection) relate(serviceKey, keyOf(collection, id));
142
+ }
143
+ for (const id of idsOf(service.data.receives)) {
144
+ const collection = messageCollection.get(id);
145
+ if (collection) relate(keyOf(collection, id), serviceKey);
146
+ }
147
+ // A data store it both writes to and reads from is one connection (like the visualiser), not two on top of each other
148
+ const reads = new Set(idsOf(service.data.readsFrom));
149
+ const writes = new Set(idsOf(service.data.writesTo));
150
+ for (const id of writes) relate(serviceKey, keyOf('containers', id), reads.has(id) ? 'reads and writes' : undefined);
151
+ for (const id of reads) if (!writes.has(id)) relate(keyOf('containers', id), serviceKey);
152
+ }
153
+
154
+ return { resources, relations };
155
+ };
@@ -0,0 +1,173 @@
1
+ import type { Edge, Node } from '@xyflow/react';
2
+ import type { CatalogRelation, CatalogResource } from './catalog-resources';
3
+ import { buildNode, createEdge, layoutGraph, withGroupSizes, GROUP_TYPES, isGroupType } from '@eventcatalog/visualiser/studio';
4
+
5
+ /**
6
+ * Catalog resources on a canvas: the node for a resource, its connections to related resources already there,
7
+ * and domains and systems as containers with what they hold in the catalog.
8
+ */
9
+
10
+ export type CatalogLink = { key: string; url: string; version: string };
11
+
12
+ /** The node data for a resource, tagged with the catalog resource it came from */
13
+ export const catalogNodeData = (resource: CatalogResource) => ({
14
+ ...resource.node.data,
15
+ catalog: { key: resource.key, url: resource.url, version: resource.version } satisfies CatalogLink,
16
+ });
17
+
18
+ export const getCatalogLink = (node: Pick<Node, 'data'>) => node.data?.catalog as CatalogLink | undefined;
19
+
20
+ export const indexRelations = (relations: CatalogRelation[]) => {
21
+ const byKey = new Map<string, CatalogRelation[]>();
22
+ for (const relation of relations) {
23
+ for (const key of [relation.source, relation.target]) byKey.set(key, [...(byKey.get(key) ?? []), relation]);
24
+ }
25
+ return byKey;
26
+ };
27
+
28
+ /**
29
+ * Edges from a newly dropped resource to the related resources already on the canvas. A container doesn't get
30
+ * "contains" edges: what it contains sits inside it.
31
+ */
32
+ export const getRelatedEdges = (
33
+ resource: CatalogResource,
34
+ nodeId: string,
35
+ existing: Node[],
36
+ relationsByKey: Map<string, CatalogRelation[]>,
37
+ nodeType = resource.node.type
38
+ ): Edge[] => {
39
+ const edges: Edge[] = [];
40
+ for (const relation of relationsByKey.get(resource.key) ?? []) {
41
+ const isSource = relation.source === resource.key;
42
+ const otherKey = isSource ? relation.target : relation.source;
43
+
44
+ for (const other of existing.filter((node) => getCatalogLink(node)?.key === otherKey)) {
45
+ if (relation.label === 'contains' && (isGroupType(nodeType) || isGroupType(other.type))) continue;
46
+ const [source, target] = isSource ? [{ id: nodeId, type: nodeType }, other] : [other, { id: nodeId, type: nodeType }];
47
+ const edge = createEdge(
48
+ { source: source.id, target: target.id, sourceHandle: null, targetHandle: null },
49
+ source.type,
50
+ target.type
51
+ );
52
+ edges.push(relation.label ? { ...edge, label: relation.label } : edge);
53
+ }
54
+ }
55
+ return edges;
56
+ };
57
+
58
+ // ---- Domains and systems as containers ----
59
+
60
+ export const canBeContainer = (resource: CatalogResource) =>
61
+ resource.collection === 'domains' || resource.collection === 'systems';
62
+
63
+ export const containerTypeFor = (resource: CatalogResource) =>
64
+ resource.collection === 'domains' ? GROUP_TYPES.domain : GROUP_TYPES.system;
65
+
66
+ /** A container's data: the domain or system it stands for (an external system marked as one), and where it is in the catalog */
67
+ export const catalogGroupData = (resource: CatalogResource) => {
68
+ const key = resource.collection === 'domains' ? 'domain' : 'system';
69
+ const { scope } = (resource.node.data[key] ?? {}) as { scope?: string };
70
+ return {
71
+ [key]: {
72
+ id: resource.id,
73
+ name: resource.name,
74
+ version: resource.version,
75
+ summary: resource.summary,
76
+ ...(scope && { scope }),
77
+ },
78
+ catalog: { key: resource.key, url: resource.url, version: resource.version } satisfies CatalogLink,
79
+ };
80
+ };
81
+
82
+ /** What a domain or system contains in the catalog: a domain's systems and services, a system's services */
83
+ export const getContents = (
84
+ resource: CatalogResource,
85
+ catalog: { resourcesByKey: Map<string, CatalogResource>; relationsByKey: Map<string, CatalogRelation[]> }
86
+ ) =>
87
+ (catalog.relationsByKey.get(resource.key) ?? [])
88
+ .filter((relation) => relation.source === resource.key && relation.label === 'contains')
89
+ .map((relation) => catalog.resourcesByKey.get(relation.target))
90
+ .filter((child): child is CatalogResource => !!child);
91
+
92
+ /** A domain or system as an (empty) container, centred on a point */
93
+ export const buildContainer = (resource: CatalogResource, center: { x: number; y: number }): Node =>
94
+ buildNode(containerTypeFor(resource), catalogGroupData(resource), center);
95
+
96
+ /**
97
+ * A domain or system as a container with everything it holds in the catalog: its systems (as containers too)
98
+ * and services, and the messages and data stores of those services, so every level of detail (L1 to L3) has
99
+ * something to show. Laid out with the visualiser's layout and centred on a point, with the connections between
100
+ * them and to related resources already on the canvas. Resources already on the canvas aren't added again.
101
+ */
102
+ export const buildContainerWithContents = async (
103
+ resource: CatalogResource,
104
+ center: { x: number; y: number },
105
+ catalog: { resourcesByKey: Map<string, CatalogResource>; relationsByKey: Map<string, CatalogRelation[]> },
106
+ existing: Node[]
107
+ ): Promise<{ nodes: Node[]; edges: Edge[] }> => {
108
+ const onCanvas = new Set(existing.map((node) => getCatalogLink(node)?.key).filter(Boolean));
109
+ const root = buildContainer(resource, { x: 0, y: 0 });
110
+ const nodes: Node[] = [root];
111
+ const added = (key: string) => onCanvas.has(key) || nodes.some((node) => getCatalogLink(node)?.key === key);
112
+ const services: { resource: CatalogResource; parentId: string }[] = [];
113
+
114
+ // Its systems (as containers, with their services) and services
115
+ const fill = (parent: CatalogResource, parentId: string) => {
116
+ for (const child of getContents(parent, catalog)) {
117
+ if (added(child.key)) continue;
118
+ if (canBeContainer(child)) {
119
+ const container = { ...buildContainer(child, { x: 0, y: 0 }), parentId };
120
+ nodes.push(container);
121
+ fill(child, container.id);
122
+ } else {
123
+ nodes.push({ ...buildNode(child.node.type, catalogNodeData(child), { x: 0, y: 0 }), parentId });
124
+ if (child.collection === 'services') services.push({ resource: child, parentId });
125
+ }
126
+ }
127
+ };
128
+ fill(resource, root.id);
129
+
130
+ // The messages its services send and receive (in the domain or system dropped), and their data stores (next to them)
131
+ for (const service of services) {
132
+ for (const relation of catalog.relationsByKey.get(service.resource.key) ?? []) {
133
+ if (relation.label === 'contains') continue;
134
+ const other = catalog.resourcesByKey.get(relation.source === service.resource.key ? relation.target : relation.source);
135
+ if (!other || added(other.key) || canBeContainer(other) || other.collection === 'services') continue;
136
+ const parentId = other.collection === 'containers' ? service.parentId : root.id;
137
+ nodes.push({ ...buildNode(other.node.type, catalogNodeData(other), { x: 0, y: 0 }), parentId });
138
+ }
139
+ }
140
+
141
+ if (nodes.length === 1) return { nodes: [buildContainer(resource, center)], edges: [] };
142
+
143
+ // Connections between them, and to related resources already on the canvas
144
+ const inside: Edge[] = [];
145
+ const outside: Edge[] = [];
146
+ const placed = [...existing];
147
+ for (const node of nodes) {
148
+ const link = getCatalogLink(node);
149
+ const related = link && catalog.resourcesByKey.get(link.key);
150
+ if (related) {
151
+ for (const edge of getRelatedEdges(related, node.id, placed, catalog.relationsByKey, node.type)) {
152
+ (existing.some((other) => other.id === edge.source || other.id === edge.target) ? outside : inside).push(edge);
153
+ }
154
+ }
155
+ placed.push(node);
156
+ }
157
+
158
+ // Laid out with its connections; containers are sized to fit what's in them
159
+ const laidOut = withGroupSizes((await layoutGraph(nodes, inside)).nodes);
160
+ const top = laidOut.find((node) => node.id === root.id)!;
161
+ const offset = { x: center.x - (top.width ?? 0) / 2 - top.position.x, y: center.y - (top.height ?? 0) / 2 - top.position.y };
162
+ return {
163
+ nodes: laidOut.map((node) => {
164
+ const original = nodes.find((candidate) => candidate.id === node.id)!;
165
+ return {
166
+ ...original,
167
+ position: node.parentId ? node.position : { x: node.position.x + offset.x, y: node.position.y + offset.y },
168
+ ...(isGroupType(node.type) && { width: node.width, height: node.height }),
169
+ };
170
+ }),
171
+ edges: [...inside, ...outside],
172
+ };
173
+ };