@eventcatalog/visualiser 5.0.0-beta.5 → 5.0.0-beta.7
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/chunk-Q3OM5AL5.mjs +1 -0
- package/dist/chunk-Q3OM5AL5.mjs.map +1 -0
- package/dist/chunk-R3QHQ7LF.mjs +427 -0
- package/dist/chunk-R3QHQ7LF.mjs.map +1 -0
- package/dist/chunk-Y2IJ5XR6.mjs +15705 -0
- package/dist/chunk-Y2IJ5XR6.mjs.map +1 -0
- package/dist/chunk-Z3G354GF.mjs +464 -0
- package/dist/chunk-Z3G354GF.mjs.map +1 -0
- package/dist/fonts/Excalifont-Regular.woff2 +0 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/fonts/README.md +2 -0
- package/dist/index.js +749 -719
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +104 -16003
- package/dist/index.mjs.map +1 -1
- package/dist/layout.mjs +10 -374
- package/dist/layout.mjs.map +1 -1
- package/dist/model.d.mts +18 -0
- package/dist/model.mjs +51 -0
- package/dist/model.mjs.map +1 -0
- package/dist/schema-DKA0EQ_H.d.mts +484 -0
- package/dist/studio-fonts.css +10 -0
- package/dist/studio.css +509 -0
- package/dist/studio.d.mts +1312 -0
- package/dist/studio.mjs +6719 -0
- package/dist/studio.mjs.map +1 -0
- package/dist/styles-core.css +580 -0
- package/dist/styles.css +580 -0
- package/package.json +26 -8
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
// src/nodes/node-types.ts
|
|
2
|
+
var SERVICE = ["service", "services"];
|
|
3
|
+
var AGENT = ["agent", "agents"];
|
|
4
|
+
var AGENT_TOOL = ["agentTool", "agent-tool"];
|
|
5
|
+
var EVENT = ["event", "events"];
|
|
6
|
+
var QUERY = ["queries", "query", "querie"];
|
|
7
|
+
var COMMAND = ["command", "commands"];
|
|
8
|
+
var CHANNEL = ["channel", "channels"];
|
|
9
|
+
var ACTOR = ["actor", "actors"];
|
|
10
|
+
var DATA = ["data"];
|
|
11
|
+
var VIEW = ["view"];
|
|
12
|
+
var MESSAGE = [...EVENT, ...COMMAND, ...QUERY];
|
|
13
|
+
|
|
14
|
+
// src/utils/utils/utils.ts
|
|
15
|
+
import { MarkerType, Position } from "@xyflow/react";
|
|
16
|
+
var generateIdForNode = (node) => {
|
|
17
|
+
return `${node.data.id}-${node.data.version}`;
|
|
18
|
+
};
|
|
19
|
+
var generateIdForNodes = (nodes) => {
|
|
20
|
+
return nodes.map((node) => `${node.data.id}-${node.data.version}`).join("-");
|
|
21
|
+
};
|
|
22
|
+
var generatedIdForEdge = (source, target) => {
|
|
23
|
+
return `${source.data.id}-${source.data.version}-${target.data.id}-${target.data.version}`;
|
|
24
|
+
};
|
|
25
|
+
var getColorFromString = (id) => {
|
|
26
|
+
let hash = 0;
|
|
27
|
+
for (let i = 0; i < id.length; i++) {
|
|
28
|
+
hash = id.charCodeAt(i) + ((hash << 5) - hash);
|
|
29
|
+
}
|
|
30
|
+
let color = "#";
|
|
31
|
+
for (let i = 0; i < 3; i++) {
|
|
32
|
+
const value = hash >> i * 8 & 255;
|
|
33
|
+
color += value.toString(16).padStart(2, "0");
|
|
34
|
+
}
|
|
35
|
+
return color;
|
|
36
|
+
};
|
|
37
|
+
var getEdgeLabelForServiceAsTarget = (data) => {
|
|
38
|
+
const type = data.collection;
|
|
39
|
+
switch (type) {
|
|
40
|
+
case "commands":
|
|
41
|
+
return "invokes";
|
|
42
|
+
case "events":
|
|
43
|
+
return "publishes \nevent";
|
|
44
|
+
case "queries":
|
|
45
|
+
return "requests";
|
|
46
|
+
default:
|
|
47
|
+
return "sends to";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var getEdgeLabelForMessageAsSource = (data, throughChannel = false) => {
|
|
51
|
+
const type = data.collection;
|
|
52
|
+
switch (type) {
|
|
53
|
+
case "commands":
|
|
54
|
+
return "accepts";
|
|
55
|
+
case "events":
|
|
56
|
+
return throughChannel ? "subscribed to" : "subscribed by";
|
|
57
|
+
case "queries":
|
|
58
|
+
return "accepts";
|
|
59
|
+
default:
|
|
60
|
+
return "sends to";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var getEdgeLabelSize = (label) => {
|
|
64
|
+
if (typeof label !== "string" || !label.trim())
|
|
65
|
+
return { width: 0, height: 0 };
|
|
66
|
+
const lines = label.split("\n");
|
|
67
|
+
const longestLine = Math.max(...lines.map((line) => line.trim().length));
|
|
68
|
+
return { width: longestLine * 6 + 20, height: lines.length * 14 + 12 };
|
|
69
|
+
};
|
|
70
|
+
var createEdge = (edgeOptions) => {
|
|
71
|
+
return {
|
|
72
|
+
label: "subscribed by",
|
|
73
|
+
animated: false,
|
|
74
|
+
// markerStart: {
|
|
75
|
+
// type: MarkerType.Arrow,
|
|
76
|
+
// width: 40,
|
|
77
|
+
// height: 40,
|
|
78
|
+
// },
|
|
79
|
+
markerEnd: {
|
|
80
|
+
type: MarkerType.ArrowClosed,
|
|
81
|
+
width: 40,
|
|
82
|
+
height: 40,
|
|
83
|
+
color: "rgb(var(--ec-page-text-muted))"
|
|
84
|
+
},
|
|
85
|
+
style: {
|
|
86
|
+
strokeWidth: 1.5,
|
|
87
|
+
stroke: "rgb(var(--ec-page-text-muted))",
|
|
88
|
+
strokeDasharray: "5 5"
|
|
89
|
+
},
|
|
90
|
+
...edgeOptions
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
var createNode = (values) => {
|
|
94
|
+
return {
|
|
95
|
+
sourcePosition: Position.Right,
|
|
96
|
+
targetPosition: Position.Left,
|
|
97
|
+
...values
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/utils/elk-layout.ts
|
|
102
|
+
var DEFAULT_SIZE = { width: 240, height: 112 };
|
|
103
|
+
var NODE_SIZES = {
|
|
104
|
+
events: { width: 240, height: 104 },
|
|
105
|
+
commands: { width: 240, height: 126 },
|
|
106
|
+
queries: { width: 240, height: 126 },
|
|
107
|
+
services: { width: 240, height: 112 },
|
|
108
|
+
data: { width: 240, height: 108 },
|
|
109
|
+
systems: { width: 240, height: 120 },
|
|
110
|
+
system: { width: 240, height: 120 },
|
|
111
|
+
"context-domain": { width: 240, height: 112 },
|
|
112
|
+
"context-actor": { width: 180, height: 80 },
|
|
113
|
+
actor: { width: 180, height: 80 },
|
|
114
|
+
note: { width: 200, height: 150 },
|
|
115
|
+
step: { width: 240, height: 80 },
|
|
116
|
+
// Groups with nothing in them (groups with children are sized to fit them)
|
|
117
|
+
"domain-group": { width: 320, height: 160 },
|
|
118
|
+
"system-group": { width: 320, height: 160 }
|
|
119
|
+
};
|
|
120
|
+
var GROUP_TYPES = /* @__PURE__ */ new Set(["domain-group", "system-group", "group"]);
|
|
121
|
+
var getNodeSize = (node) => {
|
|
122
|
+
if (node.measured?.width && node.measured?.height) {
|
|
123
|
+
return { width: node.measured.width, height: node.measured.height };
|
|
124
|
+
}
|
|
125
|
+
if (typeof node.width === "number" && typeof node.height === "number") {
|
|
126
|
+
return { width: node.width, height: node.height };
|
|
127
|
+
}
|
|
128
|
+
if (node.type === "domains" || node.type === "domain") {
|
|
129
|
+
const services = node.data?.domain?.data?.services || [];
|
|
130
|
+
return { width: 260, height: 60 + services.length * 40 };
|
|
131
|
+
}
|
|
132
|
+
return NODE_SIZES[node.type || ""] ?? DEFAULT_SIZE;
|
|
133
|
+
};
|
|
134
|
+
var GROUP_PADDING = "[top=100,left=40,bottom=40,right=40]";
|
|
135
|
+
var SPACING = {
|
|
136
|
+
"elk.layered.spacing.nodeNodeBetweenLayers": "60",
|
|
137
|
+
"elk.spacing.nodeNode": "40",
|
|
138
|
+
"elk.spacing.edgeNode": "25",
|
|
139
|
+
"elk.spacing.edgeEdge": "15"
|
|
140
|
+
};
|
|
141
|
+
var LARGE_GRAPH_NODES = 80;
|
|
142
|
+
var LARGE_GRAPH_EDGES = 200;
|
|
143
|
+
var LARGE_GRAPH_OPTIONS = {
|
|
144
|
+
"elk.layered.nodePlacement.strategy": "BRANDES_KOEPF",
|
|
145
|
+
"elk.layered.thoroughness": "1",
|
|
146
|
+
"elk.layered.crossingMinimization.greedySwitch.type": "OFF"
|
|
147
|
+
};
|
|
148
|
+
var elk;
|
|
149
|
+
var getElk = async () => {
|
|
150
|
+
if (!elk) {
|
|
151
|
+
const { default: ELK } = await import("elkjs/lib/elk.bundled.js");
|
|
152
|
+
elk = new ELK();
|
|
153
|
+
}
|
|
154
|
+
return elk;
|
|
155
|
+
};
|
|
156
|
+
var layoutWithElk = async ({ nodes, edges }, { sizeOf = getNodeSize } = {}) => {
|
|
157
|
+
const nodesById = new Map(nodes.map((node) => [node.id, node]));
|
|
158
|
+
const groupIds = new Set(
|
|
159
|
+
nodes.map((node) => node.parentId).filter((id) => !!id && nodesById.has(id))
|
|
160
|
+
);
|
|
161
|
+
const parentOf = (node) => node.parentId && groupIds.has(node.parentId) ? node.parentId : void 0;
|
|
162
|
+
const layoutEdges = edges.filter(
|
|
163
|
+
(edge) => nodesById.has(edge.source) && nodesById.has(edge.target)
|
|
164
|
+
);
|
|
165
|
+
const ports = /* @__PURE__ */ new Map();
|
|
166
|
+
const addPort = (nodeId, id, side) => {
|
|
167
|
+
const nodePorts = ports.get(nodeId) || [];
|
|
168
|
+
if (!nodePorts.some((port) => port.id === id)) {
|
|
169
|
+
ports.set(nodeId, [
|
|
170
|
+
...nodePorts,
|
|
171
|
+
{ id, layoutOptions: { "elk.port.side": side } }
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
return id;
|
|
175
|
+
};
|
|
176
|
+
const edgePorts = layoutEdges.map((edge, index) => ({
|
|
177
|
+
source: addPort(
|
|
178
|
+
edge.source,
|
|
179
|
+
edge.sourceHandle ? `${edge.source}__${edge.sourceHandle}` : `e${index}__out`,
|
|
180
|
+
"EAST"
|
|
181
|
+
),
|
|
182
|
+
target: addPort(
|
|
183
|
+
edge.target,
|
|
184
|
+
edge.targetHandle ? `${edge.target}__${edge.targetHandle}` : `e${index}__in`,
|
|
185
|
+
"WEST"
|
|
186
|
+
)
|
|
187
|
+
}));
|
|
188
|
+
const toElkNode = (node) => ({
|
|
189
|
+
id: node.id,
|
|
190
|
+
...groupIds.has(node.id) ? {
|
|
191
|
+
children: nodes.filter((child) => parentOf(child) === node.id).map(toElkNode)
|
|
192
|
+
} : sizeOf(node),
|
|
193
|
+
layoutOptions: {
|
|
194
|
+
"elk.portConstraints": "FIXED_SIDE",
|
|
195
|
+
...groupIds.has(node.id) ? { "elk.padding": GROUP_PADDING, ...SPACING } : {},
|
|
196
|
+
// A node's own options (e.g. a group's padding) win
|
|
197
|
+
...node.data?.layoutOptions ?? {}
|
|
198
|
+
},
|
|
199
|
+
ports: ports.get(node.id) || []
|
|
200
|
+
});
|
|
201
|
+
const layout = await (await getElk()).layout({
|
|
202
|
+
id: "root",
|
|
203
|
+
layoutOptions: {
|
|
204
|
+
"elk.algorithm": "layered",
|
|
205
|
+
"elk.direction": "RIGHT",
|
|
206
|
+
"elk.hierarchyHandling": "INCLUDE_CHILDREN",
|
|
207
|
+
"elk.edgeRouting": "ORTHOGONAL",
|
|
208
|
+
// Edge routes in absolute coordinates (node positions stay relative to their parent)
|
|
209
|
+
"elk.json.edgeCoords": "ROOT",
|
|
210
|
+
"elk.edgeLabels.placement": "CENTER",
|
|
211
|
+
...SPACING,
|
|
212
|
+
...nodes.length >= LARGE_GRAPH_NODES || edges.length >= LARGE_GRAPH_EDGES ? LARGE_GRAPH_OPTIONS : { "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX" }
|
|
213
|
+
},
|
|
214
|
+
children: nodes.filter((node) => !parentOf(node)).map(toElkNode),
|
|
215
|
+
edges: layoutEdges.map((edge, index) => ({
|
|
216
|
+
id: `e${index}`,
|
|
217
|
+
sources: [edgePorts[index].source],
|
|
218
|
+
targets: [edgePorts[index].target],
|
|
219
|
+
// Labels sit on their edge, rather than beside it (only works set per label)
|
|
220
|
+
labels: edge.label ? [
|
|
221
|
+
{
|
|
222
|
+
text: String(edge.label),
|
|
223
|
+
...getEdgeLabelSize(edge.label),
|
|
224
|
+
layoutOptions: { "elk.edgeLabels.inline": "true" }
|
|
225
|
+
}
|
|
226
|
+
] : []
|
|
227
|
+
}))
|
|
228
|
+
});
|
|
229
|
+
const laidOut = /* @__PURE__ */ new Map();
|
|
230
|
+
const collect = (elkNode) => (elkNode.children || []).forEach((child) => {
|
|
231
|
+
laidOut.set(child.id, child);
|
|
232
|
+
collect(child);
|
|
233
|
+
});
|
|
234
|
+
collect(layout);
|
|
235
|
+
const absolute = (nodeId) => {
|
|
236
|
+
const node = nodesById.get(nodeId);
|
|
237
|
+
const parent = node && parentOf(node);
|
|
238
|
+
const offset = parent ? absolute(parent) : { x: 0, y: 0 };
|
|
239
|
+
const elkNode = laidOut.get(nodeId);
|
|
240
|
+
return { x: offset.x + (elkNode?.x ?? 0), y: offset.y + (elkNode?.y ?? 0) };
|
|
241
|
+
};
|
|
242
|
+
const routes = /* @__PURE__ */ new Map();
|
|
243
|
+
(layout.edges || []).forEach((elkEdge) => {
|
|
244
|
+
const section = elkEdge.sections?.[0];
|
|
245
|
+
if (!section) return;
|
|
246
|
+
const label = elkEdge.labels?.[0];
|
|
247
|
+
const edge = layoutEdges[Number(elkEdge.id.slice(1))];
|
|
248
|
+
routes.set(edge, {
|
|
249
|
+
points: [
|
|
250
|
+
section.startPoint,
|
|
251
|
+
...section.bendPoints || [],
|
|
252
|
+
section.endPoint
|
|
253
|
+
],
|
|
254
|
+
label: label ? {
|
|
255
|
+
x: (label.x ?? 0) + (label.width ?? 0) / 2,
|
|
256
|
+
y: (label.y ?? 0) + (label.height ?? 0) / 2
|
|
257
|
+
} : void 0,
|
|
258
|
+
source: absolute(edge.source),
|
|
259
|
+
target: absolute(edge.target)
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
const depth = (node) => {
|
|
263
|
+
const parent = node && parentOf(node);
|
|
264
|
+
return parent ? depth(nodesById.get(parent)) + 1 : 0;
|
|
265
|
+
};
|
|
266
|
+
return {
|
|
267
|
+
// Parents must come before their children in the array for React Flow
|
|
268
|
+
nodes: [...nodes].sort((a, b) => depth(a) - depth(b)).map((node) => {
|
|
269
|
+
const elkNode = laidOut.get(node.id);
|
|
270
|
+
if (!elkNode) return node;
|
|
271
|
+
return {
|
|
272
|
+
...node,
|
|
273
|
+
origin: [0, 0],
|
|
274
|
+
position: { x: elkNode.x ?? 0, y: elkNode.y ?? 0 },
|
|
275
|
+
...groupIds.has(node.id) || GROUP_TYPES.has(node.type || "") && typeof node.style?.width !== "number" ? {
|
|
276
|
+
style: {
|
|
277
|
+
...node.style,
|
|
278
|
+
width: elkNode.width,
|
|
279
|
+
height: elkNode.height
|
|
280
|
+
},
|
|
281
|
+
// Re-measured at its new size
|
|
282
|
+
measured: void 0
|
|
283
|
+
} : {}
|
|
284
|
+
};
|
|
285
|
+
}),
|
|
286
|
+
edges: edges.map((edge) => {
|
|
287
|
+
const route = routes.get(edge);
|
|
288
|
+
return route ? { ...edge, data: { ...edge.data, route } } : edge;
|
|
289
|
+
})
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// src/utils/hide-messages.ts
|
|
294
|
+
import { MarkerType as MarkerType2 } from "@xyflow/react";
|
|
295
|
+
var MESSAGE_NODE_TYPES = [...MESSAGE, "messageGroup", "messageGroupExpanded"];
|
|
296
|
+
var isMessageNode = (node) => MESSAGE_NODE_TYPES.includes(node.type || "");
|
|
297
|
+
var getCollection = (type = "") => {
|
|
298
|
+
if (EVENT.includes(type)) return "events";
|
|
299
|
+
if (COMMAND.includes(type)) return "commands";
|
|
300
|
+
if (QUERY.includes(type)) return "queries";
|
|
301
|
+
return "messages";
|
|
302
|
+
};
|
|
303
|
+
var getMessages = (node) => {
|
|
304
|
+
const data = node.data;
|
|
305
|
+
if (node.type === "messageGroup") {
|
|
306
|
+
return (data?.messages || []).map(({ message: message2 }) => [
|
|
307
|
+
message2?.data?.name || message2?.data?.id,
|
|
308
|
+
getCollection(message2?.collection)
|
|
309
|
+
]);
|
|
310
|
+
}
|
|
311
|
+
const message = data?.message;
|
|
312
|
+
return message ? [[message.name || message.id, getCollection(node.type)]] : [];
|
|
313
|
+
};
|
|
314
|
+
var VERBS = {
|
|
315
|
+
events: "publishes",
|
|
316
|
+
commands: "invokes",
|
|
317
|
+
queries: "requests"
|
|
318
|
+
};
|
|
319
|
+
var getMessagesLabel = (messages) => {
|
|
320
|
+
if (messages.size === 0) return void 0;
|
|
321
|
+
const collections = new Set(messages.values());
|
|
322
|
+
const collection = collections.size === 1 ? Array.from(collections)[0] : "messages";
|
|
323
|
+
const verb = VERBS[collection] || "sends";
|
|
324
|
+
const sent = messages.size === 1 ? Array.from(messages.keys())[0] : `${messages.size} ${collection}`;
|
|
325
|
+
return `${verb}
|
|
326
|
+
${sent}`;
|
|
327
|
+
};
|
|
328
|
+
var isCarrier = (node) => isMessageNode(node) || node.type === "channels";
|
|
329
|
+
var isCrossDomain = (edge) => !!edge.data?.crossDomain;
|
|
330
|
+
var getRoute = (edge) => edge.data?.route;
|
|
331
|
+
var joinRoutes = (routes) => {
|
|
332
|
+
if (!routes.every((route) => route && route.points.length > 0)) return;
|
|
333
|
+
const laidOut = routes;
|
|
334
|
+
const arrives = laidOut[0].points[laidOut[0].points.length - 1];
|
|
335
|
+
const leaves = laidOut[1].points[0];
|
|
336
|
+
return {
|
|
337
|
+
points: laidOut.flatMap((route) => route.points),
|
|
338
|
+
label: { x: (arrives.x + leaves.x) / 2, y: (arrives.y + leaves.y) / 2 },
|
|
339
|
+
source: laidOut[0].source,
|
|
340
|
+
target: laidOut[laidOut.length - 1].target
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
var hideNodes = (nodes, edges, isHidden) => {
|
|
344
|
+
const hiddenNodes = new Map(
|
|
345
|
+
nodes.filter(isHidden).map((node) => [node.id, node])
|
|
346
|
+
);
|
|
347
|
+
if (hiddenNodes.size === 0) return { nodes, edges };
|
|
348
|
+
const outgoingEdges = /* @__PURE__ */ new Map();
|
|
349
|
+
for (const edge of edges) {
|
|
350
|
+
const outgoing = outgoingEdges.get(edge.source) || [];
|
|
351
|
+
outgoing.push(edge);
|
|
352
|
+
outgoingEdges.set(edge.source, outgoing);
|
|
353
|
+
}
|
|
354
|
+
const keptEdges = [];
|
|
355
|
+
const bridgedEdges = /* @__PURE__ */ new Map();
|
|
356
|
+
for (const edge of edges) {
|
|
357
|
+
if (hiddenNodes.has(edge.source)) continue;
|
|
358
|
+
const target = hiddenNodes.get(edge.target);
|
|
359
|
+
if (!target) {
|
|
360
|
+
keptEdges.push(edge);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (!isCarrier(target)) continue;
|
|
364
|
+
const stack = [
|
|
365
|
+
{
|
|
366
|
+
id: edge.target,
|
|
367
|
+
messages: [],
|
|
368
|
+
routes: [getRoute(edge)],
|
|
369
|
+
crossDomain: isCrossDomain(edge)
|
|
370
|
+
}
|
|
371
|
+
];
|
|
372
|
+
const visited = /* @__PURE__ */ new Set();
|
|
373
|
+
while (stack.length > 0) {
|
|
374
|
+
const current = stack.pop();
|
|
375
|
+
if (visited.has(current.id)) continue;
|
|
376
|
+
visited.add(current.id);
|
|
377
|
+
const messages = [
|
|
378
|
+
...current.messages,
|
|
379
|
+
...getMessages(hiddenNodes.get(current.id))
|
|
380
|
+
];
|
|
381
|
+
for (const next of outgoingEdges.get(current.id) || []) {
|
|
382
|
+
const routes = [...current.routes, getRoute(next)];
|
|
383
|
+
const crossDomain = current.crossDomain || isCrossDomain(next);
|
|
384
|
+
const nextNode = hiddenNodes.get(next.target);
|
|
385
|
+
if (nextNode) {
|
|
386
|
+
if (isCarrier(nextNode))
|
|
387
|
+
stack.push({ id: next.target, messages, routes, crossDomain });
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (next.target === edge.source) continue;
|
|
391
|
+
const id = `bridged-${edge.source}-${next.target}`;
|
|
392
|
+
const bridged = bridgedEdges.get(id) || {
|
|
393
|
+
source: edge.source,
|
|
394
|
+
target: next.target,
|
|
395
|
+
messages: /* @__PURE__ */ new Map(),
|
|
396
|
+
route: joinRoutes(routes),
|
|
397
|
+
crossDomain: false
|
|
398
|
+
};
|
|
399
|
+
bridged.crossDomain || (bridged.crossDomain = crossDomain);
|
|
400
|
+
messages.forEach(
|
|
401
|
+
([name, collection]) => bridged.messages.set(name, collection)
|
|
402
|
+
);
|
|
403
|
+
bridgedEdges.set(id, bridged);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const newEdges = Array.from(
|
|
408
|
+
bridgedEdges,
|
|
409
|
+
([id, bridged]) => createEdge({
|
|
410
|
+
id,
|
|
411
|
+
source: bridged.source,
|
|
412
|
+
target: bridged.target,
|
|
413
|
+
label: getMessagesLabel(bridged.messages),
|
|
414
|
+
// The same size arrow as the rest of the graph's edges
|
|
415
|
+
markerEnd: {
|
|
416
|
+
type: MarkerType2.ArrowClosed,
|
|
417
|
+
width: 20,
|
|
418
|
+
height: 20,
|
|
419
|
+
color: "rgb(var(--ec-page-text-muted))"
|
|
420
|
+
},
|
|
421
|
+
// Along the same route, and crossing domains if any edge it replaces did
|
|
422
|
+
data: {
|
|
423
|
+
...bridged.route ? { route: bridged.route } : {},
|
|
424
|
+
...bridged.crossDomain ? { crossDomain: true } : {}
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
);
|
|
428
|
+
return {
|
|
429
|
+
nodes: nodes.filter((node) => !hiddenNodes.has(node.id)),
|
|
430
|
+
edges: [...keptEdges, ...newEdges]
|
|
431
|
+
};
|
|
432
|
+
};
|
|
433
|
+
var hideMessageNodes = (nodes, edges) => hideNodes(nodes, edges, isCarrier);
|
|
434
|
+
|
|
435
|
+
export {
|
|
436
|
+
SERVICE,
|
|
437
|
+
AGENT,
|
|
438
|
+
AGENT_TOOL,
|
|
439
|
+
EVENT,
|
|
440
|
+
QUERY,
|
|
441
|
+
COMMAND,
|
|
442
|
+
CHANNEL,
|
|
443
|
+
ACTOR,
|
|
444
|
+
DATA,
|
|
445
|
+
VIEW,
|
|
446
|
+
MESSAGE,
|
|
447
|
+
generateIdForNode,
|
|
448
|
+
generateIdForNodes,
|
|
449
|
+
generatedIdForEdge,
|
|
450
|
+
getColorFromString,
|
|
451
|
+
getEdgeLabelForServiceAsTarget,
|
|
452
|
+
getEdgeLabelForMessageAsSource,
|
|
453
|
+
getEdgeLabelSize,
|
|
454
|
+
createEdge,
|
|
455
|
+
createNode,
|
|
456
|
+
getNodeSize,
|
|
457
|
+
layoutWithElk,
|
|
458
|
+
isMessageNode,
|
|
459
|
+
getMessagesLabel,
|
|
460
|
+
isCarrier,
|
|
461
|
+
hideNodes,
|
|
462
|
+
hideMessageNodes
|
|
463
|
+
};
|
|
464
|
+
//# sourceMappingURL=chunk-Z3G354GF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/nodes/node-types.ts","../src/utils/utils/utils.ts","../src/utils/elk-layout.ts","../src/utils/hide-messages.ts"],"sourcesContent":["export const SERVICE = [\"service\", \"services\"];\nexport const AGENT = [\"agent\", \"agents\"];\nexport const AGENT_TOOL = [\"agentTool\", \"agent-tool\"];\nexport const EVENT = [\"event\", \"events\"];\nexport const QUERY = [\"queries\", \"query\", \"querie\"];\nexport const COMMAND = [\"command\", \"commands\"];\nexport const CHANNEL = [\"channel\", \"channels\"];\nexport const ACTOR = [\"actor\", \"actors\"];\nexport const DATA = [\"data\"];\nexport const VIEW = [\"view\"];\n\nexport const MESSAGE = [...EVENT, ...COMMAND, ...QUERY];\n","// Can't use the CollectionEntry type from astro:content because a client component is using this util\n\nimport { MarkerType, Position, type Edge, type Node } from \"@xyflow/react\";\n\ninterface BaseCollectionData {\n id: string;\n version: string;\n}\n\ninterface CollectionItem {\n collection: string;\n data: BaseCollectionData;\n}\n\ninterface MessageCollectionItem extends CollectionItem {\n collection: \"commands\" | \"events\" | \"queries\";\n}\n\nexport const generateIdForNode = (node: CollectionItem) => {\n return `${node.data.id}-${node.data.version}`;\n};\nexport const generateIdForNodes = (nodes: any) => {\n return nodes\n .map((node: any) => `${node.data.id}-${node.data.version}`)\n .join(\"-\");\n};\nexport const generatedIdForEdge = (\n source: CollectionItem,\n target: CollectionItem,\n) => {\n return `${source.data.id}-${source.data.version}-${target.data.id}-${target.data.version}`;\n};\n\nexport const getColorFromString = (id: string) => {\n // Takes the given id (string) and returns a custom hex color based on the id\n // Create a hash from the string\n let hash = 0;\n for (let i = 0; i < id.length; i++) {\n hash = id.charCodeAt(i) + ((hash << 5) - hash);\n }\n\n // Convert the hash into a hex color\n let color = \"#\";\n for (let i = 0; i < 3; i++) {\n const value = (hash >> (i * 8)) & 0xff;\n color += value.toString(16).padStart(2, \"0\");\n }\n\n return color;\n};\n\nexport const getEdgeLabelForServiceAsTarget = (data: MessageCollectionItem) => {\n const type = data.collection;\n switch (type) {\n case \"commands\":\n return \"invokes\";\n case \"events\":\n return \"publishes \\nevent\";\n case \"queries\":\n return \"requests\";\n default:\n return \"sends to\";\n }\n};\nexport const getEdgeLabelForMessageAsSource = (\n data: MessageCollectionItem,\n throughChannel = false,\n) => {\n const type = data.collection;\n switch (type) {\n case \"commands\":\n return \"accepts\";\n case \"events\":\n return throughChannel ? \"subscribed to\" : \"subscribed by\";\n case \"queries\":\n return \"accepts\";\n default:\n return \"sends to\";\n }\n};\n\n/**\n * Rough size of an edge label, so the layout can leave room for it on its edge\n */\nexport const getEdgeLabelSize = (label: unknown) => {\n if (typeof label !== \"string\" || !label.trim())\n return { width: 0, height: 0 };\n const lines = label.split(\"\\n\");\n const longestLine = Math.max(...lines.map((line) => line.trim().length));\n return { width: longestLine * 6 + 20, height: lines.length * 14 + 12 };\n};\n\nexport const createEdge = (edgeOptions: Edge): Edge => {\n return {\n label: \"subscribed by\",\n animated: false,\n // markerStart: {\n // type: MarkerType.Arrow,\n // width: 40,\n // height: 40,\n // },\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 40,\n height: 40,\n color: \"rgb(var(--ec-page-text-muted))\",\n },\n style: {\n strokeWidth: 1.5,\n stroke: \"rgb(var(--ec-page-text-muted))\",\n strokeDasharray: \"5 5\",\n },\n ...edgeOptions,\n };\n};\n\nexport const createNode = (values: Node): Node => {\n return {\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n ...values,\n };\n};\n","import type { Edge, Node } from \"@xyflow/react\";\nimport type {\n ELK,\n ElkExtendedEdge,\n ElkNode,\n ElkPort,\n LayoutOptions,\n} from \"elkjs/lib/elk-api\";\nimport { getEdgeLabelSize } from \"./utils/utils\";\n\nexport type LayoutGraph = { nodes: Node[]; edges: Edge[] };\nexport type LayoutSize = { width: number; height: number };\nexport type EdgeRoute = {\n points: { x: number; y: number }[];\n label?: { x: number; y: number };\n /** Where the edge's source and target were laid out (top-left, in the flow) */\n source?: { x: number; y: number };\n target?: { x: number; y: number };\n};\n\n// The size each node type renders at (at most), for nodes that haven't been\n// rendered (and measured) yet, e.g. when laying a graph out on the server\nconst DEFAULT_SIZE: LayoutSize = { width: 240, height: 112 };\nconst NODE_SIZES: Record<string, LayoutSize> = {\n events: { width: 240, height: 104 },\n commands: { width: 240, height: 126 },\n queries: { width: 240, height: 126 },\n services: { width: 240, height: 112 },\n data: { width: 240, height: 108 },\n systems: { width: 240, height: 120 },\n system: { width: 240, height: 120 },\n \"context-domain\": { width: 240, height: 112 },\n \"context-actor\": { width: 180, height: 80 },\n actor: { width: 180, height: 80 },\n note: { width: 200, height: 150 },\n step: { width: 240, height: 80 },\n // Groups with nothing in them (groups with children are sized to fit them)\n \"domain-group\": { width: 320, height: 160 },\n \"system-group\": { width: 320, height: 160 },\n};\n\n// Nodes sized by their style, like groups: an empty one needs a size too\nconst GROUP_TYPES = new Set([\"domain-group\", \"system-group\", \"group\"]);\n\n/** The size a node is laid out at: as rendered, or an estimate for its type */\nexport const getNodeSize = (node: Node): LayoutSize => {\n if (node.measured?.width && node.measured?.height) {\n return { width: node.measured.width, height: node.measured.height };\n }\n if (typeof node.width === \"number\" && typeof node.height === \"number\") {\n return { width: node.width, height: node.height };\n }\n // Domains list their services, so grow with them\n if (node.type === \"domains\" || node.type === \"domain\") {\n const services = (node.data as any)?.domain?.data?.services || [];\n return { width: 260, height: 60 + services.length * 40 };\n }\n return NODE_SIZES[node.type || \"\"] ?? DEFAULT_SIZE;\n};\n\n// Room for a group's header above its children\nconst GROUP_PADDING = \"[top=100,left=40,bottom=40,right=40]\";\n\n// Space between nodes and edges. Set on every group as well as the graph, as\n// groups don't take it from the graph (they'd use ELK's much tighter defaults)\nconst SPACING = {\n \"elk.layered.spacing.nodeNodeBetweenLayers\": \"60\",\n \"elk.spacing.nodeNode\": \"40\",\n \"elk.spacing.edgeNode\": \"25\",\n \"elk.spacing.edgeEdge\": \"15\",\n};\n\n// Large graphs (e.g. a big domain) use cheaper settings: the nicest node\n// placement takes minutes on a few thousand edges, these take a second or two\nconst LARGE_GRAPH_NODES = 80;\nconst LARGE_GRAPH_EDGES = 200;\nconst LARGE_GRAPH_OPTIONS: LayoutOptions = {\n \"elk.layered.nodePlacement.strategy\": \"BRANDES_KOEPF\",\n \"elk.layered.thoroughness\": \"1\",\n \"elk.layered.crossingMinimization.greedySwitch.type\": \"OFF\",\n};\n\nlet elk: ELK | undefined;\n// Loaded when first needed, so pages that never lay out in the browser don't download it\nconst getElk = async () => {\n if (!elk) {\n const { default: ELK } = await import(\"elkjs/lib/elk.bundled.js\");\n elk = new ELK();\n }\n return elk;\n};\n\n/**\n * Lays a graph out with ELK (left to right). Nested groups (nodes other nodes\n * have as their `parentId`) are laid out in one pass with their children.\n * Edges are routed at right angles around nodes, each edge with its own\n * connection point so edges don't run on top of each other, and labels are\n * placed on their edge. Each edge keeps its type and gets its route (and label\n * position) in `data.route`, which the visualiser's edges are drawn along.\n *\n * Node positions are top-left corners (nodes get `origin: [0, 0]`), children\n * relative to their group. Groups are sized to fit their children.\n */\nexport const layoutWithElk = async (\n { nodes, edges }: LayoutGraph,\n { sizeOf = getNodeSize }: { sizeOf?: (node: Node) => LayoutSize } = {},\n): Promise<LayoutGraph> => {\n const nodesById = new Map(nodes.map((node) => [node.id, node]));\n const groupIds = new Set(\n nodes\n .map((node) => node.parentId)\n .filter((id): id is string => !!id && nodesById.has(id)),\n );\n const parentOf = (node: Node) =>\n node.parentId && groupIds.has(node.parentId) ? node.parentId : undefined;\n\n // Each edge gets its own port, leaving from the right of its source and\n // arriving at the left of its target, so ELK spreads edges out along a\n // node's side rather than routing them all through one point. Edges to a\n // specific handle (e.g. a service listed in a domain) share that handle's port.\n const layoutEdges = edges.filter(\n (edge) => nodesById.has(edge.source) && nodesById.has(edge.target),\n );\n const ports = new Map<string, ElkPort[]>();\n const addPort = (\n nodeId: string,\n id: string,\n side: \"EAST\" | \"WEST\",\n ): string => {\n const nodePorts = ports.get(nodeId) || [];\n if (!nodePorts.some((port) => port.id === id)) {\n ports.set(nodeId, [\n ...nodePorts,\n { id, layoutOptions: { \"elk.port.side\": side } },\n ]);\n }\n return id;\n };\n const edgePorts = layoutEdges.map((edge, index) => ({\n source: addPort(\n edge.source,\n edge.sourceHandle\n ? `${edge.source}__${edge.sourceHandle}`\n : `e${index}__out`,\n \"EAST\",\n ),\n target: addPort(\n edge.target,\n edge.targetHandle\n ? `${edge.target}__${edge.targetHandle}`\n : `e${index}__in`,\n \"WEST\",\n ),\n }));\n\n const toElkNode = (node: Node): ElkNode => ({\n id: node.id,\n ...(groupIds.has(node.id)\n ? {\n children: nodes\n .filter((child) => parentOf(child) === node.id)\n .map(toElkNode),\n }\n : sizeOf(node)),\n layoutOptions: {\n \"elk.portConstraints\": \"FIXED_SIDE\",\n ...(groupIds.has(node.id)\n ? { \"elk.padding\": GROUP_PADDING, ...SPACING }\n : {}),\n // A node's own options (e.g. a group's padding) win\n ...((node.data as { layoutOptions?: LayoutOptions } | undefined)\n ?.layoutOptions ?? {}),\n },\n ports: ports.get(node.id) || [],\n });\n\n const layout = await (\n await getElk()\n ).layout({\n id: \"root\",\n layoutOptions: {\n \"elk.algorithm\": \"layered\",\n \"elk.direction\": \"RIGHT\",\n \"elk.hierarchyHandling\": \"INCLUDE_CHILDREN\",\n \"elk.edgeRouting\": \"ORTHOGONAL\",\n // Edge routes in absolute coordinates (node positions stay relative to their parent)\n \"elk.json.edgeCoords\": \"ROOT\",\n \"elk.edgeLabels.placement\": \"CENTER\",\n ...SPACING,\n ...(nodes.length >= LARGE_GRAPH_NODES || edges.length >= LARGE_GRAPH_EDGES\n ? LARGE_GRAPH_OPTIONS\n : { \"elk.layered.nodePlacement.strategy\": \"NETWORK_SIMPLEX\" }),\n },\n children: nodes.filter((node) => !parentOf(node)).map(toElkNode),\n edges: layoutEdges.map((edge, index) => ({\n id: `e${index}`,\n sources: [edgePorts[index].source],\n targets: [edgePorts[index].target],\n // Labels sit on their edge, rather than beside it (only works set per label)\n labels: edge.label\n ? [\n {\n text: String(edge.label),\n ...getEdgeLabelSize(edge.label),\n layoutOptions: { \"elk.edgeLabels.inline\": \"true\" },\n },\n ]\n : [],\n })),\n });\n\n const laidOut = new Map<string, ElkNode>();\n const collect = (elkNode: ElkNode) =>\n (elkNode.children || []).forEach((child) => {\n laidOut.set(child.id, child);\n collect(child);\n });\n collect(layout);\n\n // Where a node was laid out in the flow (ELK positions are relative to the parent)\n const absolute = (nodeId: string): { x: number; y: number } => {\n const node = nodesById.get(nodeId);\n const parent = node && parentOf(node);\n const offset = parent ? absolute(parent) : { x: 0, y: 0 };\n const elkNode = laidOut.get(nodeId);\n return { x: offset.x + (elkNode?.x ?? 0), y: offset.y + (elkNode?.y ?? 0) };\n };\n\n const routes = new Map<Edge, EdgeRoute>();\n (layout.edges || []).forEach((elkEdge: ElkExtendedEdge) => {\n const section = elkEdge.sections?.[0];\n if (!section) return;\n const label = elkEdge.labels?.[0];\n const edge = layoutEdges[Number(elkEdge.id.slice(1))];\n routes.set(edge, {\n points: [\n section.startPoint,\n ...(section.bendPoints || []),\n section.endPoint,\n ],\n label: label\n ? {\n x: (label.x ?? 0) + (label.width ?? 0) / 2,\n y: (label.y ?? 0) + (label.height ?? 0) / 2,\n }\n : undefined,\n source: absolute(edge.source),\n target: absolute(edge.target),\n });\n });\n\n const depth = (node?: Node): number => {\n const parent = node && parentOf(node);\n return parent ? depth(nodesById.get(parent)) + 1 : 0;\n };\n\n return {\n // Parents must come before their children in the array for React Flow\n nodes: [...nodes]\n .sort((a, b) => depth(a) - depth(b))\n .map((node) => {\n const elkNode = laidOut.get(node.id);\n if (!elkNode) return node;\n return {\n ...node,\n origin: [0, 0] as [number, number],\n position: { x: elkNode.x ?? 0, y: elkNode.y ?? 0 },\n ...(groupIds.has(node.id) ||\n (GROUP_TYPES.has(node.type || \"\") &&\n typeof node.style?.width !== \"number\")\n ? {\n style: {\n ...node.style,\n width: elkNode.width,\n height: elkNode.height,\n },\n // Re-measured at its new size\n measured: undefined,\n }\n : {}),\n };\n }),\n edges: edges.map((edge) => {\n const route = routes.get(edge);\n return route ? { ...edge, data: { ...edge.data, route } } : edge;\n }),\n };\n};\n","import { MarkerType, type Edge, type Node } from \"@xyflow/react\";\nimport { COMMAND, EVENT, MESSAGE, QUERY } from \"../nodes/node-types\";\nimport { createEdge } from \"./utils/utils\";\nimport type { EdgeRoute } from \"./elk-layout\";\n\nconst MESSAGE_NODE_TYPES = [...MESSAGE, \"messageGroup\", \"messageGroupExpanded\"];\n\nexport const isMessageNode = (node: Node) =>\n MESSAGE_NODE_TYPES.includes(node.type || \"\");\n\nconst getCollection = (type = \"\") => {\n if (EVENT.includes(type)) return \"events\";\n if (COMMAND.includes(type)) return \"commands\";\n if (QUERY.includes(type)) return \"queries\";\n return \"messages\";\n};\n\n// Returns the messages a node represents, as [name, collection] pairs\nconst getMessages = (node: Node): [string, string][] => {\n const data = node.data as any;\n if (node.type === \"messageGroup\") {\n return (data?.messages || []).map(({ message }: any) => [\n message?.data?.name || message?.data?.id,\n getCollection(message?.collection),\n ]);\n }\n const message = data?.message;\n return message\n ? [[message.name || message.id, getCollection(node.type)]]\n : [];\n};\n\nconst VERBS: Record<string, string> = {\n events: \"publishes\",\n commands: \"invokes\",\n queries: \"requests\",\n};\n\n/**\n * Label for an edge carrying messages (name -> collection), e.g.\n * \"publishes\\nProduct Created\", \"publishes\\n3 events\", \"sends\\n3 messages\"\n */\nexport const getMessagesLabel = (messages: Map<string, string>) => {\n if (messages.size === 0) return undefined;\n const collections = new Set(messages.values());\n const collection =\n collections.size === 1 ? Array.from(collections)[0] : \"messages\";\n const verb = VERBS[collection] || \"sends\";\n const sent =\n messages.size === 1\n ? Array.from(messages.keys())[0]\n : `${messages.size} ${collection}`;\n return `${verb}\\n${sent}`;\n};\n\n// Messages and channels carry what's sent between the nodes either side of them\nexport const isCarrier = (node: Node) =>\n isMessageNode(node) || node.type === \"channels\";\n\nconst isCrossDomain = (edge: Edge) =>\n !!(edge.data as { crossDomain?: boolean } | undefined)?.crossDomain;\n\nconst getRoute = (edge: Edge) =>\n (edge.data as { route?: EdgeRoute } | undefined)?.route;\n\n/**\n * The route of an edge bridging hidden nodes: along the routes of the edges it\n * replaces (through where the hidden nodes were), labelled where the first\n * hidden node was. None unless they're all laid out.\n */\nconst joinRoutes = (routes: (EdgeRoute | undefined)[]) => {\n if (!routes.every((route) => route && route.points.length > 0)) return;\n const laidOut = routes as EdgeRoute[];\n const arrives = laidOut[0].points[laidOut[0].points.length - 1];\n const leaves = laidOut[1].points[0];\n return {\n points: laidOut.flatMap((route) => route.points),\n label: { x: (arrives.x + leaves.x) / 2, y: (arrives.y + leaves.y) / 2 },\n source: laidOut[0].source,\n target: laidOut[laidOut.length - 1].target,\n };\n};\n\n/**\n * Removes the nodes `isHidden` picks. Messages and channels removed are\n * bridged: the nodes either side of them are connected directly, labelled with\n * the messages between them. Other edges to removed nodes go with them.\n * e.g. hiding events, ServiceA -> OrderPlaced -> ServiceB becomes ServiceA -> ServiceB\n */\nexport const hideNodes = (\n nodes: Node[],\n edges: Edge[],\n isHidden: (node: Node) => boolean,\n) => {\n const hiddenNodes = new Map(\n nodes.filter(isHidden).map((node) => [node.id, node]),\n );\n if (hiddenNodes.size === 0) return { nodes, edges };\n\n const outgoingEdges = new Map<string, Edge[]>();\n for (const edge of edges) {\n const outgoing = outgoingEdges.get(edge.source) || [];\n outgoing.push(edge);\n outgoingEdges.set(edge.source, outgoing);\n }\n\n const keptEdges: Edge[] = [];\n const bridgedEdges = new Map<\n string,\n {\n source: string;\n target: string;\n messages: Map<string, string>;\n route?: EdgeRoute;\n crossDomain: boolean;\n }\n >();\n\n for (const edge of edges) {\n if (hiddenNodes.has(edge.source)) continue;\n const target = hiddenNodes.get(edge.target);\n if (!target) {\n keptEdges.push(edge);\n continue;\n }\n if (!isCarrier(target)) continue;\n\n // Follow the edge through hidden messages and channels until we reach\n // visible nodes, collecting the names of the messages along the way\n const stack = [\n {\n id: edge.target,\n messages: [] as [string, string][],\n routes: [getRoute(edge)],\n crossDomain: isCrossDomain(edge),\n },\n ];\n const visited = new Set<string>();\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (visited.has(current.id)) continue;\n visited.add(current.id);\n const messages = [\n ...current.messages,\n ...getMessages(hiddenNodes.get(current.id)!),\n ];\n\n for (const next of outgoingEdges.get(current.id) || []) {\n const routes = [...current.routes, getRoute(next)];\n const crossDomain = current.crossDomain || isCrossDomain(next);\n const nextNode = hiddenNodes.get(next.target);\n if (nextNode) {\n if (isCarrier(nextNode))\n stack.push({ id: next.target, messages, routes, crossDomain });\n continue;\n }\n if (next.target === edge.source) continue;\n\n // Prefixed, so it can't clash with an edge directly between the two\n const id = `bridged-${edge.source}-${next.target}`;\n const bridged = bridgedEdges.get(id) || {\n source: edge.source,\n target: next.target,\n messages: new Map<string, string>(),\n route: joinRoutes(routes),\n crossDomain: false,\n };\n bridged.crossDomain ||= crossDomain;\n messages.forEach(([name, collection]) =>\n bridged.messages.set(name, collection),\n );\n bridgedEdges.set(id, bridged);\n }\n }\n }\n\n const newEdges = Array.from(bridgedEdges, ([id, bridged]) =>\n createEdge({\n id,\n source: bridged.source,\n target: bridged.target,\n label: getMessagesLabel(bridged.messages),\n // The same size arrow as the rest of the graph's edges\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 20,\n height: 20,\n color: \"rgb(var(--ec-page-text-muted))\",\n },\n // Along the same route, and crossing domains if any edge it replaces did\n data: {\n ...(bridged.route ? { route: bridged.route } : {}),\n ...(bridged.crossDomain ? { crossDomain: true } : {}),\n },\n }),\n );\n\n return {\n nodes: nodes.filter((node) => !hiddenNodes.has(node.id)),\n edges: [...keptEdges, ...newEdges],\n };\n};\n\n/**\n * Removes message nodes (events, commands, queries) and the channels they\n * travel through, connecting the nodes on either side directly.\n * e.g. ServiceA -> OrderPlaced -> orders-topic -> ServiceB becomes ServiceA -> ServiceB\n */\nexport const hideMessageNodes = (nodes: Node[], edges: Edge[]) =>\n hideNodes(nodes, edges, isCarrier);\n"],"mappings":"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","names":["MarkerType","message","MarkerType"]}
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright (c) 2024 by Excalidraw (https://plus.excalidraw.com/excalifont).
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://openfontlicense.org
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) and the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|