@eventcatalog/core 5.0.0-beta.8 → 5.0.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 (467) 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 +157 -76
  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-AWOO63ME.js → chunk-AD7CL772.js} +11 -4
  22. package/dist/chunk-CA6WCQ2T.js +54 -0
  23. package/dist/chunk-CPW6G62V.js +17 -0
  24. package/dist/{chunk-PU25TOOJ.js → chunk-JZN4RSMF.js} +1 -1
  25. package/dist/{chunk-4W55ZOOS.js → chunk-NEAVAFSJ.js} +66 -35
  26. package/dist/{chunk-C6T2AAFR.js → chunk-NIVST4WY.js} +9 -3
  27. package/dist/{chunk-ENAG6UH7.js → chunk-NKNOXQ62.js} +1 -6
  28. package/dist/{chunk-AYNZXUB5.js → chunk-OX6TSVHY.js} +5 -5
  29. package/dist/{chunk-36RYTYT5.js → chunk-PD7KTSYN.js} +1 -1
  30. package/dist/{chunk-RDIZJ7UT.js → chunk-RE7UTPWH.js} +1 -1
  31. package/dist/chunk-S5GWAUG5.js +29 -0
  32. package/dist/{chunk-T4G3VVZ4.js → chunk-YQGRMDRB.js} +4 -2
  33. package/dist/constants.cjs +1 -1
  34. package/dist/constants.js +1 -1
  35. package/dist/docs/api/02-config.md +57 -7
  36. package/dist/docs/development/00-why-eventcatalog.md +11 -11
  37. package/dist/docs/development/01-fundamentals.md +20 -13
  38. package/dist/docs/development/01-getting-started/configuration-overview.md +2 -2
  39. package/dist/docs/development/01-getting-started/installation.md +9 -1
  40. package/dist/docs/development/_getting-started.mdx +1 -1
  41. package/dist/docs/development/ask-your-architecture/01-intro.md +5 -5
  42. package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/01-what-is-eventcatalog-assistant.md +0 -4
  43. package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/02-configuration.md +15 -3
  44. package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/03-bring-your-own-tools.md +0 -3
  45. package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/_category_.json +1 -1
  46. package/dist/docs/development/ask-your-architecture/02-llms.txt.md +1 -1
  47. package/dist/docs/development/ask-your-architecture/{05-skills/01-introduction.md → 03-install-skills.md} +57 -7
  48. package/dist/docs/development/ask-your-architecture/03-mcp-server/_category_.json +1 -1
  49. package/dist/docs/development/ask-your-architecture/03-mcp-server/getting-started.md +86 -33
  50. package/dist/docs/development/ask-your-architecture/03-mcp-server/introduction.md +14 -4
  51. package/dist/docs/development/ask-your-architecture/03-schemas.txt.md +1 -1
  52. package/dist/docs/development/ask-your-architecture/04-agents/_category_.json +1 -1
  53. package/dist/docs/development/authentication/01-introduction.md +2 -23
  54. package/dist/docs/development/authentication/02-enabling-authentication.md +0 -20
  55. package/dist/docs/development/authentication/07-rbac-middleware.md +0 -2
  56. package/dist/docs/development/authentication/providers/03-setting-up-github.md +0 -2
  57. package/dist/docs/development/authentication/providers/03a-setting-up-google.md +0 -2
  58. package/dist/docs/development/authentication/providers/04-setting-up-azure-ad.md +0 -2
  59. package/dist/docs/development/authentication/providers/05-setting-up-okta.md +0 -3
  60. package/dist/docs/development/authentication/providers/06-setting-up-auth0.md +0 -2
  61. package/dist/docs/development/bring-your-own-documentation/01-introduction.md +0 -4
  62. package/dist/docs/development/bring-your-own-documentation/custom-pages/01-introduction.md +0 -3
  63. package/dist/docs/development/bring-your-own-documentation/custom-pages/02-adding-custom-docs.md +0 -17
  64. package/dist/docs/development/bring-your-own-documentation/custom-pages/03-components.md +0 -4
  65. package/dist/docs/development/bring-your-own-documentation/custom-pages/04-owners.md +0 -2
  66. package/dist/docs/development/bring-your-own-documentation/resource-docs/01-introduction.md +1 -3
  67. package/dist/docs/development/bring-your-own-documentation/resource-docs/02-adding-resource-docs.md +1 -4
  68. package/dist/docs/development/bring-your-own-documentation/resource-docs/03-categories.md +0 -2
  69. package/dist/docs/development/bring-your-own-documentation/resource-docs/04-versioning.md +1 -3
  70. package/dist/docs/development/components/components/11-flow.md +17 -0
  71. package/dist/docs/development/components/components/15-nodegraph.md +43 -10
  72. package/dist/docs/development/components/components/18-remote-schema.md +1 -4
  73. package/dist/docs/development/components/custom-components/07-reference.md +14 -0
  74. package/dist/docs/development/customization/02-themes.md +0 -5
  75. package/dist/docs/development/customization/03-search.md +1 -1
  76. package/dist/docs/development/customization/05-custom-pages-and-api-routes/01-introduction.md +0 -2
  77. package/dist/docs/development/customization/05-custom-pages-and-api-routes/04-reference.md +7 -1
  78. package/dist/docs/development/customization/05-resource-sidebar.md +1 -1
  79. package/dist/docs/development/customization/09-embed-eventcatalog.md +20 -25
  80. package/dist/docs/development/deployment/hosting-options.md +7 -2
  81. package/dist/docs/development/developer-tools/eventcatalog-linter/how-to/05-fix-common-problems.md +16 -0
  82. package/dist/docs/development/developer-tools/eventcatalog-linter/reference/03-rules.md +31 -1
  83. package/dist/docs/development/developer-tools/eventcatalog-linter/reference/05-supported-resources.md +1 -1
  84. package/dist/docs/development/governance/architecture-change-detection/01-introduction.md +0 -10
  85. package/dist/docs/development/governance/architecture-change-detection/06-pipeline-gates.md +0 -4
  86. package/dist/docs/development/guides/97-architecture-graph.md +1 -1
  87. package/dist/docs/development/guides/99-adding-analytics.md +0 -7
  88. package/dist/docs/development/guides/domains/03-model-subdomains.md +2 -2
  89. package/dist/docs/development/guides/domains/04-add-resources-to-domains/01-add-systems-to-domains.md +3 -1
  90. package/dist/docs/development/guides/domains/04-add-resources-to-domains/02-add-services-to-domains.md +5 -1
  91. package/dist/docs/development/guides/domains/04-add-resources-to-domains/03-add-messages-to-domains.md +2 -2
  92. package/dist/docs/development/guides/domains/04-add-resources-to-domains/05-add-entities-to-domains.md +1 -1
  93. package/dist/docs/development/guides/domains/04-add-resources-to-domains/06-domain-resources-page.md +40 -0
  94. package/dist/docs/development/guides/domains/06-visualize-domains/01-domain-diagram.md +89 -0
  95. package/dist/docs/development/guides/domains/06-visualize-domains/_category_.json +1 -2
  96. package/dist/docs/development/guides/domains/09-reference.md +4 -4
  97. package/dist/docs/development/guides/owners/automated-teams-and-users/create-your-own-connector.md +0 -2
  98. package/dist/docs/development/guides/owners/automated-teams-and-users/sync-from-github.md +0 -3
  99. package/dist/docs/development/guides/owners/automated-teams-and-users/sync-from-microsoft-entra.md +0 -2
  100. package/dist/docs/development/guides/resources/adrs/03-linking-resources.md +8 -0
  101. package/dist/docs/development/guides/resources/adrs/06-reference.md +4 -4
  102. package/dist/docs/development/guides/resources/agents/11-reference.md +1 -1
  103. package/dist/docs/development/guides/resources/data/04-reference.md +1 -1
  104. package/dist/docs/development/guides/resources/data-products/07-reference.md +1 -1
  105. package/dist/docs/development/guides/resources/entities/05-entity-maps.md +1 -1
  106. package/dist/docs/development/guides/resources/entities/06-reference.md +2 -2
  107. package/dist/docs/development/guides/resources/flows/01-introduction.md +11 -1
  108. package/dist/docs/development/guides/resources/flows/03-model-flow-steps.md +65 -6
  109. package/dist/docs/development/guides/resources/flows/05-explore-flows.md +112 -0
  110. package/dist/docs/development/guides/resources/flows/06-reference.md +25 -4
  111. package/dist/docs/development/guides/resources/messages/01-what-are-messages.md +19 -0
  112. package/dist/docs/development/guides/resources/messages/04-message-channels/01-introduction.md +16 -0
  113. package/dist/docs/development/guides/resources/messages/04-message-channels/05-reference.md +2 -1
  114. package/dist/docs/development/guides/resources/messages/10-reference.md +6 -3
  115. package/dist/docs/development/guides/resources/schemas/04-explore-schemas/01-schema-explorer.md +2 -2
  116. package/dist/docs/development/guides/resources/schemas/04-explore-schemas/02-fields-explorer.md +0 -9
  117. package/dist/docs/development/guides/resources/schemas/05-schema-api.md +0 -3
  118. package/dist/docs/development/guides/resources/schemas/06-schema-mcp.md +11 -3
  119. package/dist/docs/development/guides/resources/services/04-add-resources-to-services/03-add-entities-to-services.md +1 -1
  120. package/dist/docs/development/guides/resources/services/05-resources-page.md +50 -0
  121. package/dist/docs/development/guides/resources/services/08-reference.md +2 -1
  122. package/dist/docs/development/guides/systems/01-introduction.md +1 -1
  123. package/dist/docs/development/guides/systems/02-create-system.md +2 -2
  124. package/dist/docs/development/guides/systems/03-add-resources-to-systems.md +35 -9
  125. package/dist/docs/development/guides/systems/04-model-relationships-and-actors.md +5 -3
  126. package/dist/docs/development/guides/systems/05-system-context-maps.md +39 -22
  127. package/dist/docs/development/guides/systems/06-reference.md +4 -4
  128. package/dist/docs/development/license/01-license-file.md +151 -0
  129. package/dist/docs/development/license/_category_.json +12 -0
  130. package/dist/docs/development/license-keys/_category_.json +3 -3
  131. package/dist/docs/development/license-keys/integrations.md +7 -37
  132. package/dist/docs/development/license-keys/license-validation.md +4 -0
  133. package/dist/docs/development/license-keys/overview.md +5 -1
  134. package/dist/docs/development/license-keys/plans.md +4 -2
  135. package/dist/docs/development/studio/01-introduction.md +60 -0
  136. package/dist/docs/development/studio/02-create-a-canvas.md +103 -0
  137. package/dist/docs/development/studio/03-set-up-persistent-storage.md +59 -0
  138. package/dist/docs/development/studio/04-collaborate-on-a-canvas.md +78 -0
  139. package/dist/docs/development/studio/05-connect-your-agent.md +102 -0
  140. package/dist/docs/development/studio/06-run-studio-in-production.md +54 -0
  141. package/dist/docs/development/studio/07-reference.md +294 -0
  142. package/dist/docs/development/studio/_category_.json +12 -0
  143. package/dist/docs/development/upgrading/v5.md +345 -0
  144. package/dist/docs/federation/00-overview.md +2 -8
  145. package/dist/docs/federation/01-first-federation.md +6 -18
  146. package/dist/docs/federation/explanation/how-it-works.md +0 -4
  147. package/dist/docs/federation/explanation/lockfile-and-cache.md +0 -4
  148. package/dist/docs/federation/explanation/mvp-status-and-feedback.md +0 -4
  149. package/dist/docs/federation/explanation/ownership-and-references.md +0 -4
  150. package/dist/docs/federation/how-to/configure-github-sources.md +6 -5
  151. package/dist/docs/federation/how-to/configure-validation-rules.md +0 -4
  152. package/dist/docs/federation/how-to/run-in-ci.md +2 -9
  153. package/dist/docs/federation/how-to/share-assets-and-components.md +0 -4
  154. package/dist/docs/federation/how-to/use-local-sources.md +0 -4
  155. package/dist/docs/federation/legacy-federation/00-introduction.md +4 -22
  156. package/dist/docs/federation/legacy-federation/01-installation.md +7 -58
  157. package/dist/docs/federation/legacy-federation/02-plugin-configuration.md +3 -21
  158. package/dist/docs/federation/legacy-federation/03-examples.md +3 -5
  159. package/dist/docs/federation/legacy-federation/04-configuration.md +3 -8
  160. package/dist/docs/federation/legacy-federation/05-setup-team-catalog.md +3 -6
  161. package/dist/docs/federation/reference/cli.md +2 -8
  162. package/dist/docs/federation/reference/configuration.md +0 -4
  163. package/dist/docs/federation/reference/diagnostic-rules.md +0 -5
  164. package/dist/docs/federation/reference/generated-output.md +0 -4
  165. package/dist/docs/federation/reference/supported-content.md +0 -4
  166. package/dist/docs/federation/reference/troubleshooting.md +0 -14
  167. package/dist/docs/plugins/02-generators.md +1 -1
  168. package/dist/docs/plugins/amazon-apigateway/00-intro.md +3 -28
  169. package/dist/docs/plugins/amazon-apigateway/01-installation.md +4 -56
  170. package/dist/docs/plugins/amazon-apigateway/02-plugin-configuration.md +1 -6
  171. package/dist/docs/plugins/apicurio/00-intro.md +2 -31
  172. package/dist/docs/plugins/apicurio/01-installation.md +2 -26
  173. package/dist/docs/plugins/apicurio/02-plugin-configuration.md +5 -13
  174. package/dist/docs/plugins/apicurio/03-features.md +1 -3
  175. package/dist/docs/plugins/asyncapi/00-intro.md +2 -28
  176. package/dist/docs/plugins/asyncapi/01-installation.md +3 -54
  177. package/dist/docs/plugins/asyncapi/02-plugin-configuration.md +2 -1
  178. package/dist/docs/plugins/aws-glue-registry/00-intro.md +4 -32
  179. package/dist/docs/plugins/aws-glue-registry/00a-installation.md +3 -53
  180. package/dist/docs/plugins/azure-schema-registry/00-intro.md +4 -32
  181. package/dist/docs/plugins/azure-schema-registry/01-installation.md +6 -33
  182. package/dist/docs/plugins/azure-schema-registry/02-plugin-configuration.md +1 -14
  183. package/dist/docs/plugins/azure-schema-registry/04-examples.md +0 -2
  184. package/dist/docs/plugins/backstage/00-overview.md +1 -7
  185. package/dist/docs/plugins/backstage/01-get-started.md +6 -15
  186. package/dist/docs/plugins/backstage/06-configuration.md +2 -8
  187. package/dist/docs/plugins/confluent-schema-registry/00-intro.md +2 -29
  188. package/dist/docs/plugins/confluent-schema-registry/01-installation.md +2 -26
  189. package/dist/docs/plugins/eventbridge/00-intro.md +0 -4
  190. package/dist/docs/plugins/eventbridge/00a-installation.md +1 -87
  191. package/dist/docs/plugins/eventbridge/03-api.md +2 -20
  192. package/dist/docs/plugins/github/00-intro.md +0 -31
  193. package/dist/docs/plugins/github/01-installation.md +2 -34
  194. package/dist/docs/plugins/graphql/00-intro.md +0 -30
  195. package/dist/docs/plugins/graphql/01-installation.md +1 -53
  196. package/dist/docs/plugins/graphql/02-plugin-configuration.md +0 -1
  197. package/dist/docs/plugins/hookdeck/01-intro.md +1 -1
  198. package/dist/docs/plugins/openapi/00-intro.md +0 -30
  199. package/dist/docs/plugins/openapi/01-installation.md +1 -57
  200. package/dist/docs/plugins/openapi/02-plugin-configuration.md +0 -5
  201. package/dist/docs/plugins/openapi/03-features.md +0 -4
  202. package/dist/eventcatalog-config-file-utils.cjs +34 -41
  203. package/dist/eventcatalog-config-file-utils.d.cts +56 -58
  204. package/dist/eventcatalog-config-file-utils.d.ts +56 -58
  205. package/dist/eventcatalog-config-file-utils.js +1 -1
  206. package/dist/eventcatalog.cjs +408 -281
  207. package/dist/eventcatalog.config.d.cts +26 -15
  208. package/dist/eventcatalog.config.d.ts +26 -15
  209. package/dist/eventcatalog.js +46 -27
  210. package/dist/features.cjs +36 -49
  211. package/dist/features.d.cts +1 -3
  212. package/dist/features.d.ts +1 -3
  213. package/dist/features.js +4 -6
  214. package/dist/federation/federate.cjs +37 -44
  215. package/dist/federation/federate.js +5 -5
  216. package/dist/federation/source-provider.js +2 -2
  217. package/dist/generate.cjs +37 -42
  218. package/dist/generate.js +4 -4
  219. package/dist/resolve-catalog-dependencies.cjs +34 -41
  220. package/dist/resolve-catalog-dependencies.js +2 -2
  221. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio-fonts.css.mjs +3 -0
  222. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.css.mjs +3 -0
  223. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.mjs +3 -0
  224. package/dist/runtime-dependencies/htmlparser2.mjs +3 -0
  225. package/dist/runtime-dependencies/manifest.json +5 -1
  226. package/dist/runtime-dependencies/react-syntax-highlighter__dist__cjs__create-element.js.mjs +3 -0
  227. package/dist/utils/child-process-signals.cjs +53 -0
  228. package/dist/utils/child-process-signals.d.cts +19 -0
  229. package/dist/utils/child-process-signals.d.ts +19 -0
  230. package/dist/utils/child-process-signals.js +6 -0
  231. package/dist/utils/cli-logger.cjs +1 -1
  232. package/dist/utils/cli-logger.js +2 -2
  233. package/dist/utils/license-status.cjs +11 -4
  234. package/dist/utils/license-status.d.cts +3 -2
  235. package/dist/utils/license-status.d.ts +3 -2
  236. package/dist/utils/license-status.js +1 -1
  237. package/eventcatalog/astro.config.mjs +21 -1
  238. package/eventcatalog/integrations/config-loader.mjs +56 -58
  239. package/eventcatalog/integrations/skip-startup-reload.mjs +31 -0
  240. package/eventcatalog/integrations/stable-dependency-order.mjs +29 -0
  241. package/eventcatalog/integrations/storage.mjs +20 -0
  242. package/eventcatalog/integrations/studio-server.mjs +4 -1
  243. package/eventcatalog/src/components/CatalogGraph/CatalogForceGraph.tsx +39 -0
  244. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +2 -0
  245. package/eventcatalog/src/components/Homepage/CatalogDashboard.astro +342 -0
  246. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +60 -4
  247. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -1
  248. package/eventcatalog/src/components/NavigationProgress.astro +7 -0
  249. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +2 -0
  250. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +2 -0
  251. package/eventcatalog/src/components/SchemaExplorer/SchemaCodeModal.tsx +2 -0
  252. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -0
  253. package/eventcatalog/src/components/Search/SearchDataLoader.astro +16 -28
  254. package/eventcatalog/src/components/Search/SearchModal.tsx +2 -10
  255. package/eventcatalog/src/components/Search/search-utils.ts +26 -0
  256. package/eventcatalog/src/components/Seo.astro +5 -1
  257. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +53 -48
  258. package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +183 -178
  259. package/eventcatalog/src/components/Settings/LicenseSettings.tsx +140 -31
  260. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +40 -35
  261. package/eventcatalog/src/components/Settings/LogoUpload.tsx +1 -1
  262. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +9 -8
  263. package/eventcatalog/src/components/Settings/Row.tsx +7 -4
  264. package/eventcatalog/src/components/Settings/SettingsShared.tsx +3 -3
  265. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +37 -76
  266. package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +2 -0
  267. package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +122 -1
  268. package/eventcatalog/src/components/SideNav/SideNav.astro +9 -1
  269. package/eventcatalog/src/components/TrialBadge.astro +20 -9
  270. package/eventcatalog/src/content.config.ts +19 -2
  271. package/eventcatalog/src/features/auth/error.astro +4 -2
  272. package/eventcatalog/src/features/auth/login.astro +2 -1
  273. package/eventcatalog/src/features/auth/middleware/middleware-auth.ts +21 -1
  274. package/eventcatalog/src/features/auth/unauthorized.astro +1 -1
  275. package/eventcatalog/src/features/fields/pages/fields.astro +1 -1
  276. package/eventcatalog/src/features/integrations/eventcatalog-features.ts +13 -7
  277. package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +6 -45
  278. package/eventcatalog/src/features/mcp/apps/canvas/shared.ts +3 -3
  279. package/eventcatalog/src/features/mcp/apps/canvas/styles.css +3 -1
  280. package/eventcatalog/src/features/mcp/apps/canvas/view.tsx +7 -5
  281. package/eventcatalog/src/features/mcp/apps/generated/canvas.html +123 -98
  282. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +118 -101
  283. package/eventcatalog/src/features/mcp/mcp-server.ts +20 -4
  284. package/eventcatalog/src/features/server/start.ts +25 -0
  285. package/eventcatalog/src/features/storage/database.ts +88 -0
  286. package/eventcatalog/src/features/storage/migrations.ts +85 -0
  287. package/eventcatalog/src/features/storage/sql/database.sql +5 -0
  288. package/eventcatalog/src/features/storage/sql/migrations/0001-studio-canvases.sql +12 -0
  289. package/eventcatalog/src/features/storage/sql/migrations.sql +15 -0
  290. package/eventcatalog/src/features/storage/sql.ts +28 -0
  291. package/eventcatalog/src/features/studio/agent-choreography.ts +13 -10
  292. package/eventcatalog/src/features/studio/agents.ts +28 -0
  293. package/eventcatalog/src/features/studio/api/canvases-api.ts +219 -0
  294. package/eventcatalog/src/features/studio/api/canvases.ts +25 -0
  295. package/eventcatalog/src/features/studio/api/client.ts +40 -0
  296. package/eventcatalog/src/features/studio/canvas-actions.ts +160 -34
  297. package/eventcatalog/src/features/studio/canvas-preview.ts +1 -2
  298. package/eventcatalog/src/features/studio/catalog.ts +16 -14
  299. package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +274 -105
  300. package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +15 -14
  301. package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +272 -119
  302. package/eventcatalog/src/features/studio/components/ConnectionsChooser.tsx +1 -2
  303. package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +65 -0
  304. package/eventcatalog/src/features/studio/components/Dialog.tsx +60 -0
  305. package/eventcatalog/src/features/studio/components/JoinForm.tsx +101 -26
  306. package/eventcatalog/src/features/studio/components/LeftPanel.tsx +122 -230
  307. package/eventcatalog/src/features/studio/components/NodeDetails.tsx +183 -0
  308. package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +79 -0
  309. package/eventcatalog/src/features/studio/components/Presence.tsx +52 -45
  310. package/eventcatalog/src/features/studio/components/ShareDialog.tsx +277 -141
  311. package/eventcatalog/src/features/studio/components/ShortcutsDialog.tsx +41 -0
  312. package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +1314 -385
  313. package/eventcatalog/src/features/studio/components/StudioNotice.astro +24 -0
  314. package/eventcatalog/src/features/studio/document-name.ts +7 -0
  315. package/eventcatalog/src/features/studio/from-visualiser.ts +138 -0
  316. package/eventcatalog/src/features/studio/hooks/presence-sender.ts +19 -2
  317. package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +9 -3
  318. package/eventcatalog/src/features/studio/hooks/use-comments.ts +2 -2
  319. package/eventcatalog/src/features/studio/hooks/use-follow-camera.ts +8 -3
  320. package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +244 -32
  321. package/eventcatalog/src/features/studio/identity.ts +25 -1
  322. package/eventcatalog/src/features/studio/limits.ts +2 -0
  323. package/eventcatalog/src/features/studio/pages/[id].astro +42 -16
  324. package/eventcatalog/src/features/studio/pages/index.astro +596 -373
  325. package/eventcatalog/src/features/studio/pages/webmcp-relay.ts +12 -15
  326. package/eventcatalog/src/features/studio/server/canvas-mcp.ts +8 -23
  327. package/eventcatalog/src/features/studio/server/runtime.ts +150 -46
  328. package/eventcatalog/src/features/studio/server/sql/storage.sql +18 -0
  329. package/eventcatalog/src/features/studio/server/storage.ts +53 -73
  330. package/eventcatalog/src/features/studio/webmcp-relay/LICENSE +21 -0
  331. package/eventcatalog/src/features/studio/webmcp-relay/README.md +5 -0
  332. package/eventcatalog/src/features/studio/webmcp-relay/embed.js +2 -0
  333. package/eventcatalog/src/features/studio/webmcp-relay/widget.html +10 -0
  334. package/eventcatalog/src/features/studio/webmcp-relay/widget.js +1 -0
  335. package/eventcatalog/src/features/tools/catalog-tools.ts +3 -1
  336. package/eventcatalog/src/layouts/BaseLayout.astro +4 -4
  337. package/eventcatalog/src/layouts/SettingsLayout.astro +2 -2
  338. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +3 -2
  339. package/eventcatalog/src/pages/_index.astro +5 -342
  340. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.spec.ts +2 -3
  341. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +0 -7
  342. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -1
  343. package/eventcatalog/src/pages/diagrams/[id]/[version]/_index.data.ts +0 -7
  344. package/eventcatalog/src/pages/diagrams/[id]/[version]/embed.astro +1 -0
  345. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +1 -0
  346. package/eventcatalog/src/pages/directory/[type]/_index.data.ts +5 -7
  347. package/eventcatalog/src/pages/directory/[type]/index.astro +3 -1
  348. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -7
  349. package/eventcatalog/src/pages/discover/[type]/index.astro +3 -1
  350. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +0 -7
  351. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -0
  352. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +0 -7
  353. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -0
  354. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +0 -7
  355. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +3 -1
  356. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/_[filename].data.ts +0 -7
  357. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +0 -7
  358. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +1 -0
  359. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +1 -0
  360. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/_[...filename].data.ts +0 -4
  361. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/_index.data.ts +0 -7
  362. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/field-lineage/index.astro +1 -0
  363. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +3 -1
  364. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/_[filename].data.ts +0 -7
  365. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +1 -0
  366. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.spec.ts +2 -3
  367. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +0 -7
  368. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +1 -0
  369. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +1 -0
  370. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/_[filename].data.ts +0 -7
  371. package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +0 -7
  372. package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +2 -1
  373. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/_index.data.ts +0 -7
  374. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +1 -0
  375. package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +0 -7
  376. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +1 -0
  377. package/eventcatalog/src/pages/docs/custom/[...path]/_index.data.ts +0 -7
  378. package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +1 -0
  379. package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +1 -1
  380. package/eventcatalog/src/pages/docs/services/[id]/[version]/resources/index.astro +1 -0
  381. package/eventcatalog/src/pages/docs/services/[id]/asyncapi/[filename].astro +1 -1
  382. package/eventcatalog/src/pages/docs/services/[id]/changelog/index.astro +1 -1
  383. package/eventcatalog/src/pages/docs/services/[id]/graphql/[filename].astro +1 -1
  384. package/eventcatalog/src/pages/docs/services/[id]/spec/[filename].astro +1 -1
  385. package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +0 -7
  386. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +1 -0
  387. package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +0 -7
  388. package/eventcatalog/src/pages/docs/users/[id]/index.astro +1 -0
  389. package/eventcatalog/src/pages/index.astro +4 -2
  390. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +0 -7
  391. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +9 -1
  392. package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +0 -7
  393. package/eventcatalog/src/pages/schemas/explorer/index.astro +4 -2
  394. package/eventcatalog/src/pages/settings/license.astro +9 -1
  395. package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/_index.data.ts +0 -7
  396. package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +1 -0
  397. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +0 -7
  398. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/_index.data.ts +0 -7
  399. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +1 -0
  400. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/_index.data.ts +0 -7
  401. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -0
  402. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -0
  403. package/eventcatalog/src/pages/visualiser/[type]/[id]/_index.data.ts +38 -0
  404. package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +18 -41
  405. package/eventcatalog/src/pages/visualiser/designs/[id]/_index.data.ts +0 -7
  406. package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -1
  407. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/_index.data.ts +0 -7
  408. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -0
  409. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +1 -0
  410. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +0 -7
  411. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +1 -0
  412. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +0 -7
  413. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +1 -0
  414. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +1 -0
  415. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +10 -0
  416. package/eventcatalog/src/utils/collections/flows.ts +20 -7
  417. package/eventcatalog/src/utils/collections/resource-owners.ts +8 -2
  418. package/eventcatalog/src/utils/collections/resources.ts +2 -0
  419. package/eventcatalog/src/utils/collections/util.ts +8 -4
  420. package/eventcatalog/src/utils/git.ts +11 -0
  421. package/eventcatalog/src/utils/homepage-dashboard.ts +143 -0
  422. package/eventcatalog/src/utils/license.ts +1 -1
  423. package/eventcatalog/src/utils/link-validation.ts +25 -19
  424. package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +3 -1
  425. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +3 -3
  426. package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +4 -2
  427. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +20 -1
  428. package/eventcatalog/src/utils/node-graphs/node-resource.ts +67 -0
  429. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +1 -1
  430. package/eventcatalog/src/utils/page-loaders/hybrid-page.ts +4 -15
  431. package/eventcatalog/src/utils/page-title.ts +15 -0
  432. package/eventcatalog/src/utils/syntax-highlighter-renderer.ts +64 -0
  433. package/eventcatalog/src/utils/trial.ts +13 -0
  434. package/package.json +11 -11
  435. package/dist/docs/development/ask-your-architecture/05-skills/02-installation.md +0 -60
  436. package/dist/docs/development/ask-your-architecture/05-skills/_category_.json +0 -11
  437. package/dist/docs/development/ask-your-architecture/06-slack-integration/01-introduction.md +0 -63
  438. package/dist/docs/development/ask-your-architecture/06-slack-integration/02-slack-app-setup.md +0 -154
  439. package/dist/docs/development/ask-your-architecture/06-slack-integration/03-installation.md +0 -169
  440. package/dist/docs/development/ask-your-architecture/06-slack-integration/04-deployment.md +0 -236
  441. package/dist/docs/development/ask-your-architecture/06-slack-integration/05-usage.md +0 -140
  442. package/dist/docs/development/ask-your-architecture/06-slack-integration/06-troubleshooting.md +0 -268
  443. package/dist/docs/development/ask-your-architecture/06-slack-integration/_category_.json +0 -13
  444. package/dist/docs/development/guides/domains/06-visualize-domains/01-domain-integration-map.md +0 -40
  445. package/dist/runtime-dependencies/@mcp-b__webmcp-local-relay.mjs +0 -3
  446. package/eventcatalog/src/features/studio/canvas-doc.ts +0 -409
  447. package/eventcatalog/src/features/studio/clipboard.ts +0 -97
  448. package/eventcatalog/src/features/studio/components/CanvasControls.tsx +0 -154
  449. package/eventcatalog/src/features/studio/components/Comments.tsx +0 -770
  450. package/eventcatalog/src/features/studio/components/ContainerChooser.tsx +0 -145
  451. package/eventcatalog/src/features/studio/components/DragGhost.tsx +0 -115
  452. package/eventcatalog/src/features/studio/components/Picture.tsx +0 -21
  453. package/eventcatalog/src/features/studio/components/PropertiesPanel.tsx +0 -212
  454. package/eventcatalog/src/features/studio/components/canvas-nodes.tsx +0 -255
  455. package/eventcatalog/src/features/studio/components/icons.ts +0 -53
  456. package/eventcatalog/src/features/studio/components/status.ts +0 -51
  457. package/eventcatalog/src/features/studio/edges.ts +0 -56
  458. package/eventcatalog/src/features/studio/flow-state.ts +0 -92
  459. package/eventcatalog/src/features/studio/grouping.ts +0 -226
  460. package/eventcatalog/src/features/studio/layout.ts +0 -42
  461. package/eventcatalog/src/features/studio/levels.ts +0 -282
  462. package/eventcatalog/src/features/studio/node-types.ts +0 -205
  463. package/eventcatalog/src/features/studio/pages/new.astro +0 -24
  464. package/eventcatalog/src/features/studio/pages/wake.ts +0 -15
  465. package/eventcatalog/src/features/studio/placement.ts +0 -197
  466. package/eventcatalog/src/features/studio/studio.css +0 -273
  467. package/dist/{chunk-A2RZR3U4.js → chunk-6K7XZAYI.js} +3 -3
