@eventcatalog/core 4.12.2 → 5.0.0-beta.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 (268) hide show
  1. package/LICENSE +226 -95
  2. package/NOTICE +30 -0
  3. package/README.md +3 -2
  4. package/dist/analytics/analytics.cjs +1 -1
  5. package/dist/analytics/analytics.js +2 -2
  6. package/dist/analytics/log-build.cjs +43 -16
  7. package/dist/analytics/log-build.d.cts +6 -5
  8. package/dist/analytics/log-build.d.ts +6 -5
  9. package/dist/analytics/log-build.js +4 -3
  10. package/dist/{chunk-U4YJSTGV.js → chunk-AYNZXUB5.js} +2 -10
  11. package/dist/{chunk-IVVM67LN.js → chunk-CR6AK5LR.js} +1 -1
  12. package/dist/{chunk-GTIC4R74.js → chunk-LR7AGRHN.js} +13 -16
  13. package/dist/chunk-TQLRG35T.js +203 -0
  14. package/dist/{chunk-WK4J6FP3.js → chunk-TWN43V4T.js} +1 -1
  15. package/dist/{chunk-ZW3MYAWF.js → chunk-WAIADKQE.js} +1 -1
  16. package/dist/{chunk-RPVA2SZY.js → chunk-ZHKEARLJ.js} +1 -1
  17. package/dist/constants.cjs +1 -1
  18. package/dist/constants.js +1 -1
  19. package/dist/eventcatalog.cjs +407 -291
  20. package/dist/eventcatalog.config.d.cts +2 -3
  21. package/dist/eventcatalog.config.d.ts +2 -3
  22. package/dist/eventcatalog.js +30 -93
  23. package/dist/federation/content-cache.d.cts +0 -5
  24. package/dist/federation/content-cache.d.ts +0 -5
  25. package/dist/federation/diagnostics.d.cts +0 -5
  26. package/dist/federation/diagnostics.d.ts +0 -5
  27. package/dist/federation/federate.cjs +0 -9
  28. package/dist/federation/federate.d.cts +0 -5
  29. package/dist/federation/federate.d.ts +0 -5
  30. package/dist/federation/federate.js +2 -3
  31. package/dist/federation/filesystem-source-provider.d.cts +0 -5
  32. package/dist/federation/filesystem-source-provider.d.ts +0 -5
  33. package/dist/federation/github-source-provider.d.cts +0 -5
  34. package/dist/federation/github-source-provider.d.ts +0 -5
  35. package/dist/federation/output-transaction.d.cts +0 -4
  36. package/dist/federation/output-transaction.d.ts +0 -4
  37. package/dist/federation/public-assets.d.cts +0 -5
  38. package/dist/federation/public-assets.d.ts +0 -5
  39. package/dist/federation/source-provider.d.cts +0 -5
  40. package/dist/federation/source-provider.d.ts +0 -5
  41. package/dist/federation/types.d.cts +0 -5
  42. package/dist/federation/types.d.ts +0 -5
  43. package/dist/generate.cjs +1 -1
  44. package/dist/generate.js +3 -3
  45. package/dist/license-C1y-56bb.d.cts +23 -0
  46. package/dist/license-C1y-56bb.d.ts +23 -0
  47. package/dist/runtime-dependencies/@eventcatalog__visualiser__layout.mjs +3 -0
  48. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps.mjs +3 -0
  49. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps__react.mjs +3 -0
  50. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps__server.mjs +3 -0
  51. package/dist/runtime-dependencies/@modelcontextprotocol__sdk__types.js.mjs +3 -0
  52. package/dist/runtime-dependencies/manifest.json +12 -1
  53. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__graphql.mjs +3 -0
  54. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__json.mjs +3 -0
  55. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__markup.mjs +3 -0
  56. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__protobuf.mjs +3 -0
  57. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__yaml.mjs +3 -0
  58. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__styles__prism__one-dark.mjs +3 -0
  59. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__styles__prism__one-light.mjs +3 -0
  60. package/dist/utils/cli-logger.cjs +1 -1
  61. package/dist/utils/cli-logger.js +2 -2
  62. package/dist/utils/license-status.cjs +240 -0
  63. package/dist/utils/license-status.d.cts +28 -0
  64. package/dist/utils/license-status.d.ts +28 -0
  65. package/dist/utils/license-status.js +12 -0
  66. package/eventcatalog/astro.config.mjs +1 -1
  67. package/eventcatalog/integrations/eventcatalog-runtime.mjs +1 -1
  68. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +29 -19
  69. package/eventcatalog/src/components/ChatPanel/OfflineReply.tsx +74 -0
  70. package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +24 -28
  71. package/eventcatalog/src/components/FieldsExplorer/FieldNodeGraph.tsx +16 -11
  72. package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +4 -218
  73. package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +27 -36
  74. package/eventcatalog/src/components/Header.astro +43 -58
  75. package/eventcatalog/src/components/Lists/PillListFlat.styles.css +17 -17
  76. package/eventcatalog/src/components/MDX/EntityMap/EntityMap.astro +1 -1
  77. package/eventcatalog/src/components/MDX/Flow/Flow.astro +4 -0
  78. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +14 -0
  79. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +49 -18
  80. package/eventcatalog/src/components/MDX/RemoteFile.astro +2 -24
  81. package/eventcatalog/src/components/SchemaExplorer/ApiAccessSection.tsx +59 -93
  82. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +1 -32
  83. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +20 -67
  84. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -11
  85. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +11 -60
  86. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +1 -3
  87. package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +0 -3
  88. package/eventcatalog/src/components/SchemaExplorer/VersionHistoryModal.tsx +2 -9
  89. package/eventcatalog/src/components/SchemaExplorer/parse-schema.ts +46 -0
  90. package/eventcatalog/src/components/SchemaExplorer/utils.ts +11 -0
  91. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +2 -9
  92. package/eventcatalog/src/components/Settings/LicenseSettings.tsx +288 -0
  93. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +3 -19
  94. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +85 -30
  95. package/eventcatalog/src/components/Settings/SettingsShared.tsx +7 -75
  96. package/eventcatalog/src/components/SideNav/CustomDocsNav.astro +2 -2
  97. package/eventcatalog/src/components/TrialBadge.astro +82 -0
  98. package/eventcatalog/src/content.config.ts +9 -90
  99. package/eventcatalog/src/{enterprise → features}/ai/chat-api.ts +22 -34
  100. package/eventcatalog/src/{enterprise → features}/analytics/adapters/ga4.ts +0 -5
  101. package/eventcatalog/src/{enterprise → features}/analytics/adapters/gtm.ts +0 -5
  102. package/eventcatalog/src/{enterprise → features}/analytics/adapters/posthog.ts +0 -5
  103. package/eventcatalog/src/{enterprise → features}/analytics/components/AnalyticsHead.astro +2 -4
  104. package/eventcatalog/src/{enterprise → features}/analytics/components/AnalyticsTracker.astro +2 -4
  105. package/eventcatalog/src/{enterprise → features}/analytics/tracker.ts +0 -5
  106. package/eventcatalog/src/{enterprise → features}/api/catalog.ts +0 -5
  107. package/eventcatalog/src/{enterprise → features}/auth/[...auth].ts +0 -5
  108. package/eventcatalog/src/{enterprise → features}/auth/middleware/middleware-auth.ts +0 -5
  109. package/eventcatalog/src/{enterprise → features}/auth/middleware/middleware.ts +0 -5
  110. package/eventcatalog/src/{enterprise → features}/collections/custom-pages.ts +0 -5
  111. package/eventcatalog/src/{enterprise → features}/collections/index.ts +0 -5
  112. package/eventcatalog/src/{enterprise → features}/collections/resource-docs.ts +0 -5
  113. package/eventcatalog/src/{enterprise → features}/custom-documentation/collection.ts +0 -5
  114. package/eventcatalog/src/features/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +9 -0
  115. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/CustomDocsNavWrapper.tsx +0 -5
  116. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/components/NestedItem.tsx +1 -6
  117. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/components/NoResultsFound.tsx +0 -5
  118. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/index.tsx +1 -6
  119. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/types.ts +0 -5
  120. package/eventcatalog/src/{enterprise/custom-documentation/pages/docs/custom/index.astro → features/custom-documentation/components/CustomDocumentationPage.astro} +5 -5
  121. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/badge-styles.ts +0 -5
  122. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/custom-docs.ts +1 -6
  123. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/docs-search.ts +0 -5
  124. package/eventcatalog/src/{enterprise → features}/custom-pages/routes.ts +0 -5
  125. package/eventcatalog/src/{enterprise → features}/directory/user-team-directory.ts +0 -5
  126. package/eventcatalog/src/{enterprise → features}/fields/field-extractor.ts +0 -5
  127. package/eventcatalog/src/{enterprise → features}/fields/field-indexer.ts +0 -5
  128. package/eventcatalog/src/{enterprise → features}/fields/fields-db.ts +0 -5
  129. package/eventcatalog/src/{enterprise → features}/fields/pages/api/fields.ts +1 -6
  130. package/eventcatalog/src/{enterprise → features}/fields/pages/fields.astro +1 -2
  131. package/eventcatalog/src/{enterprise → features}/integrations/eventcatalog-features.ts +17 -75
  132. package/eventcatalog/src/features/mcp/apps/architecture-diagram/links.ts +59 -0
  133. package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +299 -0
  134. package/eventcatalog/src/features/mcp/apps/architecture-diagram/shared.ts +14 -0
  135. package/eventcatalog/src/features/mcp/apps/architecture-diagram/view.tsx +454 -0
  136. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +432 -0
  137. package/eventcatalog/src/features/mcp/apps/mermaid-stub.ts +10 -0
  138. package/eventcatalog/src/features/mcp/apps/schema-viewer/schema-code.tsx +65 -0
  139. package/eventcatalog/src/features/mcp/apps/schema-viewer/shared.ts +23 -0
  140. package/eventcatalog/src/features/mcp/apps/schema-viewer/view.tsx +170 -0
  141. package/eventcatalog/src/features/mcp/apps/shared/app-view.tsx +98 -0
  142. package/eventcatalog/src/features/mcp/apps/shared/resource-types.ts +15 -0
  143. package/eventcatalog/src/features/mcp/apps/viewer/shared.ts +24 -0
  144. package/eventcatalog/src/features/mcp/apps/viewer/styles.css +25 -0
  145. package/eventcatalog/src/features/mcp/apps/viewer/view.tsx +59 -0
  146. package/eventcatalog/src/features/mcp/mcp-app-icons.ts +63 -0
  147. package/eventcatalog/src/features/mcp/mcp-apps.ts +160 -0
  148. package/eventcatalog/src/{enterprise → features}/mcp/mcp-auth.ts +0 -5
  149. package/eventcatalog/src/{enterprise → features}/mcp/mcp-scope.ts +7 -7
  150. package/eventcatalog/src/{enterprise → features}/mcp/mcp-scoped-tools.ts +47 -40
  151. package/eventcatalog/src/{enterprise → features}/mcp/mcp-server.ts +347 -34
  152. package/eventcatalog/src/{enterprise → features}/mcp/oauth-protected-resource.ts +0 -5
  153. package/eventcatalog/src/features/mcp/schema-viewer.ts +24 -0
  154. package/eventcatalog/src/{enterprise → features}/tools/catalog-tools.ts +133 -102
  155. package/eventcatalog/src/features/tools/index.ts +5 -0
  156. package/eventcatalog/src/{enterprise → features}/visualizer-layout/reset.ts +0 -5
  157. package/eventcatalog/src/{enterprise → features}/visualizer-layout/save.ts +0 -5
  158. package/eventcatalog/src/layouts/BaseLayout.astro +2 -2
  159. package/eventcatalog/src/layouts/Footer.astro +31 -39
  160. package/eventcatalog/src/layouts/SettingsLayout.astro +6 -6
  161. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +7 -37
  162. package/eventcatalog/src/{enterprise → pages}/api/schemas/[collection]/[id]/[version]/index.ts +0 -22
  163. package/eventcatalog/src/{enterprise → pages}/api/schemas/services/[id]/[version]/[specification]/index.ts +0 -19
  164. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +2 -6
  165. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -5
  166. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +2 -6
  167. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -5
  168. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].md.ts +2 -6
  169. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].mdx.ts +2 -6
  170. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +9 -5
  171. package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +12 -0
  172. package/eventcatalog/src/{enterprise/custom-documentation/pages/docs/custom/root-index.astro → pages/docs/custom/index.astro} +1 -23
  173. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +4 -9
  174. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +4 -4
  175. package/eventcatalog/src/pages/docs/llm/schemas.txt.ts +0 -11
  176. package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +2 -2
  177. package/eventcatalog/src/pages/index.astro +2 -2
  178. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +0 -3
  179. package/eventcatalog/src/pages/schemas/explorer/index.astro +1 -4
  180. package/eventcatalog/src/pages/settings/assistant.astro +2 -4
  181. package/eventcatalog/src/pages/settings/license.astro +18 -0
  182. package/eventcatalog/src/pages/settings/llm-access.astro +1 -4
  183. package/eventcatalog/src/pages/settings/mcp.astro +33 -4
  184. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -2
  185. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +2 -45
  186. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -1
  187. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +7 -109
  188. package/eventcatalog/src/pages/visualiser/_mermaid-route.ts +78 -0
  189. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/_index.data.ts +44 -0
  190. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -1
  191. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +56 -0
  192. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +3 -40
  193. package/eventcatalog/src/pages/visualiser/domains/[id]/[version].mermaid.ts +20 -0
  194. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/_index.data.ts +29 -0
  195. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +3 -38
  196. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +56 -0
  197. package/eventcatalog/src/pages/visualiser/systems/[id]/[version].mermaid.ts +20 -0
  198. package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +1 -1
  199. package/eventcatalog/src/stores/sidebar-store/builders/container.ts +1 -1
  200. package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +1 -1
  201. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +7 -32
  202. package/eventcatalog/src/stores/sidebar-store/builders/entity.ts +1 -1
  203. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +1 -1
  204. package/eventcatalog/src/stores/sidebar-store/builders/service.ts +2 -8
  205. package/eventcatalog/src/stores/sidebar-store/builders/system.ts +2 -12
  206. package/eventcatalog/src/stores/sidebar-store/custom-sidebar.ts +0 -10
  207. package/eventcatalog/src/stores/sidebar-store/state.ts +4 -6
  208. package/eventcatalog/src/styles/theme.css +22 -18
  209. package/eventcatalog/src/styles/themes/forest.css +8 -8
  210. package/eventcatalog/src/styles/themes/ocean.css +8 -8
  211. package/eventcatalog/src/styles/themes/sapphire.css +8 -8
  212. package/eventcatalog/src/styles/themes/sunset.css +8 -8
  213. package/eventcatalog/src/utils/clipboard.ts +4 -4
  214. package/eventcatalog/src/utils/collections/flow-step-schema.ts +117 -0
  215. package/eventcatalog/src/utils/collections/pointer-schema.ts +7 -0
  216. package/eventcatalog/src/utils/collections/resource-docs.ts +677 -14
  217. package/eventcatalog/src/utils/collections/schema-loader.ts +0 -5
  218. package/eventcatalog/src/utils/feature.ts +14 -23
  219. package/eventcatalog/src/utils/license.ts +114 -0
  220. package/eventcatalog/src/utils/node-graphs/architecture-diagram-types.ts +32 -0
  221. package/eventcatalog/src/utils/node-graphs/architecture-diagram.ts +84 -0
  222. package/eventcatalog/src/utils/node-graphs/catalog-force-graph.ts +1 -0
  223. package/eventcatalog/src/utils/node-graphs/channel-node-graph.ts +4 -25
  224. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -39
  225. package/eventcatalog/src/utils/node-graphs/data-products-node-graph.ts +11 -27
  226. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +679 -0
  227. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +3 -20
  228. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +62 -4
  229. package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +8 -23
  230. package/eventcatalog/src/utils/node-graphs/flow-lanes.ts +119 -0
  231. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +153 -45
  232. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +28 -0
  233. package/eventcatalog/src/utils/node-graphs/layout-persistence.ts +3 -3
  234. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +16 -34
  235. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +11 -25
  236. package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +18 -54
  237. package/eventcatalog/src/utils/node-graphs/system-levels-node-graph.ts +59 -0
  238. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +20 -80
  239. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +1 -78
  240. package/eventcatalog/src/utils/trial.ts +36 -0
  241. package/eventcatalog/tsconfig.json +1 -1
  242. package/package.json +11 -11
  243. package/dist/chunk-FV56YFM4.js +0 -7
  244. package/dist/federation/entitlement.cjs +0 -31
  245. package/dist/federation/entitlement.d.cts +0 -12
  246. package/dist/federation/entitlement.d.ts +0 -12
  247. package/dist/federation/entitlement.js +0 -6
  248. package/dist/runtime-dependencies/dagre.mjs +0 -3
  249. package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +0 -265
  250. package/eventcatalog/src/enterprise/LICENSE +0 -57
  251. package/eventcatalog/src/enterprise/README.md +0 -5
  252. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +0 -691
  253. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +0 -9
  254. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/[...path]/index.astro +0 -18
  255. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/feature.astro +0 -171
  256. package/eventcatalog/src/enterprise/feature.ts +0 -75
  257. package/eventcatalog/src/enterprise/tools/index.ts +0 -10
  258. package/eventcatalog/src/hooks/eventcatalog-visualizer.ts +0 -126
  259. package/eventcatalog/src/pages/settings/billing.astro +0 -17
  260. package/eventcatalog/src/pages/visualiser/domain-integrations/index.astro +0 -26
  261. package/eventcatalog/src/types/mcp-modules.d.ts +0 -67
  262. package/eventcatalog/src/utils/node-graphs/domains-canvas.ts +0 -261
  263. package/eventcatalog/src/utils/node-graphs/export-node-graph.ts +0 -91
  264. /package/eventcatalog/src/{enterprise → features}/auth/error.astro +0 -0
  265. /package/eventcatalog/src/{enterprise → features}/auth/login.astro +0 -0
  266. /package/eventcatalog/src/{enterprise → features}/auth/unauthorized.astro +0 -0
  267. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path]/_index.data.ts +0 -0
  268. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path].mdx.ts +0 -0
