@likec4/core 1.18.0 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +1 -1
  2. package/dist/builder/index.d.mts +502 -0
  3. package/dist/builder/index.d.ts +502 -0
  4. package/dist/builder/index.js +871 -0
  5. package/dist/compute-view/index.d.mts +9 -78
  6. package/dist/compute-view/index.d.ts +9 -78
  7. package/dist/compute-view/index.js +78 -0
  8. package/dist/index.d.mts +9 -730
  9. package/dist/index.d.ts +9 -730
  10. package/dist/{index.mjs → index.js} +7 -784
  11. package/dist/model/index.d.mts +218 -606
  12. package/dist/model/index.d.ts +218 -606
  13. package/dist/model/index.js +1 -0
  14. package/dist/shared/chunk-RAAYCPUM.M-JWF7SS.js +21 -0
  15. package/dist/shared/core.BIfgabEw.d.ts +719 -0
  16. package/dist/shared/core.BZ9Msq7w.d.mts +719 -0
  17. package/dist/shared/{core.DMYY7C8s.d.mts → core.C05RDLhi.d.ts} +179 -230
  18. package/dist/shared/{core.DMYY7C8s.d.ts → core.CmYMqgha.d.mts} +179 -230
  19. package/dist/shared/core.D6-fWbM3.d.ts +127 -0
  20. package/dist/shared/core.D74xkKkG.d.mts +148 -0
  21. package/dist/shared/core.D74xkKkG.d.ts +148 -0
  22. package/dist/shared/core.sLaWHBjR.d.mts +127 -0
  23. package/dist/shared/index.DafVOuVd.js +7443 -0
  24. package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
  25. package/dist/shared/view.CyZrG8BJ.js +354 -0
  26. package/dist/types/index.d.mts +4 -2
  27. package/dist/types/index.d.ts +4 -2
  28. package/dist/types/index.js +20 -0
  29. package/dist/utils/index.d.mts +419 -0
  30. package/dist/utils/index.d.ts +419 -0
  31. package/dist/utils/index.js +347 -0
  32. package/package.json +47 -33
  33. package/src/builder/Builder-style1.test-d.ts +190 -0
  34. package/src/builder/Builder-style2.test-d.ts +175 -0
  35. package/src/builder/Builder.deployment.ts +25 -20
  36. package/src/builder/Builder.deploymentModel.ts +80 -55
  37. package/src/builder/Builder.element.ts +2 -0
  38. package/src/builder/Builder.model.ts +57 -43
  39. package/src/builder/Builder.ts +412 -431
  40. package/src/builder/Builder.view-common.ts +234 -0
  41. package/src/builder/Builder.view-deployment.ts +135 -0
  42. package/src/builder/Builder.view-element.ts +189 -0
  43. package/src/builder/Builder.views.ts +109 -33
  44. package/src/builder/Builder.with.ts +475 -0
  45. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +374 -0
  46. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +183 -0
  47. package/src/builder/__snapshots__/Builder.spec.ts.snap +374 -0
  48. package/src/builder/_types.ts +28 -5
  49. package/src/builder/index.ts +10 -4
  50. package/src/colors/index.ts +2 -2
  51. package/src/compute-view/compute-view.ts +45 -54
  52. package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
  53. package/src/compute-view/deployment-view/__test__/fixture.ts +50 -62
  54. package/src/compute-view/deployment-view/_types.ts +26 -18
  55. package/src/compute-view/deployment-view/clean-connections.ts +173 -164
  56. package/src/compute-view/deployment-view/compute.ts +51 -37
  57. package/src/compute-view/deployment-view/memory/index.ts +9 -0
  58. package/src/compute-view/deployment-view/memory/memory.ts +97 -0
  59. package/src/compute-view/deployment-view/predicates/elements.ts +144 -0
  60. package/src/compute-view/deployment-view/predicates/relation-direct.ts +183 -76
  61. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +38 -20
  62. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +72 -23
  63. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +61 -22
  64. package/src/compute-view/deployment-view/predicates/wildcard.ts +15 -15
  65. package/src/compute-view/deployment-view/stages/stage-exclude.ts +5 -0
  66. package/src/compute-view/deployment-view/stages/stage-final.ts +245 -0
  67. package/src/compute-view/deployment-view/stages/stage-include.ts +95 -0
  68. package/src/compute-view/deployment-view/utils.ts +95 -31
  69. package/src/compute-view/dynamic-view/__test__/fixture.ts +4 -4
  70. package/src/compute-view/dynamic-view/compute.ts +59 -45
  71. package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
  72. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +64 -62
  73. package/src/compute-view/element-view/__test__/fixture.ts +147 -117
  74. package/src/compute-view/element-view/_types.ts +48 -0
  75. package/src/compute-view/element-view/clean-connections.ts +113 -0
  76. package/src/compute-view/element-view/compute.ts +264 -683
  77. package/src/compute-view/element-view/memory/NodeGroup.ts +31 -0
  78. package/src/compute-view/element-view/memory/index.ts +10 -0
  79. package/src/compute-view/element-view/memory/memory.ts +177 -0
  80. package/src/compute-view/element-view/memory/stage-exclude.ts +59 -0
  81. package/src/compute-view/element-view/memory/stage-final.ts +129 -0
  82. package/src/compute-view/element-view/memory/stage-include.ts +128 -0
  83. package/src/compute-view/element-view/predicates/_utils.ts +86 -0
  84. package/src/compute-view/element-view/predicates/element-expand.ts +33 -0
  85. package/src/compute-view/element-view/predicates/element-kind-tag.ts +26 -0
  86. package/src/compute-view/element-view/predicates/element-ref.ts +37 -0
  87. package/src/compute-view/element-view/predicates/relation-direct.ts +309 -0
  88. package/src/compute-view/element-view/predicates/relation-in-out.ts +66 -0
  89. package/src/compute-view/element-view/predicates/relation-in.ts +118 -0
  90. package/src/compute-view/element-view/predicates/relation-out.ts +116 -0
  91. package/src/compute-view/element-view/predicates/wildcard.ts +88 -0
  92. package/src/compute-view/element-view/utils.ts +59 -0
  93. package/src/compute-view/index.ts +3 -4
  94. package/src/compute-view/memory/AbstractMemory.ts +45 -0
  95. package/src/compute-view/memory/AbstractStageExclude.ts +216 -0
  96. package/src/compute-view/memory/AbstractStageInclude.ts +200 -0
  97. package/src/compute-view/memory/_types.ts +147 -0
  98. package/src/compute-view/memory/index.ts +5 -0
  99. package/src/compute-view/memory/ops.ts +43 -0
  100. package/src/compute-view/utils/buildComputedNodes.ts +4 -4
  101. package/src/compute-view/utils/elementExpressionToPredicate.ts +1 -3
  102. package/src/compute-view/utils/link-nodes-with-edges.ts +3 -7
  103. package/src/compute-view/utils/{derive-edge-props-from-relationships.ts → merge-props-from-relationships.ts} +54 -23
  104. package/src/compute-view/utils/relationExpressionToPredicates.ts +2 -2
  105. package/src/compute-view/utils/resolve-extended-views.ts +44 -40
  106. package/src/compute-view/utils/resolve-global-rules.ts +6 -6
  107. package/src/compute-view/utils/topological-sort.ts +167 -71
  108. package/src/compute-view/utils/with-readable-edges.ts +14 -9
  109. package/src/index.ts +22 -16
  110. package/src/model/DeploymentElementModel.ts +150 -85
  111. package/src/model/DeploymentModel.ts +27 -21
  112. package/src/model/ElementModel.ts +51 -25
  113. package/src/model/LikeC4Model.test-d.ts +4 -3
  114. package/src/model/LikeC4Model.ts +98 -42
  115. package/src/model/RelationModel.ts +5 -4
  116. package/src/model/__test__/fixture.ts +5 -9
  117. package/src/model/connection/Connection.ts +72 -0
  118. package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
  119. package/src/model/connection/{deployment.ts → deployment/find.ts} +14 -18
  120. package/src/model/connection/deployment/index.ts +8 -0
  121. package/src/model/connection/index.ts +22 -0
  122. package/src/model/connection/model/ConnectionModel.ts +157 -0
  123. package/src/model/connection/{model.ts → model/find.ts} +43 -49
  124. package/src/model/connection/model/index.ts +8 -0
  125. package/src/model/connection/ops.ts +274 -0
  126. package/src/model/guards.ts +9 -0
  127. package/src/model/index.ts +45 -3
  128. package/src/model/types.ts +35 -18
  129. package/src/model/view/EdgeModel.ts +6 -6
  130. package/src/model/view/LikeC4ViewModel.ts +14 -8
  131. package/src/model/view/NodeModel.ts +6 -5
  132. package/src/types/_common.ts +53 -1
  133. package/src/types/deployments.ts +88 -156
  134. package/src/types/element.ts +2 -2
  135. package/src/types/expression-v2.ts +172 -0
  136. package/src/types/expression.ts +9 -5
  137. package/src/types/global.ts +3 -3
  138. package/src/types/index.ts +220 -13
  139. package/src/types/model.ts +28 -24
  140. package/src/types/operators.ts +1 -1
  141. package/src/types/relation.ts +14 -10
  142. package/src/types/theme.ts +0 -1
  143. package/src/types/view.ts +20 -18
  144. package/src/utils/const.ts +1 -0
  145. package/src/utils/fqn.ts +140 -49
  146. package/src/utils/getOrCreate.ts +1 -1
  147. package/src/utils/index.ts +75 -9
  148. package/src/utils/iterable/_types.ts +5 -0
  149. package/src/utils/iterable/filter.ts +55 -0
  150. package/src/utils/iterable/find.ts +36 -0
  151. package/src/utils/iterable/flat.ts +17 -0
  152. package/src/utils/iterable/index.ts +13 -0
  153. package/src/utils/iterable/map.ts +40 -0
  154. package/src/utils/iterable/reduce.ts +24 -0
  155. package/src/utils/iterable/some.ts +36 -0
  156. package/src/utils/iterable/to.ts +19 -0
  157. package/src/utils/iterable/unique.ts +29 -0
  158. package/src/utils/relations.ts +3 -64
  159. package/src/utils/set.ts +11 -9
  160. package/src/utils/string-hash.ts +1 -1
  161. package/dist/compute-view/index.mjs +0 -79
  162. package/dist/model/index.mjs +0 -2
  163. package/dist/shared/core.BBgiAAv1.mjs +0 -144
  164. package/dist/shared/core.BPyJvuMU.mjs +0 -2420
  165. package/dist/shared/core.BQ4AbfvB.mjs +0 -9228
  166. package/dist/shared/core.k12s_keD.mjs +0 -203
  167. package/dist/types/index.mjs +0 -21
  168. package/src/builder/Builder.test-d.ts +0 -124
  169. package/src/builder/Builder.view.ts +0 -543
  170. package/src/compute-view/LikeC4ModelGraph.ts +0 -330
  171. package/src/compute-view/deployment-view/Memory.ts +0 -108
  172. package/src/compute-view/deployment-view/Stage.ts +0 -145
  173. package/src/compute-view/deployment-view/predicates/deployment-ref.ts +0 -146
  174. package/src/compute-view/element-view/predicates.ts +0 -517
  175. package/src/compute-view/utils/sortNodes.ts +0 -101
  176. package/src/model/connection/ConnectionModel.ts +0 -94
  177. package/src/model/connection/DeploymentConnectionModel.ts +0 -99
