@eventcatalog/core 5.4.2 → 5.5.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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-VSBMYXLL.js → chunk-3TREOJOK.js} +1 -1
- package/dist/{chunk-CQ4L4SMB.js → chunk-754U4T7K.js} +1 -1
- package/dist/{chunk-EXRIIYEP.js → chunk-RDF2OMEF.js} +1 -1
- package/dist/{chunk-XB6FJMI3.js → chunk-UBDTKNFS.js} +1 -1
- package/dist/{chunk-HV4ONKTM.js → chunk-WPFA7AGD.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +8 -8
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +2 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -0
- package/eventcatalog/src/features/ai/chat-api.ts +6 -3
- package/eventcatalog/src/features/mcp/apps/architecture-diagram/shared.ts +3 -1
- package/eventcatalog/src/features/mcp/apps/architecture-diagram/view.tsx +6 -1
- package/eventcatalog/src/features/mcp/apps/generated/canvas.html +82 -70
- package/eventcatalog/src/features/mcp/apps/generated/viewer.html +85 -71
- package/eventcatalog/src/features/mcp/mcp-scoped-tools.ts +2 -1
- package/eventcatalog/src/features/mcp/mcp-server.ts +9 -8
- package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +2 -0
- package/eventcatalog/src/features/tools/catalog-tools.ts +8 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/_mermaid-route.ts +48 -5
- package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/[level].mermaid.ts +18 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/system-context-map/index.astro +1 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/[level].mermaid.ts +18 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +1 -0
- package/eventcatalog/src/utils/node-graphs/architecture-diagram-types.ts +7 -1
- package/eventcatalog/src/utils/node-graphs/architecture-diagram.ts +5 -2
- package/eventcatalog/src/utils/node-graphs/compact-visualiser-graph.ts +2 -0
- package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +246 -29
- package/package.json +3 -3
- package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +0 -375
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
paginate,
|
|
13
13
|
} from '@features/tools/catalog-tools';
|
|
14
14
|
import type { McpScope } from './mcp-scope';
|
|
15
|
+
import type { ArchitectureDiagramDetail } from '@utils/node-graphs/architecture-diagram-types';
|
|
15
16
|
|
|
16
17
|
const notFound = (collection: string, id: string, version?: string) => ({
|
|
17
18
|
error: `Resource not found: ${collection}/${id}${version ? ` (${version})` : ''}`,
|
|
@@ -186,7 +187,7 @@ export function createScopedCatalogTools(scope: McpScope) {
|
|
|
186
187
|
resourceId: string;
|
|
187
188
|
resourceVersion?: string;
|
|
188
189
|
resourceCollection: string;
|
|
189
|
-
detail?:
|
|
190
|
+
detail?: ArchitectureDiagramDetail;
|
|
190
191
|
}) {
|
|
191
192
|
const entry = scope.find(params.resourceCollection, params.resourceId, params.resourceVersion);
|
|
192
193
|
if (!entry) return notFound(params.resourceCollection, params.resourceId, params.resourceVersion);
|
|
@@ -11,6 +11,7 @@ import { McpScopeNotFoundError, resolveMcpScope, type McpScope, type McpScopeKin
|
|
|
11
11
|
import { getArchitectureDiagramView } from '@utils/node-graphs/architecture-diagram';
|
|
12
12
|
import type {
|
|
13
13
|
ArchitectureDiagramCollection,
|
|
14
|
+
ArchitectureDiagramDetail,
|
|
14
15
|
ArchitectureDiagramView,
|
|
15
16
|
Graph,
|
|
16
17
|
} from '@utils/node-graphs/architecture-diagram-types';
|
|
@@ -30,7 +31,7 @@ const loadViewerView = getMcpAppViewLoader('viewer');
|
|
|
30
31
|
|
|
31
32
|
const SHOW_RESOURCE_DESCRIPTION = [
|
|
32
33
|
"Show the user a resource in EventCatalog's interactive viewer. Pick what to show with view:",
|
|
33
|
-
'"architecture" shows an architecture diagram of a domain, system, service, agent, event, command, query, flow, data store or data product: what it connects to, what it publishes and consumes, and the systems and domains around it. Use it whenever the user wants to see or understand how something works or fits together, e.g. "show me how the Order Service works", "how does the Ordering domain fit together", "what does Payments talk to", or asks for a diagram, map or visual of something. Prefer it over drawing your own diagram.
|
|
34
|
+
'"architecture" shows an architecture diagram of a domain, system, service, agent, event, command, query, flow, data store or data product: what it connects to, what it publishes and consumes, and the systems and domains around it. Use it whenever the user wants to see or understand how something works or fits together, e.g. "show me how the Order Service works", "how does the Ordering domain fit together", "what does Payments talk to", or asks for a diagram, map or visual of something. Prefer it over drawing your own diagram. Pick the level with detail: "overview" for just the domains, systems and their relationships (domains and systems), "services" for services and data stores without messages and channels, or "full" (default) to include messages and channels.',
|
|
34
35
|
'"schema" shows the schema of a message (event, command or query) or other resource: its properties, types, descriptions and which ones are required. Use it whenever the user wants to see or understand a schema or payload, e.g. "show me the schema for OrderCreated", "what fields does PlaceOrder have", "what does the OrderShipped payload look like".',
|
|
35
36
|
'Clients that support MCP Apps show one viewer and switch it to each thing you show, so call this again to show the user something else. The result also contains what is shown (the diagram as Mermaid in mermaidCode, or the schema code) so you can understand it.',
|
|
36
37
|
'When the client shows the viewer, do not redraw the diagram or print the whole schema again in your reply: explain it and point out what matters. Otherwise, show the user the mermaidCode or the relevant parts of the schema code.',
|
|
@@ -389,6 +390,7 @@ function createMcpServer(
|
|
|
389
390
|
resourceId: string;
|
|
390
391
|
resourceVersion: string;
|
|
391
392
|
visualiserUrl: string;
|
|
393
|
+
detail?: ArchitectureDiagramDetail;
|
|
392
394
|
}): Promise<ArchitectureDiagramPayload> => ({
|
|
393
395
|
resource: {
|
|
394
396
|
collection: diagram.resourceCollection,
|
|
@@ -405,6 +407,7 @@ function createMcpServer(
|
|
|
405
407
|
version: diagram.resourceVersion,
|
|
406
408
|
})
|
|
407
409
|
),
|
|
410
|
+
...(diagram.detail ? { detail: diagram.detail } : {}),
|
|
408
411
|
});
|
|
409
412
|
|
|
410
413
|
// The resource's schemas, parsed for the view's JSON Schema, Avro and Protobuf viewers
|
|
@@ -455,7 +458,7 @@ function createMcpServer(
|
|
|
455
458
|
resourceId: string;
|
|
456
459
|
resourceVersion?: string;
|
|
457
460
|
resourceCollection: string;
|
|
458
|
-
detail?:
|
|
461
|
+
detail?: ArchitectureDiagramDetail;
|
|
459
462
|
};
|
|
460
463
|
|
|
461
464
|
const loadArchitectureView = async ({ view, ...params }: ResourceViewParams) => {
|
|
@@ -470,7 +473,8 @@ function createMcpServer(
|
|
|
470
473
|
label: `the architecture diagram for ${result.resourceCollection}/${result.resourceId}`,
|
|
471
474
|
getPayload: async (): Promise<ViewerPayload> => ({
|
|
472
475
|
view: 'architecture',
|
|
473
|
-
|
|
476
|
+
// Opens at the level asked for, as the Mermaid the model gets is; without one, at the diagram's default
|
|
477
|
+
diagram: await getArchitectureDiagramPayload({ ...result, detail: params.detail }),
|
|
474
478
|
}),
|
|
475
479
|
};
|
|
476
480
|
};
|
|
@@ -517,12 +521,9 @@ function createMcpServer(
|
|
|
517
521
|
description: SHOW_RESOURCE_DESCRIPTION,
|
|
518
522
|
input: {
|
|
519
523
|
...resourceViewInput,
|
|
520
|
-
detail:
|
|
521
|
-
.enum(['overview', 'full'])
|
|
524
|
+
detail: catalogTools.architectureDiagramDetailSchema
|
|
522
525
|
.optional()
|
|
523
|
-
.describe(
|
|
524
|
-
'For view "architecture" of domains and systems: "overview" shows only domains, systems and their relationships; "full" (default) also shows services, messages and channels'
|
|
525
|
-
),
|
|
526
|
+
.describe(`For view "architecture": ${catalogTools.architectureDiagramDetailSchema.description}`),
|
|
526
527
|
},
|
|
527
528
|
},
|
|
528
529
|
viewTool: {
|
|
@@ -97,6 +97,7 @@ import {
|
|
|
97
97
|
type HotspotFields,
|
|
98
98
|
type HotspotSeverity,
|
|
99
99
|
type HotspotSpot,
|
|
100
|
+
RemeasureHandles,
|
|
100
101
|
} from '@eventcatalog/visualiser/studio';
|
|
101
102
|
import { X } from 'lucide-react';
|
|
102
103
|
import type { CatalogRelation, CatalogResource } from '../catalog-resources';
|
|
@@ -1751,6 +1752,7 @@ function Canvas({
|
|
|
1751
1752
|
maxZoom={2}
|
|
1752
1753
|
>
|
|
1753
1754
|
<DiagramBackground />
|
|
1755
|
+
<RemeasureHandles />
|
|
1754
1756
|
{/* Above the selected node's top right corner: its details, to edit them */}
|
|
1755
1757
|
{toEdit && <EditButton nodeId={toEdit.id} locked={locked} onClick={editSelected} />}
|
|
1756
1758
|
<LegendPanel legend={legend} hiddenKeys={hiddenLegendKeys} onLegendClick={toggleLegendKey} />
|
|
@@ -12,10 +12,11 @@ import fs from 'node:fs';
|
|
|
12
12
|
import { getArchitectureDiagramGraph } from '@utils/node-graphs/architecture-diagram';
|
|
13
13
|
import {
|
|
14
14
|
ARCHITECTURE_DIAGRAM_COLLECTIONS,
|
|
15
|
+
ARCHITECTURE_DIAGRAM_DETAILS,
|
|
15
16
|
isArchitectureDiagramCollection,
|
|
16
17
|
type ArchitectureDiagramDetail,
|
|
17
18
|
} from '@utils/node-graphs/architecture-diagram-types';
|
|
18
|
-
import { convertToMermaid } from '@
|
|
19
|
+
import { convertToMermaid } from '@eventcatalog/visualiser/layout';
|
|
19
20
|
import { glob } from 'glob';
|
|
20
21
|
import path from 'node:path';
|
|
21
22
|
import {
|
|
@@ -201,6 +202,12 @@ export const resourceCollectionSchema = z.enum([
|
|
|
201
202
|
|
|
202
203
|
export const visualiserCollectionSchema = z.enum(ARCHITECTURE_DIAGRAM_COLLECTIONS);
|
|
203
204
|
|
|
205
|
+
export const architectureDiagramDetailSchema = z
|
|
206
|
+
.enum(ARCHITECTURE_DIAGRAM_DETAILS)
|
|
207
|
+
.describe(
|
|
208
|
+
'The level of the diagram, as on its Diagram page: "overview" (L1) shows only domains, systems and their relationships (domains and systems only); "services" (L2) shows services and data stores without messages and channels; "full" (L3, default) also shows messages and channels'
|
|
209
|
+
);
|
|
210
|
+
|
|
204
211
|
// ============================================
|
|
205
212
|
// Tool implementations (core logic)
|
|
206
213
|
// ============================================
|
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Domains and systems have their own routes next to their Diagram pages
|
|
6
6
|
* (visualiser/domains/[id]/[version]), which would otherwise handle these requests first.
|
|
7
|
+
* Their levels are served at /visualiser/{domains|systems}/{id}/{version}/{overview|services}.mermaid.
|
|
7
8
|
*/
|
|
8
9
|
import { isAuthEnabled, isVisualiserEnabled } from '@utils/feature';
|
|
9
10
|
import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
|
|
10
11
|
import { getArchitectureDiagramGraph } from '@utils/node-graphs/architecture-diagram';
|
|
11
|
-
import {
|
|
12
|
-
|
|
12
|
+
import {
|
|
13
|
+
ARCHITECTURE_DIAGRAM_DETAILS,
|
|
14
|
+
isArchitectureDiagramCollection,
|
|
15
|
+
type ArchitectureDiagramDetail,
|
|
16
|
+
} from '@utils/node-graphs/architecture-diagram-types';
|
|
17
|
+
import { convertToMermaid } from '@eventcatalog/visualiser/layout';
|
|
13
18
|
import type { PageTypes } from '@types';
|
|
14
19
|
|
|
15
20
|
export type MermaidDiagramType =
|
|
@@ -34,7 +39,35 @@ export async function getMermaidDiagramPaths(types: MermaidDiagramType[]) {
|
|
|
34
39
|
);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
/** Levels served at /visualiser/{domains|systems}/{id}/{version}/{level}.mermaid ({version}.mermaid is the full diagram) */
|
|
43
|
+
export const MERMAID_LEVELS = ['overview', 'services'] as const satisfies ArchitectureDiagramDetail[];
|
|
44
|
+
|
|
45
|
+
const LEVEL_DESCRIPTIONS: Record<ArchitectureDiagramDetail, string> = {
|
|
46
|
+
overview: 'L1 overview (domains, systems and their relationships)',
|
|
47
|
+
services: 'L2 services and data stores',
|
|
48
|
+
full: 'L3 full (services, messages and channels)',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Every version of each domain or system with each level, for building their Mermaid files in static builds */
|
|
52
|
+
export async function getMermaidLevelPaths(type: 'domains' | 'systems') {
|
|
53
|
+
const paths = await getMermaidDiagramPaths([type]);
|
|
54
|
+
return paths.flatMap(({ id, version }) => MERMAID_LEVELS.map((level) => ({ params: { id, version, level } })));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const isMermaidDetail = (detail: string): detail is ArchitectureDiagramDetail =>
|
|
58
|
+
(ARCHITECTURE_DIAGRAM_DETAILS as readonly string[]).includes(detail);
|
|
59
|
+
|
|
60
|
+
export async function createMermaidDiagramResponse({
|
|
61
|
+
type,
|
|
62
|
+
id,
|
|
63
|
+
version,
|
|
64
|
+
detail = 'full',
|
|
65
|
+
}: {
|
|
66
|
+
type?: string;
|
|
67
|
+
id?: string;
|
|
68
|
+
version?: string;
|
|
69
|
+
detail?: string;
|
|
70
|
+
}) {
|
|
38
71
|
if (!type || !id || !version || !isVisualiserEnabled()) {
|
|
39
72
|
return new Response('Not found', { status: 404 });
|
|
40
73
|
}
|
|
@@ -44,9 +77,18 @@ export async function createMermaidDiagramResponse({ type, id, version }: { type
|
|
|
44
77
|
return new Response(`Unsupported type: ${type}`, { status: 400 });
|
|
45
78
|
}
|
|
46
79
|
|
|
80
|
+
if (!isMermaidDetail(detail)) {
|
|
81
|
+
return new Response('Not found', { status: 404 });
|
|
82
|
+
}
|
|
83
|
+
|
|
47
84
|
try {
|
|
48
|
-
// Built the same way as the resource's Diagram page
|
|
49
|
-
const { nodes, edges } = await getArchitectureDiagramGraph({
|
|
85
|
+
// Built the same way as the resource's Diagram page, at the level asked for
|
|
86
|
+
const { nodes, edges } = await getArchitectureDiagramGraph({
|
|
87
|
+
collection: type,
|
|
88
|
+
id,
|
|
89
|
+
version,
|
|
90
|
+
...(detail !== 'full' && { detail }),
|
|
91
|
+
});
|
|
50
92
|
|
|
51
93
|
if (!nodes || nodes.length === 0) {
|
|
52
94
|
return new Response('No diagram data available', { status: 404 });
|
|
@@ -60,6 +102,7 @@ export async function createMermaidDiagramResponse({ type, id, version }: { type
|
|
|
60
102
|
// Add header comment with metadata
|
|
61
103
|
const header = `%% EventCatalog Mermaid Diagram
|
|
62
104
|
%% Resource: ${type}/${id} (v${version})
|
|
105
|
+
%% Level: ${LEVEL_DESCRIPTIONS[detail]}
|
|
63
106
|
%% Generated: ${new Date().toISOString()}
|
|
64
107
|
|
|
65
108
|
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API endpoint to return mermaid diagram code for a level of a domain diagram
|
|
3
|
+
* URL: /visualiser/domains/{id}/{version}/{overview|services}.mermaid
|
|
4
|
+
*
|
|
5
|
+
* `overview` is level 1 (domains, systems and their relationships) and `services` level 2
|
|
6
|
+
* (services and data stores), as on the Diagram page. {version}.mermaid is the full diagram (level 3).
|
|
7
|
+
*/
|
|
8
|
+
import type { APIRoute, GetStaticPaths } from 'astro';
|
|
9
|
+
import { isAuthEnabled } from '@utils/feature';
|
|
10
|
+
import { createMermaidDiagramResponse, getMermaidLevelPaths } from '../../../_mermaid-route';
|
|
11
|
+
|
|
12
|
+
// Prerender static pages when auth is disabled, use SSR when auth is enabled
|
|
13
|
+
export const prerender = !isAuthEnabled();
|
|
14
|
+
|
|
15
|
+
export const getStaticPaths: GetStaticPaths = () => getMermaidLevelPaths('domains');
|
|
16
|
+
|
|
17
|
+
export const GET: APIRoute = async ({ params }) =>
|
|
18
|
+
createMermaidDiagramResponse({ type: 'domains', id: params.id, version: params.version, detail: params.level });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API endpoint to return mermaid diagram code for a level of a system diagram
|
|
3
|
+
* URL: /visualiser/systems/{id}/{version}/{overview|services}.mermaid
|
|
4
|
+
*
|
|
5
|
+
* `overview` is level 1 (domains, systems and their relationships) and `services` level 2
|
|
6
|
+
* (services and data stores), as on the Diagram page. {version}.mermaid is the full diagram (level 3).
|
|
7
|
+
*/
|
|
8
|
+
import type { APIRoute, GetStaticPaths } from 'astro';
|
|
9
|
+
import { isAuthEnabled } from '@utils/feature';
|
|
10
|
+
import { createMermaidDiagramResponse, getMermaidLevelPaths } from '../../../_mermaid-route';
|
|
11
|
+
|
|
12
|
+
// Prerender static pages when auth is disabled, use SSR when auth is enabled
|
|
13
|
+
export const prerender = !isAuthEnabled();
|
|
14
|
+
|
|
15
|
+
export const getStaticPaths: GetStaticPaths = () => getMermaidLevelPaths('systems');
|
|
16
|
+
|
|
17
|
+
export const GET: APIRoute = async ({ params }) =>
|
|
18
|
+
createMermaidDiagramResponse({ type: 'systems', id: params.id, version: params.version, detail: params.level });
|
|
@@ -21,7 +21,13 @@ export type ArchitectureDiagramCollection = (typeof ARCHITECTURE_DIAGRAM_COLLECT
|
|
|
21
21
|
export const isArchitectureDiagramCollection = (collection: string): collection is ArchitectureDiagramCollection =>
|
|
22
22
|
(ARCHITECTURE_DIAGRAM_COLLECTIONS as readonly string[]).includes(collection);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The levels of a diagram, as on the Diagram page's toolbar: L1 `overview` (domains, systems and their
|
|
26
|
+
* relationships), L2 `services` (services and data stores, without messages and channels) and L3 `full`.
|
|
27
|
+
*/
|
|
28
|
+
export const ARCHITECTURE_DIAGRAM_DETAILS = ['overview', 'services', 'full'] as const;
|
|
29
|
+
|
|
30
|
+
export type ArchitectureDiagramDetail = (typeof ARCHITECTURE_DIAGRAM_DETAILS)[number];
|
|
25
31
|
|
|
26
32
|
export type Graph = { nodes: any[]; edges: any[] };
|
|
27
33
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* diagram tool used by AI Chat and the MCP server, so they show the same thing.
|
|
5
5
|
*/
|
|
6
6
|
import config from '@config';
|
|
7
|
+
import { hideMessageNodes } from '@eventcatalog/visualiser/layout';
|
|
7
8
|
import { getNodesAndEdges as getNodesAndEdgesForService } from '@utils/node-graphs/services-node-graph';
|
|
8
9
|
import { getNodesAndEdges as getNodesAndEdgesForAgent } from '@utils/node-graphs/agents-node-graph';
|
|
9
10
|
import {
|
|
@@ -79,6 +80,8 @@ export async function getArchitectureDiagramGraph({
|
|
|
79
80
|
}): Promise<Graph> {
|
|
80
81
|
const view = await getArchitectureDiagramView(resource);
|
|
81
82
|
// A domain without systems or subdomains has no level 1, so it shows the full diagram
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
if (detail === 'overview' && view.overview) return { nodes: view.overview.nodes, edges: view.overview.edges };
|
|
84
|
+
// Level 2: as laid out for domains and systems, otherwise the diagram without its messages and channels
|
|
85
|
+
if (detail === 'services') return view.hiddenMessages ?? hideMessageNodes(view.nodes, view.edges);
|
|
86
|
+
return { nodes: view.nodes, edges: view.edges };
|
|
84
87
|
}
|