@eventcatalog/core 4.6.2 → 4.7.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-352FGP6W.js +123 -0
- package/dist/{chunk-LQLAEEOV.js → chunk-3HMY77MN.js} +1 -1
- package/dist/chunk-5EPNFDT5.js +133 -0
- package/dist/{chunk-AT3AQ3PK.js → chunk-CZ6C3FBV.js} +1 -1
- package/dist/{chunk-U6E25IFA.js → chunk-HRSTURLY.js} +1 -1
- package/dist/chunk-R7Z5ALYI.js +44 -0
- package/dist/{chunk-MDCIQJRX.js → chunk-WJVRBHVC.js} +1 -1
- package/dist/chunk-ZR6AH5Z2.js +204 -0
- package/dist/{chunk-LZDDSWXC.js → chunk-ZU5WMIH4.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +651 -51
- package/dist/eventcatalog.config.d.cts +18 -1
- package/dist/eventcatalog.config.d.ts +18 -1
- package/dist/eventcatalog.js +133 -6
- package/dist/federation/content-cache.cjs +78 -0
- package/dist/federation/content-cache.d.cts +9 -0
- package/dist/federation/content-cache.d.ts +9 -0
- package/dist/federation/content-cache.js +6 -0
- package/dist/federation/federate.cjs +588 -0
- package/dist/federation/federate.d.cts +81 -0
- package/dist/federation/federate.d.ts +81 -0
- package/dist/federation/federate.js +12 -0
- package/dist/federation/github-source-provider.cjs +157 -0
- package/dist/federation/github-source-provider.d.cts +24 -0
- package/dist/federation/github-source-provider.d.ts +24 -0
- package/dist/federation/github-source-provider.js +6 -0
- package/dist/federation/public-assets.cjs +167 -0
- package/dist/federation/public-assets.d.cts +24 -0
- package/dist/federation/public-assets.d.ts +24 -0
- package/dist/federation/public-assets.js +6 -0
- package/dist/federation/types.cjs +18 -0
- package/dist/federation/types.d.cts +19 -0
- package/dist/federation/types.d.ts +19 -0
- package/dist/federation/types.js +0 -0
- 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/NodeGraph.astro +2 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +8 -85
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.spec.ts +19 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +80 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +14 -1
- package/eventcatalog/src/utils/node-graphs/channel-node-graph.ts +395 -3
- package/package.json +4 -4
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import
|
|
1
|
+
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
2
|
+
import dagre from 'dagre';
|
|
3
|
+
import {
|
|
4
|
+
buildContextMenuForAgent,
|
|
5
|
+
buildContextMenuForMessage,
|
|
6
|
+
buildContextMenuForResource,
|
|
7
|
+
buildContextMenuForService,
|
|
8
|
+
calculatedNodes,
|
|
9
|
+
createDagreGraph,
|
|
10
|
+
createEdge,
|
|
11
|
+
createNode,
|
|
12
|
+
generatedIdForEdge,
|
|
13
|
+
generateIdForNode,
|
|
14
|
+
getColorFromString,
|
|
15
|
+
getEdgeLabelForMessageAsSource,
|
|
16
|
+
getEdgeLabelForServiceAsTarget,
|
|
17
|
+
getOperationFields,
|
|
18
|
+
DEFAULT_NODE_WIDTH,
|
|
19
|
+
DEFAULT_NODE_HEIGHT,
|
|
20
|
+
} from './utils/utils';
|
|
21
|
+
import { createVersionedMap, findInMap } from '@utils/collections/util';
|
|
22
|
+
import { getChannelChain, getChannels } from '@utils/collections/channels';
|
|
3
23
|
import { type Node, type Edge } from '@xyflow/react';
|
|
24
|
+
import type { CollectionMessageTypes } from '@types';
|
|
4
25
|
|
|
5
26
|
interface CollectionItem {
|
|
6
27
|
collection: string;
|
|
@@ -27,7 +48,15 @@ export const getNodesAndEdgesForChannelChain = ({
|
|
|
27
48
|
createNode({
|
|
28
49
|
id: generateIdForNode(channel),
|
|
29
50
|
type: channel.collection,
|
|
30
|
-
data: {
|
|
51
|
+
data: {
|
|
52
|
+
mode,
|
|
53
|
+
channel: { ...channel.data, ...channel },
|
|
54
|
+
contextMenu: buildContextMenuForResource({
|
|
55
|
+
collection: 'channels',
|
|
56
|
+
id: channel.data.id,
|
|
57
|
+
version: channel.data.version,
|
|
58
|
+
}),
|
|
59
|
+
},
|
|
31
60
|
position: { x: 0, y: 0 },
|
|
32
61
|
})
|
|
33
62
|
);
|
|
@@ -73,3 +102,366 @@ export const getNodesAndEdgesForChannelChain = ({
|
|
|
73
102
|
|
|
74
103
|
return { nodes, edges };
|
|
75
104
|
};
|
|
105
|
+
|
|
106
|
+
type MessageProducerOrConsumer = CollectionEntry<'services'> | CollectionEntry<'agents'>;
|
|
107
|
+
type ChannelPointer = { id: string; version?: string };
|
|
108
|
+
type ChannelRoute = CollectionEntry<'channels'>[];
|
|
109
|
+
type RoutedResource = {
|
|
110
|
+
resource: MessageProducerOrConsumer;
|
|
111
|
+
channelRoutes: ChannelRoute[];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
type DagreGraph = any;
|
|
115
|
+
|
|
116
|
+
interface Props {
|
|
117
|
+
id: string;
|
|
118
|
+
version: string;
|
|
119
|
+
defaultFlow?: DagreGraph;
|
|
120
|
+
mode?: 'simple' | 'full';
|
|
121
|
+
layout?: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Builds the graph for a single channel: everything that publishes into it on the left,
|
|
126
|
+
* everything that consumes out of it on the right, and any channels it routes to (or is
|
|
127
|
+
* routed from) either side of it.
|
|
128
|
+
*/
|
|
129
|
+
export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simple', layout = true }: Props) => {
|
|
130
|
+
const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
|
|
131
|
+
const nodes: any[] = [];
|
|
132
|
+
const edges: any[] = [];
|
|
133
|
+
|
|
134
|
+
const [channels, services, agents, events, commands, queries] = await Promise.all([
|
|
135
|
+
getChannels(),
|
|
136
|
+
getCollection('services'),
|
|
137
|
+
getCollection('agents'),
|
|
138
|
+
getCollection('events'),
|
|
139
|
+
getCollection('commands'),
|
|
140
|
+
getCollection('queries'),
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
const channel = channels.find((c) => c.data.id === id && c.data.version === version);
|
|
144
|
+
|
|
145
|
+
// Nothing found...
|
|
146
|
+
if (!channel) {
|
|
147
|
+
return { nodes: [], edges: [] };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const allMessages = [...events, ...commands, ...queries] as CollectionEntry<CollectionMessageTypes>[];
|
|
151
|
+
const messageMap = createVersionedMap(allMessages);
|
|
152
|
+
const channelMap = createVersionedMap(channels);
|
|
153
|
+
|
|
154
|
+
const getRoutesThroughFocusedChannel = (
|
|
155
|
+
pointers: ChannelPointer[] | undefined,
|
|
156
|
+
direction: 'producers' | 'consumers'
|
|
157
|
+
): ChannelRoute[] =>
|
|
158
|
+
(pointers ?? []).flatMap((pointer) => {
|
|
159
|
+
const resolved = findInMap(channelMap, pointer.id, pointer.version) as CollectionEntry<'channels'> | undefined;
|
|
160
|
+
if (!resolved) return [];
|
|
161
|
+
|
|
162
|
+
const route =
|
|
163
|
+
direction === 'producers' ? getChannelChain(resolved, channel, channels) : getChannelChain(channel, resolved, channels);
|
|
164
|
+
|
|
165
|
+
return route.length > 0 ? [route] : [];
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const routesDirectlyToFocusedChannel = (pointers: ChannelPointer[] | undefined) =>
|
|
169
|
+
(pointers ?? []).some((pointer) => {
|
|
170
|
+
const resolved = findInMap(channelMap, pointer.id, pointer.version) as CollectionEntry<'channels'> | undefined;
|
|
171
|
+
return !!resolved && generateIdForNode(resolved) === generateIdForNode(channel);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// messageNodeId -> { message, producers, consumers }
|
|
175
|
+
const messageFlows = new Map<
|
|
176
|
+
string,
|
|
177
|
+
{
|
|
178
|
+
message: CollectionEntry<CollectionMessageTypes>;
|
|
179
|
+
producers: RoutedResource[];
|
|
180
|
+
consumers: RoutedResource[];
|
|
181
|
+
}
|
|
182
|
+
>();
|
|
183
|
+
|
|
184
|
+
const trackFlow = (
|
|
185
|
+
message: CollectionEntry<CollectionMessageTypes>,
|
|
186
|
+
resource: MessageProducerOrConsumer,
|
|
187
|
+
direction: 'producers' | 'consumers',
|
|
188
|
+
channelRoutes: ChannelRoute[]
|
|
189
|
+
) => {
|
|
190
|
+
const messageNodeId = generateIdForNode(message);
|
|
191
|
+
const flowForMessage = messageFlows.get(messageNodeId) ?? { message, producers: [], consumers: [] };
|
|
192
|
+
const alreadyTracked = flowForMessage[direction].some(
|
|
193
|
+
(existing) => existing.resource.data.id === resource.data.id && existing.resource.data.version === resource.data.version
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (!alreadyTracked) {
|
|
197
|
+
flowForMessage[direction].push({ resource, channelRoutes });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
messageFlows.set(messageNodeId, flowForMessage);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
for (const resource of [...services, ...agents] as MessageProducerOrConsumer[]) {
|
|
204
|
+
const pointerGroups = [
|
|
205
|
+
{ pointers: resource.data.sends ?? [], channelKey: 'to' as const, direction: 'producers' as const },
|
|
206
|
+
{ pointers: resource.data.receives ?? [], channelKey: 'from' as const, direction: 'consumers' as const },
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
for (const { pointers, channelKey, direction } of pointerGroups) {
|
|
210
|
+
for (const pointer of pointers as any[]) {
|
|
211
|
+
const message = findInMap(messageMap, pointer.id, pointer.version) as CollectionEntry<CollectionMessageTypes> | undefined;
|
|
212
|
+
|
|
213
|
+
if (!message) continue;
|
|
214
|
+
|
|
215
|
+
const channelPointers = pointer[channelKey] as ChannelPointer[] | undefined;
|
|
216
|
+
const hasExplicitChannels = Array.isArray(channelPointers) && channelPointers.length > 0;
|
|
217
|
+
const effectiveChannelPointers = hasExplicitChannels
|
|
218
|
+
? channelPointers
|
|
219
|
+
: (message.data.channels as ChannelPointer[] | undefined);
|
|
220
|
+
const channelRoutes = getRoutesThroughFocusedChannel(effectiveChannelPointers, direction);
|
|
221
|
+
|
|
222
|
+
if (channelRoutes.length > 0) {
|
|
223
|
+
trackFlow(message, resource, direction, channelRoutes);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Messages whose declared channel routes into the focused channel still belong on the graph,
|
|
230
|
+
// even when no producer or consumer references them.
|
|
231
|
+
for (const message of allMessages) {
|
|
232
|
+
const messageNodeId = generateIdForNode(message);
|
|
233
|
+
const declaredRoutes = getRoutesThroughFocusedChannel(message.data.channels as ChannelPointer[] | undefined, 'producers');
|
|
234
|
+
if (declaredRoutes.length > 0 && !messageFlows.has(messageNodeId)) {
|
|
235
|
+
messageFlows.set(messageNodeId, { message, producers: [], consumers: [] });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const channelNodeId = generateIdForNode(channel);
|
|
240
|
+
const addedNodeIds = new Set<string>();
|
|
241
|
+
const addedEdgeIds = new Set<string>();
|
|
242
|
+
|
|
243
|
+
const addNode = (node: any) => {
|
|
244
|
+
if (addedNodeIds.has(node.id)) return;
|
|
245
|
+
addedNodeIds.add(node.id);
|
|
246
|
+
nodes.push(node);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const addEdge = (edge: any) => {
|
|
250
|
+
if (addedEdgeIds.has(edge.id)) return;
|
|
251
|
+
addedEdgeIds.add(edge.id);
|
|
252
|
+
edges.push(edge);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const addResourceNode = (resource: MessageProducerOrConsumer) => {
|
|
256
|
+
addNode(
|
|
257
|
+
createNode({
|
|
258
|
+
id: generateIdForNode(resource),
|
|
259
|
+
type: resource.collection,
|
|
260
|
+
data: {
|
|
261
|
+
mode,
|
|
262
|
+
...(resource.collection === 'agents' ? { agent: { ...resource.data } } : { service: { ...resource.data } }),
|
|
263
|
+
contextMenu:
|
|
264
|
+
resource.collection === 'agents'
|
|
265
|
+
? buildContextMenuForAgent({ id: resource.data.id, version: resource.data.version })
|
|
266
|
+
: buildContextMenuForService({
|
|
267
|
+
id: resource.data.id,
|
|
268
|
+
version: resource.data.version,
|
|
269
|
+
specifications: (resource.data as any).specifications,
|
|
270
|
+
repository: (resource.data as any).repository,
|
|
271
|
+
}),
|
|
272
|
+
},
|
|
273
|
+
position: { x: 0, y: 0 },
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const addChannelNode = (channelToAdd: CollectionEntry<'channels'>, isFocused = false) => {
|
|
279
|
+
addNode(
|
|
280
|
+
createNode({
|
|
281
|
+
id: generateIdForNode(channelToAdd),
|
|
282
|
+
type: channelToAdd.collection,
|
|
283
|
+
data: {
|
|
284
|
+
mode,
|
|
285
|
+
...(isFocused ? { isFocused: true } : {}),
|
|
286
|
+
channel: { ...channelToAdd.data },
|
|
287
|
+
contextMenu: buildContextMenuForResource({
|
|
288
|
+
collection: 'channels',
|
|
289
|
+
id: channelToAdd.data.id,
|
|
290
|
+
version: channelToAdd.data.version,
|
|
291
|
+
}),
|
|
292
|
+
},
|
|
293
|
+
position: { x: 0, y: 0 },
|
|
294
|
+
})
|
|
295
|
+
);
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// The channel itself
|
|
299
|
+
addChannelNode(channel, true);
|
|
300
|
+
|
|
301
|
+
const addChannelRoute = (route: ChannelRoute, colorSourceId: string) => {
|
|
302
|
+
route.forEach((channelInRoute) => addChannelNode(channelInRoute, generateIdForNode(channelInRoute) === channelNodeId));
|
|
303
|
+
|
|
304
|
+
for (let index = 0; index < route.length - 1; index++) {
|
|
305
|
+
const sourceChannel = route[index];
|
|
306
|
+
const targetChannel = route[index + 1];
|
|
307
|
+
addEdge(
|
|
308
|
+
createEdge({
|
|
309
|
+
id: generatedIdForEdge(sourceChannel, targetChannel),
|
|
310
|
+
source: generateIdForNode(sourceChannel),
|
|
311
|
+
target: generateIdForNode(targetChannel),
|
|
312
|
+
label: 'routes to',
|
|
313
|
+
data: { customColor: getColorFromString(colorSourceId) },
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// channelNodeId + consumerNodeId -> messages consumed, so each channel/consumer pair gets one edge.
|
|
320
|
+
const messagesByConsumer = new Map<
|
|
321
|
+
string,
|
|
322
|
+
{
|
|
323
|
+
sourceChannel: CollectionEntry<'channels'>;
|
|
324
|
+
consumer: MessageProducerOrConsumer;
|
|
325
|
+
messages: CollectionEntry<CollectionMessageTypes>[];
|
|
326
|
+
}
|
|
327
|
+
>();
|
|
328
|
+
|
|
329
|
+
for (const { message, producers, consumers } of messageFlows.values()) {
|
|
330
|
+
const messageNodeId = generateIdForNode(message);
|
|
331
|
+
|
|
332
|
+
addNode(
|
|
333
|
+
createNode({
|
|
334
|
+
id: messageNodeId,
|
|
335
|
+
type: message.collection,
|
|
336
|
+
data: {
|
|
337
|
+
mode,
|
|
338
|
+
message: { ...message.data, ...getOperationFields(message.data) },
|
|
339
|
+
contextMenu: buildContextMenuForMessage({
|
|
340
|
+
id: message.data.id,
|
|
341
|
+
version: message.data.version,
|
|
342
|
+
name: message.data.name,
|
|
343
|
+
collection: message.collection,
|
|
344
|
+
schemaPath: (message.data as any).schemaPath,
|
|
345
|
+
}),
|
|
346
|
+
},
|
|
347
|
+
position: { x: 0, y: 0 },
|
|
348
|
+
})
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
const producerRoutes = producers.flatMap((producer) => producer.channelRoutes);
|
|
352
|
+
const declaredRoutes = getRoutesThroughFocusedChannel(message.data.channels as ChannelPointer[] | undefined, 'producers');
|
|
353
|
+
const ingressRoutes = producerRoutes.length > 0 ? producerRoutes : declaredRoutes;
|
|
354
|
+
|
|
355
|
+
// When only a consumer declares the focused channel, the message still enters at the
|
|
356
|
+
// focused channel, matching the message graph's no-producer-channel behaviour.
|
|
357
|
+
const routesToRender = ingressRoutes.length > 0 ? ingressRoutes : [[channel]];
|
|
358
|
+
for (const route of routesToRender) {
|
|
359
|
+
addChannelRoute(route, message.data.id);
|
|
360
|
+
const firstChannel = route[0];
|
|
361
|
+
addEdge(
|
|
362
|
+
createEdge({
|
|
363
|
+
id: generatedIdForEdge(message, firstChannel),
|
|
364
|
+
source: messageNodeId,
|
|
365
|
+
target: generateIdForNode(firstChannel),
|
|
366
|
+
label: 'routes to',
|
|
367
|
+
data: { customColor: getColorFromString(message.data.id) },
|
|
368
|
+
})
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
for (const { resource: producer } of producers) {
|
|
373
|
+
addResourceNode(producer);
|
|
374
|
+
addEdge(
|
|
375
|
+
createEdge({
|
|
376
|
+
id: generatedIdForEdge(producer, message),
|
|
377
|
+
source: generateIdForNode(producer),
|
|
378
|
+
target: messageNodeId,
|
|
379
|
+
label: getEdgeLabelForServiceAsTarget(message),
|
|
380
|
+
type: 'multiline',
|
|
381
|
+
data: { customColor: getColorFromString(message.data.id) },
|
|
382
|
+
})
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
for (const { resource: consumer, channelRoutes } of consumers) {
|
|
387
|
+
for (const route of channelRoutes) {
|
|
388
|
+
addChannelRoute(route, message.data.id);
|
|
389
|
+
const sourceChannel = route[route.length - 1];
|
|
390
|
+
const consumerNodeId = generateIdForNode(consumer);
|
|
391
|
+
const groupKey = `${generateIdForNode(sourceChannel)}:${consumerNodeId}`;
|
|
392
|
+
const grouped = messagesByConsumer.get(groupKey) ?? { sourceChannel, consumer, messages: [] };
|
|
393
|
+
if (!grouped.messages.some((groupedMessage) => generateIdForNode(groupedMessage) === messageNodeId)) {
|
|
394
|
+
grouped.messages.push(message);
|
|
395
|
+
}
|
|
396
|
+
messagesByConsumer.set(groupKey, grouped);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// One edge per consumer, labelled with the message when there is only one
|
|
402
|
+
for (const { sourceChannel, consumer, messages } of messagesByConsumer.values()) {
|
|
403
|
+
addResourceNode(consumer);
|
|
404
|
+
addEdge(
|
|
405
|
+
createEdge({
|
|
406
|
+
id: generatedIdForEdge(sourceChannel, consumer),
|
|
407
|
+
source: generateIdForNode(sourceChannel),
|
|
408
|
+
target: generateIdForNode(consumer),
|
|
409
|
+
label:
|
|
410
|
+
messages.length === 1 ? getEdgeLabelForMessageAsSource(messages[0], true) : `consumes ${messages.length}\nmessages`,
|
|
411
|
+
type: 'multiline',
|
|
412
|
+
data: { customColor: getColorFromString(sourceChannel.data.id) },
|
|
413
|
+
})
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Channels this channel routes messages on to
|
|
418
|
+
for (const route of (channel.data.routes ?? []) as { id: string; version?: string }[]) {
|
|
419
|
+
const routedChannel = findInMap(channelMap, route.id, route.version) as CollectionEntry<'channels'> | undefined;
|
|
420
|
+
if (!routedChannel || generateIdForNode(routedChannel) === channelNodeId) continue;
|
|
421
|
+
|
|
422
|
+
addChannelNode(routedChannel);
|
|
423
|
+
addEdge(
|
|
424
|
+
createEdge({
|
|
425
|
+
id: generatedIdForEdge(channel, routedChannel),
|
|
426
|
+
source: channelNodeId,
|
|
427
|
+
target: generateIdForNode(routedChannel),
|
|
428
|
+
label: 'routes to',
|
|
429
|
+
data: { customColor: getColorFromString(channel.data.id) },
|
|
430
|
+
})
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Channels that route messages into this channel
|
|
435
|
+
for (const upstreamChannel of channels) {
|
|
436
|
+
if (generateIdForNode(upstreamChannel) === channelNodeId) continue;
|
|
437
|
+
if (!routesDirectlyToFocusedChannel(upstreamChannel.data.routes as ChannelPointer[] | undefined)) continue;
|
|
438
|
+
|
|
439
|
+
addChannelNode(upstreamChannel);
|
|
440
|
+
addEdge(
|
|
441
|
+
createEdge({
|
|
442
|
+
id: generatedIdForEdge(upstreamChannel, channel),
|
|
443
|
+
source: generateIdForNode(upstreamChannel),
|
|
444
|
+
target: channelNodeId,
|
|
445
|
+
label: 'routes to',
|
|
446
|
+
data: { customColor: getColorFromString(upstreamChannel.data.id) },
|
|
447
|
+
})
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
nodes.forEach((node) => {
|
|
452
|
+
flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
edges.forEach((edge) => {
|
|
456
|
+
flow.setEdge(edge.source, edge.target);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
if (layout) {
|
|
460
|
+
dagre.layout(flow);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return {
|
|
464
|
+
nodes: calculatedNodes(flow, nodes),
|
|
465
|
+
edges,
|
|
466
|
+
};
|
|
467
|
+
};
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "4.
|
|
10
|
+
"version": "4.7.0",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
@@ -119,9 +119,9 @@
|
|
|
119
119
|
"update-notifier": "^7.3.1",
|
|
120
120
|
"uuid": "^11.1.1",
|
|
121
121
|
"zod": "^4.3.6",
|
|
122
|
-
"@eventcatalog/
|
|
123
|
-
"@eventcatalog/
|
|
124
|
-
"@eventcatalog/visualiser": "^4.1.
|
|
122
|
+
"@eventcatalog/linter": "1.1.11",
|
|
123
|
+
"@eventcatalog/sdk": "2.27.2",
|
|
124
|
+
"@eventcatalog/visualiser": "^4.1.3"
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
127
|
"@astrojs/check": "^0.9.10",
|