@@ -1,35 +1,35 @@
1
- import { hasAtLeast, isEmpty } from 'remeda'
1
+ import { hasAtLeast, isEmpty, isNumber, isString } from 'remeda'
2
2
  import { invariant, nonexhaustive } from '../../errors'
3
3
  import type { LikeC4DeploymentModel } from '../../model'
4
4
  import type { DeploymentConnectionModel } from '../../model/connection/deployment'
5
+ import type { ElementModel } from '../../model/ElementModel'
5
6
  import type { AnyAux } from '../../model/types'
6
7
  import {
7
8
  type ComputedEdge,
8
9
  type ComputedNode,
9
10
  DefaultArrowType,
10
- DeploymentElementExpression,
11
11
  type DeploymentNodeKind,
12
12
  type DeploymentViewRule,
13
13
  type Fqn,
14
+ FqnExpr,
14
15
  isViewRuleStyle,
15
16
  type NonEmptyArray,
16
- type Tag
17
+ type Tag,
17
18
  } from '../../types'
18
19
  import { nameFromFqn, parentFqn } from '../../utils'
19
20
  import { applyViewRuleStyle } from '../utils/applyViewRuleStyles'
20
21
  import { buildComputedNodes, type ComputedNodeSource } from '../utils/buildComputedNodes'
