@eventcatalog/core 4.1.5 → 4.2.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-E6IUV4GX.js → chunk-A6SWOPJ4.js} +1 -1
- package/dist/{chunk-G74MXXTG.js → chunk-DTQ2MXRB.js} +1 -1
- package/dist/{chunk-X77TET65.js → chunk-PUTZR6SV.js} +1 -1
- package/dist/{chunk-GIU3S4CI.js → chunk-RQ36O7QA.js} +1 -1
- package/dist/{chunk-DIUAURE2.js → chunk-V6UMVNX4.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +36 -23
- package/dist/eventcatalog.js +41 -28
- 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/Lineage/LineageScenarioSwitcher.tsx +65 -0
- package/eventcatalog/src/content.config.ts +9 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +3 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +4 -2
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/_index.data.ts +66 -0
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +201 -0
- package/eventcatalog/src/stores/sidebar-store/builders/message.ts +31 -1
- package/eventcatalog/src/stores/sidebar-store/state.ts +22 -4
- package/eventcatalog/src/utils/collections/commands.ts +1 -1
- package/eventcatalog/src/utils/collections/message-triggers.ts +118 -0
- package/eventcatalog/src/utils/file-diffs.ts +4 -2
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +2 -1
- package/eventcatalog/src/utils/node-graphs/message-lineage.ts +131 -0
- package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +119 -1
- package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +15 -1
- package/eventcatalog/src/utils/node-graphs/utils/utils.ts +14 -4
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// import { getColor } from '@utils/colors';
|
|
2
2
|
import { getEvents } from '@utils/collections/events';
|
|
3
|
-
import type
|
|
3
|
+
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
4
4
|
import dagre from 'dagre';
|
|
5
5
|
import {
|
|
6
6
|
calculatedNodes,
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
import { getNodesAndEdgesForChannelChain } from './channel-node-graph';
|
|
43
43
|
import { getChannelChain, isChannelsConnected } from '@utils/collections/channels';
|
|
44
44
|
import { getChannels } from '@utils/collections/channels';
|
|
45
|
+
import { getTriggeredByOfMessage, getTriggersOfMessage, type MessageReceiver } from '@utils/collections/message-triggers';
|
|
45
46
|
|
|
46
47
|
type DagreGraph = any;
|
|
47
48
|
type RoutableResource = CollectionEntry<'agents'> | CollectionEntry<'services'>;
|
|
@@ -166,6 +167,52 @@ const getDataProductNodeData = (resource: CollectionEntry<'data-products'>, mode
|
|
|
166
167
|
contextMenu: buildContextMenuForResource({ collection: 'data-products', id: resource.data.id, version: resource.data.version }),
|
|
167
168
|
});
|
|
168
169
|
|
|
170
|
+
export const getTriggerReceiverNodeData = (receiver: MessageReceiver, mode: 'simple' | 'full') => {
|
|
171
|
+
if (receiver.collection !== 'domains') return getRoutableNodeData(receiver, mode);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
title: receiver.data.id,
|
|
175
|
+
mode,
|
|
176
|
+
domain: {
|
|
177
|
+
...receiver,
|
|
178
|
+
data: {
|
|
179
|
+
...receiver.data,
|
|
180
|
+
// Raw domain entries contain service pointers, while the visualiser's
|
|
181
|
+
// domain node expects hydrated services in full mode.
|
|
182
|
+
services: [],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
contextMenu: buildContextMenuForResource({
|
|
186
|
+
collection: 'domains',
|
|
187
|
+
id: receiver.data.id,
|
|
188
|
+
version: receiver.data.version,
|
|
189
|
+
}),
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const createTriggerMessageNode = (
|
|
194
|
+
message: CollectionEntry<CollectionMessageTypes>,
|
|
195
|
+
mode: 'simple' | 'full',
|
|
196
|
+
isFocused = false
|
|
197
|
+
) =>
|
|
198
|
+
createNode({
|
|
199
|
+
id: generateIdForNode(message),
|
|
200
|
+
type: message.collection,
|
|
201
|
+
data: {
|
|
202
|
+
mode,
|
|
203
|
+
...(isFocused ? { isFocused: true } : {}),
|
|
204
|
+
message: { ...message.data, ...getOperationFields(message.data) },
|
|
205
|
+
contextMenu: buildContextMenuForMessage({
|
|
206
|
+
id: message.data.id,
|
|
207
|
+
version: message.data.version,
|
|
208
|
+
name: message.data.name,
|
|
209
|
+
collection: message.collection,
|
|
210
|
+
schemaPath: (message.data as any).schemaPath,
|
|
211
|
+
}),
|
|
212
|
+
},
|
|
213
|
+
position: { x: 0, y: 0 },
|
|
214
|
+
});
|
|
215
|
+
|
|
169
216
|
const getNodesAndEdges = async ({
|
|
170
217
|
id,
|
|
171
218
|
version,
|
|
@@ -194,6 +241,19 @@ const getNodesAndEdges = async ({
|
|
|
194
241
|
// Pre-calculate channel map for O(1) lookups
|
|
195
242
|
const channelMap = createVersionedMap(channels);
|
|
196
243
|
|
|
244
|
+
// Trigger metadata lives on raw receive pointers. Hydrated resources replace
|
|
245
|
+
// those pointers with messages, so load the raw collections for this relation.
|
|
246
|
+
const [events, commands, queries, services, agents, domains] = await Promise.all([
|
|
247
|
+
getCollection('events'),
|
|
248
|
+
getCollection('commands'),
|
|
249
|
+
getCollection('queries'),
|
|
250
|
+
getCollection('services'),
|
|
251
|
+
getCollection('agents'),
|
|
252
|
+
getCollection('domains'),
|
|
253
|
+
]);
|
|
254
|
+
const allMessages = [...events, ...commands, ...queries] as CollectionEntry<CollectionMessageTypes>[];
|
|
255
|
+
const messageReceivers = [...services, ...agents, ...domains] as MessageReceiver[];
|
|
256
|
+
|
|
197
257
|
// We always render the message itself
|
|
198
258
|
nodes.push({
|
|
199
259
|
id: generateIdForNode(message),
|
|
@@ -201,6 +261,7 @@ const getNodesAndEdges = async ({
|
|
|
201
261
|
targetPosition: 'left',
|
|
202
262
|
data: {
|
|
203
263
|
mode,
|
|
264
|
+
isFocused: true,
|
|
204
265
|
message: {
|
|
205
266
|
...message.data,
|
|
206
267
|
...getOperationFields(message.data),
|
|
@@ -564,6 +625,63 @@ const getNodesAndEdges = async ({
|
|
|
564
625
|
}
|
|
565
626
|
});
|
|
566
627
|
|
|
628
|
+
const appendNode = (node: Node) => {
|
|
629
|
+
if (!nodes.some((existingNode: Node) => existingNode.id === node.id)) nodes.push(node);
|
|
630
|
+
};
|
|
631
|
+
const appendEdge = (source: any, target: any, label: string, colorMessage: CollectionEntry<CollectionMessageTypes>) => {
|
|
632
|
+
const id = generatedIdForEdge(source, target);
|
|
633
|
+
if (edges.some((edge: Edge) => edge.id === id)) return;
|
|
634
|
+
|
|
635
|
+
edges.push(
|
|
636
|
+
createEdge({
|
|
637
|
+
id,
|
|
638
|
+
source: generateIdForNode(source),
|
|
639
|
+
target: generateIdForNode(target),
|
|
640
|
+
label,
|
|
641
|
+
data: {
|
|
642
|
+
customColor: getColorFromString(colorMessage.data.id),
|
|
643
|
+
rootSourceAndTarget: {
|
|
644
|
+
source: { id: generateIdForNode(source), collection: source.collection },
|
|
645
|
+
target: { id: generateIdForNode(target), collection: target.collection },
|
|
646
|
+
},
|
|
647
|
+
},
|
|
648
|
+
})
|
|
649
|
+
);
|
|
650
|
+
};
|
|
651
|
+
const appendReceiver = (receiver: MessageReceiver) => {
|
|
652
|
+
const receiverId = generateIdForNode(receiver);
|
|
653
|
+
if (nodes.some((node: Node) => node.id === receiverId)) return;
|
|
654
|
+
|
|
655
|
+
appendNode(
|
|
656
|
+
createNode({
|
|
657
|
+
id: receiverId,
|
|
658
|
+
type: receiver.collection,
|
|
659
|
+
data: getTriggerReceiverNodeData(receiver, mode),
|
|
660
|
+
position: { x: 0, y: 0 },
|
|
661
|
+
})
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
if (receiver.collection !== 'domains') {
|
|
665
|
+
appendAgentToolNodesAndEdges({ agent: receiver, nodes, edges, mode });
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
// Complete both sides of a trigger chain around the focused message:
|
|
670
|
+
// triggering message -> receiver -> triggered message.
|
|
671
|
+
for (const relation of getTriggeredByOfMessage(messageReceivers, message, allMessages)) {
|
|
672
|
+
appendNode(createTriggerMessageNode(relation.message, mode));
|
|
673
|
+
appendReceiver(relation.receiver);
|
|
674
|
+
appendEdge(relation.message, relation.receiver, getEdgeLabelForMessageAsSource(relation.message), relation.message);
|
|
675
|
+
appendEdge(relation.receiver, message, getEdgeLabelForServiceAsTarget(message), message);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
for (const relation of getTriggersOfMessage(messageReceivers, message, allMessages)) {
|
|
679
|
+
appendReceiver(relation.receiver);
|
|
680
|
+
appendNode(createTriggerMessageNode(relation.message, mode));
|
|
681
|
+
appendEdge(message, relation.receiver, getEdgeLabelForMessageAsSource(message), message);
|
|
682
|
+
appendEdge(relation.receiver, relation.message, getEdgeLabelForServiceAsTarget(relation.message), relation.message);
|
|
683
|
+
}
|
|
684
|
+
|
|
567
685
|
nodes.forEach((node: any) => {
|
|
568
686
|
flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
|
|
569
687
|
});
|
|
@@ -347,7 +347,10 @@ export const getNodesAndEdges = async ({
|
|
|
347
347
|
id: generateIdForNode(service),
|
|
348
348
|
sourcePosition: 'right',
|
|
349
349
|
targetPosition: 'left',
|
|
350
|
-
data:
|
|
350
|
+
data: {
|
|
351
|
+
...getResourceNodeData(service, mode),
|
|
352
|
+
isFocused: service.collection === 'services',
|
|
353
|
+
},
|
|
351
354
|
type: service.collection,
|
|
352
355
|
});
|
|
353
356
|
|
|
@@ -606,6 +609,17 @@ export const getNodesAndEdges = async ({
|
|
|
606
609
|
uniqueNodesById.set(node.id, node);
|
|
607
610
|
}
|
|
608
611
|
});
|
|
612
|
+
|
|
613
|
+
// Inbound message processing may create the service node before the primary
|
|
614
|
+
// node is added. Mark the surviving copy after deduplication so the service
|
|
615
|
+
// currently being viewed always retains its focus treatment.
|
|
616
|
+
if (service.collection === 'services') {
|
|
617
|
+
const focusedServiceNode = uniqueNodesById.get(generateIdForNode(service));
|
|
618
|
+
if (focusedServiceNode) {
|
|
619
|
+
focusedServiceNode.data = { ...focusedServiceNode.data, isFocused: true };
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
609
623
|
const uniqueNodes = Array.from(uniqueNodesById.values());
|
|
610
624
|
|
|
611
625
|
uniqueNodes.forEach((node: any) => {
|
|
@@ -162,7 +162,10 @@ export const buildContextMenuForMessage = ({
|
|
|
162
162
|
collection: string;
|
|
163
163
|
schemaPath?: string;
|
|
164
164
|
}): ContextMenuItem[] => {
|
|
165
|
-
const items: ContextMenuItem[] = [
|
|
165
|
+
const items: ContextMenuItem[] = [
|
|
166
|
+
{ label: 'Read documentation', href: buildUrl(`/docs/${collection}/${id}/${version}`) },
|
|
167
|
+
{ label: 'Focus node', href: buildUrl(`/visualiser/${collection}/${id}/${version}`) },
|
|
168
|
+
];
|
|
166
169
|
|
|
167
170
|
if (schemaPath) {
|
|
168
171
|
items.push({
|
|
@@ -250,7 +253,10 @@ export const buildContextMenuForService = ({
|
|
|
250
253
|
specifications?: unknown;
|
|
251
254
|
repository?: { url: string };
|
|
252
255
|
}): ContextMenuItem[] => {
|
|
253
|
-
const items: ContextMenuItem[] = [
|
|
256
|
+
const items: ContextMenuItem[] = [
|
|
257
|
+
{ label: 'Read documentation', href: buildUrl(`/docs/services/${id}/${version}`) },
|
|
258
|
+
{ label: 'Focus node', href: buildUrl(`/visualiser/services/${id}/${version}`) },
|
|
259
|
+
];
|
|
254
260
|
|
|
255
261
|
const specItems = getSpecMenuItems(specifications, id, version);
|
|
256
262
|
items.push(...specItems);
|
|
@@ -283,7 +289,10 @@ export const buildContextMenuForAgent = ({
|
|
|
283
289
|
version: string;
|
|
284
290
|
repository?: { url: string };
|
|
285
291
|
}): ContextMenuItem[] => {
|
|
286
|
-
const items: ContextMenuItem[] = [
|
|
292
|
+
const items: ContextMenuItem[] = [
|
|
293
|
+
{ label: 'Read documentation', href: buildUrl(`/docs/agents/${id}/${version}`) },
|
|
294
|
+
{ label: 'Focus node', href: buildUrl(`/visualiser/agents/${id}/${version}`) },
|
|
295
|
+
];
|
|
287
296
|
|
|
288
297
|
if (repository?.url) {
|
|
289
298
|
items.push({
|
|
@@ -315,6 +324,7 @@ export const buildContextMenuForResource = ({
|
|
|
315
324
|
}): ContextMenuItem[] => {
|
|
316
325
|
return [
|
|
317
326
|
{ label: 'Read documentation', href: buildUrl(`/docs/${collection}/${id}/${version}`) },
|
|
327
|
+
{ label: 'Focus node', href: buildUrl(`/visualiser/${collection}/${id}/${version}`) },
|
|
318
328
|
{
|
|
319
329
|
label: 'Read changelog',
|
|
320
330
|
href: buildUrl(`/docs/${collection}/${id}/${version}/changelog`),
|
|
@@ -331,7 +341,7 @@ export const buildContextMenuForResource = ({
|
|
|
331
341
|
export const buildContextMenuForSystem = ({ id, version }: { id: string; version: string }): ContextMenuItem[] => {
|
|
332
342
|
return [
|
|
333
343
|
{ label: 'Read documentation', href: buildUrl(`/docs/systems/${id}/${version}`) },
|
|
334
|
-
{ label: '
|
|
344
|
+
{ label: 'Focus node', href: buildUrl(`/visualiser/systems/${id}/${version}`) },
|
|
335
345
|
{ label: 'View context', href: buildUrl(`/visualiser/systems/${id}/${version}/context`) },
|
|
336
346
|
];
|
|
337
347
|
};
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "4.1
|
|
10
|
+
"version": "4.2.1",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
@@ -116,9 +116,9 @@
|
|
|
116
116
|
"update-notifier": "^7.3.1",
|
|
117
117
|
"uuid": "^10.0.0",
|
|
118
118
|
"zod": "^4.3.6",
|
|
119
|
-
"@eventcatalog/
|
|
120
|
-
"@eventcatalog/
|
|
121
|
-
"@eventcatalog/
|
|
119
|
+
"@eventcatalog/sdk": "2.26.0",
|
|
120
|
+
"@eventcatalog/visualiser": "^4.1.0",
|
|
121
|
+
"@eventcatalog/linter": "1.1.5"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@astrojs/check": "^0.9.9",
|