@eventcatalog/core 4.12.3 → 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 (267) 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-TV3YAWKQ.js → chunk-CR6AK5LR.js} +1 -1
  12. package/dist/{chunk-M577VUOX.js → chunk-LR7AGRHN.js} +13 -16
  13. package/dist/chunk-TQLRG35T.js +203 -0
  14. package/dist/{chunk-HPC6KUDQ.js → chunk-TWN43V4T.js} +1 -1
  15. package/dist/{chunk-ZYTCBNB3.js → chunk-WAIADKQE.js} +1 -1
  16. package/dist/{chunk-5BPN6QEC.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 +35 -98
  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 +4 -5
  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 -96
  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/channel-node-graph.ts +4 -25
  223. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -39
  224. package/eventcatalog/src/utils/node-graphs/data-products-node-graph.ts +11 -27
  225. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +679 -0
  226. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +3 -20
  227. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +51 -4
  228. package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +8 -23
  229. package/eventcatalog/src/utils/node-graphs/flow-lanes.ts +119 -0
  230. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +133 -47
  231. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +28 -0
  232. package/eventcatalog/src/utils/node-graphs/layout-persistence.ts +3 -3
  233. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +16 -34
  234. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +11 -25
  235. package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +18 -54
  236. package/eventcatalog/src/utils/node-graphs/system-levels-node-graph.ts +59 -0
  237. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +20 -80
  238. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +1 -78
  239. package/eventcatalog/src/utils/trial.ts +36 -0
  240. package/eventcatalog/tsconfig.json +1 -1
  241. package/package.json +11 -11
  242. package/dist/chunk-FV56YFM4.js +0 -7
  243. package/dist/federation/entitlement.cjs +0 -31
  244. package/dist/federation/entitlement.d.cts +0 -12
  245. package/dist/federation/entitlement.d.ts +0 -12
  246. package/dist/federation/entitlement.js +0 -6
  247. package/dist/runtime-dependencies/dagre.mjs +0 -3
  248. package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +0 -265
  249. package/eventcatalog/src/enterprise/LICENSE +0 -57
  250. package/eventcatalog/src/enterprise/README.md +0 -5
  251. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +0 -691
  252. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +0 -9
  253. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/[...path]/index.astro +0 -18
  254. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/feature.astro +0 -171
  255. package/eventcatalog/src/enterprise/feature.ts +0 -75
  256. package/eventcatalog/src/enterprise/tools/index.ts +0 -10
  257. package/eventcatalog/src/hooks/eventcatalog-visualizer.ts +0 -126
  258. package/eventcatalog/src/pages/settings/billing.astro +0 -17
  259. package/eventcatalog/src/pages/visualiser/domain-integrations/index.astro +0 -26
  260. package/eventcatalog/src/types/mcp-modules.d.ts +0 -67
  261. package/eventcatalog/src/utils/node-graphs/domains-canvas.ts +0 -261
  262. package/eventcatalog/src/utils/node-graphs/export-node-graph.ts +0 -91
  263. /package/eventcatalog/src/{enterprise → features}/auth/error.astro +0 -0
  264. /package/eventcatalog/src/{enterprise → features}/auth/login.astro +0 -0
  265. /package/eventcatalog/src/{enterprise → features}/auth/unauthorized.astro +0 -0
  266. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path]/_index.data.ts +0 -0
  267. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path].mdx.ts +0 -0
@@ -0,0 +1,28 @@
1
+ import { hideMessageNodes, layoutWithElk } from '@eventcatalog/visualiser/layout';
2
+
3
+ type Graph = { nodes: any[]; edges: any[] };
4
+
5
+ /**
6
+ * Lays a node graph out for the visualiser (with ELK, left to right). Builders
7
+ * create their nodes and edges without positions and lay the finished graph
8
+ * out once with this. Nodes get top-left positions (`origin: [0, 0]`), groups
9
+ * (nodes with children) are sized to fit them, and edges get the route they're
10
+ * drawn along (`data.route`), with room for their labels.
11
+ */
12
+ export const layoutNodeGraph = async <G extends Graph>(graph: G): Promise<G> => (await layoutWithElk(graph)) as unknown as G;
13
+
14
+ /**
15
+ * Lays out the graphs of a levels page: level 1 (`overview`: domains, systems
16
+ * and their relationships), level 3 (the detailed graph, with messages and
17
+ * channels) and level 2 in between, the detailed graph with its messages and
18
+ * channels hidden (`hiddenMessages`), so the browser doesn't have to lay it out
19
+ * again. Without an overview there's no level 1.
20
+ */
21
+ export const layoutLevels = async (detailed: Graph, overview?: Graph) => {
22
+ const [laidOut, laidOutOverview, hiddenMessages] = await Promise.all([
23
+ layoutNodeGraph(detailed),
24
+ overview && layoutNodeGraph(overview),
25
+ layoutNodeGraph(hideMessageNodes(detailed.nodes, detailed.edges)),
26
+ ]);
27
+ return { ...laidOut, overview: laidOutOverview, hiddenMessages };
28
+ };
@@ -55,7 +55,7 @@ export async function loadSavedLayout(resourceKey: string): Promise<SavedLayout
55
55
 
