@likec4/core 1.47.0 → 1.49.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.
Files changed (152) hide show
  1. package/LICENSE +1 -1
  2. package/dist/THIRD-PARTY-LICENSES.md +1012 -0
  3. package/dist/_chunks/Builder.view-element.mjs +2 -0
  4. package/dist/_chunks/LikeC4Model.d.mts +1283 -0
  5. package/dist/_chunks/RichText.mjs +1 -0
  6. package/dist/_chunks/_types.d.mts +777 -0
  7. package/dist/_chunks/_types2.d.mts +36 -0
  8. package/dist/_chunks/assignTagColors.mjs +1 -0
  9. package/dist/_chunks/calcDriftsFromSnapshot.mjs +1 -0
  10. package/dist/_chunks/guards.d.mts +2026 -0
  11. package/dist/_chunks/guards.mjs +4 -0
  12. package/dist/_chunks/index.d.mts +288 -0
  13. package/dist/_chunks/libs/@mantine/colors-generator.mjs +15 -0
  14. package/dist/_chunks/libs/@radix-ui/colors.mjs +1 -0
  15. package/dist/_chunks/libs/@ungap/structured-clone.mjs +1 -0
  16. package/dist/_chunks/libs/bail.mjs +1 -0
  17. package/dist/_chunks/libs/ccount.mjs +1 -0
  18. package/dist/_chunks/libs/character-entities-html4.mjs +1 -0
  19. package/dist/_chunks/libs/character-entities-legacy.mjs +1 -0
  20. package/dist/_chunks/libs/character-entities.mjs +2 -0
  21. package/dist/_chunks/libs/comma-separated-tokens.mjs +1 -0
  22. package/dist/_chunks/libs/decode-named-character-reference.mjs +1 -0
  23. package/dist/_chunks/libs/defu.mjs +1 -0
  24. package/dist/_chunks/libs/devlop.mjs +1 -0
  25. package/dist/_chunks/libs/escape-string-regexp.mjs +1 -0
  26. package/dist/_chunks/libs/extend.mjs +1 -0
  27. package/dist/_chunks/libs/graphology-dag.mjs +1 -0
  28. package/dist/_chunks/libs/graphology.mjs +1 -0
  29. package/dist/_chunks/libs/hast-util-sanitize.mjs +1 -0
  30. package/dist/_chunks/libs/hast-util-to-html.mjs +9 -0
  31. package/dist/_chunks/libs/is-plain-obj.mjs +1 -0
  32. package/dist/_chunks/libs/longest-streak.mjs +1 -0
  33. package/dist/_chunks/libs/markdown-table.mjs +2 -0
  34. package/dist/_chunks/libs/mdast-util-find-and-replace.mjs +1 -0
  35. package/dist/_chunks/libs/mdast-util-from-markdown.mjs +3 -0
  36. package/dist/_chunks/libs/mdast-util-gfm.mjs +15 -0
  37. package/dist/_chunks/libs/mdast-util-to-hast.mjs +11 -0
  38. package/dist/_chunks/libs/micromark-extension-gfm.mjs +1 -0
  39. package/dist/_chunks/libs/mnemonist.d.mts +164 -0
  40. package/dist/_chunks/libs/mnemonist.mjs +1 -0
  41. package/dist/_chunks/libs/natural-compare-lite.mjs +9 -0
  42. package/dist/_chunks/libs/ohash.mjs +1 -0
  43. package/dist/_chunks/libs/rehype-sanitize.mjs +1 -0
  44. package/dist/_chunks/libs/rehype-stringify.mjs +1 -0
  45. package/dist/_chunks/libs/remark-gfm.mjs +1 -0
  46. package/dist/_chunks/libs/remark-github-blockquote-alert.mjs +3 -0
  47. package/dist/_chunks/libs/remark-parse.mjs +1 -0
  48. package/dist/_chunks/libs/remark-rehype.mjs +1 -0
  49. package/dist/_chunks/libs/remeda.mjs +1 -0
  50. package/dist/_chunks/libs/trough.mjs +1 -0
  51. package/dist/_chunks/libs/unified.mjs +1 -0
  52. package/dist/_chunks/rolldown-runtime.mjs +1 -0
  53. package/dist/_chunks/theme.d.mts +148 -0
  54. package/dist/_chunks/to-text.d.mts +404 -0
  55. package/dist/_chunks/to-text.mjs +1 -0
  56. package/dist/_chunks/vector.d.mts +198 -0
  57. package/dist/_chunks/vector.mjs +1 -0
  58. package/dist/builder/index.d.mts +5 -775
  59. package/dist/builder/index.mjs +1 -1053
  60. package/dist/compute-view/index.d.mts +156 -56
  61. package/dist/compute-view/index.mjs +2 -229
  62. package/dist/geometry/index.d.mts +2 -109
  63. package/dist/geometry/index.mjs +1 -328
  64. package/dist/index.d.mts +14 -20
  65. package/dist/index.mjs +1 -18
  66. package/dist/model/index.d.mts +5 -57
  67. package/dist/model/index.mjs +1 -4
  68. package/dist/styles/index.d.mts +3 -117
  69. package/dist/styles/index.mjs +1 -63
  70. package/dist/types/index.d.mts +3 -47
  71. package/dist/types/index.mjs +1 -17
  72. package/dist/utils/graphology/index.d.mts +2 -1864
  73. package/dist/utils/graphology/index.mjs +1 -1
  74. package/dist/utils/index.d.mts +4 -124
  75. package/dist/utils/index.mjs +1 -44
  76. package/package.json +20 -24
  77. package/compute-view/relationships/package.json +0 -4
  78. package/dist/compute-view/relationships-view/index.d.mts +0 -51
  79. package/dist/compute-view/relationships-view/index.mjs +0 -185
  80. package/dist/model/connection/deployment/index.d.mts +0 -15
  81. package/dist/model/connection/deployment/index.mjs +0 -2
  82. package/dist/model/connection/index.d.mts +0 -75
  83. package/dist/model/connection/index.mjs +0 -3
  84. package/dist/model/connection/model/index.d.mts +0 -15
  85. package/dist/model/connection/model/index.mjs +0 -2
  86. package/dist/shared/core.3ZhnKAlZ.mjs +0 -106
  87. package/dist/shared/core.78IWAHAE.mjs +0 -332
  88. package/dist/shared/core.B85MJLTf.mjs +0 -5
  89. package/dist/shared/core.BFd1lU9R.mjs +0 -29
  90. package/dist/shared/core.BKlholso.mjs +0 -3
  91. package/dist/shared/core.BNN-3vPH.mjs +0 -1255
  92. package/dist/shared/core.BPGOjone.d.mts +0 -46
  93. package/dist/shared/core.BP_QHEXs.mjs +0 -785
  94. package/dist/shared/core.BbE4y-yl.mjs +0 -177
  95. package/dist/shared/core.Bdy3hhTc.mjs +0 -28382
  96. package/dist/shared/core.BfCKSW-g.d.mts +0 -1266
  97. package/dist/shared/core.BhNcrwzK.mjs +0 -7
  98. package/dist/shared/core.BkVA6gjl.mjs +0 -5
  99. package/dist/shared/core.BoYfZOBm.mjs +0 -3
  100. package/dist/shared/core.BsSXS-_R.mjs +0 -7
  101. package/dist/shared/core.C3JowhaZ.mjs +0 -32
  102. package/dist/shared/core.C4x8aaWa.mjs +0 -27
  103. package/dist/shared/core.CAgYpDtM.d.mts +0 -98
  104. package/dist/shared/core.CHf8VEa3.mjs +0 -1206
  105. package/dist/shared/core.CLSZtnFh.mjs +0 -69
  106. package/dist/shared/core.C_3y3eqV.d.mts +0 -139
  107. package/dist/shared/core.CbT8JVYL.mjs +0 -5
  108. package/dist/shared/core.CdNCAwq7.mjs +0 -176
  109. package/dist/shared/core.CmGY9blO.mjs +0 -6717
  110. package/dist/shared/core.CmPXpJ8l.mjs +0 -21
  111. package/dist/shared/core.Coi_LOUZ.mjs +0 -7
  112. package/dist/shared/core.CqAJJpK_.mjs +0 -3
  113. package/dist/shared/core.CywrQs86.d.mts +0 -31
  114. package/dist/shared/core.D00YbOhQ.d.mts +0 -300
  115. package/dist/shared/core.D0WZutNd.mjs +0 -94
  116. package/dist/shared/core.D4npX2q8.mjs +0 -18
  117. package/dist/shared/core.DB0Ue5Wx.d.mts +0 -70
  118. package/dist/shared/core.DC5IAaDT.d.mts +0 -334
  119. package/dist/shared/core.DE9qzhn8.d.mts +0 -83
  120. package/dist/shared/core.DGcIbsj4.mjs +0 -3946
  121. package/dist/shared/core.DH7TXqXf.mjs +0 -136
  122. package/dist/shared/core.DKhRkHRN.d.mts +0 -41
  123. package/dist/shared/core.DRJma0Ol.mjs +0 -22
  124. package/dist/shared/core.DU5SRqNF.mjs +0 -2209
  125. package/dist/shared/core.DXhDWKFZ.d.mts +0 -3
  126. package/dist/shared/core.DbfO90vF.mjs +0 -434
  127. package/dist/shared/core.DcS-0zys.mjs +0 -10
  128. package/dist/shared/core.Dh119QSP.mjs +0 -4995
  129. package/dist/shared/core.DjcWextK.mjs +0 -1371
  130. package/dist/shared/core.Dojz4bvg.d.mts +0 -504
  131. package/dist/shared/core.FZ305VYd.mjs +0 -21
  132. package/dist/shared/core.OtRNdMxy.d.mts +0 -352
  133. package/dist/shared/core.RfnaEmgA.mjs +0 -7
  134. package/dist/shared/core.btEq3i3f.mjs +0 -300
  135. package/dist/shared/core.oSV6SRfk.mjs +0 -13
  136. package/dist/shared/core.om36dXXW.mjs +0 -41
  137. package/dist/shared/core.osFs8tU7.d.mts +0 -466
  138. package/dist/shared/core.q10OP9oJ.mjs +0 -5
  139. package/dist/shared/core.tpvDGvdC.d.mts +0 -87
  140. package/dist/shared/core.uFk_o9X6.mjs +0 -13
  141. package/dist/types/_aux.d.mts +0 -4
  142. package/dist/types/_aux.mjs +0 -8
  143. package/dist/types/expression-model.d.mts +0 -190
  144. package/dist/types/expression-model.mjs +0 -109
  145. package/dist/types/expression.d.mts +0 -6
  146. package/dist/types/expression.mjs +0 -113
  147. package/dist/types/fqnRef.d.mts +0 -60
  148. package/dist/types/fqnRef.mjs +0 -45
  149. package/dist/types/scalar.d.mts +0 -2
  150. package/dist/types/scalar.mjs +0 -4
  151. package/dist/utils/iterable/index.d.mts +0 -132
  152. package/dist/utils/iterable/index.mjs +0 -62
