@eventcatalog/core 3.28.3 → 3.29.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-KP324TGM.js → chunk-3YZL6CMP.js} +1 -1
- package/dist/{chunk-LLC66YM2.js → chunk-B3DM4RWS.js} +1 -1
- package/dist/{chunk-JLGWTWR4.js → chunk-NKN2LYFC.js} +1 -1
- package/dist/{chunk-SBZBCN3T.js → chunk-XN2XNAOY.js} +1 -1
- package/dist/{chunk-L36OEOCB.js → chunk-ZY6MUMIK.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 +5 -5
- 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/SchemaExplorer/JSONSchemaViewer.tsx +23 -9
- package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +104 -42
- package/package.json +2 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-NKN2LYFC.js";
|
|
4
|
+
import "../chunk-XN2XNAOY.js";
|
|
5
5
|
import "../chunk-4UVFXLPI.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-ZY6MUMIK.js";
|
|
7
7
|
import "../chunk-5T63CXKU.js";
|
|
8
8
|
export {
|
|
9
9
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
|
@@ -114,7 +114,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
|
|
|
114
114
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
115
115
|
|
|
116
116
|
// package.json
|
|
117
|
-
var version = "3.
|
|
117
|
+
var version = "3.29.0";
|
|
118
118
|
|
|
119
119
|
// src/constants.ts
|
|
120
120
|
var VERSION = version;
|
package/dist/eventcatalog.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "./chunk-PLNJC7NZ.js";
|
|
7
7
|
import {
|
|
8
8
|
log_build_default
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-NKN2LYFC.js";
|
|
10
|
+
import "./chunk-XN2XNAOY.js";
|
|
11
11
|
import "./chunk-4UVFXLPI.js";
|
|
12
12
|
import {
|
|
13
13
|
runMigrations
|
|
@@ -22,13 +22,13 @@ import {
|
|
|
22
22
|
} from "./chunk-3KXCGYET.js";
|
|
23
23
|
import {
|
|
24
24
|
generate
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3YZL6CMP.js";
|
|
26
26
|
import {
|
|
27
27
|
logger
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-B3DM4RWS.js";
|
|
29
29
|
import {
|
|
30
30
|
VERSION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-ZY6MUMIK.js";
|
|
32
32
|
import {
|
|
33
33
|
getEventCatalogConfigFile,
|
|
34
34
|
verifyRequiredFieldsAreInCatalogConfigFile
|
package/dist/generate.cjs
CHANGED
package/dist/generate.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generate
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-3YZL6CMP.js";
|
|
4
|
+
import "./chunk-B3DM4RWS.js";
|
|
5
|
+
import "./chunk-ZY6MUMIK.js";
|
|
6
6
|
import "./chunk-5T63CXKU.js";
|
|
7
7
|
export {
|
|
8
8
|
generate
|
package/dist/utils/cli-logger.js
CHANGED
|
@@ -19,6 +19,18 @@ interface SchemaPropertyProps {
|
|
|
19
19
|
expand: boolean;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// JSON Schema allows `type` to be a string or an array of strings (e.g. ["object", "null"]).
|
|
23
|
+
// These helpers normalise both forms so the rest of the viewer can treat type checks uniformly.
|
|
24
|
+
function hasType(type: any, candidate: string): boolean {
|
|
25
|
+
if (Array.isArray(type)) return type.includes(candidate);
|
|
26
|
+
return type === candidate;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function formatType(type: any): string {
|
|
30
|
+
if (Array.isArray(type)) return type.join(' | ');
|
|
31
|
+
return type ?? '';
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
// Helper function to count properties recursively
|
|
23
35
|
function countProperties(obj: any): number {
|
|
24
36
|
if (!obj || typeof obj !== 'object') return 0;
|
|
@@ -196,7 +208,7 @@ function processSchema(schema: any, rootSchema?: any): any {
|
|
|
196
208
|
}
|
|
197
209
|
|
|
198
210
|
// Process array items
|
|
199
|
-
if (schema.type
|
|
211
|
+
if (hasType(schema.type, 'array') && schema.items) {
|
|
200
212
|
schema = { ...schema, items: processSchema(schema.items, root) };
|
|
201
213
|
}
|
|
202
214
|
|
|
@@ -269,11 +281,11 @@ const SchemaProperty = ({ name, details, isRequired, level, isListItem = false,
|
|
|
269
281
|
setIsExpanded(expand);
|
|
270
282
|
}, [expand]);
|
|
271
283
|
|
|
272
|
-
const hasNestedProperties = details.type
|
|
273
|
-
const hasArrayItems = details.type
|
|
284
|
+
const hasNestedProperties = hasType(details.type, 'object') && details.properties && Object.keys(details.properties).length > 0;
|
|
285
|
+
const hasArrayItems = hasType(details.type, 'array') && details.items;
|
|
274
286
|
const hasArrayItemProperties =
|
|
275
287
|
hasArrayItems &&
|
|
276
|
-
((details.items.type
|
|
288
|
+
((hasType(details.items.type, 'object') && details.items.properties) ||
|
|
277
289
|
details.items.allOf ||
|
|
278
290
|
details.items.oneOf ||
|
|
279
291
|
details.items.anyOf ||
|
|
@@ -307,8 +319,8 @@ const SchemaProperty = ({ name, details, isRequired, level, isListItem = false,
|
|
|
307
319
|
<div>
|
|
308
320
|
<span className="font-semibold text-[rgb(var(--ec-page-text))] text-sm">{name}</span>
|
|
309
321
|
<span className="ml-1.5 text-[rgb(var(--ec-accent))] font-mono text-xs">
|
|
310
|
-
{hasVariants ? (details.variantType === 'anyOf' ? 'anyOf' : 'oneOf') : details.type}
|
|
311
|
-
{details.type
|
|
322
|
+
{hasVariants ? (details.variantType === 'anyOf' ? 'anyOf' : 'oneOf') : formatType(details.type)}
|
|
323
|
+
{hasType(details.type, 'array') && details.items?.type ? `[${formatType(details.items.type)}]` : ''}
|
|
312
324
|
{details.format ? `<${details.format}>` : ''}
|
|
313
325
|
{details._refPath && (
|
|
314
326
|
<span className="text-blue-600 dark:text-blue-400 ml-1">→ {details._refName || details._refPath}</span>
|
|
@@ -513,9 +525,9 @@ export default function JSONSchemaViewer({
|
|
|
513
525
|
let display = processedSchema;
|
|
514
526
|
let isArray = false;
|
|
515
527
|
|
|
516
|
-
if (processedSchema.type
|
|
528
|
+
if (hasType(processedSchema.type, 'array') && processedSchema.items) {
|
|
517
529
|
isArray = true;
|
|
518
|
-
if (processedSchema.items.type
|
|
530
|
+
if (hasType(processedSchema.items.type, 'object') && processedSchema.items.properties) {
|
|
519
531
|
display = {
|
|
520
532
|
...processedSchema.items,
|
|
521
533
|
description: processedSchema.description || processedSchema.items.description,
|
|
@@ -838,7 +850,9 @@ export default function JSONSchemaViewer({
|
|
|
838
850
|
<div className="text-[rgb(var(--ec-page-text-muted))] text-sm">
|
|
839
851
|
<p>
|
|
840
852
|
This array contains items of type:{' '}
|
|
841
|
-
<span className="font-mono text-blue-600 dark:text-blue-400">
|
|
853
|
+
<span className="font-mono text-blue-600 dark:text-blue-400">
|
|
854
|
+
{processedSchema.items?.type ? formatType(processedSchema.items.type) : 'unknown'}
|
|
855
|
+
</span>
|
|
842
856
|
</p>
|
|
843
857
|
{processedSchema.items?.description && (
|
|
844
858
|
<p className="text-xs mt-2 text-[rgb(var(--ec-page-text-muted))]">{processedSchema.items.description}</p>
|
|
@@ -22,6 +22,12 @@ interface Props {
|
|
|
22
22
|
renderAllEdges?: boolean;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
interface Maps {
|
|
26
|
+
messageMap: Map<string, any[]>;
|
|
27
|
+
serviceMap: Map<string, any[]>;
|
|
28
|
+
flowMap: Map<string, any[]>;
|
|
29
|
+
}
|
|
30
|
+
|
|
25
31
|
const getServiceNode = (step: any, serviceMap: Map<string, any[]>) => {
|
|
26
32
|
const service = findInMap(serviceMap, step.service.id, step.service.version);
|
|
27
33
|
return {
|
|
@@ -49,53 +55,58 @@ const getMessageNode = (step: any, messageMap: Map<string, any[]>) => {
|
|
|
49
55
|
};
|
|
50
56
|
};
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
// Rewrite every id/source/target in a precomputed sub-flow graph with a
|
|
59
|
+
// namespace prefix so inlined copies don't collide with the parent. Nested
|
|
60
|
+
// `data.expandedNodes` / `data.expandedEdges` payloads are rewritten too so
|
|
61
|
+
// the namespace chain stays unique when the same sub-flow is inlined under
|
|
62
|
+
// multiple parents.
|
|
63
|
+
const prefixGraph = (graph: { nodes: any[]; edges: any[] }, prefix: string) => {
|
|
64
|
+
if (!prefix) return graph;
|
|
65
|
+
const nodes = graph.nodes.map((n) => {
|
|
66
|
+
const next: any = { ...n, id: `${prefix}${n.id}` };
|
|
67
|
+
if (n.data?.expandedNodes || n.data?.expandedEdges) {
|
|
68
|
+
const nested = prefixGraph({ nodes: n.data.expandedNodes ?? [], edges: n.data.expandedEdges ?? [] }, prefix);
|
|
69
|
+
next.data = { ...n.data, expandedNodes: nested.nodes, expandedEdges: nested.edges };
|
|
70
|
+
}
|
|
71
|
+
return next;
|
|
72
|
+
});
|
|
73
|
+
const edges = graph.edges.map((e) => ({
|
|
74
|
+
...e,
|
|
75
|
+
id: `${prefix}${e.id}`,
|
|
76
|
+
source: `${prefix}${e.source}`,
|
|
77
|
+
target: `${prefix}${e.target}`,
|
|
78
|
+
}));
|
|
79
|
+
return { nodes, edges };
|
|
80
|
+
};
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// `subFlowCache` keys each flow's graph by `id@version` so an N-times
|
|
83
|
+
// referenced sub-flow is built once. `visited` short-circuits cycles.
|
|
84
|
+
const buildFlowGraphInternal = (
|
|
85
|
+
flow: any,
|
|
86
|
+
maps: Maps,
|
|
87
|
+
mode: 'simple' | 'full',
|
|
88
|
+
subFlowCache: Map<string, { nodes: any[]; edges: any[] }>,
|
|
89
|
+
visited: Set<string>
|
|
90
|
+
) => {
|
|
91
|
+
const nodes: any[] = [];
|
|
92
|
+
const edges: any[] = [];
|
|
81
93
|
|
|
82
|
-
const steps = flow?.data
|
|
94
|
+
const steps = flow?.data?.steps || [];
|
|
95
|
+
const stepNodeId = (stepId: any) => `step-${stepId}`;
|
|
83
96
|
|
|
84
|
-
// Hydrate the steps with information they may need.
|
|
85
97
|
const hydratedSteps = steps.map((step: any) => {
|
|
86
|
-
if (step.service) return getServiceNode(step, serviceMap);
|
|
87
|
-
if (step.flow) return getFlowNode(step, flowMap);
|
|
88
|
-
if (step.message) return getMessageNode(step, messageMap);
|
|
98
|
+
if (step.service) return getServiceNode(step, maps.serviceMap);
|
|
99
|
+
if (step.flow) return getFlowNode(step, maps.flowMap);
|
|
100
|
+
if (step.message) return getMessageNode(step, maps.messageMap);
|
|
89
101
|
if (step.actor) return { ...step, type: 'actor', actor: step.actor };
|
|
90
102
|
if (step.custom) return { ...step, type: 'custom', custom: step.custom };
|
|
91
103
|
if (step.externalSystem) return { ...step, type: 'externalSystem', externalSystem: step.externalSystem };
|
|
92
104
|
return { ...step, type: 'step' };
|
|
93
105
|
});
|
|
94
106
|
|
|
95
|
-
// Create nodes
|
|
96
107
|
hydratedSteps.forEach((step: any, index: number) => {
|
|
97
|
-
const node = {
|
|
98
|
-
id:
|
|
108
|
+
const node: NodeType = {
|
|
109
|
+
id: stepNodeId(step.id),
|
|
99
110
|
sourcePosition: 'right',
|
|
100
111
|
targetPosition: 'left',
|
|
101
112
|
data: {
|
|
@@ -124,6 +135,21 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
124
135
|
id: step.flow.data.id,
|
|
125
136
|
version: step.flow.data.version,
|
|
126
137
|
});
|
|
138
|
+
|
|
139
|
+
// Guard cycles; inline the sub-flow's graph so the client can expand on click.
|
|
140
|
+
const subFlowKey = `${step.flow.data.id}@${step.flow.data.version}`;
|
|
141
|
+
if (!visited.has(subFlowKey)) {
|
|
142
|
+
let cached = subFlowCache.get(subFlowKey);
|
|
143
|
+
if (!cached) {
|
|
144
|
+
cached = buildFlowGraphInternal(step.flow, maps, mode, subFlowCache, new Set([...visited, subFlowKey]));
|
|
145
|
+
subFlowCache.set(subFlowKey, cached);
|
|
146
|
+
}
|
|
147
|
+
if (cached.nodes.length > 0) {
|
|
148
|
+
const { nodes: childNodes, edges: childEdges } = prefixGraph(cached, `${node.id}__`);
|
|
149
|
+
node.data.expandedNodes = childNodes;
|
|
150
|
+
node.data.expandedEdges = childEdges;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
127
153
|
}
|
|
128
154
|
if (step.message) {
|
|
129
155
|
node.data.message = { ...step.message, ...step.message.data };
|
|
@@ -142,12 +168,10 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
142
168
|
nodes.push(node);
|
|
143
169
|
});
|
|
144
170
|
|
|
145
|
-
|
|
146
|
-
hydratedSteps.forEach((step: any, index: number) => {
|
|
171
|
+
hydratedSteps.forEach((step: any) => {
|
|
147
172
|
let paths = step.next_steps || [];
|
|
148
173
|
|
|
149
174
|
if (step.next_step) {
|
|
150
|
-
// If its a string or number
|
|
151
175
|
if (!step.next_step?.id) {
|
|
152
176
|
paths = [{ id: step.next_step }];
|
|
153
177
|
} else {
|
|
@@ -165,8 +189,8 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
165
189
|
paths.forEach((path: any) => {
|
|
166
190
|
edges.push({
|
|
167
191
|
id: `step-${step.id}-step-${path.id}`,
|
|
168
|
-
source:
|
|
169
|
-
target:
|
|
192
|
+
source: stepNodeId(step.id),
|
|
193
|
+
target: stepNodeId(path.id),
|
|
170
194
|
type: 'flow-edge',
|
|
171
195
|
label: path.label,
|
|
172
196
|
animated: true,
|
|
@@ -184,6 +208,45 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
184
208
|
});
|
|
185
209
|
});
|
|
186
210
|
|
|
211
|
+
return { nodes, edges };
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simple', renderAllEdges = false }: Props) => {
|
|
215
|
+
const graph = defaultFlow || createDagreGraph({ ranksep: 360, nodesep: 200 });
|
|
216
|
+
|
|
217
|
+
const [flows, events, commands, queries, services] = await Promise.all([
|
|
218
|
+
getCollection('flows'),
|
|
219
|
+
getCollection('events'),
|
|
220
|
+
getCollection('commands'),
|
|
221
|
+
getCollection('queries'),
|
|
222
|
+
getCollection('services'),
|
|
223
|
+
]);
|
|
224
|
+
|
|
225
|
+
const flow = flows.find((flow) => flow.data.id === id && flow.data.version === version);
|
|
226
|
+
|
|
227
|
+
if (!flow) {
|
|
228
|
+
return {
|
|
229
|
+
nodes: [],
|
|
230
|
+
edges: [],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const messages = [...events, ...commands, ...queries];
|
|
235
|
+
const maps: Maps = {
|
|
236
|
+
messageMap: createVersionedMap(messages),
|
|
237
|
+
serviceMap: createVersionedMap(services),
|
|
238
|
+
flowMap: createVersionedMap(flows),
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const subFlowCache = new Map<string, { nodes: any[]; edges: any[] }>();
|
|
242
|
+
const { nodes, edges } = buildFlowGraphInternal(
|
|
243
|
+
flow,
|
|
244
|
+
maps,
|
|
245
|
+
mode,
|
|
246
|
+
subFlowCache,
|
|
247
|
+
new Set([`${flow.data.id}@${flow.data.version}`])
|
|
248
|
+
);
|
|
249
|
+
|
|
187
250
|
nodes.forEach((node: any) => {
|
|
188
251
|
graph.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
|
|
189
252
|
});
|
|
@@ -192,7 +255,6 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
192
255
|
graph.setEdge(edge.source, edge.target);
|
|
193
256
|
});
|
|
194
257
|
|
|
195
|
-
// Render the diagram in memory getting hte X and Y
|
|
196
258
|
dagre.layout(graph);
|
|
197
259
|
|
|
198
260
|
return {
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "3.
|
|
10
|
+
"version": "3.29.0",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"zod": "^4.3.6",
|
|
106
106
|
"@eventcatalog/linter": "1.0.21",
|
|
107
107
|
"@eventcatalog/sdk": "2.20.0",
|
|
108
|
-
"@eventcatalog/visualiser": "^3.
|
|
108
|
+
"@eventcatalog/visualiser": "^3.19.0"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@astrojs/check": "^0.9.8",
|