@likec4/core 1.47.0 → 1.48.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/LICENSE +1 -1
- package/dist/_chunks/Builder.view-element.mjs +3284 -0
- package/dist/_chunks/LikeC4Model.d.mts +1287 -0
- package/dist/_chunks/LikeC4Styles.mjs +691 -0
- package/dist/_chunks/RichText.d.mts +84 -0
- package/dist/_chunks/RichText.mjs +148 -0
- package/dist/_chunks/_aux.d.mts +289 -0
- package/dist/_chunks/_aux.mjs +18 -0
- package/dist/_chunks/_types.d.mts +781 -0
- package/dist/_chunks/_types2.d.mts +38 -0
- package/dist/_chunks/assignTagColors.mjs +24 -0
- package/dist/_chunks/calcDriftsFromSnapshot.mjs +379 -0
- package/dist/_chunks/connection.mjs +0 -0
- package/dist/_chunks/const.d.mts +43 -0
- package/dist/_chunks/const.mjs +33 -0
- package/dist/_chunks/expression-model.d.mts +192 -0
- package/dist/_chunks/expression-model.mjs +103 -0
- package/dist/_chunks/expression.d.mts +347 -0
- package/dist/_chunks/expression.mjs +107 -0
- package/dist/_chunks/find.d.mts +82 -0
- package/dist/_chunks/find.mjs +646 -0
- package/dist/_chunks/find2.d.mts +78 -0
- package/dist/_chunks/find2.mjs +287 -0
- package/dist/_chunks/fqnRef.d.mts +58 -0
- package/dist/_chunks/fqnRef.mjs +41 -0
- package/dist/_chunks/geometry.mjs +335 -0
- package/dist/_chunks/index.d.mts +169 -0
- package/dist/_chunks/index2.d.mts +937 -0
- package/dist/_chunks/index3.d.mts +146 -0
- package/dist/_chunks/index4.d.mts +62 -0
- package/dist/_chunks/index5.d.mts +42 -0
- package/dist/_chunks/index6.d.mts +43 -0
- package/dist/{shared/core.OtRNdMxy.d.mts → _chunks/index7.d.mts} +113 -197
- package/dist/_chunks/index8.d.mts +144 -0
- package/dist/_chunks/invariant.mjs +18 -0
- package/dist/_chunks/iterable.mjs +146 -0
- package/dist/_chunks/libs/@mantine/colors-generator.mjs +3416 -0
- package/dist/_chunks/libs/@ungap/structured-clone.mjs +213 -0
- package/dist/_chunks/libs/bail.mjs +14 -0
- package/dist/_chunks/libs/ccount.mjs +25 -0
- package/dist/_chunks/libs/character-entities-html4.mjs +263 -0
- package/dist/_chunks/libs/character-entities-legacy.mjs +117 -0
- package/dist/_chunks/libs/character-entities.mjs +2136 -0
- package/dist/_chunks/libs/comma-separated-tokens.mjs +18 -0
- package/dist/_chunks/libs/decode-named-character-reference.mjs +21 -0
- package/dist/_chunks/libs/defu.mjs +42 -0
- package/dist/_chunks/libs/devlop.mjs +5 -0
- package/dist/_chunks/libs/escape-string-regexp.mjs +8 -0
- package/dist/_chunks/libs/extend.mjs +77 -0
- package/dist/_chunks/libs/graphology-dag.mjs +703 -0
- package/dist/_chunks/libs/graphology-types.d.mts +601 -0
- package/dist/_chunks/libs/graphology.d.mts +6 -0
- package/dist/_chunks/libs/graphology.mjs +4565 -0
- package/dist/_chunks/libs/hast-util-sanitize.mjs +863 -0
- package/dist/_chunks/libs/hast-util-to-html.mjs +2696 -0
- package/dist/_chunks/libs/is-plain-obj.mjs +9 -0
- package/dist/_chunks/libs/longest-streak.mjs +30 -0
- package/dist/_chunks/libs/markdown-table.mjs +290 -0
- package/dist/_chunks/libs/mdast-util-find-and-replace.mjs +653 -0
- package/dist/_chunks/libs/mdast-util-from-markdown.mjs +8522 -0
- package/dist/_chunks/libs/mdast-util-gfm.mjs +2393 -0
- package/dist/_chunks/libs/mdast-util-to-hast.mjs +1803 -0
- package/dist/_chunks/libs/micromark-extension-gfm.mjs +2243 -0
- package/dist/_chunks/libs/mnemonist.d.mts +254 -0
- package/dist/_chunks/libs/mnemonist.mjs +1978 -0
- package/dist/_chunks/libs/natural-compare-lite.mjs +42 -0
- package/dist/_chunks/libs/rehype-sanitize.mjs +29 -0
- package/dist/_chunks/libs/rehype-stringify.mjs +34 -0
- package/dist/_chunks/libs/remark-gfm.mjs +36 -0
- package/dist/_chunks/libs/remark-github-blockquote-alert.mjs +100 -0
- package/dist/_chunks/libs/remark-parse.mjs +39 -0
- package/dist/_chunks/libs/remark-rehype.mjs +171 -0
- package/dist/_chunks/libs/remeda.mjs +702 -0
- package/dist/_chunks/libs/trough.mjs +158 -0
- package/dist/_chunks/libs/unified.mjs +2212 -0
- package/dist/_chunks/mnemonist.d.mts +1 -0
- package/dist/_chunks/mnemonist.mjs +0 -0
- package/dist/_chunks/model.mjs +1898 -0
- package/dist/_chunks/model2.mjs +0 -0
- package/dist/_chunks/relationships-view.mjs +132 -0
- package/dist/_chunks/rolldown-runtime.mjs +42 -0
- package/dist/{shared/core.C_3y3eqV.d.mts → _chunks/scalar.d.mts} +13 -43
- package/dist/_chunks/scalar.mjs +84 -0
- package/dist/_chunks/utils.mjs +483 -0
- package/dist/builder/index.d.mts +11 -775
- package/dist/builder/index.mjs +631 -1022
- package/dist/compute-view/index.d.mts +85 -56
- package/dist/compute-view/index.mjs +247 -214
- package/dist/compute-view/relationships-view/index.d.mts +16 -51
- package/dist/compute-view/relationships-view/index.mjs +6 -184
- package/dist/geometry/index.d.mts +2 -109
- package/dist/geometry/index.mjs +2 -327
- package/dist/index.d.mts +18 -20
- package/dist/index.mjs +27 -18
- package/dist/model/connection/deployment/index.d.mts +12 -15
- package/dist/model/connection/deployment/index.mjs +9 -2
- package/dist/model/connection/index.d.mts +14 -75
- package/dist/model/connection/index.mjs +10 -3
- package/dist/model/connection/model/index.d.mts +12 -15
- package/dist/model/connection/model/index.mjs +8 -2
- package/dist/model/index.d.mts +15 -57
- package/dist/model/index.mjs +11 -4
- package/dist/styles/index.d.mts +9 -117
- package/dist/styles/index.mjs +26 -59
- package/dist/types/RichText.d.mts +3 -0
- package/dist/types/RichText.mjs +7 -0
- package/dist/types/_aux.d.mts +3 -4
- package/dist/types/_aux.mjs +2 -7
- package/dist/types/expression-model.d.mts +6 -190
- package/dist/types/expression-model.mjs +6 -108
- package/dist/types/expression.d.mts +5 -6
- package/dist/types/expression.mjs +6 -112
- package/dist/types/fqnRef.d.mts +4 -60
- package/dist/types/fqnRef.mjs +6 -44
- package/dist/types/index.d.mts +9 -47
- package/dist/types/index.mjs +14 -16
- package/dist/types/scalar.d.mts +2 -2
- package/dist/types/scalar.mjs +7 -4
- package/dist/utils/graphology/index.d.mts +2 -1864
- package/dist/utils/graphology/index.mjs +3 -1
- package/dist/utils/index.d.mts +11 -124
- package/dist/utils/index.mjs +16 -43
- package/dist/utils/iterable/index.d.mts +9 -132
- package/dist/utils/iterable/index.mjs +2 -61
- package/dist/utils/mnemonist.d.mts +2 -0
- package/dist/utils/mnemonist.mjs +12 -0
- package/package.json +17 -22
- package/compute-view/relationships/package.json +0 -4
- package/dist/shared/core.3ZhnKAlZ.mjs +0 -106
- package/dist/shared/core.78IWAHAE.mjs +0 -332
- package/dist/shared/core.B85MJLTf.mjs +0 -5
- package/dist/shared/core.BFd1lU9R.mjs +0 -29
- package/dist/shared/core.BKlholso.mjs +0 -3
- package/dist/shared/core.BNN-3vPH.mjs +0 -1255
- package/dist/shared/core.BPGOjone.d.mts +0 -46
- package/dist/shared/core.BP_QHEXs.mjs +0 -785
- package/dist/shared/core.BbE4y-yl.mjs +0 -177
- package/dist/shared/core.Bdy3hhTc.mjs +0 -28382
- package/dist/shared/core.BfCKSW-g.d.mts +0 -1266
- package/dist/shared/core.BhNcrwzK.mjs +0 -7
- package/dist/shared/core.BkVA6gjl.mjs +0 -5
- package/dist/shared/core.BoYfZOBm.mjs +0 -3
- package/dist/shared/core.BsSXS-_R.mjs +0 -7
- package/dist/shared/core.C3JowhaZ.mjs +0 -32
- package/dist/shared/core.C4x8aaWa.mjs +0 -27
- package/dist/shared/core.CAgYpDtM.d.mts +0 -98
- package/dist/shared/core.CHf8VEa3.mjs +0 -1206
- package/dist/shared/core.CLSZtnFh.mjs +0 -69
- package/dist/shared/core.CbT8JVYL.mjs +0 -5
- package/dist/shared/core.CdNCAwq7.mjs +0 -176
- package/dist/shared/core.CmGY9blO.mjs +0 -6717
- package/dist/shared/core.CmPXpJ8l.mjs +0 -21
- package/dist/shared/core.Coi_LOUZ.mjs +0 -7
- package/dist/shared/core.CqAJJpK_.mjs +0 -3
- package/dist/shared/core.CywrQs86.d.mts +0 -31
- package/dist/shared/core.D00YbOhQ.d.mts +0 -300
- package/dist/shared/core.D0WZutNd.mjs +0 -94
- package/dist/shared/core.D4npX2q8.mjs +0 -18
- package/dist/shared/core.DB0Ue5Wx.d.mts +0 -70
- package/dist/shared/core.DC5IAaDT.d.mts +0 -334
- package/dist/shared/core.DE9qzhn8.d.mts +0 -83
- package/dist/shared/core.DGcIbsj4.mjs +0 -3946
- package/dist/shared/core.DH7TXqXf.mjs +0 -136
- package/dist/shared/core.DKhRkHRN.d.mts +0 -41
- package/dist/shared/core.DRJma0Ol.mjs +0 -22
- package/dist/shared/core.DU5SRqNF.mjs +0 -2209
- package/dist/shared/core.DXhDWKFZ.d.mts +0 -3
- package/dist/shared/core.DbfO90vF.mjs +0 -434
- package/dist/shared/core.DcS-0zys.mjs +0 -10
- package/dist/shared/core.Dh119QSP.mjs +0 -4995
- package/dist/shared/core.DjcWextK.mjs +0 -1371
- package/dist/shared/core.Dojz4bvg.d.mts +0 -504
- package/dist/shared/core.FZ305VYd.mjs +0 -21
- package/dist/shared/core.RfnaEmgA.mjs +0 -7
- package/dist/shared/core.btEq3i3f.mjs +0 -300
- package/dist/shared/core.oSV6SRfk.mjs +0 -13
- package/dist/shared/core.om36dXXW.mjs +0 -41
- package/dist/shared/core.osFs8tU7.d.mts +0 -466
- package/dist/shared/core.q10OP9oJ.mjs +0 -5
- package/dist/shared/core.tpvDGvdC.d.mts +0 -87
- package/dist/shared/core.uFk_o9X6.mjs +0 -13
|
@@ -0,0 +1,3284 @@
|
|
|
1
|
+
import { r as __toESM } from "./rolldown-runtime.mjs";
|
|
2
|
+
import { $ as e$10, B as t$13, C as t$7, D as e, G as t$17, I as e$2, J as n, K as n$4, L as e$4, M as e$3, N as e$7, O as e$11, Q as t$3, R as e$1, S as t$24, T as t, V as t$18, W as t$6, X as t$10, Z as t$16, _ as t$11, a as t$5, b as t$22, d as t$12, et as t$23, g as t$15, h as t$20, i as n$3, j as e$5, m as e$6, n as e$9, o as n$1, q as t$21, r as t$19, t as t$9, tt as t$8, u as t$1, v as t$2, w as t$4, x as n$2, y as t$14, z as e$8 } from "./libs/remeda.mjs";
|
|
3
|
+
import { D as whereOperatorAsPredicate, I as exact, N as _stage, P as _type, b as isViewRuleStyle, d as isViewRuleGlobalStyle, g as isElementView, h as isDynamicView, l as isViewRuleAutoLayout, n as isViewRuleGroup, o as isDynamicStepsParallel, p as isDeploymentView, r as isViewRuleRank, s as isDynamicStepsSeries, u as isViewRuleGlobalPredicateRef, y as isViewRulePredicate } from "./LikeC4Styles.mjs";
|
|
4
|
+
import { A as sortParentsFirst, C as isAncestor, D as parentFqn, F as commonHead, N as isNonEmptyArray, O as sortByFqnHierarchically, T as isSameHierarchy, _ as ancestorsFqn, a as difference, c as intersection, d as compareRelations, i as objectHash, s as hasIntersection, u as union, v as commonAncestor, w as isDescendantOf, y as compareByFqnHierarchically } from "./utils.mjs";
|
|
5
|
+
import { n as nonNullable, r as nonexhaustive, t as invariant } from "./invariant.mjs";
|
|
6
|
+
import { n as require_topological_sort, t as require_will_create_cycle } from "./libs/graphology-dag.mjs";
|
|
7
|
+
import { l as import_stack, n as import_default_map } from "./libs/mnemonist.mjs";
|
|
8
|
+
import { f as ifilter, i as isome, l as iflat, n as toArray, o as imap, p as isIterable, r as toSet, t as iunique } from "./iterable.mjs";
|
|
9
|
+
import { n as preferSummary } from "./_aux.mjs";
|
|
10
|
+
import { a as GroupElementKind, h as isGroupElementKind, p as flattenMarkdownOrString, y as stepEdgeId } from "./scalar.mjs";
|
|
11
|
+
import { t as FqnRef } from "./fqnRef.mjs";
|
|
12
|
+
import { n as FqnExpr, r as RelationExpr } from "./expression.mjs";
|
|
13
|
+
import { n as ModelFqnExpr, r as ModelRelationExpr, t as ModelExpression } from "./expression-model.mjs";
|
|
14
|
+
import { r as buildElementNotations } from "./calcDriftsFromSnapshot.mjs";
|
|
15
|
+
import { c as isNestedElementOfDeployedInstanceModel, d as LikeC4Model, n as isDeploymentElementModel, o as isElementModel, r as isDeploymentNodeModel, t as isDeployedInstanceModel } from "./model.mjs";
|
|
16
|
+
import { a as DeploymentConnectionModel, i as find_exports, u as RelationshipsAccum } from "./find.mjs";
|
|
17
|
+
import { n as Connection, t as customInspectSymbol } from "./const.mjs";
|
|
18
|
+
import { _ as mergeConnections, a as ConnectionModel, c as findDeepestNestedConnection, g as isOutgoing, h as isNestedConnection, i as find_exports$1, l as findDescendantConnections, m as isIncoming, n as findConnectionsBetween$3, o as differenceConnections, p as isAnyInOut, s as findAscendingConnections, t as findConnection$3, v as sortConnectionsByBoundaryHierarchy } from "./find2.mjs";
|
|
19
|
+
import { t as Graph } from "./libs/graphology.mjs";
|
|
20
|
+
|
|
21
|
+
//#region src/compute-view/utils/ancestorsOfNode.ts
|
|
22
|
+
/**
|
|
23
|
+
* Returns the ancestors of given computed node, starting with the direct parent and ending with the root node.
|
|
24
|
+
*/
|
|
25
|
+
function ancestorsOfNode(node, nodes) {
|
|
26
|
+
const ancestors = [];
|
|
27
|
+
let parentId = node.parent;
|
|
28
|
+
while (parentId) {
|
|
29
|
+
const parentNode = nonNullable(nodes.get(parentId), `Parent node ${parentId} not found`);
|
|
30
|
+
ancestors.push(parentNode);
|
|
31
|
+
parentId = parentNode.parent;
|
|
32
|
+
}
|
|
33
|
+
return ancestors;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/compute-view/utils/link-nodes-with-edges.ts
|
|
38
|
+
/**
|
|
39
|
+
* Update `inEdges` and `outEdges` props of nodes based on the edges
|
|
40
|
+
* Mutates nodes and updates their in/out edges
|
|
41
|
+
*/
|
|
42
|
+
function linkNodesWithEdges(nodesMap, edges) {
|
|
43
|
+
for (const edge of edges) {
|
|
44
|
+
const source = nodesMap.get(edge.source);
|
|
45
|
+
const target = nodesMap.get(edge.target);
|
|
46
|
+
invariant(source, `Source node ${edge.source} not found`);
|
|
47
|
+
invariant(target, `Target node ${edge.target} not found`);
|
|
48
|
+
source.outEdges.push(edge.id);
|
|
49
|
+
target.inEdges.push(edge.id);
|
|
50
|
+
const sourceAncestors = ancestorsOfNode(source, nodesMap);
|
|
51
|
+
const targetAncestors = ancestorsOfNode(target, nodesMap);
|
|
52
|
+
const edgeParent = sourceAncestors.length > 0 && targetAncestors.length > 0 ? t(commonHead(t$1(sourceAncestors), t$1(targetAncestors))) : null;
|
|
53
|
+
edge.parent = edgeParent ? edgeParent.id : null;
|
|
54
|
+
for (const sourceAncestor of sourceAncestors) {
|
|
55
|
+
if (sourceAncestor === edgeParent) break;
|
|
56
|
+
sourceAncestor.outEdges.push(edge.id);
|
|
57
|
+
}
|
|
58
|
+
for (const targetAncestor of targetAncestors) {
|
|
59
|
+
if (targetAncestor === edgeParent) break;
|
|
60
|
+
targetAncestor.inEdges.push(edge.id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/compute-view/utils/topological-sort.ts
|
|
67
|
+
var import_topological_sort = require_topological_sort();
|
|
68
|
+
var import_will_create_cycle = /* @__PURE__ */ __toESM(require_will_create_cycle(), 1);
|
|
69
|
+
/**
|
|
70
|
+
* Keeps initial order of the elements, but ensures parents are placed before children
|
|
71
|
+
*/
|
|
72
|
+
function ensureParentsFirst(array) {
|
|
73
|
+
const result = [];
|
|
74
|
+
const items = [...array];
|
|
75
|
+
let item;
|
|
76
|
+
while (item = items.shift()) {
|
|
77
|
+
let parent = item.parent;
|
|
78
|
+
if (parent) {
|
|
79
|
+
const ancestors = [];
|
|
80
|
+
while (parent) {
|
|
81
|
+
const parentIndx = items.findIndex((i) => i.id === parent);
|
|
82
|
+
if (parentIndx < 0) break;
|
|
83
|
+
const [parentItem] = items.splice(parentIndx, 1);
|
|
84
|
+
if (!parentItem) throw new Error("Invalid state, should not happen");
|
|
85
|
+
ancestors.unshift(parentItem);
|
|
86
|
+
parent = parentItem.parent;
|
|
87
|
+
}
|
|
88
|
+
result.push(...ancestors);
|
|
89
|
+
}
|
|
90
|
+
result.push(item);
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Side effect, mutates node.children field to preserve same order as in the input
|
|
96
|
+
*/
|
|
97
|
+
function updateChildren(nodes) {
|
|
98
|
+
nodes.forEach((parent) => {
|
|
99
|
+
if (parent.children.length > 0) parent.children = nodes.reduce((acc, n) => {
|
|
100
|
+
if (n.parent === parent.id) acc.push(n.id);
|
|
101
|
+
return acc;
|
|
102
|
+
}, []);
|
|
103
|
+
});
|
|
104
|
+
return nodes;
|
|
105
|
+
}
|
|
106
|
+
function topologicalSort(param) {
|
|
107
|
+
let nodes = ensureParentsFirst([...param.nodes.values()]);
|
|
108
|
+
let edges = [...param.edges];
|
|
109
|
+
if (nodes.length < 2 || edges.length === 0) return {
|
|
110
|
+
nodes,
|
|
111
|
+
edges
|
|
112
|
+
};
|
|
113
|
+
const getNode = (id) => nonNullable(param.nodes.get(id));
|
|
114
|
+
const g = new Graph({
|
|
115
|
+
multi: true,
|
|
116
|
+
allowSelfLoops: true,
|
|
117
|
+
type: "directed"
|
|
118
|
+
});
|
|
119
|
+
const [edgesBetweenLeafs, edgesWithCompounds] = t$2(t$3(edges, t$4((edge) => {
|
|
120
|
+
const source = getNode(edge.source), target = getNode(edge.target), parent = edge.parent ? getNode(edge.parent) : null;
|
|
121
|
+
return {
|
|
122
|
+
id: edge.id,
|
|
123
|
+
edge,
|
|
124
|
+
parent,
|
|
125
|
+
source,
|
|
126
|
+
target
|
|
127
|
+
};
|
|
128
|
+
})), ({ source, target }) => source.children.length === 0 && target.children.length === 0);
|
|
129
|
+
const sortedEdges = [];
|
|
130
|
+
const addEdgeToGraph = (edge) => {
|
|
131
|
+
g.mergeNode(edge.source);
|
|
132
|
+
g.mergeNode(edge.target);
|
|
133
|
+
sortedEdges.push(edge);
|
|
134
|
+
if (!(0, import_will_create_cycle.default)(g, edge.source, edge.target)) g.mergeDirectedEdge(edge.source, edge.target);
|
|
135
|
+
};
|
|
136
|
+
for (const { edge, source, target } of edgesBetweenLeafs) {
|
|
137
|
+
addEdgeToGraph(edge);
|
|
138
|
+
if (target.parent && target.parent !== edge.parent) t$3(ancestorsOfNode(target, param.nodes), t$5((ancestor) => ancestor.inEdges.includes(edge.id)), t$6((ancestor) => {
|
|
139
|
+
g.mergeNode(ancestor.id);
|
|
140
|
+
if (!(0, import_will_create_cycle.default)(g, edge.source, ancestor.id)) g.mergeDirectedEdge(edge.source, ancestor.id);
|
|
141
|
+
if (!(0, import_will_create_cycle.default)(g, ancestor.id, edge.target)) g.mergeDirectedEdge(ancestor.id, edge.target);
|
|
142
|
+
}));
|
|
143
|
+
if (source.parent) {
|
|
144
|
+
const sourceParent = getNode(source.parent);
|
|
145
|
+
g.mergeNode(sourceParent.id);
|
|
146
|
+
if (!(0, import_will_create_cycle.default)(g, sourceParent.id, source.id)) g.mergeDirectedEdge(sourceParent.id, source.id);
|
|
147
|
+
if (target.parent && target.parent !== source.parent) {
|
|
148
|
+
if (!(0, import_will_create_cycle.default)(g, sourceParent.id, target.parent)) g.mergeDirectedEdge(sourceParent.id, target.parent);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const { edge } of edgesWithCompounds) addEdgeToGraph(edge);
|
|
153
|
+
invariant(sortedEdges.length === edges.length, "Not all edges were added to the graph");
|
|
154
|
+
const sortedIds = (0, import_topological_sort.topologicalSort)(g);
|
|
155
|
+
let sorted = [];
|
|
156
|
+
let unsorted = nodes.slice();
|
|
157
|
+
for (const sortedId of sortedIds) {
|
|
158
|
+
const indx = unsorted.findIndex((n) => n.id === sortedId);
|
|
159
|
+
invariant(indx >= 0, `Node "${sortedId}" not found`);
|
|
160
|
+
sorted.push(...unsorted.splice(indx, 1));
|
|
161
|
+
}
|
|
162
|
+
if (unsorted.length > 0 && sorted.length > 0) sorted = sorted.flatMap((node) => {
|
|
163
|
+
if (unsorted.length === 0) return node;
|
|
164
|
+
const wereBefore = nodes.slice(0, nodes.indexOf(node)).filter((n) => unsorted.includes(n));
|
|
165
|
+
if (wereBefore.length > 0) {
|
|
166
|
+
unsorted = unsorted.filter((n) => !wereBefore.includes(n));
|
|
167
|
+
return [...wereBefore, node];
|
|
168
|
+
}
|
|
169
|
+
return node;
|
|
170
|
+
});
|
|
171
|
+
sorted.push(...unsorted);
|
|
172
|
+
return {
|
|
173
|
+
nodes: updateChildren(ensureParentsFirst(sorted)),
|
|
174
|
+
edges: sortedEdges
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/compute-view/utils/view-hash.ts
|
|
180
|
+
function calcViewLayoutHash(view) {
|
|
181
|
+
view.hash = objectHash({
|
|
182
|
+
id: view.id,
|
|
183
|
+
__: view._type ?? "element",
|
|
184
|
+
autoLayout: view.autoLayout,
|
|
185
|
+
nodes: t$3(view.nodes, t$4((n) => ({
|
|
186
|
+
id: n.id,
|
|
187
|
+
icon: e(n.icon) && n.icon !== "none" ? "Y" : "N",
|
|
188
|
+
title: n.title,
|
|
189
|
+
description: flattenMarkdownOrString(n.description),
|
|
190
|
+
technology: n.technology ?? null,
|
|
191
|
+
shape: n.shape,
|
|
192
|
+
size: n.style.size ?? null,
|
|
193
|
+
iconSize: n.style.iconSize ?? null,
|
|
194
|
+
iconPosition: n.style.iconPosition ?? null,
|
|
195
|
+
textSize: n.style.textSize ?? null,
|
|
196
|
+
padding: n.style.padding ?? null,
|
|
197
|
+
children: n.children
|
|
198
|
+
})), t$7(({ id, ...node }) => [id, node])),
|
|
199
|
+
edges: t$3(view.edges, t$4((e) => ({
|
|
200
|
+
source: e.source,
|
|
201
|
+
target: e.target,
|
|
202
|
+
label: e.label,
|
|
203
|
+
description: flattenMarkdownOrString(e.description),
|
|
204
|
+
technology: e.technology ?? null,
|
|
205
|
+
dir: e.dir,
|
|
206
|
+
head: e.head,
|
|
207
|
+
tail: e.tail,
|
|
208
|
+
line: e.line
|
|
209
|
+
})), t$7(({ source, target, ...edge }) => [`${source}:${target}`, edge]))
|
|
210
|
+
});
|
|
211
|
+
return view;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/compute-view/memory/AbstractMemory.ts
|
|
216
|
+
var AbstractMemory = class {
|
|
217
|
+
/**
|
|
218
|
+
* Provides access to context types
|
|
219
|
+
* !IMPORTANT: Should not be called in runtime
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* type State = SomeMemory['Ctx']['MutableState']
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
get Ctx() {
|
|
227
|
+
throw new Error("Should not be called in runtime");
|
|
228
|
+
}
|
|
229
|
+
constructor(state) {
|
|
230
|
+
this.state = state;
|
|
231
|
+
}
|
|
232
|
+
get elements() {
|
|
233
|
+
return this.state.elements;
|
|
234
|
+
}
|
|
235
|
+
get explicits() {
|
|
236
|
+
return this.state.explicits;
|
|
237
|
+
}
|
|
238
|
+
get final() {
|
|
239
|
+
return this.state.final;
|
|
240
|
+
}
|
|
241
|
+
get connections() {
|
|
242
|
+
return this.state.connections;
|
|
243
|
+
}
|
|
244
|
+
isEmpty() {
|
|
245
|
+
return this.elements.size === 0 && this.connections.length === 0 && this.explicits.size === 0 && this.final.size === 0;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/compute-view/memory/AbstractStageExclude.ts
|
|
251
|
+
var AbstractStageExclude = class {
|
|
252
|
+
excluded = {
|
|
253
|
+
elements: /* @__PURE__ */ new Set(),
|
|
254
|
+
connections: []
|
|
255
|
+
};
|
|
256
|
+
constructor(memory, expression) {
|
|
257
|
+
this.memory = memory;
|
|
258
|
+
this.expression = expression;
|
|
259
|
+
}
|
|
260
|
+
markedToMoveExplicitToImplicit = false;
|
|
261
|
+
_removeElement(element) {
|
|
262
|
+
this.excluded.elements.add(element);
|
|
263
|
+
}
|
|
264
|
+
exclude(element) {
|
|
265
|
+
if (!element) return this;
|
|
266
|
+
if (isIterable(element)) {
|
|
267
|
+
for (const el of element) this._removeElement(el);
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
this._removeElement(element);
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
_removeConnection(connection) {
|
|
274
|
+
this.excluded.connections.push(connection);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Excludes from the memory relationships from given connections (still connection may be included, but without given relationships)
|
|
278
|
+
* @param moveExplicitToImplicit - if true, disconnected explicit elements will be moved to implicit
|
|
279
|
+
* @default false
|
|
280
|
+
*/
|
|
281
|
+
excludeConnections(connection, moveExplicitToImplicit) {
|
|
282
|
+
if (e$1(moveExplicitToImplicit)) {
|
|
283
|
+
invariant(!this.markedToMoveExplicitToImplicit, "Already marked to move explicits");
|
|
284
|
+
this.markedToMoveExplicitToImplicit = moveExplicitToImplicit;
|
|
285
|
+
}
|
|
286
|
+
if (isIterable(connection)) {
|
|
287
|
+
for (const c of connection) this._removeConnection(c);
|
|
288
|
+
return this;
|
|
289
|
+
}
|
|
290
|
+
this._removeConnection(connection);
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
isDirty() {
|
|
294
|
+
return this.excluded.elements.size > 0 || this.excluded.connections.length > 0;
|
|
295
|
+
}
|
|
296
|
+
isEmpty() {
|
|
297
|
+
return !this.isDirty();
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Determines whether disconnected explicits should become implicits.
|
|
301
|
+
* By default moves all disconnected explicits to implicits, if there were operation to exclude elements.
|
|
302
|
+
*
|
|
303
|
+
* Override this method to change the behavior.
|
|
304
|
+
*/
|
|
305
|
+
filterForMoveToImplicits(disconnectedExplicits) {
|
|
306
|
+
if (this.markedToMoveExplicitToImplicit || this.excluded.elements.size > 0) return disconnectedExplicits;
|
|
307
|
+
return /* @__PURE__ */ new Set();
|
|
308
|
+
}
|
|
309
|
+
moveDisconnectedExplicitsToImplicits(state) {
|
|
310
|
+
let disconnected = difference(new Set(this.memory.connections.flatMap((c) => [c.source, c.target])), new Set(state.connections.flatMap((c) => [c.source, c.target])));
|
|
311
|
+
disconnected = intersection(disconnected, state.elements);
|
|
312
|
+
disconnected = t$3(disconnected, ifilter((el) => {
|
|
313
|
+
return state.explicits.has(el) && !isome(state.final, isDescendantOf(el));
|
|
314
|
+
}), toSet());
|
|
315
|
+
if (disconnected.size > 0) {
|
|
316
|
+
disconnected = this.filterForMoveToImplicits(disconnected);
|
|
317
|
+
state.explicits = difference(state.explicits, disconnected);
|
|
318
|
+
state.final = difference(state.final, disconnected);
|
|
319
|
+
}
|
|
320
|
+
return state;
|
|
321
|
+
}
|
|
322
|
+
removeElements(state) {
|
|
323
|
+
state.elements = difference(state.elements, this.excluded.elements);
|
|
324
|
+
state.explicits = difference(state.explicits, this.excluded.elements);
|
|
325
|
+
state.final = difference(state.final, this.excluded.elements);
|
|
326
|
+
return state;
|
|
327
|
+
}
|
|
328
|
+
removeConnections(state) {
|
|
329
|
+
const excludedMap = this.excluded.connections.reduce((acc, c) => {
|
|
330
|
+
const existing = acc.get(c.id);
|
|
331
|
+
if (existing) acc.set(c.id, existing.mergeWith(c));
|
|
332
|
+
else acc.set(c.id, c);
|
|
333
|
+
return acc;
|
|
334
|
+
}, /* @__PURE__ */ new Map());
|
|
335
|
+
let disconnected = /* @__PURE__ */ new Set();
|
|
336
|
+
state.connections = state.connections.reduce((acc, c) => {
|
|
337
|
+
const excluded = excludedMap.get(c.id);
|
|
338
|
+
if (excluded) {
|
|
339
|
+
disconnected.add(c.source);
|
|
340
|
+
disconnected.add(c.target);
|
|
341
|
+
const diff = c.difference(excluded);
|
|
342
|
+
if (diff.nonEmpty()) acc.push(diff);
|
|
343
|
+
} else acc.push(c);
|
|
344
|
+
return acc;
|
|
345
|
+
}, []);
|
|
346
|
+
for (const stillExists of state.connections) {
|
|
347
|
+
disconnected.delete(stillExists.source);
|
|
348
|
+
disconnected.delete(stillExists.target);
|
|
349
|
+
if (stillExists.boundary && state.elements.has(stillExists.boundary)) disconnected.delete(stillExists.boundary);
|
|
350
|
+
}
|
|
351
|
+
if (disconnected.size === 0) return state;
|
|
352
|
+
disconnected = difference(disconnected, state.explicits);
|
|
353
|
+
state.final = difference(state.final, disconnected);
|
|
354
|
+
return state;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Precommit hook
|
|
358
|
+
*/
|
|
359
|
+
precommit(state) {
|
|
360
|
+
return state;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Postcommit hook
|
|
364
|
+
*/
|
|
365
|
+
postcommit(state) {
|
|
366
|
+
invariant(difference(state.explicits, state.elements).size === 0, "Explicits must be subset of elements");
|
|
367
|
+
invariant(difference(state.final, state.elements).size === 0, "Final elements must be subset of elements");
|
|
368
|
+
return state;
|
|
369
|
+
}
|
|
370
|
+
commit() {
|
|
371
|
+
let state = this.precommit(this.memory.mutableState());
|
|
372
|
+
if (this.excluded.elements.size > 0) {
|
|
373
|
+
const excludedConnections = state.connections.filter((c) => this.excluded.elements.has(c.source) || this.excluded.elements.has(c.target)).flatMap((c) => [c, ...findAscendingConnections(state.connections, c).map((asc) => asc.intersect(c))]).filter((asc) => asc.nonEmpty());
|
|
374
|
+
this.excludeConnections(excludedConnections);
|
|
375
|
+
}
|
|
376
|
+
if (this.excluded.connections.length > 0) state = this.removeConnections(state);
|
|
377
|
+
if (this.excluded.elements.size > 0) state = this.removeElements(state);
|
|
378
|
+
return this.memory.update(this.postcommit(state));
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
//#endregion
|
|
383
|
+
//#region src/compute-view/memory/AbstractStageInclude.ts
|
|
384
|
+
var AbstractStageInclude = class {
|
|
385
|
+
explicits = /* @__PURE__ */ new Set();
|
|
386
|
+
implicits = /* @__PURE__ */ new Set();
|
|
387
|
+
_ordered = /* @__PURE__ */ new Set();
|
|
388
|
+
_connections = [];
|
|
389
|
+
constructor(memory, expression) {
|
|
390
|
+
this.memory = memory;
|
|
391
|
+
this.expression = expression;
|
|
392
|
+
}
|
|
393
|
+
get elements() {
|
|
394
|
+
return this.explicits;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Connections from this stage
|
|
398
|
+
*/
|
|
399
|
+
get connections() {
|
|
400
|
+
return this._connections;
|
|
401
|
+
}
|
|
402
|
+
mergedConnections() {
|
|
403
|
+
return mergeConnections([...this.memory.connections, ...this._connections]);
|
|
404
|
+
}
|
|
405
|
+
connectWithExisting(_element, _direction) {
|
|
406
|
+
throw new Error("Method not implements, depends on the model");
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Possible to override
|
|
410
|
+
*/
|
|
411
|
+
_addExplicit(elements) {
|
|
412
|
+
this._ordered.add(elements);
|
|
413
|
+
this.explicits.add(elements);
|
|
414
|
+
this.implicits.delete(elements);
|
|
415
|
+
}
|
|
416
|
+
addExplicit(element) {
|
|
417
|
+
if (!element) return this;
|
|
418
|
+
if (isIterable(element)) {
|
|
419
|
+
for (const el of element) this._addExplicit(el);
|
|
420
|
+
return this;
|
|
421
|
+
}
|
|
422
|
+
this._addExplicit(element);
|
|
423
|
+
return this;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Possible to override
|
|
427
|
+
*/
|
|
428
|
+
_addImplicit(elements) {
|
|
429
|
+
if (this.explicits.has(elements)) return;
|
|
430
|
+
this._ordered.add(elements);
|
|
431
|
+
this.implicits.add(elements);
|
|
432
|
+
}
|
|
433
|
+
addImplicit(elements) {
|
|
434
|
+
if (!elements) return this;
|
|
435
|
+
if (isIterable(elements)) {
|
|
436
|
+
for (const el of elements) this._addImplicit(el);
|
|
437
|
+
return this;
|
|
438
|
+
}
|
|
439
|
+
this._addImplicit(elements);
|
|
440
|
+
return this;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Possible to override
|
|
444
|
+
*/
|
|
445
|
+
_addConnection(connection) {
|
|
446
|
+
this._connections.push(connection);
|
|
447
|
+
this._addImplicit(connection.source);
|
|
448
|
+
this._addImplicit(connection.target);
|
|
449
|
+
}
|
|
450
|
+
addConnections(connection) {
|
|
451
|
+
if (isIterable(connection)) {
|
|
452
|
+
for (const c of connection) this._addConnection(c);
|
|
453
|
+
return this;
|
|
454
|
+
}
|
|
455
|
+
this._addConnection(connection);
|
|
456
|
+
return this;
|
|
457
|
+
}
|
|
458
|
+
isDirty() {
|
|
459
|
+
return this.explicits.size > 0 || this.implicits.size > 0 || this._connections.length > 0;
|
|
460
|
+
}
|
|
461
|
+
isEmpty() {
|
|
462
|
+
return !this.isDirty();
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Precommit hook
|
|
466
|
+
*/
|
|
467
|
+
precommit(state) {
|
|
468
|
+
return state;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Postcommit hook
|
|
472
|
+
*/
|
|
473
|
+
postcommit(state) {
|
|
474
|
+
return state;
|
|
475
|
+
}
|
|
476
|
+
processConnections(connections) {
|
|
477
|
+
return connections;
|
|
478
|
+
}
|
|
479
|
+
commit() {
|
|
480
|
+
let state = this.precommit(this.memory.mutableState());
|
|
481
|
+
let fromConnections = /* @__PURE__ */ new Set();
|
|
482
|
+
if (this._connections.length > 0) {
|
|
483
|
+
const [fromKnown, rest] = t$2(this._connections, (c) => state.final.has(c.source));
|
|
484
|
+
state.connections = this.processConnections(mergeConnections([
|
|
485
|
+
...state.connections,
|
|
486
|
+
...fromKnown,
|
|
487
|
+
...rest
|
|
488
|
+
]));
|
|
489
|
+
fromConnections = new Set(state.connections.flatMap((c) => [c.source, c.target]));
|
|
490
|
+
}
|
|
491
|
+
state.elements = union(state.elements, this._ordered, this.explicits, fromConnections, this.implicits);
|
|
492
|
+
state.explicits = intersection(state.elements, union(state.explicits, this.explicits));
|
|
493
|
+
state.final = intersection(state.elements, union(state.final, this.explicits, fromConnections));
|
|
494
|
+
return this.memory.update(this.postcommit(state));
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/compute-view/memory/ops.ts
|
|
500
|
+
function treeFromMemoryState(memory, filter = "final") {
|
|
501
|
+
const sorted = sortParentsFirst(toArray(filter === "final" ? memory.final : memory.elements));
|
|
502
|
+
const connected = new Set(memory.connections.flatMap((c) => [c.source, c.target]));
|
|
503
|
+
const root = new Set(sorted);
|
|
504
|
+
const parents = new import_default_map.default(() => null);
|
|
505
|
+
const children = sorted.reduce((acc, parent, index, all) => {
|
|
506
|
+
acc.set(parent, all.slice(index + 1).filter((e) => isAncestor(parent, e)).map((e) => {
|
|
507
|
+
root.delete(e);
|
|
508
|
+
return e;
|
|
509
|
+
}).reduce((acc, el) => {
|
|
510
|
+
if (!acc.some((e) => isAncestor(e, el))) {
|
|
511
|
+
acc.push(el);
|
|
512
|
+
parents.set(el, parent);
|
|
513
|
+
}
|
|
514
|
+
return acc;
|
|
515
|
+
}, []));
|
|
516
|
+
return acc;
|
|
517
|
+
}, new import_default_map.default(() => []));
|
|
518
|
+
return {
|
|
519
|
+
root,
|
|
520
|
+
connected,
|
|
521
|
+
hasInOut: (el) => memory.connections.some(Connection.isAnyInOut(el.id)),
|
|
522
|
+
parent: (el) => parents.get(el),
|
|
523
|
+
children: (el) => children.get(el)
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
//#endregion
|
|
528
|
+
//#region src/compute-view/deployment-view/stages/stage-exclude.ts
|
|
529
|
+
var StageExclude$1 = class extends AbstractStageExclude {};
|
|
530
|
+
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/compute-view/utils/elementExpressionToPredicate.ts
|
|
533
|
+
function elementExprToPredicate(target) {
|
|
534
|
+
if (ModelFqnExpr.isCustom(target)) return elementExprToPredicate(target.custom.expr);
|
|
535
|
+
if (ModelFqnExpr.isWhere(target)) {
|
|
536
|
+
const predicate = elementExprToPredicate(target.where.expr);
|
|
537
|
+
const where = whereOperatorAsPredicate(target.where.condition);
|
|
538
|
+
return (n) => predicate(n) && where(n);
|
|
539
|
+
}
|
|
540
|
+
if (ModelFqnExpr.isElementKindExpr(target)) return target.isEqual ? (n) => n.kind === target.elementKind : (n) => n.kind !== target.elementKind;
|
|
541
|
+
if (ModelFqnExpr.isElementTagExpr(target)) return target.isEqual ? ({ tags }) => tags.includes(target.elementTag) : ({ tags }) => !tags.includes(target.elementTag);
|
|
542
|
+
if (ModelFqnExpr.isWildcard(target)) return () => true;
|
|
543
|
+
if (ModelFqnExpr.isModelRef(target)) {
|
|
544
|
+
const fqn = FqnRef.flatten(target.ref);
|
|
545
|
+
if (target.selector === "expanded") return (n) => {
|
|
546
|
+
return n.id === fqn || parentFqn(n.id) === fqn;
|
|
547
|
+
};
|
|
548
|
+
if (target.selector === "descendants" || target.selector === "children") {
|
|
549
|
+
const fqnWithDot = fqn + ".";
|
|
550
|
+
return (n) => {
|
|
551
|
+
return n.id.startsWith(fqnWithDot);
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
return (n) => {
|
|
555
|
+
return n.id === fqn;
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
nonexhaustive(target);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region src/compute-view/utils/applyViewRuleStyles.ts
|
|
563
|
+
function applyViewRuleStyle(rule, predicate, nodes) {
|
|
564
|
+
const { shape, color, icon, ...rest } = rule.style;
|
|
565
|
+
const nonEmptyStyle = !e$2(rest);
|
|
566
|
+
t$3(nodes, n(e$3(isGroupElementKind)), n(predicate), t$6((n) => {
|
|
567
|
+
n.shape = shape ?? n.shape;
|
|
568
|
+
n.color = color ?? n.color;
|
|
569
|
+
if (e$4(icon)) n.icon = icon;
|
|
570
|
+
if (e$4(rule.notation)) n.notation = rule.notation;
|
|
571
|
+
if (nonEmptyStyle) n.style = {
|
|
572
|
+
...n.style,
|
|
573
|
+
...rest
|
|
574
|
+
};
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
function applyViewRuleStyles(rules, nodes) {
|
|
578
|
+
for (const rule of rules) {
|
|
579
|
+
if (!isViewRuleStyle(rule) || rule.targets.length === 0) continue;
|
|
580
|
+
applyViewRuleStyle(rule, t$8(rule.targets.map(elementExprToPredicate)), nodes);
|
|
581
|
+
}
|
|
582
|
+
return nodes;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/compute-view/element-view/memory/NodeGroup.ts
|
|
587
|
+
var NodesGroup = class NodesGroup {
|
|
588
|
+
static kind = GroupElementKind;
|
|
589
|
+
constructor(id, viewRule, parent = null, elements = /* @__PURE__ */ new Set()) {
|
|
590
|
+
this.id = id;
|
|
591
|
+
this.viewRule = viewRule;
|
|
592
|
+
this.parent = parent;
|
|
593
|
+
this.elements = elements;
|
|
594
|
+
}
|
|
595
|
+
isEmpty() {
|
|
596
|
+
return this.elements.size === 0;
|
|
597
|
+
}
|
|
598
|
+
update(elements) {
|
|
599
|
+
return new NodesGroup(this.id, this.viewRule, this.parent, elements);
|
|
600
|
+
}
|
|
601
|
+
clone() {
|
|
602
|
+
return new NodesGroup(this.id, this.viewRule, this.parent, new Set(this.elements));
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region src/compute-view/element-view/memory/stage-exclude.ts
|
|
608
|
+
var StageExclude = class extends AbstractStageExclude {
|
|
609
|
+
excludeRelations(excluded) {
|
|
610
|
+
t$3(this.memory.connections, n((c) => hasIntersection(c.relations, excluded)), t$6((c) => {
|
|
611
|
+
this.excludeConnections(c.update(intersection(c.relations, excluded)));
|
|
612
|
+
}));
|
|
613
|
+
return this;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Precommit hook
|
|
617
|
+
*/
|
|
618
|
+
precommit(state) {
|
|
619
|
+
if (this.excluded.elements.size > 0) {
|
|
620
|
+
const excludeRelationships = new Set([...this.excluded.elements].flatMap((el) => [...el.incoming("direct"), ...el.outgoing("direct")]));
|
|
621
|
+
this.excludeRelations(excludeRelationships);
|
|
622
|
+
}
|
|
623
|
+
return state;
|
|
624
|
+
}
|
|
625
|
+
postcommit(state) {
|
|
626
|
+
const leftExplicits = difference(this.memory.explicits, state.explicits);
|
|
627
|
+
for (const explicit of leftExplicits) state.explicitFirstSeenIn.delete(explicit);
|
|
628
|
+
const left = difference(this.memory.elements, state.elements);
|
|
629
|
+
for (const el of left) state.lastSeenIn.delete(el);
|
|
630
|
+
return state;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
var ActiveGroupStageExclude = class extends StageExclude {
|
|
634
|
+
constructor(memory, expression) {
|
|
635
|
+
super(memory, expression);
|
|
636
|
+
this.memory = memory;
|
|
637
|
+
this.expression = expression;
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
//#endregion
|
|
642
|
+
//#region src/compute-view/element-view/memory/stage-include.ts
|
|
643
|
+
const { findConnection: findConnection$2, findConnectionsBetween: findConnectionsBetween$2 } = find_exports$1;
|
|
644
|
+
var StageInclude$1 = class extends AbstractStageInclude {
|
|
645
|
+
/**
|
|
646
|
+
* Connects elements with existing ones in the memory
|
|
647
|
+
*/
|
|
648
|
+
connectWithExisting(elements, direction = "both") {
|
|
649
|
+
const before = this._connections.length;
|
|
650
|
+
const hasChanged = () => this._connections.length > before;
|
|
651
|
+
if (!isIterable(elements)) {
|
|
652
|
+
if (direction === "in" || direction === "both") for (const el of this.memory.elements) this.addConnections(findConnection$2(el, elements, "directed"));
|
|
653
|
+
if (direction === "out" || direction === "both") this.addConnections(findConnectionsBetween$2(elements, this.memory.elements, "directed"));
|
|
654
|
+
return hasChanged();
|
|
655
|
+
}
|
|
656
|
+
const targets = [...elements];
|
|
657
|
+
if (direction === "in" || direction === "both") for (const el of this.memory.elements) this.addConnections(findConnectionsBetween$2(el, targets, "directed"));
|
|
658
|
+
if (direction === "out" || direction === "both") for (const el of targets) this.addConnections(findConnectionsBetween$2(el, this.memory.elements, "directed"));
|
|
659
|
+
return hasChanged();
|
|
660
|
+
}
|
|
661
|
+
addImplicitWithinScope(element) {
|
|
662
|
+
if (!element) return;
|
|
663
|
+
if (!this.memory.scope || isAncestor(this.memory.scope, element)) this.addImplicit(element);
|
|
664
|
+
}
|
|
665
|
+
processConnections(connections) {
|
|
666
|
+
if (ModelExpression.isRelationExpr(this.expression)) return connections;
|
|
667
|
+
t$3(connections, t$6(({ source, target, boundary }) => {
|
|
668
|
+
t$3(t$9([...toArray(source.ancestors()).reverse(), source], [...toArray(target.ancestors()).reverse(), target]), t$10(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor), n$1(1), t$6(([sourceAncestor, targetAncestor]) => {
|
|
669
|
+
if (sourceAncestor === source && targetAncestor === target) {
|
|
670
|
+
this.addImplicitWithinScope(boundary);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (sourceAncestor !== source) this.addImplicitWithinScope(sourceAncestor);
|
|
674
|
+
if (targetAncestor !== target) this.addImplicitWithinScope(targetAncestor);
|
|
675
|
+
}));
|
|
676
|
+
}));
|
|
677
|
+
return connections;
|
|
678
|
+
}
|
|
679
|
+
postcommit(state) {
|
|
680
|
+
const newExplicits = difference(state.explicits, this.memory.explicits);
|
|
681
|
+
for (const explicit of newExplicits) state.explicitFirstSeenIn.set(explicit, "@root");
|
|
682
|
+
return state;
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
var ActiveGroupStageInclude = class extends StageInclude$1 {
|
|
686
|
+
constructor(memory, expression) {
|
|
687
|
+
super(memory, expression);
|
|
688
|
+
this.memory = memory;
|
|
689
|
+
this.expression = expression;
|
|
690
|
+
}
|
|
691
|
+
postcommit(state) {
|
|
692
|
+
const newExplicits = difference(state.explicits, this.memory.explicits);
|
|
693
|
+
for (const explicit of newExplicits) state.explicitFirstSeenIn.set(explicit, this.memory.activeGroupId);
|
|
694
|
+
for (const implicit of [...this.explicits, ...this.implicits]) state.lastSeenIn.set(implicit, this.memory.activeGroupId);
|
|
695
|
+
return state;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
//#endregion
|
|
700
|
+
//#region src/compute-view/element-view/memory/memory.ts
|
|
701
|
+
var Memory$1 = class Memory$1 extends AbstractMemory {
|
|
702
|
+
static empty(scope) {
|
|
703
|
+
return new Memory$1({
|
|
704
|
+
elements: /* @__PURE__ */ new Set(),
|
|
705
|
+
explicits: /* @__PURE__ */ new Set(),
|
|
706
|
+
final: /* @__PURE__ */ new Set(),
|
|
707
|
+
connections: [],
|
|
708
|
+
groups: [],
|
|
709
|
+
explicitFirstSeenIn: /* @__PURE__ */ new Map(),
|
|
710
|
+
lastSeenIn: /* @__PURE__ */ new Map()
|
|
711
|
+
}, scope);
|
|
712
|
+
}
|
|
713
|
+
constructor(state, scope) {
|
|
714
|
+
super(state);
|
|
715
|
+
this.state = state;
|
|
716
|
+
this.scope = scope;
|
|
717
|
+
}
|
|
718
|
+
get groups() {
|
|
719
|
+
return this.state.groups;
|
|
720
|
+
}
|
|
721
|
+
get explicitFirstSeenIn() {
|
|
722
|
+
return this.state.explicitFirstSeenIn;
|
|
723
|
+
}
|
|
724
|
+
get lastSeenIn() {
|
|
725
|
+
return this.state.lastSeenIn;
|
|
726
|
+
}
|
|
727
|
+
stageInclude(expr) {
|
|
728
|
+
return new StageInclude$1(this, expr);
|
|
729
|
+
}
|
|
730
|
+
stageExclude(expr) {
|
|
731
|
+
return new StageExclude(this, expr);
|
|
732
|
+
}
|
|
733
|
+
mutableState() {
|
|
734
|
+
return {
|
|
735
|
+
elements: new Set(this.state.elements),
|
|
736
|
+
explicits: new Set(this.state.explicits),
|
|
737
|
+
final: new Set(this.state.final),
|
|
738
|
+
connections: [...this.state.connections],
|
|
739
|
+
groups: this.state.groups.map((g) => g.clone()),
|
|
740
|
+
explicitFirstSeenIn: new Map(this.state.explicitFirstSeenIn),
|
|
741
|
+
lastSeenIn: new Map(this.state.lastSeenIn)
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
update(newstate) {
|
|
745
|
+
return new Memory$1({
|
|
746
|
+
...this.state,
|
|
747
|
+
...newstate
|
|
748
|
+
}, this.scope);
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
var ActiveGroupMemory = class ActiveGroupMemory extends Memory$1 {
|
|
752
|
+
static enter(memory, rule) {
|
|
753
|
+
const groupId = `@gr${memory.groups.length + 1}`;
|
|
754
|
+
if (memory instanceof ActiveGroupMemory) {
|
|
755
|
+
const stack = import_stack.default.from([...memory.stack].reverse());
|
|
756
|
+
const state = memory.mutableState();
|
|
757
|
+
state.groups.push(new NodesGroup(groupId, rule, memory.activeGroupId));
|
|
758
|
+
stack.push(groupId);
|
|
759
|
+
return new ActiveGroupMemory(state, memory.scope, stack);
|
|
760
|
+
}
|
|
761
|
+
const state = memory.mutableState();
|
|
762
|
+
state.groups.push(new NodesGroup(groupId, rule, null));
|
|
763
|
+
const stack = import_stack.default.of(groupId);
|
|
764
|
+
return new ActiveGroupMemory(state, memory.scope, stack);
|
|
765
|
+
}
|
|
766
|
+
constructor(state, scope, stack) {
|
|
767
|
+
super(state, scope);
|
|
768
|
+
this.state = state;
|
|
769
|
+
this.scope = scope;
|
|
770
|
+
this.stack = stack;
|
|
771
|
+
}
|
|
772
|
+
get activeGroupId() {
|
|
773
|
+
return nonNullable(this.stack.peek(), "Stack must not be empty");
|
|
774
|
+
}
|
|
775
|
+
mutableState() {
|
|
776
|
+
return { ...super.mutableState() };
|
|
777
|
+
}
|
|
778
|
+
update(newstate) {
|
|
779
|
+
return new ActiveGroupMemory({
|
|
780
|
+
...this.state,
|
|
781
|
+
...newstate
|
|
782
|
+
}, this.scope, this.stack);
|
|
783
|
+
}
|
|
784
|
+
stageInclude(expr) {
|
|
785
|
+
return new ActiveGroupStageInclude(this, expr);
|
|
786
|
+
}
|
|
787
|
+
stageExclude(expr) {
|
|
788
|
+
return new ActiveGroupStageExclude(this, expr);
|
|
789
|
+
}
|
|
790
|
+
leave() {
|
|
791
|
+
const state = this.mutableState();
|
|
792
|
+
this.stack.pop();
|
|
793
|
+
if (this.stack.peek()) return new ActiveGroupMemory(state, this.scope, this.stack);
|
|
794
|
+
return new Memory$1(state, this.scope);
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
//#endregion
|
|
799
|
+
//#region src/compute-view/utils/buildComputedNodes.ts
|
|
800
|
+
function updateDepthOfAncestors(node, nodes) {
|
|
801
|
+
let parentNd;
|
|
802
|
+
while (!!node.parent && (parentNd = nodes.get(node.parent))) {
|
|
803
|
+
const depth = parentNd.depth ?? 1;
|
|
804
|
+
parentNd.depth = Math.max(depth, (node.depth ?? 0) + 1);
|
|
805
|
+
if (parentNd.depth === depth) break;
|
|
806
|
+
node = parentNd;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
function elementModelToNodeSource(el) {
|
|
810
|
+
const { id, title, ...rest } = n$2(el.$element, [
|
|
811
|
+
"summary",
|
|
812
|
+
"description",
|
|
813
|
+
"metadata",
|
|
814
|
+
"style",
|
|
815
|
+
"tags"
|
|
816
|
+
]);
|
|
817
|
+
const { color, icon, shape, ...style } = el.style;
|
|
818
|
+
return exact({
|
|
819
|
+
id,
|
|
820
|
+
title,
|
|
821
|
+
modelRef: id,
|
|
822
|
+
shape,
|
|
823
|
+
color,
|
|
824
|
+
icon,
|
|
825
|
+
style,
|
|
826
|
+
description: /* @__PURE__ */ preferSummary(el.$element),
|
|
827
|
+
tags: [...el.tags],
|
|
828
|
+
...rest
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
function buildComputedNodes({ defaults }, elements, groups) {
|
|
832
|
+
const nodesMap = /* @__PURE__ */ new Map();
|
|
833
|
+
const elementToGroup = /* @__PURE__ */ new Map();
|
|
834
|
+
groups?.forEach(({ id, parent, viewRule, elements }) => {
|
|
835
|
+
if (parent) nonNullable(nodesMap.get(parent), `Parent group node ${parent} not found`).children.push(id);
|
|
836
|
+
nodesMap.set(id, {
|
|
837
|
+
id,
|
|
838
|
+
parent,
|
|
839
|
+
kind: GroupElementKind,
|
|
840
|
+
title: viewRule.title ?? "",
|
|
841
|
+
color: viewRule.color ?? defaults.group?.color ?? defaults.color,
|
|
842
|
+
shape: "rectangle",
|
|
843
|
+
children: [],
|
|
844
|
+
inEdges: [],
|
|
845
|
+
outEdges: [],
|
|
846
|
+
level: 0,
|
|
847
|
+
depth: 0,
|
|
848
|
+
tags: [],
|
|
849
|
+
style: exact({
|
|
850
|
+
border: viewRule.border ?? defaults.group?.border ?? defaults.border,
|
|
851
|
+
opacity: viewRule.opacity ?? defaults.group?.opacity ?? defaults.opacity,
|
|
852
|
+
size: viewRule.size,
|
|
853
|
+
multiple: viewRule.multiple,
|
|
854
|
+
padding: viewRule.padding,
|
|
855
|
+
textSize: viewRule.textSize
|
|
856
|
+
})
|
|
857
|
+
});
|
|
858
|
+
for (const e of elements) elementToGroup.set(e.id, id);
|
|
859
|
+
});
|
|
860
|
+
Array.from(elements).sort(compareByFqnHierarchically).forEach(({ id, ...el }) => {
|
|
861
|
+
let parent = parentFqn(id);
|
|
862
|
+
let level = 0;
|
|
863
|
+
let parentNd;
|
|
864
|
+
while (parent) {
|
|
865
|
+
parentNd = nodesMap.get(parent);
|
|
866
|
+
if (parentNd) break;
|
|
867
|
+
parent = parentFqn(parent);
|
|
868
|
+
}
|
|
869
|
+
const fqn = el.modelRef ?? id;
|
|
870
|
+
if (!parentNd && elementToGroup.has(fqn)) {
|
|
871
|
+
const parentGroupId = nonNullable(elementToGroup.get(fqn));
|
|
872
|
+
parentNd = nodesMap.get(parentGroupId);
|
|
873
|
+
parent = parentGroupId;
|
|
874
|
+
}
|
|
875
|
+
if (parentNd) {
|
|
876
|
+
if (parentNd.children.length == 0) {
|
|
877
|
+
parentNd.depth = 1;
|
|
878
|
+
updateDepthOfAncestors(parentNd, nodesMap);
|
|
879
|
+
}
|
|
880
|
+
parentNd.children.push(id);
|
|
881
|
+
level = parentNd.level + 1;
|
|
882
|
+
}
|
|
883
|
+
const node = exact({
|
|
884
|
+
id,
|
|
885
|
+
parent,
|
|
886
|
+
level,
|
|
887
|
+
children: [],
|
|
888
|
+
inEdges: [],
|
|
889
|
+
outEdges: [],
|
|
890
|
+
...el
|
|
891
|
+
});
|
|
892
|
+
nodesMap.set(id, node);
|
|
893
|
+
});
|
|
894
|
+
const orderedMap = /* @__PURE__ */ new Map();
|
|
895
|
+
groups?.forEach(({ id }) => {
|
|
896
|
+
orderedMap.set(id, nonNullable(nodesMap.get(id)));
|
|
897
|
+
});
|
|
898
|
+
elements.forEach(({ id }) => {
|
|
899
|
+
orderedMap.set(id, nonNullable(nodesMap.get(id)));
|
|
900
|
+
});
|
|
901
|
+
return orderedMap;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
//#endregion
|
|
905
|
+
//#region src/compute-view/utils/merge-props-from-relationships.ts
|
|
906
|
+
function pickRelationshipProps(relation) {
|
|
907
|
+
const { title, description = null } = relation;
|
|
908
|
+
return {
|
|
909
|
+
...title && {
|
|
910
|
+
title,
|
|
911
|
+
description
|
|
912
|
+
},
|
|
913
|
+
...t$11(relation, [
|
|
914
|
+
"color",
|
|
915
|
+
"technology",
|
|
916
|
+
"head",
|
|
917
|
+
"line",
|
|
918
|
+
"tail",
|
|
919
|
+
"kind",
|
|
920
|
+
"navigateTo"
|
|
921
|
+
])
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Merges properties from multiple relationships into a single object.
|
|
926
|
+
* @param relations - The relationships to merge.
|
|
927
|
+
* @param prefer - The relationship to prefer when merging.
|
|
928
|
+
*/
|
|
929
|
+
function mergePropsFromRelationships(relations, prefer) {
|
|
930
|
+
const allprops = t$3(relations, t$12((acc, r) => {
|
|
931
|
+
if (e(r.title) && !acc.title.includes(r.title)) acc.title.push(r.title);
|
|
932
|
+
if (e(r.description) && !acc.description.some(t$13(r.description))) acc.description.push(r.description);
|
|
933
|
+
if (e(r.technology) && !acc.technology.includes(r.technology)) acc.technology.push(r.technology);
|
|
934
|
+
if (e(r.kind) && !acc.kind.includes(r.kind)) acc.kind.push(r.kind);
|
|
935
|
+
if (e(r.color) && !acc.color.includes(r.color)) acc.color.push(r.color);
|
|
936
|
+
if (e(r.line) && !acc.line.includes(r.line)) acc.line.push(r.line);
|
|
937
|
+
if (e(r.head) && !acc.head.includes(r.head)) acc.head.push(r.head);
|
|
938
|
+
if (e(r.tail) && !acc.tail.includes(r.tail)) acc.tail.push(r.tail);
|
|
939
|
+
if (e(r.navigateTo) && !acc.navigateTo.includes(r.navigateTo)) acc.navigateTo.push(r.navigateTo);
|
|
940
|
+
if (r.tags) acc.tags.push(...r.tags);
|
|
941
|
+
return acc;
|
|
942
|
+
}, {
|
|
943
|
+
title: [],
|
|
944
|
+
description: [],
|
|
945
|
+
technology: [],
|
|
946
|
+
kind: [],
|
|
947
|
+
head: [],
|
|
948
|
+
tail: [],
|
|
949
|
+
color: [],
|
|
950
|
+
tags: [],
|
|
951
|
+
line: [],
|
|
952
|
+
navigateTo: []
|
|
953
|
+
}));
|
|
954
|
+
let title = t$14(allprops.title) ?? (allprops.title.length > 1 ? "[...]" : void 0);
|
|
955
|
+
const tags = n$3(allprops.tags);
|
|
956
|
+
let merged = exact({
|
|
957
|
+
title,
|
|
958
|
+
description: t$14(allprops.description),
|
|
959
|
+
technology: t$14(allprops.technology),
|
|
960
|
+
kind: t$14(allprops.kind),
|
|
961
|
+
head: t$14(allprops.head),
|
|
962
|
+
tail: t$14(allprops.tail),
|
|
963
|
+
color: t$14(allprops.color),
|
|
964
|
+
line: t$14(allprops.line),
|
|
965
|
+
navigateTo: t$14(allprops.navigateTo),
|
|
966
|
+
...isNonEmptyArray(tags) && { tags }
|
|
967
|
+
});
|
|
968
|
+
if (prefer) {
|
|
969
|
+
const preferred = pickRelationshipProps(prefer);
|
|
970
|
+
merged = t$15({
|
|
971
|
+
...merged,
|
|
972
|
+
...preferred
|
|
973
|
+
}, e);
|
|
974
|
+
}
|
|
975
|
+
if (e$5(merged.title) && e(merged.technology)) {
|
|
976
|
+
merged.title = `[${merged.technology}]`;
|
|
977
|
+
delete merged.technology;
|
|
978
|
+
}
|
|
979
|
+
return merged;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
//#endregion
|
|
983
|
+
//#region src/compute-view/deployment-view/utils.ts
|
|
984
|
+
const { findConnection: findConnection$1, findConnectionsBetween: findConnectionsBetween$1, findConnectionsWithin: findConnectionsWithin$1 } = find_exports;
|
|
985
|
+
function resolveElements$1(model, expr) {
|
|
986
|
+
const ref = model.element(expr.ref.deployment);
|
|
987
|
+
if (ref.isDeploymentNode()) {
|
|
988
|
+
if (expr.selector === "children") return [...ref.children()];
|
|
989
|
+
if (expr.selector === "expanded") return [ref, ...ref.children()];
|
|
990
|
+
if (expr.selector === "descendants") return [...ref.descendants()];
|
|
991
|
+
}
|
|
992
|
+
return [ref];
|
|
993
|
+
}
|
|
994
|
+
function resolveModelElements(model, expr) {
|
|
995
|
+
const ref = model.$model.element(expr.ref.model);
|
|
996
|
+
if (expr.selector === "children") return [...ref.children()];
|
|
997
|
+
if (expr.selector === "expanded") return [ref, ...ref.children()];
|
|
998
|
+
if (expr.selector === "descendants") return [...ref.descendants()];
|
|
999
|
+
return [ref];
|
|
1000
|
+
}
|
|
1001
|
+
function deploymentExpressionToPredicate(target) {
|
|
1002
|
+
if (FqnExpr.isWildcard(target)) return () => true;
|
|
1003
|
+
if (FqnExpr.isElementTagExpr(target) || FqnExpr.isElementKindExpr(target)) throw new Error("element kind and tag expressions are not supported in deployment view rules");
|
|
1004
|
+
if (FqnExpr.isDeploymentRef(target)) {
|
|
1005
|
+
const fqn = target.ref.deployment;
|
|
1006
|
+
if (target.selector === "expanded") {
|
|
1007
|
+
const fqnWithDot = fqn + ".";
|
|
1008
|
+
return (n) => n.id === fqn || n.id.startsWith(fqnWithDot);
|
|
1009
|
+
}
|
|
1010
|
+
if (target.selector === "descendants") {
|
|
1011
|
+
const fqnWithDot = fqn + ".";
|
|
1012
|
+
return (n) => n.id.startsWith(fqnWithDot);
|
|
1013
|
+
}
|
|
1014
|
+
if (target.selector === "children") return (n) => parentFqn(n.id) === fqn;
|
|
1015
|
+
return (n) => n.id === fqn;
|
|
1016
|
+
}
|
|
1017
|
+
if (FqnExpr.isModelRef(target)) {
|
|
1018
|
+
const fqn = target.ref.model;
|
|
1019
|
+
if (target.selector === "expanded") {
|
|
1020
|
+
const fqnWithDot = fqn + ".";
|
|
1021
|
+
return (n) => {
|
|
1022
|
+
const m = n.modelRef ?? null;
|
|
1023
|
+
if (!m) return true;
|
|
1024
|
+
return m === fqn || m.startsWith(fqnWithDot);
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
if (target.selector === "descendants") {
|
|
1028
|
+
const fqnWithDot = fqn + ".";
|
|
1029
|
+
return (n) => {
|
|
1030
|
+
const m = n.modelRef ?? null;
|
|
1031
|
+
if (!m) return true;
|
|
1032
|
+
return m.startsWith(fqnWithDot);
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
if (target.selector === "children") return (n) => {
|
|
1036
|
+
const m = n.modelRef ?? null;
|
|
1037
|
+
if (!m) return true;
|
|
1038
|
+
return parentFqn(m) === fqn;
|
|
1039
|
+
};
|
|
1040
|
+
return (n) => {
|
|
1041
|
+
const m = n.modelRef ?? null;
|
|
1042
|
+
if (!m) return true;
|
|
1043
|
+
return m === fqn;
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
nonexhaustive(target);
|
|
1047
|
+
}
|
|
1048
|
+
function instanceSummary(model) {
|
|
1049
|
+
return /* @__PURE__ */ preferSummary(model.$instance) ?? /* @__PURE__ */ preferSummary(model.element.$element);
|
|
1050
|
+
}
|
|
1051
|
+
function deploymentNodeToNodeSource(el) {
|
|
1052
|
+
const id = el.id;
|
|
1053
|
+
const onlyOneInstance = el.onlyOneInstance();
|
|
1054
|
+
return exact({
|
|
1055
|
+
id,
|
|
1056
|
+
deploymentRef: id,
|
|
1057
|
+
title: el.title,
|
|
1058
|
+
kind: el.kind,
|
|
1059
|
+
technology: el.technology ?? void 0,
|
|
1060
|
+
links: t$16(el.links, 1) ? [...el.links] : void 0,
|
|
1061
|
+
notation: el.$node.notation ?? void 0,
|
|
1062
|
+
color: el.color,
|
|
1063
|
+
shape: el.shape,
|
|
1064
|
+
modelRef: onlyOneInstance?.element.id,
|
|
1065
|
+
icon: el.style.icon,
|
|
1066
|
+
description: /* @__PURE__ */ preferSummary(el.$node) ?? void 0,
|
|
1067
|
+
tags: [...el.tags],
|
|
1068
|
+
style: n$2(el.style, [
|
|
1069
|
+
"icon",
|
|
1070
|
+
"shape",
|
|
1071
|
+
"color"
|
|
1072
|
+
])
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
function instanceToNodeSource(el) {
|
|
1076
|
+
const instance = el.$instance;
|
|
1077
|
+
const element = el.element;
|
|
1078
|
+
const { icon, color, shape, ...style } = el.style;
|
|
1079
|
+
const links = [...element.links, ...instance.links ?? []];
|
|
1080
|
+
return exact({
|
|
1081
|
+
id: el.id,
|
|
1082
|
+
kind: "instance",
|
|
1083
|
+
title: el.title,
|
|
1084
|
+
description: instanceSummary(el) ?? void 0,
|
|
1085
|
+
technology: el.technology ?? void 0,
|
|
1086
|
+
tags: [...el.tags],
|
|
1087
|
+
links: t$16(links, 1) ? links : void 0,
|
|
1088
|
+
icon,
|
|
1089
|
+
color,
|
|
1090
|
+
shape,
|
|
1091
|
+
style,
|
|
1092
|
+
deploymentRef: instance.id,
|
|
1093
|
+
modelRef: element.id,
|
|
1094
|
+
notation: instance.notation
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
function toNodeSource(el) {
|
|
1098
|
+
if (el.isInstance()) return instanceToNodeSource(el);
|
|
1099
|
+
return deploymentNodeToNodeSource(el);
|
|
1100
|
+
}
|
|
1101
|
+
function toComputedEdges$1(connections) {
|
|
1102
|
+
return connections.reduce((acc, e) => {
|
|
1103
|
+
const relations = [...e.relations.model, ...e.relations.deployment];
|
|
1104
|
+
invariant(t$16(relations, 1), "Edge must have at least one relation");
|
|
1105
|
+
const defaults = e.source.$model.$styles.defaults;
|
|
1106
|
+
const source = e.source.id;
|
|
1107
|
+
const target = e.target.id;
|
|
1108
|
+
const { title, color = defaults.relationship.color, line = defaults.relationship.line, head = defaults.relationship.arrow, ...props } = mergePropsFromRelationships(relations.map((r) => r.$relationship));
|
|
1109
|
+
const edge = exact({
|
|
1110
|
+
id: e.id,
|
|
1111
|
+
parent: e.boundary?.id ?? null,
|
|
1112
|
+
source,
|
|
1113
|
+
target,
|
|
1114
|
+
label: title ?? null,
|
|
1115
|
+
relations: relations.map((r) => r.id),
|
|
1116
|
+
color,
|
|
1117
|
+
line,
|
|
1118
|
+
head,
|
|
1119
|
+
...props
|
|
1120
|
+
});
|
|
1121
|
+
const existing = acc.find((e) => e.source === target && e.target === source);
|
|
1122
|
+
if (existing && edge.label === existing.label) {
|
|
1123
|
+
existing.dir = "both";
|
|
1124
|
+
const head = existing.head ?? edge.head ?? e.source.$model.$styles.defaults.relationship.arrow;
|
|
1125
|
+
existing.head ??= head;
|
|
1126
|
+
existing.tail ??= head;
|
|
1127
|
+
if (edge.color) existing.color ??= edge.color;
|
|
1128
|
+
if (edge.line) existing.line ??= edge.line;
|
|
1129
|
+
return acc;
|
|
1130
|
+
}
|
|
1131
|
+
acc.push(edge);
|
|
1132
|
+
return acc;
|
|
1133
|
+
}, []);
|
|
1134
|
+
}
|
|
1135
|
+
function buildNodes$1(model, memory) {
|
|
1136
|
+
const nodesMap = buildComputedNodes(model.$styles, [...memory.final].map(toNodeSource));
|
|
1137
|
+
for (const node of nodesMap.values()) {
|
|
1138
|
+
if (!node.deploymentRef || !node.modelRef || node.children.length > 0) continue;
|
|
1139
|
+
const deploymentNode = model.deployment.element(node.deploymentRef);
|
|
1140
|
+
const onlyOneInstance = deploymentNode.isDeploymentNode() && deploymentNode.onlyOneInstance();
|
|
1141
|
+
if (!onlyOneInstance) continue;
|
|
1142
|
+
if (node.title === deploymentNode.name) node.title = onlyOneInstance.title;
|
|
1143
|
+
node.description ??= instanceSummary(onlyOneInstance) ?? null;
|
|
1144
|
+
node.technology ??= onlyOneInstance.technology;
|
|
1145
|
+
if (e$2(node.tags)) node.tags = [...onlyOneInstance.tags];
|
|
1146
|
+
if ((!node.links || e$2(node.links)) && t$16(onlyOneInstance.links, 1)) node.links = [...onlyOneInstance.links];
|
|
1147
|
+
const defaults = model.$styles.defaults;
|
|
1148
|
+
if (node.shape === defaults.shape && node.shape !== onlyOneInstance.shape) {
|
|
1149
|
+
node.shape = onlyOneInstance.shape;
|
|
1150
|
+
node.notation = null;
|
|
1151
|
+
}
|
|
1152
|
+
if (node.color === defaults.color && node.color !== onlyOneInstance.color) {
|
|
1153
|
+
node.color = onlyOneInstance.color;
|
|
1154
|
+
node.notation = null;
|
|
1155
|
+
}
|
|
1156
|
+
if (!node.icon && onlyOneInstance.icon) node.icon = onlyOneInstance.icon;
|
|
1157
|
+
}
|
|
1158
|
+
return nodesMap;
|
|
1159
|
+
}
|
|
1160
|
+
function applyDeploymentViewRuleStyles(rules, nodes) {
|
|
1161
|
+
for (const rule of rules) {
|
|
1162
|
+
if (!isViewRuleStyle(rule) || rule.targets.length === 0) continue;
|
|
1163
|
+
applyViewRuleStyle(rule, t$8(rule.targets.map(deploymentExpressionToPredicate)), nodes);
|
|
1164
|
+
}
|
|
1165
|
+
return nodes;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
//#endregion
|
|
1169
|
+
//#region src/compute-view/deployment-view/clean-connections.ts
|
|
1170
|
+
function findCrossBoundarySameSourceOrTarget(connections) {
|
|
1171
|
+
const groupedByRelation = new import_default_map.default(() => []);
|
|
1172
|
+
for (const conn of connections) for (const relation of conn.relations.model) groupedByRelation.get(relation).push(conn);
|
|
1173
|
+
const excludedRelations = new import_default_map.default(() => /* @__PURE__ */ new Set());
|
|
1174
|
+
for (const [relation, sameRelationGroup] of groupedByRelation) {
|
|
1175
|
+
if (!t$16(sameRelationGroup, 2)) continue;
|
|
1176
|
+
t$3(sameRelationGroup, t$17((conn) => [{
|
|
1177
|
+
group: `$source-${conn.source.id}`,
|
|
1178
|
+
conn
|
|
1179
|
+
}, {
|
|
1180
|
+
group: `$target-${conn.target.id}`,
|
|
1181
|
+
conn
|
|
1182
|
+
}]), t$18(e$6("group")), t$19(), n(t$16(2)), t$6(t$20(t$4(e$6("conn")), sortConnectionsByBoundaryHierarchy("desc"), t$10((conn, i, all) => i === 0 || conn.boundary === all[i - 1].boundary), t$6((conn) => {
|
|
1183
|
+
excludedRelations.get(conn).add(relation);
|
|
1184
|
+
}))));
|
|
1185
|
+
}
|
|
1186
|
+
return excludedRelations;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Identifies and processes cross-boundary connections in a deployment diagram.
|
|
1190
|
+
* This function analyzes connections between nodes and removes redundant relations
|
|
1191
|
+
* when multiple connections exist between the same elements across different boundaries.
|
|
1192
|
+
*
|
|
1193
|
+
* The function performs the following:
|
|
1194
|
+
* 1. Groups connections by their relationship type
|
|
1195
|
+
* 2. For each relationship group, identifies connections that:
|
|
1196
|
+
* - Share the same source
|
|
1197
|
+
* - Share the same target
|
|
1198
|
+
* 3. When multiple connections are found in the same group, keeps only the most specific
|
|
1199
|
+
* (deepest in hierarchy) connection and removes the relationship from others
|
|
1200
|
+
*
|
|
1201
|
+
* @param connections - The input collection of deployment connections to analyze
|
|
1202
|
+
* @returns connections with redundant cross-boundary relationships
|
|
1203
|
+
*/
|
|
1204
|
+
function findCrossBoundaryConnections(connections) {
|
|
1205
|
+
connections = mergeConnections(connections);
|
|
1206
|
+
const excludedRelations = findCrossBoundarySameSourceOrTarget(connections);
|
|
1207
|
+
for (const c of connections) {
|
|
1208
|
+
const { source, target } = c;
|
|
1209
|
+
const connectionModelRelations = c.relations.model;
|
|
1210
|
+
if (source.isDeploymentNode() !== target.isDeploymentNode()) {
|
|
1211
|
+
const node = source.isDeploymentNode() ? source : c.target;
|
|
1212
|
+
invariant(node.isDeploymentNode());
|
|
1213
|
+
const toExclude = intersection(connectionModelRelations, node.internalModelRelationships());
|
|
1214
|
+
for (const relation of toExclude) excludedRelations.get(c).add(relation);
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
if (source.isDeploymentNode() && target.isDeploymentNode()) {
|
|
1218
|
+
const toExclude = union(intersection(c.relations.model, source.internalModelRelationships()), intersection(c.relations.model, target.internalModelRelationships()));
|
|
1219
|
+
for (const relation of toExclude) excludedRelations.get(c).add(relation);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return t$3(excludedRelations.entries(), imap(([c, excluded]) => c.update({
|
|
1223
|
+
model: excluded,
|
|
1224
|
+
deployment: null
|
|
1225
|
+
})), toArray());
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Cleans connections that cross boundaries by removing overlapping parts.
|
|
1229
|
+
* @example
|
|
1230
|
+
* ```ts
|
|
1231
|
+
* const connections = getConnections();
|
|
1232
|
+
* const cleanedConnections = cleanCrossBoundary(connections);
|
|
1233
|
+
* ```
|
|
1234
|
+
*/
|
|
1235
|
+
function cleanCrossBoundary(connections) {
|
|
1236
|
+
return differenceConnections(connections, findCrossBoundaryConnections(connections));
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Identifies and returns redundant connections in a deployment view.
|
|
1240
|
+
* A connection is considered redundant if its relationships are already implied
|
|
1241
|
+
* through other connections
|
|
1242
|
+
*
|
|
1243
|
+
* @returns Array of redundant connections that can be safely removed
|
|
1244
|
+
*/
|
|
1245
|
+
function findRedundantConnections$1(connections) {
|
|
1246
|
+
return t$3(connections, mergeConnections, t$12((redundants, connection) => {
|
|
1247
|
+
const { source, target, relations } = connection;
|
|
1248
|
+
if (source.isInstance() && target.isInstance()) return redundants;
|
|
1249
|
+
let redundantAccum = RelationshipsAccum.empty();
|
|
1250
|
+
if (source.isDeploymentNode() && target.isDeploymentNode()) {
|
|
1251
|
+
const [reversed] = findConnection$1(target, source, "directed");
|
|
1252
|
+
if (reversed) redundantAccum = relations.intersect(reversed.relations);
|
|
1253
|
+
}
|
|
1254
|
+
for (const c of connections) if (isNestedConnection(c, connection)) redundantAccum = redundantAccum.union(relations.intersect(c.relations));
|
|
1255
|
+
if (redundantAccum.nonEmpty) redundants.push(new DeploymentConnectionModel(source, target, redundantAccum));
|
|
1256
|
+
return redundants;
|
|
1257
|
+
}, []));
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Remove relationships from connection model, that are already included in the connections between descendants.
|
|
1261
|
+
* In other words - if there is same connection down the hierarchy.
|
|
1262
|
+
*
|
|
1263
|
+
* @returns New connection without redundant relationships
|
|
1264
|
+
* Connection may be empty if all relationships are redundant, in this case it should be removed
|
|
1265
|
+
*/
|
|
1266
|
+
function cleanRedundantRelationships(connections) {
|
|
1267
|
+
return differenceConnections(connections, findRedundantConnections$1(connections));
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
//#endregion
|
|
1271
|
+
//#region src/compute-view/deployment-view/stages/stage-include.ts
|
|
1272
|
+
var StageInclude = class extends AbstractStageInclude {
|
|
1273
|
+
/**
|
|
1274
|
+
* Connects elements with existing ones in the memory
|
|
1275
|
+
*/
|
|
1276
|
+
connectWithExisting(elements, direction = "both") {
|
|
1277
|
+
const before = this._connections.length;
|
|
1278
|
+
const hasChanged = () => this._connections.length > before;
|
|
1279
|
+
if (!isIterable(elements)) {
|
|
1280
|
+
if (direction === "in" || direction === "both") for (const el of this.memory.elements) this.addConnections(findConnection$1(el, elements, "directed"));
|
|
1281
|
+
if (direction === "out" || direction === "both") this.addConnections(findConnectionsBetween$1(elements, this.memory.elements, "directed"));
|
|
1282
|
+
return hasChanged();
|
|
1283
|
+
}
|
|
1284
|
+
const targets = [...elements];
|
|
1285
|
+
if (direction === "in" || direction === "both") for (const el of this.memory.elements) this.addConnections(findConnectionsBetween$1(el, targets, "directed"));
|
|
1286
|
+
if (direction === "out" || direction === "both") for (const el of targets) this.addConnections(findConnectionsBetween$1(el, this.memory.elements, "directed"));
|
|
1287
|
+
return hasChanged();
|
|
1288
|
+
}
|
|
1289
|
+
processConnections(connections) {
|
|
1290
|
+
const clean = t$3(connections, cleanCrossBoundary, cleanRedundantRelationships);
|
|
1291
|
+
t$3(clean, t$6(({ source, target, boundary }) => {
|
|
1292
|
+
t$3(t$9([...toArray(source.ancestors()).reverse(), source], [...toArray(target.ancestors()).reverse(), target]), t$10(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor), n$1(1), t$6(([sourceAncestor, targetAncestor]) => {
|
|
1293
|
+
if (source === sourceAncestor && target === targetAncestor) {
|
|
1294
|
+
this.addImplicit(boundary);
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
if (sourceAncestor !== source && sourceAncestor.isDeploymentNode() && !sourceAncestor.onlyOneInstance()) this.addImplicit(sourceAncestor);
|
|
1298
|
+
if (targetAncestor !== target && targetAncestor.isDeploymentNode() && !targetAncestor.onlyOneInstance()) this.addImplicit(targetAncestor);
|
|
1299
|
+
}));
|
|
1300
|
+
}));
|
|
1301
|
+
return clean;
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
//#endregion
|
|
1306
|
+
//#region src/compute-view/deployment-view/memory/memory.ts
|
|
1307
|
+
var Memory = class Memory extends AbstractMemory {
|
|
1308
|
+
static empty() {
|
|
1309
|
+
return new Memory({
|
|
1310
|
+
elements: /* @__PURE__ */ new Set(),
|
|
1311
|
+
explicits: /* @__PURE__ */ new Set(),
|
|
1312
|
+
final: /* @__PURE__ */ new Set(),
|
|
1313
|
+
connections: []
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
stageInclude(expr) {
|
|
1317
|
+
return new StageInclude(this, expr);
|
|
1318
|
+
}
|
|
1319
|
+
stageExclude(expr) {
|
|
1320
|
+
return new StageExclude$1(this, expr);
|
|
1321
|
+
}
|
|
1322
|
+
mutableState() {
|
|
1323
|
+
return {
|
|
1324
|
+
elements: new Set(this.state.elements),
|
|
1325
|
+
explicits: new Set(this.state.explicits),
|
|
1326
|
+
final: new Set(this.state.final),
|
|
1327
|
+
connections: [...this.state.connections]
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
update(newstate) {
|
|
1331
|
+
return new Memory({
|
|
1332
|
+
...this.state,
|
|
1333
|
+
...newstate
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
equals(other) {
|
|
1337
|
+
return other instanceof Memory && t$13(this.state, other.state);
|
|
1338
|
+
}
|
|
1339
|
+
diff(state) {
|
|
1340
|
+
return {
|
|
1341
|
+
added: {
|
|
1342
|
+
elements: toArray(difference(state.elements, this.elements)),
|
|
1343
|
+
explicits: toArray(difference(state.explicits, this.explicits)),
|
|
1344
|
+
final: toArray(difference(state.final, this.final)),
|
|
1345
|
+
connections: toArray(differenceConnections(state.connections, this.connections))
|
|
1346
|
+
},
|
|
1347
|
+
removed: {
|
|
1348
|
+
elements: toArray(difference(this.elements, state.elements)),
|
|
1349
|
+
explicits: toArray(difference(this.explicits, state.explicits)),
|
|
1350
|
+
final: toArray(difference(this.final, state.final)),
|
|
1351
|
+
connections: differenceConnections(this.connections, state.connections)
|
|
1352
|
+
}
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
toString() {
|
|
1356
|
+
return [
|
|
1357
|
+
"final:",
|
|
1358
|
+
...[...this.final].map((e) => " " + e.id),
|
|
1359
|
+
"connections:",
|
|
1360
|
+
...this.connections.map((c) => " " + c.expression)
|
|
1361
|
+
].join("\n");
|
|
1362
|
+
}
|
|
1363
|
+
[customInspectSymbol](_depth, _inspectOptions, _inspect) {
|
|
1364
|
+
return this.toString();
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1368
|
+
//#endregion
|
|
1369
|
+
//#region src/compute-view/deployment-view/predicates/deploymentRefs-where.ts
|
|
1370
|
+
const WhereDeploymentRefPredicate = {
|
|
1371
|
+
include: ({ expr, model, memory, stage }) => {
|
|
1372
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
1373
|
+
return predicateToPatch("include", {
|
|
1374
|
+
expr: expr.where.expr,
|
|
1375
|
+
model,
|
|
1376
|
+
stage,
|
|
1377
|
+
memory,
|
|
1378
|
+
where
|
|
1379
|
+
});
|
|
1380
|
+
},
|
|
1381
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
1382
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
1383
|
+
return predicateToPatch("exclude", {
|
|
1384
|
+
expr: expr.where.expr,
|
|
1385
|
+
model,
|
|
1386
|
+
stage,
|
|
1387
|
+
memory,
|
|
1388
|
+
where
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
|
|
1393
|
+
//#endregion
|
|
1394
|
+
//#region src/compute-view/deployment-view/predicates/relation-incoming.ts
|
|
1395
|
+
const IncomingRelationPredicate = {
|
|
1396
|
+
include: ({ expr, model, memory, stage, where }) => {
|
|
1397
|
+
const sources = [...memory.elements];
|
|
1398
|
+
if (FqnExpr.isWildcard(expr.incoming)) {
|
|
1399
|
+
for (const source of sources) {
|
|
1400
|
+
if (source.allOutgoing.isEmpty) continue;
|
|
1401
|
+
const toInclude = applyPredicate(findConnectionsBetween$1(source, [...resolveAscendingSiblings(source)], "directed"), where);
|
|
1402
|
+
stage.addConnections(toInclude);
|
|
1403
|
+
}
|
|
1404
|
+
return stage;
|
|
1405
|
+
}
|
|
1406
|
+
invariant(FqnExpr.isDeploymentRef(expr.incoming), "Only deployment refs are supported in include");
|
|
1407
|
+
const targets = resolveElements$1(model, expr.incoming);
|
|
1408
|
+
for (const source of sources) {
|
|
1409
|
+
const toInclude = applyPredicate(findConnectionsBetween$1(source, targets, "directed"), where);
|
|
1410
|
+
stage.addConnections(toInclude);
|
|
1411
|
+
}
|
|
1412
|
+
return stage;
|
|
1413
|
+
},
|
|
1414
|
+
exclude: ({ expr, model, memory, stage, where }) => {
|
|
1415
|
+
if (FqnExpr.isElementTagExpr(expr.incoming) || FqnExpr.isElementKindExpr(expr.incoming)) throw new Error("element kind and tag expressions are not supported in exclude");
|
|
1416
|
+
if (FqnExpr.isModelRef(expr.incoming)) return excludeModelRelations(resolveAllImcomingRelations(model, expr.incoming), {
|
|
1417
|
+
stage,
|
|
1418
|
+
memory
|
|
1419
|
+
}, where);
|
|
1420
|
+
if (FqnExpr.isWildcard(expr.incoming)) return stage;
|
|
1421
|
+
const isIncoming = filterIncomingConnections(resolveElements$1(model, expr.incoming));
|
|
1422
|
+
const toExclude = t$3(memory.connections, n(isIncoming), applyPredicate(where));
|
|
1423
|
+
stage.excludeConnections(toExclude);
|
|
1424
|
+
return stage;
|
|
1425
|
+
}
|
|
1426
|
+
};
|
|
1427
|
+
function filterIncomingConnections(targets) {
|
|
1428
|
+
return t$8(targets.map((target) => {
|
|
1429
|
+
const satisfies = (el) => el === target || isAncestor(target, el);
|
|
1430
|
+
return (connection) => {
|
|
1431
|
+
return !satisfies(connection.source) && satisfies(connection.target);
|
|
1432
|
+
};
|
|
1433
|
+
}));
|
|
1434
|
+
}
|
|
1435
|
+
function resolveAllImcomingRelations(model, moodelRef) {
|
|
1436
|
+
const targets = resolveModelElements(model, moodelRef);
|
|
1437
|
+
return new Set(targets.flatMap((e) => [...e.allIncoming]));
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
//#endregion
|
|
1441
|
+
//#region src/compute-view/deployment-view/predicates/relation-outgoing.ts
|
|
1442
|
+
const OutgoingRelationPredicate = {
|
|
1443
|
+
include: ({ expr, model, memory, stage, where }) => {
|
|
1444
|
+
const targets = [...memory.elements];
|
|
1445
|
+
if (FqnExpr.isWildcard(expr.outgoing)) {
|
|
1446
|
+
for (const target of targets) {
|
|
1447
|
+
if (target.allIncoming.isEmpty) continue;
|
|
1448
|
+
for (const source of resolveAscendingSiblings(target)) {
|
|
1449
|
+
const toInclude = applyPredicate(findConnection$1(source, target, "directed"), where);
|
|
1450
|
+
stage.addConnections(toInclude);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
return stage;
|
|
1454
|
+
}
|
|
1455
|
+
invariant(FqnExpr.isDeploymentRef(expr.outgoing), "Only deployment refs are supported in include");
|
|
1456
|
+
const sources = resolveElements$1(model, expr.outgoing);
|
|
1457
|
+
for (const source of sources) {
|
|
1458
|
+
const toInclude = applyPredicate(findConnectionsBetween$1(source, targets, "directed"), where);
|
|
1459
|
+
stage.addConnections(toInclude);
|
|
1460
|
+
}
|
|
1461
|
+
return stage;
|
|
1462
|
+
},
|
|
1463
|
+
exclude: ({ expr, model, memory, stage, where }) => {
|
|
1464
|
+
if (FqnExpr.isElementTagExpr(expr.outgoing) || FqnExpr.isElementKindExpr(expr.outgoing)) throw new Error("element kind and tag expressions are not supported in exclude");
|
|
1465
|
+
if (FqnExpr.isModelRef(expr.outgoing)) return excludeModelRelations(resolveAllOutgoingRelations(model, expr.outgoing), {
|
|
1466
|
+
stage,
|
|
1467
|
+
memory
|
|
1468
|
+
}, where);
|
|
1469
|
+
if (FqnExpr.isWildcard(expr.outgoing)) return stage;
|
|
1470
|
+
const isOutgoing = filterOutgoingConnections(resolveElements$1(model, expr.outgoing));
|
|
1471
|
+
const toExclude = t$3(memory.connections, n(isOutgoing), applyPredicate(where));
|
|
1472
|
+
stage.excludeConnections(toExclude);
|
|
1473
|
+
return stage;
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
function filterOutgoingConnections(sources) {
|
|
1477
|
+
return t$8(sources.map((source) => {
|
|
1478
|
+
const satisfies = (el) => el === source || isAncestor(source, el);
|
|
1479
|
+
return (connection) => {
|
|
1480
|
+
return satisfies(connection.source) && !satisfies(connection.target);
|
|
1481
|
+
};
|
|
1482
|
+
}));
|
|
1483
|
+
}
|
|
1484
|
+
function resolveAllOutgoingRelations(model, moodelRef) {
|
|
1485
|
+
const targets = resolveModelElements(model, moodelRef);
|
|
1486
|
+
return new Set(targets.flatMap((e) => [...e.allOutgoing]));
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
//#endregion
|
|
1490
|
+
//#region src/compute-view/deployment-view/predicates/relation-direct.ts
|
|
1491
|
+
const DirectRelationPredicate = {
|
|
1492
|
+
include: ({ expr: { source, target, isBidirectional = false }, model, stage, where }) => {
|
|
1493
|
+
if (FqnExpr.isElementTagExpr(source) || FqnExpr.isElementKindExpr(source)) throw new Error("element kind and tag expressions are not supported in include");
|
|
1494
|
+
if (FqnExpr.isElementTagExpr(target) || FqnExpr.isElementKindExpr(target)) throw new Error("element kind and tag expressions are not supported in include");
|
|
1495
|
+
invariant(!FqnExpr.isModelRef(source), "Invalid source model ref in direct relation");
|
|
1496
|
+
invariant(!FqnExpr.isModelRef(target), "Invalid target model ref in direct relation");
|
|
1497
|
+
const sourceIsWildcard = FqnExpr.isWildcard(source);
|
|
1498
|
+
const targetIsWildcard = FqnExpr.isWildcard(target);
|
|
1499
|
+
const dir = isBidirectional ? "both" : "directed";
|
|
1500
|
+
let connections;
|
|
1501
|
+
switch (true) {
|
|
1502
|
+
case sourceIsWildcard && targetIsWildcard:
|
|
1503
|
+
connections = t$3(findConnectionsWithin$1(model.instances()), applyPredicate(where), t$4((c) => {
|
|
1504
|
+
stage.addImplicit(c.boundary);
|
|
1505
|
+
return c;
|
|
1506
|
+
}));
|
|
1507
|
+
break;
|
|
1508
|
+
case !sourceIsWildcard && targetIsWildcard: {
|
|
1509
|
+
const sources = resolveElements$1(model, source);
|
|
1510
|
+
const isSource = filterOutgoingConnections(sources);
|
|
1511
|
+
let postFilter = isSource;
|
|
1512
|
+
if (isBidirectional) {
|
|
1513
|
+
const isTarget = filterIncomingConnections(sources);
|
|
1514
|
+
postFilter = (c) => isSource(c) !== isTarget(c);
|
|
1515
|
+
}
|
|
1516
|
+
connections = t$3(sources, t$17((source) => {
|
|
1517
|
+
return findConnectionsBetween$1(source, resolveAscendingSiblings(source), dir);
|
|
1518
|
+
}), n(postFilter), applyPredicate(where));
|
|
1519
|
+
break;
|
|
1520
|
+
}
|
|
1521
|
+
case sourceIsWildcard && !targetIsWildcard: {
|
|
1522
|
+
const targets = resolveElements$1(model, target);
|
|
1523
|
+
const isTarget = filterIncomingConnections(targets);
|
|
1524
|
+
let postFilter = isTarget;
|
|
1525
|
+
if (isBidirectional) {
|
|
1526
|
+
const isSource = filterOutgoingConnections(targets);
|
|
1527
|
+
postFilter = (c) => isSource(c) !== isTarget(c);
|
|
1528
|
+
}
|
|
1529
|
+
connections = t$3(targets, t$17((target) => {
|
|
1530
|
+
return [...resolveAscendingSiblings(target)].flatMap((source) => findConnection$1(source, target, dir));
|
|
1531
|
+
}), n(postFilter), applyPredicate(where));
|
|
1532
|
+
break;
|
|
1533
|
+
}
|
|
1534
|
+
default: {
|
|
1535
|
+
invariant(!sourceIsWildcard, "Inferrence failed - source should be a deployment ref");
|
|
1536
|
+
invariant(!targetIsWildcard, "Inferrence failed - target should be a deployment ref");
|
|
1537
|
+
const sources = resolveElements$1(model, source);
|
|
1538
|
+
const targets = resolveElements$1(model, target);
|
|
1539
|
+
const isSource = filterOutgoingConnections(sources);
|
|
1540
|
+
const isTarget = filterIncomingConnections(targets);
|
|
1541
|
+
connections = t$3(sources, t$17((s) => findConnectionsBetween$1(s, targets, dir)), n((c) => isSource(c) && isTarget(c)), applyPredicate(where));
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
stage.addConnections(connections);
|
|
1545
|
+
if (FqnExpr.isDeploymentRef(source) && e$7(source.selector)) stage.addImplicit(model.element(source.ref.deployment));
|
|
1546
|
+
if (FqnExpr.isDeploymentRef(target) && e$7(target.selector)) stage.addImplicit(model.element(target.ref.deployment));
|
|
1547
|
+
return stage;
|
|
1548
|
+
},
|
|
1549
|
+
exclude: ({ expr, model, memory, stage, where }) => {
|
|
1550
|
+
const isTarget = deploymentExpressionToPredicate(expr.target);
|
|
1551
|
+
const isSource = deploymentExpressionToPredicate(expr.source);
|
|
1552
|
+
let modelRelationsToExclude;
|
|
1553
|
+
switch (true) {
|
|
1554
|
+
case FqnExpr.isWildcard(expr.source) && FqnExpr.isWildcard(expr.target):
|
|
1555
|
+
stage.excludeConnections(applyPredicate(memory.connections, where));
|
|
1556
|
+
return stage;
|
|
1557
|
+
case FqnExpr.isModelRef(expr.source) && FqnExpr.isModelRef(expr.target):
|
|
1558
|
+
modelRelationsToExclude = resolveRelationsBetweenModelElements({
|
|
1559
|
+
source: expr.source,
|
|
1560
|
+
target: expr.target,
|
|
1561
|
+
expr,
|
|
1562
|
+
model
|
|
1563
|
+
});
|
|
1564
|
+
return excludeModelRelations(modelRelationsToExclude, {
|
|
1565
|
+
stage,
|
|
1566
|
+
memory
|
|
1567
|
+
}, where);
|
|
1568
|
+
case FqnExpr.isModelRef(expr.source) && FqnExpr.isWildcard(expr.target):
|
|
1569
|
+
modelRelationsToExclude = resolveAllOutgoingRelations(model, expr.source);
|
|
1570
|
+
return excludeModelRelations(modelRelationsToExclude, {
|
|
1571
|
+
stage,
|
|
1572
|
+
memory
|
|
1573
|
+
}, where);
|
|
1574
|
+
case FqnExpr.isModelRef(expr.source):
|
|
1575
|
+
modelRelationsToExclude = resolveAllOutgoingRelations(model, expr.source);
|
|
1576
|
+
return excludeModelRelations(modelRelationsToExclude, {
|
|
1577
|
+
stage,
|
|
1578
|
+
memory
|
|
1579
|
+
}, where, (c) => isTarget(c.target));
|
|
1580
|
+
case FqnExpr.isModelRef(expr.target):
|
|
1581
|
+
modelRelationsToExclude = resolveAllImcomingRelations(model, expr.target);
|
|
1582
|
+
return excludeModelRelations(modelRelationsToExclude, {
|
|
1583
|
+
stage,
|
|
1584
|
+
memory
|
|
1585
|
+
}, where, (c) => isSource(c.source));
|
|
1586
|
+
default:
|
|
1587
|
+
const satisfies = (connection) => {
|
|
1588
|
+
return isSource(connection.source) && isTarget(connection.target) || expr.isBidirectional === true && isSource(connection.target) && isTarget(connection.source);
|
|
1589
|
+
};
|
|
1590
|
+
const deploymentRelationsToExclude = t$3(memory.connections, n(satisfies), applyPredicate(where));
|
|
1591
|
+
if (deploymentRelationsToExclude.length === 0) return stage;
|
|
1592
|
+
stage.excludeConnections(deploymentRelationsToExclude);
|
|
1593
|
+
return stage;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
function resolveRelationsBetweenModelElements({ source, target, expr, model }) {
|
|
1598
|
+
const sources = resolveModelElements(model, source);
|
|
1599
|
+
const targets = resolveModelElements(model, target);
|
|
1600
|
+
const dir = expr.isBidirectional ? "both" : "directed";
|
|
1601
|
+
const modelConnections = [];
|
|
1602
|
+
for (const source of sources) modelConnections.push(...findConnectionsBetween$3(source, targets, dir));
|
|
1603
|
+
return new Set(modelConnections.flatMap((c) => [...c.relations]));
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
//#endregion
|
|
1607
|
+
//#region src/compute-view/deployment-view/predicates/relation-in-out.ts
|
|
1608
|
+
const InOutRelationPredicate$1 = {
|
|
1609
|
+
include: ({ expr, model, memory, stage, where }) => {
|
|
1610
|
+
const sources = [...memory.elements];
|
|
1611
|
+
if (FqnExpr.isWildcard(expr.inout)) {
|
|
1612
|
+
for (const source of sources) {
|
|
1613
|
+
const toInclude = matchConnections(findConnectionsBetween$1(source, [...resolveAscendingSiblings(source)], "both"), where);
|
|
1614
|
+
stage.addConnections(toInclude);
|
|
1615
|
+
}
|
|
1616
|
+
return stage;
|
|
1617
|
+
}
|
|
1618
|
+
invariant(FqnExpr.isDeploymentRef(expr.inout), "Only deployment refs are supported in include");
|
|
1619
|
+
const targets = resolveElements$1(model, expr.inout);
|
|
1620
|
+
for (const source of sources) {
|
|
1621
|
+
const toInclude = matchConnections(findConnectionsBetween$1(source, targets, "both"), where);
|
|
1622
|
+
stage.addConnections(toInclude);
|
|
1623
|
+
}
|
|
1624
|
+
return stage;
|
|
1625
|
+
},
|
|
1626
|
+
exclude: ({ expr, model, memory, stage, where }) => {
|
|
1627
|
+
if (FqnExpr.isElementTagExpr(expr.inout) || FqnExpr.isElementKindExpr(expr.inout)) throw new Error("element kind and tag expressions are not supported in exclude");
|
|
1628
|
+
if (FqnExpr.isModelRef(expr.inout)) {
|
|
1629
|
+
const elements = resolveModelElements(model, expr.inout);
|
|
1630
|
+
if (elements.length === 0) return stage;
|
|
1631
|
+
return excludeModelRelations(union(/* @__PURE__ */ new Set(), ...elements.flatMap((e) => [e.allIncoming, e.allOutgoing])), {
|
|
1632
|
+
stage,
|
|
1633
|
+
memory
|
|
1634
|
+
}, where);
|
|
1635
|
+
}
|
|
1636
|
+
if (FqnExpr.isWildcard(expr.inout)) return stage;
|
|
1637
|
+
const elements = resolveElements$1(model, expr.inout);
|
|
1638
|
+
const isIncoming = filterIncomingConnections(elements);
|
|
1639
|
+
const isOutgoing = filterOutgoingConnections(elements);
|
|
1640
|
+
const toExclude = t$3(memory.connections, n((c) => isIncoming(c) !== isOutgoing(c)), applyPredicate(where));
|
|
1641
|
+
stage.excludeConnections(toExclude);
|
|
1642
|
+
return stage;
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
|
|
1646
|
+
//#endregion
|
|
1647
|
+
//#region src/compute-view/deployment-view/predicates/relation-where.ts
|
|
1648
|
+
const WhereRelationPredicate = {
|
|
1649
|
+
include: ({ expr, model, memory, stage }) => {
|
|
1650
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
1651
|
+
return predicateToPatch("include", {
|
|
1652
|
+
expr: expr.where.expr,
|
|
1653
|
+
model,
|
|
1654
|
+
stage,
|
|
1655
|
+
memory,
|
|
1656
|
+
where
|
|
1657
|
+
});
|
|
1658
|
+
},
|
|
1659
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
1660
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
1661
|
+
return predicateToPatch("exclude", {
|
|
1662
|
+
expr: expr.where.expr,
|
|
1663
|
+
model,
|
|
1664
|
+
stage,
|
|
1665
|
+
memory,
|
|
1666
|
+
where
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1669
|
+
};
|
|
1670
|
+
|
|
1671
|
+
//#endregion
|
|
1672
|
+
//#region src/compute-view/deployment-view/predicates/wildcard.ts
|
|
1673
|
+
const WildcardPredicate$1 = {
|
|
1674
|
+
include: ({ model, stage, where }) => {
|
|
1675
|
+
const children = [];
|
|
1676
|
+
const rootElements = t$3([...model.roots()], applyElementPredicate(where), t$4((root) => {
|
|
1677
|
+
if (!root.onlyOneInstance()) children.push(...root.children());
|
|
1678
|
+
return root;
|
|
1679
|
+
}));
|
|
1680
|
+
stage.addExplicit(rootElements);
|
|
1681
|
+
if (children.length > 1) stage.addConnections(findConnectionsWithin$1([...rootElements, ...children]));
|
|
1682
|
+
return stage;
|
|
1683
|
+
},
|
|
1684
|
+
exclude: ({ stage, memory, where }) => {
|
|
1685
|
+
const elementsToExclude = t$3([...memory.elements], applyElementPredicate(where));
|
|
1686
|
+
stage.exclude(elementsToExclude);
|
|
1687
|
+
return stage;
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
|
|
1691
|
+
//#endregion
|
|
1692
|
+
//#region src/compute-view/deployment-view/predicates/utils.ts
|
|
1693
|
+
/**
|
|
1694
|
+
* Builds a patch object from an expression
|
|
1695
|
+
*/
|
|
1696
|
+
function predicateToPatch(op, { expr, where, ...ctx }) {
|
|
1697
|
+
switch (true) {
|
|
1698
|
+
case FqnExpr.isElementTagExpr(expr):
|
|
1699
|
+
case FqnExpr.isElementKindExpr(expr): throw new Error("element kind and tag expressions are not supported in deployment view rules");
|
|
1700
|
+
case RelationExpr.isCustom(expr):
|
|
1701
|
+
case FqnExpr.isCustom(expr):
|
|
1702
|
+
case FqnExpr.isModelRef(expr): return;
|
|
1703
|
+
case FqnExpr.isWhere(expr): return WhereDeploymentRefPredicate[op]({
|
|
1704
|
+
...ctx,
|
|
1705
|
+
expr,
|
|
1706
|
+
where
|
|
1707
|
+
});
|
|
1708
|
+
case RelationExpr.isWhere(expr): return WhereRelationPredicate[op]({
|
|
1709
|
+
...ctx,
|
|
1710
|
+
expr,
|
|
1711
|
+
where
|
|
1712
|
+
});
|
|
1713
|
+
case FqnExpr.isDeploymentRef(expr): return DeploymentRefPredicate[op]({
|
|
1714
|
+
...ctx,
|
|
1715
|
+
expr,
|
|
1716
|
+
where
|
|
1717
|
+
});
|
|
1718
|
+
case FqnExpr.isWildcard(expr): return WildcardPredicate$1[op]({
|
|
1719
|
+
...ctx,
|
|
1720
|
+
expr,
|
|
1721
|
+
where
|
|
1722
|
+
});
|
|
1723
|
+
case RelationExpr.isDirect(expr): return DirectRelationPredicate[op]({
|
|
1724
|
+
...ctx,
|
|
1725
|
+
expr,
|
|
1726
|
+
where
|
|
1727
|
+
});
|
|
1728
|
+
case RelationExpr.isInOut(expr): return InOutRelationPredicate$1[op]({
|
|
1729
|
+
...ctx,
|
|
1730
|
+
expr,
|
|
1731
|
+
where
|
|
1732
|
+
});
|
|
1733
|
+
case RelationExpr.isOutgoing(expr): return OutgoingRelationPredicate[op]({
|
|
1734
|
+
...ctx,
|
|
1735
|
+
expr,
|
|
1736
|
+
where
|
|
1737
|
+
});
|
|
1738
|
+
case RelationExpr.isIncoming(expr): return IncomingRelationPredicate[op]({
|
|
1739
|
+
...ctx,
|
|
1740
|
+
expr,
|
|
1741
|
+
where
|
|
1742
|
+
});
|
|
1743
|
+
default: nonexhaustive(expr);
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
function excludeModelRelations(relationsToExclude, { stage, memory }, where, filterConnections = () => true) {
|
|
1747
|
+
if (relationsToExclude.size === 0) return stage;
|
|
1748
|
+
const toExclude = t$3(memory.connections, n((c) => filterConnections(c)), n((c) => hasIntersection(c.relations.model, relationsToExclude)), t$4((c) => c.update({
|
|
1749
|
+
deployment: null,
|
|
1750
|
+
model: intersection(c.relations.model, relationsToExclude)
|
|
1751
|
+
})), applyPredicate(where), n((c) => c.nonEmpty()));
|
|
1752
|
+
if (toExclude.length === 0) return stage;
|
|
1753
|
+
return stage.excludeConnections(toExclude);
|
|
1754
|
+
}
|
|
1755
|
+
function matchConnection(c, where) {
|
|
1756
|
+
return applyPredicate(c, where).nonEmpty();
|
|
1757
|
+
}
|
|
1758
|
+
function applyPredicate(...args) {
|
|
1759
|
+
if (args.length === 1) return (x) => applyPredicate(x, args[0]);
|
|
1760
|
+
const [c, where] = args;
|
|
1761
|
+
if (where === null) return c;
|
|
1762
|
+
if (e$8(c)) return c.map((x) => applyPredicate(x, where)).filter((x) => x.nonEmpty());
|
|
1763
|
+
return c.update({
|
|
1764
|
+
model: new Set([...c.relations.model.values()].filter((r) => where(toFilterableRelation(c)(r)))),
|
|
1765
|
+
deployment: new Set([...c.relations.deployment.values()].filter((r) => where(toFilterableRelation(c)(r))))
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
function applyElementPredicate(...args) {
|
|
1769
|
+
if (args.length === 1) return (x) => applyElementPredicate(x, args[0]);
|
|
1770
|
+
const [c, where] = args;
|
|
1771
|
+
if (e$8(c)) return c.filter((x) => applyElementPredicate(x, where));
|
|
1772
|
+
return where?.(toFilterable(c, c)) ?? true;
|
|
1773
|
+
}
|
|
1774
|
+
function matchConnections(connections, where) {
|
|
1775
|
+
if (!where) return connections;
|
|
1776
|
+
return t$3(connections, n((c) => matchConnection(c, where)));
|
|
1777
|
+
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Builds filterable presentation for relation endpoint. Enriches model properties with deployment properties when needed.
|
|
1780
|
+
* @param relationEndpoint Endpoint for which to build presentation
|
|
1781
|
+
* @param connectionEndpoint Endpoint of connection which was build from the relation.
|
|
1782
|
+
* @returns Presentation of the endpoint for usage in predicates
|
|
1783
|
+
*/
|
|
1784
|
+
function toFilterable(relationEndpoint, connectionEndpoint) {
|
|
1785
|
+
if (isElementModel(relationEndpoint)) {
|
|
1786
|
+
const deployedInstance = isDeploymentElementModel(connectionEndpoint) && isDeployedInstanceModel(connectionEndpoint) ? connectionEndpoint : null;
|
|
1787
|
+
return {
|
|
1788
|
+
kind: relationEndpoint.kind,
|
|
1789
|
+
tags: [...relationEndpoint.tags, ...deployedInstance?.tags ?? []]
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
if (isNestedElementOfDeployedInstanceModel(relationEndpoint)) return t$11(relationEndpoint.element, ["tags", "kind"]);
|
|
1793
|
+
if (isDeployedInstanceModel(relationEndpoint)) return {
|
|
1794
|
+
kind: relationEndpoint.element.kind,
|
|
1795
|
+
tags: [...relationEndpoint.tags, ...relationEndpoint.element.tags]
|
|
1796
|
+
};
|
|
1797
|
+
if (isDeploymentNodeModel(relationEndpoint)) return t$11(relationEndpoint, ["tags", "kind"]);
|
|
1798
|
+
nonexhaustive(relationEndpoint);
|
|
1799
|
+
}
|
|
1800
|
+
function toFilterableRelation(c) {
|
|
1801
|
+
return (relation) => ({
|
|
1802
|
+
tags: relation.tags,
|
|
1803
|
+
kind: relation.kind,
|
|
1804
|
+
source: toFilterable(relation.source, c.source),
|
|
1805
|
+
target: toFilterable(relation.target, c.target)
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
function resolveAscendingSiblings(element) {
|
|
1809
|
+
const siblings = /* @__PURE__ */ new Set();
|
|
1810
|
+
for (let sibling of element.descendingSiblings()) siblings.add(sibling);
|
|
1811
|
+
return siblings;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
//#endregion
|
|
1815
|
+
//#region src/compute-view/deployment-view/predicates/deploymentRefs.ts
|
|
1816
|
+
const DeploymentRefPredicate = {
|
|
1817
|
+
include: (ctx) => {
|
|
1818
|
+
const { expr, where } = ctx;
|
|
1819
|
+
const el = ctx.model.element(expr.ref.deployment);
|
|
1820
|
+
if (isDeployedInstanceModel(el)) {
|
|
1821
|
+
if (applyElementPredicate(el, where)) {
|
|
1822
|
+
ctx.stage.addExplicit(el);
|
|
1823
|
+
ctx.stage.connectWithExisting(el);
|
|
1824
|
+
}
|
|
1825
|
+
return ctx.stage;
|
|
1826
|
+
}
|
|
1827
|
+
switch (true) {
|
|
1828
|
+
case expr.selector === "expanded":
|
|
1829
|
+
includeDeployedNodeWithExpanded(el, ctx);
|
|
1830
|
+
break;
|
|
1831
|
+
case expr.selector === "children":
|
|
1832
|
+
includeDeployedNodeChildren(el, ctx);
|
|
1833
|
+
break;
|
|
1834
|
+
case expr.selector === "descendants":
|
|
1835
|
+
includeDeployedNodeDescendants(el, ctx);
|
|
1836
|
+
break;
|
|
1837
|
+
default: if (applyElementPredicate(el, where)) {
|
|
1838
|
+
ctx.stage.addExplicit(el);
|
|
1839
|
+
ctx.stage.connectWithExisting(el);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
return ctx.stage;
|
|
1843
|
+
},
|
|
1844
|
+
exclude: ({ expr, stage, memory, where }) => {
|
|
1845
|
+
const exprPredicate = deploymentExpressionToPredicate(expr);
|
|
1846
|
+
const toExclude = t$3([...memory.elements], n(exprPredicate), applyElementPredicate(where));
|
|
1847
|
+
stage.exclude(toExclude);
|
|
1848
|
+
return stage;
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
/**
|
|
1852
|
+
* include node.*
|
|
1853
|
+
*/
|
|
1854
|
+
function includeDeployedNodeChildren(node, { stage, where }) {
|
|
1855
|
+
const children = applyElementPredicate([...node.children()], where);
|
|
1856
|
+
if (children.length === 0) return;
|
|
1857
|
+
stage.addImplicit(node);
|
|
1858
|
+
stage.addConnections(findConnectionsWithin$1(children));
|
|
1859
|
+
stage.connectWithExisting(children);
|
|
1860
|
+
stage.addExplicit(children);
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
* include node._
|
|
1864
|
+
*/
|
|
1865
|
+
function includeDeployedNodeWithExpanded(node, { memory, stage, where }) {
|
|
1866
|
+
stage.addImplicit(node);
|
|
1867
|
+
stage.connectWithExisting(node);
|
|
1868
|
+
const children = applyElementPredicate([...node.children()], where);
|
|
1869
|
+
let hasConnectionsWithVisible = false;
|
|
1870
|
+
for (const child of children) if (findConnectionsBetween$1(child, memory.elements).length > 0) {
|
|
1871
|
+
hasConnectionsWithVisible = true;
|
|
1872
|
+
break;
|
|
1873
|
+
}
|
|
1874
|
+
if (hasConnectionsWithVisible) {
|
|
1875
|
+
stage.connectWithExisting(children, "in");
|
|
1876
|
+
stage.addConnections(findConnectionsWithin$1(children));
|
|
1877
|
+
stage.connectWithExisting(children, "out");
|
|
1878
|
+
}
|
|
1879
|
+
stage.addImplicit(children);
|
|
1880
|
+
if (stage.connections.length > 0) stage.addExplicit(node);
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* include node.**
|
|
1884
|
+
*/
|
|
1885
|
+
function includeDeployedNodeDescendants(node, { stage, where }) {
|
|
1886
|
+
const dfs = (node) => {
|
|
1887
|
+
const children = [];
|
|
1888
|
+
for (const child of node.children()) {
|
|
1889
|
+
if (child.isDeploymentNode()) children.push(...dfs(child));
|
|
1890
|
+
if (applyElementPredicate(child, where)) children.push(child);
|
|
1891
|
+
}
|
|
1892
|
+
stage.connectWithExisting(children, "in");
|
|
1893
|
+
stage.addConnections(findConnectionsWithin$1(children));
|
|
1894
|
+
stage.addImplicit(children);
|
|
1895
|
+
return children;
|
|
1896
|
+
};
|
|
1897
|
+
const descendants = dfs(node);
|
|
1898
|
+
if (descendants.length === 0) return;
|
|
1899
|
+
stage.connectWithExisting(descendants, "out");
|
|
1900
|
+
const allConnected = findConnectedElements(stage);
|
|
1901
|
+
t$3(descendants, n((desc) => allConnected.has(desc)), t$6((desc) => stage.addExplicit(desc)));
|
|
1902
|
+
}
|
|
1903
|
+
function findConnectedElements(stage) {
|
|
1904
|
+
return t$3(stage.mergedConnections(), cleanCrossBoundary, cleanRedundantRelationships, t$12((acc, c) => {
|
|
1905
|
+
acc.add(c.source);
|
|
1906
|
+
acc.add(c.target);
|
|
1907
|
+
return acc;
|
|
1908
|
+
}, /* @__PURE__ */ new Set()));
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
//#endregion
|
|
1912
|
+
//#region src/compute-view/deployment-view/stages/stage-final.ts
|
|
1913
|
+
/**
|
|
1914
|
+
* This patch:
|
|
1915
|
+
* 1. Keeps connections between leafs or having direct deployment relations
|
|
1916
|
+
* 2. Removes cross-boundary model relations, that already exist inside boundaries
|
|
1917
|
+
* (e.g. prefer relations inside same deployment node over relations between nodes)
|
|
1918
|
+
* 3. Removes implicit connections between elements, if their descendants have same connection
|
|
1919
|
+
*/
|
|
1920
|
+
var StageFinal$1 = class StageFinal$1 {
|
|
1921
|
+
static for(memory) {
|
|
1922
|
+
return new StageFinal$1(memory);
|
|
1923
|
+
}
|
|
1924
|
+
constructor(memory) {
|
|
1925
|
+
this.memory = memory;
|
|
1926
|
+
}
|
|
1927
|
+
step1CleanConnections(memory) {
|
|
1928
|
+
if (memory.connections.length < 2) return memory;
|
|
1929
|
+
const connections = t$3(memory.connections, cleanCrossBoundary, cleanRedundantRelationships);
|
|
1930
|
+
const connectionsToExclude = differenceConnections(memory.connections, connections);
|
|
1931
|
+
if (connectionsToExclude.length === 0) return memory;
|
|
1932
|
+
const stage = memory.stageExclude({});
|
|
1933
|
+
stage.excludeConnections(connectionsToExclude, true);
|
|
1934
|
+
return stage.commit();
|
|
1935
|
+
}
|
|
1936
|
+
step2ProcessImplicits(memory) {
|
|
1937
|
+
const implicits = union(this.memory.elements, memory.elements);
|
|
1938
|
+
const final = union(memory.final, this.memory.explicits);
|
|
1939
|
+
const groupedByRelation = new import_default_map.default(() => /* @__PURE__ */ new Set());
|
|
1940
|
+
for (const conn of memory.connections) if (conn.boundary) for (const relation of conn.relations.model) groupedByRelation.get(relation).add(conn.boundary);
|
|
1941
|
+
for (const [_, boundaries] of groupedByRelation) {
|
|
1942
|
+
if (boundaries.size < 2) continue;
|
|
1943
|
+
for (const boundary of boundaries) if (implicits.delete(boundary)) final.add(boundary);
|
|
1944
|
+
}
|
|
1945
|
+
const snapshot = new Set(final);
|
|
1946
|
+
const isFinalOrHasIncludedDescendant = (el) => {
|
|
1947
|
+
for (const final of snapshot) if (el === final || isAncestor(el, final)) return true;
|
|
1948
|
+
return false;
|
|
1949
|
+
};
|
|
1950
|
+
t$3(difference(implicits, snapshot), ifilter((e) => e.isDeploymentNode()), toArray(), sortByFqnHierarchically, t$6((el) => {
|
|
1951
|
+
const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length;
|
|
1952
|
+
if (childrensToWrap >= 2) {
|
|
1953
|
+
final.add(el);
|
|
1954
|
+
return;
|
|
1955
|
+
}
|
|
1956
|
+
if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) final.add(el);
|
|
1957
|
+
}));
|
|
1958
|
+
return memory.update({ final });
|
|
1959
|
+
}
|
|
1960
|
+
step3ProcessBoundaries(memory) {
|
|
1961
|
+
const boundaries = /* @__PURE__ */ new Set();
|
|
1962
|
+
for (const conn of memory.connections) if (conn.boundary) boundaries.add(conn.boundary);
|
|
1963
|
+
const tree = treeFromMemoryState(memory, "final");
|
|
1964
|
+
const stage = memory.stageExclude({});
|
|
1965
|
+
const isRemovable = (el) => !(boundaries.has(el) || memory.explicits.has(el) || tree.hasInOut(el) || tree.root.has(el));
|
|
1966
|
+
const singleRoot = t$14([...tree.root]);
|
|
1967
|
+
if (singleRoot && !memory.explicits.has(singleRoot)) stage.exclude(singleRoot);
|
|
1968
|
+
for (const el of memory.final) {
|
|
1969
|
+
const singleChild = t$14(tree.children(el));
|
|
1970
|
+
if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) stage.exclude(el);
|
|
1971
|
+
}
|
|
1972
|
+
if (stage.isDirty()) return stage.commit();
|
|
1973
|
+
return memory;
|
|
1974
|
+
}
|
|
1975
|
+
commit() {
|
|
1976
|
+
const step1 = this.step1CleanConnections(this.memory);
|
|
1977
|
+
const step2 = this.step2ProcessImplicits(step1);
|
|
1978
|
+
return this.step3ProcessBoundaries(step2);
|
|
1979
|
+
}
|
|
1980
|
+
};
|
|
1981
|
+
|
|
1982
|
+
//#endregion
|
|
1983
|
+
//#region src/compute-view/deployment-view/compute.ts
|
|
1984
|
+
function processPredicates$1(model, rules) {
|
|
1985
|
+
let memory = Memory.empty();
|
|
1986
|
+
for (const rule of rules) if (isViewRulePredicate(rule)) {
|
|
1987
|
+
const op = "include" in rule ? "include" : "exclude";
|
|
1988
|
+
const exprs = rule.include ?? rule.exclude;
|
|
1989
|
+
for (const expr of exprs) {
|
|
1990
|
+
let stage = op === "include" ? memory.stageInclude(expr) : memory.stageExclude(expr);
|
|
1991
|
+
stage = predicateToPatch(op, {
|
|
1992
|
+
expr,
|
|
1993
|
+
model,
|
|
1994
|
+
stage,
|
|
1995
|
+
memory,
|
|
1996
|
+
where: null
|
|
1997
|
+
}) ?? stage;
|
|
1998
|
+
memory = stage.commit();
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
return StageFinal$1.for(memory).commit();
|
|
2002
|
+
}
|
|
2003
|
+
function computeDeploymentView(likec4model, { docUri: _docUri, rules, ...view }) {
|
|
2004
|
+
const memory = processPredicates$1(likec4model.deployment, rules);
|
|
2005
|
+
const nodesMap = buildNodes$1(likec4model, memory);
|
|
2006
|
+
const computedEdges = toComputedEdges$1(memory.connections);
|
|
2007
|
+
linkNodesWithEdges(nodesMap, computedEdges);
|
|
2008
|
+
const sorted = topologicalSort({
|
|
2009
|
+
nodes: nodesMap,
|
|
2010
|
+
edges: computedEdges
|
|
2011
|
+
});
|
|
2012
|
+
const nodes = applyDeploymentViewRuleStyles(rules, sorted.nodes);
|
|
2013
|
+
const autoLayoutRule = t$21(rules, isViewRuleAutoLayout);
|
|
2014
|
+
const elementNotations = buildElementNotations(nodes);
|
|
2015
|
+
return calcViewLayoutHash({
|
|
2016
|
+
...view,
|
|
2017
|
+
[_stage]: "computed",
|
|
2018
|
+
[_type]: "deployment",
|
|
2019
|
+
autoLayout: {
|
|
2020
|
+
direction: autoLayoutRule?.direction ?? "TB",
|
|
2021
|
+
...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
|
|
2022
|
+
...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
|
|
2023
|
+
},
|
|
2024
|
+
edges: sorted.edges,
|
|
2025
|
+
nodes: t$4(nodes, (n) => {
|
|
2026
|
+
if (n.icon === "none") delete n.icon;
|
|
2027
|
+
return n;
|
|
2028
|
+
}),
|
|
2029
|
+
...elementNotations.length > 0 && { notation: { nodes: elementNotations } }
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
//#endregion
|
|
2034
|
+
//#region src/compute-view/utils/applyCustomElementProperties.ts
|
|
2035
|
+
function flattenGroupRules(guard) {
|
|
2036
|
+
return (rule) => {
|
|
2037
|
+
if (isViewRuleGroup(rule)) return rule.groupRules.flatMap(flattenGroupRules(guard));
|
|
2038
|
+
if (isViewRulePredicate(rule)) return "include" in rule ? rule.include.filter(guard) : [];
|
|
2039
|
+
return [];
|
|
2040
|
+
};
|
|
2041
|
+
}
|
|
2042
|
+
function applyCustomElementProperties(_rules, _nodes) {
|
|
2043
|
+
const rules = _rules.flatMap(flattenGroupRules(ModelFqnExpr.isCustom));
|
|
2044
|
+
if (rules.length === 0) return _nodes;
|
|
2045
|
+
const nodes = [..._nodes];
|
|
2046
|
+
for (const { custom: { expr, ...props } } of rules) {
|
|
2047
|
+
const { border, opacity, multiple, iconColor, iconSize, iconPosition, padding, size, textSize, description, ...rest } = t$22(props, e$5);
|
|
2048
|
+
const style = exact({
|
|
2049
|
+
border,
|
|
2050
|
+
opacity,
|
|
2051
|
+
multiple,
|
|
2052
|
+
iconColor,
|
|
2053
|
+
iconSize,
|
|
2054
|
+
iconPosition,
|
|
2055
|
+
padding,
|
|
2056
|
+
size,
|
|
2057
|
+
textSize
|
|
2058
|
+
});
|
|
2059
|
+
const styleNotEmpty = !e$2(style);
|
|
2060
|
+
const propsNotEmpty = !e$2(rest);
|
|
2061
|
+
const satisfies = elementExprToPredicate(expr);
|
|
2062
|
+
nodes.forEach((node, i) => {
|
|
2063
|
+
if (isGroupElementKind(node) || !satisfies(node)) return;
|
|
2064
|
+
if (propsNotEmpty) node = {
|
|
2065
|
+
...node,
|
|
2066
|
+
isCustomized: true,
|
|
2067
|
+
...rest
|
|
2068
|
+
};
|
|
2069
|
+
if (description !== void 0) node = {
|
|
2070
|
+
...node,
|
|
2071
|
+
isCustomized: true,
|
|
2072
|
+
description
|
|
2073
|
+
};
|
|
2074
|
+
if (styleNotEmpty) node = {
|
|
2075
|
+
...node,
|
|
2076
|
+
isCustomized: true,
|
|
2077
|
+
style: {
|
|
2078
|
+
...node.style,
|
|
2079
|
+
...style
|
|
2080
|
+
}
|
|
2081
|
+
};
|
|
2082
|
+
nodes[i] = node;
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
return nodes;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
//#endregion
|
|
2089
|
+
//#region src/compute-view/utils/resolve-global-rules.ts
|
|
2090
|
+
function resolveGlobalRulesInElementView(rules, globals) {
|
|
2091
|
+
return rules.reduce((acc, rule) => {
|
|
2092
|
+
if (isViewRuleGlobalPredicateRef(rule)) {
|
|
2093
|
+
const globalPredicates = globals.predicates[rule.predicateId];
|
|
2094
|
+
if (e$5(globalPredicates)) return acc;
|
|
2095
|
+
return acc.concat(globalPredicates);
|
|
2096
|
+
}
|
|
2097
|
+
if (isViewRuleGlobalStyle(rule)) {
|
|
2098
|
+
const globalStyles = globals.styles[rule.styleId];
|
|
2099
|
+
if (e$5(globalStyles)) return acc;
|
|
2100
|
+
return acc.concat(globalStyles);
|
|
2101
|
+
}
|
|
2102
|
+
acc.push(rule);
|
|
2103
|
+
return acc;
|
|
2104
|
+
}, []);
|
|
2105
|
+
}
|
|
2106
|
+
function resolveGlobalRulesInDynamicView(rules, globals) {
|
|
2107
|
+
return rules.reduce((acc, rule) => {
|
|
2108
|
+
if (isViewRuleGlobalPredicateRef(rule)) {
|
|
2109
|
+
const globalPredicates = globals.dynamicPredicates[rule.predicateId];
|
|
2110
|
+
if (e$5(globalPredicates)) return acc;
|
|
2111
|
+
return acc.concat(globalPredicates);
|
|
2112
|
+
}
|
|
2113
|
+
if (isViewRuleGlobalStyle(rule)) {
|
|
2114
|
+
const globalStyles = globals.styles[rule.styleId];
|
|
2115
|
+
if (e$5(globalStyles)) return acc;
|
|
2116
|
+
return acc.concat(globalStyles);
|
|
2117
|
+
}
|
|
2118
|
+
acc.push(rule);
|
|
2119
|
+
return acc;
|
|
2120
|
+
}, []);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
//#endregion
|
|
2124
|
+
//#region src/compute-view/dynamic-view/utils.ts
|
|
2125
|
+
function elementsFromIncludeProperties(model, resolvedRules) {
|
|
2126
|
+
const explicits = /* @__PURE__ */ new Set();
|
|
2127
|
+
for (const rule of resolvedRules) if (isViewRulePredicate(rule)) for (const expr of rule.include) {
|
|
2128
|
+
const satisfies = elementExprToPredicate(expr);
|
|
2129
|
+
for (const e of model.elements()) if (satisfies(e)) explicits.add(e);
|
|
2130
|
+
}
|
|
2131
|
+
return explicits;
|
|
2132
|
+
}
|
|
2133
|
+
const flattenSteps = (s) => {
|
|
2134
|
+
if (isDynamicStepsParallel(s)) {
|
|
2135
|
+
const heads = [];
|
|
2136
|
+
const tails = [];
|
|
2137
|
+
for (const step of s.__parallel) if (isDynamicStepsSeries(step)) {
|
|
2138
|
+
const [head, ...tail] = step.__series;
|
|
2139
|
+
heads.push(head);
|
|
2140
|
+
tails.push(...tail);
|
|
2141
|
+
} else heads.push(step);
|
|
2142
|
+
return [...heads, ...tails];
|
|
2143
|
+
}
|
|
2144
|
+
if (isDynamicStepsSeries(s)) return [...s.__series];
|
|
2145
|
+
return s;
|
|
2146
|
+
};
|
|
2147
|
+
function elementsFromSteps(model, steps) {
|
|
2148
|
+
const actors = [];
|
|
2149
|
+
const addActor = (...[source, target]) => {
|
|
2150
|
+
if (!actors.includes(source)) {
|
|
2151
|
+
const indexOfTarget = actors.indexOf(target);
|
|
2152
|
+
if (indexOfTarget > 0) {
|
|
2153
|
+
actors.splice(indexOfTarget, 0, source);
|
|
2154
|
+
return;
|
|
2155
|
+
} else actors.push(source);
|
|
2156
|
+
}
|
|
2157
|
+
if (!actors.includes(target)) actors.push(target);
|
|
2158
|
+
};
|
|
2159
|
+
for (const step of t$17(steps, flattenSteps)) {
|
|
2160
|
+
const source = model.element(step.source);
|
|
2161
|
+
const target = model.element(step.target);
|
|
2162
|
+
let sourceColumn = actors.indexOf(source);
|
|
2163
|
+
let targetColumn = actors.indexOf(target);
|
|
2164
|
+
if (sourceColumn >= 0 && targetColumn >= 0) continue;
|
|
2165
|
+
if (step.isBackward) addActor(target, source);
|
|
2166
|
+
else addActor(source, target);
|
|
2167
|
+
}
|
|
2168
|
+
return new Set(actors);
|
|
2169
|
+
}
|
|
2170
|
+
function findRelations(source, target, currentViewId) {
|
|
2171
|
+
const relationships = findConnection$3(source, target, "directed").flatMap((r) => [...r.relations]).sort(compareRelations);
|
|
2172
|
+
if (!isNonEmptyArray(relationships)) return {};
|
|
2173
|
+
if (relationships.length === 1) {
|
|
2174
|
+
const relation = relationships[0];
|
|
2175
|
+
return exact({
|
|
2176
|
+
title: relation.title ?? void 0,
|
|
2177
|
+
kind: relation.kind ?? void 0,
|
|
2178
|
+
tags: relation.tags,
|
|
2179
|
+
relations: [relation.id],
|
|
2180
|
+
navigateTo: relation.$relationship.navigateTo,
|
|
2181
|
+
color: relation.$relationship.color,
|
|
2182
|
+
line: relation.$relationship.line,
|
|
2183
|
+
technology: relation.technology ?? void 0,
|
|
2184
|
+
description: relation.$relationship.description ?? void 0
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
const alltags = t$3(relationships, t$17((r) => r.tags), n$3());
|
|
2188
|
+
const tags = t$16(alltags, 1) ? alltags : void 0;
|
|
2189
|
+
const relations = t$4(relationships, (r) => r.id);
|
|
2190
|
+
let navigateTo = n$4(relationships).$relationship.navigateTo;
|
|
2191
|
+
if (navigateTo === currentViewId) navigateTo = void 0;
|
|
2192
|
+
if (!navigateTo) navigateTo = t$3(relationships, t$17((r) => r.$relationship.navigateTo && r.$relationship.navigateTo !== currentViewId ? r.$relationship.navigateTo : []), n$3(), t$14());
|
|
2193
|
+
const commonProperties = t$3(relationships, t$12((acc, { title, technology, $relationship: r }) => {
|
|
2194
|
+
e(title) && acc.title.add(title);
|
|
2195
|
+
e(r.color) && acc.color.add(r.color);
|
|
2196
|
+
e(r.line) && acc.line.add(r.line);
|
|
2197
|
+
e(r.kind) && acc.kind.add(r.kind);
|
|
2198
|
+
e(technology) && acc.technology.add(technology);
|
|
2199
|
+
if (e(r.description) && !acc.description.some(t$13(r.description))) acc.description.push(r.description);
|
|
2200
|
+
return acc;
|
|
2201
|
+
}, {
|
|
2202
|
+
kind: /* @__PURE__ */ new Set(),
|
|
2203
|
+
color: /* @__PURE__ */ new Set(),
|
|
2204
|
+
line: /* @__PURE__ */ new Set(),
|
|
2205
|
+
title: /* @__PURE__ */ new Set(),
|
|
2206
|
+
technology: /* @__PURE__ */ new Set(),
|
|
2207
|
+
description: []
|
|
2208
|
+
}));
|
|
2209
|
+
return exact({
|
|
2210
|
+
tags: tags ?? void 0,
|
|
2211
|
+
relations,
|
|
2212
|
+
navigateTo,
|
|
2213
|
+
kind: t$14([...commonProperties.kind]),
|
|
2214
|
+
title: t$14([...commonProperties.title]),
|
|
2215
|
+
color: t$14([...commonProperties.color]),
|
|
2216
|
+
line: t$14([...commonProperties.line]),
|
|
2217
|
+
technology: t$14([...commonProperties.technology]),
|
|
2218
|
+
description: t$14(commonProperties.description)
|
|
2219
|
+
});
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
//#endregion
|
|
2223
|
+
//#region src/compute-view/dynamic-view/compute.ts
|
|
2224
|
+
var DynamicViewCompute = class {
|
|
2225
|
+
steps = [];
|
|
2226
|
+
constructor(model, view) {
|
|
2227
|
+
this.model = model;
|
|
2228
|
+
this.view = view;
|
|
2229
|
+
}
|
|
2230
|
+
compute() {
|
|
2231
|
+
const { docUri: _docUri, rules: _rules, steps: viewSteps, ...view } = this.view;
|
|
2232
|
+
const rules = resolveGlobalRulesInDynamicView(_rules, this.model.globals);
|
|
2233
|
+
const explicits = elementsFromIncludeProperties(this.model, rules);
|
|
2234
|
+
const fromSteps = elementsFromSteps(this.model, viewSteps);
|
|
2235
|
+
const actors = t$3(union(intersection(explicits, fromSteps), fromSteps, explicits), toArray(), sortParentsFirst);
|
|
2236
|
+
const compounds = actors.reduce((acc, actor, index, all) => {
|
|
2237
|
+
for (let i = index + 1; i < all.length; i++) {
|
|
2238
|
+
const other = all[i];
|
|
2239
|
+
if (isAncestor(actor, other)) {
|
|
2240
|
+
acc.push(actor);
|
|
2241
|
+
break;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return acc;
|
|
2245
|
+
}, []);
|
|
2246
|
+
const processStep = (step, stepNum, prefix) => {
|
|
2247
|
+
if (isDynamicStepsSeries(step)) {
|
|
2248
|
+
for (const s of step.__series) stepNum = processStep(s, stepNum, prefix);
|
|
2249
|
+
return stepNum;
|
|
2250
|
+
}
|
|
2251
|
+
const id = prefix ? stepEdgeId(prefix, stepNum) : stepEdgeId(stepNum);
|
|
2252
|
+
const { source: stepSource, target: stepTarget, title: stepTitle, isBackward: _isBackward, navigateTo: stepNavigateTo, notation: _notation, ...rest } = step;
|
|
2253
|
+
const source = this.model.element(stepSource);
|
|
2254
|
+
const sourceColumn = actors.indexOf(source);
|
|
2255
|
+
invariant(sourceColumn >= 0, `Source ${stepSource} not found`);
|
|
2256
|
+
const target = this.model.element(stepTarget);
|
|
2257
|
+
const targetColumn = actors.indexOf(target);
|
|
2258
|
+
invariant(targetColumn >= 0, `Target ${stepTarget} not found`);
|
|
2259
|
+
if (compounds.includes(source) || compounds.includes(target)) console.error(`Step ${source.id} -> ${target.id} because it involves a compound`);
|
|
2260
|
+
const { title, relations, navigateTo: derivedNavigateTo, ...derived } = findRelations(source, target, this.view.id);
|
|
2261
|
+
const navigateTo = e(stepNavigateTo) && stepNavigateTo !== this.view.id ? stepNavigateTo : derivedNavigateTo;
|
|
2262
|
+
const kindTechnology = step.kind && !step.technology ? this.model.specification.relationships[step.kind]?.technology : void 0;
|
|
2263
|
+
this.steps.push(exact({
|
|
2264
|
+
...derived,
|
|
2265
|
+
...rest,
|
|
2266
|
+
...kindTechnology && { technology: kindTechnology },
|
|
2267
|
+
id,
|
|
2268
|
+
source,
|
|
2269
|
+
target,
|
|
2270
|
+
navigateTo,
|
|
2271
|
+
title: stepTitle ?? title,
|
|
2272
|
+
relations: relations ?? [],
|
|
2273
|
+
isBackward: sourceColumn > targetColumn
|
|
2274
|
+
}));
|
|
2275
|
+
return stepNum + 1;
|
|
2276
|
+
};
|
|
2277
|
+
let stepNum = 1;
|
|
2278
|
+
for (const step of viewSteps) {
|
|
2279
|
+
if (isDynamicStepsParallel(step)) {
|
|
2280
|
+
let nestedStepNum = 1;
|
|
2281
|
+
for (const s of step.__parallel) nestedStepNum = processStep(s, nestedStepNum, stepNum);
|
|
2282
|
+
stepNum++;
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
stepNum = processStep(step, stepNum);
|
|
2286
|
+
}
|
|
2287
|
+
const nodesMap = buildComputedNodes(this.model.$styles, actors.map(elementModelToNodeSource));
|
|
2288
|
+
const defaults = this.model.$styles.defaults.relationship;
|
|
2289
|
+
const edges = this.steps.map(({ id, source, target, relations, title, isBackward, tags, ...step }) => {
|
|
2290
|
+
const sourceNode = nonNullable(nodesMap.get(source.id), `Source node ${source.id} not found`);
|
|
2291
|
+
const targetNode = nonNullable(nodesMap.get(target.id), `Target node ${target.id} not found`);
|
|
2292
|
+
const edge = {
|
|
2293
|
+
id,
|
|
2294
|
+
parent: commonAncestor(source.id, target.id),
|
|
2295
|
+
source: sourceNode.id,
|
|
2296
|
+
target: targetNode.id,
|
|
2297
|
+
label: title ?? null,
|
|
2298
|
+
relations,
|
|
2299
|
+
color: defaults.color,
|
|
2300
|
+
line: defaults.line,
|
|
2301
|
+
head: defaults.arrow,
|
|
2302
|
+
tags: tags ?? [],
|
|
2303
|
+
...step
|
|
2304
|
+
};
|
|
2305
|
+
if (isBackward) edge.dir = "back";
|
|
2306
|
+
while (edge.parent && !nodesMap.has(edge.parent)) edge.parent = parentFqn(edge.parent);
|
|
2307
|
+
sourceNode.outEdges.push(edge.id);
|
|
2308
|
+
targetNode.inEdges.push(edge.id);
|
|
2309
|
+
for (const sourceAncestor of ancestorsFqn(edge.source)) {
|
|
2310
|
+
if (sourceAncestor === edge.parent) break;
|
|
2311
|
+
nodesMap.get(sourceAncestor)?.outEdges.push(edge.id);
|
|
2312
|
+
}
|
|
2313
|
+
for (const targetAncestor of ancestorsFqn(edge.target)) {
|
|
2314
|
+
if (targetAncestor === edge.parent) break;
|
|
2315
|
+
nodesMap.get(targetAncestor)?.inEdges.push(edge.id);
|
|
2316
|
+
}
|
|
2317
|
+
return edge;
|
|
2318
|
+
});
|
|
2319
|
+
const nodes = applyCustomElementProperties(rules, applyViewRuleStyles(rules, actors.map((e) => nonNullable(nodesMap.get(e.id)))));
|
|
2320
|
+
const autoLayoutRule = t$21(rules, isViewRuleAutoLayout);
|
|
2321
|
+
const nodeNotations = buildElementNotations(nodes);
|
|
2322
|
+
return calcViewLayoutHash({
|
|
2323
|
+
...view,
|
|
2324
|
+
[_type]: "dynamic",
|
|
2325
|
+
[_stage]: "computed",
|
|
2326
|
+
variant: view.variant ?? "diagram",
|
|
2327
|
+
autoLayout: {
|
|
2328
|
+
direction: autoLayoutRule?.direction ?? "LR",
|
|
2329
|
+
...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
|
|
2330
|
+
...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
|
|
2331
|
+
},
|
|
2332
|
+
nodes: t$4(nodes, (n) => {
|
|
2333
|
+
if (n.icon === "none") delete n.icon;
|
|
2334
|
+
return n;
|
|
2335
|
+
}),
|
|
2336
|
+
edges,
|
|
2337
|
+
...nodeNotations.length > 0 && { notation: { nodes: nodeNotations } }
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
};
|
|
2341
|
+
function computeDynamicView(model, view) {
|
|
2342
|
+
return new DynamicViewCompute(model, view).compute();
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
//#endregion
|
|
2346
|
+
//#region src/compute-view/utils/relationExpressionToPredicates.ts
|
|
2347
|
+
function relationExpressionToPredicates(expr) {
|
|
2348
|
+
switch (true) {
|
|
2349
|
+
case ModelRelationExpr.isCustom(expr): return relationExpressionToPredicates(expr.customRelation.expr);
|
|
2350
|
+
case ModelRelationExpr.isWhere(expr): {
|
|
2351
|
+
const predicate = relationExpressionToPredicates(expr.where.expr);
|
|
2352
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
2353
|
+
return (e) => predicate(e) && where({
|
|
2354
|
+
source: {
|
|
2355
|
+
tags: e.source.tags,
|
|
2356
|
+
kind: e.source.kind
|
|
2357
|
+
},
|
|
2358
|
+
target: {
|
|
2359
|
+
tags: e.target.tags,
|
|
2360
|
+
kind: e.target.kind
|
|
2361
|
+
},
|
|
2362
|
+
...e.tags && { tags: e.tags },
|
|
2363
|
+
...e.kind && { kind: e.kind }
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
case ModelRelationExpr.isDirect(expr): {
|
|
2367
|
+
const isSource = elementExprToPredicate(expr.source);
|
|
2368
|
+
const isTarget = elementExprToPredicate(expr.target);
|
|
2369
|
+
return (edge) => {
|
|
2370
|
+
return isSource(edge.source) && isTarget(edge.target) || !!expr.isBidirectional && isSource(edge.target) && isTarget(edge.source);
|
|
2371
|
+
};
|
|
2372
|
+
}
|
|
2373
|
+
case ModelRelationExpr.isInOut(expr): {
|
|
2374
|
+
const isInOut = elementExprToPredicate(expr.inout);
|
|
2375
|
+
return (edge) => isInOut(edge.source) || isInOut(edge.target);
|
|
2376
|
+
}
|
|
2377
|
+
case ModelRelationExpr.isIncoming(expr): {
|
|
2378
|
+
const isTarget = elementExprToPredicate(expr.incoming);
|
|
2379
|
+
return (edge) => isTarget(edge.target);
|
|
2380
|
+
}
|
|
2381
|
+
case ModelRelationExpr.isOutgoing(expr): {
|
|
2382
|
+
const isSource = elementExprToPredicate(expr.outgoing);
|
|
2383
|
+
return (edge) => isSource(edge.source);
|
|
2384
|
+
}
|
|
2385
|
+
default: nonexhaustive(expr);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
//#endregion
|
|
2390
|
+
//#region src/compute-view/utils/applyCustomRelationProperties.ts
|
|
2391
|
+
function applyCustomRelationProperties(_rules, nodes, _edges) {
|
|
2392
|
+
const rules = _rules.flatMap(flattenGroupRules(ModelRelationExpr.isCustom));
|
|
2393
|
+
const edges = Array.from(_edges);
|
|
2394
|
+
if (rules.length === 0 || edges.length === 0) return edges;
|
|
2395
|
+
for (const { customRelation: { expr, title, description: _description, notes: _notes, ...customprops } } of rules) {
|
|
2396
|
+
const description = _description ? { description: { txt: _description } } : {};
|
|
2397
|
+
const notes = _notes ? { notes: { txt: _notes } } : {};
|
|
2398
|
+
const props = t$22(customprops, e$5);
|
|
2399
|
+
const satisfies = relationExpressionToPredicates(expr);
|
|
2400
|
+
edges.forEach((edge, i) => {
|
|
2401
|
+
let source, target;
|
|
2402
|
+
for (const node of nodes) {
|
|
2403
|
+
if (node.id === edge.source) source = node;
|
|
2404
|
+
if (node.id === edge.target) target = node;
|
|
2405
|
+
if (source && target) break;
|
|
2406
|
+
}
|
|
2407
|
+
if (!source || !target) return;
|
|
2408
|
+
if (satisfies({
|
|
2409
|
+
source,
|
|
2410
|
+
target,
|
|
2411
|
+
...t$11(edge, ["kind", "tags"])
|
|
2412
|
+
})) edges[i] = {
|
|
2413
|
+
...edge,
|
|
2414
|
+
...props,
|
|
2415
|
+
...description,
|
|
2416
|
+
...notes,
|
|
2417
|
+
label: title ?? edge.label,
|
|
2418
|
+
isCustomized: true
|
|
2419
|
+
};
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
return edges;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
//#endregion
|
|
2426
|
+
//#region src/compute-view/element-view/clean-connections.ts
|
|
2427
|
+
function findRedundantConnections(connections) {
|
|
2428
|
+
return t$3([...connections], mergeConnections, t$12((reducedConnections, connection, _, all) => {
|
|
2429
|
+
const descendants = findDescendantConnections(all, connection);
|
|
2430
|
+
const nestedRelations = union(...descendants.map(e$6("relations")));
|
|
2431
|
+
let accum = intersection(connection.relations, nestedRelations);
|
|
2432
|
+
if (descendants.length > 0) accum = union(accum, connection.directRelations);
|
|
2433
|
+
if (findDeepestNestedConnection(all, connection.reversed())) accum = union(accum, connection.directRelations);
|
|
2434
|
+
if (accum.size < connection.relations.size) {
|
|
2435
|
+
const isSourceExpanded = all.some(isAnyInOut(connection.source));
|
|
2436
|
+
const isTargetExpanded = all.some(isAnyInOut(connection.target));
|
|
2437
|
+
if (isSourceExpanded) accum = union(accum, toSet(ifilter(connection.relations, isOutgoing(connection.source))));
|
|
2438
|
+
if (isTargetExpanded) accum = union(accum, toSet(ifilter(connection.relations, isIncoming(connection.target))));
|
|
2439
|
+
}
|
|
2440
|
+
if (accum.size > 0) reducedConnections.push(connection.update(accum));
|
|
2441
|
+
return reducedConnections;
|
|
2442
|
+
}, []));
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
//#endregion
|
|
2446
|
+
//#region src/compute-view/element-view/memory/stage-final.ts
|
|
2447
|
+
var StageFinal = class StageFinal {
|
|
2448
|
+
static for(memory) {
|
|
2449
|
+
return new StageFinal(memory);
|
|
2450
|
+
}
|
|
2451
|
+
constructor(memory) {
|
|
2452
|
+
this.memory = memory;
|
|
2453
|
+
}
|
|
2454
|
+
step1CleanConnections(memory) {
|
|
2455
|
+
if (memory.connections.length < 2) return memory;
|
|
2456
|
+
const connectionsToExclude = findRedundantConnections(memory.connections);
|
|
2457
|
+
if (connectionsToExclude.length === 0) return memory;
|
|
2458
|
+
const stage = memory.stageExclude({});
|
|
2459
|
+
stage.excludeConnections(connectionsToExclude, true);
|
|
2460
|
+
return stage.commit();
|
|
2461
|
+
}
|
|
2462
|
+
step2ProcessImplicits(memory) {
|
|
2463
|
+
const implicits = union(this.memory.elements, memory.elements);
|
|
2464
|
+
const final = union(memory.final, this.memory.explicits);
|
|
2465
|
+
const snapshot = new Set(final);
|
|
2466
|
+
const isFinalOrHasIncludedDescendant = (el) => {
|
|
2467
|
+
for (const final of snapshot) if (el === final || isAncestor(el, final)) return true;
|
|
2468
|
+
return false;
|
|
2469
|
+
};
|
|
2470
|
+
t$3(difference(implicits, snapshot), toArray(), sortByFqnHierarchically, t$6((el) => {
|
|
2471
|
+
const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length;
|
|
2472
|
+
if (childrensToWrap >= 2) {
|
|
2473
|
+
final.add(el);
|
|
2474
|
+
return;
|
|
2475
|
+
}
|
|
2476
|
+
if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) final.add(el);
|
|
2477
|
+
}));
|
|
2478
|
+
return memory.update({ final });
|
|
2479
|
+
}
|
|
2480
|
+
step3ProcessBoundaries(memory) {
|
|
2481
|
+
const boundaries = /* @__PURE__ */ new Set();
|
|
2482
|
+
for (const conn of memory.connections) if (conn.boundary && conn.boundary !== conn.source && conn.boundary !== conn.target) boundaries.add(conn.boundary);
|
|
2483
|
+
const tree = treeFromMemoryState(memory, "final");
|
|
2484
|
+
const stage = memory.stageExclude({});
|
|
2485
|
+
const isRemovable = (el) => !(boundaries.has(el) || memory.explicits.has(el) || tree.hasInOut(el) || tree.root.has(el));
|
|
2486
|
+
const singleRoot = t$14([...tree.root]);
|
|
2487
|
+
if (singleRoot && !memory.explicits.has(singleRoot)) stage.exclude(singleRoot);
|
|
2488
|
+
for (const el of memory.final) {
|
|
2489
|
+
const singleChild = t$14(tree.children(el));
|
|
2490
|
+
if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) stage.exclude(el);
|
|
2491
|
+
}
|
|
2492
|
+
if (stage.isDirty()) return stage.commit();
|
|
2493
|
+
return memory;
|
|
2494
|
+
}
|
|
2495
|
+
commit() {
|
|
2496
|
+
const step1 = this.step1CleanConnections(this.memory);
|
|
2497
|
+
const step2 = this.step2ProcessImplicits(step1);
|
|
2498
|
+
return this.step3ProcessBoundaries(step2);
|
|
2499
|
+
}
|
|
2500
|
+
};
|
|
2501
|
+
|
|
2502
|
+
//#endregion
|
|
2503
|
+
//#region src/compute-view/element-view/predicates/_utils.ts
|
|
2504
|
+
const { findConnection, findConnectionsBetween, findConnectionsWithin } = find_exports$1;
|
|
2505
|
+
/**
|
|
2506
|
+
* Resolve elements from the model based on the given expression
|
|
2507
|
+
*/
|
|
2508
|
+
function resolveElements(model, expr) {
|
|
2509
|
+
switch (true) {
|
|
2510
|
+
case ModelFqnExpr.isElementKindExpr(expr): return [...ifilter(model.elements(), (el) => {
|
|
2511
|
+
return expr.isEqual === (el.kind === expr.elementKind);
|
|
2512
|
+
})];
|
|
2513
|
+
case ModelFqnExpr.isElementTagExpr(expr): return [...ifilter(model.elements(), (el) => {
|
|
2514
|
+
return expr.isEqual === el.tags.includes(expr.elementTag);
|
|
2515
|
+
})];
|
|
2516
|
+
case expr.selector === "expanded": {
|
|
2517
|
+
const element = model.element(FqnRef.flatten(expr.ref));
|
|
2518
|
+
return [element, ...element.children()];
|
|
2519
|
+
}
|
|
2520
|
+
case expr.selector === "children":
|
|
2521
|
+
case expr.selector === "descendants": {
|
|
2522
|
+
const element = model.element(FqnRef.flatten(expr.ref));
|
|
2523
|
+
let children = expr.selector === "children" ? toArray(element.children()) : toArray(element.descendants());
|
|
2524
|
+
return children && children.length > 0 ? children : [element];
|
|
2525
|
+
}
|
|
2526
|
+
case ModelFqnExpr.isModelRef(expr): return [model.element(FqnRef.flatten(expr.ref))];
|
|
2527
|
+
default: nonexhaustive(expr);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
/**
|
|
2531
|
+
* Include elements that are not in the given set but are descendants of the current set
|
|
2532
|
+
* Consider the following example:
|
|
2533
|
+
* a1.* -> b1
|
|
2534
|
+
* If there are a1.a2.a3 and b1.b2 in the memory, but not connected yet - we connect them
|
|
2535
|
+
*/
|
|
2536
|
+
function includeDescendantsFromMemory(elements, memory) {
|
|
2537
|
+
if (memory.isEmpty() || elements.length === 0) return elements;
|
|
2538
|
+
const descedantsOf = t$8(elements.map((e) => isDescendantOf(e)));
|
|
2539
|
+
const fromMemory = toArray(ifilter(memory.elements, (el) => !elements.includes(el) && descedantsOf(el)));
|
|
2540
|
+
return [...elements, ...fromMemory];
|
|
2541
|
+
}
|
|
2542
|
+
/**
|
|
2543
|
+
* Combination of `resolveElements` and `includeDescendantsFromMemory`
|
|
2544
|
+
*/
|
|
2545
|
+
function resolveAndIncludeFromMemory(nonWildcard, { memory, model }) {
|
|
2546
|
+
const resolved = resolveElements(model, nonWildcard);
|
|
2547
|
+
if (ModelFqnExpr.isModelRef(nonWildcard)) {
|
|
2548
|
+
if (nonWildcard.selector === "descendants") return resolved;
|
|
2549
|
+
return includeDescendantsFromMemory(resolved, memory);
|
|
2550
|
+
}
|
|
2551
|
+
return resolved;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
//#endregion
|
|
2555
|
+
//#region src/compute-view/element-view/predicates/element-expand.ts
|
|
2556
|
+
const ExpandedElementPredicate = {
|
|
2557
|
+
include: ({ expr, model, stage, where }) => {
|
|
2558
|
+
const parent = model.element(FqnRef.flatten(expr.ref));
|
|
2559
|
+
if (where(parent)) {
|
|
2560
|
+
stage.addExplicit(parent);
|
|
2561
|
+
stage.connectWithExisting(parent);
|
|
2562
|
+
}
|
|
2563
|
+
const children = [...parent.children()].filter(where);
|
|
2564
|
+
const expanded = [];
|
|
2565
|
+
for (const child of children) {
|
|
2566
|
+
stage.addImplicit(child);
|
|
2567
|
+
if (stage.connectWithExisting(child)) expanded.push(child);
|
|
2568
|
+
}
|
|
2569
|
+
stage.addConnections(findConnectionsWithin(expanded));
|
|
2570
|
+
return stage;
|
|
2571
|
+
},
|
|
2572
|
+
exclude: ({ expr, model, stage, filterWhere }) => {
|
|
2573
|
+
const elements = filterWhere(resolveElements(model, expr));
|
|
2574
|
+
stage.exclude(elements);
|
|
2575
|
+
return stage;
|
|
2576
|
+
}
|
|
2577
|
+
};
|
|
2578
|
+
|
|
2579
|
+
//#endregion
|
|
2580
|
+
//#region src/compute-view/element-view/predicates/element-kind-tag.ts
|
|
2581
|
+
const ElementKindOrTagPredicate = {
|
|
2582
|
+
include: ({ expr, model, stage, filterWhere }) => {
|
|
2583
|
+
const elements = filterWhere(resolveElements(model, expr));
|
|
2584
|
+
if (elements.length === 0) return;
|
|
2585
|
+
stage.addExplicit(elements);
|
|
2586
|
+
stage.connectWithExisting(elements);
|
|
2587
|
+
stage.addConnections(findConnectionsWithin(elements));
|
|
2588
|
+
return stage;
|
|
2589
|
+
},
|
|
2590
|
+
exclude: ({ expr, model, stage, filterWhere }) => {
|
|
2591
|
+
const elements = filterWhere(resolveElements(model, expr));
|
|
2592
|
+
stage.exclude(elements);
|
|
2593
|
+
return stage;
|
|
2594
|
+
}
|
|
2595
|
+
};
|
|
2596
|
+
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/compute-view/element-view/predicates/element-ref.ts
|
|
2599
|
+
const ElementRefPredicate = {
|
|
2600
|
+
include: ({ expr, model, stage, filterWhere }) => {
|
|
2601
|
+
const elements = filterWhere(resolveElements(model, expr));
|
|
2602
|
+
if (elements.length === 0) return;
|
|
2603
|
+
stage.addExplicit(elements);
|
|
2604
|
+
stage.connectWithExisting(elements);
|
|
2605
|
+
stage.addConnections(findConnectionsWithin(elements));
|
|
2606
|
+
return stage;
|
|
2607
|
+
},
|
|
2608
|
+
exclude: ({ expr, model, stage, filterWhere }) => {
|
|
2609
|
+
const elements = filterWhere(resolveElements(model, expr));
|
|
2610
|
+
stage.exclude(elements);
|
|
2611
|
+
return stage;
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
|
|
2615
|
+
//#endregion
|
|
2616
|
+
//#region src/compute-view/element-view/utils.ts
|
|
2617
|
+
const NoWhere = () => true;
|
|
2618
|
+
const NoFilter = (x) => x;
|
|
2619
|
+
function toComputedEdges(connections) {
|
|
2620
|
+
return connections.reduce((acc, e) => {
|
|
2621
|
+
const relations = [...e.relations];
|
|
2622
|
+
invariant(t$16(relations, 1), "Edge must have at least one relation");
|
|
2623
|
+
const $defaults = e.source.$model.$styles.defaults;
|
|
2624
|
+
const source = e.source.id;
|
|
2625
|
+
const target = e.target.id;
|
|
2626
|
+
const { title, color = $defaults.relationship.color, line = $defaults.relationship.line, head = $defaults.relationship.arrow, ...props } = mergePropsFromRelationships(relations.map((r) => r.$relationship), t$14(n(relations, (r) => r.source.id === source && r.target.id === target))?.$relationship);
|
|
2627
|
+
const edge = exact({
|
|
2628
|
+
id: e.id,
|
|
2629
|
+
parent: e.boundary?.id ?? null,
|
|
2630
|
+
source,
|
|
2631
|
+
target,
|
|
2632
|
+
label: title ?? null,
|
|
2633
|
+
relations: relations.map((r) => r.id),
|
|
2634
|
+
color,
|
|
2635
|
+
line,
|
|
2636
|
+
head,
|
|
2637
|
+
...props
|
|
2638
|
+
});
|
|
2639
|
+
acc.push(edge);
|
|
2640
|
+
return acc;
|
|
2641
|
+
}, []);
|
|
2642
|
+
}
|
|
2643
|
+
function buildNodes(model, memory) {
|
|
2644
|
+
return buildComputedNodes(model.$styles, [...memory.final].map(elementModelToNodeSource), memory.groups);
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
//#endregion
|
|
2648
|
+
//#region src/compute-view/element-view/predicates/relation-direct.ts
|
|
2649
|
+
const isWildcard = ModelFqnExpr.isWildcard;
|
|
2650
|
+
const isAncestorOrDescendantOf = (a, b) => a.isAncestorOf(b) || a.isDescendantOf(b);
|
|
2651
|
+
const DirectRelationExprPredicate = {
|
|
2652
|
+
include: ({ expr: { source, target, isBidirectional = false }, memory, model, stage, where, filterWhere }) => {
|
|
2653
|
+
const sourceIsWildcard = isWildcard(source);
|
|
2654
|
+
const targetIsWildcard = isWildcard(target);
|
|
2655
|
+
const connections = [];
|
|
2656
|
+
switch (true) {
|
|
2657
|
+
case sourceIsWildcard && targetIsWildcard && memory.isEmpty() && where !== NoWhere: {
|
|
2658
|
+
const connections = t$3(model.relationships(), ifilter(where), toArray(), t$4((r) => new ConnectionModel(r.source, r.target, new Set([r]))));
|
|
2659
|
+
stage.addConnections(connections);
|
|
2660
|
+
return stage;
|
|
2661
|
+
}
|
|
2662
|
+
case sourceIsWildcard && targetIsWildcard && !memory.isEmpty() && where !== NoWhere:
|
|
2663
|
+
connections.push(...findConnectionsWithin(memory.elements));
|
|
2664
|
+
break;
|
|
2665
|
+
case sourceIsWildcard && targetIsWildcard:
|
|
2666
|
+
connections.push(...findConnectionsWithin(model.roots()));
|
|
2667
|
+
break;
|
|
2668
|
+
case !sourceIsWildcard && targetIsWildcard && where !== NoWhere: {
|
|
2669
|
+
const connections = t$3(resolveElements(model, source), t$17((source) => t$3(source, e$9(e$10(isBidirectional === true), {
|
|
2670
|
+
onTrue: (s) => union(s.allIncoming, s.allOutgoing),
|
|
2671
|
+
onFalse: (s) => s.allOutgoing
|
|
2672
|
+
}), ifilter(where), iunique(), toArray(), t$2((r) => r.source === source), ([outgoing, incoming]) => t$23(t$3(outgoing, n((r) => !isAncestorOrDescendantOf(source, r.target)), t$4((outgoing) => new ConnectionModel(source, outgoing.target, new Set([outgoing])))), t$3(incoming, n((r) => !isAncestorOrDescendantOf(source, r.source)), t$4((incoming) => new ConnectionModel(incoming.source, source, new Set([incoming]))))))));
|
|
2673
|
+
stage.addConnections(connections);
|
|
2674
|
+
return stage;
|
|
2675
|
+
}
|
|
2676
|
+
case !sourceIsWildcard && targetIsWildcard: {
|
|
2677
|
+
const [sources, targets] = resolveWildcard(source, {
|
|
2678
|
+
memory,
|
|
2679
|
+
model
|
|
2680
|
+
});
|
|
2681
|
+
const dir = isBidirectional ? "both" : "directed";
|
|
2682
|
+
for (const source of sources) connections.push(...findConnectionsBetween(source, targets, dir));
|
|
2683
|
+
break;
|
|
2684
|
+
}
|
|
2685
|
+
case sourceIsWildcard && !targetIsWildcard && where !== NoWhere: {
|
|
2686
|
+
const connections = t$3(resolveElements(model, target), t$17((target) => t$3(target, e$9(e$10(isBidirectional === true), {
|
|
2687
|
+
onTrue: (s) => union(s.allIncoming, s.allOutgoing),
|
|
2688
|
+
onFalse: (s) => s.allIncoming
|
|
2689
|
+
}), ifilter(where), toArray(), t$2((r) => r.target === target), ([incoming, outgoing]) => t$23(t$3(outgoing, n((r) => !isAncestorOrDescendantOf(target, r.target)), t$4((outgoing) => new ConnectionModel(target, outgoing.target, new Set([outgoing])))), t$3(incoming, n((r) => !isAncestorOrDescendantOf(target, r.source)), t$4((incoming) => new ConnectionModel(incoming.source, target, new Set([incoming]))))))));
|
|
2690
|
+
stage.addConnections(connections);
|
|
2691
|
+
return stage;
|
|
2692
|
+
}
|
|
2693
|
+
case sourceIsWildcard && !targetIsWildcard: {
|
|
2694
|
+
const [targets, sources] = resolveWildcard(target, {
|
|
2695
|
+
memory,
|
|
2696
|
+
model
|
|
2697
|
+
});
|
|
2698
|
+
const dir = isBidirectional ? "both" : "directed";
|
|
2699
|
+
for (const source of sources) connections.push(...findConnectionsBetween(source, targets, dir));
|
|
2700
|
+
break;
|
|
2701
|
+
}
|
|
2702
|
+
default: {
|
|
2703
|
+
invariant(!isWildcard(source), "Inference failed - source must be not a wildcard");
|
|
2704
|
+
invariant(!isWildcard(target), "Inference failed - target must be not a wildcard");
|
|
2705
|
+
const sources = resolveAndIncludeFromMemory(source, {
|
|
2706
|
+
memory,
|
|
2707
|
+
model
|
|
2708
|
+
});
|
|
2709
|
+
const targets = resolveAndIncludeFromMemory(target, {
|
|
2710
|
+
memory,
|
|
2711
|
+
model
|
|
2712
|
+
});
|
|
2713
|
+
const dir = isBidirectional ? "both" : "directed";
|
|
2714
|
+
for (const source of sources) connections.push(...findConnectionsBetween(source, targets, dir));
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
stage.addConnections(filterWhere(connections));
|
|
2718
|
+
return stage;
|
|
2719
|
+
},
|
|
2720
|
+
exclude: ({ expr: { source, target, isBidirectional }, model, memory, stage, where }) => {
|
|
2721
|
+
const sourceIsWildcard = isWildcard(source);
|
|
2722
|
+
const targetIsWildcard = isWildcard(target);
|
|
2723
|
+
let relations;
|
|
2724
|
+
switch (true) {
|
|
2725
|
+
case sourceIsWildcard && targetIsWildcard:
|
|
2726
|
+
relations = t$3(memory.connections, t$17(t$20(e$6("relations"), ifilter(where), toArray())), toSet());
|
|
2727
|
+
break;
|
|
2728
|
+
case !sourceIsWildcard && targetIsWildcard:
|
|
2729
|
+
relations = t$3(resolveElements(model, source), t$17((source) => t$3(source, e$9(e$10(isBidirectional === true), {
|
|
2730
|
+
onTrue: (s) => union(s.allIncoming, s.allOutgoing),
|
|
2731
|
+
onFalse: (s) => s.allOutgoing
|
|
2732
|
+
}), ifilter(where), toArray())), toSet());
|
|
2733
|
+
break;
|
|
2734
|
+
case sourceIsWildcard && !targetIsWildcard:
|
|
2735
|
+
relations = t$3(resolveElements(model, target), t$17((target) => t$3(target, e$9(e$10(isBidirectional === true), {
|
|
2736
|
+
onTrue: (s) => union(s.allIncoming, s.allOutgoing),
|
|
2737
|
+
onFalse: (s) => s.allIncoming
|
|
2738
|
+
}), ifilter(where), toArray())), toSet());
|
|
2739
|
+
break;
|
|
2740
|
+
default: {
|
|
2741
|
+
invariant(!isWildcard(source), "Inferrence failed - source must be not a wildcard");
|
|
2742
|
+
invariant(!isWildcard(target), "Inferrence failed - target must be not a wildcard");
|
|
2743
|
+
const sources = resolveElements(model, source);
|
|
2744
|
+
const targets = resolveElements(model, target);
|
|
2745
|
+
let accum = /* @__PURE__ */ new Set();
|
|
2746
|
+
for (const source of sources) for (const target of targets) {
|
|
2747
|
+
if (isSameHierarchy(source, target)) continue;
|
|
2748
|
+
accum = union(accum, intersection(source.allOutgoing, target.allIncoming), isBidirectional ? intersection(target.allOutgoing, source.allIncoming) : /* @__PURE__ */ new Set());
|
|
2749
|
+
}
|
|
2750
|
+
relations = toSet(ifilter(accum, where));
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
stage.excludeRelations(relations);
|
|
2754
|
+
return stage;
|
|
2755
|
+
}
|
|
2756
|
+
};
|
|
2757
|
+
/**
|
|
2758
|
+
* Resolve elements for both source and target, when one of them is a wildcard
|
|
2759
|
+
*/
|
|
2760
|
+
function resolveWildcard(nonWildcard, { memory, model }) {
|
|
2761
|
+
let sources = resolveElements(model, nonWildcard);
|
|
2762
|
+
if (!t$16(sources, 1)) return [[], []];
|
|
2763
|
+
if (ModelFqnExpr.isModelRef(nonWildcard)) {
|
|
2764
|
+
const targets = toArray(model.element(FqnRef.flatten(nonWildcard.ref)).ascendingSiblings());
|
|
2765
|
+
return [includeDescendantsFromMemory(sources, memory), includeDescendantsFromMemory(targets, memory)];
|
|
2766
|
+
}
|
|
2767
|
+
return [sources, t$3(sources, t$4((el) => el.ascendingSiblings()), iflat(), iunique(), toArray(), (all) => includeDescendantsFromMemory(all, memory))];
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
//#endregion
|
|
2771
|
+
//#region src/compute-view/element-view/predicates/relation-in.ts
|
|
2772
|
+
const IncomingExprPredicate = {
|
|
2773
|
+
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
2774
|
+
const target = expr.incoming;
|
|
2775
|
+
const connections = [];
|
|
2776
|
+
if (ModelFqnExpr.isWildcard(target)) {
|
|
2777
|
+
if (!scope) return;
|
|
2778
|
+
for (const sibling of scope.ascendingSiblings()) connections.push(...findConnection(sibling, scope, "directed"));
|
|
2779
|
+
} else {
|
|
2780
|
+
const targets = resolveAndIncludeFromMemory(target, {
|
|
2781
|
+
memory,
|
|
2782
|
+
model
|
|
2783
|
+
});
|
|
2784
|
+
const visibleElements = [...memory.elements];
|
|
2785
|
+
if (visibleElements.length === 0) visibleElements.push(...n$3(targets.flatMap((el) => [...el.ascendingSiblings()])));
|
|
2786
|
+
const ensureIncoming = incomingConnectionPredicate(model, target);
|
|
2787
|
+
for (const visible of visibleElements) connections.push(...findConnectionsBetween(visible, targets, "directed").filter(ensureIncoming));
|
|
2788
|
+
}
|
|
2789
|
+
stage.addConnections(filterWhere(connections));
|
|
2790
|
+
return stage;
|
|
2791
|
+
},
|
|
2792
|
+
exclude: ({ expr: { incoming }, model, scope, stage, where }) => {
|
|
2793
|
+
const excluded = [];
|
|
2794
|
+
if (ModelFqnExpr.isWildcard(incoming)) {
|
|
2795
|
+
if (!scope) return;
|
|
2796
|
+
excluded.push(...scope.allIncoming);
|
|
2797
|
+
} else {
|
|
2798
|
+
const elements = resolveElements(model, incoming);
|
|
2799
|
+
excluded.push(...elements.flatMap((e) => [...e.allIncoming]));
|
|
2800
|
+
}
|
|
2801
|
+
stage.excludeRelations(new Set(excluded.filter(where)));
|
|
2802
|
+
return stage;
|
|
2803
|
+
}
|
|
2804
|
+
};
|
|
2805
|
+
function incomingConnectionPredicate(model, expr) {
|
|
2806
|
+
switch (true) {
|
|
2807
|
+
case ModelFqnExpr.isElementKindExpr(expr):
|
|
2808
|
+
case ModelFqnExpr.isElementTagExpr(expr): {
|
|
2809
|
+
const isElement = elementExprToPredicate(expr);
|
|
2810
|
+
return (connection) => isElement(connection.target);
|
|
2811
|
+
}
|
|
2812
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "children": {
|
|
2813
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2814
|
+
return t$8([...model.children(fqn)].map((el) => Connection.isIncoming(el.id)));
|
|
2815
|
+
}
|
|
2816
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "descendants": {
|
|
2817
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2818
|
+
return t$8([Connection.isInside(fqn), ...[...model.children(fqn)].map((el) => Connection.isIncoming(el.id))]);
|
|
2819
|
+
}
|
|
2820
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded": {
|
|
2821
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2822
|
+
return t$8([Connection.isIncoming(fqn), Connection.isInside(fqn)]);
|
|
2823
|
+
}
|
|
2824
|
+
case ModelFqnExpr.isModelRef(expr): {
|
|
2825
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2826
|
+
return Connection.isIncoming(fqn);
|
|
2827
|
+
}
|
|
2828
|
+
default: nonexhaustive(expr);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
//#endregion
|
|
2833
|
+
//#region src/compute-view/element-view/predicates/relation-in-out.ts
|
|
2834
|
+
const InOutRelationPredicate = {
|
|
2835
|
+
include: ({ expr: { inout }, scope, model, memory, stage, filterWhere }) => {
|
|
2836
|
+
const connections = [];
|
|
2837
|
+
if (ModelFqnExpr.isWildcard(inout)) {
|
|
2838
|
+
if (!scope) return;
|
|
2839
|
+
connections.push(...findConnectionsBetween(scope, scope.ascendingSiblings()));
|
|
2840
|
+
} else {
|
|
2841
|
+
const elements = resolveAndIncludeFromMemory(inout, {
|
|
2842
|
+
memory,
|
|
2843
|
+
model
|
|
2844
|
+
});
|
|
2845
|
+
let visibleElements = [...memory.elements];
|
|
2846
|
+
if (visibleElements.length === 0) visibleElements = n$3(elements.flatMap((el) => toArray(el.ascendingSiblings())));
|
|
2847
|
+
for (const el of elements) connections.push(...findConnectionsBetween(el, visibleElements));
|
|
2848
|
+
}
|
|
2849
|
+
stage.addConnections(filterWhere(connections));
|
|
2850
|
+
return stage;
|
|
2851
|
+
},
|
|
2852
|
+
exclude: ({ expr: { inout }, model, scope, stage, where }) => {
|
|
2853
|
+
const excluded = [];
|
|
2854
|
+
if (ModelFqnExpr.isWildcard(inout)) {
|
|
2855
|
+
if (!scope) return;
|
|
2856
|
+
excluded.push(...scope.allOutgoing);
|
|
2857
|
+
excluded.push(...scope.allIncoming);
|
|
2858
|
+
} else {
|
|
2859
|
+
const elements = resolveElements(model, inout);
|
|
2860
|
+
excluded.push(...elements.flatMap((e) => [...e.allOutgoing, ...e.allIncoming]));
|
|
2861
|
+
}
|
|
2862
|
+
stage.excludeRelations(toSet(excluded.filter(where)));
|
|
2863
|
+
return stage;
|
|
2864
|
+
}
|
|
2865
|
+
};
|
|
2866
|
+
|
|
2867
|
+
//#endregion
|
|
2868
|
+
//#region src/compute-view/element-view/predicates/relation-out.ts
|
|
2869
|
+
const OutgoingExprPredicate = {
|
|
2870
|
+
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
2871
|
+
const target = expr.outgoing;
|
|
2872
|
+
const connections = [];
|
|
2873
|
+
if (ModelFqnExpr.isWildcard(target)) {
|
|
2874
|
+
if (!scope) return;
|
|
2875
|
+
connections.push(...findConnectionsBetween(scope, scope.ascendingSiblings(), "directed"));
|
|
2876
|
+
} else {
|
|
2877
|
+
const elements = resolveAndIncludeFromMemory(target, {
|
|
2878
|
+
memory,
|
|
2879
|
+
model
|
|
2880
|
+
});
|
|
2881
|
+
const visibleElements = [...memory.elements];
|
|
2882
|
+
if (visibleElements.length === 0) visibleElements.push(...n$3(elements.flatMap((el) => [...el.ascendingSiblings()])));
|
|
2883
|
+
const ensureOutgoing = outgoingConnectionPredicate(model, target);
|
|
2884
|
+
for (const source of elements) connections.push(...findConnectionsBetween(source, visibleElements, "directed").filter(ensureOutgoing));
|
|
2885
|
+
}
|
|
2886
|
+
stage.addConnections(filterWhere(connections));
|
|
2887
|
+
return stage;
|
|
2888
|
+
},
|
|
2889
|
+
exclude: ({ expr: { outgoing }, model, scope, stage, where }) => {
|
|
2890
|
+
const excluded = [];
|
|
2891
|
+
if (ModelFqnExpr.isWildcard(outgoing)) {
|
|
2892
|
+
if (!scope) return;
|
|
2893
|
+
excluded.push(...scope.allOutgoing);
|
|
2894
|
+
} else {
|
|
2895
|
+
const elements = resolveElements(model, outgoing);
|
|
2896
|
+
excluded.push(...elements.flatMap((e) => [...e.allOutgoing]));
|
|
2897
|
+
}
|
|
2898
|
+
stage.excludeRelations(toSet(excluded.filter(where)));
|
|
2899
|
+
return stage;
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
function outgoingConnectionPredicate(model, expr) {
|
|
2903
|
+
switch (true) {
|
|
2904
|
+
case ModelFqnExpr.isElementKindExpr(expr):
|
|
2905
|
+
case ModelFqnExpr.isElementTagExpr(expr): {
|
|
2906
|
+
const isElement = elementExprToPredicate(expr);
|
|
2907
|
+
return (connection) => isElement(connection.source);
|
|
2908
|
+
}
|
|
2909
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "children": {
|
|
2910
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2911
|
+
return t$8([...model.children(fqn)].map((el) => Connection.isOutgoing(el.id)));
|
|
2912
|
+
}
|
|
2913
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "descendants": {
|
|
2914
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2915
|
+
return t$8([Connection.isInside(fqn), ...[...model.children(fqn)].map((el) => Connection.isOutgoing(el.id))]);
|
|
2916
|
+
}
|
|
2917
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded": {
|
|
2918
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2919
|
+
return t$8([Connection.isOutgoing(fqn), Connection.isInside(fqn)]);
|
|
2920
|
+
}
|
|
2921
|
+
case ModelFqnExpr.isModelRef(expr): {
|
|
2922
|
+
const fqn = FqnRef.flatten(expr.ref);
|
|
2923
|
+
return Connection.isOutgoing(fqn);
|
|
2924
|
+
}
|
|
2925
|
+
default: nonexhaustive(expr);
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
//#endregion
|
|
2930
|
+
//#region src/compute-view/element-view/predicates/wildcard.ts
|
|
2931
|
+
const WildcardPredicate = {
|
|
2932
|
+
include: ({ scope, model, stage, memory, where }) => {
|
|
2933
|
+
if (!scope) {
|
|
2934
|
+
const rootElements = [...model.roots()].filter(where);
|
|
2935
|
+
if (rootElements.length === 0) return;
|
|
2936
|
+
const [projectElements, importedElements] = t$2(rootElements, (e) => !e.imported);
|
|
2937
|
+
stage.addExplicit(projectElements);
|
|
2938
|
+
stage.addImplicit(importedElements);
|
|
2939
|
+
stage.addConnections(findConnectionsWithin(rootElements));
|
|
2940
|
+
stage.connectWithExisting(rootElements);
|
|
2941
|
+
return stage;
|
|
2942
|
+
}
|
|
2943
|
+
const root = where(scope) ? scope : null;
|
|
2944
|
+
const children = toArray(ifilter(scope.children(), where));
|
|
2945
|
+
const hasChildren = children.length > 0;
|
|
2946
|
+
if (!hasChildren) if (!root) return stage;
|
|
2947
|
+
else {
|
|
2948
|
+
if (findConnectionsBetween(root, root.siblings()).length === 0) {
|
|
2949
|
+
const parent = root.parent;
|
|
2950
|
+
if (parent && where(parent)) stage.addExplicit(parent);
|
|
2951
|
+
}
|
|
2952
|
+
children.push(root);
|
|
2953
|
+
}
|
|
2954
|
+
if (root) stage.addExplicit(root);
|
|
2955
|
+
const neighbours = toSet([...memory.elements, ...scope.descendingSiblings()]);
|
|
2956
|
+
for (const neighbour of neighbours) stage.addConnections(findConnectionsBetween(neighbour, children, "directed"));
|
|
2957
|
+
if (hasChildren) {
|
|
2958
|
+
stage.addConnections(findConnectionsWithin(children));
|
|
2959
|
+
stage.addExplicit(children);
|
|
2960
|
+
}
|
|
2961
|
+
for (const child of children) stage.addConnections(findConnectionsBetween(child, neighbours, "directed"));
|
|
2962
|
+
return stage;
|
|
2963
|
+
},
|
|
2964
|
+
exclude: ({ scope, memory, stage, where }) => {
|
|
2965
|
+
if (where !== NoWhere) {
|
|
2966
|
+
stage.exclude(n([...memory.elements], where));
|
|
2967
|
+
return stage;
|
|
2968
|
+
}
|
|
2969
|
+
if (scope) {
|
|
2970
|
+
stage.exclude([scope, ...scope.descendants()]);
|
|
2971
|
+
return stage;
|
|
2972
|
+
}
|
|
2973
|
+
return Memory$1.empty(memory.scope).stageExclude(stage.expression);
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
|
|
2977
|
+
//#endregion
|
|
2978
|
+
//#region src/compute-view/element-view/compute.ts
|
|
2979
|
+
function processElementPredicate(expr, op, ctx) {
|
|
2980
|
+
switch (true) {
|
|
2981
|
+
case ModelFqnExpr.isCustom(expr):
|
|
2982
|
+
if (op === "include") return processElementPredicate(expr.custom.expr, op, ctx);
|
|
2983
|
+
return ctx.stage;
|
|
2984
|
+
case ModelFqnExpr.isWhere(expr): {
|
|
2985
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
2986
|
+
const filterWhere = (elements) => {
|
|
2987
|
+
return n(elements, where);
|
|
2988
|
+
};
|
|
2989
|
+
return processElementPredicate(expr.where.expr, op, {
|
|
2990
|
+
...ctx,
|
|
2991
|
+
where,
|
|
2992
|
+
filterWhere
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
case ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded": return ExpandedElementPredicate[op]({
|
|
2996
|
+
...ctx,
|
|
2997
|
+
expr
|
|
2998
|
+
}) ?? ctx.stage;
|
|
2999
|
+
case ModelFqnExpr.isWildcard(expr): return WildcardPredicate[op]({
|
|
3000
|
+
...ctx,
|
|
3001
|
+
expr
|
|
3002
|
+
}) ?? ctx.stage;
|
|
3003
|
+
case ModelFqnExpr.isElementKindExpr(expr):
|
|
3004
|
+
case ModelFqnExpr.isElementTagExpr(expr): return ElementKindOrTagPredicate[op]({
|
|
3005
|
+
...ctx,
|
|
3006
|
+
expr
|
|
3007
|
+
}) ?? ctx.stage;
|
|
3008
|
+
case ModelFqnExpr.isModelRef(expr): return ElementRefPredicate[op]({
|
|
3009
|
+
...ctx,
|
|
3010
|
+
expr
|
|
3011
|
+
}) ?? ctx.stage;
|
|
3012
|
+
default: nonexhaustive(expr);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
function processRelationtPredicate(expr, op, ctx) {
|
|
3016
|
+
switch (true) {
|
|
3017
|
+
case ModelRelationExpr.isCustom(expr):
|
|
3018
|
+
if (op === "include") return processRelationtPredicate(expr.customRelation.expr, op, ctx);
|
|
3019
|
+
return ctx.stage;
|
|
3020
|
+
case ModelRelationExpr.isWhere(expr): {
|
|
3021
|
+
const where = whereOperatorAsPredicate(expr.where.condition);
|
|
3022
|
+
const filterRelations = (relations) => {
|
|
3023
|
+
return new Set(n([...relations], where));
|
|
3024
|
+
};
|
|
3025
|
+
const filterWhere = (connections) => {
|
|
3026
|
+
return t$3(connections, t$4((c) => new ConnectionModel(c.source, c.target, filterRelations(c.relations))), n((c) => c.nonEmpty()));
|
|
3027
|
+
};
|
|
3028
|
+
return processRelationtPredicate(expr.where.expr, op, {
|
|
3029
|
+
...ctx,
|
|
3030
|
+
where,
|
|
3031
|
+
filterWhere
|
|
3032
|
+
});
|
|
3033
|
+
}
|
|
3034
|
+
case ModelRelationExpr.isInOut(expr): return InOutRelationPredicate[op]({
|
|
3035
|
+
...ctx,
|
|
3036
|
+
expr
|
|
3037
|
+
}) ?? ctx.stage;
|
|
3038
|
+
case ModelRelationExpr.isDirect(expr): return DirectRelationExprPredicate[op]({
|
|
3039
|
+
...ctx,
|
|
3040
|
+
expr
|
|
3041
|
+
}) ?? ctx.stage;
|
|
3042
|
+
case ModelRelationExpr.isOutgoing(expr): return OutgoingExprPredicate[op]({
|
|
3043
|
+
...ctx,
|
|
3044
|
+
expr
|
|
3045
|
+
}) ?? ctx.stage;
|
|
3046
|
+
case ModelRelationExpr.isIncoming(expr): return IncomingExprPredicate[op]({
|
|
3047
|
+
...ctx,
|
|
3048
|
+
expr
|
|
3049
|
+
}) ?? ctx.stage;
|
|
3050
|
+
default: nonexhaustive(expr);
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* Iterates over the rules and applies them to the memory.
|
|
3055
|
+
* If the rule is a group, it recursively processes the group rules.
|
|
3056
|
+
*/
|
|
3057
|
+
function process_predicates(model, memory, rules) {
|
|
3058
|
+
const ctx = {
|
|
3059
|
+
model,
|
|
3060
|
+
scope: memory.scope,
|
|
3061
|
+
where: NoWhere,
|
|
3062
|
+
filterWhere: NoFilter
|
|
3063
|
+
};
|
|
3064
|
+
for (const rule of rules) {
|
|
3065
|
+
if (isViewRuleGroup(rule)) {
|
|
3066
|
+
memory = process_predicates(model, ActiveGroupMemory.enter(memory, rule), rule.groupRules);
|
|
3067
|
+
invariant(memory instanceof ActiveGroupMemory, "processPredicates must return ActiveGroupMemory");
|
|
3068
|
+
memory = memory.leave();
|
|
3069
|
+
continue;
|
|
3070
|
+
}
|
|
3071
|
+
if (isViewRulePredicate(rule)) {
|
|
3072
|
+
const op = "include" in rule ? "include" : "exclude";
|
|
3073
|
+
const exprs = rule.include ?? rule.exclude;
|
|
3074
|
+
for (const expr of exprs) {
|
|
3075
|
+
let stage = op === "include" ? memory.stageInclude(expr) : memory.stageExclude(expr);
|
|
3076
|
+
switch (true) {
|
|
3077
|
+
case ModelExpression.isFqnExpr(expr):
|
|
3078
|
+
stage = processElementPredicate(expr, op, {
|
|
3079
|
+
...ctx,
|
|
3080
|
+
stage,
|
|
3081
|
+
memory
|
|
3082
|
+
}) ?? stage;
|
|
3083
|
+
break;
|
|
3084
|
+
case ModelExpression.isRelationExpr(expr):
|
|
3085
|
+
stage = processRelationtPredicate(expr, op, {
|
|
3086
|
+
...ctx,
|
|
3087
|
+
stage,
|
|
3088
|
+
memory
|
|
3089
|
+
}) ?? stage;
|
|
3090
|
+
break;
|
|
3091
|
+
default: nonexhaustive(expr);
|
|
3092
|
+
}
|
|
3093
|
+
memory = stage.commit();
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
return memory;
|
|
3098
|
+
}
|
|
3099
|
+
function processPredicates(model, memory, rules) {
|
|
3100
|
+
memory = process_predicates(model, memory, rules);
|
|
3101
|
+
return StageFinal.for(memory).commit();
|
|
3102
|
+
}
|
|
3103
|
+
function computeElementView(likec4model, { docUri: _docUri, rules: _rules, ...view }) {
|
|
3104
|
+
const rules = resolveGlobalRulesInElementView(_rules, likec4model.globals);
|
|
3105
|
+
const scope = view.viewOf ? likec4model.asComputed.element(view.viewOf) : null;
|
|
3106
|
+
let memory = processPredicates(likec4model, Memory$1.empty(scope), rules);
|
|
3107
|
+
if (memory.isEmpty() && scope) memory = memory.update({ final: new Set([scope]) });
|
|
3108
|
+
memory = assignElementsToGroups(memory);
|
|
3109
|
+
const nodesMap = buildNodes(likec4model, memory);
|
|
3110
|
+
const computedEdges = toComputedEdges(memory.connections);
|
|
3111
|
+
linkNodesWithEdges(nodesMap, computedEdges);
|
|
3112
|
+
const sorted = topologicalSort({
|
|
3113
|
+
nodes: nodesMap,
|
|
3114
|
+
edges: computedEdges
|
|
3115
|
+
});
|
|
3116
|
+
const nodes = applyCustomElementProperties(rules, applyViewRuleStyles(rules, sorted.nodes));
|
|
3117
|
+
const autoLayoutRule = t$21(rules, isViewRuleAutoLayout);
|
|
3118
|
+
const nodeNotations = buildElementNotations(nodes);
|
|
3119
|
+
const ranks = collectRankConstraints(rules, nodes);
|
|
3120
|
+
return calcViewLayoutHash({
|
|
3121
|
+
...view,
|
|
3122
|
+
_stage: "computed",
|
|
3123
|
+
autoLayout: {
|
|
3124
|
+
direction: autoLayoutRule?.direction ?? "TB",
|
|
3125
|
+
...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
|
|
3126
|
+
...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
|
|
3127
|
+
},
|
|
3128
|
+
edges: applyCustomRelationProperties(rules, nodes, sorted.edges),
|
|
3129
|
+
nodes: t$4(nodes, (n) => {
|
|
3130
|
+
if (n.icon === "none") delete n.icon;
|
|
3131
|
+
return n;
|
|
3132
|
+
}),
|
|
3133
|
+
...nodeNotations.length > 0 && { notation: { nodes: nodeNotations } },
|
|
3134
|
+
...ranks.length > 0 && { ranks }
|
|
3135
|
+
});
|
|
3136
|
+
}
|
|
3137
|
+
function collectRankConstraints(rules, nodes) {
|
|
3138
|
+
const constraints = [];
|
|
3139
|
+
for (const rule of rules) {
|
|
3140
|
+
if (!isViewRuleRank(rule) || rule.targets.length === 0) continue;
|
|
3141
|
+
const nodesInRank = t$3(nodes, n(t$8(rule.targets.map(elementExprToPredicate))), t$4((n) => n.id));
|
|
3142
|
+
if (!t$16(nodesInRank, 1)) continue;
|
|
3143
|
+
constraints.push({
|
|
3144
|
+
type: rule.rank,
|
|
3145
|
+
nodes: nodesInRank
|
|
3146
|
+
});
|
|
3147
|
+
}
|
|
3148
|
+
return constraints;
|
|
3149
|
+
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Clean up group.explicits and group.implicits
|
|
3152
|
+
*/
|
|
3153
|
+
function assignElementsToGroups(memory) {
|
|
3154
|
+
if (memory.groups.length === 0) return memory;
|
|
3155
|
+
const groupAssignments = new import_default_map.default(() => /* @__PURE__ */ new Set());
|
|
3156
|
+
const assignedTo = /* @__PURE__ */ new Map();
|
|
3157
|
+
const isAncestorAssigned = (el) => {
|
|
3158
|
+
for (const parent of el.ancestors()) {
|
|
3159
|
+
const groupId = assignedTo.get(parent);
|
|
3160
|
+
if (groupId) {
|
|
3161
|
+
assignedTo.set(el, groupId);
|
|
3162
|
+
groupAssignments.get(groupId).add(el);
|
|
3163
|
+
return true;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
return false;
|
|
3167
|
+
};
|
|
3168
|
+
const isDescendantAssigned = (el) => {
|
|
3169
|
+
for (const descendant of el.descendants("asc")) {
|
|
3170
|
+
const groupId = assignedTo.get(descendant);
|
|
3171
|
+
if (groupId) {
|
|
3172
|
+
assignedTo.set(el, groupId);
|
|
3173
|
+
groupAssignments.get(groupId).add(el);
|
|
3174
|
+
return true;
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
return false;
|
|
3178
|
+
};
|
|
3179
|
+
t$3(sortParentsFirst([...memory.explicitFirstSeenIn.keys()]), t$6((el) => {
|
|
3180
|
+
if (!isAncestorAssigned(el)) {
|
|
3181
|
+
const groupId = nonNullable(memory.explicitFirstSeenIn.get(el));
|
|
3182
|
+
assignedTo.set(el, groupId);
|
|
3183
|
+
groupAssignments.get(groupId).add(el);
|
|
3184
|
+
}
|
|
3185
|
+
}));
|
|
3186
|
+
t$3(sortParentsFirst([...memory.lastSeenIn.keys()]), n((el) => !assignedTo.has(el)), t$6((el) => {
|
|
3187
|
+
if (isAncestorAssigned(el)) return;
|
|
3188
|
+
if (isDescendantAssigned(el)) return;
|
|
3189
|
+
const groupId = nonNullable(memory.lastSeenIn.get(el));
|
|
3190
|
+
assignedTo.set(el, groupId);
|
|
3191
|
+
groupAssignments.get(groupId).add(el);
|
|
3192
|
+
}));
|
|
3193
|
+
if (groupAssignments.size === 0) return memory;
|
|
3194
|
+
let groups = memory.groups.map((group) => {
|
|
3195
|
+
const explicits = groupAssignments.get(group.id);
|
|
3196
|
+
if (!explicits) return group;
|
|
3197
|
+
return group.update(explicits);
|
|
3198
|
+
});
|
|
3199
|
+
return memory.update({ groups });
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
//#endregion
|
|
3203
|
+
//#region src/compute-view/compute-view.ts
|
|
3204
|
+
function unsafeComputeView(viewsource, likec4model) {
|
|
3205
|
+
switch (true) {
|
|
3206
|
+
case isElementView(viewsource): return computeElementView(likec4model, viewsource);
|
|
3207
|
+
case isDeploymentView(viewsource): return computeDeploymentView(likec4model, viewsource);
|
|
3208
|
+
case isDynamicView(viewsource): return computeDynamicView(likec4model, viewsource);
|
|
3209
|
+
default: nonexhaustive(viewsource);
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
function computeView(viewsource, likec4model) {
|
|
3213
|
+
try {
|
|
3214
|
+
return {
|
|
3215
|
+
isSuccess: true,
|
|
3216
|
+
view: unsafeComputeView(viewsource, likec4model)
|
|
3217
|
+
};
|
|
3218
|
+
} catch (e) {
|
|
3219
|
+
return {
|
|
3220
|
+
isSuccess: false,
|
|
3221
|
+
error: e instanceof Error ? e : /* @__PURE__ */ new Error(`Unknown error: ${e}`),
|
|
3222
|
+
view: void 0
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
function computeParsedModelData(parsed) {
|
|
3227
|
+
const likec4model = LikeC4Model.create(parsed);
|
|
3228
|
+
let { views: _views, _stage: __omitted, ...rest } = parsed;
|
|
3229
|
+
const views = t$24(_views, (v) => unsafeComputeView(v, likec4model));
|
|
3230
|
+
return {
|
|
3231
|
+
[_stage]: "computed",
|
|
3232
|
+
...rest,
|
|
3233
|
+
views
|
|
3234
|
+
};
|
|
3235
|
+
}
|
|
3236
|
+
function computeLikeC4Model(parsed) {
|
|
3237
|
+
return LikeC4Model.create(computeParsedModelData(parsed));
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
//#endregion
|
|
3241
|
+
//#region src/builder/Builder.view-element.ts
|
|
3242
|
+
const asTypedExpr = (expr) => {
|
|
3243
|
+
return expr;
|
|
3244
|
+
};
|
|
3245
|
+
function $expr(expr) {
|
|
3246
|
+
if (!e$11(expr)) return expr;
|
|
3247
|
+
if (expr === "*") return asTypedExpr({ wildcard: true });
|
|
3248
|
+
if (expr.startsWith("->")) {
|
|
3249
|
+
if (expr.endsWith("->")) return asTypedExpr({ inout: $expr(expr.replace(/->/g, "").trim()) });
|
|
3250
|
+
return asTypedExpr({ incoming: $expr(expr.replace("-> ", "")) });
|
|
3251
|
+
}
|
|
3252
|
+
if (expr.endsWith(" ->")) return asTypedExpr({ outgoing: $expr(expr.replace(" ->", "")) });
|
|
3253
|
+
if (expr.includes(" <-> ")) {
|
|
3254
|
+
const [source, target] = expr.split(" <-> ");
|
|
3255
|
+
return asTypedExpr({
|
|
3256
|
+
source: $expr(source),
|
|
3257
|
+
target: $expr(target),
|
|
3258
|
+
isBidirectional: true
|
|
3259
|
+
});
|
|
3260
|
+
}
|
|
3261
|
+
if (expr.includes(" -> ")) {
|
|
3262
|
+
const [source, target] = expr.split(" -> ");
|
|
3263
|
+
return asTypedExpr({
|
|
3264
|
+
source: $expr(source),
|
|
3265
|
+
target: $expr(target)
|
|
3266
|
+
});
|
|
3267
|
+
}
|
|
3268
|
+
if (expr.endsWith("._")) return asTypedExpr({
|
|
3269
|
+
ref: { model: expr.replace("._", "") },
|
|
3270
|
+
selector: "expanded"
|
|
3271
|
+
});
|
|
3272
|
+
if (expr.endsWith(".**")) return asTypedExpr({
|
|
3273
|
+
ref: { model: expr.replace(".**", "") },
|
|
3274
|
+
selector: "descendants"
|
|
3275
|
+
});
|
|
3276
|
+
if (expr.endsWith(".*")) return asTypedExpr({
|
|
3277
|
+
ref: { model: expr.replace(".*", "") },
|
|
3278
|
+
selector: "children"
|
|
3279
|
+
});
|
|
3280
|
+
return asTypedExpr({ ref: { model: expr } });
|
|
3281
|
+
}
|
|
3282
|
+
|
|
3283
|
+
//#endregion
|
|
3284
|
+
export { unsafeComputeView as a, linkNodesWithEdges as c, computeView as i, computeLikeC4Model as n, computeElementView as o, computeParsedModelData as r, topologicalSort as s, $expr as t };
|