21
- import { deriveEdgePropsFromRelationships } from '../utils/derive-edge-props-from-relationships'
22
+ import { mergePropsFromRelationships } from '../utils/merge-props-from-relationships'
22
23
  import { uniqueTags } from '../utils/uniqueTags'
23
- import type { Elem } from './_types'
24
- import { type Memory, MutableMemory } from './Memory'
24
+ import type { Elem, Memory } from './_types'
25
25
 
26
26
  type Predicate<T> = (x: T) => boolean
27
27
 
28
28
  export function resolveElements(
29
29
  model: LikeC4DeploymentModel,
30
- expr: DeploymentElementExpression.Ref
31
- ) {
32
- const ref = model.element(expr.ref)
30
+ expr: FqnExpr.DeploymentRef,
31
+ ): Elem[] {
32
+ const ref = model.element(expr.ref.deployment)
33
33
  if (ref.isDeploymentNode()) {
34
34
  if (expr.selector === 'children') {
35
35
  return [...ref.children()]
@@ -44,14 +44,31 @@ export function resolveElements(
44
44
  return [ref]
45
45
  }
46
46
 
47
- export function deploymentExpressionToPredicate<T extends { id: string }>(
48
- target: DeploymentElementExpression
47
+ export function resolveModelElements(
48
+ model: LikeC4DeploymentModel,
49
+ expr: FqnExpr.ModelRef,
50
+ ): ElementModel[] {
51
+ const ref = model.$model.element(expr.ref.model)
52
+ if (expr.selector === 'children') {
53
+ return [...ref.children()]
54
+ }
55
+ if (expr.selector === 'expanded') {
56
+ return [ref, ...ref.children()]
57
+ }
58
+ if (expr.selector === 'descendants') {
59
+ return [...ref.descendants()]
60
+ }
61
+ return [ref]
62
+ }
63
+
64
+ export function deploymentExpressionToPredicate<T extends { id: string; modelRef?: number | string }>(
65
+ target: FqnExpr,
49
66
  ): Predicate<T> {
50
- if (DeploymentElementExpression.isWildcard(target)) {
67
+ if (FqnExpr.isWildcard(target)) {
51
68
  return () => true
52
69
  }
53
- if (DeploymentElementExpression.isRef(target)) {
54
- const fqn = target.ref.id
70
+ if (FqnExpr.isDeploymentRef(target)) {
71
+ const fqn = target.ref.deployment
55
72
  if (target.selector === 'expanded') {
56
73
  const fqnWithDot = fqn + '.'
57
74
  return n => n.id === fqn || n.id.startsWith(fqnWithDot)
@@ -65,6 +82,55 @@ export function deploymentExpressionToPredicate<T extends { id: string }>(
65
82
  }
66
83
  return n => n.id === fqn
67
84
  }
85
+ if (FqnExpr.isModelRef(target)) {
86
+ const modelFqn = (node: T) => {
87
+ if (isString(node.modelRef)) {
88
+ return node.modelRef
89
+ }
90
+ if (isNumber(node.modelRef)) {
91
+ return node.id
92
+ }
93
+ return null
94
+ }
95
+
96
+ const fqn = target.ref.model
97
+ if (target.selector === 'expanded') {
98
+ const fqnWithDot = fqn + '.'
99
+ return (n) => {
100
+ const m = modelFqn(n)
101
+ if (!m) {
102
+ return true
103
+ }
104
+ return m === fqn || m.startsWith(fqnWithDot)
105
+ }
106
+ }
107
+ if (target.selector === 'descendants') {
108
+ const fqnWithDot = fqn + '.'
109
+ return (n) => {
110
+ const m = modelFqn(n)
111
+ if (!m) {
112
+ return true
113
+ }
114
+ return m.startsWith(fqnWithDot)
115
+ }
116
+ }
117
+ if (target.selector === 'children') {
118
+ return (n) => {
119
+ const m = modelFqn(n)
120
+ if (!m) {
121
+ return true
122
+ }
123
+ return parentFqn(m) === fqn
124
+ }
125
+ }
126
+ return (n) => {
127
+ const m = modelFqn(n)
128
+ if (!m) {
129
+ return true
130
+ }
131
+ return m === fqn
132
+ }
133
+ }
68
134
  nonexhaustive(target)
69
135
  }
70
136
 
@@ -82,7 +148,7 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
82
148
  return {
83
149
  ...(onlyOneInstance && {
84
150
  ...toNodeSource(onlyOneInstance),
85
- modelRef: onlyOneInstance.$element.id
151
+ modelRef: onlyOneInstance.element.id,
86
152
  }),
87
153
  title,
88
154
  ...$node,
@@ -90,16 +156,16 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
90
156
  ...(color && { color }),
91
157
  ...(shape && { shape }),
92
158
  style: {
93
- ...style
159
+ ...style,
94
160
  },
95
161
  deploymentRef: 1,
96
162
  kind,
97
- id
163
+ id,
98
164
  }
99
165
  }
100
166
  invariant(el.isInstance(), 'Expected Instance')
101
167
  const instance = el.$instance
102
- const element = el.$element.$element
168
+ const element = el.element.$element
103
169
 
104
170
  const icon = instance.style?.icon ?? element.icon
105
171
  const color = instance.style?.color ?? element.color
@@ -107,12 +173,12 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
107
173
 
108
174
  const links = [
109
175
  ...(element.links ?? []),
110
- ...(instance.links ?? [])
176
+ ...(instance.links ?? []),
111
177
  ]
112
178
 
113
179
  const metadata = {
114
180
  ...element.metadata,
115
- ...instance.metadata
181
+ ...instance.metadata,
116
182
  }
117
183
 
118
184
  const notation = instance.notation ?? element.notation
@@ -130,24 +196,24 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
130
196
  ...shape && { shape },
131
197
  style: {
132
198
  ...element.style,
133
- ...instance.style
199
+ ...instance.style,
134
200
  },
135
201
  deploymentRef: el.id === instance.id ? 1 : instance.id,
136
202
  modelRef: el.id === element.id ? 1 : element.id,
137
203
  ...notation && { notation },
138
- ...!isEmpty(metadata) && ({ metadata })
204
+ ...!isEmpty(metadata) && ({ metadata }),
139
205
  }
140
206
  }
141
207
 
142
208
  export function toComputedEdges<M extends AnyAux>(
143
- connections: ReadonlyArray<DeploymentConnectionModel<M>>
209
+ connections: ReadonlyArray<DeploymentConnectionModel<M>>,
144
210
  ): ComputedEdge[] {
145
211
  return connections.reduce((acc, e) => {
146
212
  // const modelRelations = []
147
213
  // const deploymentRelations = []
148
214
  const relations = [
149
215
  ...e.relations.model,
150
- ...e.relations.deployment
216
+ ...e.relations.deployment,
151
217
  ]
152
218
  invariant(hasAtLeast(relations, 1), 'Edge must have at least one relation')
153
219
 
@@ -157,7 +223,7 @@ export function toComputedEdges<M extends AnyAux>(
157
223
  const {
158
224
  title,
159
225
  ...props
160
- } = deriveEdgePropsFromRelationships(relations.map(r => r.$relationship)) // || relations.find(r => r.source === source && r.target === target)
226
+ } = mergePropsFromRelationships(relations.map(r => r.$relationship)) // || relations.find(r => r.source === source && r.target === target)
161
227
 
162
228
  const edge: ComputedEdge = {
163
229
  id: e.id,
@@ -166,7 +232,7 @@ export function toComputedEdges<M extends AnyAux>(
166
232
  target,
167
233
  label: title ?? null,
168
234
  relations: relations.map((r) => r.id as M['RelationId']),
169
- ...props
235
+ ...props,
170
236
  }
171
237
 
172
238
  // If exists same edge but in opposite direction
@@ -192,15 +258,13 @@ export function toComputedEdges<M extends AnyAux>(
192
258
  }
193
259
 
194
260
  export function buildNodes(memory: Memory): ReadonlyMap<Fqn, ComputedNode> {
195
- // typecast to MutableMemory
196
- invariant(memory instanceof MutableMemory, 'Expected MutableMemory')
197
- return buildComputedNodes([...memory.finalElements].map(toNodeSource))
261
+ return buildComputedNodes([...memory.final].map(toNodeSource))
198
262
  }
199
263
 
200
264
  export function applyDeploymentViewRuleStyles(
201
265
  rules: DeploymentViewRule[],
202
- nodes: ComputedNode[]
203
- ) {
266
+ nodes: ComputedNode[],
267
+ ): ComputedNode[] {
204
268
  for (const rule of rules) {
205
269
  if (!isViewRuleStyle(rule) || rule.targets.length === 0) {
206
270
  continue
@@ -1,7 +1,7 @@
1
1
  import { partition } from 'remeda'
2
2
  import type { DynamicViewRule, DynamicViewStep, Fqn, ViewId, ViewRulePredicate } from '../../../types'
3
3
  import { type FakeElementIds, fakeModel } from '../../element-view/__test__/fixture'
4
- import { DynamicViewComputeCtx } from '../compute'
4
+ import { computeDynamicView } from '../compute'
5
5
 
6
6
  const emptyView = {
7
7
  __: 'dynamic' as const,
@@ -43,13 +43,13 @@ export function $step(expr: StepExpr, props?: string | Partial<StepProps>): Dyna
43
43
 
44
44
  export function compute(stepsAndRules: (DynamicViewStep | ViewRulePredicate)[]) {
45
45
  const [steps, rules] = partition(stepsAndRules, (s): s is DynamicViewStep => 'source' in s)
46
- const view = DynamicViewComputeCtx.compute(
46
+ let view = computeDynamicView(
47
+ fakeModel,
47
48
  {
48
49
  ...emptyView,
49
50
  steps,
50
51
  rules: rules as DynamicViewRule[]
51
- },
52
- fakeModel
52
+ }
53
53
  )
54
54
  return Object.assign(view, {
55
55
  nodeIds: view.nodes.map((node) => node.id) as string[],
@@ -1,5 +1,9 @@
1
- import { filter, findLast, flatMap, hasAtLeast, isTruthy, map, only, pipe, unique } from 'remeda'
1
+ import { filter, findLast, flatMap, hasAtLeast, isTruthy, map, only, pipe, reduce, unique } from 'remeda'
2
2
  import { nonNullable } from '../../errors'
3
+ import type { LikeC4Model } from '../../model'
4
+ import { findConnection } from '../../model/connection/model'
5
+ import type { ElementModel } from '../../model/ElementModel'
6
+ import type { AnyAux } from '../../model/types'
3
7
  import {
4
8
  type Color,
5
9
  type ComputedDynamicView,
@@ -9,7 +13,6 @@ import {
9
13
  DefaultRelationshipColor,
10
14
  type DynamicView,
11
15
  type DynamicViewStep,
12
- type Element,
13
16
  isDynamicViewParallelSteps,
14
17
  isViewRuleAutoLayout,
15
18
  isViewRulePredicate,
@@ -23,7 +26,6 @@ import {
23
26
  type ViewId
24
27
  } from '../../types'
25
28
  import { ancestorsFqn, commonAncestor, parentFqn } from '../../utils/fqn'
26
- import type { LikeC4ModelGraph } from '../LikeC4ModelGraph'
27
29
  import { applyCustomElementProperties } from '../utils/applyCustomElementProperties'
28
30
  import { applyViewRuleStyles } from '../utils/applyViewRuleStyles'
29
31
  import { buildComputedNodesFromElements } from '../utils/buildComputedNodes'
@@ -32,7 +34,9 @@ import { elementExprToPredicate } from '../utils/elementExpressionToPredicate'
32
34
  import { resolveGlobalRulesInDynamicView } from '../utils/resolve-global-rules'
33
35
  import { calcViewLayoutHash } from '../utils/view-hash'
34
36
 
35
- export namespace DynamicViewComputeCtx {
37
+ type Element = ElementModel
38
+
39
+ namespace DynamicViewCompute {
36
40
  export interface Step {
37
41
  id: StepEdgeId
38
42
  source: Element
@@ -51,18 +55,14 @@ export namespace DynamicViewComputeCtx {
51
55
  }
52
56
  }
53
57
 
54
- export class DynamicViewComputeCtx {
58
+ class DynamicViewCompute {
55
59
  // Intermediate state
56
60
  private explicits = new Set<Element>()
57
- private steps = [] as DynamicViewComputeCtx.Step[]
58
-
59
- public static compute(view: DynamicView, graph: LikeC4ModelGraph): ComputedDynamicView {
60
- return new DynamicViewComputeCtx(view, graph).compute()
61
- }
61
+ private steps = [] as DynamicViewCompute.Step[]
62
62
 
63
- private constructor(
64
- protected view: DynamicView,
65
- protected graph: LikeC4ModelGraph
63
+ constructor(
64
+ protected model: LikeC4Model,
65
+ protected view: DynamicView
66
66
  ) {}
67
67
 
68
68
  private addStep(
@@ -78,8 +78,8 @@ export class DynamicViewComputeCtx {
78
78
  parent?: number
79
79
  ) {
80
80
  const id = parent ? stepEdgeId(parent, index) : stepEdgeId(index)
81
- const source = this.graph.element(stepSource)
82
- const target = this.graph.element(stepTarget)
81
+ const source = this.model.element(stepSource)
82
+ const target = this.model.element(stepTarget)
83
83
 
84
84
  this.explicits.add(source)
85
85
  this.explicits.add(target)
@@ -116,7 +116,7 @@ export class DynamicViewComputeCtx {
116
116
  })
117
117
  }
118
118
 
119
- protected compute(): ComputedDynamicView {
119
+ compute(): ComputedDynamicView {
120
120
  const {
121
121
  docUri: _docUri, // exclude docUri
122
122
  rules: _rules, // exclude rules
@@ -141,18 +141,22 @@ export class DynamicViewComputeCtx {
141
141
  stepNum++
142
142
  }
143
143
 
144
- const rules = resolveGlobalRulesInDynamicView(this.view, this.graph.globals)
144
+ const rules = resolveGlobalRulesInDynamicView(_rules, this.model.globals())
145
145
 
146
146
  for (const rule of rules) {
147
147
  if (isViewRulePredicate(rule)) {
148
148
  for (const expr of rule.include) {
149
- const predicate = elementExprToPredicate(expr)
150
- this.graph.elements.filter(predicate).forEach(e => this.explicits.add(e))
149
+ const satisfies = elementExprToPredicate(expr)
150
+ for (const e of this.model.elements()) {
151
+ if (satisfies(e)) {
152
+ this.explicits.add(e)
153
+ }
154
+ }
151
155
  }
152
156
  }
153
157
  }
154
158
 
155
- const elements = [...this.explicits]
159
+ const elements = [...this.explicits].map(e => e.$element)
156
160
  const nodesMap = buildComputedNodesFromElements(elements)
157
161
 
158
162
  const edges = this.steps.map(({ source, target, relations, title, isBackward, ...step }) => {
@@ -243,7 +247,7 @@ export class DynamicViewComputeCtx {
243
247
  line: RelationshipLineType | null
244
248
  notation: string | null
245
249
  } {
246
- const relationships = unique(this.graph.edgesBetween(source, target).flatMap(e => e.relations))
250
+ const relationships = findConnection(source, target, 'directed').flatMap(r => [...r.relations])
247
251
  if (relationships.length === 0) {
248
252
  return {
249
253
  title: null,
@@ -267,44 +271,54 @@ export class DynamicViewComputeCtx {
267
271
  const relations = hasAtLeast(relationships, 1) ? map(relationships, r => r.id) : null
268
272
 
269
273
  // Most closest relation
270
- const relation = only(relationships) || relationships.find(r => r.source === source.id && r.target === target.id)
274
+ const relation = only(relationships) || relationships.find(r => r.source === source && r.target === target)
275
+ const relationNavigateTo = relation?.$relationship.navigateTo ?? null
271
276
 
272
- const navigateTo = !!relation?.navigateTo && relation.navigateTo !== this.view.id ? relation.navigateTo : pipe(
277
+ const navigateTo = relationNavigateTo && relationNavigateTo !== this.view.id ? relationNavigateTo : pipe(
273
278
  relationships,
274
- map(r => r.navigateTo),
279
+ map(r => r.$relationship.navigateTo),
275
280
  filter(isTruthy),
276
281
  filter(v => v !== this.view.id),
277
282
  unique(),
278
283
  only()
279
284
  )
280
285
 
281
- const commonProperties = relationships.reduce((acc, r) => {
282
- isTruthy(r.title) && acc.title.push(r.title)
283
- isTruthy(r.tail) && acc.tail.push(r.tail)
284
- isTruthy(r.head) && acc.head.push(r.head)
285
- isTruthy(r.color) && acc.color.push(r.color)
286
- isTruthy(r.line) && acc.line.push(r.line)
286
+ const commonProperties = pipe(
287
+ relationships,
288
+ reduce((acc, { title, $relationship: r }) => {
289
+ isTruthy(title) && acc.title.add(title)
290
+ isTruthy(r.tail) && acc.tail.add(r.tail)
291
+ isTruthy(r.head) && acc.head.add(r.head)
292
+ isTruthy(r.color) && acc.color.add(r.color)
293
+ isTruthy(r.line) && acc.line.add(r.line)
287
294
 
288
- return acc
289
- }, {
290
- title: [] as string[],
291
- tail: [] as RelationshipArrowType[],
292
- head: [] as RelationshipArrowType[],
293
- color: [] as Color[],
294
- line: [] as RelationshipLineType[],
295
- notation: [] as string[]
296
- })
295
+ return acc
296
+ }, {
297
+ tail: new Set<RelationshipArrowType>(),
298
+ head: new Set<RelationshipArrowType>(),
299
+ color: new Set<Color>(),
300
+ line: new Set<RelationshipLineType>(),
301
+ notation: new Set<string>(),
302
+ title: new Set<string>()
303
+ })
304
+ )
297
305
 
298
306
  return {
299
307
  tags,
300
308
  relations,
301
309
  navigateTo: navigateTo ?? null,
302
- title: pipe(commonProperties.title, unique(), only()) ?? null,
303
- tail: pipe(commonProperties.tail, unique(), only()) ?? null,
304
- head: pipe(commonProperties.head, unique(), only()) ?? null,
305
- color: pipe(commonProperties.color, unique(), only()) ?? null,
306
- line: pipe(commonProperties.line, unique(), only()) ?? null,
307
- notation: pipe(commonProperties.notation, unique(), only()) ?? null
310
+ title: only([...commonProperties.title]) ?? null,
311
+ tail: only([...commonProperties.tail]) ?? null,
312
+ head: only([...commonProperties.head]) ?? null,
313
+ color: only([...commonProperties.color]) ?? null,
314
+ line: only([...commonProperties.line]) ?? null,
315
+ notation: only([...commonProperties.notation]) ?? null
308
316
  }
309
317
  }
310
318
  }
319
+ export function computeDynamicView<M extends AnyAux>(
320
+ model: LikeC4Model<M>,
321
+ view: DynamicView
322
+ ): ComputedDynamicView {
323
+ return new DynamicViewCompute(model, view).compute()
324
+ }