@@ -1,7 +1,7 @@
1
- import { useEffect, useState } from 'react';
2
- import { Bot, Check, ChevronDown, Copy, X } from 'lucide-react';
1
+ import { useEffect, useState, type ReactNode } from 'react';
2
+ import { Check, ChevronDown, Code2, Copy, Globe, Sparkles, X } from 'lucide-react';
3
3
  import type { WebMcpStatus } from '../hooks/use-canvas-webmcp';
4
- import { STATUS } from './status';
4
+ import { STATUS, ClaudeCodeLogo, ClaudeLogo, CursorLogo, OpenAILogo } from '@eventcatalog/visualiser/studio';
5
5
 
6
6
  type CanvasLink = { canvasId: string; title?: string; canvasUrl: string; mcpUrl: string };
7
7
 
@@ -72,41 +72,56 @@ Connect with the first of these you can use:
72
72
 
73
73
  Once connected:
74
74
  - Read the canvas first (getCanvas / get_canvas) and tell me here who else is on it.
75
- - Ask me here, in our conversation, what we are designing, then work on the canvas as we talk: add catalog resources (find them with getResources / search_catalog), add new components for things that don't exist yet, and connect them. Leave out positions so new nodes go next to what they connect to; only re-lay the whole canvas (layoutCanvas / layout_canvas) when I ask.
75
+ - Ask me here, in our conversation, what we are designing, then work on the canvas as we talk: add catalog resources (find them with getResources / search_catalog), add new components for things that don't exist yet, and connect them. Leave out positions so new nodes go next to what they connect to. When you finish a round of changes, tidy the whole canvas once (layoutCanvas / layout_canvas) before you hand back to me, unless I asked you to keep the layout.
76
76
  - Talk to me here, not in canvas comments. Only comment on the canvas when I ask you to (e.g. to review it), and reply to comments people leave for you.