56
56
  /**
57
57
  * Applies saved positions to nodes. Nodes with saved positions get them applied,
58
- * nodes without saved positions keep their Dagre-calculated positions.
58
+ * nodes without saved positions keep their laid out positions.
59
59
  */
60
60
  export function applyLayoutToNodes<T extends { id: string; position: { x: number; y: number } }>(
61
61
  nodes: T[],
@@ -63,7 +63,7 @@ export function applyLayoutToNodes<T extends { id: string; position: { x: number
63
63
  ): T[];
64
64
  export function applyLayoutToNodes(nodes: any[], savedLayout: SavedLayout | null): any[] {
65
65
  if (!savedLayout) {
66
- return nodes; // No saved layout, use original Dagre positions
66
+ return nodes; // No saved layout, use the laid out positions
67
67
  }
68
68
 
69
69
  return nodes.map((node) => {
@@ -75,7 +75,7 @@ export function applyLayoutToNodes(nodes: any[], savedLayout: SavedLayout | null
75
75
  position: { x: savedPosition.x, y: savedPosition.y },
76
76
  };
77
77
  }
78
- // Keep Dagre-calculated position for new/unmatched nodes
78
+ // Keep the laid out position for new/unmatched nodes
79
79
  return node;
80
80
  });
81
81
  }
@@ -2,8 +2,6 @@
2
2
  import { getEvents } from '@utils/collections/events';
3
3
  import { getCollection, type CollectionEntry } from 'astro:content';
4
4
  import {
5
- calculatedNodes,
6
- createDagreGraph,
7
5
  createEdge,
8
6
  generatedIdForEdge,
9
7
  generateIdForNode,
@@ -11,8 +9,8 @@ import {
11
9
  getEdgeLabelForMessageAsSource,
12
10
  getEdgeLabelForServiceAsTarget,
13
11
  versionMatches,
14
- layoutDagreGraph,
15
12
  } from './utils/utils';
13
+ import { layoutNodeGraph } from '@utils/node-graphs/layout-node-graph';
16
14
  import { MarkerType, type Node, type Edge } from '@xyflow/react';
17
15
  import {
18
16
  findMatchingNodes,
@@ -31,8 +29,6 @@ import {
31
29
  buildContextMenuForService,
32
30
  buildContextMenuForResource,
33
31
  getOperationFields,
34
- DEFAULT_NODE_WIDTH,
35
- DEFAULT_NODE_HEIGHT,
36
32
  } from './utils/utils';
37
33
  import { getConsumersOfMessage, getProducersOfMessage } from '@utils/collections/services';
38
34
  import {
@@ -44,16 +40,15 @@ import { getChannelChain, isChannelsConnected } from '@utils/collections/channel
44
40
  import { getChannels } from '@utils/collections/channels';
45
41
  import { getTriggeredByOfMessage, getTriggersOfMessage, type MessageReceiver } from '@utils/collections/message-triggers';
46
42
 
47
- type DagreGraph = any;
48
43
  type RoutableResource = CollectionEntry<'agents'> | CollectionEntry<'services'>;
49
44
  type ProducerConsumerResource = RoutableResource | CollectionEntry<'data-products'>;
50
45
 
51
46
  interface Props {
52
47
  id: string;
53
48
  version: string;
54
- defaultFlow?: DagreGraph;
55
49
  mode?: 'simple' | 'full';
56
50
  channelRenderMode?: 'flat' | 'single';
51
+ layout?: boolean;
57
52
  collection?: CollectionEntry<CollectionMessageTypes>[];
58
53
  channels?: CollectionEntry<'channels'>[];
59
54
  }
@@ -216,15 +211,14 @@ export const createTriggerMessageNode = (
216
211
  const getNodesAndEdges = async ({
217
212
  id,
218
213
  version,
219
- defaultFlow,
220
214
  mode = 'simple',
221
215
  channelRenderMode = 'flat',
222
216
  collection = [],
223
217
  channels = [],
218
+ layout = true,
224
219
  }: Props) => {
225
- const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
226
- const nodes = [] as any,
227
- edges = [] as any;
220
+ const nodes: any[] = [],
221
+ edges: any[] = [];
228
222
 
229
223
  const message = collection.find((message) => {
230
224
  return message.data.id === id && message.data.version === version;
@@ -297,7 +291,7 @@ const getNodesAndEdges = async ({
297
291
  sourcePosition: 'right',
298
292
  targetPosition: 'left',
299
293
  data: isDataProduct(producer) ? getDataProductNodeData(producer, mode) : getRoutableNodeData(producer, mode),
300
- position: { x: 250, y: 0 },
294
+ position: { x: 0, y: 0 },
301
295
  });
302
296
  if (!isDataProduct(producer)) {
303
297
  appendAgentToolNodesAndEdges({ agent: producer, nodes, edges, mode });
@@ -684,54 +678,42 @@ const getNodesAndEdges = async ({
684
678
  appendEdge(relation.receiver, relation.message, getEdgeLabelForServiceAsTarget(relation.message), relation.message);
685
679
  }
686
680
 
687
- nodes.forEach((node: any) => {
688
- flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
689
- });
690
-
691
- edges.forEach((edge: any) => {
692
- flow.setEdge(edge.source, edge.target);
693
- });
681
+ if (!layout) return { nodes, edges };
694
682
 
695
- // Render the diagram in memory getting hte X and Y
696
- layoutDagreGraph(flow);
697
-
698
- return {
699
- nodes: calculatedNodes(flow, nodes),
700
- edges,
701
- };
683
+ return layoutNodeGraph({ nodes, edges });
702
684
  };
703
685
 
704
686
  export const getNodesAndEdgesForQueries = async ({
705
687
  id,
706
688
  version,
707
- defaultFlow,
708
689
  mode = 'simple',
709
690
  channelRenderMode = 'flat',
691
+ layout = true,
710
692
  }: Props) => {
711
693
  const [queries, channels] = await Promise.all([getQueries(), getChannels()]);
712
- return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: queries, channels });
694
+ return getNodesAndEdges({ id, version, mode, channelRenderMode, collection: queries, channels, layout });
713
695
  };
714
696
 
715
697
  export const getNodesAndEdgesForCommands = async ({
716
698
  id,
717
699
  version,
718
- defaultFlow,
719
700
  mode = 'simple',
720
701
  channelRenderMode = 'flat',
702
+ layout = true,
721
703
  }: Props) => {
722
704
  const [commands, channels] = await Promise.all([getCommands(), getChannels()]);
723
- return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: commands, channels });
705
+ return getNodesAndEdges({ id, version, mode, channelRenderMode, collection: commands, channels, layout });
724
706
  };
725
707
 
726
708
  export const getNodesAndEdgesForEvents = async ({
727
709
  id,
728
710
  version,
729
- defaultFlow,
730
711
  mode = 'simple',
731
712
  channelRenderMode = 'flat',
713
+ layout = true,
732
714
  }: Props) => {
733
715
  const [events, channels] = await Promise.all([getEvents(), getChannels()]);
734
- return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: events, channels });
716
+ return getNodesAndEdges({ id, version, mode, channelRenderMode, collection: events, channels, layout });
735
717
  };
736
718
 
737
719
  export const getNodesAndEdgesForConsumedMessage = ({
@@ -756,7 +738,7 @@ export const getNodesAndEdgesForConsumedMessage = ({
756
738
  channelMap?: Map<string, CollectionEntry<'channels'>[]>;
757
739
  }) => {
758
740
  let nodes = [] as Node[],
759
- edges = [] as any;
741
+ edges: any[] = [];
760
742
 
761
743
  // Use the provided map or create one if missing
762
744
  const map = channelMap || createVersionedMap(channels);
@@ -1092,7 +1074,7 @@ export const getNodesAndEdgesForProducedMessage = ({
1092
1074
  channelMap?: Map<string, CollectionEntry<'channels'>[]>;
1093
1075
  }) => {
1094
1076
  let nodes = [] as Node[],
1095
- edges = [] as any;
1077
+ edges: any[] = [];
1096
1078
 
1097
1079
  // Use provided map or create one
1098
1080
  const map = channelMap || createVersionedMap(channels);
@@ -1,20 +1,16 @@
1
1
  import { getCollection, type CollectionEntry } from 'astro:content';
2
2
  import {
3
- createDagreGraph,
4
3
  generateIdForNode,
5
4
  generatedIdForEdge,
6
- calculatedNodes,
7
5
  createEdge,
8
6
  buildContextMenuForAgent,
9
7
  buildContextMenuForService,
10
8
  buildContextMenuForResource,
11
9
  versionMatches,
12
- DEFAULT_NODE_WIDTH,
13
- DEFAULT_NODE_HEIGHT,
14
10
  partitionMessagesByGroup,
15
11
  getOperationFields,
16
- layoutDagreGraph,
17
12
  } from '@utils/node-graphs/utils/utils';
13
+ import { layoutNodeGraph } from '@utils/node-graphs/layout-node-graph';
18
14
 
19
15
  const sanitizeGroupId = (name: string) => name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
20
16
  const sanitizeToolId = (name: string) =>
@@ -108,12 +104,9 @@ const precomputeGroupExpansion = (
108
104
  return { expandedNodes, expandedEdges };
109
105
  };
110
106
 
111
- type DagreGraph = any;
112
-
113
107
  interface Props {
114
108
  id: string;
115
109
  version: string;
116
- defaultFlow?: DagreGraph;
117
110
  mode?: 'simple' | 'full';
118
111
  renderAllEdges?: boolean;
119
112
  channelRenderMode?: 'single' | 'flat';
@@ -172,7 +165,6 @@ const getReceivesMessageByMessageType = (messageType: string) => {
172
165
 
173
166
  export const getNodesAndEdges = async ({
174
167
  id,
175
- defaultFlow,
176
168
  version,
177
169
  mode = 'simple',
178
170
  renderAllEdges = false,
@@ -181,7 +173,6 @@ export const getNodesAndEdges = async ({
181
173
  collection = 'services',
182
174
  layout = true,
183
175
  }: Props) => {
184
- const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
185
176
  let nodes = [] as any,
186
177
  edges = [] as any;
187
178
 
@@ -282,6 +273,7 @@ export const getNodesAndEdges = async ({
282
273
 
283
274
  nodes.push({
284
275
  id: groupNodeId,
276
+ position: { x: 0, y: 0 },
285
277
  sourcePosition: 'right',
286
278
  targetPosition: 'left',
287
279
  type: 'messageGroup',
@@ -345,6 +337,7 @@ export const getNodesAndEdges = async ({
345
337
  // The service itself
346
338
  nodes.push({
347
339
  id: generateIdForNode(service),
340
+ position: { x: 0, y: 0 },
348
341
  sourcePosition: 'right',
349
342
  targetPosition: 'left',
350
343
  data: {
@@ -358,6 +351,7 @@ export const getNodesAndEdges = async ({
358
351
  writesTo.forEach((writeTo) => {
359
352
  nodes.push({
360
353
  id: generateIdForNode(writeTo),
354
+ position: { x: 0, y: 0 },
361
355
  sourcePosition: 'right',
362
356
  targetPosition: 'left',
363
357
  data: {
@@ -398,6 +392,7 @@ export const getNodesAndEdges = async ({
398
392
 
399
393
  nodes.push({
400
394
  id: toolNodeId,
395
+ position: { x: 0, y: 0 },
401
396
  sourcePosition: 'right',
402
397
  targetPosition: 'left',
403
398
  data: {
@@ -447,6 +442,7 @@ export const getNodesAndEdges = async ({
447
442
  readsFrom.forEach((readFrom) => {
448
443
  nodes.push({
449
444
  id: generateIdForNode(readFrom),
445
+ position: { x: 0, y: 0 },
450
446
  sourcePosition: 'right',
451
447
  targetPosition: 'left',
452
448
  data: {
@@ -500,6 +496,7 @@ export const getNodesAndEdges = async ({
500
496
 
501
497
  nodes.push({
502
498
  id: groupNodeId,
499
+ position: { x: 0, y: 0 },
503
500
  sourcePosition: 'right',
504
501
  targetPosition: 'left',
505
502
  type: 'messageGroup',
@@ -626,19 +623,6 @@ export const getNodesAndEdges = async ({
626
623
 
627
624
  const uniqueNodes = Array.from(uniqueNodesById.values());
628
625
 
629
- uniqueNodes.forEach((node: any) => {
630
- flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
631
- });
632
-
633
- edges.forEach((edge: any) => {
634
- flow.setEdge(edge.source, edge.target);
635
- });
636
-
637
- if (layout) {
638
- // Render the diagram in memory getting the X and Y
639
- layoutDagreGraph(flow);
640
- }
641
-
642
626
  // Find any duplicated edges, and merge them into one edge
643
627
  const uniqueEdgesById = new Map<string, any>();
644
628
  edges.forEach((edge: any) => {
@@ -661,8 +645,10 @@ export const getNodesAndEdges = async ({
661
645
  });
662
646
  const uniqueEdges = Array.from(uniqueEdgesById.values());
663
647
 
664
- return {
665
- nodes: calculatedNodes(flow, uniqueNodes),
648
+ const graph = {
649
+ nodes: uniqueNodes.map((node: any) => ({ ...node, position: node.position ?? { x: 0, y: 0 } })),
666
650
  edges: uniqueEdges,
667
651
  };
652
+
653
+ return layout ? await layoutNodeGraph(graph) : graph;
668
654
  };
@@ -1,32 +1,17 @@
1
1
  import { getCollection } from 'astro:content';
2
2
  import type { CollectionEntry } from 'astro:content';
3
- import {
4
- createDagreGraph,
5
- calculatedNodes,
6
- createEdge,
7
- generateIdForNode,
8
- buildContextMenuForSystem,
9
- DEFAULT_NODE_HEIGHT,
10
- layoutDagreGraph,
11
- } from '@utils/node-graphs/utils/utils';
3
+ import { createEdge, generateIdForNode, buildContextMenuForSystem } from '@utils/node-graphs/utils/utils';
4
+ import { layoutNodeGraph } from '@utils/node-graphs/layout-node-graph';
12
5
  import { MarkerType } from '@xyflow/react';
13
6
  import { createVersionedMap, findInMap } from '@utils/collections/util';
14
7
 
15
- type DagreGraph = any;
16
-
17
8
  interface NodesAndEdgesProps {
18
9
  id: string;
19
10
  version: string;
20
- defaultFlow?: DagreGraph;
21
11
  mode?: 'simple' | 'full';
22
12
  layout?: boolean;
23
13
  }
24
14
 
25
- // System nodes are wider than the default to fit the system name + summary comfortably.
26
- const SYSTEM_NODE_WIDTH = 270;
27
- // Actor nodes are narrower than systems — a compact pill with an icon + name.
28
- const ACTOR_NODE_WIDTH = 180;
29
-
30
15
  type SystemActor = {
31
16
  id: string;
32
17
  name?: string;
@@ -52,7 +37,6 @@ interface ContextGraphFromSeedsProps {
52
37
  seedSystems: CollectionEntry<'systems'>[];
53
38
  systemMap: Map<string, CollectionEntry<'systems'>[]>;
54
39
  serviceMap: Map<string, CollectionEntry<'services'>[]>;
55
- defaultFlow?: DagreGraph;
56
40
  mode?: 'simple' | 'full';
57
41
  layout?: boolean;
58
42
  }
@@ -67,15 +51,13 @@ interface ContextGraphFromSeedsProps {
67
51
  * (relationships without a label are intentionally not drawn). Actors are rendered
68
52
  * inline and deduped across all systems.
69
53
  */
70
- const buildContextGraphFromSeeds = ({
54
+ const buildContextGraphFromSeeds = async ({
71
55
  seedSystems,
72
56
  systemMap,
73
57
  serviceMap,
74
- defaultFlow,
75
58
  mode = 'simple',
76
59
  layout = true,
77
60
  }: ContextGraphFromSeedsProps) => {
78
- const flow = defaultFlow || createDagreGraph({ ranksep: 280, nodesep: 80, edgesep: 50 });
79
61
  const nodes = new Map<string, any>();
80
62
  const edges = new Map<string, any>();
81
63
 
@@ -89,8 +71,6 @@ const buildContextGraphFromSeeds = ({
89
71
  }, 0);
90
72
  };
91
73
 
92
- // Actor node ids, tracked so they can be sized differently during layout.
93
- const actorNodeIds = new Set<string>();
94
74
  // System node ids, tracked so we can detect reciprocal system-to-system
95
75
  // relationships and collapse them into a single double-headed edge.
96
76
  const systemNodeIds = new Set<string>();
@@ -118,7 +98,6 @@ const buildContextGraphFromSeeds = ({
118
98
  const nodeId = `actor-${actor.id}`;
119
99
  if (nodes.has(nodeId)) return nodeId;
120
100
 
121
- actorNodeIds.add(nodeId);
122
101
  nodes.set(nodeId, {
123
102
  id: nodeId,
124
103
  type: 'context-actor',
@@ -292,30 +271,15 @@ const buildContextGraphFromSeeds = ({
292
271
  mergedEdgeKeys.add(reverseId);
293
272
  }
294
273
 
295
- // Lay the graph out
296
- nodes.forEach((node) =>
297
- flow.setNode(node.id, {
298
- width: actorNodeIds.has(node.id) ? ACTOR_NODE_WIDTH : SYSTEM_NODE_WIDTH,
299
- height: DEFAULT_NODE_HEIGHT,
300
- })
301
- );
302
- edges.forEach((edge) => flow.setEdge(edge.source, edge.target));
303
-
304
- if (layout) {
305
- layoutDagreGraph(flow);
306
- }
307
-
308
- return {
309
- nodes: calculatedNodes(flow, Array.from(nodes.values())),
310
- edges: [...edges.values()],
311
- };
274
+ const graph = { nodes: [...nodes.values()], edges: [...edges.values()] };
275
+ return layout ? layoutNodeGraph(graph) : graph;
312
276
  };
313
277
 
314
278
  /**
315
279
  * Builds the System Diagram for a single system, seeding the traversal from
316
280
  * that system and walking its relationships and actors outward.
317
281
  */
318
- export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simple', layout = true }: NodesAndEdgesProps) => {
282
+ export const getNodesAndEdges = async ({ id, version, mode = 'simple', layout = true }: NodesAndEdgesProps) => {
319
283
  const [allSystems, allServices] = await Promise.all([getCollection('systems'), getCollection('services')]);
320
284
  const systemMap = createVersionedMap(allSystems);
321
285
  const serviceMap = createVersionedMap(allServices);
@@ -327,7 +291,14 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
327
291
  return { nodes: [], edges: [] };
328
292
  }
329
293
 
330
- return buildContextGraphFromSeeds({ seedSystems: [rootSystem], systemMap, serviceMap, defaultFlow, mode, layout });
294
+ const graph = await buildContextGraphFromSeeds({ seedSystems: [rootSystem], systemMap, serviceMap, mode, layout });
295
+
296
+ // Mark the system being viewed, like other resource graphs do
297
+ const rootNodeId = generateIdForNode(rootSystem);
298
+ return {
299
+ ...graph,
300
+ nodes: graph.nodes.map((node: any) => (node.id === rootNodeId ? { ...node, data: { ...node.data, isFocused: true } } : node)),
301
+ };
331
302
  };
332
303
 
333
304
  /**
@@ -336,13 +307,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
336
307
  * the domain's systems plus any related systems they point at (or that point at them),
337
308
  * with actors rendered inline — giving a single context view across the domain.
338
309
  */
339
- export const getNodesAndEdgesForDomainSystems = async ({
340
- id,
341
- version,
342
- defaultFlow,
343
- mode = 'simple',
344
- layout = true,
345
- }: NodesAndEdgesProps) => {
310
+ export const getNodesAndEdgesForDomainSystems = async ({ id, version, mode = 'simple', layout = true }: NodesAndEdgesProps) => {
346
311
  const [allDomains, allSystems, allServices] = await Promise.all([
347
312
  getCollection('domains'),
348
313
  getCollection('systems'),
@@ -367,11 +332,10 @@ export const getNodesAndEdgesForDomainSystems = async ({
367
332
  return { nodes: [], edges: [] };
368
333
  }
369
334
 
370
- return buildContextGraphFromSeeds({ seedSystems, systemMap, serviceMap, defaultFlow, mode, layout });
335
+ return buildContextGraphFromSeeds({ seedSystems, systemMap, serviceMap, mode, layout });
371
336
  };
372
337
 
373
338
  interface AllSystemsProps {
374
- defaultFlow?: DagreGraph;
375
339
  mode?: 'simple' | 'full';
376
340
  layout?: boolean;
377
341
  }
@@ -381,7 +345,7 @@ interface AllSystemsProps {
381
345
  * seed, so the traversal draws all systems, the relationships between them, and the
382
346
  * actors around them — a single map of how every system in the catalog relates.
383
347
  */
384
- export const getNodesAndEdgesForAllSystems = async ({ defaultFlow, mode = 'simple', layout = true }: AllSystemsProps = {}) => {
348
+ export const getNodesAndEdgesForAllSystems = async ({ mode = 'simple', layout = true }: AllSystemsProps = {}) => {
385
349
  const [allSystems, allServices] = await Promise.all([getCollection('systems'), getCollection('services')]);
386
350
  const systemMap = createVersionedMap(allSystems);
387
351
  const serviceMap = createVersionedMap(allServices);
@@ -396,5 +360,5 @@ export const getNodesAndEdgesForAllSystems = async ({ defaultFlow, mode = 'simpl
396
360
  return { nodes: [], edges: [] };
397
361
  }
398
362
 
399
- return buildContextGraphFromSeeds({ seedSystems, systemMap, serviceMap, defaultFlow, mode, layout });
363
+ return buildContextGraphFromSeeds({ seedSystems, systemMap, serviceMap, mode, layout });
400
364
  };
@@ -0,0 +1,59 @@
1
+ import { getNodesAndEdges as getSystemContextNodesAndEdges } from './system-context-node-graph';
2
+ import { getNodesAndEdges as getSystemNodesAndEdges } from './systems-node-graph';
3
+ import { layoutLevels } from '@utils/node-graphs/layout-node-graph';
4
+
5
+ interface NodesAndEdgesProps {
6
+ id: string;
7
+ version: string;
8
+ mode?: 'simple' | 'full';
9
+ channelRenderMode?: 'single' | 'flat';
10
+ }
11
+
12
+ const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
13
+
14
+ // Built once for each system version and options
15
+ const levelsCache = new Map<string, ReturnType<typeof buildLevels>>();
16
+
17
+ export const getNodesAndEdges = (props: NodesAndEdgesProps) => {
18
+ if (!CACHE_ENABLED) return buildLevels(props);
19
+ const { id, version, mode = 'simple', channelRenderMode } = props;
20
+ const key = [id, version, mode, channelRenderMode].join('/');
21
+ if (!levelsCache.has(key)) levelsCache.set(key, buildLevels(props));
22
+ return levelsCache.get(key)!;
23
+ };
24
+
25
+ /**
26
+ * A system's resource diagram shown inside its context diagram: the system's node
27
+ * is replaced by the expanded system group (services, data stores, messages...),
28
+ * and the system's relationships and actors connect to the group instead.
29
+ * Returns level 1 too (`overview`, the context diagram) and the graph without
30
+ * its messages and channels (`hiddenMessages`).
31
+ */
32
+ const buildLevels = async ({ id, version, mode = 'simple', channelRenderMode }: NodesAndEdgesProps) => {
33
+ const [context, system] = await Promise.all([
34
+ getSystemContextNodesAndEdges({ id, version, mode, layout: false }),
35
+ getSystemNodesAndEdges({ id, version, mode, channelRenderMode, wrapInSystemGroup: true, layout: false }),
36
+ ]);
37
+
38
+ const group = system.nodes.find((node: any) => node.type === 'system-group');
39
+ const rootSystemNode = context.nodes.find((node: any) => node.data?.isFocused);
40
+ if (!group || !rootSystemNode) return layoutLevels(system, context);
41
+
42
+ const systemNodeIds = new Set(system.nodes.map((node: any) => node.id));
43
+ const contextNodes = context.nodes.filter((node: any) => node.id !== rootSystemNode.id && !systemNodeIds.has(node.id));
44
+ const toGroup = (nodeId: string) => (nodeId === rootSystemNode.id ? group.id : nodeId);
45
+ const contextEdges = context.edges.map((edge: any) => ({
46
+ ...edge,
47
+ id: `context-${edge.id}`,
48
+ source: toGroup(edge.source),
49
+ target: toGroup(edge.target),
50
+ }));
51
+
52
+ // Lay the context and the expanded system out together
53
+ const detailed = {
54
+ // Parent must come before its children in the array for React Flow
55
+ nodes: [group, ...contextNodes, ...system.nodes.filter((node: any) => node.id !== group.id)],
56
+ edges: [...system.edges, ...contextEdges],
57
+ };
58
+ return layoutLevels(detailed, context);
59
+ };