@@ -1,4995 +0,0 @@
1
- import { n as n$d, d as t$i, e as t$j, f as t$l, b as t$m, g as buildElementNotations, t as t$q } from './core.DjcWextK.mjs';
2
- import { t as t$a, a as t$b } from './core.BsSXS-_R.mjs';
3
- import { t as t$e } from './core.CbT8JVYL.mjs';
4
- import { a as t$c, t as t$k, i as isElementModel, b as isNestedElementOfDeployedInstanceModel, c as isDeployedInstanceModel, d as isDeploymentNodeModel, e as isDeploymentElementModel, L as LikeC4Model } from './core.DU5SRqNF.mjs';
5
- import { c as commonHead, t as t$f, o as objectHash, b as t$n, a as compareRelations, S as Stack } from './core.btEq3i3f.mjs';
6
- import { a as nonNullable, i as invariant, n as nonexhaustive } from './core.D4npX2q8.mjs';
7
- import { G as Graph } from './core.CmGY9blO.mjs';
8
- import { r as requireIterables, e as exact, t as t$o } from './core.CHf8VEa3.mjs';
9
- import { b as requireIterator } from './core.Bdy3hhTc.mjs';
10
- import { g as getDefaultExportFromCjs } from './core.B85MJLTf.mjs';
11
- import { n as n$c, t as t$d } from './core.3ZhnKAlZ.mjs';
12
- import { e as e$4 } from './core.BKlholso.mjs';
13
- import { f as flattenMarkdownOrString, i as isGroupElementKind, G as GroupElementKind, e as stepEdgeId } from './core.D0WZutNd.mjs';
14
- import { b as isDescendantOf, f as sortParentsFirst, i as isAncestor, p as parentFqn, j as compareByFqnHierarchically, c as isNonEmptyArray, o as sortByFqnHierarchically, g as commonAncestor, a as ancestorsFqn, d as isSameHierarchy } from './core.CdNCAwq7.mjs';
15
- import { d as difference, i as intersection, u as union, h as hasIntersection } from './core.DbfO90vF.mjs';
16
- import { e as e$9 } from './core.Coi_LOUZ.mjs';
17
- import { w as whereOperatorAsPredicate, m as isViewRuleStyle, v as t$g, u as e$8, l as isViewRulePredicate, a as _type, _ as _stage, t as isDynamicView, s as isDeploymentView, p as isElementView } from './core.DH7TXqXf.mjs';
18
- import { e as e$5, d as deploymentConnection, R as RelationshipsAccum, D as DeploymentConnectionModel } from './core.BP_QHEXs.mjs';
19
- import { e as e$6, a as iunique, i as iflat } from './core.C4x8aaWa.mjs';
20
- import { e as e$7 } from './core.BoYfZOBm.mjs';
21
- import { ModelFqnExpr, ModelRelationExpr, ModelExpression } from '../types/expression-model.mjs';
22
- import { FqnRef } from '../types/fqnRef.mjs';
23
- import { preferSummary } from '../types/_aux.mjs';
24
- import { a as t$h } from './core.DGcIbsj4.mjs';
25
- import { n as n$e } from './core.BhNcrwzK.mjs';
26
- import { FqnExpr, RelationExpr } from '../types/expression.mjs';
27
- import { f as findAscendingConnections, m as mergeConnections, d as differenceConnections, j as isNestedConnection, s as sortConnectionsByBoundaryHierarchy, o as findConnectionsBetween$3, p as findConnection$3, n as modelConnection, b as findDescendantConnections, a as findDeepestNestedConnection, i as isAnyInOut, k as isOutgoing, g as isIncoming, C as ConnectionModel } from './core.78IWAHAE.mjs';
28
- import { t as toSet, a as toArray, i as imap } from './core.C3JowhaZ.mjs';
29
- import { D as DefaultMap } from './core.BbE4y-yl.mjs';
30
- import { i as isome } from './core.FZ305VYd.mjs';
31
- import { i as ifilter } from './core.DRJma0Ol.mjs';
32
- import { C as Connection, c as customInspectSymbol } from './core.BFd1lU9R.mjs';
33
- import { i as isIterable, e as e$a } from './core.RfnaEmgA.mjs';
34
- import { k as e$b, c as isViewRuleAutoLayout, h as isViewRuleGroup, a as isViewRuleGlobalPredicateRef, i as isViewRuleGlobalStyle, e as isDynamicStepsParallel, f as isDynamicStepsSeries, j as isViewRuleRank } from './core.om36dXXW.mjs';
35
- import { t as t$p } from './core.q10OP9oJ.mjs';
36
-
37
- function e$3(e){return ()=>e}
38
-
39
- function t$9(...t){return t$a(n$b,t)}function n$b(e,t){for(let[n,r]of e.entries())if(!t(r,n,e))return e.slice(n);return []}
40
-
41
- const e$2=e=>Object.assign(e,{single:true});
42
-
43
- function t$8(...t){return t$a(n$a,t)}const n$a=(e,t)=>{for(let n=e.length-1;n>=0;n--){let r=e[n];if(t(r,n,e))return r}};
44
-
45
- function n$9(...n){return t$a(r$3,n,e$2(i$1))}const r$3=([e])=>e,i$1=()=>a,a=e=>({hasNext:true,next:e,done:true});
46
-
47
- function t$7(...t){return t$a(n$8,t,r$2)}function n$8(e,t){return e.forEach(t),e}const r$2=e=>(t,n,r)=>(e(t,n,r),{done:false,hasNext:true,next:t});
48
-
49
- function e$1(e){return typeof e==`boolean`}
50
-
51
- function t$6(...t){return t$a(n$7,t)}function n$7(e,t){let n={};for(let[r,i]of e.entries()){let[a,o]=t(i,r,e);n[a]=o;}return n}
52
-
53
- function n$6(...t){return t$a(r$1,t)}function r$1(e,n){if(!t$b(n,1))return {...e};if(!t$b(n,2)){let{[n[0]]:t,...r}=e;return r}let r={...e};for(let e of n)delete r[e];return r}
54
-
55
- function t$5(...t){return t$a(n$5,t)}const n$5=e=>e.length===1?e[0]:void 0;
56
-
57
- function t$4(...t){return t$a(n$4,t)}const n$4=(e,t)=>{let n=[[],[]];for(let[r,i]of e.entries())t(i,r,e)?n[0].push(i):n[1].push(i);return n};
58
-
59
- function t$3(...t){return t$a(n$3,t)}function n$3(e,t){let n={};for(let[r,i]of Object.entries(e))t(i,r,e)&&(n[r]=i);return n}
60
-
61
- function t$2(...t){return t$a(n$2,t)}const n$2=(e,t,n)=>e.reduce(t,n);
62
-
63
- function t$1(...t){return t$a(n$1,t)}function n$1(e){return [...e].reverse()}
64
-
65
- function n(...t){return t$a(r,t,i)}const r=(e,t)=>t<0?[]:e.slice(0,t);function i(e){if(e<=0)return n$c;let n=e;return e=>(--n,{done:n<=0,hasNext:true,next:e})}
66
-
67
- function e(...e){return e.length===2?(n,...r)=>t(n,...e,...r):t(...e)}const t=(e,t,n,...r)=>t(e,...r)?typeof n==`function`?n(e,...r):n.onTrue(e,...r):typeof n==`function`?e:n.onFalse(e,...r);
68
-
69
- function ancestorsOfNode(node, nodes) {
70
- const ancestors = [];
71
- let parentId = node.parent;
72
- while (parentId) {
73
- const parentNode = nonNullable(nodes.get(parentId), `Parent node ${parentId} not found`);
74
- ancestors.push(parentNode);
75
- parentId = parentNode.parent;
76
- }
77
- return ancestors;
78
- }
79
-
80
- function linkNodesWithEdges(nodesMap, edges) {
81
- for (const edge of edges) {
82
- const source = nodesMap.get(edge.source);
83
- const target = nodesMap.get(edge.target);
84
- invariant(source, `Source node ${edge.source} not found`);
85
- invariant(target, `Target node ${edge.target} not found`);
86
- source.outEdges.push(edge.id);
87
- target.inEdges.push(edge.id);
88
- const sourceAncestors = ancestorsOfNode(source, nodesMap);
89
- const targetAncestors = ancestorsOfNode(target, nodesMap);
90
- const hasAncestors = sourceAncestors.length > 0 && targetAncestors.length > 0;
91
- const edgeParent = hasAncestors ? t$c(
92
- commonHead(
93
- t$1(sourceAncestors),
94
- t$1(targetAncestors)
95
- )
96
- ) : null;
97
- edge.parent = edgeParent ? edgeParent.id : null;
98
- for (const sourceAncestor of sourceAncestors) {
99
- if (sourceAncestor === edgeParent) {
100
- break;
101
- }
102
- sourceAncestor.outEdges.push(edge.id);
103
- }
104
- for (const targetAncestor of targetAncestors) {
105
- if (targetAncestor === edgeParent) {
106
- break;
107
- }
108
- targetAncestor.inEdges.push(edge.id);
109
- }
110
- }
111
- }
112
-
113
- var topologicalSort$1 = {};
114
-
115
- /**
116
- * Graphology isGraph
117
- * ===================
118
- *
119
- * Very simple function aiming at ensuring the given variable is a
120
- * graphology instance.
121
- */
122
-
123
- var isGraph;
124
- var hasRequiredIsGraph;
125
-
126
- function requireIsGraph () {
127
- if (hasRequiredIsGraph) return isGraph;
128
- hasRequiredIsGraph = 1;
129
- /**
130
- * Checking the value is a graphology instance.
131
- *
132
- * @param {any} value - Target value.
133
- * @return {boolean}
134
- */
135
- isGraph = function isGraph(value) {
136
- return (
137
- value !== null &&
138
- typeof value === 'object' &&
139
- typeof value.addUndirectedEdgeWithKey === 'function' &&
140
- typeof value.dropNode === 'function' &&
141
- typeof value.multi === 'boolean'
142
- );
143
- };
144
- return isGraph;
145
- }
146
-
147
- /**
148
- * Mnemonist FixedDeque
149
- * =====================
150
- *
151
- * Fixed capacity double-ended queue implemented as ring deque.
152
- */
153
-
154
- var fixedDeque;
155
- var hasRequiredFixedDeque;
156
-
157
- function requireFixedDeque () {
158
- if (hasRequiredFixedDeque) return fixedDeque;
159
- hasRequiredFixedDeque = 1;
160
- var iterables = /*@__PURE__*/ requireIterables(),
161
- Iterator = requireIterator();
162
-
163
- /**
164
- * FixedDeque.
165
- *
166
- * @constructor
167
- */
168
- function FixedDeque(ArrayClass, capacity) {
169
-
170
- if (arguments.length < 2)
171
- throw new Error('mnemonist/fixed-deque: expecting an Array class and a capacity.');
172
-
173
- if (typeof capacity !== 'number' || capacity <= 0)
174
- throw new Error('mnemonist/fixed-deque: `capacity` should be a positive number.');
175
-
176
- this.ArrayClass = ArrayClass;
177
- this.capacity = capacity;
178
- this.items = new ArrayClass(this.capacity);
179
- this.clear();
180
- }
181
-
182
- /**
183
- * Method used to clear the structure.
184
- *
185
- * @return {undefined}
186
- */
187
- FixedDeque.prototype.clear = function() {
188
-
189
- // Properties
190
- this.start = 0;
191
- this.size = 0;
192
- };
193
-
194
- /**
195
- * Method used to append a value to the deque.
196
- *
197
- * @param {any} item - Item to append.
198
- * @return {number} - Returns the new size of the deque.
199
- */
200
- FixedDeque.prototype.push = function(item) {
201
- if (this.size === this.capacity)
202
- throw new Error('mnemonist/fixed-deque.push: deque capacity (' + this.capacity + ') exceeded!');
203
-
204
- var index = this.start + this.size;
205
-
206
- if (index >= this.capacity)
207
- index -= this.capacity;
208
-
209
- this.items[index] = item;
210
-
211
- return ++this.size;
212
- };
213
-
214
- /**
215
- * Method used to prepend a value to the deque.
216
- *
217
- * @param {any} item - Item to prepend.
218
- * @return {number} - Returns the new size of the deque.
219
- */
220
- FixedDeque.prototype.unshift = function(item) {
221
- if (this.size === this.capacity)
222
- throw new Error('mnemonist/fixed-deque.unshift: deque capacity (' + this.capacity + ') exceeded!');
223
-
224
- var index = this.start - 1;
225
-
226
- if (this.start === 0)
227
- index = this.capacity - 1;
228
-
229
- this.items[index] = item;
230
- this.start = index;
231
-
232
- return ++this.size;
233
- };
234
-
235
- /**
236
- * Method used to pop the deque.
237
- *
238
- * @return {any} - Returns the popped item.
239
- */
240
- FixedDeque.prototype.pop = function() {
241
- if (this.size === 0)
242
- return;
243
-
244
- this.size--;
245
-
246
- var index = this.start + this.size;
247
-
248
- if (index >= this.capacity)
249
- index -= this.capacity;
250
-
251
- return this.items[index];
252
- };
253
-
254
- /**
255
- * Method used to shift the deque.
256
- *
257
- * @return {any} - Returns the shifted item.
258
- */
259
- FixedDeque.prototype.shift = function() {
260
- if (this.size === 0)
261
- return;
262
-
263
- var index = this.start;
264
-
265
- this.size--;
266
- this.start++;
267
-
268
- if (this.start === this.capacity)
269
- this.start = 0;
270
-
271
- return this.items[index];
272
- };
273
-
274
- /**
275
- * Method used to peek the first value of the deque.
276
- *
277
- * @return {any}
278
- */
279
- FixedDeque.prototype.peekFirst = function() {
280
- if (this.size === 0)
281
- return;
282
-
283
- return this.items[this.start];
284
- };
285
-
286
- /**
287
- * Method used to peek the last value of the deque.
288
- *
289
- * @return {any}
290
- */
291
- FixedDeque.prototype.peekLast = function() {
292
- if (this.size === 0)
293
- return;
294
-
295
- var index = this.start + this.size - 1;
296
-
297
- if (index >= this.capacity)
298
- index -= this.capacity;
299
-
300
- return this.items[index];
301
- };
302
-
303
- /**
304
- * Method used to get the desired value of the deque.
305
- *
306
- * @param {number} index
307
- * @return {any}
308
- */
309
- FixedDeque.prototype.get = function(index) {
310
- if (this.size === 0 || index >= this.capacity)
311
- return;
312
-
313
- index = this.start + index;
314
-
315
- if (index >= this.capacity)
316
- index -= this.capacity;
317
-
318
- return this.items[index];
319
- };
320
-
321
- /**
322
- * Method used to iterate over the deque.
323
- *
324
- * @param {function} callback - Function to call for each item.
325
- * @param {object} scope - Optional scope.
326
- * @return {undefined}
327
- */
328
- FixedDeque.prototype.forEach = function(callback, scope) {
329
- scope = arguments.length > 1 ? scope : this;
330
-
331
- var c = this.capacity,
332
- l = this.size,
333
- i = this.start,
334
- j = 0;
335
-
336
- while (j < l) {
337
- callback.call(scope, this.items[i], j, this);
338
- i++;
339
- j++;
340
-
341
- if (i === c)
342
- i = 0;
343
- }
344
- };
345
-
346
- /**
347
- * Method used to convert the deque to a JavaScript array.
348
- *
349
- * @return {array}
350
- */
351
- // TODO: optional array class as argument?
352
- FixedDeque.prototype.toArray = function() {
353
-
354
- // Optimization
355
- var offset = this.start + this.size;
356
-
357
- if (offset < this.capacity)
358
- return this.items.slice(this.start, offset);
359
-
360
- var array = new this.ArrayClass(this.size),
361
- c = this.capacity,
362
- l = this.size,
363
- i = this.start,
364
- j = 0;
365
-
366
- while (j < l) {
367
- array[j] = this.items[i];
368
- i++;
369
- j++;
370
-
371
- if (i === c)
372
- i = 0;
373
- }
374
-
375
- return array;
376
- };
377
-
378
- /**
379
- * Method used to create an iterator over the deque's values.
380
- *
381
- * @return {Iterator}
382
- */
383
- FixedDeque.prototype.values = function() {
384
- var items = this.items,
385
- c = this.capacity,
386
- l = this.size,
387
- i = this.start,
388
- j = 0;
389
-
390
- return new Iterator(function() {
391
- if (j >= l)
392
- return {
393
- done: true
394
- };
395
-
396
- var value = items[i];
397
-
398
- i++;
399
- j++;
400
-
401
- if (i === c)
402
- i = 0;
403
-
404
- return {
405
- value: value,
406
- done: false
407
- };
408
- });
409
- };
410
-
411
- /**
412
- * Method used to create an iterator over the deque's entries.
413
- *
414
- * @return {Iterator}
415
- */
416
- FixedDeque.prototype.entries = function() {
417
- var items = this.items,
418
- c = this.capacity,
419
- l = this.size,
420
- i = this.start,
421
- j = 0;
422
-
423
- return new Iterator(function() {
424
- if (j >= l)
425
- return {
426
- done: true
427
- };
428
-
429
- var value = items[i];
430
-
431
- i++;
432
-
433
- if (i === c)
434
- i = 0;
435
-
436
- return {
437
- value: [j++, value],
438
- done: false
439
- };
440
- });
441
- };
442
-
443
- /**
444
- * Attaching the #.values method to Symbol.iterator if possible.
445
- */
446
- if (typeof Symbol !== 'undefined')
447
- FixedDeque.prototype[Symbol.iterator] = FixedDeque.prototype.values;
448
-
449
- /**
450
- * Convenience known methods.
451
- */
452
- FixedDeque.prototype.inspect = function() {
453
- var array = this.toArray();
454
-
455
- array.type = this.ArrayClass.name;
456
- array.capacity = this.capacity;
457
-
458
- // Trick so that node displays the name of the constructor
459
- Object.defineProperty(array, 'constructor', {
460
- value: FixedDeque,
461
- enumerable: false
462
- });
463
-
464
- return array;
465
- };
466
-
467
- if (typeof Symbol !== 'undefined')
468
- FixedDeque.prototype[Symbol.for('nodejs.util.inspect.custom')] = FixedDeque.prototype.inspect;
469
-
470
- /**
471
- * Static @.from function taking an arbitrary iterable & converting it into
472
- * a deque.
473
- *
474
- * @param {Iterable} iterable - Target iterable.
475
- * @param {function} ArrayClass - Array class to use.
476
- * @param {number} capacity - Desired capacity.
477
- * @return {FiniteStack}
478
- */
479
- FixedDeque.from = function(iterable, ArrayClass, capacity) {
480
- if (arguments.length < 3) {
481
- capacity = iterables.guessLength(iterable);
482
-
483
- if (typeof capacity !== 'number')
484
- throw new Error('mnemonist/fixed-deque.from: could not guess iterable length. Please provide desired capacity as last argument.');
485
- }
486
-
487
- var deque = new FixedDeque(ArrayClass, capacity);
488
-
489
- if (iterables.isArrayLike(iterable)) {
490
- var i, l;
491
-
492
- for (i = 0, l = iterable.length; i < l; i++)
493
- deque.items[i] = iterable[i];
494
-
495
- deque.size = l;
496
-
497
- return deque;
498
- }
499
-
500
- iterables.forEach(iterable, function(value) {
501
- deque.push(value);
502
- });
503
-
504
- return deque;
505
- };
506
-
507
- /**
508
- * Exporting.
509
- */
510
- fixedDeque = FixedDeque;
511
- return fixedDeque;
512
- }
513
-
514
- /**
515
- * Graphology Topological Sort
516
- * ============================
517
- *
518
- * Function performing topological sort over the given DAG using Kahn's
519
- * algorithm.
520
- *
521
- * This function also works on disconnected graphs.
522
- *
523
- * [Reference]:
524
- * https://en.wikipedia.org/wiki/Topological_sorting
525
- */
526
-
527
- var hasRequiredTopologicalSort;
528
-
529
- function requireTopologicalSort () {
530
- if (hasRequiredTopologicalSort) return topologicalSort$1;
531
- hasRequiredTopologicalSort = 1;
532
- const isGraph = requireIsGraph();
533
- const FixedDeque = /*@__PURE__*/ requireFixedDeque();
534
-
535
- function simpleInDegree(graph, node) {
536
- let degree = 0;
537
-
538
- graph.forEachInNeighbor(node, () => {
539
- degree++;
540
- });
541
-
542
- return degree;
543
- }
544
-
545
- function forEachNodeInTopologicalOrder(graph, callback) {
546
- if (!isGraph(graph))
547
- throw new Error(
548
- 'graphology-dag/topological-sort: the given graph is not a valid graphology instance.'
549
- );
550
-
551
- // NOTE: falsely mixed graph representing directed graphs will work
552
- if (graph.type === 'undirected' || graph.undirectedSize !== 0)
553
- throw new Error(
554
- 'graphology-dag/topological-sort: cannot work if graph is not directed.'
555
- );
556
-
557
- if (graph.order === 0) return;
558
-
559
- const queue = new FixedDeque(Array, graph.order);
560
- const inDegrees = {};
561
- let total = 0;
562
-
563
- graph.forEachNode((node, attr) => {
564
- const inDegree = graph.multi
565
- ? simpleInDegree(graph, node)
566
- : graph.inDegree(node);
567
-
568
- if (inDegree === 0) {
569
- queue.push([node, attr, 0]);
570
- } else {
571
- inDegrees[node] = inDegree;
572
- total += inDegree;
573
- }
574
- });
575
-
576
- let currentGeneration = 0;
577
-
578
- function neighborCallback(neighbor, attr) {
579
- const neighborInDegree = --inDegrees[neighbor];
580
-
581
- total--;
582
-
583
- if (neighborInDegree === 0)
584
- queue.push([neighbor, attr, currentGeneration + 1]);
585
-
586
- inDegrees[neighbor] = neighborInDegree;
587
-
588
- // NOTE: key deletion is expensive in JS and in this case pointless so
589
- // we just skip it for performance reasons
590
- }
591
-
592
- while (queue.size !== 0) {
593
- const [node, attr, gen] = queue.shift();
594
- currentGeneration = gen;
595
-
596
- callback(node, attr, gen);
597
-
598
- graph.forEachOutNeighbor(node, neighborCallback);
599
- }
600
-
601
- if (total !== 0)
602
- throw new Error(
603
- 'graphology-dag/topological-sort: given graph is not acyclic.'
604
- );
605
- }
606
-
607
- function topologicalSort(graph) {
608
- if (!isGraph(graph))
609
- throw new Error(
610
- 'graphology-dag/topological-sort: the given graph is not a valid graphology instance.'
611
- );
612
-
613
- const sortedNodes = new Array(graph.order);
614
- let i = 0;
615
-
616
- forEachNodeInTopologicalOrder(graph, node => {
617
- sortedNodes[i++] = node;
618
- });
619
-
620
- return sortedNodes;
621
- }
622
-
623
- function forEachTopologicalGeneration(graph, callback) {
624
- if (!isGraph(graph))
625
- throw new Error(
626
- 'graphology-dag/topological-generations: the given graph is not a valid graphology instance.'
627
- );
628
-
629
- if (graph.order === 0) return;
630
-
631
- let lastGenLevel = 0;
632
- let lastGen = [];
633
-
634
- forEachNodeInTopologicalOrder(graph, (node, _, gen) => {
635
- if (gen > lastGenLevel) {
636
- callback(lastGen);
637
- lastGenLevel = gen;
638
- lastGen = [];
639
- }
640
-
641
- lastGen.push(node);
642
- });
643
-
644
- callback(lastGen);
645
- }
646
-
647
- function topologicalGenerations(graph) {
648
- if (!isGraph(graph))
649
- throw new Error(
650
- 'graphology-dag/topological-generations: the given graph is not a valid graphology instance.'
651
- );
652
-
653
- const generations = [];
654
-
655
- forEachTopologicalGeneration(graph, generation => {
656
- generations.push(generation);
657
- });
658
-
659
- return generations;
660
- }
661
-
662
- /**
663
- * Exporting.
664
- */
665
- topologicalSort$1.topologicalSort = topologicalSort;
666
- topologicalSort$1.forEachNodeInTopologicalOrder = forEachNodeInTopologicalOrder;
667
- topologicalSort$1.topologicalGenerations = topologicalGenerations;
668
- topologicalSort$1.forEachTopologicalGeneration = forEachTopologicalGeneration;
669
- return topologicalSort$1;
670
- }
671
-
672
- var topologicalSortExports = requireTopologicalSort();
673
-
674
- /**
675
- * Graphology Cycle Creation Checker
676
- * ==================================
677
- *
678
- * Function returning whether adding the given directed edge to a DAG will
679
- * create a cycle.
680
- *
681
- * Note that this function requires the given graph to be a valid DAG forest
682
- * and will not check it beforehand for performance reasons.
683
- */
684
-
685
- var willCreateCycle$1;
686
- var hasRequiredWillCreateCycle;
687
-
688
- function requireWillCreateCycle () {
689
- if (hasRequiredWillCreateCycle) return willCreateCycle$1;
690
- hasRequiredWillCreateCycle = 1;
691
- const isGraph = requireIsGraph();
692
-
693
- willCreateCycle$1 = function willCreateCycle(graph, source, target) {
694
- if (!isGraph(graph))
695
- throw new Error(
696
- 'graphology-dag/will-create-cycle: the given graph is not a valid graphology instance.'
697
- );
698
-
699
- source = '' + source;
700
- target = '' + target;
701
-
702
- // If the edge is a self loop, it will obviously add a cycle
703
- if (source === target) return true;
704
-
705
- // If any of the pointed nodes isn't in the graph yet,
706
- // then no cycle can be created by adding this edge
707
- if (!graph.hasNode(source) || !graph.hasNode(target)) return false;
708
-
709
- // Early exit for existing edge or mutual one
710
- if (graph.hasDirectedEdge(source, target)) return false;
711
- if (graph.hasDirectedEdge(target, source)) return true;
712
-
713
- // Else, we need to assess whether a directed path between target and source
714
- // can be found. We will use DFS traversal because it is usually less
715
- // costly than BFS (stack vs. queue).
716
- const stack = graph.outNeighbors(target);
717
-
718
- function push(neighbor) {
719
- // NOTE: we don't check whether pushed neighbors have not been seen
720
- // because this is not necessary in a DAG. This could result in
721
- // undefined behavior for cyclic graphs, ranging from infinite loop to
722
- // overkill memory usage.
723
- stack.push(neighbor);
724
- }
725
-
726
- while (stack.length !== 0) {
727
- const node = stack.pop();
728
-
729
- if (node === source) return true;
730
-
731
- graph.forEachOutNeighbor(node, push);
732
- }
733
-
734
- return false;
735
- };
736
- return willCreateCycle$1;
737
- }
738
-
739
- var willCreateCycleExports = requireWillCreateCycle();
740
- const willCreateCycle = /*@__PURE__*/getDefaultExportFromCjs(willCreateCycleExports);
741
-
742
- function ensureParentsFirst(array) {
743
- const result = [];
744
- const items = [...array];
745
- let item;
746
- while (item = items.shift()) {
747
- let parent = item.parent;
748
- if (parent) {
749
- const ancestors = [];
750
- while (parent) {
751
- const parentIndx = items.findIndex((i) => i.id === parent);
752
- if (parentIndx < 0) {
753
- break;
754
- }
755
- const [parentItem] = items.splice(parentIndx, 1);
756
- if (!parentItem) {
757
- throw new Error("Invalid state, should not happen");
758
- }
759
- ancestors.unshift(parentItem);
760
- parent = parentItem.parent;
761
- }
762
- result.push(...ancestors);
763
- }
764
- result.push(item);
765
- }
766
- return result;
767
- }
768
- function updateChildren(nodes) {
769
- nodes.forEach((parent) => {
770
- if (parent.children.length > 0) {
771
- parent.children = nodes.reduce((acc, n) => {
772
- if (n.parent === parent.id) {
773
- acc.push(n.id);
774
- }
775
- return acc;
776
- }, []);
777
- }
778
- });
779
- return nodes;
780
- }
781
- function topologicalSort(param) {
782
- let nodes = ensureParentsFirst([...param.nodes.values()]);
783
- let edges = [...param.edges];
784
- if (nodes.length < 2 || edges.length === 0) {
785
- return {
786
- nodes,
787
- edges
788
- };
789
- }
790
- const getNode = (id) => nonNullable(param.nodes.get(id));
791
- const g = new Graph({
792
- multi: true,
793
- allowSelfLoops: true,
794
- type: "directed"
795
- });
796
- const enrichedEdges = t$d(
797
- edges,
798
- t$e((edge) => {
799
- const source = getNode(edge.source), target = getNode(edge.target), parent = edge.parent ? getNode(edge.parent) : null;
800
- return {
801
- id: edge.id,
802
- edge,
803
- parent,
804
- source,
805
- target
806
- };
807
- })
808
- );
809
- const [edgesBetweenLeafs, edgesWithCompounds] = t$4(
810
- enrichedEdges,
811
- ({ source, target }) => source.children.length === 0 && target.children.length === 0
812
- );
813
- const sortedEdges = [];
814
- const addEdgeToGraph = (edge) => {
815
- g.mergeNode(edge.source);
816
- g.mergeNode(edge.target);
817
- sortedEdges.push(edge);
818
- if (!willCreateCycle(g, edge.source, edge.target)) {
819
- g.mergeDirectedEdge(edge.source, edge.target);
820
- }
821
- };
822
- for (const { edge, source, target } of edgesBetweenLeafs) {
823
- addEdgeToGraph(edge);
824
- if (target.parent && target.parent !== edge.parent) {
825
- t$d(
826
- ancestorsOfNode(target, param.nodes),
827
- t$f((ancestor) => ancestor.inEdges.includes(edge.id)),
828
- t$7((ancestor) => {
829
- g.mergeNode(ancestor.id);
830
- if (!willCreateCycle(g, edge.source, ancestor.id)) {
831
- g.mergeDirectedEdge(edge.source, ancestor.id);
832
- }
833
- if (!willCreateCycle(g, ancestor.id, edge.target)) {
834
- g.mergeDirectedEdge(ancestor.id, edge.target);
835
- }
836
- })
837
- );
838
- }
839
- if (source.parent) {
840
- const sourceParent = getNode(source.parent);
841
- g.mergeNode(sourceParent.id);
842
- if (!willCreateCycle(g, sourceParent.id, source.id)) {
843
- g.mergeDirectedEdge(sourceParent.id, source.id);
844
- }
845
- if (target.parent && target.parent !== source.parent) {
846
- if (!willCreateCycle(g, sourceParent.id, target.parent)) {
847
- g.mergeDirectedEdge(sourceParent.id, target.parent);
848
- }
849
- }
850
- }
851
- }
852
- for (const { edge } of edgesWithCompounds) {
853
- addEdgeToGraph(edge);
854
- }
855
- invariant(sortedEdges.length === edges.length, "Not all edges were added to the graph");
856
- const sortedIds = topologicalSortExports.topologicalSort(g);
857
- let sorted = [];
858
- let unsorted = nodes.slice();
859
- for (const sortedId of sortedIds) {
860
- const indx = unsorted.findIndex((n) => n.id === sortedId);
861
- invariant(indx >= 0, `Node "${sortedId}" not found`);
862
- sorted.push(...unsorted.splice(indx, 1));
863
- }
864
- if (unsorted.length > 0 && sorted.length > 0) {
865
- sorted = sorted.flatMap((node) => {
866
- if (unsorted.length === 0) {
867
- return node;
868
- }
869
- const wereBefore = nodes.slice(0, nodes.indexOf(node)).filter((n) => unsorted.includes(n));
870
- if (wereBefore.length > 0) {
871
- unsorted = unsorted.filter((n) => !wereBefore.includes(n));
872
- return [...wereBefore, node];
873
- }
874
- return node;
875
- });
876
- }
877
- sorted.push(...unsorted);
878
- return {
879
- nodes: updateChildren(
880
- ensureParentsFirst(sorted)
881
- ),
882
- edges: sortedEdges
883
- };
884
- }
885
-
886
- function calcViewLayoutHash(view) {
887
- const tohash = {
888
- id: view.id,
889
- __: view._type ?? "element",
890
- autoLayout: view.autoLayout,
891
- nodes: t$d(
892
- view.nodes,
893
- t$e((n) => ({
894
- id: n.id,
895
- icon: e$4(n.icon) && n.icon !== "none" ? "Y" : "N",
896
- title: n.title,
897
- description: flattenMarkdownOrString(n.description),
898
- technology: n.technology ?? null,
899
- shape: n.shape,
900
- size: n.style.size ?? null,
901
- textSize: n.style.textSize ?? null,
902
- padding: n.style.padding ?? null,
903
- children: n.children
904
- })),
905
- t$6(({ id, ...node }) => [id, node])
906
- ),
907
- edges: t$d(
908
- view.edges,
909
- t$e((e) => ({
910
- source: e.source,
911
- target: e.target,
912
- label: e.label,
913
- description: flattenMarkdownOrString(e.description),
914
- technology: e.technology ?? null,
915
- dir: e.dir,
916
- head: e.head,
917
- tail: e.tail,
918
- line: e.line
919
- })),
920
- t$6(({ source, target, ...edge }) => [`${source}:${target}`, edge])
921
- )
922
- };
923
- view.hash = objectHash(tohash);
924
- return view;
925
- }
926
-
927
- class AbstractMemory {
928
- constructor(state) {
929
- this.state = state;
930
- }
931
- /**
932
- * Provides access to context types
933
- * !IMPORTANT: Should not be called in runtime
934
- *
935
- * @example
936
- * ```ts
937
- * type State = SomeMemory['Ctx']['MutableState']
938
- * ```
939
- */
940
- get Ctx() {
941
- throw new Error("Should not be called in runtime");
942
- }
943
- get elements() {
944
- return this.state.elements;
945
- }
946
- get explicits() {
947
- return this.state.explicits;
948
- }
949
- get final() {
950
- return this.state.final;
951
- }
952
- get connections() {
953
- return this.state.connections;
954
- }
955
- isEmpty() {
956
- return this.elements.size === 0 && this.connections.length === 0 && this.explicits.size === 0 && this.final.size === 0;
957
- }
958
- }
959
-
960
- class AbstractStageExclude {
961
- constructor(memory, expression) {
962
- this.memory = memory;
963
- this.expression = expression;
964
- }
965
- // Removed elements
966
- excluded = {
967
- elements: /* @__PURE__ */ new Set(),
968
- connections: []
969
- };
970
- markedToMoveExplicitToImplicit = false;
971
- _removeElement(element) {
972
- this.excluded.elements.add(element);
973
- }
974
- exclude(element) {
975
- if (!element) {
976
- return this;
977
- }
978
- if (isIterable(element)) {
979
- for (const el of element) {
980
- this._removeElement(el);
981
- }
982
- return this;
983
- }
984
- this._removeElement(element);
985
- return this;
986
- }
987
- _removeConnection(connection) {
988
- this.excluded.connections.push(connection);
989
- }
990
- /**
991
- * Excludes from the memory relationships from given connections (still connection may be included, but without given relationships)
992
- * @param moveExplicitToImplicit - if true, disconnected explicit elements will be moved to implicit
993
- * @default false
994
- */
995
- excludeConnections(connection, moveExplicitToImplicit) {
996
- if (e$1(moveExplicitToImplicit)) {
997
- invariant(!this.markedToMoveExplicitToImplicit, "Already marked to move explicits");
998
- this.markedToMoveExplicitToImplicit = moveExplicitToImplicit;
999
- }
1000
- if (isIterable(connection)) {
1001
- for (const c of connection) {
1002
- this._removeConnection(c);
1003
- }
1004
- return this;
1005
- }
1006
- this._removeConnection(connection);
1007
- return this;
1008
- }
1009
- isDirty() {
1010
- return this.excluded.elements.size > 0 || this.excluded.connections.length > 0;
1011
- }
1012
- isEmpty() {
1013
- return !this.isDirty();
1014
- }
1015
- /**
1016
- * Determines whether disconnected explicits should become implicits.
1017
- * By default moves all disconnected explicits to implicits, if there were operation to exclude elements.
1018
- *
1019
- * Override this method to change the behavior.
1020
- */
1021
- filterForMoveToImplicits(disconnectedExplicits) {
1022
- if (this.markedToMoveExplicitToImplicit || this.excluded.elements.size > 0) {
1023
- return disconnectedExplicits;
1024
- }
1025
- return /* @__PURE__ */ new Set();
1026
- }
1027
- // Check if Leaf EXPLICIT elements are becoming IMPLICIT
1028
- // (it means that they are not connected anymore)
1029
- moveDisconnectedExplicitsToImplicits(state) {
1030
- let disconnected = difference(
1031
- new Set(this.memory.connections.flatMap((c) => [c.source, c.target])),
1032
- new Set(state.connections.flatMap((c) => [c.source, c.target]))
1033
- );
1034
- disconnected = intersection(
1035
- disconnected,
1036
- state.elements
1037
- );
1038
- disconnected = t$d(
1039
- disconnected,
1040
- ifilter((el) => {
1041
- return state.explicits.has(el) && !isome(state.final, isDescendantOf(el));
1042
- }),
1043
- toSet()
1044
- );
1045
- if (disconnected.size > 0) {
1046
- disconnected = this.filterForMoveToImplicits(disconnected);
1047
- state.explicits = difference(state.explicits, disconnected);
1048
- state.final = difference(state.final, disconnected);
1049
- }
1050
- return state;
1051
- }
1052
- removeElements(state) {
1053
- state.elements = difference(state.elements, this.excluded.elements);
1054
- state.explicits = difference(state.explicits, this.excluded.elements);
1055
- state.final = difference(state.final, this.excluded.elements);
1056
- return state;
1057
- }
1058
- removeConnections(state) {
1059
- const excludedMap = this.excluded.connections.reduce((acc, c) => {
1060
- const existing = acc.get(c.id);
1061
- if (existing) {
1062
- acc.set(c.id, existing.mergeWith(c));
1063
- } else {
1064
- acc.set(c.id, c);
1065
- }
1066
- return acc;
1067
- }, /* @__PURE__ */ new Map());
1068
- let disconnected = /* @__PURE__ */ new Set();
1069
- state.connections = state.connections.reduce((acc, c) => {
1070
- const excluded = excludedMap.get(c.id);
1071
- if (excluded) {
1072
- disconnected.add(c.source);
1073
- disconnected.add(c.target);
1074
- const diff = c.difference(excluded);
1075
- if (diff.nonEmpty()) {
1076
- acc.push(diff);
1077
- }
1078
- } else {
1079
- acc.push(c);
1080
- }
1081
- return acc;
1082
- }, []);
1083
- for (const stillExists of state.connections) {
1084
- disconnected.delete(stillExists.source);
1085
- disconnected.delete(stillExists.target);
1086
- if (stillExists.boundary && state.elements.has(stillExists.boundary)) {
1087
- disconnected.delete(stillExists.boundary);
1088
- }
1089
- }
1090
- if (disconnected.size === 0) {
1091
- return state;
1092
- }
1093
- disconnected = difference(disconnected, state.explicits);
1094
- state.final = difference(state.final, disconnected);
1095
- return state;
1096
- }
1097
- /**
1098
- * Precommit hook
1099
- */
1100
- precommit(state) {
1101
- return state;
1102
- }
1103
- /**
1104
- * Postcommit hook
1105
- */
1106
- postcommit(state) {
1107
- invariant(difference(state.explicits, state.elements).size === 0, "Explicits must be subset of elements");
1108
- invariant(difference(state.final, state.elements).size === 0, "Final elements must be subset of elements");
1109
- return state;
1110
- }
1111
- commit() {
1112
- let state = this.precommit(this.memory.mutableState());
1113
- if (this.excluded.elements.size > 0) {
1114
- const excludedConnections = state.connections.filter((c) => this.excluded.elements.has(c.source) || this.excluded.elements.has(c.target)).flatMap((c) => [
1115
- c,
1116
- ...findAscendingConnections(state.connections, c).map((asc) => asc.intersect(c))
1117
- ]).filter((asc) => asc.nonEmpty());
1118
- this.excludeConnections(excludedConnections);
1119
- }
1120
- if (this.excluded.connections.length > 0) {
1121
- state = this.removeConnections(state);
1122
- }
1123
- if (this.excluded.elements.size > 0) {
1124
- state = this.removeElements(state);
1125
- }
1126
- return this.memory.update(this.postcommit(state));
1127
- }
1128
- }
1129
-
1130
- class AbstractStageInclude {
1131
- constructor(memory, expression) {
1132
- this.memory = memory;
1133
- this.expression = expression;
1134
- }
1135
- // New elements
1136
- explicits = /* @__PURE__ */ new Set();
1137
- implicits = /* @__PURE__ */ new Set();
1138
- // Ordered Set of explicit and implicit elements
1139
- _ordered = /* @__PURE__ */ new Set();
1140
- _connections = [];
1141
- get elements() {
1142
- return this.explicits;
1143
- }
1144
- /**
1145
- * Connections from this stage
1146
- */
1147
- get connections() {
1148
- return this._connections;
1149
- }
1150
- mergedConnections() {
1151
- return mergeConnections([
1152
- ...this.memory.connections,
1153
- ...this._connections
1154
- ]);
1155
- }
1156
- connectWithExisting(_element, _direction) {
1157
- throw new Error("Method not implements, depends on the model");
1158
- }
1159
- /**
1160
- * Possible to override
1161
- */
1162
- _addExplicit(elements) {
1163
- this._ordered.add(elements);
1164
- this.explicits.add(elements);
1165
- this.implicits.delete(elements);
1166
- }
1167
- addExplicit(element) {
1168
- if (!element) {
1169
- return this;
1170
- }
1171
- if (isIterable(element)) {
1172
- for (const el of element) {
1173
- this._addExplicit(el);
1174
- }
1175
- return this;
1176
- }
1177
- this._addExplicit(element);
1178
- return this;
1179
- }
1180
- /**
1181
- * Possible to override
1182
- */
1183
- _addImplicit(elements) {
1184
- if (this.explicits.has(elements)) {
1185
- return;
1186
- }
1187
- this._ordered.add(elements);
1188
- this.implicits.add(elements);
1189
- }
1190
- addImplicit(elements) {
1191
- if (!elements) {
1192
- return this;
1193
- }
1194
- if (isIterable(elements)) {
1195
- for (const el of elements) {
1196
- this._addImplicit(el);
1197
- }
1198
- return this;
1199
- }
1200
- this._addImplicit(elements);
1201
- return this;
1202
- }
1203
- /**
1204
- * Possible to override
1205
- */
1206
- _addConnection(connection) {
1207
- this._connections.push(connection);
1208
- this._addImplicit(connection.source);
1209
- this._addImplicit(connection.target);
1210
- }
1211
- addConnections(connection) {
1212
- if (isIterable(connection)) {
1213
- for (const c of connection) {
1214
- this._addConnection(c);
1215
- }
1216
- return this;
1217
- }
1218
- this._addConnection(connection);
1219
- return this;
1220
- }
1221
- isDirty() {
1222
- return this.explicits.size > 0 || this.implicits.size > 0 || this._connections.length > 0;
1223
- }
1224
- isEmpty() {
1225
- return !this.isDirty();
1226
- }
1227
- /**
1228
- * Precommit hook
1229
- */
1230
- precommit(state) {
1231
- return state;
1232
- }
1233
- /**
1234
- * Postcommit hook
1235
- */
1236
- postcommit(state) {
1237
- return state;
1238
- }
1239
- processConnections(connections) {
1240
- return connections;
1241
- }
1242
- commit() {
1243
- let state = this.precommit(this.memory.mutableState());
1244
- let fromConnections = /* @__PURE__ */ new Set();
1245
- if (this._connections.length > 0) {
1246
- const [fromKnown, rest] = t$4(
1247
- this._connections,
1248
- (c) => state.final.has(c.source)
1249
- );
1250
- state.connections = this.processConnections(
1251
- mergeConnections([
1252
- ...state.connections,
1253
- ...fromKnown,
1254
- ...rest
1255
- ])
1256
- );
1257
- fromConnections = new Set(state.connections.flatMap((c) => [c.source, c.target]));
1258
- }
1259
- state.elements = union(
1260
- state.elements,
1261
- this._ordered,
1262
- this.explicits,
1263
- fromConnections,
1264
- this.implicits
1265
- );
1266
- state.explicits = intersection(
1267
- state.elements,
1268
- union(
1269
- state.explicits,
1270
- this.explicits
1271
- )
1272
- );
1273
- state.final = intersection(
1274
- state.elements,
1275
- union(
1276
- state.final,
1277
- this.explicits,
1278
- fromConnections
1279
- )
1280
- );
1281
- return this.memory.update(this.postcommit(state));
1282
- }
1283
- }
1284
-
1285
- function treeFromMemoryState(memory, filter = "final") {
1286
- const sorted = sortParentsFirst(toArray(filter === "final" ? memory.final : memory.elements));
1287
- const connected = new Set(memory.connections.flatMap((c) => [c.source, c.target]));
1288
- const root = new Set(sorted);
1289
- const parents = new DefaultMap(() => null);
1290
- const children = sorted.reduce((acc, parent, index, all) => {
1291
- acc.set(
1292
- parent,
1293
- all.slice(index + 1).filter((e) => isAncestor(parent, e)).map((e) => {
1294
- root.delete(e);
1295
- return e;
1296
- }).reduce((acc2, el) => {
1297
- if (!acc2.some((e) => isAncestor(e, el))) {
1298
- acc2.push(el);
1299
- parents.set(el, parent);
1300
- }
1301
- return acc2;
1302
- }, [])
1303
- );
1304
- return acc;
1305
- }, new DefaultMap(() => []));
1306
- return {
1307
- root,
1308
- connected,
1309
- hasInOut: (el) => memory.connections.some(Connection.isAnyInOut(el.id)),
1310
- parent: (el) => parents.get(el),
1311
- children: (el) => children.get(el)
1312
- };
1313
- }
1314
-
1315
- let StageExclude$1 = class StageExclude extends AbstractStageExclude {
1316
- };
1317
-
1318
- function elementExprToPredicate(target) {
1319
- if (ModelFqnExpr.isCustom(target)) {
1320
- return elementExprToPredicate(target.custom.expr);
1321
- }
1322
- if (ModelFqnExpr.isWhere(target)) {
1323
- const predicate = elementExprToPredicate(target.where.expr);
1324
- const where = whereOperatorAsPredicate(target.where.condition);
1325
- return (n) => predicate(n) && where(n);
1326
- }
1327
- if (ModelFqnExpr.isElementKindExpr(target)) {
1328
- return target.isEqual ? (n) => n.kind === target.elementKind : (n) => n.kind !== target.elementKind;
1329
- }
1330
- if (ModelFqnExpr.isElementTagExpr(target)) {
1331
- return target.isEqual ? ({ tags }) => tags.includes(target.elementTag) : ({ tags }) => !tags.includes(target.elementTag);
1332
- }
1333
- if (ModelFqnExpr.isWildcard(target)) {
1334
- return () => true;
1335
- }
1336
- if (ModelFqnExpr.isModelRef(target)) {
1337
- const fqn = FqnRef.flatten(target.ref);
1338
- if (target.selector === "expanded") {
1339
- return (n) => {
1340
- return n.id === fqn || parentFqn(n.id) === fqn;
1341
- };
1342
- }
1343
- if (target.selector === "descendants" || target.selector === "children") {
1344
- const fqnWithDot = fqn + ".";
1345
- return (n) => {
1346
- return n.id.startsWith(fqnWithDot);
1347
- };
1348
- }
1349
- return (n) => {
1350
- return n.id === fqn;
1351
- };
1352
- }
1353
- nonexhaustive(target);
1354
- }
1355
-
1356
- function applyViewRuleStyle(rule, predicate, nodes) {
1357
- const { shape, color, icon, ...rest } = rule.style;
1358
- const nonEmptyStyle = !e$5(rest);
1359
- t$d(
1360
- nodes,
1361
- n$d(e$7(isGroupElementKind)),
1362
- n$d(predicate),
1363
- t$7((n) => {
1364
- n.shape = shape ?? n.shape;
1365
- n.color = color ?? n.color;
1366
- if (e$6(icon)) {
1367
- n.icon = icon;
1368
- }
1369
- if (e$6(rule.notation)) {
1370
- n.notation = rule.notation;
1371
- }
1372
- if (nonEmptyStyle) {
1373
- n.style = {
1374
- ...n.style,
1375
- ...rest
1376
- };
1377
- }
1378
- })
1379
- );
1380
- }
1381
- function applyViewRuleStyles(rules, nodes) {
1382
- for (const rule of rules) {
1383
- if (!isViewRuleStyle(rule) || rule.targets.length === 0) {
1384
- continue;
1385
- }
1386
- const predicates = rule.targets.map(elementExprToPredicate);
1387
- applyViewRuleStyle(
1388
- rule,
1389
- t$g(predicates),
1390
- nodes
1391
- );
1392
- }
1393
- return nodes;
1394
- }
1395
-
1396
- function updateDepthOfAncestors(node, nodes) {
1397
- let parentNd;
1398
- while (!!node.parent && (parentNd = nodes.get(node.parent))) {
1399
- const depth = parentNd.depth ?? 1;
1400
- parentNd.depth = Math.max(depth, (node.depth ?? 0) + 1);
1401
- if (parentNd.depth === depth) {
1402
- break;
1403
- }
1404
- node = parentNd;
1405
- }
1406
- }
1407
- function elementModelToNodeSource(el) {
1408
- const {
1409
- id,
1410
- title,
1411
- ...rest
1412
- } = n$6(el.$element, ["summary", "description", "metadata", "style", "tags"]);
1413
- const { color, icon, shape, ...style } = el.style;
1414
- return exact({
1415
- id,
1416
- title,
1417
- modelRef: id,
1418
- shape,
1419
- color,
1420
- icon,
1421
- style,
1422
- description: preferSummary(el.$element),
1423
- tags: [...el.tags],
1424
- ...rest
1425
- });
1426
- }
1427
- function buildComputedNodes({ defaults }, elements, groups) {
1428
- const nodesMap = /* @__PURE__ */ new Map();
1429
- const elementToGroup = /* @__PURE__ */ new Map();
1430
- groups?.forEach(({ id, parent, viewRule, elements: elements2 }) => {
1431
- if (parent) {
1432
- nonNullable(nodesMap.get(parent), `Parent group node ${parent} not found`).children.push(id);
1433
- }
1434
- nodesMap.set(id, {
1435
- id,
1436
- parent,
1437
- kind: GroupElementKind,
1438
- title: viewRule.title ?? "",
1439
- color: viewRule.color ?? defaults.group?.color ?? defaults.color,
1440
- shape: "rectangle",
1441
- children: [],
1442
- inEdges: [],
1443
- outEdges: [],
1444
- level: 0,
1445
- depth: 0,
1446
- tags: [],
1447
- style: exact({
1448
- border: viewRule.border ?? defaults.group?.border ?? defaults.border,
1449
- opacity: viewRule.opacity ?? defaults.group?.opacity ?? defaults.opacity,
1450
- size: viewRule.size,
1451
- multiple: viewRule.multiple,
1452
- padding: viewRule.padding,
1453
- textSize: viewRule.textSize
1454
- })
1455
- });
1456
- for (const e of elements2) {
1457
- elementToGroup.set(e.id, id);
1458
- }
1459
- });
1460
- Array.from(elements).sort(compareByFqnHierarchically).forEach(({ id, ...el }) => {
1461
- let parent = parentFqn(id);
1462
- let level = 0;
1463
- let parentNd;
1464
- while (parent) {
1465
- parentNd = nodesMap.get(parent);
1466
- if (parentNd) {
1467
- break;
1468
- }
1469
- parent = parentFqn(parent);
1470
- }
1471
- const fqn = el.modelRef ?? id;
1472
- if (!parentNd && elementToGroup.has(fqn)) {
1473
- const parentGroupId = nonNullable(elementToGroup.get(fqn));
1474
- parentNd = nodesMap.get(parentGroupId);
1475
- parent = parentGroupId;
1476
- }
1477
- if (parentNd) {
1478
- if (parentNd.children.length == 0) {
1479
- parentNd.depth = 1;
1480
- updateDepthOfAncestors(parentNd, nodesMap);
1481
- }
1482
- parentNd.children.push(id);
1483
- level = parentNd.level + 1;
1484
- }
1485
- const node = exact({
1486
- id,
1487
- parent,
1488
- level,
1489
- children: [],
1490
- inEdges: [],
1491
- outEdges: [],
1492
- ...el
1493
- });
1494
- nodesMap.set(id, node);
1495
- });
1496
- const orderedMap = /* @__PURE__ */ new Map();
1497
- groups?.forEach(({ id }) => {
1498
- orderedMap.set(id, nonNullable(nodesMap.get(id)));
1499
- });
1500
- elements.forEach(({ id }) => {
1501
- orderedMap.set(id, nonNullable(nodesMap.get(id)));
1502
- });
1503
- return orderedMap;
1504
- }
1505
-
1506
- function pickRelationshipProps(relation) {
1507
- const {
1508
- title,
1509
- description = null
1510
- } = relation;
1511
- return {
1512
- // Pick description only if title is present
1513
- ...title && {
1514
- title,
1515
- description
1516
- },
1517
- ...t$i(relation, ["color", "technology", "head", "line", "tail", "kind", "navigateTo"])
1518
- };
1519
- }
1520
- function mergePropsFromRelationships(relations, prefer) {
1521
- const allprops = t$d(
1522
- relations,
1523
- t$2(
1524
- (acc, r) => {
1525
- if (e$4(r.title) && !acc.title.includes(r.title)) {
1526
- acc.title.push(r.title);
1527
- }
1528
- if (e$4(r.description) && !acc.description.some(t$h(r.description))) {
1529
- acc.description.push(r.description);
1530
- }
1531
- if (e$4(r.technology) && !acc.technology.includes(r.technology)) {
1532
- acc.technology.push(r.technology);
1533
- }
1534
- if (e$4(r.kind) && !acc.kind.includes(r.kind)) {
1535
- acc.kind.push(r.kind);
1536
- }
1537
- if (e$4(r.color) && !acc.color.includes(r.color)) {
1538
- acc.color.push(r.color);
1539
- }
1540
- if (e$4(r.line) && !acc.line.includes(r.line)) {
1541
- acc.line.push(r.line);
1542
- }
1543
- if (e$4(r.head) && !acc.head.includes(r.head)) {
1544
- acc.head.push(r.head);
1545
- }
1546
- if (e$4(r.tail) && !acc.tail.includes(r.tail)) {
1547
- acc.tail.push(r.tail);
1548
- }
1549
- if (e$4(r.navigateTo) && !acc.navigateTo.includes(r.navigateTo)) {
1550
- acc.navigateTo.push(r.navigateTo);
1551
- }
1552
- if (r.tags) {
1553
- acc.tags.push(...r.tags);
1554
- }
1555
- return acc;
1556
- },
1557
- {
1558
- title: [],
1559
- description: [],
1560
- technology: [],
1561
- kind: [],
1562
- head: [],
1563
- tail: [],
1564
- color: [],
1565
- tags: [],
1566
- line: [],
1567
- navigateTo: []
1568
- }
1569
- )
1570
- );
1571
- let title = t$5(allprops.title) ?? (allprops.title.length > 1 ? "[...]" : void 0);
1572
- const tags = n$e(allprops.tags);
1573
- let merged = exact({
1574
- title,
1575
- description: t$5(allprops.description),
1576
- technology: t$5(allprops.technology),
1577
- kind: t$5(allprops.kind),
1578
- head: t$5(allprops.head),
1579
- tail: t$5(allprops.tail),
1580
- color: t$5(allprops.color),
1581
- line: t$5(allprops.line),
1582
- navigateTo: t$5(allprops.navigateTo),
1583
- ...isNonEmptyArray(tags) && { tags }
1584
- });
1585
- if (prefer) {
1586
- const preferred = pickRelationshipProps(prefer);
1587
- merged = t$3({
1588
- ...merged,
1589
- ...preferred
1590
- }, e$4);
1591
- }
1592
- if (e$8(merged.title) && e$4(merged.technology)) {
1593
- merged.title = `[${merged.technology}]`;
1594
- delete merged.technology;
1595
- }
1596
- return merged;
1597
- }
1598
-
1599
- const { findConnection: findConnection$2, findConnectionsBetween: findConnectionsBetween$2, findConnectionsWithin: findConnectionsWithin$1 } = deploymentConnection;
1600
- function resolveElements$1(model, expr) {
1601
- const ref = model.element(expr.ref.deployment);
1602
- if (ref.isDeploymentNode()) {
1603
- if (expr.selector === "children") {
1604
- return [...ref.children()];
1605
- }
1606
- if (expr.selector === "expanded") {
1607
- return [ref, ...ref.children()];
1608
- }
1609
- if (expr.selector === "descendants") {
1610
- return [...ref.descendants()];
1611
- }
1612
- }
1613
- return [ref];
1614
- }
1615
- function resolveModelElements(model, expr) {
1616
- const ref = model.$model.element(expr.ref.model);
1617
- if (expr.selector === "children") {
1618
- return [...ref.children()];
1619
- }
1620
- if (expr.selector === "expanded") {
1621
- return [ref, ...ref.children()];
1622
- }
1623
- if (expr.selector === "descendants") {
1624
- return [...ref.descendants()];
1625
- }
1626
- return [ref];
1627
- }
1628
- function deploymentExpressionToPredicate(target) {
1629
- if (FqnExpr.isWildcard(target)) {
1630
- return () => true;
1631
- }
1632
- if (FqnExpr.isElementTagExpr(target) || FqnExpr.isElementKindExpr(target)) {
1633
- throw new Error("element kind and tag expressions are not supported in deployment view rules");
1634
- }
1635
- if (FqnExpr.isDeploymentRef(target)) {
1636
- const fqn = target.ref.deployment;
1637
- if (target.selector === "expanded") {
1638
- const fqnWithDot = fqn + ".";
1639
- return (n) => n.id === fqn || n.id.startsWith(fqnWithDot);
1640
- }
1641
- if (target.selector === "descendants") {
1642
- const fqnWithDot = fqn + ".";
1643
- return (n) => n.id.startsWith(fqnWithDot);
1644
- }
1645
- if (target.selector === "children") {
1646
- return (n) => parentFqn(n.id) === fqn;
1647
- }
1648
- return (n) => n.id === fqn;
1649
- }
1650
- if (FqnExpr.isModelRef(target)) {
1651
- const fqn = target.ref.model;
1652
- if (target.selector === "expanded") {
1653
- const fqnWithDot = fqn + ".";
1654
- return (n) => {
1655
- const m = n.modelRef ?? null;
1656
- if (!m) {
1657
- return true;
1658
- }
1659
- return m === fqn || m.startsWith(fqnWithDot);
1660
- };
1661
- }
1662
- if (target.selector === "descendants") {
1663
- const fqnWithDot = fqn + ".";
1664
- return (n) => {
1665
- const m = n.modelRef ?? null;
1666
- if (!m) {
1667
- return true;
1668
- }
1669
- return m.startsWith(fqnWithDot);
1670
- };
1671
- }
1672
- if (target.selector === "children") {
1673
- return (n) => {
1674
- const m = n.modelRef ?? null;
1675
- if (!m) {
1676
- return true;
1677
- }
1678
- return parentFqn(m) === fqn;
1679
- };
1680
- }
1681
- return (n) => {
1682
- const m = n.modelRef ?? null;
1683
- if (!m) {
1684
- return true;
1685
- }
1686
- return m === fqn;
1687
- };
1688
- }
1689
- nonexhaustive(target);
1690
- }
1691
- function instanceSummary(model) {
1692
- return preferSummary(model.$instance) ?? preferSummary(model.element.$element);
1693
- }
1694
- function deploymentNodeToNodeSource(el) {
1695
- const id = el.id;
1696
- const onlyOneInstance = el.onlyOneInstance();
1697
- return exact({
1698
- id,
1699
- deploymentRef: id,
1700
- title: el.title,
1701
- kind: el.kind,
1702
- technology: el.technology ?? void 0,
1703
- links: t$b(el.links, 1) ? [...el.links] : void 0,
1704
- notation: el.$node.notation ?? void 0,
1705
- color: el.color,
1706
- shape: el.shape,
1707
- modelRef: onlyOneInstance?.element.id,
1708
- icon: el.style.icon,
1709
- description: preferSummary(el.$node) ?? void 0,
1710
- tags: [...el.tags],
1711
- style: n$6(el.style, ["icon", "shape", "color"])
1712
- });
1713
- }
1714
- function instanceToNodeSource(el) {
1715
- const instance = el.$instance;
1716
- const element = el.element;
1717
- const { icon, color, shape, ...style } = el.style;
1718
- const links = [
1719
- ...element.links,
1720
- ...instance.links ?? []
1721
- ];
1722
- return exact({
1723
- id: el.id,
1724
- kind: "instance",
1725
- title: el.title,
1726
- description: instanceSummary(el) ?? void 0,
1727
- technology: el.technology ?? void 0,
1728
- tags: [...el.tags],
1729
- links: t$b(links, 1) ? links : void 0,
1730
- icon,
1731
- color,
1732
- shape,
1733
- style,
1734
- deploymentRef: instance.id,
1735
- modelRef: element.id,
1736
- notation: instance.notation
1737
- });
1738
- }
1739
- function toNodeSource(el) {
1740
- if (el.isInstance()) {
1741
- return instanceToNodeSource(el);
1742
- }
1743
- return deploymentNodeToNodeSource(el);
1744
- }
1745
- function toComputedEdges$1(connections) {
1746
- return connections.reduce((acc, e) => {
1747
- const relations = [
1748
- ...e.relations.model,
1749
- ...e.relations.deployment
1750
- ];
1751
- invariant(t$b(relations, 1), "Edge must have at least one relation");
1752
- const defaults = e.source.$model.$styles.defaults;
1753
- const source = e.source.id;
1754
- const target = e.target.id;
1755
- const {
1756
- title,
1757
- color = defaults.relationship.color,
1758
- line = defaults.relationship.line,
1759
- head = defaults.relationship.arrow,
1760
- ...props
1761
- } = mergePropsFromRelationships(relations.map((r) => r.$relationship));
1762
- const edge = exact({
1763
- id: e.id,
1764
- parent: e.boundary?.id ?? null,
1765
- source,
1766
- target,
1767
- label: title ?? null,
1768
- relations: relations.map((r) => r.id),
1769
- color,
1770
- line,
1771
- head,
1772
- ...props
1773
- });
1774
- const existing = acc.find((e2) => e2.source === target && e2.target === source);
1775
- if (existing && edge.label === existing.label) {
1776
- existing.dir = "both";
1777
- const head2 = existing.head ?? edge.head ?? e.source.$model.$styles.defaults.relationship.arrow;
1778
- existing.head ??= head2;
1779
- existing.tail ??= head2;
1780
- if (edge.color) {
1781
- existing.color ??= edge.color;
1782
- }
1783
- if (edge.line) {
1784
- existing.line ??= edge.line;
1785
- }
1786
- return acc;
1787
- }
1788
- acc.push(edge);
1789
- return acc;
1790
- }, []);
1791
- }
1792
- function buildNodes$1(model, memory) {
1793
- const nodesMap = buildComputedNodes(model.$styles, [...memory.final].map(toNodeSource));
1794
- for (const node of nodesMap.values()) {
1795
- if (!node.deploymentRef || !node.modelRef || node.children.length > 0) {
1796
- continue;
1797
- }
1798
- const deploymentNode = model.deployment.element(node.deploymentRef);
1799
- const onlyOneInstance = deploymentNode.isDeploymentNode() && deploymentNode.onlyOneInstance();
1800
- if (!onlyOneInstance) {
1801
- continue;
1802
- }
1803
- if (node.title === deploymentNode.name) {
1804
- node.title = onlyOneInstance.title;
1805
- }
1806
- node.description ??= instanceSummary(onlyOneInstance) ?? null;
1807
- node.technology ??= onlyOneInstance.technology;
1808
- if (e$5(node.tags)) {
1809
- node.tags = [...onlyOneInstance.tags];
1810
- }
1811
- if ((!node.links || e$5(node.links)) && t$b(onlyOneInstance.links, 1)) {
1812
- node.links = [...onlyOneInstance.links];
1813
- }
1814
- const defaults = model.$styles.defaults;
1815
- if (node.shape === defaults.shape && node.shape !== onlyOneInstance.shape) {
1816
- node.shape = onlyOneInstance.shape;
1817
- node.notation = null;
1818
- }
1819
- if (node.color === defaults.color && node.color !== onlyOneInstance.color) {
1820
- node.color = onlyOneInstance.color;
1821
- node.notation = null;
1822
- }
1823
- if (!node.icon && onlyOneInstance.icon) {
1824
- node.icon = onlyOneInstance.icon;
1825
- }
1826
- }
1827
- return nodesMap;
1828
- }
1829
- function applyDeploymentViewRuleStyles(rules, nodes) {
1830
- for (const rule of rules) {
1831
- if (!isViewRuleStyle(rule) || rule.targets.length === 0) {
1832
- continue;
1833
- }
1834
- const predicates = rule.targets.map(deploymentExpressionToPredicate);
1835
- applyViewRuleStyle(
1836
- rule,
1837
- t$g(predicates),
1838
- nodes
1839
- );
1840
- }
1841
- return nodes;
1842
- }
1843
-
1844
- function findCrossBoundarySameSourceOrTarget(connections) {
1845
- const groupedByRelation = new DefaultMap(() => []);
1846
- for (const conn of connections) {
1847
- for (const relation of conn.relations.model) {
1848
- groupedByRelation.get(relation).push(conn);
1849
- }
1850
- }
1851
- const excludedRelations = new DefaultMap(() => /* @__PURE__ */ new Set());
1852
- for (const [relation, sameRelationGroup] of groupedByRelation) {
1853
- if (!t$b(sameRelationGroup, 2)) {
1854
- continue;
1855
- }
1856
- t$d(
1857
- sameRelationGroup,
1858
- t$m((conn) => [
1859
- { group: `$source-${conn.source.id}`, conn },
1860
- { group: `$target-${conn.target.id}`, conn }
1861
- ]),
1862
- t$l(e$9("group")),
1863
- t$k(),
1864
- n$d(t$b(2)),
1865
- t$7(
1866
- // In each group, sort by hierarchy, first are deepest
1867
- t$j(
1868
- t$e(e$9("conn")),
1869
- sortConnectionsByBoundaryHierarchy("desc"),
1870
- // Drop first, as it is the deepest
1871
- // Drop if boundary is same as previous
1872
- t$9((conn, i, all) => i === 0 || conn.boundary === all[i - 1].boundary),
1873
- // Drop relations from boundaries above
1874
- t$7((conn) => {
1875
- excludedRelations.get(conn).add(relation);
1876
- })
1877
- )
1878
- )
1879
- );
1880
- }
1881
- return excludedRelations;
1882
- }
1883
- function findCrossBoundaryConnections(connections) {
1884
- connections = mergeConnections(connections);
1885
- const excludedRelations = findCrossBoundarySameSourceOrTarget(connections);
1886
- for (const c of connections) {
1887
- const { source, target } = c;
1888
- const connectionModelRelations = c.relations.model;
1889
- if (source.isDeploymentNode() !== target.isDeploymentNode()) {
1890
- const node = source.isDeploymentNode() ? source : c.target;
1891
- invariant(node.isDeploymentNode());
1892
- const nodeInternals = node.internalModelRelationships();
1893
- const toExclude = intersection(
1894
- connectionModelRelations,
1895
- nodeInternals
1896
- );
1897
- for (const relation of toExclude) {
1898
- excludedRelations.get(c).add(relation);
1899
- }
1900
- continue;
1901
- }
1902
- if (source.isDeploymentNode() && target.isDeploymentNode()) {
1903
- const toExclude = union(
1904
- // Exclude node internals (otherwise thay are cross-boundary)
1905
- intersection(
1906
- c.relations.model,
1907
- source.internalModelRelationships()
1908
- ),
1909
- intersection(
1910
- c.relations.model,
1911
- target.internalModelRelationships()
1912
- )
1913
- );
1914
- for (const relation of toExclude) {
1915
- excludedRelations.get(c).add(relation);
1916
- }
1917
- }
1918
- }
1919
- return t$d(
1920
- excludedRelations.entries(),
1921
- imap(
1922
- ([c, excluded]) => c.update({
1923
- model: excluded,
1924
- deployment: null
1925
- })
1926
- ),
1927
- toArray()
1928
- );
1929
- }
1930
- function cleanCrossBoundary(connections) {
1931
- return differenceConnections(
1932
- connections,
1933
- findCrossBoundaryConnections(connections)
1934
- );
1935
- }
1936
- function findRedundantConnections$1(connections) {
1937
- return t$d(
1938
- connections,
1939
- mergeConnections,
1940
- t$2((redundants, connection) => {
1941
- const { source, target, relations } = connection;
1942
- if (source.isInstance() && target.isInstance()) {
1943
- return redundants;
1944
- }
1945
- let redundantAccum = RelationshipsAccum.empty();
1946
- if (source.isDeploymentNode() && target.isDeploymentNode()) {
1947
- const [reversed] = findConnection$2(target, source, "directed");
1948
- if (reversed) {
1949
- redundantAccum = relations.intersect(reversed.relations);
1950
- }
1951
- }
1952
- for (const c of connections) {
1953
- if (isNestedConnection(c, connection)) {
1954
- redundantAccum = redundantAccum.union(
1955
- relations.intersect(c.relations)
1956
- );
1957
- }
1958
- }
1959
- if (redundantAccum.nonEmpty) {
1960
- redundants.push(
1961
- new DeploymentConnectionModel(
1962
- source,
1963
- target,
1964
- redundantAccum
1965
- )
1966
- );
1967
- }
1968
- return redundants;
1969
- }, [])
1970
- );
1971
- }
1972
- function cleanRedundantRelationships(connections) {
1973
- return differenceConnections(
1974
- connections,
1975
- findRedundantConnections$1(connections)
1976
- );
1977
- }
1978
-
1979
- let StageInclude$1 = class StageInclude extends AbstractStageInclude {
1980
- /**
1981
- * Connects elements with existing ones in the memory
1982
- */
1983
- connectWithExisting(elements, direction = "both") {
1984
- const before = this._connections.length;
1985
- const hasChanged = () => this._connections.length > before;
1986
- if (!isIterable(elements)) {
1987
- if (direction === "in" || direction === "both") {
1988
- for (const el of this.memory.elements) {
1989
- this.addConnections(
1990
- findConnection$2(el, elements, "directed")
1991
- );
1992
- }
1993
- }
1994
- if (direction === "out" || direction === "both") {
1995
- this.addConnections(
1996
- findConnectionsBetween$2(elements, this.memory.elements, "directed")
1997
- );
1998
- }
1999
- return hasChanged();
2000
- }
2001
- const targets = [...elements];
2002
- if (direction === "in" || direction === "both") {
2003
- for (const el of this.memory.elements) {
2004
- this.addConnections(
2005
- findConnectionsBetween$2(el, targets, "directed")
2006
- );
2007
- }
2008
- }
2009
- if (direction === "out" || direction === "both") {
2010
- for (const el of targets) {
2011
- this.addConnections(
2012
- findConnectionsBetween$2(el, this.memory.elements, "directed")
2013
- );
2014
- }
2015
- }
2016
- return hasChanged();
2017
- }
2018
- processConnections(connections) {
2019
- const clean = t$d(
2020
- connections,
2021
- cleanCrossBoundary,
2022
- cleanRedundantRelationships
2023
- );
2024
- t$d(
2025
- clean,
2026
- // Process only connection from this stage
2027
- // filter(c => this._connections.some(c2 => c2.id === c.id)),
2028
- t$7(({ source, target, boundary }) => {
2029
- t$d(
2030
- t$n(
2031
- [...toArray(source.ancestors()).reverse(), source],
2032
- [...toArray(target.ancestors()).reverse(), target]
2033
- ),
2034
- // Filter out common ancestors
2035
- t$9(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor),
2036
- n(1),
2037
- t$7(([sourceAncestor, targetAncestor]) => {
2038
- if (source === sourceAncestor && target === targetAncestor) {
2039
- this.addImplicit(boundary);
2040
- return;
2041
- }
2042
- if (sourceAncestor !== source && sourceAncestor.isDeploymentNode() && !sourceAncestor.onlyOneInstance()) {
2043
- this.addImplicit(sourceAncestor);
2044
- }
2045
- if (targetAncestor !== target && targetAncestor.isDeploymentNode() && !targetAncestor.onlyOneInstance()) {
2046
- this.addImplicit(targetAncestor);
2047
- }
2048
- })
2049
- );
2050
- })
2051
- );
2052
- return clean;
2053
- }
2054
- };
2055
-
2056
- let Memory$1 = class Memory extends AbstractMemory {
2057
- static empty() {
2058
- return new Memory({
2059
- elements: /* @__PURE__ */ new Set(),
2060
- explicits: /* @__PURE__ */ new Set(),
2061
- final: /* @__PURE__ */ new Set(),
2062
- connections: []
2063
- });
2064
- }
2065
- stageInclude(expr) {
2066
- return new StageInclude$1(this, expr);
2067
- }
2068
- stageExclude(expr) {
2069
- return new StageExclude$1(this, expr);
2070
- }
2071
- mutableState() {
2072
- return {
2073
- elements: new Set(this.state.elements),
2074
- explicits: new Set(this.state.explicits),
2075
- final: new Set(this.state.final),
2076
- connections: [...this.state.connections]
2077
- };
2078
- }
2079
- update(newstate) {
2080
- return new Memory({
2081
- ...this.state,
2082
- ...newstate
2083
- });
2084
- }
2085
- equals(other) {
2086
- return other instanceof Memory && t$h(this.state, other.state);
2087
- }
2088
- diff(state) {
2089
- return {
2090
- added: {
2091
- elements: toArray(difference(state.elements, this.elements)),
2092
- explicits: toArray(difference(state.explicits, this.explicits)),
2093
- final: toArray(difference(state.final, this.final)),
2094
- connections: toArray(differenceConnections(state.connections, this.connections))
2095
- },
2096
- removed: {
2097
- elements: toArray(difference(this.elements, state.elements)),
2098
- explicits: toArray(difference(this.explicits, state.explicits)),
2099
- final: toArray(difference(this.final, state.final)),
2100
- connections: differenceConnections(this.connections, state.connections)
2101
- }
2102
- };
2103
- }
2104
- toString() {
2105
- return [
2106
- "final:",
2107
- ...[...this.final].map((e) => " " + e.id),
2108
- "connections:",
2109
- ...this.connections.map((c) => " " + c.expression)
2110
- ].join("\n");
2111
- }
2112
- [customInspectSymbol](_depth, _inspectOptions, _inspect) {
2113
- const asString = this.toString();
2114
- return asString;
2115
- }
2116
- };
2117
-
2118
- const WhereDeploymentRefPredicate = {
2119
- include: ({ expr, model, memory, stage }) => {
2120
- const where = whereOperatorAsPredicate(expr.where.condition);
2121
- return predicateToPatch("include", { expr: expr.where.expr, model, stage, memory, where });
2122
- },
2123
- exclude: ({ expr, model, memory, stage }) => {
2124
- const where = whereOperatorAsPredicate(expr.where.condition);
2125
- return predicateToPatch("exclude", { expr: expr.where.expr, model, stage, memory, where });
2126
- }
2127
- };
2128
-
2129
- const IncomingRelationPredicate = {
2130
- include: ({ expr, model, memory, stage, where }) => {
2131
- const sources = [...memory.elements];
2132
- if (FqnExpr.isWildcard(expr.incoming)) {
2133
- for (const source of sources) {
2134
- if (source.allOutgoing.isEmpty) {
2135
- continue;
2136
- }
2137
- const targets2 = [...resolveAscendingSiblings(source)];
2138
- const toInclude = applyPredicate(findConnectionsBetween$2(source, targets2, "directed"), where);
2139
- stage.addConnections(toInclude);
2140
- }
2141
- return stage;
2142
- }
2143
- invariant(FqnExpr.isDeploymentRef(expr.incoming), "Only deployment refs are supported in include");
2144
- const targets = resolveElements$1(model, expr.incoming);
2145
- for (const source of sources) {
2146
- const toInclude = applyPredicate(findConnectionsBetween$2(source, targets, "directed"), where);
2147
- stage.addConnections(toInclude);
2148
- }
2149
- return stage;
2150
- },
2151
- exclude: ({ expr, model, memory, stage, where }) => {
2152
- if (FqnExpr.isElementTagExpr(expr.incoming) || FqnExpr.isElementKindExpr(expr.incoming)) {
2153
- throw new Error("element kind and tag expressions are not supported in exclude");
2154
- }
2155
- if (FqnExpr.isModelRef(expr.incoming)) {
2156
- const excludedRelations = resolveAllImcomingRelations(model, expr.incoming);
2157
- return excludeModelRelations(excludedRelations, { stage, memory }, where);
2158
- }
2159
- if (FqnExpr.isWildcard(expr.incoming)) {
2160
- return stage;
2161
- }
2162
- const isIncoming = filterIncomingConnections(resolveElements$1(model, expr.incoming));
2163
- const toExclude = t$d(
2164
- memory.connections,
2165
- n$d(isIncoming),
2166
- applyPredicate(where)
2167
- );
2168
- stage.excludeConnections(toExclude);
2169
- return stage;
2170
- }
2171
- };
2172
- function filterIncomingConnections(targets) {
2173
- return t$g(
2174
- targets.map((target) => {
2175
- const satisfies = (el) => el === target || isAncestor(target, el);
2176
- return (connection) => {
2177
- return !satisfies(connection.source) && satisfies(connection.target);
2178
- };
2179
- })
2180
- );
2181
- }
2182
- function resolveAllImcomingRelations(model, moodelRef) {
2183
- const targets = resolveModelElements(model, moodelRef);
2184
- return new Set(targets.flatMap((e) => [...e.allIncoming]));
2185
- }
2186
-
2187
- const OutgoingRelationPredicate = {
2188
- include: ({ expr, model, memory, stage, where }) => {
2189
- const targets = [...memory.elements];
2190
- if (FqnExpr.isWildcard(expr.outgoing)) {
2191
- for (const target of targets) {
2192
- if (target.allIncoming.isEmpty) {
2193
- continue;
2194
- }
2195
- for (const source of resolveAscendingSiblings(target)) {
2196
- const toInclude = applyPredicate(findConnection$2(source, target, "directed"), where);
2197
- stage.addConnections(toInclude);
2198
- }
2199
- }
2200
- return stage;
2201
- }
2202
- invariant(FqnExpr.isDeploymentRef(expr.outgoing), "Only deployment refs are supported in include");
2203
- const sources = resolveElements$1(model, expr.outgoing);
2204
- for (const source of sources) {
2205
- const toInclude = applyPredicate(findConnectionsBetween$2(source, targets, "directed"), where);
2206
- stage.addConnections(toInclude);
2207
- }
2208
- return stage;
2209
- },
2210
- exclude: ({ expr, model, memory, stage, where }) => {
2211
- if (FqnExpr.isElementTagExpr(expr.outgoing) || FqnExpr.isElementKindExpr(expr.outgoing)) {
2212
- throw new Error("element kind and tag expressions are not supported in exclude");
2213
- }
2214
- if (FqnExpr.isModelRef(expr.outgoing)) {
2215
- const excludedRelations = resolveAllOutgoingRelations(model, expr.outgoing);
2216
- return excludeModelRelations(excludedRelations, { stage, memory }, where);
2217
- }
2218
- if (FqnExpr.isWildcard(expr.outgoing)) {
2219
- return stage;
2220
- }
2221
- const isOutgoing = filterOutgoingConnections(resolveElements$1(model, expr.outgoing));
2222
- const toExclude = t$d(
2223
- memory.connections,
2224
- n$d(isOutgoing),
2225
- applyPredicate(where)
2226
- );
2227
- stage.excludeConnections(toExclude);
2228
- return stage;
2229
- }
2230
- };
2231
- function filterOutgoingConnections(sources) {
2232
- return t$g(
2233
- sources.map((source) => {
2234
- const satisfies = (el) => el === source || isAncestor(source, el);
2235
- return (connection) => {
2236
- return satisfies(connection.source) && !satisfies(connection.target);
2237
- };
2238
- })
2239
- );
2240
- }
2241
- function resolveAllOutgoingRelations(model, moodelRef) {
2242
- const targets = resolveModelElements(model, moodelRef);
2243
- return new Set(targets.flatMap((e) => [...e.allOutgoing]));
2244
- }
2245
-
2246
- const resolveAscendingSiblings = (element) => {
2247
- const siblings = /* @__PURE__ */ new Set();
2248
- for (let sibling of element.descendingSiblings()) {
2249
- siblings.add(sibling);
2250
- }
2251
- return siblings;
2252
- };
2253
- const DirectRelationPredicate = {
2254
- include: ({ expr: { source, target, isBidirectional = false }, model, stage, where }) => {
2255
- if (FqnExpr.isElementTagExpr(source) || FqnExpr.isElementKindExpr(source)) {
2256
- throw new Error("element kind and tag expressions are not supported in include");
2257
- }
2258
- if (FqnExpr.isElementTagExpr(target) || FqnExpr.isElementKindExpr(target)) {
2259
- throw new Error("element kind and tag expressions are not supported in include");
2260
- }
2261
- invariant(!FqnExpr.isModelRef(source), "Invalid source model ref in direct relation");
2262
- invariant(!FqnExpr.isModelRef(target), "Invalid target model ref in direct relation");
2263
- const sourceIsWildcard = FqnExpr.isWildcard(source);
2264
- const targetIsWildcard = FqnExpr.isWildcard(target);
2265
- const dir = isBidirectional ? "both" : "directed";
2266
- let connections;
2267
- switch (true) {
2268
- // * -> *
2269
- case (sourceIsWildcard && targetIsWildcard): {
2270
- connections = t$d(
2271
- findConnectionsWithin$1(model.instances()),
2272
- applyPredicate(where),
2273
- t$e((c) => {
2274
- stage.addImplicit(c.boundary);
2275
- return c;
2276
- })
2277
- );
2278
- break;
2279
- }
2280
- // source -> *; source <-> *
2281
- case (!sourceIsWildcard && targetIsWildcard): {
2282
- const sources = resolveElements$1(model, source);
2283
- const isSource = filterOutgoingConnections(sources);
2284
- let postFilter = isSource;
2285
- if (isBidirectional) {
2286
- const isTarget = filterIncomingConnections(sources);
2287
- postFilter = (c) => isSource(c) !== isTarget(c);
2288
- }
2289
- connections = t$d(
2290
- sources,
2291
- t$m((source2) => {
2292
- const targets = resolveAscendingSiblings(source2);
2293
- return findConnectionsBetween$2(source2, targets, dir);
2294
- }),
2295
- n$d(postFilter),
2296
- applyPredicate(where)
2297
- );
2298
- break;
2299
- }
2300
- // * -> target; * <-> target
2301
- case (sourceIsWildcard && !targetIsWildcard): {
2302
- const targets = resolveElements$1(model, target);
2303
- const isTarget = filterIncomingConnections(targets);
2304
- let postFilter = isTarget;
2305
- if (isBidirectional) {
2306
- const isSource = filterOutgoingConnections(targets);
2307
- postFilter = (c) => isSource(c) !== isTarget(c);
2308
- }
2309
- connections = t$d(
2310
- targets,
2311
- t$m((target2) => {
2312
- const sources = resolveAscendingSiblings(target2);
2313
- return [...sources].flatMap((source2) => findConnection$2(source2, target2, dir));
2314
- }),
2315
- n$d(postFilter),
2316
- applyPredicate(where)
2317
- );
2318
- break;
2319
- }
2320
- default: {
2321
- invariant(!sourceIsWildcard, "Inferrence failed - source should be a deployment ref");
2322
- invariant(!targetIsWildcard, "Inferrence failed - target should be a deployment ref");
2323
- const sources = resolveElements$1(model, source);
2324
- const targets = resolveElements$1(model, target);
2325
- const isSource = filterOutgoingConnections(sources);
2326
- const isTarget = filterIncomingConnections(targets);
2327
- connections = t$d(
2328
- sources,
2329
- t$m((s) => findConnectionsBetween$2(s, targets, dir)),
2330
- n$d((c) => isSource(c) && isTarget(c)),
2331
- applyPredicate(where)
2332
- );
2333
- }
2334
- }
2335
- stage.addConnections(connections);
2336
- if (FqnExpr.isDeploymentRef(source) && e$a(source.selector)) {
2337
- stage.addImplicit(model.element(source.ref.deployment));
2338
- }
2339
- if (FqnExpr.isDeploymentRef(target) && e$a(target.selector)) {
2340
- stage.addImplicit(model.element(target.ref.deployment));
2341
- }
2342
- return stage;
2343
- },
2344
- exclude: ({ expr, model, memory, stage, where }) => {
2345
- const isTarget = deploymentExpressionToPredicate(expr.target);
2346
- const isSource = deploymentExpressionToPredicate(expr.source);
2347
- let modelRelationsToExclude;
2348
- switch (true) {
2349
- // * -> *
2350
- case (FqnExpr.isWildcard(expr.source) && FqnExpr.isWildcard(expr.target)):
2351
- stage.excludeConnections(applyPredicate(memory.connections, where));
2352
- return stage;
2353
- // model -> model
2354
- case (FqnExpr.isModelRef(expr.source) && FqnExpr.isModelRef(expr.target)):
2355
- modelRelationsToExclude = resolveRelationsBetweenModelElements({
2356
- source: expr.source,
2357
- target: expr.target,
2358
- expr,
2359
- model
2360
- });
2361
- return excludeModelRelations(modelRelationsToExclude, { stage, memory }, where);
2362
- // model -> *
2363
- case (FqnExpr.isModelRef(expr.source) && FqnExpr.isWildcard(expr.target)):
2364
- modelRelationsToExclude = resolveAllOutgoingRelations(model, expr.source);
2365
- return excludeModelRelations(modelRelationsToExclude, { stage, memory }, where);
2366
- // model -> deployment
2367
- case FqnExpr.isModelRef(expr.source):
2368
- modelRelationsToExclude = resolveAllOutgoingRelations(model, expr.source);
2369
- return excludeModelRelations(
2370
- modelRelationsToExclude,
2371
- { stage, memory },
2372
- where,
2373
- (c) => isTarget(c.target)
2374
- );
2375
- // deployment -> model
2376
- case FqnExpr.isModelRef(expr.target):
2377
- modelRelationsToExclude = resolveAllImcomingRelations(model, expr.target);
2378
- return excludeModelRelations(
2379
- modelRelationsToExclude,
2380
- { stage, memory },
2381
- where,
2382
- (c) => isSource(c.source)
2383
- );
2384
- // deployment -> deployment
2385
- default:
2386
- const satisfies = (connection) => {
2387
- return isSource(connection.source) && isTarget(connection.target) || expr.isBidirectional === true && isSource(connection.target) && isTarget(connection.source);
2388
- };
2389
- const deploymentRelationsToExclude = t$d(
2390
- memory.connections,
2391
- n$d(satisfies),
2392
- applyPredicate(where)
2393
- );
2394
- if (deploymentRelationsToExclude.length === 0) {
2395
- return stage;
2396
- }
2397
- stage.excludeConnections(deploymentRelationsToExclude);
2398
- return stage;
2399
- }
2400
- }
2401
- };
2402
- function resolveRelationsBetweenModelElements({
2403
- source,
2404
- target,
2405
- expr,
2406
- model
2407
- }) {
2408
- const sources = resolveModelElements(model, source);
2409
- const targets = resolveModelElements(model, target);
2410
- const dir = expr.isBidirectional ? "both" : "directed";
2411
- const modelConnections = [];
2412
- for (const source2 of sources) {
2413
- modelConnections.push(...findConnectionsBetween$3(source2, targets, dir));
2414
- }
2415
- return new Set(modelConnections.flatMap((c) => [...c.relations]));
2416
- }
2417
-
2418
- const InOutRelationPredicate$1 = {
2419
- include: ({ expr, model, memory, stage, where }) => {
2420
- const sources = [...memory.elements];
2421
- if (FqnExpr.isWildcard(expr.inout)) {
2422
- for (const source of sources) {
2423
- const targets2 = [...resolveAscendingSiblings(source)];
2424
- const toInclude = matchConnections(findConnectionsBetween$2(source, targets2, "both"), where);
2425
- stage.addConnections(toInclude);
2426
- }
2427
- return stage;
2428
- }
2429
- invariant(FqnExpr.isDeploymentRef(expr.inout), "Only deployment refs are supported in include");
2430
- const targets = resolveElements$1(model, expr.inout);
2431
- for (const source of sources) {
2432
- const toInclude = matchConnections(findConnectionsBetween$2(source, targets, "both"), where);
2433
- stage.addConnections(toInclude);
2434
- }
2435
- return stage;
2436
- },
2437
- exclude: ({ expr, model, memory, stage, where }) => {
2438
- if (FqnExpr.isElementTagExpr(expr.inout) || FqnExpr.isElementKindExpr(expr.inout)) {
2439
- throw new Error("element kind and tag expressions are not supported in exclude");
2440
- }
2441
- if (FqnExpr.isModelRef(expr.inout)) {
2442
- const elements2 = resolveModelElements(model, expr.inout);
2443
- if (elements2.length === 0) {
2444
- return stage;
2445
- }
2446
- const excludedRelations = union(
2447
- /* @__PURE__ */ new Set(),
2448
- ...elements2.flatMap((e) => [e.allIncoming, e.allOutgoing])
2449
- );
2450
- return excludeModelRelations(excludedRelations, { stage, memory }, where);
2451
- }
2452
- if (FqnExpr.isWildcard(expr.inout)) {
2453
- return stage;
2454
- }
2455
- const elements = resolveElements$1(model, expr.inout);
2456
- const isIncoming = filterIncomingConnections(elements);
2457
- const isOutgoing = filterOutgoingConnections(elements);
2458
- const toExclude = t$d(
2459
- memory.connections,
2460
- n$d((c) => isIncoming(c) !== isOutgoing(c)),
2461
- applyPredicate(where)
2462
- );
2463
- stage.excludeConnections(toExclude);
2464
- return stage;
2465
- }
2466
- };
2467
-
2468
- const WhereRelationPredicate = {
2469
- include: ({ expr, model, memory, stage }) => {
2470
- const where = whereOperatorAsPredicate(expr.where.condition);
2471
- return predicateToPatch("include", { expr: expr.where.expr, model, stage, memory, where });
2472
- },
2473
- exclude: ({ expr, model, memory, stage }) => {
2474
- const where = whereOperatorAsPredicate(expr.where.condition);
2475
- return predicateToPatch("exclude", { expr: expr.where.expr, model, stage, memory, where });
2476
- }
2477
- };
2478
-
2479
- const WildcardPredicate$1 = {
2480
- include: ({ model, stage, where }) => {
2481
- const children = [];
2482
- const rootElements = t$d(
2483
- [...model.roots()],
2484
- applyElementPredicate(where),
2485
- t$e((root) => {
2486
- if (!root.onlyOneInstance()) {
2487
- children.push(...root.children());
2488
- }
2489
- return root;
2490
- })
2491
- );
2492
- stage.addExplicit(rootElements);
2493
- if (children.length > 1) {
2494
- stage.addConnections(findConnectionsWithin$1([
2495
- ...rootElements,
2496
- ...children
2497
- ]));
2498
- }
2499
- return stage;
2500
- },
2501
- exclude: ({ stage, memory, where }) => {
2502
- const elementsToExclude = t$d(
2503
- [...memory.elements],
2504
- applyElementPredicate(where)
2505
- );
2506
- stage.exclude(elementsToExclude);
2507
- return stage;
2508
- }
2509
- };
2510
-
2511
- function predicateToPatch(op, { expr, where, ...ctx }) {
2512
- switch (true) {
2513
- case FqnExpr.isElementTagExpr(expr):
2514
- case FqnExpr.isElementKindExpr(expr):
2515
- throw new Error("element kind and tag expressions are not supported in deployment view rules");
2516
- case RelationExpr.isCustom(expr):
2517
- case FqnExpr.isCustom(expr):
2518
- case FqnExpr.isModelRef(expr):
2519
- return void 0;
2520
- case FqnExpr.isWhere(expr):
2521
- return WhereDeploymentRefPredicate[op]({ ...ctx, expr, where });
2522
- case RelationExpr.isWhere(expr):
2523
- return WhereRelationPredicate[op]({ ...ctx, expr, where });
2524
- case FqnExpr.isDeploymentRef(expr):
2525
- return DeploymentRefPredicate[op]({ ...ctx, expr, where });
2526
- case FqnExpr.isWildcard(expr):
2527
- return WildcardPredicate$1[op]({ ...ctx, expr, where });
2528
- case RelationExpr.isDirect(expr):
2529
- return DirectRelationPredicate[op]({ ...ctx, expr, where });
2530
- case RelationExpr.isInOut(expr):
2531
- return InOutRelationPredicate$1[op]({ ...ctx, expr, where });
2532
- case RelationExpr.isOutgoing(expr):
2533
- return OutgoingRelationPredicate[op]({ ...ctx, expr, where });
2534
- case RelationExpr.isIncoming(expr):
2535
- return IncomingRelationPredicate[op]({ ...ctx, expr, where });
2536
- default:
2537
- nonexhaustive(expr);
2538
- }
2539
- }
2540
- function excludeModelRelations(relationsToExclude, { stage, memory }, where, filterConnections = () => true) {
2541
- if (relationsToExclude.size === 0) {
2542
- return stage;
2543
- }
2544
- const toExclude = t$d(
2545
- memory.connections,
2546
- n$d((c) => filterConnections(c)),
2547
- // Find connections that have at least one relation in common with the excluded relations
2548
- n$d((c) => hasIntersection(c.relations.model, relationsToExclude)),
2549
- t$e(
2550
- (c) => c.update({
2551
- deployment: null,
2552
- model: intersection(c.relations.model, relationsToExclude)
2553
- })
2554
- ),
2555
- applyPredicate(where),
2556
- n$d((c) => c.nonEmpty())
2557
- );
2558
- if (toExclude.length === 0) {
2559
- return stage;
2560
- }
2561
- return stage.excludeConnections(toExclude);
2562
- }
2563
- function matchConnection(c, where) {
2564
- return applyPredicate(c, where).nonEmpty();
2565
- }
2566
- function applyPredicate(...args) {
2567
- if (args.length === 1) {
2568
- return (x) => applyPredicate(x, args[0]);
2569
- }
2570
- const [c, where] = args;
2571
- if (where === null) {
2572
- return c;
2573
- }
2574
- if (e$b(c)) {
2575
- return c.map((x) => applyPredicate(x, where)).filter((x) => x.nonEmpty());
2576
- }
2577
- return c.update({
2578
- model: new Set([...c.relations.model.values()].filter((r) => where(toFilterableRelation(c)(r)))),
2579
- deployment: new Set([...c.relations.deployment.values()].filter((r) => where(toFilterableRelation(c)(r))))
2580
- });
2581
- }
2582
- function applyElementPredicate(...args) {
2583
- if (args.length === 1) {
2584
- return (x) => applyElementPredicate(x, args[0]);
2585
- }
2586
- const [c, where] = args;
2587
- if (e$b(c)) {
2588
- return c.filter((x) => applyElementPredicate(x, where));
2589
- }
2590
- return where?.(toFilterable(c, c)) ?? true;
2591
- }
2592
- function matchConnections(connections, where) {
2593
- if (!where) {
2594
- return connections;
2595
- }
2596
- return t$d(
2597
- connections,
2598
- n$d((c) => matchConnection(c, where))
2599
- );
2600
- }
2601
- function toFilterable(relationEndpoint, connectionEndpoint) {
2602
- if (isElementModel(relationEndpoint)) {
2603
- const deployedInstance = isDeploymentElementModel(connectionEndpoint) && isDeployedInstanceModel(connectionEndpoint) ? connectionEndpoint : null;
2604
- return {
2605
- kind: relationEndpoint.kind,
2606
- tags: [...relationEndpoint.tags, ...deployedInstance?.tags ?? []]
2607
- };
2608
- }
2609
- if (isNestedElementOfDeployedInstanceModel(relationEndpoint)) {
2610
- return t$i(relationEndpoint.element, ["tags", "kind"]);
2611
- }
2612
- if (isDeployedInstanceModel(relationEndpoint)) {
2613
- return {
2614
- kind: relationEndpoint.element.kind,
2615
- tags: [...relationEndpoint.tags, ...relationEndpoint.element.tags]
2616
- };
2617
- }
2618
- if (isDeploymentNodeModel(relationEndpoint)) {
2619
- return t$i(relationEndpoint, ["tags", "kind"]);
2620
- }
2621
- nonexhaustive(relationEndpoint);
2622
- }
2623
- function toFilterableRelation(c) {
2624
- return (relation) => ({
2625
- tags: relation.tags,
2626
- kind: relation.kind,
2627
- source: toFilterable(relation.source, c.source),
2628
- target: toFilterable(relation.target, c.target)
2629
- });
2630
- }
2631
-
2632
- const DeploymentRefPredicate = {
2633
- include: (ctx) => {
2634
- const { expr, where } = ctx;
2635
- const el = ctx.model.element(expr.ref.deployment);
2636
- if (isDeployedInstanceModel(el)) {
2637
- if (applyElementPredicate(el, where)) {
2638
- ctx.stage.addExplicit(el);
2639
- ctx.stage.connectWithExisting(el);
2640
- }
2641
- return ctx.stage;
2642
- }
2643
- switch (true) {
2644
- case expr.selector === "expanded":
2645
- includeDeployedNodeWithExpanded(el, ctx);
2646
- break;
2647
- case expr.selector === "children":
2648
- includeDeployedNodeChildren(el, ctx);
2649
- break;
2650
- case expr.selector === "descendants":
2651
- includeDeployedNodeDescendants(el, ctx);
2652
- break;
2653
- default: {
2654
- if (applyElementPredicate(el, where)) {
2655
- ctx.stage.addExplicit(el);
2656
- ctx.stage.connectWithExisting(el);
2657
- }
2658
- }
2659
- }
2660
- return ctx.stage;
2661
- },
2662
- exclude: ({ expr, stage, memory, where }) => {
2663
- const exprPredicate = deploymentExpressionToPredicate(expr);
2664
- const toExclude = t$d(
2665
- [...memory.elements],
2666
- n$d(exprPredicate),
2667
- applyElementPredicate(where)
2668
- );
2669
- stage.exclude(toExclude);
2670
- return stage;
2671
- }
2672
- };
2673
- function includeDeployedNodeChildren(node, { stage, where }) {
2674
- const children = applyElementPredicate([...node.children()], where);
2675
- if (children.length === 0) {
2676
- return;
2677
- }
2678
- stage.addImplicit(node);
2679
- stage.addConnections(findConnectionsWithin$1(children));
2680
- stage.connectWithExisting(children);
2681
- stage.addExplicit(children);
2682
- }
2683
- function includeDeployedNodeWithExpanded(node, { memory, stage, where }) {
2684
- stage.addImplicit(node);
2685
- stage.connectWithExisting(node);
2686
- const children = applyElementPredicate([...node.children()], where);
2687
- let hasConnectionsWithVisible = false;
2688
- for (const child of children) {
2689
- if (findConnectionsBetween$2(child, memory.elements).length > 0) {
2690
- hasConnectionsWithVisible = true;
2691
- break;
2692
- }
2693
- }
2694
- if (hasConnectionsWithVisible) {
2695
- stage.connectWithExisting(children, "in");
2696
- stage.addConnections(findConnectionsWithin$1(children));
2697
- stage.connectWithExisting(children, "out");
2698
- }
2699
- stage.addImplicit(children);
2700
- if (stage.connections.length > 0) {
2701
- stage.addExplicit(node);
2702
- }
2703
- }
2704
- function includeDeployedNodeDescendants(node, { stage, where }) {
2705
- const dfs = (node2) => {
2706
- const children = [];
2707
- for (const child of node2.children()) {
2708
- if (child.isDeploymentNode()) {
2709
- children.push(...dfs(child));
2710
- }
2711
- if (applyElementPredicate(child, where)) {
2712
- children.push(child);
2713
- }
2714
- }
2715
- stage.connectWithExisting(children, "in");
2716
- stage.addConnections(findConnectionsWithin$1(children));
2717
- stage.addImplicit(children);
2718
- return children;
2719
- };
2720
- const descendants = dfs(node);
2721
- if (descendants.length === 0) {
2722
- return;
2723
- }
2724
- stage.connectWithExisting(descendants, "out");
2725
- const allConnected = findConnectedElements(stage);
2726
- t$d(
2727
- descendants,
2728
- n$d((desc) => allConnected.has(desc)),
2729
- t$7((desc) => stage.addExplicit(desc))
2730
- );
2731
- }
2732
- function findConnectedElements(stage) {
2733
- return t$d(
2734
- stage.mergedConnections(),
2735
- cleanCrossBoundary,
2736
- cleanRedundantRelationships,
2737
- t$2((acc, c) => {
2738
- acc.add(c.source);
2739
- acc.add(c.target);
2740
- return acc;
2741
- }, /* @__PURE__ */ new Set())
2742
- );
2743
- }
2744
-
2745
- let StageFinal$1 = class StageFinal {
2746
- constructor(memory) {
2747
- this.memory = memory;
2748
- }
2749
- static for(memory) {
2750
- return new StageFinal(memory);
2751
- }
2752
- step1CleanConnections(memory) {
2753
- if (memory.connections.length < 2) {
2754
- return memory;
2755
- }
2756
- const connections = t$d(
2757
- memory.connections,
2758
- // Keep connections
2759
- // - between leafs
2760
- // - has direct deployment relation
2761
- // filter(c => {
2762
- // return (leafs.has(c.source) && leafs.has(c.target)) || c.hasDirectDeploymentRelation()
2763
- // }),
2764
- cleanCrossBoundary,
2765
- cleanRedundantRelationships
2766
- );
2767
- const connectionsToExclude = differenceConnections(
2768
- memory.connections,
2769
- connections
2770
- );
2771
- if (connectionsToExclude.length === 0) {
2772
- return memory;
2773
- }
2774
- const stage = memory.stageExclude({});
2775
- stage.excludeConnections(connectionsToExclude, true);
2776
- return stage.commit();
2777
- }
2778
- step2ProcessImplicits(memory) {
2779
- const implicits = union(this.memory.elements, memory.elements);
2780
- const final = union(memory.final, this.memory.explicits);
2781
- const groupedByRelation = new DefaultMap(() => /* @__PURE__ */ new Set());
2782
- for (const conn of memory.connections) {
2783
- if (conn.boundary) {
2784
- for (const relation of conn.relations.model) {
2785
- groupedByRelation.get(relation).add(conn.boundary);
2786
- }
2787
- }
2788
- }
2789
- for (const [_, boundaries] of groupedByRelation) {
2790
- if (boundaries.size < 2) {
2791
- continue;
2792
- }
2793
- for (const boundary of boundaries) {
2794
- if (implicits.delete(boundary)) {
2795
- final.add(boundary);
2796
- }
2797
- }
2798
- }
2799
- const snapshot = new Set(final);
2800
- const isFinalOrHasIncludedDescendant = (el) => {
2801
- for (const final2 of snapshot) {
2802
- if (el === final2 || isAncestor(el, final2)) {
2803
- return true;
2804
- }
2805
- }
2806
- return false;
2807
- };
2808
- t$d(
2809
- difference(implicits, snapshot),
2810
- ifilter((e) => e.isDeploymentNode()),
2811
- toArray(),
2812
- sortByFqnHierarchically,
2813
- t$7((el) => {
2814
- const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length;
2815
- if (childrensToWrap >= 2) {
2816
- final.add(el);
2817
- return;
2818
- }
2819
- if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) {
2820
- final.add(el);
2821
- }
2822
- })
2823
- );
2824
- return memory.update({ final });
2825
- }
2826
- step3ProcessBoundaries(memory) {
2827
- const boundaries = /* @__PURE__ */ new Set();
2828
- for (const conn of memory.connections) {
2829
- if (conn.boundary) {
2830
- boundaries.add(conn.boundary);
2831
- }
2832
- }
2833
- const tree = treeFromMemoryState(memory, "final");
2834
- const stage = memory.stageExclude({});
2835
- const isRemovable = (el) => !(boundaries.has(el) || memory.explicits.has(el) || tree.hasInOut(el) || tree.root.has(el));
2836
- const singleRoot = t$5([...tree.root]);
2837
- if (singleRoot && !memory.explicits.has(singleRoot)) {
2838
- stage.exclude(singleRoot);
2839
- }
2840
- for (const el of memory.final) {
2841
- const singleChild = t$5(tree.children(el));
2842
- if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) {
2843
- stage.exclude(el);
2844
- }
2845
- }
2846
- if (stage.isDirty()) {
2847
- return stage.commit();
2848
- }
2849
- return memory;
2850
- }
2851
- // TODO: Lot of corner cases to cover, skip for now
2852
- // public step3FlatNodes(memory: Memory): Memory {
2853
- // // final implicits
2854
- // const explicits = new Set<Elem>([
2855
- // ...memory.explicits,
2856
- // ...memory.connections.flatMap(c => [c.source, c.target]),
2857
- // ])
2858
- // const sorted = sortParentsFirst(toArray(memory.final))
2859
- // const toplevel = new Set<Elem>(sorted)
2860
- // const children = sorted.reduce((acc, el, index, all) => {
2861
- // acc.set(
2862
- // el,
2863
- // new Set(
2864
- // all
2865
- // .slice(index + 1)
2866
- // .filter(e => isAncestor(el, e))
2867
- // .reduce((acc, el) => {
2868
- // if (!acc.some(e => isAncestor(e, el))) {
2869
- // toplevel.delete(el)
2870
- // acc.push(el)
2871
- // }
2872
- // return acc
2873
- // }, [] as Elem[]),
2874
- // ),
2875
- // )
2876
- // return acc
2877
- // }, new DefaultMap<Elem, Set<Elem>>(() => new Set()))
2878
- // const state = memory.mutableState()
2879
- // function flattenNode(node: Elem) {
2880
- // const _children = [...children.get(node)]
2881
- // if (_children.length > 1) {
2882
- // for (const child of _children) {
2883
- // flattenNode(child)
2884
- // }
2885
- // return !explicits.has(node)
2886
- // }
2887
- // if (hasAtLeast(_children, 1)) {
2888
- // if (flattenNode(_children[0])) {
2889
- // state.final.delete(_children[0])
2890
- // }
2891
- // }
2892
- // return !explicits.has(node)
2893
- // }
2894
- // const root = [...toplevel]
2895
- // for (const node of root) {
2896
- // flattenNode(node)
2897
- // if (!explicits.has(node) && children.get(node).size === 1) {
2898
- // state.final.delete(node)
2899
- // }
2900
- // }
2901
- // if (root.length === 1 && !explicits.has(root[0]!)) {
2902
- // state.final.delete(root[0]!)
2903
- // }
2904
- // return memory.update(state)
2905
- // }
2906
- commit() {
2907
- const step1 = this.step1CleanConnections(this.memory);
2908
- const step2 = this.step2ProcessImplicits(step1);
2909
- return this.step3ProcessBoundaries(step2);
2910
- }
2911
- };
2912
-
2913
- function processPredicates$1(model, rules) {
2914
- let memory = Memory$1.empty();
2915
- for (const rule of rules) {
2916
- if (isViewRulePredicate(rule)) {
2917
- const op = "include" in rule ? "include" : "exclude";
2918
- const exprs = rule.include ?? rule.exclude;
2919
- for (const expr of exprs) {
2920
- let stage = op === "include" ? memory.stageInclude(expr) : memory.stageExclude(expr);
2921
- const ctx = { expr, model, stage, memory, where: null };
2922
- stage = predicateToPatch(op, ctx) ?? stage;
2923
- memory = stage.commit();
2924
- }
2925
- }
2926
- }
2927
- return StageFinal$1.for(memory).commit();
2928
- }
2929
- function computeDeploymentView(likec4model, {
2930
- docUri: _docUri,
2931
- // exclude docUri
2932
- rules,
2933
- // exclude rules
2934
- ...view
2935
- }) {
2936
- const memory = processPredicates$1(likec4model.deployment, rules);
2937
- const nodesMap = buildNodes$1(likec4model, memory);
2938
- const computedEdges = toComputedEdges$1(memory.connections);
2939
- linkNodesWithEdges(nodesMap, computedEdges);
2940
- const sorted = topologicalSort({
2941
- nodes: nodesMap,
2942
- edges: computedEdges
2943
- });
2944
- const nodes = applyDeploymentViewRuleStyles(
2945
- rules,
2946
- sorted.nodes
2947
- );
2948
- const autoLayoutRule = t$8(rules, isViewRuleAutoLayout);
2949
- const elementNotations = buildElementNotations(nodes);
2950
- return calcViewLayoutHash({
2951
- ...view,
2952
- [_stage]: "computed",
2953
- [_type]: "deployment",
2954
- autoLayout: {
2955
- direction: autoLayoutRule?.direction ?? "TB",
2956
- ...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
2957
- ...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
2958
- },
2959
- edges: sorted.edges,
2960
- nodes: t$e(nodes, (n) => {
2961
- if (n.icon === "none") {
2962
- delete n.icon;
2963
- }
2964
- return n;
2965
- }),
2966
- ...elementNotations.length > 0 && {
2967
- notation: {
2968
- nodes: elementNotations
2969
- }
2970
- }
2971
- });
2972
- }
2973
-
2974
- function flattenGroupRules(guard) {
2975
- return (rule) => {
2976
- if (isViewRuleGroup(rule)) {
2977
- return rule.groupRules.flatMap(flattenGroupRules(guard));
2978
- }
2979
- if (isViewRulePredicate(rule)) {
2980
- return "include" in rule ? rule.include.filter(guard) : [];
2981
- }
2982
- return [];
2983
- };
2984
- }
2985
- function applyCustomElementProperties(_rules, _nodes) {
2986
- const rules = _rules.flatMap(flattenGroupRules(ModelFqnExpr.isCustom));
2987
- if (rules.length === 0) {
2988
- return _nodes;
2989
- }
2990
- const nodes = [..._nodes];
2991
- for (const {
2992
- custom: { expr, ...props }
2993
- } of rules) {
2994
- const {
2995
- border,
2996
- opacity,
2997
- multiple,
2998
- padding,
2999
- size,
3000
- textSize,
3001
- description,
3002
- ...rest
3003
- } = t$o(props, e$8);
3004
- const style = exact({
3005
- border,
3006
- opacity,
3007
- multiple,
3008
- padding,
3009
- size,
3010
- textSize
3011
- });
3012
- const styleNotEmpty = !e$5(style);
3013
- const propsNotEmpty = !e$5(rest);
3014
- const satisfies = elementExprToPredicate(expr);
3015
- nodes.forEach((node, i) => {
3016
- if (isGroupElementKind(node) || !satisfies(node)) {
3017
- return;
3018
- }
3019
- if (propsNotEmpty) {
3020
- node = {
3021
- ...node,
3022
- isCustomized: true,
3023
- ...rest
3024
- };
3025
- }
3026
- if (description !== void 0) {
3027
- node = {
3028
- ...node,
3029
- isCustomized: true,
3030
- description
3031
- };
3032
- }
3033
- if (styleNotEmpty) {
3034
- node = {
3035
- ...node,
3036
- isCustomized: true,
3037
- style: {
3038
- ...node.style,
3039
- ...style
3040
- }
3041
- };
3042
- }
3043
- nodes[i] = node;
3044
- });
3045
- }
3046
- return nodes;
3047
- }
3048
-
3049
- function resolveGlobalRulesInElementView(rules, globals) {
3050
- return rules.reduce((acc, rule) => {
3051
- if (isViewRuleGlobalPredicateRef(rule)) {
3052
- const globalPredicates = globals.predicates[rule.predicateId];
3053
- if (e$8(globalPredicates)) {
3054
- return acc;
3055
- }
3056
- return acc.concat(globalPredicates);
3057
- }
3058
- if (isViewRuleGlobalStyle(rule)) {
3059
- const globalStyles = globals.styles[rule.styleId];
3060
- if (e$8(globalStyles)) {
3061
- return acc;
3062
- }
3063
- return acc.concat(globalStyles);
3064
- }
3065
- acc.push(rule);
3066
- return acc;
3067
- }, []);
3068
- }
3069
- function resolveGlobalRulesInDynamicView(rules, globals) {
3070
- return rules.reduce((acc, rule) => {
3071
- if (isViewRuleGlobalPredicateRef(rule)) {
3072
- const globalPredicates = globals.dynamicPredicates[rule.predicateId];
3073
- if (e$8(globalPredicates)) {
3074
- return acc;
3075
- }
3076
- return acc.concat(globalPredicates);
3077
- }
3078
- if (isViewRuleGlobalStyle(rule)) {
3079
- const globalStyles = globals.styles[rule.styleId];
3080
- if (e$8(globalStyles)) {
3081
- return acc;
3082
- }
3083
- return acc.concat(globalStyles);
3084
- }
3085
- acc.push(rule);
3086
- return acc;
3087
- }, []);
3088
- }
3089
-
3090
- function elementsFromIncludeProperties(model, resolvedRules) {
3091
- const explicits = /* @__PURE__ */ new Set();
3092
- for (const rule of resolvedRules) {
3093
- if (isViewRulePredicate(rule)) {
3094
- for (const expr of rule.include) {
3095
- const satisfies = elementExprToPredicate(expr);
3096
- for (const e of model.elements()) {
3097
- if (satisfies(e)) {
3098
- explicits.add(e);
3099
- }
3100
- }
3101
- }
3102
- }
3103
- }
3104
- return explicits;
3105
- }
3106
- const flattenSteps = (s) => {
3107
- if (isDynamicStepsParallel(s)) {
3108
- const heads = [];
3109
- const tails = [];
3110
- for (const step of s.__parallel) {
3111
- if (isDynamicStepsSeries(step)) {
3112
- const [head, ...tail] = step.__series;
3113
- heads.push(head);
3114
- tails.push(...tail);
3115
- } else {
3116
- heads.push(step);
3117
- }
3118
- }
3119
- return [...heads, ...tails];
3120
- }
3121
- if (isDynamicStepsSeries(s)) {
3122
- return [...s.__series];
3123
- }
3124
- return s;
3125
- };
3126
- function elementsFromSteps(model, steps) {
3127
- const actors = [];
3128
- const addActor = (...[source, target]) => {
3129
- if (!actors.includes(source)) {
3130
- const indexOfTarget = actors.indexOf(target);
3131
- if (indexOfTarget > 0) {
3132
- actors.splice(indexOfTarget, 0, source);
3133
- return;
3134
- } else {
3135
- actors.push(source);
3136
- }
3137
- }
3138
- if (!actors.includes(target)) {
3139
- actors.push(target);
3140
- }
3141
- };
3142
- for (const step of t$m(steps, flattenSteps)) {
3143
- const source = model.element(step.source);
3144
- const target = model.element(step.target);
3145
- let sourceColumn = actors.indexOf(source);
3146
- let targetColumn = actors.indexOf(target);
3147
- const alreadyAdded = sourceColumn >= 0 && targetColumn >= 0;
3148
- if (alreadyAdded) {
3149
- continue;
3150
- }
3151
- if (step.isBackward) {
3152
- addActor(target, source);
3153
- } else {
3154
- addActor(source, target);
3155
- }
3156
- }
3157
- return new Set(actors);
3158
- }
3159
- function findRelations(source, target, currentViewId) {
3160
- const relationships = findConnection$3(source, target, "directed").flatMap((r) => [...r.relations]).sort(compareRelations);
3161
- if (!isNonEmptyArray(relationships)) {
3162
- return {};
3163
- }
3164
- if (relationships.length === 1) {
3165
- const relation2 = relationships[0];
3166
- return exact({
3167
- title: relation2.title ?? void 0,
3168
- tags: relation2.tags,
3169
- relations: [relation2.id],
3170
- navigateTo: relation2.$relationship.navigateTo,
3171
- color: relation2.$relationship.color,
3172
- line: relation2.$relationship.line
3173
- });
3174
- }
3175
- const alltags = t$d(
3176
- relationships,
3177
- t$m((r) => r.tags),
3178
- n$e()
3179
- );
3180
- const tags = t$b(alltags, 1) ? alltags : void 0;
3181
- const relations = t$e(relationships, (r) => r.id);
3182
- const relation = n$9(relationships);
3183
- let navigateTo = relation.$relationship.navigateTo;
3184
- if (navigateTo === currentViewId) {
3185
- navigateTo = void 0;
3186
- }
3187
- if (!navigateTo) {
3188
- navigateTo = t$d(
3189
- relationships,
3190
- t$m(
3191
- (r) => r.$relationship.navigateTo && r.$relationship.navigateTo !== currentViewId ? r.$relationship.navigateTo : []
3192
- ),
3193
- n$e(),
3194
- t$5()
3195
- );
3196
- }
3197
- const commonProperties = t$d(
3198
- relationships,
3199
- t$2((acc, { title, $relationship: r }) => {
3200
- e$4(title) && acc.title.add(title);
3201
- e$4(r.color) && acc.color.add(r.color);
3202
- e$4(r.line) && acc.line.add(r.line);
3203
- e$4(r.kind) && acc.kind.add(r.kind);
3204
- return acc;
3205
- }, {
3206
- kind: /* @__PURE__ */ new Set(),
3207
- color: /* @__PURE__ */ new Set(),
3208
- line: /* @__PURE__ */ new Set(),
3209
- title: /* @__PURE__ */ new Set()
3210
- })
3211
- );
3212
- return exact({
3213
- tags: tags ?? void 0,
3214
- relations,
3215
- navigateTo,
3216
- kind: t$5([...commonProperties.kind]),
3217
- title: t$5([...commonProperties.title]),
3218
- color: t$5([...commonProperties.color]),
3219
- line: t$5([...commonProperties.line])
3220
- });
3221
- }
3222
-
3223
- class DynamicViewCompute {
3224
- constructor(model, view) {
3225
- this.model = model;
3226
- this.view = view;
3227
- }
3228
- // Intermediate state
3229
- steps = [];
3230
- compute() {
3231
- const {
3232
- docUri: _docUri,
3233
- // exclude docUri
3234
- rules: _rules,
3235
- // exclude rules
3236
- steps: viewSteps,
3237
- ...view
3238
- } = this.view;
3239
- const rules = resolveGlobalRulesInDynamicView(_rules, this.model.globals);
3240
- const explicits = elementsFromIncludeProperties(this.model, rules);
3241
- const fromSteps = elementsFromSteps(this.model, viewSteps);
3242
- const actors = t$d(
3243
- union(
3244
- // First all actors, that are explicitly included
3245
- intersection(explicits, fromSteps),
3246
- // Then all actors from steps
3247
- fromSteps,
3248
- // Then all explicits (not from steps)
3249
- explicits
3250
- ),
3251
- toArray(),
3252
- sortParentsFirst
3253
- );
3254
- const compounds = actors.reduce((acc, actor, index, all) => {
3255
- for (let i = index + 1; i < all.length; i++) {
3256
- const other = all[i];
3257
- if (isAncestor(actor, other)) {
3258
- acc.push(actor);
3259
- break;
3260
- }
3261
- }
3262
- return acc;
3263
- }, []);
3264
- const processStep = (step, stepNum2, prefix) => {
3265
- if (isDynamicStepsSeries(step)) {
3266
- for (const s of step.__series) {
3267
- stepNum2 = processStep(s, stepNum2, prefix);
3268
- }
3269
- return stepNum2;
3270
- }
3271
- const id = prefix ? stepEdgeId(prefix, stepNum2) : stepEdgeId(stepNum2);
3272
- const {
3273
- source: stepSource,
3274
- target: stepTarget,
3275
- title: stepTitle,
3276
- isBackward: _isBackward,
3277
- // omit
3278
- navigateTo: stepNavigateTo,
3279
- notation: _notation,
3280
- // omit
3281
- ...rest
3282
- } = step;
3283
- const source = this.model.element(stepSource);
3284
- const sourceColumn = actors.indexOf(source);
3285
- invariant(sourceColumn >= 0, `Source ${stepSource} not found`);
3286
- const target = this.model.element(stepTarget);
3287
- const targetColumn = actors.indexOf(target);
3288
- invariant(targetColumn >= 0, `Target ${stepTarget} not found`);
3289
- if (compounds.includes(source) || compounds.includes(target)) {
3290
- console.error(`Step ${source.id} -> ${target.id} because it involves a compound`);
3291
- }
3292
- const {
3293
- title,
3294
- relations,
3295
- navigateTo: derivedNavigateTo,
3296
- ...derived
3297
- } = findRelations(source, target, this.view.id);
3298
- const navigateTo = e$4(stepNavigateTo) && stepNavigateTo !== this.view.id ? stepNavigateTo : derivedNavigateTo;
3299
- this.steps.push(exact({
3300
- ...derived,
3301
- ...rest,
3302
- id,
3303
- source,
3304
- target,
3305
- navigateTo,
3306
- title: stepTitle ?? title,
3307
- relations: relations ?? [],
3308
- isBackward: sourceColumn > targetColumn
3309
- }));
3310
- return stepNum2 + 1;
3311
- };
3312
- let stepNum = 1;
3313
- for (const step of viewSteps) {
3314
- if (isDynamicStepsParallel(step)) {
3315
- let nestedStepNum = 1;
3316
- for (const s of step.__parallel) {
3317
- nestedStepNum = processStep(s, nestedStepNum, stepNum);
3318
- }
3319
- stepNum++;
3320
- continue;
3321
- }
3322
- stepNum = processStep(step, stepNum);
3323
- }
3324
- const nodesMap = buildComputedNodes(
3325
- this.model.$styles,
3326
- actors.map(elementModelToNodeSource)
3327
- );
3328
- const defaults = this.model.$styles.defaults.relationship;
3329
- const edges = this.steps.map(({ id, source, target, relations, title, isBackward, tags, ...step }) => {
3330
- const sourceNode = nonNullable(nodesMap.get(source.id), `Source node ${source.id} not found`);
3331
- const targetNode = nonNullable(nodesMap.get(target.id), `Target node ${target.id} not found`);
3332
- const edge = {
3333
- id,
3334
- parent: commonAncestor(source.id, target.id),
3335
- source: sourceNode.id,
3336
- target: targetNode.id,
3337
- label: title ?? null,
3338
- relations,
3339
- color: defaults.color,
3340
- line: defaults.line,
3341
- head: defaults.arrow,
3342
- tags: tags ?? [],
3343
- ...step
3344
- };
3345
- if (isBackward) {
3346
- edge.dir = "back";
3347
- }
3348
- while (edge.parent && !nodesMap.has(edge.parent)) {
3349
- edge.parent = parentFqn(edge.parent);
3350
- }
3351
- sourceNode.outEdges.push(edge.id);
3352
- targetNode.inEdges.push(edge.id);
3353
- for (const sourceAncestor of ancestorsFqn(edge.source)) {
3354
- if (sourceAncestor === edge.parent) {
3355
- break;
3356
- }
3357
- nodesMap.get(sourceAncestor)?.outEdges.push(edge.id);
3358
- }
3359
- for (const targetAncestor of ancestorsFqn(edge.target)) {
3360
- if (targetAncestor === edge.parent) {
3361
- break;
3362
- }
3363
- nodesMap.get(targetAncestor)?.inEdges.push(edge.id);
3364
- }
3365
- return edge;
3366
- });
3367
- const nodes = applyCustomElementProperties(
3368
- rules,
3369
- applyViewRuleStyles(
3370
- rules,
3371
- // Keep order of elements
3372
- actors.map((e) => nonNullable(nodesMap.get(e.id)))
3373
- )
3374
- );
3375
- const autoLayoutRule = t$8(rules, isViewRuleAutoLayout);
3376
- const nodeNotations = buildElementNotations(nodes);
3377
- return calcViewLayoutHash({
3378
- ...view,
3379
- [_type]: "dynamic",
3380
- [_stage]: "computed",
3381
- variant: view.variant ?? "diagram",
3382
- autoLayout: {
3383
- direction: autoLayoutRule?.direction ?? "LR",
3384
- ...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
3385
- ...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
3386
- },
3387
- nodes: t$e(nodes, (n) => {
3388
- if (n.icon === "none") {
3389
- delete n.icon;
3390
- }
3391
- return n;
3392
- }),
3393
- edges,
3394
- ...nodeNotations.length > 0 && {
3395
- notation: {
3396
- nodes: nodeNotations
3397
- }
3398
- }
3399
- });
3400
- }
3401
- }
3402
- function computeDynamicView(model, view) {
3403
- return new DynamicViewCompute(model, view).compute();
3404
- }
3405
-
3406
- function relationExpressionToPredicates(expr) {
3407
- switch (true) {
3408
- case ModelRelationExpr.isCustom(expr): {
3409
- return relationExpressionToPredicates(expr.customRelation.expr);
3410
- }
3411
- case ModelRelationExpr.isWhere(expr): {
3412
- const predicate = relationExpressionToPredicates(expr.where.expr);
3413
- const where = whereOperatorAsPredicate(expr.where.condition);
3414
- return (e) => predicate(e) && where({
3415
- source: { tags: e.source.tags, kind: e.source.kind },
3416
- target: { tags: e.target.tags, kind: e.target.kind },
3417
- ...e.tags && { tags: e.tags },
3418
- ...e.kind && { kind: e.kind }
3419
- });
3420
- }
3421
- case ModelRelationExpr.isDirect(expr): {
3422
- const isSource = elementExprToPredicate(expr.source);
3423
- const isTarget = elementExprToPredicate(expr.target);
3424
- return (edge) => {
3425
- return isSource(edge.source) && isTarget(edge.target) || !!expr.isBidirectional && isSource(edge.target) && isTarget(edge.source);
3426
- };
3427
- }
3428
- case ModelRelationExpr.isInOut(expr): {
3429
- const isInOut = elementExprToPredicate(expr.inout);
3430
- return (edge) => isInOut(edge.source) || isInOut(edge.target);
3431
- }
3432
- case ModelRelationExpr.isIncoming(expr): {
3433
- const isTarget = elementExprToPredicate(expr.incoming);
3434
- return (edge) => isTarget(edge.target);
3435
- }
3436
- case ModelRelationExpr.isOutgoing(expr): {
3437
- const isSource = elementExprToPredicate(expr.outgoing);
3438
- return (edge) => isSource(edge.source);
3439
- }
3440
- default:
3441
- nonexhaustive(expr);
3442
- }
3443
- }
3444
-
3445
- function applyCustomRelationProperties(_rules, nodes, _edges) {
3446
- const rules = _rules.flatMap(flattenGroupRules(ModelRelationExpr.isCustom));
3447
- const edges = Array.from(_edges);
3448
- if (rules.length === 0 || edges.length === 0) {
3449
- return edges;
3450
- }
3451
- for (const {
3452
- customRelation: {
3453
- expr,
3454
- title,
3455
- description: _description,
3456
- notes: _notes,
3457
- ...customprops
3458
- }
3459
- } of rules) {
3460
- const description = _description ? { description: { txt: _description } } : {};
3461
- const notes = _notes ? { notes: { txt: _notes } } : {};
3462
- const props = t$o(customprops, e$8);
3463
- const satisfies = relationExpressionToPredicates(expr);
3464
- edges.forEach((edge, i) => {
3465
- let source, target;
3466
- for (const node of nodes) {
3467
- if (node.id === edge.source) {
3468
- source = node;
3469
- }
3470
- if (node.id === edge.target) {
3471
- target = node;
3472
- }
3473
- if (source && target) {
3474
- break;
3475
- }
3476
- }
3477
- if (!source || !target) {
3478
- return;
3479
- }
3480
- if (satisfies({ source, target, ...t$i(edge, ["kind", "tags"]) })) {
3481
- edges[i] = {
3482
- ...edge,
3483
- ...props,
3484
- ...description,
3485
- ...notes,
3486
- label: title ?? edge.label,
3487
- isCustomized: true
3488
- };
3489
- }
3490
- });
3491
- }
3492
- return edges;
3493
- }
3494
-
3495
- class NodesGroup {
3496
- constructor(id, viewRule, parent = null, elements = /* @__PURE__ */ new Set()) {
3497
- this.id = id;
3498
- this.viewRule = viewRule;
3499
- this.parent = parent;
3500
- this.elements = elements;
3501
- }
3502
- static kind = GroupElementKind;
3503
- isEmpty() {
3504
- return this.elements.size === 0;
3505
- }
3506
- update(elements) {
3507
- return new NodesGroup(
3508
- this.id,
3509
- this.viewRule,
3510
- this.parent,
3511
- elements
3512
- );
3513
- }
3514
- clone() {
3515
- return new NodesGroup(this.id, this.viewRule, this.parent, new Set(this.elements));
3516
- }
3517
- }
3518
-
3519
- class StageExclude extends AbstractStageExclude {
3520
- excludeRelations(excluded) {
3521
- t$d(
3522
- this.memory.connections,
3523
- n$d((c) => hasIntersection(c.relations, excluded)),
3524
- t$7((c) => {
3525
- this.excludeConnections(
3526
- c.update(intersection(c.relations, excluded))
3527
- );
3528
- })
3529
- );
3530
- return this;
3531
- }
3532
- /**
3533
- * Precommit hook
3534
- */
3535
- precommit(state) {
3536
- if (this.excluded.elements.size > 0) {
3537
- const excludeRelationships = new Set(
3538
- [...this.excluded.elements].flatMap((el) => [
3539
- ...el.incoming("direct"),
3540
- ...el.outgoing("direct")
3541
- ])
3542
- );
3543
- this.excludeRelations(excludeRelationships);
3544
- }
3545
- return state;
3546
- }
3547
- postcommit(state) {
3548
- const leftExplicits = difference(this.memory.explicits, state.explicits);
3549
- for (const explicit of leftExplicits) {
3550
- state.explicitFirstSeenIn.delete(explicit);
3551
- }
3552
- const left = difference(this.memory.elements, state.elements);
3553
- for (const el of left) {
3554
- state.lastSeenIn.delete(el);
3555
- }
3556
- return state;
3557
- }
3558
- }
3559
- class ActiveGroupStageExclude extends StageExclude {
3560
- constructor(memory, expression) {
3561
- super(memory, expression);
3562
- this.memory = memory;
3563
- this.expression = expression;
3564
- }
3565
- }
3566
-
3567
- const { findConnection: findConnection$1, findConnectionsBetween: findConnectionsBetween$1 } = modelConnection;
3568
- class StageInclude extends AbstractStageInclude {
3569
- /**
3570
- * Connects elements with existing ones in the memory
3571
- */
3572
- connectWithExisting(elements, direction = "both") {
3573
- const before = this._connections.length;
3574
- const hasChanged = () => this._connections.length > before;
3575
- if (!isIterable(elements)) {
3576
- if (direction === "in" || direction === "both") {
3577
- for (const el of this.memory.elements) {
3578
- this.addConnections(
3579
- findConnection$1(el, elements, "directed")
3580
- );
3581
- }
3582
- }
3583
- if (direction === "out" || direction === "both") {
3584
- this.addConnections(
3585
- findConnectionsBetween$1(elements, this.memory.elements, "directed")
3586
- );
3587
- }
3588
- return hasChanged();
3589
- }
3590
- const targets = [...elements];
3591
- if (direction === "in" || direction === "both") {
3592
- for (const el of this.memory.elements) {
3593
- this.addConnections(
3594
- findConnectionsBetween$1(el, targets, "directed")
3595
- );
3596
- }
3597
- }
3598
- if (direction === "out" || direction === "both") {
3599
- for (const el of targets) {
3600
- this.addConnections(
3601
- findConnectionsBetween$1(el, this.memory.elements, "directed")
3602
- );
3603
- }
3604
- }
3605
- return hasChanged();
3606
- }
3607
- addImplicitWithinScope(element) {
3608
- if (!element) {
3609
- return;
3610
- }
3611
- if (!this.memory.scope || isAncestor(this.memory.scope, element)) {
3612
- this.addImplicit(element);
3613
- }
3614
- }
3615
- processConnections(connections) {
3616
- if (ModelExpression.isRelationExpr(this.expression)) {
3617
- return connections;
3618
- }
3619
- t$d(
3620
- connections,
3621
- t$7(({ source, target, boundary }) => {
3622
- t$d(
3623
- t$n(
3624
- [...toArray(source.ancestors()).reverse(), source],
3625
- [...toArray(target.ancestors()).reverse(), target]
3626
- ),
3627
- // Filter out common ancestors
3628
- t$9(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor),
3629
- n(1),
3630
- t$7(([sourceAncestor, targetAncestor]) => {
3631
- if (sourceAncestor === source && targetAncestor === target) {
3632
- this.addImplicitWithinScope(boundary);
3633
- return;
3634
- }
3635
- if (sourceAncestor !== source) {
3636
- this.addImplicitWithinScope(sourceAncestor);
3637
- }
3638
- if (targetAncestor !== target) {
3639
- this.addImplicitWithinScope(targetAncestor);
3640
- }
3641
- })
3642
- );
3643
- })
3644
- );
3645
- return connections;
3646
- }
3647
- postcommit(state) {
3648
- const newExplicits = difference(state.explicits, this.memory.explicits);
3649
- for (const explicit of newExplicits) {
3650
- state.explicitFirstSeenIn.set(explicit, "@root");
3651
- }
3652
- return state;
3653
- }
3654
- }
3655
- class ActiveGroupStageInclude extends StageInclude {
3656
- constructor(memory, expression) {
3657
- super(memory, expression);
3658
- this.memory = memory;
3659
- this.expression = expression;
3660
- }
3661
- postcommit(state) {
3662
- const newExplicits = difference(state.explicits, this.memory.explicits);
3663
- for (const explicit of newExplicits) {
3664
- state.explicitFirstSeenIn.set(explicit, this.memory.activeGroupId);
3665
- }
3666
- for (const implicit of [...this.explicits, ...this.implicits]) {
3667
- state.lastSeenIn.set(implicit, this.memory.activeGroupId);
3668
- }
3669
- return state;
3670
- }
3671
- }
3672
-
3673
- class Memory extends AbstractMemory {
3674
- constructor(state, scope) {
3675
- super(state);
3676
- this.state = state;
3677
- this.scope = scope;
3678
- }
3679
- static empty(scope) {
3680
- return new Memory({
3681
- elements: /* @__PURE__ */ new Set(),
3682
- explicits: /* @__PURE__ */ new Set(),
3683
- final: /* @__PURE__ */ new Set(),
3684
- connections: [],
3685
- groups: [],
3686
- explicitFirstSeenIn: /* @__PURE__ */ new Map(),
3687
- lastSeenIn: /* @__PURE__ */ new Map()
3688
- }, scope);
3689
- }
3690
- get groups() {
3691
- return this.state.groups;
3692
- }
3693
- get explicitFirstSeenIn() {
3694
- return this.state.explicitFirstSeenIn;
3695
- }
3696
- get lastSeenIn() {
3697
- return this.state.lastSeenIn;
3698
- }
3699
- stageInclude(expr) {
3700
- return new StageInclude(this, expr);
3701
- }
3702
- stageExclude(expr) {
3703
- return new StageExclude(this, expr);
3704
- }
3705
- mutableState() {
3706
- return {
3707
- elements: new Set(this.state.elements),
3708
- explicits: new Set(this.state.explicits),
3709
- final: new Set(this.state.final),
3710
- connections: [...this.state.connections],
3711
- groups: this.state.groups.map((g) => g.clone()),
3712
- explicitFirstSeenIn: new Map(this.state.explicitFirstSeenIn),
3713
- lastSeenIn: new Map(this.state.lastSeenIn)
3714
- };
3715
- }
3716
- update(newstate) {
3717
- return new Memory({
3718
- ...this.state,
3719
- ...newstate
3720
- }, this.scope);
3721
- }
3722
- }
3723
- class ActiveGroupMemory extends Memory {
3724
- constructor(state, scope, stack) {
3725
- super(state, scope);
3726
- this.state = state;
3727
- this.scope = scope;
3728
- this.stack = stack;
3729
- }
3730
- static enter(memory, rule) {
3731
- const groupId = `@gr${memory.groups.length + 1}`;
3732
- if (memory instanceof ActiveGroupMemory) {
3733
- const stack2 = Stack.from([...memory.stack].reverse());
3734
- const state2 = memory.mutableState();
3735
- state2.groups.push(new NodesGroup(groupId, rule, memory.activeGroupId));
3736
- stack2.push(groupId);
3737
- return new ActiveGroupMemory(state2, memory.scope, stack2);
3738
- }
3739
- const state = memory.mutableState();
3740
- state.groups.push(new NodesGroup(groupId, rule, null));
3741
- const stack = Stack.of(groupId);
3742
- return new ActiveGroupMemory(state, memory.scope, stack);
3743
- }
3744
- get activeGroupId() {
3745
- return nonNullable(this.stack.peek(), "Stack must not be empty");
3746
- }
3747
- mutableState() {
3748
- const state = super.mutableState();
3749
- return {
3750
- ...state
3751
- // activeGroup: this.findActiveGroup(state.groups)
3752
- };
3753
- }
3754
- // private findActiveGroup(groups: NodesGroup[]): NodesGroup {
3755
- // return nonNullable(groups.find(g => g.id === this.activeGroup.id), 'Active group not found in groups')
3756
- // }
3757
- update(newstate) {
3758
- const nextstate = {
3759
- ...this.state,
3760
- ...newstate
3761
- };
3762
- return new ActiveGroupMemory(nextstate, this.scope, this.stack);
3763
- }
3764
- stageInclude(expr) {
3765
- return new ActiveGroupStageInclude(this, expr);
3766
- }
3767
- stageExclude(expr) {
3768
- return new ActiveGroupStageExclude(this, expr);
3769
- }
3770
- leave() {
3771
- const state = this.mutableState();
3772
- this.stack.pop();
3773
- const prevgroup = this.stack.peek();
3774
- if (prevgroup) {
3775
- return new ActiveGroupMemory(state, this.scope, this.stack);
3776
- }
3777
- return new Memory(state, this.scope);
3778
- }
3779
- }
3780
-
3781
- function findRedundantConnections(connections) {
3782
- return t$d(
3783
- [...connections],
3784
- mergeConnections,
3785
- t$2((reducedConnections, connection, _, all) => {
3786
- const descendants = findDescendantConnections(all, connection);
3787
- const nestedRelations = union(
3788
- ...descendants.map(e$9("relations"))
3789
- );
3790
- let accum = intersection(connection.relations, nestedRelations);
3791
- if (descendants.length > 0) {
3792
- accum = union(accum, connection.directRelations);
3793
- }
3794
- if (findDeepestNestedConnection(all, connection.reversed(false))) {
3795
- accum = union(accum, connection.directRelations);
3796
- }
3797
- if (accum.size < connection.relations.size) {
3798
- const isSourceExpanded = all.some(isAnyInOut(connection.source));
3799
- const isTargetExpanded = all.some(isAnyInOut(connection.target));
3800
- if (isSourceExpanded) {
3801
- accum = union(
3802
- accum,
3803
- toSet(
3804
- ifilter(
3805
- connection.relations,
3806
- isOutgoing(connection.source)
3807
- )
3808
- )
3809
- );
3810
- }
3811
- if (isTargetExpanded) {
3812
- accum = union(
3813
- accum,
3814
- toSet(
3815
- ifilter(
3816
- connection.relations,
3817
- isIncoming(connection.target)
3818
- )
3819
- )
3820
- );
3821
- }
3822
- }
3823
- if (accum.size > 0) {
3824
- reducedConnections.push(connection.update(accum));
3825
- }
3826
- return reducedConnections;
3827
- }, [])
3828
- );
3829
- }
3830
-
3831
- class StageFinal {
3832
- constructor(memory) {
3833
- this.memory = memory;
3834
- }
3835
- static for(memory) {
3836
- return new StageFinal(memory);
3837
- }
3838
- step1CleanConnections(memory) {
3839
- if (memory.connections.length < 2) {
3840
- return memory;
3841
- }
3842
- const connectionsToExclude = findRedundantConnections(memory.connections);
3843
- if (connectionsToExclude.length === 0) {
3844
- return memory;
3845
- }
3846
- const stage = memory.stageExclude({});
3847
- stage.excludeConnections(connectionsToExclude, true);
3848
- return stage.commit();
3849
- }
3850
- step2ProcessImplicits(memory) {
3851
- const implicits = union(this.memory.elements, memory.elements);
3852
- const final = union(memory.final, this.memory.explicits);
3853
- const snapshot = new Set(final);
3854
- const isFinalOrHasIncludedDescendant = (el) => {
3855
- for (const final2 of snapshot) {
3856
- if (el === final2 || isAncestor(el, final2)) {
3857
- return true;
3858
- }
3859
- }
3860
- return false;
3861
- };
3862
- t$d(
3863
- difference(implicits, snapshot),
3864
- toArray(),
3865
- sortByFqnHierarchically,
3866
- t$7((el) => {
3867
- const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length;
3868
- if (childrensToWrap >= 2) {
3869
- final.add(el);
3870
- return;
3871
- }
3872
- if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) {
3873
- final.add(el);
3874
- }
3875
- })
3876
- );
3877
- return memory.update({ final });
3878
- }
3879
- step3ProcessBoundaries(memory) {
3880
- const boundaries = /* @__PURE__ */ new Set();
3881
- for (const conn of memory.connections) {
3882
- if (conn.boundary && conn.boundary !== conn.source && conn.boundary !== conn.target) {
3883
- boundaries.add(conn.boundary);
3884
- }
3885
- }
3886
- const tree = treeFromMemoryState(memory, "final");
3887
- const stage = memory.stageExclude({});
3888
- const isRemovable = (el) => !(boundaries.has(el) || memory.explicits.has(el) || tree.hasInOut(el) || tree.root.has(el));
3889
- const singleRoot = t$5([...tree.root]);
3890
- if (singleRoot && !memory.explicits.has(singleRoot)) {
3891
- stage.exclude(singleRoot);
3892
- }
3893
- for (const el of memory.final) {
3894
- const singleChild = t$5(tree.children(el));
3895
- if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) {
3896
- stage.exclude(el);
3897
- }
3898
- }
3899
- if (stage.isDirty()) {
3900
- return stage.commit();
3901
- }
3902
- return memory;
3903
- }
3904
- commit() {
3905
- const step1 = this.step1CleanConnections(this.memory);
3906
- const step2 = this.step2ProcessImplicits(step1);
3907
- return this.step3ProcessBoundaries(step2);
3908
- }
3909
- }
3910
-
3911
- const { findConnection, findConnectionsBetween, findConnectionsWithin } = modelConnection;
3912
- function resolveElements(model, expr) {
3913
- switch (true) {
3914
- case ModelFqnExpr.isElementKindExpr(expr): {
3915
- return [...ifilter(model.elements(), (el) => {
3916
- return expr.isEqual === (el.kind === expr.elementKind);
3917
- })];
3918
- }
3919
- case ModelFqnExpr.isElementTagExpr(expr): {
3920
- return [...ifilter(model.elements(), (el) => {
3921
- return expr.isEqual === el.tags.includes(expr.elementTag);
3922
- })];
3923
- }
3924
- case expr.selector === "expanded": {
3925
- const element = model.element(FqnRef.flatten(expr.ref));
3926
- return [
3927
- element,
3928
- ...element.children()
3929
- ];
3930
- }
3931
- case expr.selector === "children":
3932
- case expr.selector === "descendants": {
3933
- const element = model.element(FqnRef.flatten(expr.ref));
3934
- let children = expr.selector === "children" ? toArray(element.children()) : toArray(element.descendants());
3935
- return children && children.length > 0 ? children : [element];
3936
- }
3937
- case ModelFqnExpr.isModelRef(expr): {
3938
- return [model.element(FqnRef.flatten(expr.ref))];
3939
- }
3940
- default:
3941
- nonexhaustive(expr);
3942
- }
3943
- }
3944
- function includeDescendantsFromMemory(elements, memory) {
3945
- if (memory.isEmpty() || elements.length === 0) {
3946
- return elements;
3947
- }
3948
- const descedantsOf = t$g(elements.map((e) => isDescendantOf(e)));
3949
- const fromMemory = toArray(
3950
- ifilter(
3951
- memory.elements,
3952
- (el) => !elements.includes(el) && descedantsOf(el)
3953
- )
3954
- );
3955
- return [
3956
- ...elements,
3957
- ...fromMemory
3958
- ];
3959
- }
3960
- function resolveAndIncludeFromMemory(nonWildcard, { memory, model }) {
3961
- const resolved = resolveElements(model, nonWildcard);
3962
- if (ModelFqnExpr.isModelRef(nonWildcard)) {
3963
- if (nonWildcard.selector === "descendants") {
3964
- return resolved;
3965
- }
3966
- return includeDescendantsFromMemory(resolved, memory);
3967
- }
3968
- return resolved;
3969
- }
3970
-
3971
- const ExpandedElementPredicate = {
3972
- include: ({ expr, model, stage, where }) => {
3973
- const parent = model.element(FqnRef.flatten(expr.ref));
3974
- if (where(parent)) {
3975
- stage.addExplicit(parent);
3976
- stage.connectWithExisting(parent);
3977
- }
3978
- const children = [...parent.children()].filter(where);
3979
- const expanded = [];
3980
- for (const child of children) {
3981
- stage.addImplicit(child);
3982
- if (stage.connectWithExisting(child)) {
3983
- expanded.push(child);
3984
- }
3985
- }
3986
- stage.addConnections(findConnectionsWithin(expanded));
3987
- return stage;
3988
- },
3989
- exclude: ({ expr, model, stage, filterWhere }) => {
3990
- const elements = filterWhere(resolveElements(model, expr));
3991
- stage.exclude(elements);
3992
- return stage;
3993
- }
3994
- };
3995
-
3996
- const ElementKindOrTagPredicate = {
3997
- include: ({ expr, model, stage, filterWhere }) => {
3998
- const elements = filterWhere(resolveElements(model, expr));
3999
- if (elements.length === 0) {
4000
- return;
4001
- }
4002
- stage.addExplicit(elements);
4003
- stage.connectWithExisting(elements);
4004
- stage.addConnections(findConnectionsWithin(elements));
4005
- return stage;
4006
- },
4007
- exclude: ({ expr, model, stage, filterWhere }) => {
4008
- const elements = filterWhere(resolveElements(model, expr));
4009
- stage.exclude(elements);
4010
- return stage;
4011
- }
4012
- };
4013
-
4014
- const ElementRefPredicate = {
4015
- include: ({ expr, model, stage, filterWhere }) => {
4016
- const elements = filterWhere(resolveElements(model, expr));
4017
- if (elements.length === 0) {
4018
- return;
4019
- }
4020
- stage.addExplicit(elements);
4021
- stage.connectWithExisting(elements);
4022
- stage.addConnections(findConnectionsWithin(elements));
4023
- return stage;
4024
- },
4025
- exclude: ({ expr, model, stage, filterWhere }) => {
4026
- const elements = filterWhere(resolveElements(model, expr));
4027
- stage.exclude(elements);
4028
- return stage;
4029
- }
4030
- };
4031
-
4032
- const NoWhere = () => true;
4033
- const NoFilter = (x) => x;
4034
- function toComputedEdges(connections) {
4035
- return connections.reduce((acc, e) => {
4036
- const relations = [
4037
- ...e.relations
4038
- ];
4039
- invariant(t$b(relations, 1), "Edge must have at least one relation");
4040
- const $defaults = e.source.$model.$styles.defaults;
4041
- const source = e.source.id;
4042
- const target = e.target.id;
4043
- const {
4044
- title,
4045
- color = $defaults.relationship.color,
4046
- line = $defaults.relationship.line,
4047
- head = $defaults.relationship.arrow,
4048
- ...props
4049
- } = mergePropsFromRelationships(
4050
- relations.map((r) => r.$relationship),
4051
- // Prefer only single relationship
4052
- // https://github.com/likec4/likec4/issues/1423
4053
- t$5(
4054
- n$d(relations, (r) => r.source.id === source && r.target.id === target)
4055
- )?.$relationship
4056
- );
4057
- const edge = exact({
4058
- id: e.id,
4059
- parent: e.boundary?.id ?? null,
4060
- source,
4061
- target,
4062
- label: title ?? null,
4063
- relations: relations.map((r) => r.id),
4064
- color,
4065
- line,
4066
- head,
4067
- ...props
4068
- });
4069
- acc.push(edge);
4070
- return acc;
4071
- }, []);
4072
- }
4073
- function buildNodes(model, memory) {
4074
- return buildComputedNodes(
4075
- model.$styles,
4076
- [...memory.final].map(elementModelToNodeSource),
4077
- memory.groups
4078
- );
4079
- }
4080
-
4081
- const isWildcard = ModelFqnExpr.isWildcard;
4082
- const isAncestorOrDescendantOf = (a, b) => a.isAncestorOf(b) || a.isDescendantOf(b);
4083
- const DirectRelationExprPredicate = {
4084
- include: ({ expr: { source, target, isBidirectional = false }, memory, model, stage, where, filterWhere }) => {
4085
- const sourceIsWildcard = isWildcard(source);
4086
- const targetIsWildcard = isWildcard(target);
4087
- const connections = [];
4088
- switch (true) {
4089
- // This is a special case, we look for all relationships that satisfy the where clause
4090
- // * -> * ; Empty memory; Where clause
4091
- case (sourceIsWildcard && targetIsWildcard && memory.isEmpty() && where !== NoWhere): {
4092
- const connections2 = t$d(
4093
- model.relationships(),
4094
- ifilter(where),
4095
- toArray(),
4096
- t$e((r) => new ConnectionModel(r.source, r.target, /* @__PURE__ */ new Set([r])))
4097
- );
4098
- stage.addConnections(connections2);
4099
- return stage;
4100
- }
4101
- // This is a special case, we look for all relationships between elements that satisfy the where clause
4102
- // * -> *; Not empty memory; Where clause
4103
- case (sourceIsWildcard && targetIsWildcard && !memory.isEmpty() && where !== NoWhere): {
4104
- connections.push(
4105
- ...findConnectionsWithin(memory.elements)
4106
- );
4107
- break;
4108
- }
4109
- // * -> *
4110
- case (sourceIsWildcard && targetIsWildcard): {
4111
- connections.push(
4112
- ...findConnectionsWithin(model.roots())
4113
- );
4114
- break;
4115
- }
4116
- // This is a special case, we look for all relationships that satisfy the where clause
4117
- // element -> *; Where clause
4118
- case (!sourceIsWildcard && targetIsWildcard && where !== NoWhere): {
4119
- const sources = resolveElements(model, source);
4120
- const connections2 = t$d(
4121
- sources,
4122
- t$m(
4123
- (source2) => t$d(
4124
- source2,
4125
- e(e$3(isBidirectional === true), {
4126
- onTrue: (s) => union(s.allIncoming, s.allOutgoing),
4127
- onFalse: (s) => s.allOutgoing
4128
- }),
4129
- ifilter(where),
4130
- iunique(),
4131
- toArray(),
4132
- t$4((r) => r.source === source2),
4133
- ([outgoing, incoming]) => t$p(
4134
- t$d(
4135
- outgoing,
4136
- n$d((r) => !isAncestorOrDescendantOf(source2, r.target)),
4137
- t$e(
4138
- (outgoing2) => new ConnectionModel(
4139
- source2,
4140
- outgoing2.target,
4141
- /* @__PURE__ */ new Set([outgoing2])
4142
- )
4143
- )
4144
- ),
4145
- t$d(
4146
- incoming,
4147
- n$d((r) => !isAncestorOrDescendantOf(source2, r.source)),
4148
- t$e(
4149
- (incoming2) => new ConnectionModel(
4150
- incoming2.source,
4151
- source2,
4152
- /* @__PURE__ */ new Set([incoming2])
4153
- )
4154
- )
4155
- )
4156
- )
4157
- )
4158
- )
4159
- );
4160
- stage.addConnections(connections2);
4161
- return stage;
4162
- }
4163
- // element -> *
4164
- case (!sourceIsWildcard && targetIsWildcard): {
4165
- const [sources, targets] = resolveWildcard(source, { memory, model });
4166
- const dir = isBidirectional ? "both" : "directed";
4167
- for (const source2 of sources) {
4168
- connections.push(
4169
- ...findConnectionsBetween(source2, targets, dir)
4170
- );
4171
- }
4172
- break;
4173
- }
4174
- // This is a special case, we look for all relationships that satisfy the where clause
4175
- // * -> element; Where clause
4176
- case (sourceIsWildcard && !targetIsWildcard && where !== NoWhere): {
4177
- const targets = resolveElements(model, target);
4178
- const connections2 = t$d(
4179
- targets,
4180
- t$m(
4181
- (target2) => t$d(
4182
- target2,
4183
- e(e$3(isBidirectional === true), {
4184
- onTrue: (s) => union(s.allIncoming, s.allOutgoing),
4185
- onFalse: (s) => s.allIncoming
4186
- }),
4187
- ifilter(where),
4188
- toArray(),
4189
- t$4((r) => r.target === target2),
4190
- ([incoming, outgoing]) => t$p(
4191
- t$d(
4192
- outgoing,
4193
- n$d((r) => !isAncestorOrDescendantOf(target2, r.target)),
4194
- t$e(
4195
- (outgoing2) => new ConnectionModel(
4196
- target2,
4197
- outgoing2.target,
4198
- /* @__PURE__ */ new Set([outgoing2])
4199
- )
4200
- )
4201
- ),
4202
- t$d(
4203
- incoming,
4204
- n$d((r) => !isAncestorOrDescendantOf(target2, r.source)),
4205
- t$e(
4206
- (incoming2) => new ConnectionModel(
4207
- incoming2.source,
4208
- target2,
4209
- /* @__PURE__ */ new Set([incoming2])
4210
- )
4211
- )
4212
- )
4213
- )
4214
- )
4215
- )
4216
- );
4217
- stage.addConnections(connections2);
4218
- return stage;
4219
- }
4220
- // * -> element
4221
- case (sourceIsWildcard && !targetIsWildcard): {
4222
- const [targets, sources] = resolveWildcard(target, { memory, model });
4223
- const dir = isBidirectional ? "both" : "directed";
4224
- for (const source2 of sources) {
4225
- connections.push(
4226
- ...findConnectionsBetween(source2, targets, dir)
4227
- );
4228
- }
4229
- break;
4230
- }
4231
- default: {
4232
- invariant(!isWildcard(source), "Inference failed - source must be not a wildcard");
4233
- invariant(!isWildcard(target), "Inference failed - target must be not a wildcard");
4234
- const sources = resolveAndIncludeFromMemory(source, { memory, model });
4235
- const targets = resolveAndIncludeFromMemory(target, { memory, model });
4236
- const dir = isBidirectional ? "both" : "directed";
4237
- for (const source2 of sources) {
4238
- connections.push(
4239
- ...findConnectionsBetween(source2, targets, dir)
4240
- );
4241
- }
4242
- }
4243
- }
4244
- stage.addConnections(
4245
- filterWhere(connections)
4246
- );
4247
- return stage;
4248
- },
4249
- exclude: ({ expr: { source, target, isBidirectional }, model, memory, stage, where }) => {
4250
- const sourceIsWildcard = isWildcard(source);
4251
- const targetIsWildcard = isWildcard(target);
4252
- let relations;
4253
- switch (true) {
4254
- // * -> *
4255
- case (sourceIsWildcard && targetIsWildcard): {
4256
- relations = t$d(
4257
- memory.connections,
4258
- t$m(t$j(
4259
- e$9("relations"),
4260
- ifilter(where),
4261
- toArray()
4262
- )),
4263
- toSet()
4264
- );
4265
- break;
4266
- }
4267
- // element -> *
4268
- case (!sourceIsWildcard && targetIsWildcard): {
4269
- const sources = resolveElements(model, source);
4270
- relations = t$d(
4271
- sources,
4272
- t$m(
4273
- (source2) => t$d(
4274
- source2,
4275
- e(e$3(isBidirectional === true), {
4276
- onTrue: (s) => union(s.allIncoming, s.allOutgoing),
4277
- onFalse: (s) => s.allOutgoing
4278
- }),
4279
- ifilter(where),
4280
- toArray()
4281
- )
4282
- ),
4283
- toSet()
4284
- );
4285
- break;
4286
- }
4287
- // * -> element
4288
- case (sourceIsWildcard && !targetIsWildcard): {
4289
- const targets = resolveElements(model, target);
4290
- relations = t$d(
4291
- targets,
4292
- t$m(
4293
- (target2) => t$d(
4294
- target2,
4295
- e(e$3(isBidirectional === true), {
4296
- onTrue: (s) => union(s.allIncoming, s.allOutgoing),
4297
- onFalse: (s) => s.allIncoming
4298
- }),
4299
- ifilter(where),
4300
- toArray()
4301
- )
4302
- ),
4303
- toSet()
4304
- );
4305
- break;
4306
- }
4307
- default: {
4308
- invariant(!isWildcard(source), "Inferrence failed - source must be not a wildcard");
4309
- invariant(!isWildcard(target), "Inferrence failed - target must be not a wildcard");
4310
- const sources = resolveElements(model, source);
4311
- const targets = resolveElements(model, target);
4312
- let accum = /* @__PURE__ */ new Set();
4313
- for (const source2 of sources) {
4314
- for (const target2 of targets) {
4315
- if (isSameHierarchy(source2, target2)) {
4316
- continue;
4317
- }
4318
- accum = union(
4319
- accum,
4320
- intersection(source2.allOutgoing, target2.allIncoming),
4321
- isBidirectional ? intersection(target2.allOutgoing, source2.allIncoming) : /* @__PURE__ */ new Set()
4322
- );
4323
- }
4324
- }
4325
- relations = toSet(ifilter(accum, where));
4326
- }
4327
- }
4328
- stage.excludeRelations(relations);
4329
- return stage;
4330
- }
4331
- };
4332
- function resolveWildcard(nonWildcard, { memory, model }) {
4333
- let sources = resolveElements(model, nonWildcard);
4334
- if (!t$b(sources, 1)) {
4335
- return [[], []];
4336
- }
4337
- if (ModelFqnExpr.isModelRef(nonWildcard)) {
4338
- const parent = model.element(FqnRef.flatten(nonWildcard.ref));
4339
- const targets2 = toArray(parent.ascendingSiblings());
4340
- return [
4341
- includeDescendantsFromMemory(sources, memory),
4342
- includeDescendantsFromMemory(targets2, memory)
4343
- ];
4344
- }
4345
- const targets = t$d(
4346
- sources,
4347
- t$e((el) => el.ascendingSiblings()),
4348
- iflat(),
4349
- iunique(),
4350
- toArray(),
4351
- (all) => includeDescendantsFromMemory(all, memory)
4352
- );
4353
- return [sources, targets];
4354
- }
4355
-
4356
- const IncomingExprPredicate = {
4357
- include: ({ expr, scope, model, memory, stage, filterWhere }) => {
4358
- const target = expr.incoming;
4359
- const connections = [];
4360
- if (ModelFqnExpr.isWildcard(target)) {
4361
- if (!scope) {
4362
- return;
4363
- }
4364
- for (const sibling of scope.ascendingSiblings()) {
4365
- connections.push(
4366
- ...findConnection(
4367
- sibling,
4368
- scope,
4369
- "directed"
4370
- )
4371
- );
4372
- }
4373
- } else {
4374
- const targets = resolveAndIncludeFromMemory(target, { memory, model });
4375
- const visibleElements = [...memory.elements];
4376
- if (visibleElements.length === 0) {
4377
- visibleElements.push(
4378
- ...n$e(
4379
- targets.flatMap((el) => [...el.ascendingSiblings()])
4380
- )
4381
- );
4382
- }
4383
- const ensureIncoming = incomingConnectionPredicate(model, target);
4384
- for (const visible of visibleElements) {
4385
- connections.push(
4386
- ...findConnectionsBetween(
4387
- visible,
4388
- targets,
4389
- "directed"
4390
- ).filter(ensureIncoming)
4391
- );
4392
- }
4393
- }
4394
- stage.addConnections(
4395
- filterWhere(connections)
4396
- );
4397
- return stage;
4398
- },
4399
- exclude: ({ expr: { incoming }, model, scope, stage, where }) => {
4400
- const excluded = [];
4401
- if (ModelFqnExpr.isWildcard(incoming)) {
4402
- if (!scope) {
4403
- return;
4404
- }
4405
- excluded.push(...scope.allIncoming);
4406
- } else {
4407
- const elements = resolveElements(model, incoming);
4408
- excluded.push(
4409
- ...elements.flatMap((e) => [...e.allIncoming])
4410
- );
4411
- }
4412
- stage.excludeRelations(new Set(excluded.filter(where)));
4413
- return stage;
4414
- }
4415
- };
4416
- function incomingConnectionPredicate(model, expr) {
4417
- switch (true) {
4418
- case ModelFqnExpr.isElementKindExpr(expr):
4419
- case ModelFqnExpr.isElementTagExpr(expr): {
4420
- const isElement = elementExprToPredicate(expr);
4421
- return (connection) => isElement(connection.target);
4422
- }
4423
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "children"): {
4424
- const fqn = FqnRef.flatten(expr.ref);
4425
- return t$g(
4426
- [...model.children(fqn)].map(
4427
- (el) => Connection.isIncoming(el.id)
4428
- )
4429
- );
4430
- }
4431
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "descendants"): {
4432
- const fqn = FqnRef.flatten(expr.ref);
4433
- return t$g([
4434
- Connection.isInside(fqn),
4435
- ...[...model.children(fqn)].map(
4436
- (el) => Connection.isIncoming(el.id)
4437
- )
4438
- ]);
4439
- }
4440
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded"): {
4441
- const fqn = FqnRef.flatten(expr.ref);
4442
- return t$g([
4443
- Connection.isIncoming(fqn),
4444
- Connection.isInside(fqn)
4445
- ]);
4446
- }
4447
- case ModelFqnExpr.isModelRef(expr): {
4448
- const fqn = FqnRef.flatten(expr.ref);
4449
- return Connection.isIncoming(fqn);
4450
- }
4451
- default:
4452
- nonexhaustive(expr);
4453
- }
4454
- }
4455
-
4456
- const InOutRelationPredicate = {
4457
- include: ({ expr: { inout }, scope, model, memory, stage, filterWhere }) => {
4458
- const connections = [];
4459
- if (ModelFqnExpr.isWildcard(inout)) {
4460
- if (!scope) {
4461
- return;
4462
- }
4463
- connections.push(
4464
- ...findConnectionsBetween(
4465
- scope,
4466
- scope.ascendingSiblings()
4467
- )
4468
- );
4469
- } else {
4470
- const elements = resolveAndIncludeFromMemory(inout, { memory, model });
4471
- let visibleElements = [...memory.elements];
4472
- if (visibleElements.length === 0) {
4473
- visibleElements = n$e(
4474
- elements.flatMap((el) => toArray(el.ascendingSiblings()))
4475
- );
4476
- }
4477
- for (const el of elements) {
4478
- connections.push(
4479
- ...findConnectionsBetween(
4480
- el,
4481
- visibleElements
4482
- )
4483
- );
4484
- }
4485
- }
4486
- stage.addConnections(
4487
- filterWhere(connections)
4488
- );
4489
- return stage;
4490
- },
4491
- exclude: ({ expr: { inout }, model, scope, stage, where }) => {
4492
- const excluded = [];
4493
- if (ModelFqnExpr.isWildcard(inout)) {
4494
- if (!scope) {
4495
- return;
4496
- }
4497
- excluded.push(...scope.allOutgoing);
4498
- excluded.push(...scope.allIncoming);
4499
- } else {
4500
- const elements = resolveElements(model, inout);
4501
- excluded.push(
4502
- ...elements.flatMap((e) => [...e.allOutgoing, ...e.allIncoming])
4503
- );
4504
- }
4505
- stage.excludeRelations(toSet(excluded.filter(where)));
4506
- return stage;
4507
- }
4508
- };
4509
-
4510
- const OutgoingExprPredicate = {
4511
- include: ({ expr, scope, model, memory, stage, filterWhere }) => {
4512
- const target = expr.outgoing;
4513
- const connections = [];
4514
- if (ModelFqnExpr.isWildcard(target)) {
4515
- if (!scope) {
4516
- return;
4517
- }
4518
- connections.push(
4519
- ...findConnectionsBetween(
4520
- scope,
4521
- scope.ascendingSiblings(),
4522
- "directed"
4523
- )
4524
- );
4525
- } else {
4526
- const elements = resolveAndIncludeFromMemory(target, { memory, model });
4527
- const visibleElements = [...memory.elements];
4528
- if (visibleElements.length === 0) {
4529
- visibleElements.push(
4530
- ...n$e(
4531
- elements.flatMap((el) => [...el.ascendingSiblings()])
4532
- )
4533
- );
4534
- }
4535
- const ensureOutgoing = outgoingConnectionPredicate(model, target);
4536
- for (const source of elements) {
4537
- connections.push(
4538
- ...findConnectionsBetween(
4539
- source,
4540
- visibleElements,
4541
- "directed"
4542
- ).filter(ensureOutgoing)
4543
- );
4544
- }
4545
- }
4546
- stage.addConnections(
4547
- filterWhere(connections)
4548
- );
4549
- return stage;
4550
- },
4551
- exclude: ({ expr: { outgoing }, model, scope, stage, where }) => {
4552
- const excluded = [];
4553
- if (ModelFqnExpr.isWildcard(outgoing)) {
4554
- if (!scope) {
4555
- return;
4556
- }
4557
- excluded.push(...scope.allOutgoing);
4558
- } else {
4559
- const elements = resolveElements(model, outgoing);
4560
- excluded.push(
4561
- ...elements.flatMap((e) => [...e.allOutgoing])
4562
- );
4563
- }
4564
- stage.excludeRelations(
4565
- toSet(excluded.filter(where))
4566
- );
4567
- return stage;
4568
- }
4569
- };
4570
- function outgoingConnectionPredicate(model, expr) {
4571
- switch (true) {
4572
- case ModelFqnExpr.isElementKindExpr(expr):
4573
- case ModelFqnExpr.isElementTagExpr(expr): {
4574
- const isElement = elementExprToPredicate(expr);
4575
- return (connection) => isElement(connection.source);
4576
- }
4577
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "children"): {
4578
- const fqn = FqnRef.flatten(expr.ref);
4579
- return t$g(
4580
- [...model.children(fqn)].map(
4581
- (el) => Connection.isOutgoing(el.id)
4582
- )
4583
- );
4584
- }
4585
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "descendants"): {
4586
- const fqn = FqnRef.flatten(expr.ref);
4587
- return t$g([
4588
- Connection.isInside(fqn),
4589
- ...[...model.children(fqn)].map(
4590
- (el) => Connection.isOutgoing(el.id)
4591
- )
4592
- ]);
4593
- }
4594
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded"): {
4595
- const fqn = FqnRef.flatten(expr.ref);
4596
- return t$g([
4597
- Connection.isOutgoing(fqn),
4598
- Connection.isInside(fqn)
4599
- ]);
4600
- }
4601
- case ModelFqnExpr.isModelRef(expr): {
4602
- const fqn = FqnRef.flatten(expr.ref);
4603
- return Connection.isOutgoing(fqn);
4604
- }
4605
- default:
4606
- nonexhaustive(expr);
4607
- }
4608
- }
4609
-
4610
- const WildcardPredicate = {
4611
- include: ({ scope, model, stage, memory, where }) => {
4612
- if (!scope) {
4613
- const rootElements = [...model.roots()].filter(where);
4614
- if (rootElements.length === 0) {
4615
- return;
4616
- }
4617
- const [projectElements, importedElements] = t$4(rootElements, (e) => !e.imported);
4618
- stage.addExplicit(projectElements);
4619
- stage.addImplicit(importedElements);
4620
- stage.addConnections(findConnectionsWithin(rootElements));
4621
- stage.connectWithExisting(rootElements);
4622
- return stage;
4623
- }
4624
- const root = where(scope) ? scope : null;
4625
- const children = toArray(ifilter(scope.children(), where));
4626
- const hasChildren = children.length > 0;
4627
- if (!hasChildren) {
4628
- if (!root) {
4629
- return stage;
4630
- } else {
4631
- const edgesWithSiblings = findConnectionsBetween(root, root.siblings());
4632
- if (edgesWithSiblings.length === 0) {
4633
- const parent = root.parent;
4634
- if (parent && where(parent)) {
4635
- stage.addExplicit(parent);
4636
- }
4637
- }
4638
- children.push(root);
4639
- }
4640
- }
4641
- if (root) {
4642
- stage.addExplicit(root);
4643
- }
4644
- const neighbours = toSet([
4645
- ...memory.elements,
4646
- ...scope.descendingSiblings()
4647
- ]);
4648
- for (const neighbour of neighbours) {
4649
- stage.addConnections(findConnectionsBetween(neighbour, children, "directed"));
4650
- }
4651
- if (hasChildren) {
4652
- stage.addConnections(findConnectionsWithin(children));
4653
- stage.addExplicit(children);
4654
- }
4655
- for (const child of children) {
4656
- stage.addConnections(findConnectionsBetween(child, neighbours, "directed"));
4657
- }
4658
- return stage;
4659
- },
4660
- exclude: ({ scope, memory, stage, where }) => {
4661
- if (where !== NoWhere) {
4662
- stage.exclude(
4663
- n$d(
4664
- [...memory.elements],
4665
- where
4666
- )
4667
- );
4668
- return stage;
4669
- }
4670
- if (scope) {
4671
- stage.exclude([scope, ...scope.descendants()]);
4672
- return stage;
4673
- }
4674
- return Memory.empty(memory.scope).stageExclude(stage.expression);
4675
- }
4676
- };
4677
-
4678
- function processElementPredicate(expr, op, ctx) {
4679
- switch (true) {
4680
- case ModelFqnExpr.isCustom(expr): {
4681
- if (op === "include") {
4682
- return processElementPredicate(expr.custom.expr, op, ctx);
4683
- }
4684
- return ctx.stage;
4685
- }
4686
- case ModelFqnExpr.isWhere(expr): {
4687
- const where = whereOperatorAsPredicate(expr.where.condition);
4688
- const filterWhere = (elements) => {
4689
- return n$d(elements, where);
4690
- };
4691
- return processElementPredicate(expr.where.expr, op, { ...ctx, where, filterWhere });
4692
- }
4693
- case (ModelFqnExpr.isModelRef(expr) && expr.selector === "expanded"): {
4694
- return ExpandedElementPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4695
- }
4696
- case ModelFqnExpr.isWildcard(expr): {
4697
- return WildcardPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4698
- }
4699
- case ModelFqnExpr.isElementKindExpr(expr):
4700
- case ModelFqnExpr.isElementTagExpr(expr): {
4701
- return ElementKindOrTagPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4702
- }
4703
- case ModelFqnExpr.isModelRef(expr): {
4704
- return ElementRefPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4705
- }
4706
- default:
4707
- nonexhaustive(expr);
4708
- }
4709
- }
4710
- function processRelationtPredicate(expr, op, ctx) {
4711
- switch (true) {
4712
- case ModelRelationExpr.isCustom(expr): {
4713
- if (op === "include") {
4714
- return processRelationtPredicate(expr.customRelation.expr, op, ctx);
4715
- }
4716
- return ctx.stage;
4717
- }
4718
- case ModelRelationExpr.isWhere(expr): {
4719
- const where = whereOperatorAsPredicate(expr.where.condition);
4720
- const filterRelations = (relations) => {
4721
- return new Set(n$d([...relations], where));
4722
- };
4723
- const filterWhere = (connections) => {
4724
- return t$d(
4725
- connections,
4726
- t$e((c) => new ConnectionModel(c.source, c.target, filterRelations(c.relations))),
4727
- n$d((c) => c.nonEmpty())
4728
- );
4729
- };
4730
- return processRelationtPredicate(expr.where.expr, op, {
4731
- ...ctx,
4732
- where,
4733
- filterWhere
4734
- });
4735
- }
4736
- case ModelRelationExpr.isInOut(expr): {
4737
- return InOutRelationPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4738
- }
4739
- case ModelRelationExpr.isDirect(expr): {
4740
- return DirectRelationExprPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4741
- }
4742
- case ModelRelationExpr.isOutgoing(expr): {
4743
- return OutgoingExprPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4744
- }
4745
- case ModelRelationExpr.isIncoming(expr): {
4746
- return IncomingExprPredicate[op]({ ...ctx, expr }) ?? ctx.stage;
4747
- }
4748
- default:
4749
- nonexhaustive(expr);
4750
- }
4751
- }
4752
- function process_predicates(model, memory, rules) {
4753
- const ctx = {
4754
- model,
4755
- scope: memory.scope,
4756
- where: NoWhere,
4757
- filterWhere: NoFilter
4758
- };
4759
- for (const rule of rules) {
4760
- if (isViewRuleGroup(rule)) {
4761
- const groupMemory = ActiveGroupMemory.enter(memory, rule);
4762
- memory = process_predicates(model, groupMemory, rule.groupRules);
4763
- invariant(memory instanceof ActiveGroupMemory, "processPredicates must return ActiveGroupMemory");
4764
- memory = memory.leave();
4765
- continue;
4766
- }
4767
- if (isViewRulePredicate(rule)) {
4768
- const op = "include" in rule ? "include" : "exclude";
4769
- const exprs = rule.include ?? rule.exclude;
4770
- for (const expr of exprs) {
4771
- let stage = op === "include" ? memory.stageInclude(expr) : memory.stageExclude(expr);
4772
- switch (true) {
4773
- case ModelExpression.isFqnExpr(expr):
4774
- stage = processElementPredicate(expr, op, {
4775
- ...ctx,
4776
- stage,
4777
- memory
4778
- }) ?? stage;
4779
- break;
4780
- case ModelExpression.isRelationExpr(expr):
4781
- stage = processRelationtPredicate(expr, op, {
4782
- ...ctx,
4783
- stage,
4784
- memory
4785
- }) ?? stage;
4786
- break;
4787
- default:
4788
- nonexhaustive(expr);
4789
- }
4790
- memory = stage.commit();
4791
- }
4792
- }
4793
- }
4794
- return memory;
4795
- }
4796
- function processPredicates(model, memory, rules) {
4797
- memory = process_predicates(model, memory, rules);
4798
- return StageFinal.for(memory).commit();
4799
- }
4800
- function computeElementView(likec4model, {
4801
- docUri: _docUri,
4802
- // exclude docUri
4803
- rules: _rules,
4804
- // exclude rules
4805
- ...view
4806
- }) {
4807
- const rules = resolveGlobalRulesInElementView(
4808
- _rules,
4809
- likec4model.globals
4810
- );
4811
- const scope = view.viewOf ? likec4model.asComputed.element(view.viewOf) : null;
4812
- let memory = processPredicates(
4813
- likec4model,
4814
- Memory.empty(scope),
4815
- rules
4816
- );
4817
- if (memory.isEmpty() && scope) {
4818
- memory = memory.update({
4819
- final: /* @__PURE__ */ new Set([scope])
4820
- });
4821
- }
4822
- memory = assignElementsToGroups(memory);
4823
- const nodesMap = buildNodes(likec4model, memory);
4824
- const computedEdges = toComputedEdges(memory.connections);
4825
- linkNodesWithEdges(nodesMap, computedEdges);
4826
- const sorted = topologicalSort({
4827
- nodes: nodesMap,
4828
- edges: computedEdges
4829
- });
4830
- const nodes = applyCustomElementProperties(
4831
- rules,
4832
- applyViewRuleStyles(
4833
- rules,
4834
- sorted.nodes
4835
- )
4836
- );
4837
- const autoLayoutRule = t$8(rules, isViewRuleAutoLayout);
4838
- const nodeNotations = buildElementNotations(nodes);
4839
- const ranks = collectRankConstraints(rules, nodes);
4840
- return calcViewLayoutHash({
4841
- ...view,
4842
- _stage: "computed",
4843
- autoLayout: {
4844
- direction: autoLayoutRule?.direction ?? "TB",
4845
- ...autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep },
4846
- ...autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep }
4847
- },
4848
- edges: applyCustomRelationProperties(rules, nodes, sorted.edges),
4849
- nodes: t$e(nodes, (n) => {
4850
- if (n.icon === "none") {
4851
- delete n.icon;
4852
- }
4853
- return n;
4854
- }),
4855
- ...nodeNotations.length > 0 && {
4856
- notation: {
4857
- nodes: nodeNotations
4858
- }
4859
- },
4860
- ...ranks.length > 0 && { ranks }
4861
- });
4862
- }
4863
- function collectRankConstraints(rules, nodes) {
4864
- const constraints = [];
4865
- for (const rule of rules) {
4866
- if (!isViewRuleRank(rule) || rule.targets.length === 0) {
4867
- continue;
4868
- }
4869
- const isTargeted = t$g(rule.targets.map(elementExprToPredicate));
4870
- const nodesInRank = t$d(
4871
- nodes,
4872
- n$d(isTargeted),
4873
- t$e((n) => n.id)
4874
- );
4875
- if (!t$b(nodesInRank, 1)) {
4876
- continue;
4877
- }
4878
- constraints.push({
4879
- type: rule.rank,
4880
- nodes: nodesInRank
4881
- });
4882
- }
4883
- return constraints;
4884
- }
4885
- function assignElementsToGroups(memory) {
4886
- if (memory.groups.length === 0) {
4887
- return memory;
4888
- }
4889
- const groupAssignments = new DefaultMap(() => /* @__PURE__ */ new Set());
4890
- const assignedTo = /* @__PURE__ */ new Map();
4891
- const isAncestorAssigned = (el) => {
4892
- for (const parent of el.ancestors()) {
4893
- const groupId = assignedTo.get(parent);
4894
- if (groupId) {
4895
- assignedTo.set(el, groupId);
4896
- groupAssignments.get(groupId).add(el);
4897
- return true;
4898
- }
4899
- }
4900
- return false;
4901
- };
4902
- const isDescendantAssigned = (el) => {
4903
- for (const descendant of el.descendants("asc")) {
4904
- const groupId = assignedTo.get(descendant);
4905
- if (groupId) {
4906
- assignedTo.set(el, groupId);
4907
- groupAssignments.get(groupId).add(el);
4908
- return true;
4909
- }
4910
- }
4911
- return false;
4912
- };
4913
- t$d(
4914
- sortParentsFirst([...memory.explicitFirstSeenIn.keys()]),
4915
- t$7((el) => {
4916
- if (!isAncestorAssigned(el)) {
4917
- const groupId = nonNullable(memory.explicitFirstSeenIn.get(el));
4918
- assignedTo.set(el, groupId);
4919
- groupAssignments.get(groupId).add(el);
4920
- }
4921
- })
4922
- );
4923
- t$d(
4924
- sortParentsFirst([...memory.lastSeenIn.keys()]),
4925
- n$d((el) => !assignedTo.has(el)),
4926
- t$7((el) => {
4927
- if (isAncestorAssigned(el)) {
4928
- return;
4929
- }
4930
- if (isDescendantAssigned(el)) {
4931
- return;
4932
- }
4933
- const groupId = nonNullable(memory.lastSeenIn.get(el));
4934
- assignedTo.set(el, groupId);
4935
- groupAssignments.get(groupId).add(el);
4936
- })
4937
- );
4938
- if (groupAssignments.size === 0) {
4939
- return memory;
4940
- }
4941
- let groups = memory.groups.map((group) => {
4942
- const explicits = groupAssignments.get(group.id);
4943
- if (!explicits) {
4944
- return group;
4945
- }
4946
- return group.update(explicits);
4947
- });
4948
- return memory.update({ groups });
4949
- }
4950
-
4951
- function unsafeComputeView(viewsource, likec4model) {
4952
- switch (true) {
4953
- case isElementView(viewsource):
4954
- return computeElementView(likec4model, viewsource);
4955
- case isDeploymentView(viewsource):
4956
- return computeDeploymentView(likec4model, viewsource);
4957
- case isDynamicView(viewsource):
4958
- return computeDynamicView(likec4model, viewsource);
4959
- default:
4960
- nonexhaustive(viewsource);
4961
- }
4962
- }
4963
- function computeView(viewsource, likec4model) {
4964
- try {
4965
- return {
4966
- isSuccess: true,
4967
- view: unsafeComputeView(viewsource, likec4model)
4968
- };
4969
- } catch (e) {
4970
- return {
4971
- isSuccess: false,
4972
- error: e instanceof Error ? e : new Error(`Unknown error: ${e}`),
4973
- view: void 0
4974
- };
4975
- }
4976
- }
4977
- function computeParsedModelData(parsed) {
4978
- const likec4model = LikeC4Model.create(parsed);
4979
- let {
4980
- views: _views,
4981
- _stage: __omitted,
4982
- ...rest
4983
- } = parsed;
4984
- const views = t$q(_views, (v) => unsafeComputeView(v, likec4model));
4985
- return {
4986
- [_stage]: "computed",
4987
- ...rest,
4988
- views
4989
- };
4990
- }
4991
- function computeLikeC4Model(parsed) {
4992
- return LikeC4Model.create(computeParsedModelData(parsed));
4993
- }
4994
-
4995
- export { t$6 as a, t$5 as b, topologicalSort as c, computeLikeC4Model as d, computeParsedModelData as e, computeView as f, linkNodesWithEdges as l, n$6 as n, topologicalSortExports as t, unsafeComputeView as u, willCreateCycle as w };