@@ -0,0 +1,454 @@
1
+ /**
2
+ * The architecture diagram, shown by the EventCatalog viewer MCP App (../viewer) for showResource with
3
+ * view "architecture". Renders the EventCatalog visualiser in MCP hosts that support MCP Apps (e.g. Claude,
4
+ * ChatGPT, VS Code). Hosts without MCP Apps support show the tool's Mermaid text instead.
5
+ */
6
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
+ import { NodeGraph } from '@eventcatalog/visualiser';
8
+ import { ArrowLeft, ExternalLink, Maximize2, Minimize2 } from 'lucide-react';
9
+ // Expects Tailwind's base reset, which the viewer's stylesheet includes (as EventCatalog pages do)
10
+ import visualiserStyles from '@eventcatalog/visualiser/styles.css?inline';
11
+ import type { App, McpUiHostContext } from '@modelcontextprotocol/ext-apps';
12
+ import type { Node } from '@xyflow/react';
13
+ import type { ArchitectureDiagramPayload } from './shared';
14
+ import { NodeChat, describeNode, describeNodeForModel, type SelectedNode } from './node-chat';
15
+ import { parseAskLink, parseDiagramLink, withAskMenuItem, type DiagramLink } from './links';
16
+ import { getToolResultPayload } from '../shared/app-view';
17
+ import { RESOURCE_TYPE_LABELS } from '../shared/resource-types';
18
+ import { VIEWER_META_KEY, VIEWER_VIEW_TOOL, type ViewerPayload } from '../viewer/shared';
19
+
20
+ const INLINE_HEIGHT = 560;
21
+
22
+ // Styles for the view's own header and question modal
23
+ const viewStyles = `
24
+ body {
25
+ background: rgb(var(--ec-page-bg));
26
+ color: rgb(var(--ec-page-text));
27
+ font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
28
+ }
29
+ .ec-mcp-header {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: space-between;
33
+ gap: 12px;
34
+ padding: 8px 12px;
35
+ border-bottom: 1px solid rgb(var(--ec-page-border));
36
+ background: rgb(var(--ec-page-bg));
37
+ }
38
+ .ec-mcp-title { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13px; }
39
+ .ec-mcp-type {
40
+ flex-shrink: 0;
41
+ padding: 1px 6px;
42
+ border-radius: 4px;
43
+ background: rgb(var(--ec-accent-subtle));
44
+ color: rgb(var(--ec-accent));
45
+ font-size: 10px;
46
+ font-weight: 600;
47
+ letter-spacing: 0.04em;
48
+ text-transform: uppercase;
49
+ }
50
+ .ec-mcp-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
51
+ .ec-mcp-version { flex-shrink: 0; color: rgb(var(--ec-page-text-muted)); font-size: 12px; }
52
+ .ec-mcp-actions { display: flex; gap: 6px; flex-shrink: 0; }
53
+ .ec-mcp-button {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ gap: 6px;
57
+ height: 28px;
58
+ padding: 0 10px;
59
+ border: 1px solid rgb(var(--ec-page-border));
60
+ border-radius: 6px;
61
+ background: rgb(var(--ec-card-bg));
62
+ color: rgb(var(--ec-page-text));
63
+ font-size: 12px;
64
+ font-weight: 500;
65
+ cursor: pointer;
66
+ transition: border-color 150ms, color 150ms;
67
+ }
68
+ .ec-mcp-button:hover { border-color: rgb(var(--ec-accent)); color: rgb(var(--ec-accent)); }
69
+ .ec-mcp-button svg { width: 14px; height: 14px; }
70
+ .ec-mcp-back { padding: 0 7px; }
71
+ .ec-mcp-loading { flex-shrink: 0; color: rgb(var(--ec-page-text-muted)); font-size: 12px; }
72
+ .ec-mcp-graph { position: relative; flex: 1; min-height: 0; }
73
+ .ec-mcp-modal {
74
+ position: absolute;
75
+ z-index: 20;
76
+ padding: 12px;
77
+ border: 1px solid rgb(var(--ec-page-border));
78
+ border-radius: 12px;
79
+ background: rgb(var(--ec-card-bg));
80
+ color: rgb(var(--ec-page-text));
81
+ box-shadow: 0 12px 32px rgb(0 0 0 / 0.18), 0 2px 6px rgb(0 0 0 / 0.08);
82
+ font-size: 13px;
83
+ }
84
+ /* Pointer towards the node */
85
+ .ec-mcp-modal::before {
86
+ content: '';
87
+ position: absolute;
88
+ top: 16px;
89
+ width: 10px;
90
+ height: 10px;
91
+ background: rgb(var(--ec-card-bg));
92
+ border: 1px solid rgb(var(--ec-page-border));
93
+ transform: rotate(45deg);
94
+ }
95
+ .ec-mcp-modal[data-side='right']::before { left: -6px; border-top-color: transparent; border-right-color: transparent; }
96
+ .ec-mcp-modal[data-side='left']::before { right: -6px; border-bottom-color: transparent; border-left-color: transparent; }
97
+ .ec-mcp-modal-header { display: flex; align-items: center; gap: 6px; min-width: 0; }
98
+ .ec-mcp-modal-close {
99
+ margin-left: auto;
100
+ flex-shrink: 0;
101
+ display: inline-flex;
102
+ padding: 3px;
103
+ border-radius: 6px;
104
+ color: rgb(var(--ec-page-text-muted));
105
+ cursor: pointer;
106
+ }
107
+ .ec-mcp-modal-close:hover { background: color-mix(in srgb, rgb(var(--ec-page-border)) 50%, transparent); color: rgb(var(--ec-page-text)); }
108
+ .ec-mcp-modal-close svg { width: 14px; height: 14px; }
109
+ .ec-mcp-modal-summary {
110
+ margin-top: 6px;
111
+ color: rgb(var(--ec-page-text-muted));
112
+ font-size: 12px;
113
+ line-height: 1.45;
114
+ display: -webkit-box;
115
+ -webkit-line-clamp: 3;
116
+ -webkit-box-orient: vertical;
117
+ overflow: hidden;
118
+ }
119
+ .ec-mcp-modal-form { margin-top: 10px; padding-top: 10px; border-top: 1px solid rgb(var(--ec-page-border)); }
120
+ .ec-mcp-modal-form label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; }
121
+ .ec-mcp-composer {
122
+ border: 1px solid rgb(var(--ec-page-border));
123
+ border-radius: 10px;
124
+ background: rgb(var(--ec-page-bg));
125
+ transition: border-color 150ms, box-shadow 150ms;
126
+ }
127
+ .ec-mcp-composer:focus-within {
128
+ border-color: rgb(var(--ec-accent));
129
+ box-shadow: 0 0 0 3px color-mix(in srgb, rgb(var(--ec-accent)) 15%, transparent);
130
+ }
131
+ .ec-mcp-composer textarea {
132
+ display: block;
133
+ width: 100%;
134
+ padding: 9px 11px 2px;
135
+ background: transparent;
136
+ color: rgb(var(--ec-page-text));
137
+ font-family: inherit;
138
+ font-size: 13px;
139
+ line-height: 1.45;
140
+ resize: none;
141
+ outline: none;
142
+ }
143
+ .ec-mcp-composer textarea::placeholder { color: color-mix(in srgb, rgb(var(--ec-page-text-muted)) 70%, transparent); opacity: 1; }
144
+ .ec-mcp-composer-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 6px 6px 11px; }
145
+ .ec-mcp-composer-hint { color: color-mix(in srgb, rgb(var(--ec-page-text-muted)) 75%, transparent); font-size: 11px; }
146
+ .ec-mcp-composer-send {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ flex-shrink: 0;
151
+ width: 28px;
152
+ height: 28px;
153
+ border-radius: 8px;
154
+ background: rgb(var(--ec-accent));
155
+ color: rgb(var(--ec-button-text));
156
+ cursor: pointer;
157
+ transition: opacity 150ms, transform 150ms;
158
+ }
159
+ .ec-mcp-composer-send:hover:not(:disabled) { transform: translateY(-1px); }
160
+ .ec-mcp-composer-send:disabled { background: rgb(var(--ec-page-border)); color: rgb(var(--ec-page-text-muted)); cursor: default; }
161
+ .ec-mcp-composer-send svg { width: 14px; height: 14px; }
162
+ .ec-mcp-modal-link {
163
+ display: inline-flex;
164
+ align-items: center;
165
+ gap: 6px;
166
+ margin-top: 8px;
167
+ padding: 4px 8px;
168
+ border: 1px solid rgb(var(--ec-page-border));
169
+ border-radius: 6px;
170
+ color: rgb(var(--ec-page-text));
171
+ font-size: 12px;
172
+ font-weight: 500;
173
+ cursor: pointer;
174
+ transition: border-color 150ms, color 150ms;
175
+ }
176
+ .ec-mcp-modal-link:hover { border-color: rgb(var(--ec-accent)); color: rgb(var(--ec-accent)); }
177
+ .ec-mcp-modal-link svg { width: 13px; height: 13px; }
178
+ .ec-mcp-modal-hint { margin-top: 10px; color: rgb(var(--ec-page-text-muted)); font-size: 12px; }
179
+ /* There are no error or success colour tokens in the theme yet, so these are fixed */
180
+ .ec-mcp-modal-error { margin-top: 6px; color: rgb(220 38 38); font-size: 12px; }
181
+ .ec-mcp-modal-sent {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: 6px;
185
+ margin-top: 10px;
186
+ padding-top: 10px;
187
+ border-top: 1px solid rgb(var(--ec-page-border));
188
+ color: rgb(22 163 74);
189
+ font-size: 13px;
190
+ font-weight: 500;
191
+ }
192
+ .ec-mcp-modal-sent svg { width: 14px; height: 14px; }
193
+ `;
194
+
195
+ /** The diagram's styles: the visualiser's, and the view's own header and question modal */
196
+ export const architectureDiagramStyles = [visualiserStyles, viewStyles].join('\n');
197
+
198
+ // The visualiser's theme variables (colours for light and dark mode) are set on this class
199
+ export const VISUALISER_BODY_CLASS = 'eventcatalog-visualizer';
200
+
201
+ type ArchitectureDiagramViewProps = {
202
+ app: App | null;
203
+ /** The diagram from the latest tool result */
204
+ payload: ArchitectureDiagramPayload;
205
+ hostContext?: McpUiHostContext;
206
+ };
207
+
208
+ export function ArchitectureDiagramView({ app, payload: toolPayload, hostContext }: ArchitectureDiagramViewProps) {
209
+ // The diagrams opened in the view, the current one last (links like "Focus node" open another)
210
+ const [diagrams, setDiagrams] = useState<ArchitectureDiagramPayload[]>([toolPayload]);
211
+ const payload = diagrams[diagrams.length - 1] ?? null;
212
+ const [isOpeningDiagram, setIsOpeningDiagram] = useState(false);
213
+ const [selectedNode, setSelectedNode] = useState<SelectedNode | null>(null);
214
+
215
+ // Each tool result starts the view again on its diagram
216
+ useEffect(() => {
217
+ if (toolPayload) setDiagrams([toolPayload]);
218
+ }, [toolPayload]);
219
+
220
+ const toCatalogUrl = useCallback((path: string) => (payload ? new URL(path, payload.catalogUrl).href : path), [payload]);
221
+
222
+ // Links in the diagram open EventCatalog in the host (the view itself can't navigate)
223
+ const openInCatalog = useCallback((url: string) => app?.openLink({ url: toCatalogUrl(url) }), [app, toCatalogUrl]);
224
+
225
+ // Opens another resource's diagram in the view, loaded from the MCP server through the host
226
+ const openDiagram = useCallback(
227
+ async (diagram: DiagramLink) => {
228
+ if (!app) return;
229
+ setIsOpeningDiagram(true);
230
+ try {
231
+ const result = await app.callServerTool({
232
+ name: VIEWER_VIEW_TOOL,
233
+ arguments: {
234
+ view: 'architecture',
235
+ resourceId: diagram.id,
236
+ resourceVersion: diagram.version,
237
+ resourceCollection: diagram.collection,
238
+ },
239
+ });
240
+ const loaded = getToolResultPayload<ViewerPayload>(result, VIEWER_META_KEY);
241
+ if (result.isError || loaded?.view !== 'architecture') throw new Error('The diagram could not be loaded');
242
+ setSelectedNode(null);
243
+ setDiagrams((opened) => [...opened, loaded.diagram]);
244
+ } catch {
245
+ // Show it in EventCatalog instead
246
+ openInCatalog(`/visualiser/${diagram.collection}/${diagram.id}/${diagram.version}`);
247
+ } finally {
248
+ setIsOpeningDiagram(false);
249
+ }
250
+ },
251
+ [app, openInCatalog]
252
+ );
253
+
254
+ const goBack = useCallback(() => {
255
+ setSelectedNode(null);
256
+ setDiagrams((opened) => (opened.length > 1 ? opened.slice(0, -1) : opened));
257
+ }, []);
258
+
259
+ // Diagram links open in the view when the host can call the MCP server for the view, other links in EventCatalog
260
+ const followLink = useCallback(
261
+ (href: string) => {
262
+ const diagram = payload && parseDiagramLink(href, payload.catalogUrl);
263
+ if (diagram && app?.getHostCapabilities()?.serverTools) {
264
+ const current = payload.resource;
265
+ const isCurrent =
266
+ diagram.collection === current.collection && diagram.id === current.id && diagram.version === current.version;
267
+ if (!isCurrent) openDiagram(diagram);
268
+ return;
269
+ }
270
+ openInCatalog(href);
271
+ },
272
+ [app, payload, openDiagram, openInCatalog]
273
+ );
274
+
275
+ // The diagram's levels, with "Ask a question" added to every node's right-click menu
276
+ const graph = useMemo(() => {
277
+ if (!payload) return null;
278
+ const { view } = payload;
279
+ const withAsk = (level?: { nodes: any[]; edges: any[] }) => level && { ...level, nodes: withAskMenuItem(level.nodes) };
280
+ const levels = { ...withAsk(view)!, overview: withAsk(view.overview), hiddenMessages: withAsk(view.hiddenMessages) };
281
+ const nodesById = new Map<string, Node>(
282
+ [levels, levels.overview, levels.hiddenMessages].flatMap((level) => level?.nodes ?? []).map((node) => [node.id, node])
283
+ );
284
+ return { ...levels, nodesById };
285
+ }, [payload]);
286
+
287
+ // The view can't navigate (it runs in a sandbox), so links in the diagram, such as the ones in
288
+ // a node's right-click menu, are followed here
289
+ const followLinkRef = useRef(followLink);
290
+ followLinkRef.current = followLink;
291
+ const askAboutNodeIdRef = useRef((nodeId: string) => {});
292
+ askAboutNodeIdRef.current = (nodeId: string) => {
293
+ const node = graph?.nodesById.get(nodeId);
294
+ if (node) setSelectedNode(describeNode(node));
295
+ };
296
+ useEffect(() => {
297
+ const onClick = (event: MouseEvent) => {
298
+ const anchor = (event.target as Element | null)?.closest?.('a[href]');
299
+ const href = anchor?.getAttribute('href');
300
+ if (!href) return;
301
+ // "Ask a question" links only point within the view, so the click isn't cancelled: that lets
302
+ // the right-click menu handle it and close
303
+ const askNodeId = parseAskLink(href);
304
+ if (askNodeId) {
305
+ askAboutNodeIdRef.current(askNodeId);
306
+ return;
307
+ }
308
+ if (href.startsWith('#')) return;
309
+ event.preventDefault();
310
+ // Cancelling the click stops a right-click menu closing itself, so close it (menus close on Escape)
311
+ if (anchor?.closest('[role="menu"]')) {
312
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
313
+ }
314
+ followLinkRef.current(href);
315
+ };
316
+ document.addEventListener('click', onClick, true);
317
+ return () => document.removeEventListener('click', onClick, true);
318
+ }, []);
319
+
320
+ // Domain and system cards navigate with window.__ecNavigate (or by changing the page, which would
321
+ // take the view away). Clicking them opens the question modal, which offers to open their diagram.
322
+ const catalogUrl = payload?.catalogUrl;
323
+ useEffect(() => {
324
+ const bridge = window as unknown as { __ecNavigate?: (url: string) => void };
325
+ bridge.__ecNavigate = (url: string) => {
326
+ if (catalogUrl && parseDiagramLink(url, catalogUrl)) return;
327
+ followLinkRef.current(url);
328
+ };
329
+ return () => {
330
+ delete bridge.__ecNavigate;
331
+ };
332
+ }, [catalogUrl]);
333
+
334
+ const isFullscreen = hostContext?.displayMode === 'fullscreen';
335
+
336
+ // Fit the diagram to the view again when the host resizes it (e.g. going full screen)
337
+ const [fitRequestId, setFitRequestId] = useState(0);
338
+ useEffect(() => setFitRequestId((id) => id + 1), [hostContext?.displayMode]);
339
+ const canGoFullscreen = hostContext?.availableDisplayModes?.includes('fullscreen');
340
+
341
+ // Clicking a node opens a modal next to it, to ask the conversation about it
342
+ const graphRef = useRef<HTMLDivElement>(null);
343
+ const closeChat = useCallback(() => setSelectedNode(null), []);
344
+ const hostCapabilities = app?.getHostCapabilities();
345
+
346
+ // Only opens the modal: nothing is sent to the host until the user sends a question
347
+ const handleNodeClick = useCallback((node: Node) => setSelectedNode(describeNode(node)), []);
348
+
349
+ const askAboutNode = useCallback(
350
+ async (question: string) => {
351
+ if (!app || !selectedNode || !payload) return;
352
+ const result = await app.sendMessage({
353
+ role: 'user',
354
+ content: [
355
+ {
356
+ type: 'text',
357
+ text: `${question}\n\n(About ${describeNodeForModel(selectedNode)} in the EventCatalog architecture diagram for ${payload.resource.name}.)`,
358
+ },
359
+ ],
360
+ });
361
+ if (result.isError) throw new Error('The host did not accept the message');
362
+ },
363
+ [app, selectedNode, payload]
364
+ );
365
+
366
+ if (!payload || !graph) {
367
+ return <p style={{ padding: 16, fontFamily: 'sans-serif' }}>Loading diagram…</p>;
368
+ }
369
+
370
+ const { resource } = payload;
371
+ const isCurrentDiagram = (diagram: DiagramLink) =>
372
+ diagram.collection === resource.collection && diagram.id === resource.id && diagram.version === resource.version;
373
+ // NodeGraph renders into a portal element with this id (as the Diagram page provides one)
374
+ const graphId = `mcp-${resource.collection}-${resource.id}-${resource.version}`;
375
+
376
+ return (
377
+ <div style={{ height: isFullscreen ? '100vh' : INLINE_HEIGHT, display: 'flex', flexDirection: 'column' }}>
378
+ <div className="ec-mcp-header">
379
+ <div className="ec-mcp-title">
380
+ {diagrams.length > 1 && (
381
+ <button type="button" className="ec-mcp-button ec-mcp-back" aria-label="Back" title="Back" onClick={goBack}>
382
+ <ArrowLeft aria-hidden />
383
+ </button>
384
+ )}
385
+ <span className="ec-mcp-type">{RESOURCE_TYPE_LABELS[resource.collection] ?? resource.collection}</span>
386
+ <span className="ec-mcp-name">{resource.name}</span>
387
+ <span className="ec-mcp-version">v{resource.version}</span>
388
+ {isOpeningDiagram && <span className="ec-mcp-loading">Opening diagram…</span>}
389
+ </div>
390
+ <div className="ec-mcp-actions">
391
+ <button type="button" className="ec-mcp-button" onClick={() => openInCatalog(payload.visualiserPath)}>
392
+ <ExternalLink aria-hidden />
393
+ Open in EventCatalog
394
+ </button>
395
+ {canGoFullscreen && (
396
+ <button
397
+ type="button"
398
+ className="ec-mcp-button"
399
+ aria-label={isFullscreen ? 'Exit full screen' : 'Full screen'}
400
+ onClick={() => app?.requestDisplayMode({ mode: isFullscreen ? 'inline' : 'fullscreen' })}
401
+ >
402
+ {isFullscreen ? <Minimize2 aria-hidden /> : <Maximize2 aria-hidden />}
403
+ </button>
404
+ )}
405
+ </div>
406
+ </div>
407
+ <div className="ec-mcp-graph" ref={graphRef} key={graphId}>
408
+ <div id={`${graphId}-portal`} style={{ height: '100%' }} />
409
+ {selectedNode && (
410
+ <NodeChat
411
+ node={selectedNode}
412
+ containerRef={graphRef}
413
+ canSend={!!hostCapabilities?.message}
414
+ onSend={askAboutNode}
415
+ onOpenDiagram={
416
+ selectedNode.diagram && app?.getHostCapabilities()?.serverTools && !isCurrentDiagram(selectedNode.diagram)
417
+ ? () => openDiagram(selectedNode.diagram!)
418
+ : undefined
419
+ }
420
+ onClose={closeChat}
421
+ />
422
+ )}
423
+ </div>
424
+ <div style={{ display: 'none' }} key={`${graphId}-graph`}>
425
+ <NodeGraph
426
+ id={graphId}
427
+ nodes={graph.nodes}
428
+ edges={graph.edges}
429
+ overviewGraph={
430
+ graph.overview
431
+ ? {
432
+ ...graph.overview,
433
+ label: resource.collection === 'domains' ? 'domains and systems' : 'system context',
434
+ }
435
+ : undefined
436
+ }
437
+ hiddenMessagesGraph={graph.hiddenMessages}
438
+ preferenceScope={resource.collection}
439
+ mode="full"
440
+ linkTo="docs"
441
+ showSearch
442
+ compactSearch
443
+ showMenu={false}
444
+ hideAttribution
445
+ zoomOnScroll
446
+ fitRequestId={fitRequestId}
447
+ onNodeClick={handleNodeClick}
448
+ onBuildUrl={toCatalogUrl}
449
+ onNavigate={followLink}
450
+ />
451
+ </div>
452
+ </div>
453
+ );
454
+ }