77
77
  - Pass agentName with your name on MCP tools, so people on the canvas can see who you are.`;
78
78
 
79
- function CopyButton({ text, label = 'Copy', large = false }: { text: string; label?: string; large?: boolean }) {
80
- const [copied, setCopied] = useState(false);
81
- return (
82
- <button
83
- onClick={async () => {
84
- await navigator.clipboard.writeText(text);
85
- setCopied(true);
86
- setTimeout(() => setCopied(false), 1500);
87
- }}
88
- className={`flex shrink-0 items-center justify-center gap-1.5 rounded-lg font-medium bg-[rgb(var(--ec-button-bg))] text-[rgb(var(--ec-button-text))] hover:bg-[rgb(var(--ec-button-bg-hover))] ${
89
- large ? 'w-full px-4 py-2.5 text-sm' : 'px-2.5 py-1.5 text-xs'
90
- }`}
91
- >
92
- {copied ? <Check size={large ? 16 : 14} /> : <Copy size={large ? 16 : 14} />}
93
- {copied ? 'Copied' : label}
94
- </button>
95
- );
96
- }
79
+ const button =
80
+ 'inline-flex h-9 flex-none items-center justify-center gap-2 rounded-lg px-4 text-sm font-medium transition-colors [&_svg]:h-4 [&_svg]:w-4';
81
+ const primary = `${button} bg-[rgb(var(--ec-page-text))] text-[rgb(var(--ec-page-bg))] hover:bg-[rgb(var(--ec-page-text)/0.85)]`;
82
+ const secondary = `${button} border border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))]`;
83
+
84
+ const copyText = async (text: string) => {
85
+ try {
86
+ await navigator.clipboard.writeText(text);
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ };
97
92
 
98
- /** Something to copy (an address or a command), with its copy button */
99
- function CopyField({ value }: { value: string }) {
93
+ /** Something to copy, with a button that copies it (as Studio on the web's) */
94
+ function Snippet({ text, label }: { text: string; label: string }) {
95
+ const [copied, setCopied] = useState(false);
96
+ useEffect(() => {
97
+ if (!copied) return;
98
+ const timer = setTimeout(() => setCopied(false), 1500);
99
+ return () => clearTimeout(timer);
100
+ }, [copied]);
100
101
  return (
101
- <div className="flex items-center gap-2">
102
- <code className="min-w-0 flex-1 truncate rounded-md border px-2 py-1.5 text-xs bg-[rgb(var(--ec-input-bg))] border-[rgb(var(--ec-input-border))]">
103
- {value}
104
- </code>
105
- <CopyButton text={value} />
102
+ <div className="relative mt-2 rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover))]">
103
+ <pre className="overflow-x-auto whitespace-pre p-3 pr-12 font-mono text-xs leading-relaxed text-[rgb(var(--ec-page-text))]">
104
+ {text}
105
+ </pre>
106
+ <button
107
+ type="button"
108
+ aria-label={`Copy ${label}`}
109
+ title="Copy"
110
+ onClick={async () => setCopied(await copyText(text))}
111
+ className="absolute right-2 top-2 rounded-md p-1.5 text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-card-bg))] hover:text-[rgb(var(--ec-page-text))] [&_svg]:h-4 [&_svg]:w-4"
112
+ >
113
+ {copied ? <Check aria-hidden /> : <Copy aria-hidden />}
114
+ </button>
106
115
  </div>
107
116
  );
108
117
  }
109
118
 
119
+ const Steps = ({ children }: { children: ReactNode }) => (
120
+ <ol className="list-decimal space-y-2 pl-5 text-sm leading-relaxed text-[rgb(var(--ec-page-text))] marker:text-[rgb(var(--ec-page-text-muted))]">
121
+ {children}
122
+ </ol>
123
+ );
124
+
110
125
  /** Turns something on for this tab, or says it's on */
111
126
  function TabSwitch({ on, onTurnOn, label }: { on: boolean; onTurnOn: () => void; label: string }) {
112
127
  return on ? (
@@ -115,25 +130,36 @@ function TabSwitch({ on, onTurnOn, label }: { on: boolean; onTurnOn: () => void;
115
130
  On for this tab
116
131
  </p>
117
132
  ) : (
118
- <button
119
- onClick={onTurnOn}
120
- className="shrink-0 whitespace-nowrap rounded-lg border px-2.5 py-1.5 text-xs font-medium border-[rgb(var(--ec-page-border))] hover:bg-[rgb(var(--ec-page-border)/0.4)]"
121
- >
133
+ <button type="button" onClick={onTurnOn} className={`${secondary} h-8 px-3 text-xs`}>
122
134
  {label}
123
135
  </button>
124
136
  );
125
137
  }
126
138
 
127
- type Way = 'chat' | 'code' | 'browser';
128
- const WAYS: { id: Way; label: string; hint: string }[] = [
129
- { id: 'chat', label: 'Chat app', hint: 'Claude, ChatGPT' },
130
- { id: 'code', label: 'Coding agent', hint: 'Claude Code, Cursor, Codex' },
131
- { id: 'browser', label: 'This browser', hint: 'WebMCP' },
139
+ /** Things to ask, for the two ways of pairing with an agent on a canvas: designing something new, and understanding what's there */
140
+ const PAIRING = [
141
+ {
142
+ title: 'Design ideas together',
143
+ prompts: [
144
+ 'Add a payments service that listens to OrderPlaced',
145
+ 'How could we split the orders service?',
146
+ 'Add retries and a dead letter queue to this',
147
+ ],
148
+ },
149
+ {
150
+ title: 'Understand how it works',
151
+ prompts: [
152
+ 'Put everything the Orders domain owns on the canvas',
153
+ 'Walk me through what happens when a payment fails',
154
+ 'Which services consume this event?',
155
+ ],
156
+ },
132
157
  ];
133
158
 
134
159
  /**
135
- * Bringing an AI agent onto the canvas: copy the prompt and give it to the agent (it works out how to connect).
136
- * The prompt is there to read, and how each kind of agent connects is one step each, for setting it up by hand.
160
+ * Bringing an AI agent onto the canvas, as Studio on the web does it: how to add EventCatalog's MCP server to each
161
+ * common client, a step or two each with what to copy, and what to ask it. The quickest way first: a prompt to give
162
+ * the agent, which works out how to connect (and which canvas to join) itself. Agents in this browser use WebMCP.
137
163
  */
138
164
  export default function ConnectAgentDialog({
139
165
  link,
@@ -151,15 +177,22 @@ export default function ConnectAgentDialog({
151
177
  onClose: () => void;
152
178
  }) {
153
179
  const prompt = buildAgentPrompt(link);
180
+ const { mcpUrl, canvasId } = link;
154
181
  const [relayOn, setRelayOn] = useState(isRelayEnabled);
155
182
  const [showPrompt, setShowPrompt] = useState(false);
156
- const [way, setWay] = useState<Way>('chat');
183
+ const [promptCopied, setPromptCopied] = useState(false);
184
+ const [client, setClient] = useState(0);
157
185
 
158
186
  useEffect(() => {
159
187
  const onKeyDown = (event: KeyboardEvent) => event.key === 'Escape' && onClose();
160
188
  window.addEventListener('keydown', onKeyDown);
161
189
  return () => window.removeEventListener('keydown', onKeyDown);
162
190
  }, [onClose]);
191
+ useEffect(() => {
192
+ if (!promptCopied) return;
193
+ const timer = setTimeout(() => setPromptCopied(false), 1500);
194
+ return () => clearTimeout(timer);
195
+ }, [promptCopied]);
163
196
 
164
197
  const turnOnRelay = () => {
165
198
  if (!relayScriptPath) return;
@@ -169,111 +202,231 @@ export default function ConnectAgentDialog({
169
202
  onEnableWebMcp();
170
203
  };
171
204
 
205
+ const joinThisCanvas = (
206
+ <>
207
+ Ask it to join this canvas (<code className="text-xs">{canvasId}</code>), or paste the prompt above, and start pairing (try
208
+ one of the prompts below).
209
+ </>
210
+ );
211
+ const clients: { name: string; logo: ReactNode; body: ReactNode }[] = [
212
+ {
213
+ name: 'Claude',
214
+ logo: <ClaudeLogo />,
215
+ body: (
216
+ <Steps>
217
+ <li>
218
+ In Claude, open <strong>Settings → Connectors</strong> and choose <strong>Add custom connector</strong>.
219
+ </li>
220
+ <li>
221
+ Name it <strong>EventCatalog</strong> and paste this URL:
222
+ <Snippet text={mcpUrl} label="the URL" />
223
+ </li>
224
+ <li>In a chat, turn the connector on. {joinThisCanvas}</li>
225
+ </Steps>
226
+ ),
227
+ },
228
+ {
229
+ name: 'Claude Code',
230
+ logo: <ClaudeCodeLogo />,
231
+ body: (
232
+ <>
233
+ <Steps>
234
+ <li>
235
+ Run this in your project:
236
+ <Snippet text={`claude mcp add --transport http eventcatalog ${mcpUrl}`} label="the command" />
237
+ </li>
238
+ <li>{joinThisCanvas}</li>
239
+ </Steps>
240
+ {relayScriptPath && (
241
+ <div className="mt-4 flex items-center justify-between gap-3 rounded-lg border border-[rgb(var(--ec-page-border))] p-3">
242
+ <p className="text-xs text-[rgb(var(--ec-page-text-muted))]">
243
+ Can't reach this EventCatalog from your computer? Use this tab through the local relay: add{' '}
244
+ <code>{RELAY_COMMAND}</code> as an MCP server.
245
+ </p>
246
+ <TabSwitch on={relayOn} onTurnOn={turnOnRelay} label="Turn on relay" />
247
+ </div>
248
+ )}
249
+ </>
250
+ ),
251
+ },
252
+ {
253
+ name: 'ChatGPT',
254
+ logo: <OpenAILogo />,
255
+ body: (
256
+ <Steps>
257
+ <li>
258
+ In ChatGPT, open <strong>Settings → Apps &amp; Connectors</strong>, turn on developer mode and choose{' '}
259
+ <strong>Create</strong>.
260
+ </li>
261
+ <li>
262
+ Name it <strong>EventCatalog</strong> and paste this URL:
263
+ <Snippet text={mcpUrl} label="the URL" />
264
+ </li>
265
+ <li>In a chat, add the connector. Chats that show MCP Apps open the canvas right there. {joinThisCanvas}</li>
266
+ </Steps>
267
+ ),
268
+ },
269
+ {
270
+ name: 'Cursor',
271
+ logo: <CursorLogo />,
272
+ body: (
273
+ <Steps>
274
+ <li>
275
+ Add this server to <code className="text-xs">.cursor/mcp.json</code> in your project:
276
+ <Snippet text={JSON.stringify({ mcpServers: { eventcatalog: { url: mcpUrl } } }, null, 2)} label="the settings" />
277
+ </li>
278
+ <li>{joinThisCanvas}</li>
279
+ </Steps>
280
+ ),
281
+ },
282
+ {
283
+ name: 'VS Code',
284
+ logo: <Code2 />,
285
+ body: (
286
+ <Steps>
287
+ <li>
288
+ Add this server to <code className="text-xs">.vscode/mcp.json</code> in your project:
289
+ <Snippet
290
+ text={JSON.stringify({ servers: { eventcatalog: { type: 'http', url: mcpUrl } } }, null, 2)}
291
+ label="the settings"
292
+ />
293
+ </li>
294
+ <li>In Copilot's agent mode: {joinThisCanvas}</li>
295
+ </Steps>
296
+ ),
297
+ },
298
+ {
299
+ name: 'This browser',
300
+ logo: <Globe />,
301
+ body: (
302
+ <div className="flex items-center justify-between gap-3">
303
+ <p className="text-sm leading-relaxed text-[rgb(var(--ec-page-text))]">
304
+ {webMcp.state === 'on'
305
+ ? `This tab offers ${webMcp.tools} canvas tools to agents in your browser (like the MCP-B extension) through WebMCP.`
306
+ : 'Let agents in your browser (like the MCP-B extension) use this canvas through WebMCP.'}
307
+ </p>
308
+ <TabSwitch on={webMcp.state === 'on'} onTurnOn={onEnableWebMcp} label="Turn on" />
309
+ </div>
310
+ ),
311
+ },
312
+ ];
313
+
172
314
  return (
173
- <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4" onClick={onClose}>
315
+ <div className="fixed inset-0 z-[80] flex items-center justify-center bg-black/40 p-4" onClick={onClose}>
174
316
  <div
175
317
  role="dialog"
176
- aria-label="Connect your agent"
318
+ aria-modal="true"
319
+ aria-labelledby="connect-agent-title"
177
320
  onClick={(event) => event.stopPropagation()}
178
- className="flex max-h-full w-full max-w-md flex-col rounded-xl border shadow-2xl bg-[rgb(var(--ec-card-bg))] border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))]"
321
+ className="flex max-h-full w-full max-w-2xl flex-col rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg))] text-[rgb(var(--ec-page-text))] shadow-2xl"
179
322
  >
180
- <header className="flex items-start justify-between gap-3 px-5 pb-3 pt-5">
181
- <div className="flex items-center gap-3">
182
- <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))]">
183
- <Bot size={18} />
184
- </span>
185
- <div>
186
- <h2 className="text-base font-semibold">Bring in an AI agent</h2>
187
- <p className="text-xs text-[rgb(var(--ec-page-text-muted))]">It joins this canvas and designs with you, live.</p>
188
- </div>
323
+ <div className="flex items-start gap-3 px-5 pt-5">
324
+ <div className="min-w-0 flex-1">
325
+ <h2 id="connect-agent-title" className="text-base font-semibold">
326
+ Connect your AI agent
327
+ </h2>
328
+ <p className="mt-1.5 text-sm font-light leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
329
+ Pair with your AI agent on this canvas: sketch ideas together, or have it bring in what your catalog has and walk
330
+ you through it. It joins with its own pointer, and you both change the canvas. Add this EventCatalog as an MCP
331
+ server.
332
+ </p>
189
333
  </div>
190
334
  <button
191
- onClick={onClose}
335
+ type="button"
192
336
  aria-label="Close"
193
- className="rounded-md p-1 text-[rgb(var(--ec-icon-color))] hover:bg-[rgb(var(--ec-page-border)/0.5)]"
337
+ onClick={onClose}
338
+ className="-mr-1 -mt-1 rounded-md p-1.5 text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-page-text))]"
194
339
  >
195
- <X size={16} />
340
+ <X aria-hidden className="h-4 w-4" />
196
341
  </button>
197
- </header>
342
+ </div>
198
343
 
199
- <div className="min-h-0 space-y-5 overflow-y-auto px-5 pb-5">
200
- {/* The one thing most people need: the prompt */}
201
- <section className="space-y-2">
202
- <CopyButton text={prompt} label="Copy prompt" large />
203
- <p className="text-center text-xs text-[rgb(var(--ec-page-text-muted))]">
204
- Paste it into your agent. It works out how to connect.{' '}
344
+ <div className="min-h-0 overflow-y-auto">
345
+ {/* The quickest way: one prompt, which the agent works out how to connect from (and which canvas to join) */}
346
+ <section className="mx-5 mt-4 overflow-hidden rounded-xl border border-[color-mix(in_srgb,rgb(var(--ec-accent))_35%,rgb(var(--ec-page-border)))] bg-[color-mix(in_srgb,rgb(var(--ec-accent))_6%,transparent)]">
347
+ <div className="flex items-center gap-3 p-4">
348
+ <span className="flex h-9 w-9 flex-none items-center justify-center rounded-lg bg-[color-mix(in_srgb,rgb(var(--ec-accent))_14%,transparent)] text-[rgb(var(--ec-accent))]">
349
+ <Sparkles aria-hidden className="h-[18px] w-[18px]" />
350
+ </span>
351
+ <div className="min-w-0 flex-1">
352
+ <h3 className="text-sm font-semibold">Quickest: paste one prompt</h3>
353
+ <p className="mt-0.5 text-xs leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
354
+ Give it to your agent: it connects to this EventCatalog and joins this canvas on its own.
355
+ </p>
356
+ </div>
357
+ <button type="button" onClick={async () => setPromptCopied(await copyText(prompt))} className={primary}>
358
+ {promptCopied ? <Check aria-hidden /> : <Copy aria-hidden />}
359
+ {promptCopied ? 'Copied' : 'Copy prompt'}
360
+ </button>
361
+ </div>
362
+ {/* What's in it, at a glance (the whole of it on a click) */}
363
+ <div className="relative border-t border-[color-mix(in_srgb,rgb(var(--ec-accent))_20%,rgb(var(--ec-page-border)))] bg-[rgb(var(--ec-card-bg)/0.6)]">
364
+ <pre
365
+ className={`whitespace-pre-wrap px-4 py-3 font-mono text-[11px] leading-relaxed text-[rgb(var(--ec-page-text-muted))] ${
366
+ showPrompt ? 'max-h-56 overflow-y-auto' : 'max-h-[112px] overflow-hidden'
367
+ }`}
368
+ >
369
+ {prompt}
370
+ </pre>
371
+ {!showPrompt && (
372
+ <div className="pointer-events-none absolute inset-x-0 bottom-0 h-20 bg-gradient-to-t from-[rgb(var(--ec-card-bg))] via-[rgb(var(--ec-card-bg)/0.85)] to-transparent" />
373
+ )}
205
374
  <button
375
+ type="button"
206
376
  onClick={() => setShowPrompt((shown) => !shown)}
207
377
  aria-expanded={showPrompt}
208
- className="inline-flex items-center gap-0.5 font-medium text-[rgb(var(--ec-accent))] hover:underline"
378
+ className={`${
379
+ showPrompt ? 'mx-4 mb-3' : 'absolute bottom-2 left-1/2 -translate-x-1/2'
380
+ } inline-flex items-center gap-1 rounded-full border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg))] px-2.5 py-1 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] shadow-sm hover:text-[rgb(var(--ec-page-text))]`}
209
381
  >
210
- {showPrompt ? 'Hide prompt' : 'Show prompt'}
211
- <ChevronDown size={12} className={`transition-transform ${showPrompt ? 'rotate-180' : ''}`} />
382
+ {showPrompt ? 'Show less' : 'Show the whole prompt'}
383
+ <ChevronDown aria-hidden size={12} className={`transition-transform ${showPrompt ? 'rotate-180' : ''}`} />
212
384
  </button>
213
- </p>
214
- {showPrompt && (
215
- <pre className="max-h-56 overflow-y-auto whitespace-pre-wrap rounded-lg border p-3 font-mono text-[11px] leading-relaxed bg-[rgb(var(--ec-page-bg))] border-[rgb(var(--ec-page-border))]">
216
- {prompt}
217
- </pre>
218
- )}
385
+ </div>
219
386
  </section>
220
387
 
221
- {/* Or set it up by hand, for the kind of agent you use */}
222
- <section className="space-y-3 border-t pt-4 border-[rgb(var(--ec-page-border))]">
223
- <h3 className="text-xs font-semibold">Or connect it yourself</h3>
224
- <div role="tablist" className="grid grid-cols-3 gap-1 rounded-lg p-1 bg-[rgb(var(--ec-page-border)/0.5)]">
225
- {WAYS.map(({ id, label, hint }) => (
388
+ <p className="mx-5 mt-5 text-[11px] font-semibold uppercase tracking-wide text-[rgb(var(--ec-page-text-muted))]">
389
+ Or set it up yourself
390
+ </p>
391
+ {/* Or add the server to the client they use, a step or two each */}
392
+ <div className="px-5 pb-5 pt-2">
393
+ <div role="tablist" className="flex gap-1 rounded-lg bg-[rgb(var(--ec-content-hover))] p-1">
394
+ {clients.map(({ name, logo }, index) => (
226
395
  <button
227
- key={id}
396
+ key={name}
397
+ type="button"
228
398
  role="tab"
229
- aria-selected={way === id}
230
- onClick={() => setWay(id)}
231
- className={`rounded-md px-2 py-1.5 text-center ${
232
- way === id ? 'bg-[rgb(var(--ec-card-bg))] shadow-sm' : 'text-[rgb(var(--ec-page-text-muted))]'
399
+ aria-selected={client === index}
400
+ onClick={() => setClient(index)}
401
+ className={`flex flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md px-2 py-1.5 text-xs font-medium outline-none [&_svg]:h-3.5 [&_svg]:w-3.5 [&_svg]:flex-none ${
402
+ client === index
403
+ ? 'bg-[rgb(var(--ec-card-bg))] text-[rgb(var(--ec-page-text))] shadow-sm'
404
+ : 'text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
233
405
  }`}
234
406
  >
235
- <span className="block text-xs font-medium">{label}</span>
236
- <span className="block truncate text-[10px] text-[rgb(var(--ec-page-text-muted))]">{hint}</span>
407
+ {logo}
408
+ {name}
237
409
  </button>
238
410
  ))}
