@eventcatalog/core 5.9.0 → 5.10.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 (51) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-WN6ZFSXF.js → chunk-5QOG7UYZ.js} +1 -1
  6. package/dist/{chunk-C4L6B5KR.js → chunk-EETSYUKN.js} +1 -1
  7. package/dist/{chunk-UIJUSHOT.js → chunk-EGOTM5ZG.js} +3 -2
  8. package/dist/{chunk-26C26LFE.js → chunk-EXBUNFIM.js} +1 -1
  9. package/dist/{chunk-SZU7I2PD.js → chunk-ZE2RPUNY.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/docs/development/00-why-eventcatalog.md +3 -0
  13. package/dist/docs/development/ask-your-architecture/01-intro.md +17 -4
  14. package/dist/docs/development/ask-your-architecture/06-sync-docs-with-your-code.md +8 -1
  15. package/dist/docs/development/ask-your-architecture/07-catch-breaking-changes.md +8 -1
  16. package/dist/docs/development/ask-your-architecture/08-check-code-against-adrs.md +169 -0
  17. package/dist/docs/development/guides/resources/adrs/01-introduction.md +1 -0
  18. package/dist/docs/development/guides/resources/entities/05-entity-maps.md +5 -0
  19. package/dist/docs/development/guides/resources/entities/06-global-entity-map.md +101 -0
  20. package/dist/docs/development/guides/resources/entities/{06-reference.md → 07-reference.md} +2 -1
  21. package/dist/eventcatalog.cjs +6 -5
  22. package/dist/eventcatalog.js +5 -5
  23. package/dist/generate.cjs +3 -2
  24. package/dist/generate.js +3 -3
  25. package/dist/utils/cli-logger.cjs +1 -1
  26. package/dist/utils/cli-logger.js +2 -2
  27. package/eventcatalog/auth.config.ts +7 -9
  28. package/eventcatalog/src/components/MDX/EntityMap/CatalogEntityMap.tsx +301 -0
  29. package/eventcatalog/src/features/ai/chat-api.ts +2 -4
  30. package/eventcatalog/src/features/auth/login.astro +2 -4
  31. package/eventcatalog/src/features/auth/middleware/middleware.ts +2 -3
  32. package/eventcatalog/src/features/mcp/apps/generated/canvas.html +61 -61
  33. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +72 -72
  34. package/eventcatalog/src/features/mcp/mcp-server.ts +2 -1
  35. package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +1 -1
  36. package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +2 -2
  37. package/eventcatalog/src/features/studio/pages/webmcp-relay.ts +1 -1
  38. package/eventcatalog/src/features/studio/webmcp-relay/README.md +1 -1
  39. package/eventcatalog/src/features/studio/webmcp-relay/embed.js +1 -2
  40. package/eventcatalog/src/features/studio/webmcp-relay/widget.html +2 -1
  41. package/eventcatalog/src/features/studio/webmcp-relay/widget.js +2 -1
  42. package/eventcatalog/src/pages/visualiser/entity-map/index.astro +47 -0
  43. package/eventcatalog/src/pages/visualiser/graph/index.astro +2 -2
  44. package/eventcatalog/src/stores/sidebar-store/state.ts +10 -1
  45. package/eventcatalog/src/utils/catalog-modules.ts +16 -0
  46. package/eventcatalog/src/utils/node-graphs/catalog-entity-map-view.ts +82 -0
  47. package/eventcatalog/src/utils/node-graphs/catalog-entity-map.ts +113 -0
  48. package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +17 -61
  49. package/eventcatalog/src/utils/node-graphs/entity-layout.ts +53 -0
  50. package/eventcatalog/src/utils/node-graphs/flow-lanes.ts +2 -2
  51. package/package.json +6 -6
@@ -1,24 +1,22 @@
1
1
  import { getCollection, getEntry } from 'astro:content';
2
2
  import { generateIdForNode } from './utils/utils';
3
- import ELK from 'elkjs/lib/elk.bundled.js';
4
3
  import { MarkerType } from '@xyflow/react';
5
4
  import { createVersionedMap, findInMap } from '@utils/collections/util';
6
5
  import { getVersionFromCollection } from '@utils/collections/versions';
7
6
  import { getEntities, type Entity } from '@utils/collections/entities';
8
7
  import { getDomains, type Domain } from '@utils/collections/domains';
9
8
  import { getServices, type Service } from '@utils/collections/services';
10
-
11
- const elk = new ELK();
9
+ import { layoutEntityNodes } from './entity-layout';
12
10
 
13
11
  export const ENTITY_TARGET_HANDLE_ID = '__eventcatalog-entity-target';
14
12
 
15
- const getReferencedEntityId = (property: any, entityMap: Map<string, Entity[]>) => {
13
+ export const getReferencedEntityId = (property: any, entityMap: Map<string, Entity[]>) => {
16
14
  if (property.references) return property.references;
17
15
  if (property.type === 'array' && property.items?.type && entityMap.has(property.items.type)) return property.items.type;
18
16
  return undefined;
19
17
  };
20
18
 
21
- const getReferencePropertyNames = (entity: Entity, entityMap: Map<string, Entity[]>) =>
19
+ export const getReferencePropertyNames = (entity: Entity, entityMap: Map<string, Entity[]>) =>
22
20
  entity.data.properties
23
21
  ?.filter((property: any) => getReferencedEntityId(property, entityMap))
24
22
  .map((property: any) => property.name) ?? [];
@@ -151,6 +149,19 @@ export const getNodesAndEdges = async ({ id, version, entities, type = 'domains'
151
149
  // Create complete list of entities for edge creation and layout
152
150
  const allEntitiesInGraph = [...resourceEntities, ...addedExternalEntities];
153
151
 
152
+ edges = createEntityReferenceEdges(entitiesWithReferences, allEntitiesInGraph, entityMap);
153
+
154
+ return { nodes: await layoutEntityNodes(nodes, edges), edges };
155
+ };
156
+
157
+ /** The edges between entities: one for each property referencing another entity in the graph */
158
+ export const createEntityReferenceEdges = (
159
+ entitiesWithReferences: Entity[],
160
+ allEntitiesInGraph: Entity[],
161
+ entityMap: Map<string, Entity[]>
162
+ ) => {
163
+ const edges: any[] = [];
164
+
154
165
  // Go through any entities that are related to other entities
155
166
  for (const entity of entitiesWithReferences) {
156
167
  // Get a list of properties that reference other entities
@@ -220,60 +231,5 @@ export const getNodesAndEdges = async ({ id, version, entities, type = 'domains'
220
231
  }
221
232
  }
222
233
 
223
- // No virtual edges - only show actual relationships between entities
224
-
225
- // Separate entities with and without relationships (including external entities)
226
- const entitiesWithRelationships = allEntitiesInGraph.filter((entity) => {
227
- // Has outgoing references
228
- const hasOutgoingRefs = entity.data.properties?.some((property: any) => getReferencedEntityId(property, entityMap));
229
- // Has incoming references (is referenced by others)
230
- const hasIncomingRefs = entitiesWithReferences.some((e: any) =>
231
- e.data.properties?.some((prop: any) => getReferencedEntityId(prop, entityMap) === entity.data.id)
232
- );
233
- return hasOutgoingRefs || hasIncomingRefs;
234
- });
235
-
236
- // Prepare ELK graph structure
237
- const elkNodes = nodes.map((node: any) => ({
238
- id: node.id,
239
- width: 220,
240
- height: Math.max(120, 72 + (node.data.entity.data.properties?.length ?? 0) * 40),
241
- }));
242
-
243
- const elkEdges = edges.map((edge: any) => ({
244
- id: edge.id,
245
- sources: [edge.source],
246
- targets: [edge.target],
247
- }));
248
-
249
- const elkGraph = {
250
- id: 'root',
251
- layoutOptions: {
252
- 'elk.algorithm': 'force',
253
- 'elk.force.iterations': '300',
254
- 'elk.spacing.nodeNode': '45',
255
- 'elk.spacing.componentComponent': '50',
256
- 'elk.padding': '[top=30,left=30,bottom=30,right=30]',
257
- 'elk.separateConnectedComponents': 'true',
258
- },
259
- children: elkNodes,
260
- edges: elkEdges,
261
- };
262
-
263
- // Run ELK layout
264
- const layoutedGraph = await elk.layout(elkGraph);
265
-
266
- // Apply positions to nodes
267
- const positionedNodes = nodes.map((node: any) => {
268
- const elkNode = layoutedGraph.children?.find((n: any) => n.id === node.id);
269
- return {
270
- ...node,
271
- position: {
272
- x: elkNode?.x || 0,
273
- y: elkNode?.y || 0,
274
- },
275
- };
276
- });
277
-
278
- return { nodes: positionedNodes, edges };
234
+ return edges;
279
235
  };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * How entity maps are laid out: ELK's force layout, each entity sized by how many properties it has.
3
+ * Kept apart from the graph builders (which read the catalog's collections), so the catalog's entity
4
+ * map can lay out what it shows in the browser the same way.
5
+ */
6
+ import ELK from 'elkjs/lib/elk.bundled.js';
7
+ import { getNodeSize } from '@eventcatalog/visualiser/layout';
8
+
9
+ const elk = new ELK();
10
+
11
+ /** Places entities with ELK's force layout, sized by how many properties they have */
12
+ export const layoutEntityNodes = async (nodes: any[], edges: any[]) => {
13
+ // Prepare ELK graph structure
14
+ // Sized as the visualiser estimates them (a row for each property), so the catalog and the browser agree
15
+ const elkNodes = nodes.map((node: any) => ({ id: node.id, ...getNodeSize(node) }));
16
+
17
+ const elkEdges = edges.map((edge: any) => ({
18
+ id: edge.id,
19
+ sources: [edge.source],
20
+ targets: [edge.target],
21
+ }));
22
+
23
+ const elkGraph = {
24
+ id: 'root',
25
+ layoutOptions: {
26
+ 'elk.algorithm': 'force',
27
+ 'elk.force.iterations': '300',
28
+ 'elk.spacing.nodeNode': '45',
29
+ 'elk.spacing.componentComponent': '50',
30
+ 'elk.padding': '[top=30,left=30,bottom=30,right=30]',
31
+ 'elk.separateConnectedComponents': 'true',
32
+ },
33
+ children: elkNodes,
34
+ edges: elkEdges,
35
+ };
36
+
37
+ // Run ELK layout
38
+ const layoutedGraph = await elk.layout(elkGraph);
39
+
40
+ // Apply positions to nodes
41
+ const positionedNodes = nodes.map((node: any) => {
42
+ const elkNode = layoutedGraph.children?.find((n: any) => n.id === node.id);
43
+ return {
44
+ ...node,
45
+ position: {
46
+ x: elkNode?.x || 0,
47
+ y: elkNode?.y || 0,
48
+ },
49
+ };
50
+ });
51
+
52
+ return positionedNodes;
53
+ };
@@ -30,8 +30,8 @@ type Resource = { data: { id: string; name?: string; owners?: (string | { id: st
30
30
 
31
31
  // Lanes use the latest version of each domain and system (as the collection
32
32
  // utils do when they don't ask for every version)
33
- const isLatest = (entry: { filePath?: string }) => !entry.filePath?.includes('versioned');
34
- const toLane = (entry: Resource): Lane => ({ id: entry.data.id, name: entry.data.name || entry.data.id });
33
+ export const isLatest = (entry: { filePath?: string }) => !entry.filePath?.includes('versioned');
34
+ export const toLane = (entry: Resource): Lane => ({ id: entry.data.id, name: entry.data.name || entry.data.id });
35
35
  const pointerIds = (pointers?: { id: string }[]) => (pointers || []).map((pointer) => pointer.id);
36
36
 
37
37
  /**
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "BUSL-1.1",
9
9
  "type": "module",
10
- "version": "5.9.0",
10
+ "version": "5.10.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -63,7 +63,7 @@
63
63
  "@hocuspocus/provider": "^4.7.0",
64
64
  "@hocuspocus/server": "^4.7.0",
65
65
  "@iconify-json/logos": "^1.2.4",
66
- "@mcp-b/webmcp-polyfill": "5.1.0",
66
+ "@mcp-b/webmcp-polyfill": "6.0.3",
67
67
  "@mermaid-js/layout-elk": "^0.2.0",
68
68
  "@modelcontextprotocol/client": "2.3.1",
69
69
  "@modelcontextprotocol/ext-apps": "2.0.3",
@@ -95,7 +95,7 @@
95
95
  "diff2html": "^3.4.56",
96
96
  "dotenv": "^16.5.0",
97
97
  "elkjs": "^0.10.0",
98
- "glob": "^13.0.6",
98
+ "glob": "^13.0.7",
99
99
  "gray-matter": "^4.0.3",
100
100
  "hono": "^4.13.7",
101
101
  "html-to-image": "^1.11.11",
@@ -142,10 +142,10 @@
142
142
  "yjs": "^13.6.33",
143
143
  "zod": "^4.6.6",
144
144
  "@eventcatalog/exporters": "0.1.4",
145
- "@eventcatalog/sdk": "2.32.0",
146
- "@eventcatalog/visualiser": "^5.2.5",
147
145
  "@eventcatalog/fitness": "0.1.1",
148
- "@eventcatalog/linter": "1.3.1"
146
+ "@eventcatalog/linter": "1.3.1",
147
+ "@eventcatalog/sdk": "2.32.0",
148
+ "@eventcatalog/visualiser": "^5.3.0"
149
149
  },
150
150
  "devDependencies": {
151
151
  "@astrojs/check": "^0.9.10",