@eventcatalog/core 3.25.6 → 3.26.1
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-P23BMUBV.js → chunk-6BTN7CY7.js} +1 -1
- package/dist/{chunk-ZEOK723Y.js → chunk-EL6ZQNAX.js} +1 -1
- package/dist/{chunk-53HXLUNO.js → chunk-LTWPA4SA.js} +1 -1
- package/dist/{chunk-R7P4GTFQ.js → chunk-N3QSCVYA.js} +1 -1
- package/dist/{chunk-2ILJMBQM.js → chunk-Y736FREK.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +562 -19
- package/dist/eventcatalog.js +576 -31
- 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/astro.config.mjs +2 -1
- package/eventcatalog/integrations/eventcatalog-features.ts +13 -0
- package/eventcatalog/public/icons/graphql.svg +3 -1
- package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +225 -0
- package/eventcatalog/src/components/FieldsExplorer/FieldNodeGraph.tsx +521 -0
- package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +501 -0
- package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +236 -0
- package/eventcatalog/src/enterprise/fields/field-extractor.test.ts +241 -0
- package/eventcatalog/src/enterprise/fields/field-extractor.ts +183 -0
- package/eventcatalog/src/enterprise/fields/field-indexer.ts +131 -0
- package/eventcatalog/src/enterprise/fields/fields-db.test.ts +186 -0
- package/eventcatalog/src/enterprise/fields/fields-db.ts +453 -0
- package/eventcatalog/src/enterprise/fields/pages/api/fields.ts +43 -0
- package/eventcatalog/src/enterprise/fields/pages/fields.astro +19 -0
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +23 -3
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +14 -16
- package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +192 -0
- package/package.json +6 -4
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { Node, Edge } from '@xyflow/react';
|
|
2
|
+
import dagre from 'dagre';
|
|
3
|
+
import {
|
|
4
|
+
createDagreGraph,
|
|
5
|
+
calculatedNodes,
|
|
6
|
+
createEdge,
|
|
7
|
+
createNode,
|
|
8
|
+
buildContextMenuForMessage,
|
|
9
|
+
buildContextMenuForService,
|
|
10
|
+
DEFAULT_NODE_WIDTH,
|
|
11
|
+
DEFAULT_NODE_HEIGHT,
|
|
12
|
+
} from './utils/utils';
|
|
13
|
+
|
|
14
|
+
export interface FieldOccurrence {
|
|
15
|
+
messageId: string;
|
|
16
|
+
messageVersion: string;
|
|
17
|
+
messageType: string;
|
|
18
|
+
messageName?: string;
|
|
19
|
+
messageSummary?: string;
|
|
20
|
+
messageOwners?: string[];
|
|
21
|
+
fieldType?: string;
|
|
22
|
+
producers: { id: string; version: string; name?: string; summary?: string; owners?: string[] }[];
|
|
23
|
+
consumers: { id: string; version: string; name?: string; summary?: string; owners?: string[] }[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
fieldPath: string;
|
|
28
|
+
fieldType: string;
|
|
29
|
+
occurrences: FieldOccurrence[];
|
|
30
|
+
mode?: 'simple' | 'full';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const getNodesAndEdges = ({
|
|
34
|
+
fieldPath,
|
|
35
|
+
fieldType,
|
|
36
|
+
occurrences,
|
|
37
|
+
mode = 'full',
|
|
38
|
+
}: Props): { nodes: Node[]; edges: Edge[] } => {
|
|
39
|
+
const flow = createDagreGraph({ ranksep: 200, nodesep: 50 });
|
|
40
|
+
const nodes: Node[] = [];
|
|
41
|
+
const edges: Edge[] = [];
|
|
42
|
+
const addedNodes = new Set<string>();
|
|
43
|
+
|
|
44
|
+
// Detect distinct types across occurrences
|
|
45
|
+
const typeCounts = new Map<string, number>();
|
|
46
|
+
for (const occ of occurrences) {
|
|
47
|
+
const t = occ.fieldType || fieldType;
|
|
48
|
+
typeCounts.set(t, (typeCounts.get(t) || 0) + 1);
|
|
49
|
+
}
|
|
50
|
+
const hasConflicts = typeCounts.size > 1;
|
|
51
|
+
|
|
52
|
+
// Create field node(s) — one per type if conflicts, otherwise a single node
|
|
53
|
+
const fieldNodeIds = new Map<string, string>();
|
|
54
|
+
|
|
55
|
+
if (hasConflicts) {
|
|
56
|
+
for (const [type] of typeCounts) {
|
|
57
|
+
const nodeId = `field-${fieldPath}-${type}`;
|
|
58
|
+
fieldNodeIds.set(type, nodeId);
|
|
59
|
+
nodes.push(
|
|
60
|
+
createNode({
|
|
61
|
+
id: nodeId,
|
|
62
|
+
type: 'field',
|
|
63
|
+
position: { x: 0, y: 0 },
|
|
64
|
+
data: { name: fieldPath, type, mode },
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
addedNodes.add(nodeId);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
const nodeId = `field-${fieldPath}`;
|
|
71
|
+
fieldNodeIds.set(fieldType, nodeId);
|
|
72
|
+
nodes.push(
|
|
73
|
+
createNode({
|
|
74
|
+
id: nodeId,
|
|
75
|
+
type: 'field',
|
|
76
|
+
position: { x: 0, y: 0 },
|
|
77
|
+
data: { name: fieldPath, type: fieldType, mode },
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
addedNodes.add(nodeId);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const occ of occurrences) {
|
|
84
|
+
const msgNodeId = `msg-${occ.messageId}-${occ.messageVersion}`;
|
|
85
|
+
const occType = occ.fieldType || fieldType;
|
|
86
|
+
const fieldNodeId = fieldNodeIds.get(occType) || fieldNodeIds.values().next().value;
|
|
87
|
+
|
|
88
|
+
if (!addedNodes.has(msgNodeId)) {
|
|
89
|
+
nodes.push(
|
|
90
|
+
createNode({
|
|
91
|
+
id: msgNodeId,
|
|
92
|
+
type: occ.messageType,
|
|
93
|
+
position: { x: 0, y: 0 },
|
|
94
|
+
data: {
|
|
95
|
+
message: {
|
|
96
|
+
name: occ.messageName || occ.messageId,
|
|
97
|
+
version: occ.messageVersion,
|
|
98
|
+
summary: occ.messageSummary || '',
|
|
99
|
+
id: occ.messageId,
|
|
100
|
+
owners: occ.messageOwners || [],
|
|
101
|
+
},
|
|
102
|
+
contextMenu: buildContextMenuForMessage({
|
|
103
|
+
id: occ.messageId,
|
|
104
|
+
version: occ.messageVersion,
|
|
105
|
+
name: occ.messageName || occ.messageId,
|
|
106
|
+
collection: occ.messageType === 'query' ? 'queries' : `${occ.messageType}s`,
|
|
107
|
+
}),
|
|
108
|
+
mode,
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
addedNodes.add(msgNodeId);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Producer services
|
|
116
|
+
for (const p of occ.producers) {
|
|
117
|
+
const svcNodeId = `svc-producer-${p.id}-${p.version}`;
|
|
118
|
+
if (!addedNodes.has(svcNodeId)) {
|
|
119
|
+
nodes.push(
|
|
120
|
+
createNode({
|
|
121
|
+
id: svcNodeId,
|
|
122
|
+
type: 'service',
|
|
123
|
+
position: { x: 0, y: 0 },
|
|
124
|
+
data: {
|
|
125
|
+
service: { name: p.name || p.id, version: p.version, summary: p.summary || '', id: p.id, owners: p.owners || [] },
|
|
126
|
+
contextMenu: buildContextMenuForService({ id: p.id, version: p.version }),
|
|
127
|
+
mode,
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
addedNodes.add(svcNodeId);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const prodEdgeId = `e-${svcNodeId}-${msgNodeId}`;
|
|
135
|
+
if (!edges.find((e) => e.id === prodEdgeId)) {
|
|
136
|
+
edges.push(createEdge({ id: prodEdgeId, source: svcNodeId, target: msgNodeId, label: 'produces', type: 'smoothstep' }));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Message → Field (connects to the field node matching this occurrence's type)
|
|
141
|
+
const msgFieldEdgeId = `e-${msgNodeId}-${fieldNodeId}`;
|
|
142
|
+
if (!edges.find((e) => e.id === msgFieldEdgeId)) {
|
|
143
|
+
edges.push(
|
|
144
|
+
createEdge({
|
|
145
|
+
id: msgFieldEdgeId,
|
|
146
|
+
source: msgNodeId,
|
|
147
|
+
target: fieldNodeId,
|
|
148
|
+
label: hasConflicts ? `contains (${occType})` : 'contains',
|
|
149
|
+
type: 'smoothstep',
|
|
150
|
+
})
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Field → Consumer services (from the specific field type node)
|
|
155
|
+
for (const c of occ.consumers) {
|
|
156
|
+
const svcNodeId = `svc-consumer-${c.id}-${c.version}`;
|
|
157
|
+
if (!addedNodes.has(svcNodeId)) {
|
|
158
|
+
nodes.push(
|
|
159
|
+
createNode({
|
|
160
|
+
id: svcNodeId,
|
|
161
|
+
type: 'service',
|
|
162
|
+
position: { x: 0, y: 0 },
|
|
163
|
+
data: {
|
|
164
|
+
service: { name: c.name || c.id, version: c.version, summary: c.summary || '', id: c.id, owners: c.owners || [] },
|
|
165
|
+
contextMenu: buildContextMenuForService({ id: c.id, version: c.version }),
|
|
166
|
+
mode,
|
|
167
|
+
},
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
addedNodes.add(svcNodeId);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const consEdgeId = `e-${fieldNodeId}-${svcNodeId}`;
|
|
174
|
+
if (!edges.find((e) => e.id === consEdgeId)) {
|
|
175
|
+
edges.push(
|
|
176
|
+
createEdge({ id: consEdgeId, source: fieldNodeId, target: svcNodeId, label: 'consumed by', type: 'smoothstep' })
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Apply layout
|
|
183
|
+
for (const node of nodes) {
|
|
184
|
+
flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
|
|
185
|
+
}
|
|
186
|
+
for (const edge of edges) {
|
|
187
|
+
flow.setEdge(edge.source, edge.target);
|
|
188
|
+
}
|
|
189
|
+
dagre.layout(flow);
|
|
190
|
+
|
|
191
|
+
return { nodes: calculatedNodes(flow, nodes), edges };
|
|
192
|
+
};
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/event-catalog/eventcatalog.git"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.26.1",
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
@@ -50,12 +50,13 @@
|
|
|
50
50
|
"@tanstack/react-table": "^8.17.3",
|
|
51
51
|
"@xyflow/react": "^12.3.6",
|
|
52
52
|
"ai": "^6.0.17",
|
|
53
|
-
"astro": "^6.0.
|
|
53
|
+
"astro": "^6.0.8",
|
|
54
54
|
"astro-compress": "^2.3.9",
|
|
55
55
|
"astro-expressive-code": "^0.41.7",
|
|
56
56
|
"astro-seo": "^0.8.4",
|
|
57
57
|
"auth-astro": "^4.2.0",
|
|
58
58
|
"axios": "^1.13.5",
|
|
59
|
+
"better-sqlite3": "^12.8.0",
|
|
59
60
|
"boxen": "^8.0.1",
|
|
60
61
|
"commander": "^12.1.0",
|
|
61
62
|
"concurrently": "^8.2.2",
|
|
@@ -102,11 +103,12 @@
|
|
|
102
103
|
"uuid": "^10.0.0",
|
|
103
104
|
"zod": "^4.3.6",
|
|
104
105
|
"@eventcatalog/linter": "1.0.17",
|
|
105
|
-
"@eventcatalog/
|
|
106
|
-
"@eventcatalog/
|
|
106
|
+
"@eventcatalog/sdk": "2.18.2",
|
|
107
|
+
"@eventcatalog/visualiser": "^3.16.0"
|
|
107
108
|
},
|
|
108
109
|
"devDependencies": {
|
|
109
110
|
"@astrojs/check": "^0.9.8",
|
|
111
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
110
112
|
"@types/dagre": "^0.7.52",
|
|
111
113
|
"@types/diff": "^5.2.2",
|
|
112
114
|
"@types/js-yaml": "^4.0.9",
|