@eventcatalog/core 2.11.7 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/bin/dist/eventcatalog.config.d.cts +3 -0
- package/bin/dist/eventcatalog.config.d.ts +3 -0
- package/bin/eventcatalog.config.ts +3 -0
- package/package.json +2 -2
- package/src/components/MDX/NodeGraph/NodeGraph.tsx +13 -2
- package/src/components/MDX/NodeGraph/Nodes/Command.tsx +3 -6
- package/src/components/MDX/NodeGraph/Nodes/Event.tsx +3 -6
- package/src/components/MDX/NodeGraph/Nodes/ExternalSystem.tsx +3 -3
- package/src/components/MDX/NodeGraph/Nodes/Query.tsx +2 -2
- package/src/components/MDX/NodeGraph/Nodes/Service.tsx +3 -3
- package/src/components/MDX/NodeGraph/Nodes/Step.tsx +3 -6
- package/src/components/MDX/NodeGraph/Nodes/User.tsx +2 -5
- package/src/components/SideBars/DomainSideBar.astro +1 -1
- package/src/components/SideBars/MessageSideBar.astro +1 -1
- package/src/components/SideBars/ServiceSideBar.astro +1 -1
- package/src/components/Tables/Table.tsx +0 -4
- package/src/layouts/VerticalSideBarLayout.astro +0 -2
- package/src/pages/docs/[type]/[id]/[version]/asyncapi/index.astro +4 -3
- package/src/utils/collections/util.ts +12 -0
- package/src/utils/commands/node-graph.ts +29 -3
- package/src/utils/events/node-graph.ts +26 -0
- package/src/utils/queries/node-graph.ts +29 -3
- package/src/utils/services/node-graph.ts +31 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @eventcatalog/core
|
|
2
2
|
|
|
3
|
+
## 2.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a57282e: fix(core): new property for AsyncAPI rendering
|
|
8
|
+
- d739d7b: fix(core): changelog buttons now render the correct changelog
|
|
9
|
+
|
|
10
|
+
## 2.12.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- a136d50: feat(core): services can now send and receive the same messages in vis…
|
|
15
|
+
|
|
3
16
|
## 2.11.7
|
|
4
17
|
|
|
5
18
|
### 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.
|
|
9
|
+
"version": "2.12.1",
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@astrojs/mdx": "^3.1.8",
|
|
42
42
|
"@astrojs/react": "^3.6.2",
|
|
43
43
|
"@astrojs/tailwind": "^5.1.2",
|
|
44
|
-
"@asyncapi/react-component": "^2.
|
|
44
|
+
"@asyncapi/react-component": "^2.4.3",
|
|
45
45
|
"@headlessui/react": "^2.0.3",
|
|
46
46
|
"@heroicons/react": "^2.1.3",
|
|
47
47
|
"@parcel/watcher": "^2.4.1",
|
|
@@ -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 {
|
|
111
|
+
return {
|
|
112
|
+
...edge,
|
|
113
|
+
style: { ...edge.style, opacity: 1 },
|
|
114
|
+
labelStyle: { ...edge.labelStyle, opacity: 1 },
|
|
115
|
+
animated: true,
|
|
116
|
+
};
|
|
111
117
|
}
|
|
112
|
-
return {
|
|
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
|
|
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
|
-
{
|
|
45
|
-
{
|
|
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
|
|
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
|
-
{
|
|
45
|
-
{
|
|
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
|
|
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
|
-
{
|
|
47
|
-
{
|
|
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
|
|
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
|
-
{
|
|
41
|
-
{
|
|
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
|
|
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
|
-
{
|
|
42
|
-
{
|
|
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
|
-
{
|
|
49
|
-
{
|
|
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 ">
|
|
@@ -66,7 +66,7 @@ const ownersList = owners.map((o) => ({
|
|
|
66
66
|
<span class="block">View in visualiser</span>
|
|
67
67
|
</a>
|
|
68
68
|
<a
|
|
69
|
-
href={buildUrl(`/docs/${domain.collection}/${domain.data.id}/${domain.data.
|
|
69
|
+
href={buildUrl(`/docs/${domain.collection}/${domain.data.id}/${domain.data.latestVersion}/changelog`)}
|
|
70
70
|
class="flex items-center space-x-2 justify-center text-center rounded-md w-full bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-100/60 hover:text-primary"
|
|
71
71
|
>
|
|
72
72
|
<ScrollText strokeWidth={2} size={16} />
|
|
@@ -151,7 +151,7 @@ const schemaURL = path.join(publicPath, schemaFilePath || '');
|
|
|
151
151
|
</a>
|
|
152
152
|
|
|
153
153
|
<a
|
|
154
|
-
href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.
|
|
154
|
+
href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.latestVersion}/changelog`)}
|
|
155
155
|
class="flex items-center space-x-2 justify-center text-center rounded-md w-full bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-100/60 hover:text-primary"
|
|
156
156
|
>
|
|
157
157
|
<ScrollText strokeWidth={2} size={16} />
|
|
@@ -107,7 +107,7 @@ const schemaURL = join(publicPath, schemaFilePath || '');
|
|
|
107
107
|
<span class="block">View in visualiser</span>
|
|
108
108
|
</a>
|
|
109
109
|
<a
|
|
110
|
-
href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.
|
|
110
|
+
href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.latestVersion}/changelog`)}
|
|
111
111
|
class="flex items-center space-x-2 justify-center text-center rounded-md w-full bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-100/60 hover:text-primary"
|
|
112
112
|
>
|
|
113
113
|
<ScrollText strokeWidth={2} size={16} />
|
|
@@ -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');
|
|
@@ -268,8 +268,6 @@ const showSideBarOnLoad = currentNavigationItem?.sidebar;
|
|
|
268
268
|
|
|
269
269
|
const navItem = navigationItems.find((navItem) => navItem.id === id);
|
|
270
270
|
|
|
271
|
-
console.log(navItem);
|
|
272
|
-
|
|
273
271
|
if (!navItem.sidebar || !currentPath.includes(navItem.id)) {
|
|
274
272
|
window.location.href = navItem.href;
|
|
275
273
|
return;
|
|
@@ -7,14 +7,13 @@ import { Parser } from '@asyncapi/parser';
|
|
|
7
7
|
|
|
8
8
|
import type { CollectionTypes, PageTypes } from '@types';
|
|
9
9
|
|
|
10
|
-
import PlainPage from '@layouts/PlainPage.astro';
|
|
11
|
-
|
|
12
10
|
import '@asyncapi/react-component/styles/default.min.css';
|
|
13
11
|
import js from '@asyncapi/react-component/browser/standalone/without-parser.js?url';
|
|
14
12
|
import { AsyncApiComponentWP, type ConfigInterface } from '@asyncapi/react-component';
|
|
15
13
|
import { pageDataLoader } from '@utils/pages/pages';
|
|
16
14
|
import type { CollectionEntry } from 'astro:content';
|
|
17
15
|
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
16
|
+
import Config from '@eventcatalog';
|
|
18
17
|
|
|
19
18
|
export async function getStaticPaths() {
|
|
20
19
|
const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains'];
|
|
@@ -45,7 +44,9 @@ const pathToSpec = path.join(catalog.publicPath, fileName);
|
|
|
45
44
|
const pathOnDisk = path.join(process.cwd(), 'public', pathToSpec);
|
|
46
45
|
const fileContent = readFileSync(pathOnDisk, 'utf-8');
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
// AsyncAPI parser will parser schemas for users, they can turn this off.
|
|
48
|
+
const parseSchemas = Config?.asyncAPI?.renderParsedSchemas ?? true;
|
|
49
|
+
const parsed = await new Parser().parse(fileContent, { parseSchemas });
|
|
49
50
|
const stringified = parsed.document?.json();
|
|
50
51
|
const config: ConfigInterface = { show: { sidebar: true, errors: true } };
|
|
51
52
|
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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:
|
|
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:
|
|
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
|
|
183
|
+
// Render the diagram in memory getting the X and Y
|
|
160
184
|
dagre.layout(flow);
|
|
161
185
|
|
|
162
186
|
return {
|