@eventcatalog/core 2.12.3 → 2.13.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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/public/icons/protocols/kafka.svg +1 -0
- package/scripts/catalog-to-astro-content-directory.js +13 -1
- package/scripts/default-files-for-collections/channels.md +8 -0
- package/scripts/map-catalog-to-astro.js +1 -0
- package/src/components/DocsNavigation.astro +4 -4
- package/src/components/Header.astro +1 -1
- package/src/components/Lists/PillListFlat.tsx +19 -12
- package/src/components/Lists/ProtocolList.tsx +88 -0
- package/src/components/MDX/ChannelInformation/ChannelInformation.tsx +79 -0
- package/src/components/MDX/Flow/Flow.astro +3 -3
- package/src/components/MDX/NodeGraph/DownloadButton.tsx +3 -3
- package/src/components/MDX/NodeGraph/Edges/AnimatedMessageEdge.tsx +82 -0
- package/src/components/MDX/NodeGraph/NodeGraph.astro +24 -67
- package/src/components/MDX/NodeGraph/NodeGraph.tsx +188 -17
- package/src/components/MDX/NodeGraph/Nodes/Channel.tsx +133 -0
- package/src/components/MDX/components.tsx +2 -0
- package/src/components/Seo.astro +0 -2
- package/src/components/SideBars/CatalogResourcesSideBar/index.tsx +4 -13
- package/src/components/SideBars/ChannelSideBar.astro +117 -0
- package/src/components/SideBars/MessageSideBar.astro +13 -0
- package/src/content/config.ts +37 -0
- package/src/icons/protocols/WebSocket.svg +1 -0
- package/src/icons/protocols/amqp.svg +1 -0
- package/src/icons/protocols/eventbridge.svg +6 -0
- package/src/icons/protocols/googlepubsub.svg +1 -0
- package/src/icons/protocols/http.svg +1 -0
- package/src/icons/protocols/index.ts +15 -0
- package/src/icons/protocols/jms.svg +1 -0
- package/src/icons/protocols/kafka.svg +1 -0
- package/src/icons/protocols/mercure.svg +20 -0
- package/src/icons/protocols/mqtt.svg +17 -0
- package/src/icons/protocols/nats.svg +13 -0
- package/src/icons/protocols/pulsar.svg +4 -0
- package/src/icons/protocols/redis.svg +1 -0
- package/src/icons/protocols/sns.svg +6 -0
- package/src/icons/protocols/solace.svg +1 -0
- package/src/icons/protocols/sqs.svg +7 -0
- package/src/icons/protocols/ws.svg +1 -0
- package/src/layouts/DiscoverLayout.astro +3 -3
- package/src/layouts/VerticalSideBarLayout.astro +10 -5
- package/src/layouts/VisualiserLayout.astro +3 -3
- package/src/pages/discover/[type]/index.astro +3 -3
- package/src/pages/docs/[type]/[id]/[version]/asyncapi/index.astro +2 -2
- package/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +2 -2
- package/src/pages/docs/[type]/[id]/[version]/index.astro +11 -4
- package/src/pages/docs/[type]/[id]/[version]/spec/index.astro +2 -2
- package/src/pages/docs/[type]/[id]/index.astro +17 -4
- package/src/pages/index.astro +3 -3
- package/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
- package/src/pages/visualiser/[type]/[id]/index.astro +2 -2
- package/src/remark-plugins/mermaid.ts +0 -1
- package/src/types/index.ts +2 -2
- package/src/utils/channels.ts +64 -0
- package/src/utils/collections/icons.ts +6 -0
- package/src/utils/commands.ts +6 -0
- package/src/utils/{config → eventcatalog-config}/catalog.ts +1 -1
- package/src/utils/events.ts +5 -0
- package/src/utils/{domains/node-graph.ts → node-graphs/domains-node-graph.ts} +2 -2
- package/src/utils/{flows/node-graph.ts → node-graphs/flows-node-graph.ts} +2 -2
- package/src/utils/node-graphs/message-node-graph.ts +216 -0
- package/src/utils/{services/node-graph.ts → node-graphs/services-node-graph.ts} +79 -54
- package/src/utils/node-graphs/utils/utils.ts +128 -0
- package/src/utils/{pages/pages.ts → page-loaders/page-data-loader.ts} +4 -2
- package/src/utils/queries.ts +5 -0
- package/tsconfig.json +2 -1
- package/src/remark-plugins/remark-modified-time.mjs +0 -9
- package/src/utils/commands/node-graph.ts +0 -144
- package/src/utils/events/node-graph.ts +0 -145
- package/src/utils/node-graph-utils/utils.ts +0 -29
- package/src/utils/queries/node-graph.ts +0 -144
- /package/src/pages/docs/[type]/[id]/[version]/spec/{styles.css → _styles.css} +0 -0
- /package/src/utils/{changelogs → collections}/changelogs.ts +0 -0
- /package/src/utils/{domains → collections}/domains.ts +0 -0
- /package/src/utils/{flows → collections}/flows.ts +0 -0
- /package/src/utils/{services → collections}/services.ts +0 -0
- /package/src/utils/{versions → collections}/versions.ts +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getCollection } from 'astro:content';
|
|
2
|
+
import type { CollectionEntry } from 'astro:content';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { getVersionForCollectionItem, satisfies } from './collections/util';
|
|
5
|
+
import { getMessages } from './messages';
|
|
6
|
+
import type { CollectionMessageTypes } from '@types';
|
|
7
|
+
|
|
8
|
+
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
9
|
+
|
|
10
|
+
type Channel = CollectionEntry<'channels'> & {
|
|
11
|
+
catalog: {
|
|
12
|
+
path: string;
|
|
13
|
+
filePath: string;
|
|
14
|
+
type: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
getAllVersions?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const getChannels = async ({ getAllVersions = true }: Props = {}): Promise<Channel[]> => {
|
|
23
|
+
const channels = await getCollection('channels', (query) => {
|
|
24
|
+
return (getAllVersions || !query.slug.includes('versioned')) && query.data.hidden !== true;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const { commands, events, queries } = await getMessages();
|
|
28
|
+
const allMessages = [...commands, ...events, ...queries];
|
|
29
|
+
|
|
30
|
+
return channels.map((channel) => {
|
|
31
|
+
const { latestVersion, versions } = getVersionForCollectionItem(channel, channels);
|
|
32
|
+
|
|
33
|
+
const messagesForChannel = allMessages.filter((message) => {
|
|
34
|
+
return message.data.channels?.some((messageChannel) => {
|
|
35
|
+
if (messageChannel.id != channel.data.id) return false;
|
|
36
|
+
if (messageChannel.version == 'latest' || messageChannel.version == undefined)
|
|
37
|
+
return channel.data.version == latestVersion;
|
|
38
|
+
return satisfies(channel.data.version, messageChannel.version);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const messages = messagesForChannel.map((message: CollectionEntry<CollectionMessageTypes>) => {
|
|
43
|
+
return { id: message.data.id, name: message.data.name, version: message.data.version, collection: message.collection };
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...channel,
|
|
48
|
+
data: {
|
|
49
|
+
...channel.data,
|
|
50
|
+
versions,
|
|
51
|
+
latestVersion,
|
|
52
|
+
messages,
|
|
53
|
+
},
|
|
54
|
+
catalog: {
|
|
55
|
+
path: path.join(channel.collection, channel.id.replace('/index.mdx', '')),
|
|
56
|
+
absoluteFilePath: path.join(PROJECT_DIR, channel.collection, channel.id.replace('/index.mdx', '/index.md')),
|
|
57
|
+
astroContentFilePath: path.join(process.cwd(), 'src', 'content', channel.collection, channel.id),
|
|
58
|
+
filePath: path.join(process.cwd(), 'src', 'catalog-files', channel.collection, channel.id.replace('/index.mdx', '')),
|
|
59
|
+
publicPath: path.join('/generated', channel.collection, channel.id.replace('/index.mdx', '')),
|
|
60
|
+
type: 'event',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
};
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
QueueListIcon,
|
|
8
8
|
UserGroupIcon,
|
|
9
9
|
UserIcon,
|
|
10
|
+
ArrowsRightLeftIcon,
|
|
11
|
+
VariableIcon,
|
|
10
12
|
} from '@heroicons/react/24/outline';
|
|
11
13
|
|
|
12
14
|
export const getIconForCollection = (collection: string) => {
|
|
@@ -27,6 +29,10 @@ export const getIconForCollection = (collection: string) => {
|
|
|
27
29
|
return UserGroupIcon;
|
|
28
30
|
case 'users':
|
|
29
31
|
return UserIcon;
|
|
32
|
+
case 'channels':
|
|
33
|
+
return ArrowsRightLeftIcon;
|
|
34
|
+
case 'channels-parameter':
|
|
35
|
+
return VariableIcon;
|
|
30
36
|
default:
|
|
31
37
|
return ServerIcon;
|
|
32
38
|
}
|
package/src/utils/commands.ts
CHANGED
|
@@ -21,7 +21,9 @@ export const getCommands = async ({ getAllVersions = true }: Props = {}): Promis
|
|
|
21
21
|
const commands = await getCollection('commands', (command) => {
|
|
22
22
|
return (getAllVersions || !command.slug.includes('versioned')) && command.data.hidden !== true;
|
|
23
23
|
});
|
|
24
|
+
|
|
24
25
|
const services = await getCollection('services');
|
|
26
|
+
const allChannels = await getCollection('channels');
|
|
25
27
|
|
|
26
28
|
return commands.map((command) => {
|
|
27
29
|
const { latestVersion, versions } = getVersionForCollectionItem(command, commands);
|
|
@@ -42,10 +44,14 @@ export const getCommands = async ({ getAllVersions = true }: Props = {}): Promis
|
|
|
42
44
|
});
|
|
43
45
|
});
|
|
44
46
|
|
|
47
|
+
const messageChannels = command.data.channels || [];
|
|
48
|
+
const channelsForCommand = allChannels.filter((c) => messageChannels.some((channel) => c.data.id === channel.id));
|
|
49
|
+
|
|
45
50
|
return {
|
|
46
51
|
...command,
|
|
47
52
|
data: {
|
|
48
53
|
...command.data,
|
|
54
|
+
messageChannels: channelsForCommand,
|
|
49
55
|
producers,
|
|
50
56
|
consumers,
|
|
51
57
|
versions,
|
|
@@ -24,7 +24,7 @@ const getConfigValue = (obj: any, key: string, defaultValue: any) => {
|
|
|
24
24
|
|
|
25
25
|
export const isCollectionVisibleInCatalog = (collection: string) => {
|
|
26
26
|
const sidebarConfig = config?.default?.docs?.sidebar || {};
|
|
27
|
-
const collections = ['events', 'commands', 'queries', 'domains', 'flows', 'services', 'teams', 'users'];
|
|
27
|
+
const collections = ['events', 'commands', 'queries', 'domains', 'channels', 'flows', 'services', 'teams', 'users'];
|
|
28
28
|
|
|
29
29
|
if (!collections.includes(collection)) return false;
|
|
30
30
|
|
package/src/utils/events.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const getEvents = async ({ getAllVersions = true }: Props = {}): Promise<
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
const services = await getCollection('services');
|
|
26
|
+
const allChannels = await getCollection('channels');
|
|
26
27
|
|
|
27
28
|
return events.map((event) => {
|
|
28
29
|
const { latestVersion, versions } = getVersionForCollectionItem(event, events);
|
|
@@ -43,10 +44,14 @@ export const getEvents = async ({ getAllVersions = true }: Props = {}): Promise<
|
|
|
43
44
|
})
|
|
44
45
|
);
|
|
45
46
|
|
|
47
|
+
const messageChannels = event.data.channels || [];
|
|
48
|
+
const channelsForEvent = allChannels.filter((c) => messageChannels.some((channel) => c.data.id === channel.id));
|
|
49
|
+
|
|
46
50
|
return {
|
|
47
51
|
...event,
|
|
48
52
|
data: {
|
|
49
53
|
...event.data,
|
|
54
|
+
messageChannels: channelsForEvent,
|
|
50
55
|
producers,
|
|
51
56
|
consumers,
|
|
52
57
|
versions,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCollection } from 'astro:content';
|
|
2
|
-
import { createDagreGraph, calculatedNodes } from '@utils/node-
|
|
3
|
-
import { getNodesAndEdges as getServicesNodeAndEdges } from '
|
|
2
|
+
import { createDagreGraph, calculatedNodes } from '@utils/node-graphs/utils/utils';
|
|
3
|
+
import { getNodesAndEdges as getServicesNodeAndEdges } from './services-node-graph';
|
|
4
4
|
import merge from 'lodash.merge';
|
|
5
5
|
import { getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
2
2
|
import dagre from 'dagre';
|
|
3
|
-
import { createDagreGraph, calculatedNodes } from '@utils/node-
|
|
3
|
+
import { createDagreGraph, calculatedNodes } from '@utils/node-graphs/utils/utils';
|
|
4
4
|
import { MarkerType } from 'reactflow';
|
|
5
5
|
import type { Node as NodeType } from 'reactflow';
|
|
6
6
|
import { getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
|
|
@@ -118,7 +118,7 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
118
118
|
id: `step-${step.id}-step-${path.id}`,
|
|
119
119
|
source: `step-${step.id}`,
|
|
120
120
|
target: `step-${path.id}`,
|
|
121
|
-
type: '
|
|
121
|
+
type: 'bezier',
|
|
122
122
|
label: path.label,
|
|
123
123
|
animated: true,
|
|
124
124
|
markerEnd: {
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// import { getColor } from '@utils/colors';
|
|
2
|
+
import { getEvents } from '@utils/events';
|
|
3
|
+
import type { CollectionEntry } from 'astro:content';
|
|
4
|
+
import dagre from 'dagre';
|
|
5
|
+
import {
|
|
6
|
+
calculatedNodes,
|
|
7
|
+
createDagreGraph,
|
|
8
|
+
createEdge,
|
|
9
|
+
generatedIdForEdge,
|
|
10
|
+
generateIdForNode,
|
|
11
|
+
getChannelNodesAndEdges,
|
|
12
|
+
} from './utils/utils';
|
|
13
|
+
import { MarkerType } from 'reactflow';
|
|
14
|
+
import { findMatchingNodes } from '@utils/collections/util';
|
|
15
|
+
import type { CollectionMessageTypes } from '@types';
|
|
16
|
+
import { getCommands } from '@utils/commands';
|
|
17
|
+
import { getQueries } from '@utils/queries';
|
|
18
|
+
|
|
19
|
+
type DagreGraph = any;
|
|
20
|
+
|
|
21
|
+
interface Props {
|
|
22
|
+
id: string;
|
|
23
|
+
version: string;
|
|
24
|
+
defaultFlow?: DagreGraph;
|
|
25
|
+
mode?: 'simple' | 'full';
|
|
26
|
+
collection?: CollectionEntry<CollectionMessageTypes>[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getEdgeLabelForServiceAsTarget = (data: CollectionEntry<CollectionMessageTypes>) => {
|
|
30
|
+
const type = data.collection;
|
|
31
|
+
switch (type) {
|
|
32
|
+
case 'commands':
|
|
33
|
+
return 'invokes';
|
|
34
|
+
case 'events':
|
|
35
|
+
return 'publishes event';
|
|
36
|
+
case 'queries':
|
|
37
|
+
return 'requests';
|
|
38
|
+
default:
|
|
39
|
+
return 'sends to';
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const getEdgeLabelForMessageAsSource = (data: CollectionEntry<CollectionMessageTypes>) => {
|
|
43
|
+
const type = data.collection;
|
|
44
|
+
switch (type) {
|
|
45
|
+
case 'commands':
|
|
46
|
+
return 'accepts';
|
|
47
|
+
case 'events':
|
|
48
|
+
return 'subscribed by';
|
|
49
|
+
case 'queries':
|
|
50
|
+
return 'accepts';
|
|
51
|
+
default:
|
|
52
|
+
return 'sends to';
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simple', collection = [] }: Props) => {
|
|
57
|
+
const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
|
|
58
|
+
const nodes = [] as any,
|
|
59
|
+
edges = [] as any;
|
|
60
|
+
|
|
61
|
+
const message = collection.find((message) => {
|
|
62
|
+
return message.data.id === id && message.data.version === version;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Nothing found...
|
|
66
|
+
if (!message) {
|
|
67
|
+
return {
|
|
68
|
+
nodes: [],
|
|
69
|
+
edges: [],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const producers = (message.data.producers as CollectionEntry<'services'>[]) || [];
|
|
74
|
+
const consumers = (message.data.consumers as CollectionEntry<'services'>[]) || [];
|
|
75
|
+
const channels = (message.data.messageChannels as CollectionEntry<'channels'>[]) || [];
|
|
76
|
+
|
|
77
|
+
// Track nodes that are both sent and received
|
|
78
|
+
const bothSentAndReceived = findMatchingNodes(producers, consumers);
|
|
79
|
+
|
|
80
|
+
producers.forEach((producer) => {
|
|
81
|
+
nodes.push({
|
|
82
|
+
id: generateIdForNode(producer),
|
|
83
|
+
type: producer?.collection,
|
|
84
|
+
sourcePosition: 'right',
|
|
85
|
+
targetPosition: 'left',
|
|
86
|
+
data: { mode, service: producer },
|
|
87
|
+
position: { x: 250, y: 0 },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// If the event has channels, we need to render them, otherwise connect the producer to the event
|
|
91
|
+
if (message.data.channels) {
|
|
92
|
+
const { nodes: channelNodes, edges: channelEdges } = getChannelNodesAndEdges({
|
|
93
|
+
channels,
|
|
94
|
+
channelsToRender: message.data.channels,
|
|
95
|
+
source: producer,
|
|
96
|
+
target: message,
|
|
97
|
+
sourceToChannelLabel: getEdgeLabelForServiceAsTarget(message),
|
|
98
|
+
channelToTargetLabel: getEdgeLabelForServiceAsTarget(message),
|
|
99
|
+
mode,
|
|
100
|
+
currentNodes: nodes,
|
|
101
|
+
});
|
|
102
|
+
nodes.push(...channelNodes);
|
|
103
|
+
edges.push(...channelEdges);
|
|
104
|
+
} else {
|
|
105
|
+
edges.push({
|
|
106
|
+
id: generatedIdForEdge(producer, message),
|
|
107
|
+
source: generateIdForNode(producer),
|
|
108
|
+
target: generateIdForNode(message),
|
|
109
|
+
label: getEdgeLabelForServiceAsTarget(message),
|
|
110
|
+
data: { message },
|
|
111
|
+
animated: false,
|
|
112
|
+
markerEnd: {
|
|
113
|
+
type: MarkerType.ArrowClosed,
|
|
114
|
+
width: 40,
|
|
115
|
+
height: 40,
|
|
116
|
+
},
|
|
117
|
+
style: {
|
|
118
|
+
strokeWidth: 1,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// The message itself
|
|
125
|
+
nodes.push({
|
|
126
|
+
id: generateIdForNode(message),
|
|
127
|
+
sourcePosition: 'right',
|
|
128
|
+
targetPosition: 'left',
|
|
129
|
+
data: { mode, message: message },
|
|
130
|
+
position: { x: 0, y: 0 },
|
|
131
|
+
type: message.collection,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// The messages the service sends
|
|
135
|
+
consumers.forEach((consumer) => {
|
|
136
|
+
nodes.push({
|
|
137
|
+
id: generateIdForNode(consumer),
|
|
138
|
+
sourcePosition: 'right',
|
|
139
|
+
targetPosition: 'left',
|
|
140
|
+
data: { title: consumer?.data.id, mode, service: consumer },
|
|
141
|
+
position: { x: 0, y: 0 },
|
|
142
|
+
type: consumer?.collection,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (message.data.channels) {
|
|
146
|
+
const { nodes: channelNodes, edges: channelEdges } = getChannelNodesAndEdges({
|
|
147
|
+
channels,
|
|
148
|
+
channelsToRender: channels.map((channel) => ({ id: channel.data.id, version: channel.data.version })),
|
|
149
|
+
source: message,
|
|
150
|
+
target: consumer,
|
|
151
|
+
channelToTargetLabel: getEdgeLabelForMessageAsSource(message),
|
|
152
|
+
mode,
|
|
153
|
+
currentNodes: nodes,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
nodes.push(...channelNodes);
|
|
157
|
+
edges.push(...channelEdges);
|
|
158
|
+
} else {
|
|
159
|
+
edges.push(
|
|
160
|
+
createEdge({
|
|
161
|
+
id: generatedIdForEdge(message, consumer),
|
|
162
|
+
source: generateIdForNode(message),
|
|
163
|
+
target: generateIdForNode(consumer),
|
|
164
|
+
label: getEdgeLabelForMessageAsSource(message),
|
|
165
|
+
data: { message },
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Handle messages that are both sent and received
|
|
172
|
+
bothSentAndReceived.forEach((_message) => {
|
|
173
|
+
if (message) {
|
|
174
|
+
edges.push(
|
|
175
|
+
createEdge({
|
|
176
|
+
id: generatedIdForEdge(message, _message) + '-both',
|
|
177
|
+
source: generateIdForNode(message),
|
|
178
|
+
target: generateIdForNode(_message),
|
|
179
|
+
label: 'publishes and subscribes',
|
|
180
|
+
data: { message },
|
|
181
|
+
})
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
nodes.forEach((node: any) => {
|
|
187
|
+
flow.setNode(node.id, { width: 150, height: 100 });
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
edges.forEach((edge: any) => {
|
|
191
|
+
flow.setEdge(edge.source, edge.target);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Render the diagram in memory getting hte X and Y
|
|
195
|
+
dagre.layout(flow);
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
nodes: calculatedNodes(flow, nodes),
|
|
199
|
+
edges,
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export const getNodesAndEdgesForQueries = async ({ id, version, defaultFlow, mode = 'simple' }: Props) => {
|
|
204
|
+
const queries = await getQueries();
|
|
205
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, collection: queries });
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export const getNodesAndEdgesForCommands = async ({ id, version, defaultFlow, mode = 'simple' }: Props) => {
|
|
209
|
+
const commands = await getCommands();
|
|
210
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, collection: commands });
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export const getNodesAndEdgesForEvents = async ({ id, version, defaultFlow, mode = 'simple' }: Props) => {
|
|
214
|
+
const events = await getEvents();
|
|
215
|
+
return getNodesAndEdges({ id, version, defaultFlow, mode, collection: events });
|
|
216
|
+
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
2
2
|
import dagre from 'dagre';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createDagreGraph,
|
|
5
|
+
generateIdForNode,
|
|
6
|
+
generatedIdForEdge,
|
|
7
|
+
calculatedNodes,
|
|
8
|
+
createEdge,
|
|
9
|
+
getChannelNodesAndEdges,
|
|
10
|
+
} from '@utils/node-graphs/utils/utils';
|
|
4
11
|
import { findMatchingNodes, getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
|
|
5
12
|
import { MarkerType } from 'reactflow';
|
|
13
|
+
import type { CollectionMessageTypes } from '@types';
|
|
6
14
|
|
|
7
15
|
type DagreGraph = any;
|
|
8
16
|
|
|
@@ -62,6 +70,7 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
62
70
|
const events = await getCollection('events');
|
|
63
71
|
const commands = await getCollection('commands');
|
|
64
72
|
const queries = await getCollection('queries');
|
|
73
|
+
const channels = await getCollection('channels');
|
|
65
74
|
|
|
66
75
|
const messages = [...events, ...commands, ...queries];
|
|
67
76
|
|
|
@@ -75,50 +84,57 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
75
84
|
.flat()
|
|
76
85
|
.filter((e) => e !== undefined);
|
|
77
86
|
|
|
78
|
-
const receives = (receivesHydrated as CollectionEntry<
|
|
79
|
-
const sends = (sendsHydrated as CollectionEntry<
|
|
87
|
+
const receives = (receivesHydrated as CollectionEntry<CollectionMessageTypes>[]) || [];
|
|
88
|
+
const sends = (sendsHydrated as CollectionEntry<CollectionMessageTypes>[]) || [];
|
|
80
89
|
|
|
81
90
|
// Track messages that are both sent and received
|
|
82
91
|
const bothSentAndReceived = findMatchingNodes(receives, sends);
|
|
83
92
|
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
data: { mode, message: receive, showTarget: renderAllEdges },
|
|
94
|
-
position: { x: 250, y: index * 100 },
|
|
95
|
-
});
|
|
96
|
-
edges.push({
|
|
97
|
-
id: generatedIdForEdge(receive, service),
|
|
98
|
-
source: generateIdForNode(receive),
|
|
99
|
-
target: generateIdForNode(service),
|
|
100
|
-
type: 'smoothstep',
|
|
101
|
-
label: getReceivesMessageByMessageType(receive?.collection),
|
|
102
|
-
animated: false,
|
|
103
|
-
markerEnd: {
|
|
104
|
-
type: MarkerType.ArrowClosed,
|
|
105
|
-
width: 40,
|
|
106
|
-
height: 40,
|
|
107
|
-
},
|
|
108
|
-
style: {
|
|
109
|
-
strokeWidth: 1,
|
|
110
|
-
},
|
|
111
|
-
});
|
|
93
|
+
// All the messages the service receives
|
|
94
|
+
receives.forEach((receive) => {
|
|
95
|
+
// Create the node for the message
|
|
96
|
+
nodes.push({
|
|
97
|
+
id: generateIdForNode(receive),
|
|
98
|
+
type: receive?.collection,
|
|
99
|
+
sourcePosition: 'right',
|
|
100
|
+
targetPosition: 'left',
|
|
101
|
+
data: { mode, message: receive },
|
|
112
102
|
});
|
|
113
|
-
|
|
103
|
+
|
|
104
|
+
// does the message have channels defined?
|
|
105
|
+
if (receive.data.channels) {
|
|
106
|
+
const { nodes: channelNodes, edges: channelEdges } = getChannelNodesAndEdges({
|
|
107
|
+
channels,
|
|
108
|
+
channelsToRender: receive.data.channels,
|
|
109
|
+
source: receive,
|
|
110
|
+
channelToTargetLabel: getReceivesMessageByMessageType(receive?.collection),
|
|
111
|
+
target: service,
|
|
112
|
+
mode,
|
|
113
|
+
currentNodes: nodes,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
nodes.push(...channelNodes);
|
|
117
|
+
edges.push(...channelEdges);
|
|
118
|
+
} else {
|
|
119
|
+
// No channels, just link the message to the service
|
|
120
|
+
edges.push(
|
|
121
|
+
createEdge({
|
|
122
|
+
id: generatedIdForEdge(receive, service),
|
|
123
|
+
source: generateIdForNode(receive),
|
|
124
|
+
target: generateIdForNode(service),
|
|
125
|
+
label: getReceivesMessageByMessageType(receive?.collection),
|
|
126
|
+
data: { message: receive },
|
|
127
|
+
})
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
114
131
|
|
|
115
132
|
// The service itself
|
|
116
133
|
nodes.push({
|
|
117
134
|
id: generateIdForNode(service),
|
|
118
135
|
sourcePosition: 'right',
|
|
119
136
|
targetPosition: 'left',
|
|
120
|
-
data: { mode, service: service
|
|
121
|
-
position: { x: 0, y: 0 },
|
|
137
|
+
data: { mode, service: service },
|
|
122
138
|
type: service.collection,
|
|
123
139
|
});
|
|
124
140
|
|
|
@@ -128,26 +144,35 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
128
144
|
id: generateIdForNode(send),
|
|
129
145
|
sourcePosition: 'right',
|
|
130
146
|
targetPosition: 'left',
|
|
131
|
-
data: { mode, message: send
|
|
132
|
-
position: { x: 500, y: index * 100 },
|
|
147
|
+
data: { mode, message: send },
|
|
133
148
|
type: send?.collection,
|
|
134
149
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
|
|
151
|
+
if (send.data.channels) {
|
|
152
|
+
const { nodes: channelNodes, edges: channelEdges } = getChannelNodesAndEdges({
|
|
153
|
+
channels,
|
|
154
|
+
channelsToRender: send.data.channels,
|
|
155
|
+
source: service,
|
|
156
|
+
target: send,
|
|
157
|
+
mode,
|
|
158
|
+
sourceToChannelLabel: `${getSendsMessageByMessageType(send?.collection)}`,
|
|
159
|
+
channelToTargetLabel: getSendsMessageByMessageType(send?.collection),
|
|
160
|
+
currentNodes: nodes,
|
|
161
|
+
});
|
|
162
|
+
nodes.push(...channelNodes);
|
|
163
|
+
edges.push(...channelEdges);
|
|
164
|
+
} else {
|
|
165
|
+
// No channels, just link the message to the service
|
|
166
|
+
edges.push(
|
|
167
|
+
createEdge({
|
|
168
|
+
id: generatedIdForEdge(service, send),
|
|
169
|
+
source: generateIdForNode(service),
|
|
170
|
+
target: generateIdForNode(send),
|
|
171
|
+
label: getSendsMessageByMessageType(send?.collection),
|
|
172
|
+
data: { message: send },
|
|
173
|
+
})
|
|
174
|
+
);
|
|
175
|
+
}
|
|
151
176
|
});
|
|
152
177
|
|
|
153
178
|
// Handle messages that are both sent and received
|
|
@@ -157,9 +182,9 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
157
182
|
id: generatedIdForEdge(service, message) + '-both',
|
|
158
183
|
source: generateIdForNode(service),
|
|
159
184
|
target: generateIdForNode(message),
|
|
160
|
-
type: 'smoothstep',
|
|
161
185
|
label: `${getSendsMessageByMessageType(message?.collection)} & ${getReceivesMessageByMessageType(message?.collection)}`,
|
|
162
186
|
animated: false,
|
|
187
|
+
data: { message },
|
|
163
188
|
markerEnd: {
|
|
164
189
|
type: MarkerType.ArrowClosed,
|
|
165
190
|
width: 40,
|
|
@@ -185,6 +210,6 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
|
|
|
185
210
|
|
|
186
211
|
return {
|
|
187
212
|
nodes: calculatedNodes(flow, nodes),
|
|
188
|
-
edges
|
|
213
|
+
edges,
|
|
189
214
|
};
|
|
190
215
|
};
|