@eventcatalog/core 2.64.3 → 2.65.0-beta.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/README.md +2 -1
- 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-CXZKUSOU.js → chunk-2ZXSFW7J.js} +1 -1
- package/dist/chunk-622JYJWG.js +109 -0
- package/dist/{chunk-C7L3FLQL.js → chunk-6MJGAOPK.js} +1 -1
- package/dist/chunk-BH3JMNAV.js +12 -0
- package/dist/{chunk-WAWMXWSY.js → chunk-GGFP7ZBX.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +139 -24
- package/dist/eventcatalog.js +9 -3
- package/dist/migrations/index.cjs +150 -0
- package/dist/migrations/index.d.cts +3 -0
- package/dist/migrations/index.d.ts +3 -0
- package/dist/migrations/index.js +7 -0
- package/dist/migrations/message-channels-to-service-channels.cjs +139 -0
- package/dist/migrations/message-channels-to-service-channels.d.cts +6 -0
- package/dist/migrations/message-channels-to-service-channels.d.ts +6 -0
- package/dist/migrations/message-channels-to-service-channels.js +6 -0
- package/eventcatalog/src/components/MDX/NodeGraph/Edges/AnimatedMessageEdge.tsx +42 -28
- package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewerRoot.astro +1 -0
- package/eventcatalog/src/components/SideNav/ListViewSideBar/index.tsx +41 -35
- package/eventcatalog/src/content.config.ts +31 -3
- package/eventcatalog/src/enterprise/eventcatalog-chat/providers/ai-provider.ts +0 -4
- package/eventcatalog/src/hooks/eventcatalog-visualizer.ts +35 -15
- package/eventcatalog/src/utils/channels.ts +73 -1
- package/eventcatalog/src/utils/collections/util.ts +7 -0
- package/eventcatalog/src/utils/node-graphs/channel-node-graph.ts +75 -0
- package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +856 -61
- package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +46 -70
- package/eventcatalog/src/utils/node-graphs/utils/utils.ts +26 -80
- package/package.json +2 -2
|
@@ -8,15 +8,24 @@ import {
|
|
|
8
8
|
createEdge,
|
|
9
9
|
generatedIdForEdge,
|
|
10
10
|
generateIdForNode,
|
|
11
|
-
|
|
11
|
+
getColorFromString,
|
|
12
12
|
getEdgeLabelForMessageAsSource,
|
|
13
13
|
getEdgeLabelForServiceAsTarget,
|
|
14
14
|
} from './utils/utils';
|
|
15
|
-
import { MarkerType } from '@xyflow/react';
|
|
16
|
-
import {
|
|
15
|
+
import { MarkerType, type Node, type Edge } from '@xyflow/react';
|
|
16
|
+
import {
|
|
17
|
+
findMatchingNodes,
|
|
18
|
+
getItemsFromCollectionByIdAndSemverOrLatest,
|
|
19
|
+
getLatestVersionInCollectionById,
|
|
20
|
+
} from '@utils/collections/util';
|
|
17
21
|
import type { CollectionMessageTypes } from '@types';
|
|
18
22
|
import { getCommands } from '@utils/commands';
|
|
19
23
|
import { getQueries } from '@utils/queries';
|
|
24
|
+
import { createNode } from './utils/utils';
|
|
25
|
+
import { getConsumersOfMessage, getProducersOfMessage } from '@utils/collections/services';
|
|
26
|
+
import { getNodesAndEdgesForChannelChain } from './channel-node-graph';
|
|
27
|
+
import { getChannelChain, isChannelsConnected } from '@utils/channels';
|
|
28
|
+
import { getChannels } from '@utils/channels';
|
|
20
29
|
|
|
21
30
|
type DagreGraph = any;
|
|
22
31
|
|
|
@@ -27,6 +36,7 @@ interface Props {
|
|
|
27
36
|
mode?: 'simple' | 'full';
|
|
28
37
|
channelRenderMode?: 'flat' | 'single';
|
|
29
38
|
collection?: CollectionEntry<CollectionMessageTypes>[];
|
|
39
|
+
channels?: CollectionEntry<'channels'>[];
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
const getNodesAndEdges = async ({
|
|
@@ -36,6 +46,7 @@ const getNodesAndEdges = async ({
|
|
|
36
46
|
mode = 'simple',
|
|
37
47
|
channelRenderMode = 'flat',
|
|
38
48
|
collection = [],
|
|
49
|
+
channels = [],
|
|
39
50
|
}: Props) => {
|
|
40
51
|
const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
|
|
41
52
|
const nodes = [] as any,
|
|
@@ -53,14 +64,29 @@ const getNodesAndEdges = async ({
|
|
|
53
64
|
};
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
// We always render the message itself
|
|
68
|
+
nodes.push({
|
|
69
|
+
id: generateIdForNode(message),
|
|
70
|
+
sourcePosition: 'right',
|
|
71
|
+
targetPosition: 'left',
|
|
72
|
+
data: {
|
|
73
|
+
mode,
|
|
74
|
+
message: {
|
|
75
|
+
...message.data,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
position: { x: 0, y: 0 },
|
|
79
|
+
type: message.collection,
|
|
80
|
+
});
|
|
81
|
+
|
|
56
82
|
const producers = (message.data.producers as CollectionEntry<'services'>[]) || [];
|
|
57
83
|
const consumers = (message.data.consumers as CollectionEntry<'services'>[]) || [];
|
|
58
|
-
const channels = (message.data.messageChannels as CollectionEntry<'channels'>[]) || [];
|
|
59
84
|
|
|
60
85
|
// Track nodes that are both sent and received
|
|
61
86
|
const bothSentAndReceived = findMatchingNodes(producers, consumers);
|
|
62
87
|
|
|
63
|
-
|
|
88
|
+
for (const producer of producers) {
|
|
89
|
+
// Create the producer node
|
|
64
90
|
nodes.push({
|
|
65
91
|
id: generateIdForNode(producer),
|
|
66
92
|
type: producer?.collection,
|
|
@@ -70,58 +96,94 @@ const getNodesAndEdges = async ({
|
|
|
70
96
|
position: { x: 250, y: 0 },
|
|
71
97
|
});
|
|
72
98
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
nodes.push(...channelNodes);
|
|
87
|
-
edges.push(...channelEdges);
|
|
88
|
-
} else {
|
|
99
|
+
// Is the producer sending this message to a channel?
|
|
100
|
+
const producerConfigurationForMessage = producer.data.sends?.find((send) => send.id === message.data.id);
|
|
101
|
+
const producerChannelConfiguration = producerConfigurationForMessage?.to ?? [];
|
|
102
|
+
|
|
103
|
+
const producerHasChannels = producerChannelConfiguration?.length > 0;
|
|
104
|
+
|
|
105
|
+
const rootSourceAndTarget = {
|
|
106
|
+
source: { id: generateIdForNode(producer), collection: producer.collection },
|
|
107
|
+
target: { id: generateIdForNode(message), collection: message.collection },
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// If the producer does not have any channels defined, then we just connect the producer to the event directly
|
|
111
|
+
if (!producerHasChannels) {
|
|
89
112
|
edges.push({
|
|
90
113
|
id: generatedIdForEdge(producer, message),
|
|
91
114
|
source: generateIdForNode(producer),
|
|
92
115
|
target: generateIdForNode(message),
|
|
93
116
|
label: getEdgeLabelForServiceAsTarget(message),
|
|
94
|
-
data: { message },
|
|
117
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
95
118
|
animated: false,
|
|
96
119
|
markerEnd: {
|
|
97
120
|
type: MarkerType.ArrowClosed,
|
|
98
121
|
width: 40,
|
|
99
122
|
height: 40,
|
|
100
123
|
},
|
|
101
|
-
style: {
|
|
102
|
-
strokeWidth: 1,
|
|
103
|
-
},
|
|
104
124
|
});
|
|
125
|
+
continue;
|
|
105
126
|
}
|
|
106
|
-
});
|
|
107
127
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
// If the producer has channels defined, we need to render them
|
|
129
|
+
for (const producerChannel of producerChannelConfiguration) {
|
|
130
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
131
|
+
channels,
|
|
132
|
+
producerChannel.id,
|
|
133
|
+
producerChannel.version
|
|
134
|
+
)[0] as CollectionEntry<'channels'>;
|
|
135
|
+
|
|
136
|
+
// If we cannot find the channel in EventCatalog, we just connect the producer to the event directly
|
|
137
|
+
if (!channel) {
|
|
138
|
+
edges.push(
|
|
139
|
+
createEdge({
|
|
140
|
+
id: generatedIdForEdge(producer, message),
|
|
141
|
+
source: generateIdForNode(producer),
|
|
142
|
+
target: generateIdForNode(message),
|
|
143
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
144
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
145
|
+
})
|
|
146
|
+
);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// We render the channel node
|
|
151
|
+
nodes.push(
|
|
152
|
+
createNode({
|
|
153
|
+
id: generateIdForNode(channel),
|
|
154
|
+
type: channel.collection,
|
|
155
|
+
data: { mode, channel: { ...channel.data } },
|
|
156
|
+
position: { x: 0, y: 0 },
|
|
157
|
+
})
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Connect the producer to the message
|
|
161
|
+
edges.push(
|
|
162
|
+
createEdge({
|
|
163
|
+
id: generatedIdForEdge(producer, message),
|
|
164
|
+
source: generateIdForNode(producer),
|
|
165
|
+
target: generateIdForNode(message),
|
|
166
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
167
|
+
label: getEdgeLabelForServiceAsTarget(message),
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Connect the message to the channel
|
|
172
|
+
edges.push(
|
|
173
|
+
createEdge({
|
|
174
|
+
id: generatedIdForEdge(message, channel),
|
|
175
|
+
source: generateIdForNode(message),
|
|
176
|
+
target: generateIdForNode(channel),
|
|
177
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
178
|
+
label: 'routes to',
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
122
183
|
|
|
123
184
|
// The messages the service sends
|
|
124
|
-
|
|
185
|
+
for (const consumer of consumers) {
|
|
186
|
+
// Render the consumer node
|
|
125
187
|
nodes.push({
|
|
126
188
|
id: generateIdForNode(consumer),
|
|
127
189
|
sourcePosition: 'right',
|
|
@@ -131,32 +193,152 @@ const getNodesAndEdges = async ({
|
|
|
131
193
|
type: consumer?.collection,
|
|
132
194
|
});
|
|
133
195
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
channelsToRender: channels.map((channel) => ({ id: channel.data.id, version: channel.data.version })),
|
|
138
|
-
source: message,
|
|
139
|
-
target: consumer,
|
|
140
|
-
channelToTargetLabel: getEdgeLabelForMessageAsSource(message),
|
|
141
|
-
mode,
|
|
142
|
-
currentNodes: nodes,
|
|
143
|
-
channelRenderMode,
|
|
144
|
-
});
|
|
196
|
+
// Is the consumer receiving this message from a channel?
|
|
197
|
+
const consumerConfigurationForMessage = consumer.data.receives?.find((receive) => receive.id === message.data.id);
|
|
198
|
+
const consumerChannelConfiguration = consumerConfigurationForMessage?.from ?? [];
|
|
145
199
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
200
|
+
const consumerHasChannels = consumerChannelConfiguration.length > 0;
|
|
201
|
+
|
|
202
|
+
const rootSourceAndTarget = {
|
|
203
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
204
|
+
target: { id: generateIdForNode(consumer), collection: consumer.collection },
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// If the consumer does not have any channels defined, connect the consumer to the event directly
|
|
208
|
+
if (!consumerHasChannels) {
|
|
149
209
|
edges.push(
|
|
150
210
|
createEdge({
|
|
151
211
|
id: generatedIdForEdge(message, consumer),
|
|
152
212
|
source: generateIdForNode(message),
|
|
153
213
|
target: generateIdForNode(consumer),
|
|
154
214
|
label: getEdgeLabelForMessageAsSource(message),
|
|
155
|
-
data: { message },
|
|
215
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
156
216
|
})
|
|
157
217
|
);
|
|
158
218
|
}
|
|
159
|
-
|
|
219
|
+
|
|
220
|
+
// If the consumer has channels defined, we try and render them
|
|
221
|
+
for (const consumerChannel of consumerChannelConfiguration) {
|
|
222
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
223
|
+
channels,
|
|
224
|
+
consumerChannel.id,
|
|
225
|
+
consumerChannel.version
|
|
226
|
+
)[0] as CollectionEntry<'channels'>;
|
|
227
|
+
|
|
228
|
+
// If we cannot find the channel in EventCatalog, we connect the message directly to the consumer
|
|
229
|
+
if (!channel) {
|
|
230
|
+
edges.push(
|
|
231
|
+
createEdge({
|
|
232
|
+
id: generatedIdForEdge(message, consumer),
|
|
233
|
+
source: generateIdForNode(message),
|
|
234
|
+
target: generateIdForNode(consumer),
|
|
235
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
236
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Can any of the consumer channels be linked to any of the producer channels?
|
|
243
|
+
const producerChannels = producers
|
|
244
|
+
.map((producer) => producer.data.sends?.find((send) => send.id === message.data.id)?.to ?? [])
|
|
245
|
+
.flat();
|
|
246
|
+
const consumerChannels = consumer.data.receives?.find((receive) => receive.id === message.data.id)?.from ?? [];
|
|
247
|
+
|
|
248
|
+
for (const producerChannel of producerChannels) {
|
|
249
|
+
const producerChannelValue = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
250
|
+
channels,
|
|
251
|
+
producerChannel.id,
|
|
252
|
+
producerChannel.version
|
|
253
|
+
)[0] as CollectionEntry<'channels'>;
|
|
254
|
+
|
|
255
|
+
for (const consumerChannel of consumerChannels) {
|
|
256
|
+
const consumerChannelValue = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
257
|
+
channels,
|
|
258
|
+
consumerChannel.id,
|
|
259
|
+
consumerChannel.version
|
|
260
|
+
)[0] as CollectionEntry<'channels'>;
|
|
261
|
+
const channelChainToRender = getChannelChain(producerChannelValue, consumerChannelValue, channels);
|
|
262
|
+
|
|
263
|
+
// If there is a chain between them we need to render them al
|
|
264
|
+
if (channelChainToRender.length > 0) {
|
|
265
|
+
const { nodes: channelNodes, edges: channelEdges } = getNodesAndEdgesForChannelChain({
|
|
266
|
+
source: message,
|
|
267
|
+
target: consumer,
|
|
268
|
+
channelChain: channelChainToRender,
|
|
269
|
+
mode,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
nodes.push(...channelNodes);
|
|
273
|
+
edges.push(...channelEdges);
|
|
274
|
+
} else {
|
|
275
|
+
// There is no chain found, we need to render the channel between message and the consumers
|
|
276
|
+
nodes.push(
|
|
277
|
+
createNode({
|
|
278
|
+
id: generateIdForNode(channel),
|
|
279
|
+
type: channel.collection,
|
|
280
|
+
data: { mode, channel: { ...channel.data } },
|
|
281
|
+
position: { x: 0, y: 0 },
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
edges.push(
|
|
285
|
+
createEdge({
|
|
286
|
+
id: generatedIdForEdge(message, channel),
|
|
287
|
+
source: generateIdForNode(message),
|
|
288
|
+
target: generateIdForNode(channel),
|
|
289
|
+
label: 'routes to',
|
|
290
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
291
|
+
})
|
|
292
|
+
);
|
|
293
|
+
edges.push(
|
|
294
|
+
createEdge({
|
|
295
|
+
id: generatedIdForEdge(channel, consumer),
|
|
296
|
+
source: generateIdForNode(channel),
|
|
297
|
+
target: generateIdForNode(consumer),
|
|
298
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
299
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// If producer does not have a any channels defined, we need to connect the message to the consumer directly
|
|
307
|
+
if (producerChannels.length === 0 && channel) {
|
|
308
|
+
// Create the channel node
|
|
309
|
+
nodes.push(
|
|
310
|
+
createNode({
|
|
311
|
+
id: generateIdForNode(channel),
|
|
312
|
+
type: channel.collection,
|
|
313
|
+
data: { mode, channel: { ...channel.data } },
|
|
314
|
+
position: { x: 0, y: 0 },
|
|
315
|
+
})
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// Connect the message to the channel
|
|
319
|
+
edges.push(
|
|
320
|
+
createEdge({
|
|
321
|
+
id: generatedIdForEdge(message, channel),
|
|
322
|
+
source: generateIdForNode(message),
|
|
323
|
+
target: generateIdForNode(channel),
|
|
324
|
+
label: 'routes to',
|
|
325
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
326
|
+
})
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
// Connect the channel to the consumer
|
|
330
|
+
edges.push(
|
|
331
|
+
createEdge({
|
|
332
|
+
id: generatedIdForEdge(channel, consumer),
|
|
333
|
+
source: generateIdForNode(channel),
|
|
334
|
+
target: generateIdForNode(consumer),
|
|
335
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
336
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
337
|
+
})
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
160
342
|
|
|
161
343
|
// Handle messages that are both sent and received
|
|
162
344
|
bothSentAndReceived.forEach((_message) => {
|
|
@@ -167,7 +349,7 @@ const getNodesAndEdges = async ({
|
|
|
167
349
|
source: generateIdForNode(message),
|
|
168
350
|
target: generateIdForNode(_message),
|
|
169
351
|
label: 'publishes and subscribes',
|
|
170
|
-
data: { message },
|
|
352
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget: { source: message, target: _message } },
|
|
171
353
|
})
|
|
172
354
|
);
|
|
173
355
|
}
|
|
@@ -198,7 +380,8 @@ export const getNodesAndEdgesForQueries = async ({
|
|
|
198
380
|
channelRenderMode = 'flat',
|
|
199
381
|
}: Props) => {
|
|
200
382
|
const queries = await getQueries();
|
|
201
|
-
|
|
383
|
+
const channels = await getChannels();
|
|
384
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: queries, channels });
|
|
202
385
|
};
|
|
203
386
|
|
|
204
387
|
export const getNodesAndEdgesForCommands = async ({
|
|
@@ -209,7 +392,8 @@ export const getNodesAndEdgesForCommands = async ({
|
|
|
209
392
|
channelRenderMode = 'flat',
|
|
210
393
|
}: Props) => {
|
|
211
394
|
const commands = await getCommands();
|
|
212
|
-
|
|
395
|
+
const channels = await getChannels();
|
|
396
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: commands, channels });
|
|
213
397
|
};
|
|
214
398
|
|
|
215
399
|
export const getNodesAndEdgesForEvents = async ({
|
|
@@ -220,5 +404,616 @@ export const getNodesAndEdgesForEvents = async ({
|
|
|
220
404
|
channelRenderMode = 'flat',
|
|
221
405
|
}: Props) => {
|
|
222
406
|
const events = await getEvents();
|
|
223
|
-
|
|
407
|
+
const channels = await getChannels();
|
|
408
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, channelRenderMode, collection: events, channels });
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
export const getNodesAndEdgesForConsumedMessage = ({
|
|
412
|
+
message,
|
|
413
|
+
targetChannels = [],
|
|
414
|
+
services,
|
|
415
|
+
channels,
|
|
416
|
+
currentNodes = [],
|
|
417
|
+
target,
|
|
418
|
+
mode = 'simple',
|
|
419
|
+
}: {
|
|
420
|
+
message: CollectionEntry<CollectionMessageTypes>;
|
|
421
|
+
targetChannels?: { id: string; version: string }[];
|
|
422
|
+
services: CollectionEntry<'services'>[];
|
|
423
|
+
channels: CollectionEntry<'channels'>[];
|
|
424
|
+
currentNodes: Node[];
|
|
425
|
+
target: CollectionEntry<'services'>;
|
|
426
|
+
mode?: 'simple' | 'full';
|
|
427
|
+
}) => {
|
|
428
|
+
let nodes = [] as Node[],
|
|
429
|
+
edges = [] as any;
|
|
430
|
+
|
|
431
|
+
const messageId = generateIdForNode(message);
|
|
432
|
+
|
|
433
|
+
const rootSourceAndTarget = {
|
|
434
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
435
|
+
target: { id: generateIdForNode(target), collection: target.collection },
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// Render the message node
|
|
439
|
+
nodes.push(
|
|
440
|
+
createNode({
|
|
441
|
+
id: messageId,
|
|
442
|
+
type: message.collection,
|
|
443
|
+
data: { mode, message: { ...message.data } },
|
|
444
|
+
position: { x: 0, y: 0 },
|
|
445
|
+
})
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
// Render the target node
|
|
449
|
+
nodes.push(
|
|
450
|
+
createNode({
|
|
451
|
+
id: generateIdForNode(target),
|
|
452
|
+
type: target.collection,
|
|
453
|
+
data: { mode, service: { ...target.data } },
|
|
454
|
+
position: { x: 0, y: 0 },
|
|
455
|
+
})
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
const targetMessageConfiguration = target.data.receives?.find((receive) => receive.id === message.data.id);
|
|
459
|
+
const channelsFromMessageToTarget = targetMessageConfiguration?.from ?? [];
|
|
460
|
+
const hydratedChannelsFromMessageToTarget = channelsFromMessageToTarget
|
|
461
|
+
.map((channel) => getItemsFromCollectionByIdAndSemverOrLatest(channels, channel.id, channel.version)[0])
|
|
462
|
+
.filter((channel) => channel !== undefined);
|
|
463
|
+
|
|
464
|
+
// Now we get the producers of the message and create nodes and edges for them
|
|
465
|
+
const producers = getProducersOfMessage(services, message);
|
|
466
|
+
|
|
467
|
+
const hasProducers = producers.length > 0;
|
|
468
|
+
const targetHasDefinedChannels = targetChannels.length > 0;
|
|
469
|
+
|
|
470
|
+
const isMessageEvent = message.collection === 'events';
|
|
471
|
+
|
|
472
|
+
// Warning edge if no producers or target channels are defined
|
|
473
|
+
if (!hasProducers && !targetHasDefinedChannels) {
|
|
474
|
+
edges.push(
|
|
475
|
+
createEdge({
|
|
476
|
+
id: generatedIdForEdge(message, target) + '-warning',
|
|
477
|
+
source: messageId,
|
|
478
|
+
target: generateIdForNode(target),
|
|
479
|
+
label: isMessageEvent ? `⚠️ No producers found \n ${message.data.name}` : getEdgeLabelForMessageAsSource(message),
|
|
480
|
+
data: { customColor: getColorFromString(message.data.id), warning: isMessageEvent, rootSourceAndTarget },
|
|
481
|
+
})
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// If the target defined channels they consume the message from, we need to create the channel nodes and edges
|
|
486
|
+
if (targetHasDefinedChannels) {
|
|
487
|
+
for (const targetChannel of targetChannels) {
|
|
488
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
489
|
+
channels,
|
|
490
|
+
targetChannel.id,
|
|
491
|
+
targetChannel.version
|
|
492
|
+
)[0] as CollectionEntry<'channels'>;
|
|
493
|
+
|
|
494
|
+
if (!channel) {
|
|
495
|
+
// No channe found, we just connect the message to the target directly
|
|
496
|
+
edges.push(
|
|
497
|
+
createEdge({
|
|
498
|
+
id: generatedIdForEdge(message, target),
|
|
499
|
+
source: messageId,
|
|
500
|
+
target: generateIdForNode(target),
|
|
501
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
502
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
503
|
+
})
|
|
504
|
+
);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const channelId = generateIdForNode(channel);
|
|
509
|
+
|
|
510
|
+
// Create the channel node
|
|
511
|
+
nodes.push(
|
|
512
|
+
createNode({
|
|
513
|
+
id: channelId,
|
|
514
|
+
type: channel.collection,
|
|
515
|
+
data: { mode, channel: { ...channel.data, ...channel } },
|
|
516
|
+
position: { x: 0, y: 0 },
|
|
517
|
+
})
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
// Connect the channel to the target
|
|
521
|
+
edges.push(
|
|
522
|
+
createEdge({
|
|
523
|
+
id: generatedIdForEdge(channel, target),
|
|
524
|
+
source: channelId,
|
|
525
|
+
target: generateIdForNode(target),
|
|
526
|
+
label: `consumes \n ${message.data.name}`,
|
|
527
|
+
data: { customColor: getColorFromString(message.data.id), warning: producers.length === 0, rootSourceAndTarget },
|
|
528
|
+
})
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
// If we dont have any producers, we will connect the message to the channel directly
|
|
532
|
+
if (producers.length === 0) {
|
|
533
|
+
const isEvent = message.collection === 'events';
|
|
534
|
+
|
|
535
|
+
edges.push(
|
|
536
|
+
createEdge({
|
|
537
|
+
id: generatedIdForEdge(message, channel),
|
|
538
|
+
source: messageId,
|
|
539
|
+
target: channelId,
|
|
540
|
+
label: isEvent ? `⚠️ No producers found \n ${message.data.name}` : getEdgeLabelForMessageAsSource(message),
|
|
541
|
+
data: { customColor: getColorFromString(message.data.id), warning: isEvent, rootSourceAndTarget },
|
|
542
|
+
markerEnd: {
|
|
543
|
+
type: MarkerType.ArrowClosed,
|
|
544
|
+
width: 40,
|
|
545
|
+
height: 40,
|
|
546
|
+
color: 'red',
|
|
547
|
+
},
|
|
548
|
+
style: {
|
|
549
|
+
strokeWidth: 5,
|
|
550
|
+
stroke: 'red',
|
|
551
|
+
},
|
|
552
|
+
})
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Process the producers for the message
|
|
559
|
+
for (const producer of producers) {
|
|
560
|
+
const producerId = generateIdForNode(producer);
|
|
561
|
+
|
|
562
|
+
// Create the producer node
|
|
563
|
+
nodes.push(
|
|
564
|
+
createNode({
|
|
565
|
+
id: producerId,
|
|
566
|
+
type: producer.collection,
|
|
567
|
+
data: { mode, service: { ...producer.data } },
|
|
568
|
+
position: { x: 0, y: 0 },
|
|
569
|
+
})
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
// The message is always connected directly to the producer
|
|
573
|
+
edges.push(
|
|
574
|
+
createEdge({
|
|
575
|
+
id: generatedIdForEdge(producer, message),
|
|
576
|
+
source: producerId,
|
|
577
|
+
target: messageId,
|
|
578
|
+
label: getEdgeLabelForServiceAsTarget(message),
|
|
579
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
580
|
+
})
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
// Check if the producer is sending the message to a channel
|
|
584
|
+
const producerConfigurationForMessage = producer.data.sends?.find((send) => send.id === message.data.id);
|
|
585
|
+
const producerChannelConfiguration = producerConfigurationForMessage?.to ?? [];
|
|
586
|
+
|
|
587
|
+
const producerHasChannels = producerChannelConfiguration.length > 0;
|
|
588
|
+
const targetHasChannels = hydratedChannelsFromMessageToTarget.length > 0;
|
|
589
|
+
|
|
590
|
+
// If the producer or target (consumer) has no channels defined, we just connect the message to the consumer directly
|
|
591
|
+
// of the target has no channels defined, we just connect the message to the target directly
|
|
592
|
+
if ((!producerHasChannels && !targetHasChannels) || !targetHasChannels) {
|
|
593
|
+
edges.push(
|
|
594
|
+
createEdge({
|
|
595
|
+
id: generatedIdForEdge(message, target),
|
|
596
|
+
source: messageId,
|
|
597
|
+
target: generateIdForNode(target),
|
|
598
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
599
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
600
|
+
})
|
|
601
|
+
);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// If the target has channels but the producer does not
|
|
606
|
+
// We then connect the message to the channels directly
|
|
607
|
+
if (targetHasChannels && !producerHasChannels) {
|
|
608
|
+
for (const targetChannel of hydratedChannelsFromMessageToTarget) {
|
|
609
|
+
edges.push(
|
|
610
|
+
createEdge({
|
|
611
|
+
id: generatedIdForEdge(message, targetChannel),
|
|
612
|
+
source: messageId,
|
|
613
|
+
target: generateIdForNode(targetChannel),
|
|
614
|
+
label: 'routes to',
|
|
615
|
+
data: {
|
|
616
|
+
customColor: getColorFromString(message.data.id),
|
|
617
|
+
rootSourceAndTarget: {
|
|
618
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
619
|
+
target: { id: generateIdForNode(target), collection: target.collection },
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
})
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Process each producer channel configuration
|
|
629
|
+
for (const producerChannel of producerChannelConfiguration) {
|
|
630
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
631
|
+
channels,
|
|
632
|
+
producerChannel.id,
|
|
633
|
+
producerChannel.version
|
|
634
|
+
)[0] as CollectionEntry<'channels'>;
|
|
635
|
+
|
|
636
|
+
// If we cannot find the channel in EventCatalog, we just connect the message to the target directly
|
|
637
|
+
if (!channel) {
|
|
638
|
+
edges.push(
|
|
639
|
+
createEdge({
|
|
640
|
+
id: generatedIdForEdge(message, target),
|
|
641
|
+
source: messageId,
|
|
642
|
+
target: generateIdForNode(target),
|
|
643
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
644
|
+
data: {
|
|
645
|
+
customColor: getColorFromString(message.data.id),
|
|
646
|
+
rootSourceAndTarget: {
|
|
647
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
648
|
+
target: { id: generateIdForNode(target), collection: target.collection },
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
})
|
|
652
|
+
);
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Does the producer have any channels defined? If not, we just connect the message to the target directly
|
|
657
|
+
if (!producerHasChannels) {
|
|
658
|
+
edges.push(
|
|
659
|
+
createEdge({
|
|
660
|
+
id: generatedIdForEdge(message, target),
|
|
661
|
+
source: messageId,
|
|
662
|
+
target: generateIdForNode(target),
|
|
663
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
664
|
+
data: {
|
|
665
|
+
customColor: getColorFromString(message.data.id),
|
|
666
|
+
rootSourceAndTarget: {
|
|
667
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
668
|
+
target: { id: generateIdForNode(target), collection: target.collection },
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
continue;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// The producer does have channels defined, we need to try and work out the path the message takes to the target
|
|
677
|
+
for (const targetChannel of hydratedChannelsFromMessageToTarget) {
|
|
678
|
+
const channelChainToRender = getChannelChain(channel, targetChannel, channels);
|
|
679
|
+
if (channelChainToRender.length > 0) {
|
|
680
|
+
const { nodes: channelNodes, edges: channelEdges } = getNodesAndEdgesForChannelChain({
|
|
681
|
+
source: message,
|
|
682
|
+
target: target,
|
|
683
|
+
channelChain: channelChainToRender,
|
|
684
|
+
mode,
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
nodes.push(...channelNodes);
|
|
688
|
+
edges.push(...channelEdges);
|
|
689
|
+
|
|
690
|
+
break;
|
|
691
|
+
} else {
|
|
692
|
+
// No chain found create the channel, and connect the message to the target channel directly
|
|
693
|
+
nodes.push(
|
|
694
|
+
createNode({
|
|
695
|
+
id: generateIdForNode(targetChannel),
|
|
696
|
+
type: targetChannel.collection,
|
|
697
|
+
data: { mode, channel: { ...targetChannel.data, ...targetChannel } },
|
|
698
|
+
position: { x: 0, y: 0 },
|
|
699
|
+
})
|
|
700
|
+
);
|
|
701
|
+
edges.push(
|
|
702
|
+
createEdge({
|
|
703
|
+
id: generatedIdForEdge(message, targetChannel),
|
|
704
|
+
source: messageId,
|
|
705
|
+
target: generateIdForNode(targetChannel),
|
|
706
|
+
label: 'routes to',
|
|
707
|
+
data: {
|
|
708
|
+
rootSourceAndTarget: {
|
|
709
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
710
|
+
target: { id: generateIdForNode(targetChannel), collection: targetChannel.collection },
|
|
711
|
+
},
|
|
712
|
+
},
|
|
713
|
+
})
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Remove any nodes that are already in the current nodes (already on the UI)
|
|
721
|
+
nodes = nodes.filter((node) => !currentNodes.find((n) => n.id === node.id));
|
|
722
|
+
|
|
723
|
+
// Make sure all nodes are unique
|
|
724
|
+
const uniqueNodes = nodes.filter((node, index, self) => index === self.findIndex((t) => t.id === node.id));
|
|
725
|
+
|
|
726
|
+
const uniqueEdges = edges.filter(
|
|
727
|
+
(edge: any, index: number, self: any[]) => index === self.findIndex((t: any) => t.id === edge.id)
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
return { nodes: uniqueNodes, edges: uniqueEdges };
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
export const getNodesAndEdgesForProducedMessage = ({
|
|
734
|
+
message,
|
|
735
|
+
sourceChannels,
|
|
736
|
+
services,
|
|
737
|
+
channels,
|
|
738
|
+
currentNodes = [],
|
|
739
|
+
currentEdges = [],
|
|
740
|
+
source,
|
|
741
|
+
mode = 'simple',
|
|
742
|
+
}: {
|
|
743
|
+
message: CollectionEntry<CollectionMessageTypes>;
|
|
744
|
+
sourceChannels?: { id: string; version: string }[];
|
|
745
|
+
services: CollectionEntry<'services'>[];
|
|
746
|
+
channels: CollectionEntry<'channels'>[];
|
|
747
|
+
currentNodes: Node[];
|
|
748
|
+
currentEdges: Edge[];
|
|
749
|
+
source: CollectionEntry<'services'>;
|
|
750
|
+
mode?: 'simple' | 'full';
|
|
751
|
+
}) => {
|
|
752
|
+
let nodes = [] as Node[],
|
|
753
|
+
edges = [] as any;
|
|
754
|
+
|
|
755
|
+
const messageId = generateIdForNode(message);
|
|
756
|
+
|
|
757
|
+
const rootSourceAndTarget = {
|
|
758
|
+
source: { id: generateIdForNode(source), collection: source.collection },
|
|
759
|
+
target: { id: generateIdForNode(message), collection: message.collection },
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
// Render the message node
|
|
763
|
+
nodes.push(
|
|
764
|
+
createNode({
|
|
765
|
+
id: messageId,
|
|
766
|
+
type: message.collection,
|
|
767
|
+
data: { mode, message: { ...message.data } },
|
|
768
|
+
position: { x: 0, y: 0 },
|
|
769
|
+
})
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
// Render the producer node
|
|
773
|
+
nodes.push(
|
|
774
|
+
createNode({
|
|
775
|
+
id: generateIdForNode(source),
|
|
776
|
+
type: source.collection,
|
|
777
|
+
data: { mode, service: { ...source.data } },
|
|
778
|
+
position: { x: 0, y: 0 },
|
|
779
|
+
})
|
|
780
|
+
);
|
|
781
|
+
|
|
782
|
+
// Render the edge from the producer to the message
|
|
783
|
+
edges.push(
|
|
784
|
+
createEdge({
|
|
785
|
+
id: generatedIdForEdge(source, message),
|
|
786
|
+
source: generateIdForNode(source),
|
|
787
|
+
target: messageId,
|
|
788
|
+
label: getEdgeLabelForServiceAsTarget(message),
|
|
789
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
790
|
+
})
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
const sourceMessageConfiguration = source.data.sends?.find((send) => send.id === message.data.id);
|
|
794
|
+
const channelsFromSourceToMessage = sourceMessageConfiguration?.to ?? [];
|
|
795
|
+
|
|
796
|
+
const hydratedChannelsFromSourceToMessage = channelsFromSourceToMessage
|
|
797
|
+
.map((channel) => getItemsFromCollectionByIdAndSemverOrLatest(channels, channel.id, channel.version)[0])
|
|
798
|
+
.filter((channel) => channel !== undefined);
|
|
799
|
+
|
|
800
|
+
// If the source defined channels they send the message to, we need to create the channel nodes and edges
|
|
801
|
+
if (sourceChannels && sourceChannels.length > 0) {
|
|
802
|
+
for (const sourceChannel of sourceChannels) {
|
|
803
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
804
|
+
channels,
|
|
805
|
+
sourceChannel.id,
|
|
806
|
+
sourceChannel.version
|
|
807
|
+
)[0] as CollectionEntry<'channels'>;
|
|
808
|
+
|
|
809
|
+
if (!channel) {
|
|
810
|
+
// No channel found, we just connect the message to the source directly
|
|
811
|
+
edges.push(
|
|
812
|
+
createEdge({
|
|
813
|
+
id: generatedIdForEdge(message, source),
|
|
814
|
+
source: messageId,
|
|
815
|
+
target: generateIdForNode(source),
|
|
816
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
817
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
818
|
+
})
|
|
819
|
+
);
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const channelId = generateIdForNode(channel);
|
|
824
|
+
|
|
825
|
+
// Create the channel node
|
|
826
|
+
nodes.push(
|
|
827
|
+
createNode({
|
|
828
|
+
id: channelId,
|
|
829
|
+
type: channel.collection,
|
|
830
|
+
data: { mode, channel: { ...channel.data, ...channel, mode } },
|
|
831
|
+
position: { x: 0, y: 0 },
|
|
832
|
+
})
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
// Connect the produced message to the channel
|
|
836
|
+
edges.push(
|
|
837
|
+
createEdge({
|
|
838
|
+
id: generatedIdForEdge(message, channel),
|
|
839
|
+
source: messageId,
|
|
840
|
+
target: channelId,
|
|
841
|
+
label: 'routes to',
|
|
842
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
843
|
+
})
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// Now we get the producers of the message and create nodes and edges for them
|
|
849
|
+
const consumers = getConsumersOfMessage(services, message);
|
|
850
|
+
|
|
851
|
+
// TODO: Make this a UI Switch in the future....
|
|
852
|
+
const latestConsumers = consumers.filter(
|
|
853
|
+
(consumer) => getLatestVersionInCollectionById(services, consumer.data.id) === consumer.data.version
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
// Process the consumers for the message
|
|
857
|
+
for (const consumer of latestConsumers) {
|
|
858
|
+
const consumerId = generateIdForNode(consumer);
|
|
859
|
+
|
|
860
|
+
// Create the consumer node
|
|
861
|
+
nodes.push(
|
|
862
|
+
createNode({
|
|
863
|
+
id: consumerId,
|
|
864
|
+
type: consumer.collection,
|
|
865
|
+
data: { mode, service: { ...consumer.data } },
|
|
866
|
+
position: { x: 0, y: 0 },
|
|
867
|
+
})
|
|
868
|
+
);
|
|
869
|
+
|
|
870
|
+
// Check if the consumer is consuming the message from a channel
|
|
871
|
+
const consumerConfigurationForMessage = consumer.data.receives?.find((receive) => receive.id === message.data.id);
|
|
872
|
+
const consumerChannelConfiguration = consumerConfigurationForMessage?.from ?? [];
|
|
873
|
+
|
|
874
|
+
const consumerHasChannels = consumerChannelConfiguration.length > 0;
|
|
875
|
+
const producerHasChannels = hydratedChannelsFromSourceToMessage.length > 0;
|
|
876
|
+
|
|
877
|
+
// If the consumer and producer have no channels defined,
|
|
878
|
+
// or the consumer has no channels defined, we just connect the message to the consumer directly
|
|
879
|
+
if ((!consumerHasChannels && !producerHasChannels) || !consumerHasChannels) {
|
|
880
|
+
edges.push(
|
|
881
|
+
createEdge({
|
|
882
|
+
id: generatedIdForEdge(message, consumer),
|
|
883
|
+
source: messageId,
|
|
884
|
+
target: consumerId,
|
|
885
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
886
|
+
data: { customColor: getColorFromString(message.data.id), rootSourceAndTarget },
|
|
887
|
+
})
|
|
888
|
+
);
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Process each consumer channel configuration
|
|
893
|
+
for (const consumerChannel of consumerChannelConfiguration) {
|
|
894
|
+
const channel = getItemsFromCollectionByIdAndSemverOrLatest(
|
|
895
|
+
channels,
|
|
896
|
+
consumerChannel.id,
|
|
897
|
+
consumerChannel.version
|
|
898
|
+
)[0] as CollectionEntry<'channels'>;
|
|
899
|
+
|
|
900
|
+
const edgeProps = { customColor: getColorFromString(message.data.id), rootSourceAndTarget };
|
|
901
|
+
|
|
902
|
+
// If the channel cannot be found in EventCatalog, we just connect the message to the consumer directly
|
|
903
|
+
// as a fallback, rather than just an empty node floating around
|
|
904
|
+
if (!channel) {
|
|
905
|
+
edges.push(
|
|
906
|
+
createEdge({
|
|
907
|
+
id: generatedIdForEdge(message, consumer),
|
|
908
|
+
source: messageId,
|
|
909
|
+
target: consumerId,
|
|
910
|
+
label: 'consumes',
|
|
911
|
+
data: edgeProps,
|
|
912
|
+
})
|
|
913
|
+
);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// We always add the consumer channel to be rendered
|
|
918
|
+
nodes.push(
|
|
919
|
+
createNode({
|
|
920
|
+
id: generateIdForNode(channel),
|
|
921
|
+
type: channel.collection,
|
|
922
|
+
data: { mode, channel: { ...channel.data, ...channel } },
|
|
923
|
+
position: { x: 0, y: 0 },
|
|
924
|
+
})
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
// If the producer does not have any channels defined, we connect the message to the consumers channel directly
|
|
928
|
+
if (!producerHasChannels) {
|
|
929
|
+
edges.push(
|
|
930
|
+
createEdge({
|
|
931
|
+
id: generatedIdForEdge(message, channel),
|
|
932
|
+
source: messageId,
|
|
933
|
+
target: generateIdForNode(channel),
|
|
934
|
+
label: 'routes to',
|
|
935
|
+
data: edgeProps,
|
|
936
|
+
})
|
|
937
|
+
);
|
|
938
|
+
edges.push(
|
|
939
|
+
createEdge({
|
|
940
|
+
id: generatedIdForEdge(channel, consumer),
|
|
941
|
+
source: generateIdForNode(channel),
|
|
942
|
+
target: generateIdForNode(consumer),
|
|
943
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
944
|
+
data: {
|
|
945
|
+
...edgeProps,
|
|
946
|
+
rootSourceAndTarget: {
|
|
947
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
948
|
+
target: { id: generateIdForNode(consumer), collection: consumer.collection },
|
|
949
|
+
},
|
|
950
|
+
},
|
|
951
|
+
})
|
|
952
|
+
);
|
|
953
|
+
continue;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// The producer has channels defined, we need to try and work out the path the message takes to the consumer
|
|
957
|
+
for (const sourceChannel of hydratedChannelsFromSourceToMessage) {
|
|
958
|
+
const channelChainToRender = getChannelChain(sourceChannel, channel, channels);
|
|
959
|
+
|
|
960
|
+
if (channelChainToRender.length > 0) {
|
|
961
|
+
const { nodes: channelNodes, edges: channelEdges } = getNodesAndEdgesForChannelChain({
|
|
962
|
+
source: message,
|
|
963
|
+
target: consumer,
|
|
964
|
+
channelChain: channelChainToRender,
|
|
965
|
+
mode,
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
nodes.push(...channelNodes);
|
|
969
|
+
edges.push(...channelEdges);
|
|
970
|
+
} else {
|
|
971
|
+
// No chain found, we need to connect to the message to the channel
|
|
972
|
+
// And the channel to the consumer
|
|
973
|
+
edges.push(
|
|
974
|
+
createEdge({
|
|
975
|
+
id: generatedIdForEdge(message, channel),
|
|
976
|
+
source: messageId,
|
|
977
|
+
target: generateIdForNode(channel),
|
|
978
|
+
label: 'routes to',
|
|
979
|
+
data: {
|
|
980
|
+
...edgeProps,
|
|
981
|
+
rootSourceAndTarget: {
|
|
982
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
983
|
+
target: { id: generateIdForNode(consumer), collection: consumer.collection },
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
})
|
|
987
|
+
);
|
|
988
|
+
edges.push(
|
|
989
|
+
createEdge({
|
|
990
|
+
id: generatedIdForEdge(channel, consumer),
|
|
991
|
+
source: generateIdForNode(channel),
|
|
992
|
+
target: generateIdForNode(consumer),
|
|
993
|
+
label: `${getEdgeLabelForMessageAsSource(message, true)} \n ${message.data.name}`,
|
|
994
|
+
data: {
|
|
995
|
+
...edgeProps,
|
|
996
|
+
rootSourceAndTarget: {
|
|
997
|
+
source: { id: generateIdForNode(message), collection: message.collection },
|
|
998
|
+
target: { id: generateIdForNode(consumer), collection: consumer.collection },
|
|
999
|
+
},
|
|
1000
|
+
},
|
|
1001
|
+
})
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// Remove any nodes that are already in the current nodes (already on the UI)
|
|
1009
|
+
nodes = nodes.filter((node) => !currentNodes.find((n) => n.id === node.id));
|
|
1010
|
+
|
|
1011
|
+
// Make sure all nodes are unique
|
|
1012
|
+
const uniqueNodes = nodes.filter((node, index, self) => index === self.findIndex((t) => t.id === node.id));
|
|
1013
|
+
|
|
1014
|
+
const uniqueEdges = edges.filter(
|
|
1015
|
+
(edge: any, index: number, self: any[]) => index === self.findIndex((t: any) => t.id === edge.id)
|
|
1016
|
+
);
|
|
1017
|
+
|
|
1018
|
+
return { nodes: uniqueNodes, edges: uniqueEdges };
|
|
224
1019
|
};
|