@eventcatalog/core 2.11.6 → 2.12.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @eventcatalog/core
2
2
 
3
+ ## 2.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a136d50: feat(core): services can now send and receive the same messages in vis…
8
+
9
+ ## 2.11.7
10
+
11
+ ### Patch Changes
12
+
13
+ - 159e2d4: feat(core): added ability to embed discovery table
14
+
3
15
  ## 2.11.6
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/event-catalog/eventcatalog.git"
7
7
  },
8
8
  "type": "module",
9
- "version": "2.11.6",
9
+ "version": "2.12.0",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
@@ -81,6 +81,7 @@ const NodeGraphBuilder = ({
81
81
  setEdges((eds) =>
82
82
  eds.map((edge) => {
83
83
  edge.style = { ...edge.style, opacity: 1 };
84
+ edge.labelStyle = { ...edge.labelStyle, opacity: 1 };
84
85
  return { ...edge, animated: false };
85
86
  })
86
87
  );
@@ -107,9 +108,19 @@ const NodeGraphBuilder = ({
107
108
  if (edge.source === node.id || edge.target === node.id) {
108
109
  connectedNodeIds.add(edge.source);
109
110
  connectedNodeIds.add(edge.target);
110
- return { ...edge, style: { ...edge.style, opacity: 1 }, animated: true };
111
+ return {
112
+ ...edge,
113
+ style: { ...edge.style, opacity: 1 },
114
+ labelStyle: { ...edge.labelStyle, opacity: 1 },
115
+ animated: true,
116
+ };
111
117
  }
112
- return { ...edge, style: { ...edge.style, opacity: 0.1 }, animated: false };
118
+ return {
119
+ ...edge,
120
+ style: { ...edge.style, opacity: 0.1 },
121
+ labelStyle: { ...edge.labelStyle, opacity: 0.1 },
122
+ animated: false,
123
+ };
113
124
  });
114
125
 
115
126
  const updatedNodes = nodes.map((n) => {
@@ -18,13 +18,10 @@ function classNames(...classes: any) {
18
18
  }
19
19
 
20
20
  export default function CommandNode({ data, sourcePosition, targetPosition }: any) {
21
- const { mode, message, showSource = true, showTarget = true } = data as Data;
21
+ const { mode, message } = data as Data;
22
22
 
23
23
  const { name, version, summary, owners = [], producers = [], consumers = [] } = message.data;
24
24
 
25
- const renderTarget = showTarget || (targetPosition && producers.length > 0);
26
- const renderSource = showSource || (sourcePosition && consumers.length > 0);
27
-
28
25
  return (
29
26
  <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-blue-400')}>
30
27
  <div
@@ -41,8 +38,8 @@ export default function CommandNode({ data, sourcePosition, targetPosition }: an
41
38
  )}
42
39
  </div>
43
40
  <div className="p-1 min-w-60 max-w-[min-content]">
44
- {renderTarget && <Handle type="target" position={targetPosition} />}
45
- {renderSource && <Handle type="source" position={sourcePosition} />}
41
+ {targetPosition && <Handle type="target" position={targetPosition} />}
42
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
46
43
  <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
47
44
  <span className="text-xs font-bold block pb-0.5">{name}</span>
48
45
  <div className="flex justify-between">
@@ -18,13 +18,10 @@ function classNames(...classes: any) {
18
18
  }
19
19
 
20
20
  export default function EventNode({ data, sourcePosition, targetPosition }: any) {
21
- const { mode, message, showTarget = true, showSource = true } = data as Data;
21
+ const { mode, message } = data as Data;
22
22
 
23
23
  const { name, version, summary, owners = [], producers = [], consumers = [] } = message.data;
24
24
 
25
- const renderTarget = showTarget || (targetPosition && producers.length > 0);
26
- const renderSource = showSource || (sourcePosition && consumers.length > 0);
27
-
28
25
  return (
29
26
  <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-orange-400')}>
30
27
  <div
@@ -41,8 +38,8 @@ export default function EventNode({ data, sourcePosition, targetPosition }: any)
41
38
  )}
42
39
  </div>
43
40
  <div className="p-1 min-w-60 max-w-[min-content]">
44
- {renderTarget && <Handle type="target" position={targetPosition} />}
45
- {renderSource && <Handle type="source" position={sourcePosition} />}
41
+ {targetPosition && <Handle type="target" position={targetPosition} />}
42
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
46
43
  <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
47
44
  <span className="text-xs font-bold block pb-0.5">{name}</span>
48
45
  <div className="flex justify-between">
@@ -18,7 +18,7 @@ function classNames(...classes: any) {
18
18
  }
19
19
 
20
20
  export default function ExternalSystemNode({ data, sourcePosition, targetPosition }: any) {
21
- const { mode, step, showTarget = true, showSource = true } = data as Data;
21
+ const { mode, step } = data as Data;
22
22
  const { externalSystem } = step;
23
23
  const { name, summary, url } = externalSystem;
24
24
 
@@ -43,8 +43,8 @@ export default function ExternalSystemNode({ data, sourcePosition, targetPositio
43
43
  )}
44
44
  </div>
45
45
  <div className="p-1 min-w-60 max-w-[min-content]">
46
- {showTarget && <Handle type="target" position={targetPosition} />}
47
- {showSource && <Handle type="source" position={sourcePosition} />}
46
+ {targetPosition && <Handle type="target" position={targetPosition} />}
47
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
48
48
  <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
49
49
  <div className="h-full ">
50
50
  <span className="text-sm font-bold pb-0.5 block w-full">{name}</span>
@@ -22,8 +22,8 @@ export default function QueryNode({ data, sourcePosition, targetPosition }: any)
22
22
 
23
23
  const { name, version, summary, owners = [], producers = [], consumers = [] } = message.data;
24
24
 
25
- const renderTarget = showTarget || (targetPosition && producers.length > 0);
26
- const renderSource = showSource || (sourcePosition && consumers.length > 0);
25
+ const renderTarget = true; //showTarget || (targetPosition && producers.length > 0);
26
+ const renderSource = true; // showSource || (sourcePosition && consumers.length > 0);
27
27
 
28
28
  return (
29
29
  <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-green-400')}>
@@ -17,7 +17,7 @@ function classNames(...classes: any) {
17
17
  }
18
18
 
19
19
  export default function ServiceNode({ data, sourcePosition, targetPosition }: any) {
20
- const { label, bgColor = 'bg-blue-500', mode, service, showTarget = true, showSource = true } = data as Data;
20
+ const { label, bgColor = 'bg-blue-500', mode, service } = data as Data;
21
21
 
22
22
  const { version, owners = [], sends = [], receives = [], name } = service.data;
23
23
 
@@ -37,8 +37,8 @@ export default function ServiceNode({ data, sourcePosition, targetPosition }: an
37
37
  )}
38
38
  </div>
39
39
  <div className="p-1 min-w-60 max-w-[min-content]">
40
- {showTarget && <Handle type="target" position={targetPosition} />}
41
- {showSource && <Handle type="source" position={sourcePosition} />}
40
+ {targetPosition && <Handle type="target" position={targetPosition} />}
41
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
42
42
  <div className={classNames(mode === 'full' ? `border-b border-gray-200` : '')}>
43
43
  <span className="text-xs font-bold block pt-0.5 pb-0.5">{name}</span>
44
44
  <div className="flex justify-between">
@@ -16,13 +16,10 @@ function classNames(...classes: any) {
16
16
  }
17
17
 
18
18
  export default function StepNode({ data, sourcePosition, targetPosition }: any) {
19
- const { mode, step, showTarget = true, showSource = true } = data as Data;
19
+ const { mode, step } = data as Data;
20
20
 
21
21
  const { title, summary } = step;
22
22
 
23
- const renderTarget = showTarget || true;
24
- const renderSource = showSource || true;
25
-
26
23
  return (
27
24
  <div className={classNames('w-full rounded-md border flex justify-start bg-white text-black border-blue-400 min-h-[3em]')}>
28
25
  <div
@@ -38,8 +35,8 @@ export default function StepNode({ data, sourcePosition, targetPosition }: any)
38
35
  )}
39
36
  </div>
40
37
  <div className="p-1 min-w-60 max-w-[min-content]">
41
- {renderTarget && <Handle type="target" position={targetPosition} />}
42
- {renderSource && <Handle type="source" position={sourcePosition} />}
38
+ {targetPosition && <Handle type="target" position={targetPosition} />}
39
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
43
40
 
44
41
  {!summary && (
45
42
  <div className="h-full flex items-center">
@@ -21,9 +21,6 @@ export default function UserNode({ data, sourcePosition, targetPosition }: any)
21
21
 
22
22
  const { summary, actor: { name } = {} } = step;
23
23
 
24
- const renderTarget = showTarget || true;
25
- const renderSource = showSource || true;
26
-
27
24
  return (
28
25
  <div
29
26
  className={classNames(
@@ -45,8 +42,8 @@ export default function UserNode({ data, sourcePosition, targetPosition }: any)
45
42
  )}
46
43
  </div>
47
44
  <div className="p-1 min-w-60 max-w-[min-content]">
48
- {renderTarget && <Handle type="target" position={targetPosition} />}
49
- {renderSource && <Handle type="source" position={sourcePosition} />}
45
+ {targetPosition && <Handle type="target" position={targetPosition} />}
46
+ {sourcePosition && <Handle type="source" position={sourcePosition} />}
50
47
 
51
48
  {(!summary || mode !== 'full') && (
52
49
  <div className="h-full ">
@@ -40,10 +40,6 @@ export const Table = ({
40
40
  const [data, _setData] = useState(initialData);
41
41
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
42
42
 
43
- useEffect(() => {
44
- console.log(window.location.pathname);
45
- }, []);
46
-
47
43
  useEffect(() => {
48
44
  const urlParams = new URLSearchParams(window.location.search);
49
45
  const id = urlParams.get('id');
@@ -102,7 +102,7 @@ const tabs = [
102
102
  <!-- Table -->
103
103
  <div class="pb-20 ml-6">
104
104
  <div>
105
- <div class="sm:flex sm:items-center py-4 pb-4">
105
+ <div class="sm:flex sm:items-center py-4 pb-4" id="discover-title">
106
106
  <div class="sm:flex-auto space-y-2">
107
107
  <h1 class="text-4xl font-semibold text-gray-900 capitalize">{title}</h1>
108
108
  <p class="text-md text-gray-700">{subtitle}</p>
@@ -232,7 +232,9 @@ const showSideBarOnLoad = currentNavigationItem?.sidebar;
232
232
  'eventcatalog-header',
233
233
  'eventcatalog-header-spacer',
234
234
  'visualiser-footer',
235
+ // /discover page elements
235
236
  'discover-collection-tabs',
237
+ 'discover-title',
236
238
  ];
237
239
 
238
240
  elementsToHide.forEach((id) => {
@@ -266,8 +268,6 @@ const showSideBarOnLoad = currentNavigationItem?.sidebar;
266
268
 
267
269
  const navItem = navigationItems.find((navItem) => navItem.id === id);
268
270
 
269
- console.log(navItem);
270
-
271
271
  if (!navItem.sidebar || !currentPath.includes(navItem.id)) {
272
272
  window.location.href = navItem.href;
273
273
  return;
@@ -57,3 +57,15 @@ export const getItemsFromCollectionByIdAndSemverOrLatest = <T extends { data: {
57
57
  // latest version
58
58
  return sorted.length > 0 ? [sorted[sorted.length - 1]] : [];
59
59
  };
60
+
61
+ export const findMatchingNodes = (
62
+ nodesA: CollectionEntry<'events' | 'commands' | 'queries' | 'services'>[],
63
+ nodesB: CollectionEntry<'events' | 'commands' | 'queries' | 'services'>[]
64
+ ) => {
65
+ // Track messages that are both sent and received
66
+ return nodesA.filter((nodeA) => {
67
+ return nodesB.some((nodeB) => {
68
+ return nodeB.data.id === nodeA.data.id && nodeB.data.version === nodeA.data.version;
69
+ });
70
+ });
71
+ };
@@ -1,3 +1,4 @@
1
+ import { findMatchingNodes } from '@utils/collections/util';
1
2
  import { getCommands } from '@utils/commands';
2
3
  import { calculatedNodes, createDagreGraph, generateIdForNode, generatedIdForEdge } from '@utils/node-graph-utils/utils';
3
4
  import { type CollectionEntry } from 'astro:content';
@@ -33,6 +34,9 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
33
34
  const producers = (command.data.producers as CollectionEntry<'services'>[]) || [];
34
35
  const consumers = (command.data.consumers as CollectionEntry<'services'>[]) || [];
35
36
 
37
+ // Track nodes that are both sent and received
38
+ const bothSentAndReceived = findMatchingNodes(producers, consumers);
39
+
36
40
  if (producers && producers.length > 0) {
37
41
  producers.forEach((producer, index) => {
38
42
  nodes.push({
@@ -40,7 +44,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
40
44
  type: producer?.collection,
41
45
  sourcePosition: 'right',
42
46
  targetPosition: 'left',
43
- data: { mode, service: producer, showTarget: false },
47
+ data: { mode, service: producer },
44
48
  position: { x: 250, y: 0 },
45
49
  });
46
50
  edges.push({
@@ -67,7 +71,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
67
71
  id: generateIdForNode(command),
68
72
  sourcePosition: 'right',
69
73
  targetPosition: 'left',
70
- data: { mode, message: command, showTarget: producers.length > 0, showSource: consumers.length > 0 },
74
+ data: { mode, message: command },
71
75
  position: { x: 0, y: 0 },
72
76
  type: command.collection,
73
77
  });
@@ -78,7 +82,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
78
82
  id: generateIdForNode(consumer),
79
83
  sourcePosition: 'right',
80
84
  targetPosition: 'left',
81
- data: { title: consumer?.data.id, mode, service: consumer, showSource: false },
85
+ data: { title: consumer?.data.id, mode, service: consumer },
82
86
  position: { x: 0, y: 0 },
83
87
  type: consumer?.collection,
84
88
  });
@@ -100,6 +104,28 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
100
104
  });
101
105
  });
102
106
 
107
+ // Handle nodes that are both sent and received
108
+ bothSentAndReceived.forEach((message) => {
109
+ if (message) {
110
+ edges.push({
111
+ id: generatedIdForEdge(command, message) + '-both',
112
+ source: generateIdForNode(command),
113
+ target: generateIdForNode(message),
114
+ type: 'smoothstep',
115
+ label: `publishes and subscribes`,
116
+ animated: false,
117
+ markerEnd: {
118
+ type: MarkerType.ArrowClosed,
119
+ width: 40,
120
+ height: 40,
121
+ },
122
+ style: {
123
+ strokeWidth: 1,
124
+ },
125
+ });
126
+ }
127
+ });
128
+
103
129
  nodes.forEach((node: any) => {
104
130
  flow.setNode(node.id, { width: 150, height: 100 });
105
131
  });
@@ -4,6 +4,7 @@ import type { CollectionEntry } from 'astro:content';
4
4
  import dagre from 'dagre';
5
5
  import { calculatedNodes, createDagreGraph, generatedIdForEdge, generateIdForNode } from '../node-graph-utils/utils';
6
6
  import { MarkerType } from 'reactflow';
7
+ import { findMatchingNodes } from '@utils/collections/util';
7
8
 
8
9
  type DagreGraph = any;
9
10
 
@@ -34,6 +35,9 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
34
35
  const producers = (event.data.producers as CollectionEntry<'services'>[]) || [];
35
36
  const consumers = (event.data.consumers as CollectionEntry<'services'>[]) || [];
36
37
 
38
+ // Track nodes that are both sent and received
39
+ const bothSentAndReceived = findMatchingNodes(producers, consumers);
40
+
37
41
  if (producers && producers.length > 0) {
38
42
  producers.forEach((producer) => {
39
43
  nodes.push({
@@ -101,6 +105,28 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
101
105
  });
102
106
  });
103
107
 
108
+ // Handle messages that are both sent and received
109
+ bothSentAndReceived.forEach((message) => {
110
+ if (message) {
111
+ edges.push({
112
+ id: generatedIdForEdge(event, message) + '-both',
113
+ source: generateIdForNode(event),
114
+ target: generateIdForNode(message),
115
+ type: 'smoothstep',
116
+ label: `publishes and subscribes`,
117
+ animated: false,
118
+ markerEnd: {
119
+ type: MarkerType.ArrowClosed,
120
+ width: 40,
121
+ height: 40,
122
+ },
123
+ style: {
124
+ strokeWidth: 1,
125
+ },
126
+ });
127
+ }
128
+ });
129
+
104
130
  nodes.forEach((node: any) => {
105
131
  flow.setNode(node.id, { width: 150, height: 100 });
106
132
  });
@@ -3,6 +3,7 @@ import type { CollectionEntry } from 'astro:content';
3
3
  import dagre from 'dagre';
4
4
  import { calculatedNodes, createDagreGraph, generatedIdForEdge, generateIdForNode } from '../node-graph-utils/utils';
5
5
  import { MarkerType } from 'reactflow';
6
+ import { findMatchingNodes } from '@utils/collections/util';
6
7
 
7
8
  type DagreGraph = any;
8
9
 
@@ -33,6 +34,9 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
33
34
  const producers = (query.data.producers as CollectionEntry<'services'>[]) || [];
34
35
  const consumers = (query.data.consumers as CollectionEntry<'services'>[]) || [];
35
36
 
37
+ // Track nodes that are both sent and received
38
+ const bothSentAndReceived = findMatchingNodes(producers, consumers);
39
+
36
40
  if (producers && producers.length > 0) {
37
41
  producers.forEach((producer) => {
38
42
  nodes.push({
@@ -40,7 +44,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
40
44
  type: producer?.collection,
41
45
  sourcePosition: 'right',
42
46
  targetPosition: 'left',
43
- data: { mode, service: producer, showTarget: false },
47
+ data: { mode, service: producer },
44
48
  position: { x: 250, y: 0 },
45
49
  });
46
50
  edges.push({
@@ -67,7 +71,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
67
71
  id: generateIdForNode(query),
68
72
  sourcePosition: 'right',
69
73
  targetPosition: 'left',
70
- data: { mode, message: query, showTarget: producers.length > 0, showSource: consumers.length > 0 },
74
+ data: { mode, message: query },
71
75
  position: { x: 0, y: 0 },
72
76
  type: query.collection,
73
77
  });
@@ -78,7 +82,7 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
78
82
  id: generateIdForNode(consumer),
79
83
  sourcePosition: 'right',
80
84
  targetPosition: 'left',
81
- data: { title: consumer?.data.id, mode, service: consumer, showSource: false },
85
+ data: { title: consumer?.data.id, mode, service: consumer },
82
86
  position: { x: 0, y: 0 },
83
87
  type: consumer?.collection,
84
88
  });
@@ -100,6 +104,28 @@ export const getNodesAndEdges = async ({ id, version, defaultFlow, mode = 'simpl
100
104
  });
101
105
  });
102
106
 
107
+ // Handle nodes that are both sent and received
108
+ bothSentAndReceived.forEach((message) => {
109
+ if (message) {
110
+ edges.push({
111
+ id: generatedIdForEdge(query, message) + '-both',
112
+ source: generateIdForNode(query),
113
+ target: generateIdForNode(message),
114
+ type: 'smoothstep',
115
+ label: `publishes and subscribes`,
116
+ animated: false,
117
+ markerEnd: {
118
+ type: MarkerType.ArrowClosed,
119
+ width: 40,
120
+ height: 40,
121
+ },
122
+ style: {
123
+ strokeWidth: 1,
124
+ },
125
+ });
126
+ }
127
+ });
128
+
103
129
  nodes.forEach((node: any) => {
104
130
  flow.setNode(node.id, { width: 150, height: 100 });
105
131
  });
@@ -1,7 +1,7 @@
1
1
  import { getCollection, type CollectionEntry } from 'astro:content';
2
2
  import dagre from 'dagre';
3
3
  import { createDagreGraph, generateIdForNode, generatedIdForEdge, calculatedNodes } from '@utils/node-graph-utils/utils';
4
- import { getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
4
+ import { findMatchingNodes, getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
5
5
  import { MarkerType } from 'reactflow';
6
6
 
7
7
  type DagreGraph = any;
@@ -78,10 +78,12 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
78
78
  const receives = (receivesHydrated as CollectionEntry<'events' | 'commands' | 'queries'>[]) || [];
79
79
  const sends = (sendsHydrated as CollectionEntry<'events' | 'commands' | 'queries'>[]) || [];
80
80
 
81
- // Get all the data from them
81
+ // Track messages that are both sent and received
82
+ const bothSentAndReceived = findMatchingNodes(receives, sends);
82
83
 
84
+ // Get all the data from them
83
85
  if (receives && receives.length > 0) {
84
- //All the messages the service receives
86
+ // All the messages the service receives
85
87
  receives.forEach((receive, index) => {
86
88
  nodes.push({
87
89
  id: generateIdForNode(receive),
@@ -89,7 +91,7 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
89
91
  sourcePosition: 'right',
90
92
  targetPosition: 'left',
91
93
  data: { mode, message: receive, showTarget: renderAllEdges },
92
- position: { x: 250, y: 0 },
94
+ position: { x: 250, y: index * 100 },
93
95
  });
94
96
  edges.push({
95
97
  id: generatedIdForEdge(receive, service),
@@ -121,13 +123,13 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
121
123
  });
122
124
 
123
125
  // The messages the service sends
124
- sends.forEach((send) => {
126
+ sends.forEach((send, index) => {
125
127
  nodes.push({
126
128
  id: generateIdForNode(send),
127
129
  sourcePosition: 'right',
128
130
  targetPosition: 'left',
129
131
  data: { mode, message: send, showSource: renderAllEdges },
130
- position: { x: 0, y: 0 },
132
+ position: { x: 500, y: index * 100 },
131
133
  type: send?.collection,
132
134
  });
133
135
  edges.push({
@@ -148,6 +150,28 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
148
150
  });
149
151
  });
150
152
 
153
+ // Handle messages that are both sent and received
154
+ bothSentAndReceived.forEach((message) => {
155
+ if (message) {
156
+ edges.push({
157
+ id: generatedIdForEdge(service, message) + '-both',
158
+ source: generateIdForNode(service),
159
+ target: generateIdForNode(message),
160
+ type: 'smoothstep',
161
+ label: `${getSendsMessageByMessageType(message?.collection)} & ${getReceivesMessageByMessageType(message?.collection)}`,
162
+ animated: false,
163
+ markerEnd: {
164
+ type: MarkerType.ArrowClosed,
165
+ width: 40,
166
+ height: 40,
167
+ },
168
+ style: {
169
+ strokeWidth: 1,
170
+ },
171
+ });
172
+ }
173
+ });
174
+
151
175
  nodes.forEach((node: any) => {
152
176
  flow.setNode(node.id, { width: 150, height: 100 });
153
177
  });
@@ -156,7 +180,7 @@ export const getNodesAndEdges = async ({ id, defaultFlow, version, mode = 'simpl
156
180
  flow.setEdge(edge.source, edge.target);
157
181
  });
158
182
 
159
- // Render the diagram in memory getting hte X and Y
183
+ // Render the diagram in memory getting the X and Y
160
184
  dagre.layout(flow);
161
185
 
162
186
  return {