-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
flowGenerator.ts
114 lines (99 loc) · 4.16 KB
/
flowGenerator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { AsyncAPIDocument, Channel, Operation, Message } from '@asyncapi/parser';
import { Edge, Node } from 'reactflow';
import { connect } from 'mqtt';
interface FileredChannel {
channel: string;
channelModel: Channel;
operationModel: Operation;
messagesModel: Message[];
}
function createMqttClient() {
const client = connect('mqtt://localhost:1883', {
manualConnect: true,
});
return client;
}
//given the operation publish/subscribe we will extract the channels realted to it from the spec
function getChannelsByOperation(operation: string, spec: AsyncAPIDocument) {
const channels = spec.channels();
return Object.keys(channels).reduce((filteredChannels: FileredChannel[], channel) => {
const operationFn = operation === 'publish' ? 'hasPublish' : 'hasSubscribe';
// eslint-disable-next-line
if (channels[String(channel)][operationFn]()) {
const operationModel = (channels as any)[String(channel)][String(operation)]() as OldOperation;
filteredChannels.push({
channel,
channelModel: channels[String(channel)],
operationModel,
messagesModel: operationModel.messages(),
});
}
return filteredChannels;
}, []);
}
function buildFlowElementsForOperation({ operation, spec, applicationLinkType, data }: { operation: 'publish' | 'subscribe'; spec: AsyncAPIDocument; applicationLinkType: string, data: any }): Array<{ node: Node, edge: Edge }> {
return getChannelsByOperation(operation, spec).reduce((nodes: any, channel) => {
const { channelModel, operationModel, messagesModel } = channel;
const mqttClient = createMqttClient();
const node: Node = {
id: `${operation}-${channel.channel}`,
type: `${operation}Node`,
data: {
title: operationModel.id(),
channel: channel.channel,
tags: operationModel.tags(),
messages: messagesModel.map((message) => ({
title: message.uid(),
description: message.description(),
})),
autoClient: mqttClient,
spec,
description: channelModel.description(),
operationId: operationModel.id(),
elementType: operation,
theme: operation === 'subscribe' ? 'green' : 'blue',
...data
},
position: { x: 0, y: 0 },
};
const edge: Edge = {
id: `${operation}-${channel.channel}-to-application`,
// type: 'smoothstep',
animated: true,
label: messagesModel.map(message => message.uid()).join(','),
style: { stroke: applicationLinkType === 'target' ? '#00A5FA' : '#7ee3be', strokeWidth: 4 },
source: applicationLinkType === 'target' ? `${operation}-${channel.channel}` : 'application',
target: applicationLinkType === 'target' ? 'application' : `${operation}-${channel.channel}`,
};
return [...nodes, { node, edge }];
}, []);
}
//this will be the entry point of the node creation where we will us the specs to create the application, the publish and the subscribe nodes
export function generateFromSpecs(spec: AsyncAPIDocument): Array<{node:Node, edge:Edge}>{
//here we will use the publish operation to generate the nodes and edges for the publish section col-1
const publishNodes = buildFlowElementsForOperation({
operation: 'publish',
spec,
applicationLinkType: 'target',
data: { columnToRenderIn: 'col-1' },
});
//here we will use the subscribe operation to generate the nodes and edges for subscribe section col-3
const subscribeNodes = buildFlowElementsForOperation({
operation: 'subscribe',
spec,
applicationLinkType: 'source',
data: { columnToRenderIn: 'col-3' },
});
//here we will build the application node which will lie in the center of the canvas
const applicationNode = {
id: 'application',
type: 'applicationNode',
data: { spec, elementType: 'application', theme: 'indigo', columnToRenderIn: 'col-2' },
position: { x: 0, y: 0 },
}
return [
...publishNodes,
{ node: applicationNode } as { node: Node, edge: Edge },
...subscribeNodes
];
}