239
411
  </div>
412
+ <div role="tabpanel" className="mt-4">
413
+ {clients[client].body}
414
+ </div>
415
+ </div>
240
416
 
241
- {way === 'chat' && (
242
- <div className="space-y-2">
243
- <p className="text-xs text-[rgb(var(--ec-page-text-muted))]">
244
- Add this MCP server to your chat app. Chats that show MCP Apps open the canvas right in the chat.
245
- </p>
246
- <CopyField value={link.mcpUrl} />
417
+ {/* What pairing looks like: the two ways people work with their agent on a canvas */}
418
+ <div className="grid gap-3 border-t border-[rgb(var(--ec-page-border))] px-5 py-4 sm:grid-cols-2">
419
+ {PAIRING.map(({ title, prompts }) => (
420
+ <div key={title}>
421
+ <h3 className="text-xs font-semibold text-[rgb(var(--ec-page-text))]">{title}</h3>
422
+ <ul className="mt-1.5 space-y-1 text-xs leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
423
+ {prompts.map((text) => (
424
+ <li key={text}>“{text}”</li>
425
+ ))}
426
+ </ul>
247
427
  </div>
248
- )}
249
- {way === 'code' && (
250
- <div className="space-y-2">
251
- <p className="text-xs text-[rgb(var(--ec-page-text-muted))]">
252
- Add EventCatalog's MCP server, e.g. in Claude Code:
253
- </p>
254
- <CopyField value={`claude mcp add --transport http eventcatalog ${link.mcpUrl}`} />
255
- {relayScriptPath && (
256
- <div className="flex items-center justify-between gap-3 pt-1">
257
- <p className="text-[11px] text-[rgb(var(--ec-page-text-muted))]">
258
- Can't reach this server? Use this tab through the local relay: add <code>{RELAY_COMMAND}</code> as an MCP
259
- server.
260
- </p>
261
- <TabSwitch on={relayOn} onTurnOn={turnOnRelay} label="Turn on relay" />
262
- </div>
263
- )}
264
- </div>
265
- )}
266
- {way === 'browser' && (
267
- <div className="flex items-center justify-between gap-3">
268
- <p className="text-xs text-[rgb(var(--ec-page-text-muted))]">
269
- {webMcp.state === 'on'
270
- ? `This tab offers ${webMcp.tools} canvas tools to agents in your browser (like the MCP-B extension).`
271
- : 'Let agents in your browser (like the MCP-B extension) use this canvas through WebMCP.'}
272
- </p>
273
- <TabSwitch on={webMcp.state === 'on'} onTurnOn={onEnableWebMcp} label="Turn on" />
274
- </div>
275
- )}
276
- </section>
428
+ ))}
429
+ </div>
277
430
  </div>
278
431
  </div>
279
432
  </div>
@@ -2,8 +2,7 @@ import { useEffect, useState, type ReactElement } from 'react';
2
2
  import { X } from 'lucide-react';
3
3
  import type { ConnectionGroup, ConnectionGroupId } from '../canvas-actions';
4
4
  import type { CatalogResource } from '../catalog-resources';
5
- import { getNodeLabel } from '../node-types';
6
- import { CardPreview } from './ContainerChooser';
5
+ import { getNodeLabel, CardPreview } from '@eventcatalog/visualiser/studio';
7
6
 
8
7
  /**
9
8
  * Asked when a catalog service or message is dropped on the canvas (and connects to things that aren't on it yet):
@@ -0,0 +1,65 @@
1
+ import { useState } from 'react';
2
+ import { usePeople, type PresenceStore } from '../hooks/presence-store';
3
+ import Dialog, { SECONDARY_BUTTON } from './Dialog';
4
+ import { STATUS } from '@eventcatalog/visualiser/studio';
5
+
6
+ /** Asks before deleting a canvas: it's deleted for everyone, for good */
7
+ export default function DeleteCanvasDialog({
8
+ title,
9
+ presence,
10
+ clientId,
11
+ onDelete,
12
+ onClose,
13
+ }: {
14
+ title?: string;
15
+ /** Who has it open (to say it closes for them) */
16
+ presence: PresenceStore | null;
17
+ clientId: number | null;
18
+ /** Deletes it (rejects with what went wrong) */
19
+ onDelete: () => Promise<void>;
20
+ onClose: () => void;
21
+ }) {
22
+ const othersHere = usePeople(presence).filter((peer) => peer.clientId !== clientId).length;
23
+ const [deleting, setDeleting] = useState(false);
24
+ const [error, setError] = useState<string>();
25
+
26
+ const confirm = async () => {
27
+ setDeleting(true);
28
+ setError(undefined);
29
+ try {
30
+ await onDelete();
31
+ } catch (failure) {
32
+ setError((failure as Error).message);
33
+ setDeleting(false);
34
+ }
35
+ };
36
+
37
+ return (
38
+ <Dialog role="alertdialog" labelledBy="delete-canvas-title" busy={deleting} onClose={onClose}>
39
+ <div className="space-y-2 px-5 py-4">
40
+ <h2 id="delete-canvas-title" className="text-base font-semibold">
41
+ Delete {title ? `"${title}"` : 'this canvas'}?
42
+ </h2>
43
+ <p className="text-sm text-[rgb(var(--ec-page-text-muted))]">
44
+ It's deleted for everyone, with its comments, and can't be brought back.
45
+ {othersHere > 0 &&
46
+ ` ${othersHere === 1 ? 'Someone else has' : `${othersHere} others have`} it open: it closes for them too.`}
47
+ </p>
48
+ {error && <p className={`text-sm ${STATUS.danger.text}`}>{error}</p>}
49
+ </div>
50
+ <div className="flex justify-end gap-2 border-t px-5 py-4 border-[rgb(var(--ec-page-border))]">
51
+ <button onClick={onClose} disabled={deleting} className={SECONDARY_BUTTON}>
52
+ Cancel
53
+ </button>
54
+ <button
55
+ autoFocus
56
+ onClick={confirm}
57
+ disabled={deleting}
58
+ className={`rounded-lg px-4 py-2 text-sm font-medium disabled:opacity-60 ${STATUS.danger.button}`}
59
+ >
60
+ {deleting ? 'Deleting…' : 'Delete canvas'}
61
+ </button>
62
+ </div>
63
+ </Dialog>
64
+ );
65
+ }
@@ -0,0 +1,60 @@
1
+ import { useEffect, useRef, type ReactNode } from 'react';
2
+
3
+ /**
4
+ * Studio's dialogs: a card over the page, closed by Escape or clicking outside it (not while it's busy). Focus stays
5
+ * in it: anything that moves focus outside (e.g. the menu it was opened from, closing) sends it back to its first
6
+ * field or button.
7
+ */
8
+
9
+ export const SECONDARY_BUTTON =
10
+ 'rounded-lg border px-4 py-2 text-sm font-medium border-[rgb(var(--ec-page-border))] hover:bg-[rgb(var(--ec-page-border)/0.4)] disabled:opacity-50';
11
+ export const PRIMARY_BUTTON =
12
+ 'rounded-lg px-4 py-2 text-sm font-medium bg-[rgb(var(--ec-button-bg))] text-[rgb(var(--ec-button-text))] hover:bg-[rgb(var(--ec-button-bg-hover))] disabled:opacity-60';
13
+
14
+ export default function Dialog({
15
+ labelledBy,
16
+ role = 'dialog',
17
+ busy = false,
18
+ onClose,
19
+ children,
20
+ }: {
21
+ /** The id of its heading */
22
+ labelledBy: string;
23
+ /** `alertdialog` when it asks to confirm something that can't be undone */
24
+ role?: 'dialog' | 'alertdialog';
25
+ /** Doing what was asked: it can't be closed until it's done */
26
+ busy?: boolean;
27
+ onClose: () => void;
28
+ children: ReactNode;
29
+ }) {
30
+ useEffect(() => {
31
+ const onKeyDown = (event: KeyboardEvent) => event.key === 'Escape' && !busy && onClose();
32
+ window.addEventListener('keydown', onKeyDown);
33
+ return () => window.removeEventListener('keydown', onKeyDown);
34
+ }, [onClose, busy]);
35
+
36
+ const card = useRef<HTMLDivElement>(null);
37
+ useEffect(() => {
38
+ const keepFocus = (event: FocusEvent) => {
39
+ if (!card.current || card.current.contains(event.target as globalThis.Node)) return;
40
+ card.current.querySelector<HTMLElement>('input, button')?.focus();
41
+ };
42
+ document.addEventListener('focusin', keepFocus);
43
+ return () => document.removeEventListener('focusin', keepFocus);
44
+ }, []);
45
+
46
+ return (
47
+ <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4" onClick={() => !busy && onClose()}>
48
+ <div
49
+ ref={card}
50
+ role={role}
51
+ aria-modal="true"
52
+ aria-labelledby={labelledBy}
53
+ onClick={(event) => event.stopPropagation()}
54
+ className="w-full max-w-md rounded-xl border shadow-2xl bg-[rgb(var(--ec-card-bg))] border-[rgb(var(--ec-page-border))] text-[rgb(var(--ec-page-text))]"
55
+ >
56
+ {children}
57
+ </div>
58
+ </div>
59
+ );
60
+ }