@likec4/core 1.31.0 → 1.32.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 (185) hide show
  1. package/README.md +407 -5
  2. package/dist/builder/index.d.mts +221 -42
  3. package/dist/builder/index.mjs +118 -65
  4. package/dist/compute-view/index.d.mts +23 -7
  5. package/dist/compute-view/index.mjs +11 -6
  6. package/dist/compute-view/relationships-view/index.d.mts +9 -7
  7. package/dist/compute-view/relationships-view/index.mjs +3 -2
  8. package/dist/index.d.mts +10 -14
  9. package/dist/index.mjs +9 -6
  10. package/dist/model/index.d.mts +173 -19
  11. package/dist/model/index.mjs +6 -1
  12. package/dist/shared/core.BaYE_r29.d.mts +258 -0
  13. package/dist/shared/core.Bk7wEZFG.mjs +276 -0
  14. package/dist/shared/core.BrCnZFTn.mjs +32 -0
  15. package/dist/shared/core.BuO4ncfY.d.mts +146 -0
  16. package/dist/shared/{core.Bq753SYD.mjs → core.CBpKAlhj.mjs} +2012 -4422
  17. package/dist/shared/core.CUYDgv2-.mjs +214 -0
  18. package/dist/shared/{core.Cu-UdkSl.mjs → core.CpXlRyE5.mjs} +7 -494
  19. package/dist/shared/{core.C-YXI-43.mjs → core.Cy9smucx.mjs} +3 -1
  20. package/dist/shared/core.CywrQs86.d.mts +31 -0
  21. package/dist/shared/core.DXzRBkuI.d.mts +1264 -0
  22. package/dist/shared/core.DoK86JEe.mjs +518 -0
  23. package/dist/shared/{core.D2830qgg.d.mts → core.Pf5I9o0e.d.mts} +1 -1
  24. package/dist/shared/core.cbA9VZ02.mjs +2681 -0
  25. package/dist/shared/{core.CQXU9DF7.mjs → core.rmvsy0n3.mjs} +23 -32
  26. package/dist/shared/core.znRaUX_A.d.mts +920 -0
  27. package/dist/types/aux.d.mts +3 -0
  28. package/dist/types/aux.mjs +1 -0
  29. package/dist/types/index.d.mts +7 -45
  30. package/dist/types/index.mjs +130 -3
  31. package/dist/utils/index.d.mts +221 -53
  32. package/dist/utils/index.mjs +14 -10
  33. package/package.json +16 -8
  34. package/src/builder/Builder.deploymentModel.ts +82 -18
  35. package/src/builder/Builder.element.ts +40 -20
  36. package/src/builder/Builder.model.ts +66 -17
  37. package/src/builder/Builder.ts +168 -76
  38. package/src/builder/Builder.view-common.ts +35 -17
  39. package/src/builder/Builder.view-deployment.ts +25 -25
  40. package/src/builder/Builder.view-element.ts +13 -12
  41. package/src/builder/Builder.views.ts +12 -7
  42. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +62 -34
  43. package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +319 -0
  44. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +45 -24
  45. package/src/builder/_types.ts +34 -27
  46. package/src/compute-view/compute-view.ts +31 -34
  47. package/src/compute-view/deployment-view/__test__/TestHelper.ts +27 -14
  48. package/src/compute-view/deployment-view/__test__/fixture.ts +15 -13
  49. package/src/compute-view/deployment-view/_types.ts +10 -10
  50. package/src/compute-view/deployment-view/clean-connections.ts +5 -7
  51. package/src/compute-view/deployment-view/compute.ts +16 -13
  52. package/src/compute-view/deployment-view/memory/memory.ts +5 -6
  53. package/src/compute-view/deployment-view/predicates/deploymentRefs.ts +4 -5
  54. package/src/compute-view/deployment-view/predicates/relation-direct.ts +25 -50
  55. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +5 -7
  56. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +7 -11
  57. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +7 -10
  58. package/src/compute-view/deployment-view/predicates/utils.ts +37 -31
  59. package/src/compute-view/deployment-view/predicates/wildcard.ts +3 -2
  60. package/src/compute-view/deployment-view/stages/stage-final.ts +2 -2
  61. package/src/compute-view/deployment-view/stages/stage-include.ts +1 -1
  62. package/src/compute-view/deployment-view/utils.ts +79 -72
  63. package/src/compute-view/dynamic-view/__test__/fixture.ts +20 -11
  64. package/src/compute-view/dynamic-view/compute.ts +60 -53
  65. package/src/compute-view/element-view/__test__/TestHelper.ts +53 -29
  66. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +26 -26
  67. package/src/compute-view/element-view/__test__/fixture.ts +134 -83
  68. package/src/compute-view/element-view/_types.ts +14 -19
  69. package/src/compute-view/element-view/clean-connections.ts +12 -8
  70. package/src/compute-view/element-view/compute.ts +61 -51
  71. package/src/compute-view/element-view/memory/NodeGroup.ts +8 -9
  72. package/src/compute-view/element-view/memory/memory.ts +22 -22
  73. package/src/compute-view/element-view/memory/stage-include.ts +5 -3
  74. package/src/compute-view/element-view/predicates/_utils.ts +18 -14
  75. package/src/compute-view/element-view/predicates/element-expand.ts +4 -5
  76. package/src/compute-view/element-view/predicates/element-kind-tag.ts +3 -4
  77. package/src/compute-view/element-view/predicates/element-ref.ts +3 -4
  78. package/src/compute-view/element-view/predicates/relation-direct.ts +16 -12
  79. package/src/compute-view/element-view/predicates/relation-in-out.ts +7 -8
  80. package/src/compute-view/element-view/predicates/relation-in.ts +19 -26
  81. package/src/compute-view/element-view/predicates/relation-out.ts +20 -21
  82. package/src/compute-view/element-view/predicates/wildcard.ts +3 -3
  83. package/src/compute-view/element-view/utils.ts +25 -23
  84. package/src/compute-view/index.ts +1 -1
  85. package/src/compute-view/memory/AbstractStageExclude.ts +3 -4
  86. package/src/compute-view/memory/AbstractStageInclude.ts +1 -1
  87. package/src/compute-view/memory/_types.ts +3 -2
  88. package/src/compute-view/relationships-view/_types.ts +3 -4
  89. package/src/compute-view/relationships-view/compute.ts +8 -11
  90. package/src/compute-view/relationships-view/layout.ts +6 -6
  91. package/src/compute-view/relationships-view/utils.ts +4 -4
  92. package/src/compute-view/utils/ancestorsOfNode.ts +7 -7
  93. package/src/compute-view/utils/applyCustomElementProperties.ts +16 -8
  94. package/src/compute-view/utils/applyCustomRelationProperties.ts +19 -9
  95. package/src/compute-view/utils/applyViewRuleStyles.ts +18 -10
  96. package/src/compute-view/utils/buildComputedNodes.ts +40 -40
  97. package/src/compute-view/utils/buildElementNotations.ts +14 -14
  98. package/src/compute-view/utils/elementExpressionToPredicate.ts +14 -15
  99. package/src/compute-view/utils/link-nodes-with-edges.ts +6 -4
  100. package/src/compute-view/utils/merge-props-from-relationships.ts +52 -20
  101. package/src/compute-view/utils/relationExpressionToPredicates.ts +19 -19
  102. package/src/compute-view/utils/resolve-extended-views.ts +8 -7
  103. package/src/compute-view/utils/resolve-global-rules.ts +31 -26
  104. package/src/compute-view/utils/topological-sort.ts +14 -14
  105. package/src/compute-view/utils/view-hash.ts +2 -2
  106. package/src/compute-view/utils/with-readable-edges.ts +9 -5
  107. package/src/index.ts +0 -32
  108. package/src/model/DeploymentElementModel.ts +171 -144
  109. package/src/model/DeploymentModel.ts +88 -65
  110. package/src/model/ElementModel.ts +85 -74
  111. package/src/model/LikeC4Model.ts +430 -241
  112. package/src/model/RelationModel.ts +63 -29
  113. package/src/model/__test__/fixture.ts +50 -36
  114. package/src/model/connection/Connection.ts +2 -2
  115. package/src/model/connection/deployment/DeploymentConnectionModel.ts +21 -24
  116. package/src/model/connection/deployment/find.ts +1 -1
  117. package/src/model/connection/model/ConnectionModel.ts +21 -20
  118. package/src/model/connection/model/find.ts +7 -7
  119. package/src/model/connection/ops.ts +6 -6
  120. package/src/model/guards.ts +66 -14
  121. package/src/model/index.ts +20 -7
  122. package/src/model/types.ts +41 -97
  123. package/src/model/view/EdgeModel.ts +47 -41
  124. package/src/model/view/LikeC4ViewModel.ts +130 -80
  125. package/src/model/view/NodeModel.ts +102 -96
  126. package/src/theme/element.ts +1 -1
  127. package/src/theme/index.ts +9 -9
  128. package/src/theme/relationships.ts +1 -1
  129. package/src/types/_common.ts +21 -15
  130. package/src/types/aux.ts +285 -0
  131. package/src/types/const.ts +34 -0
  132. package/src/types/expression-model.ts +292 -0
  133. package/src/types/expression.ts +311 -0
  134. package/src/types/fqnRef.ts +88 -0
  135. package/src/types/geometry.ts +131 -0
  136. package/src/types/global.ts +10 -8
  137. package/src/types/index.ts +39 -201
  138. package/src/types/model-data.ts +52 -84
  139. package/src/types/model-deployment.ts +87 -0
  140. package/src/types/model-dump.ts +72 -0
  141. package/src/types/model-logical.ts +111 -0
  142. package/src/types/model-spec.ts +81 -0
  143. package/src/types/operators.ts +51 -52
  144. package/src/types/scalar.ts +114 -0
  145. package/src/types/{theme.ts → styles.ts} +55 -15
  146. package/src/types/view-changes.ts +4 -5
  147. package/src/types/view-common.ts +157 -0
  148. package/src/types/view-computed.ts +113 -0
  149. package/src/types/view-layouted.ts +82 -0
  150. package/src/types/view-parsed.deployment.ts +40 -0
  151. package/src/types/view-parsed.dynamic.ts +78 -0
  152. package/src/types/view-parsed.element.ts +65 -0
  153. package/src/types/view.ts +122 -542
  154. package/src/utils/compare-natural.ts +43 -1
  155. package/src/utils/getOrCreate.ts +0 -34
  156. package/src/utils/index.ts +7 -12
  157. package/src/utils/iterable/filter.ts +1 -1
  158. package/src/utils/iterable/find.ts +3 -1
  159. package/src/utils/iterable/head.ts +22 -0
  160. package/src/utils/iterable/index.ts +1 -0
  161. package/src/utils/iterable/map.ts +1 -1
  162. package/src/utils/iterable/reduce.ts +1 -1
  163. package/src/utils/iterable/some.ts +1 -1
  164. package/src/utils/memoize-prop.ts +30 -0
  165. package/src/utils/object-hash.ts +1 -1
  166. package/src/utils/relations.ts +14 -11
  167. package/src/utils/string-hash.ts +1 -1
  168. package/dist/shared/core.CQDU11hR.d.mts +0 -753
  169. package/dist/shared/core.DJvmfnEi.d.mts +0 -1153
  170. package/dist/shared/core.DgfwjBtu.mjs +0 -495
  171. package/dist/shared/core.Dx7siloV.d.mts +0 -146
  172. package/dist/shared/core.SjLhMA7a.d.mts +0 -62
  173. package/src/builder/__snapshots__/Builder.spec.ts.snap +0 -374
  174. package/src/compute-view/element-view/predicates.ts +0 -520
  175. package/src/compute-view/utils/uniqueTags.ts +0 -21
  176. package/src/types/deployments.ts +0 -170
  177. package/src/types/element.ts +0 -109
  178. package/src/types/expression-v2-model.ts +0 -314
  179. package/src/types/expression-v2.ts +0 -392
  180. package/src/types/overview-graph.ts +0 -43
  181. package/src/types/relation.ts +0 -61
  182. package/src/types/scalars.ts +0 -39
  183. package/src/types/view-notation.ts +0 -9
  184. package/src/utils/graphlib.ts +0 -10
  185. /package/src/{errors/index.ts → utils/invariant.ts} +0 -0
@@ -1,16 +1,22 @@
1
1
  import { filter, isArray, map, pick, pipe } from 'remeda'
2
- import { nonexhaustive } from '../../../errors'
3
- import { type DeploymentConnectionModel, ElementModel, isDeployedInstance, isDeploymentNode } from '../../../model'
4
2
  import type {
5
3
  DeploymentElementModel,
6
4
  DeploymentRelationEndpoint,
7
5
  DeploymentRelationModel,
8
- } from '../../../model/DeploymentElementModel'
9
- import { isElementModel } from '../../../model/ElementModel'
10
- import { isDeploymentElementModel, isNestedElementOfDeployedInstanceModel } from '../../../model/guards'
11
- import type { RelationshipModel } from '../../../model/RelationModel'
12
- import type { AnyAux } from '../../../model/types'
6
+ RelationshipModel,
7
+ } from '../../../model'
8
+ import {
9
+ type DeploymentConnectionModel,
10
+ ElementModel,
11
+ isDeployedInstanceModel as isDeployedInstance,
12
+ isDeploymentElementModel,
13
+ isDeploymentNodeModel as isDeploymentNode,
14
+ isElementModel,
15
+ isNestedElementOfDeployedInstanceModel,
16
+ } from '../../../model'
17
+ import type { AnyAux } from '../../../types'
13
18
  import { type Filterable, type OperatorPredicate, FqnExpr, RelationExpr } from '../../../types'
19
+ import { nonexhaustive } from '../../../utils'
14
20
  import { hasIntersection, intersection } from '../../../utils/set'
15
21
  import type { ExcludePredicateCtx, PredicateCtx } from '../_types'
16
22
  import type { StageExclude, StageInclude } from '../memory'
@@ -60,18 +66,18 @@ export function predicateToPatch(
60
66
  }
61
67
  }
62
68
 
63
- export function excludeModelRelations(
64
- relationsToExclude: ReadonlySet<RelationshipModel<AnyAux>>,
69
+ export function excludeModelRelations<M extends AnyAux>(
70
+ relationsToExclude: ReadonlySet<RelationshipModel<M>>,
65
71
  { stage, memory }: Pick<ExcludePredicateCtx, 'stage' | 'memory'>,
66
- where: OperatorPredicate<Filterable> | null,
72
+ where: OperatorPredicate<M> | null,
67
73
  // Optional filter to scope the connections to exclude
68
- filterConnections: (c: DeploymentConnectionModel) => boolean = () => true,
74
+ filterConnections: (c: DeploymentConnectionModel<M>) => boolean = () => true,
69
75
  ): StageExclude {
70
76
  if (relationsToExclude.size === 0) {
71
77
  return stage
72
78
  }
73
79
  const toExclude = pipe(
74
- memory.connections,
80
+ memory.connections as unknown as readonly DeploymentConnectionModel<M>[],
75
81
  filter(c => filterConnections(c)),
76
82
  // Find connections that have at least one relation in common with the excluded relations
77
83
  filter(c => hasIntersection(c.relations.model, relationsToExclude)),
@@ -87,12 +93,12 @@ export function excludeModelRelations(
87
93
  if (toExclude.length === 0) {
88
94
  return stage
89
95
  }
90
- return stage.excludeConnections(toExclude)
96
+ return stage.excludeConnections(toExclude as unknown as DeploymentConnectionModel[])
91
97
  }
92
98
 
93
99
  export function matchConnection<M extends AnyAux>(
94
100
  c: DeploymentConnectionModel<M>,
95
- where: OperatorPredicate<Filterable> | null,
101
+ where: OperatorPredicate<M> | null,
96
102
  ): boolean {
97
103
  return applyPredicate(c, where).nonEmpty()
98
104
  }
@@ -108,7 +114,7 @@ export function matchConnection<M extends AnyAux>(
108
114
  */
109
115
  export function applyPredicate<M extends AnyAux>(
110
116
  c: readonly DeploymentConnectionModel<M>[],
111
- where: OperatorPredicate<Filterable> | null,
117
+ where: OperatorPredicate<M> | null,
112
118
  ): readonly DeploymentConnectionModel<M>[]
113
119
  /**
114
120
  * Filters relations of the connection using the provided predicate.
@@ -119,7 +125,7 @@ export function applyPredicate<M extends AnyAux>(
119
125
  */
120
126
  export function applyPredicate<M extends AnyAux>(
121
127
  c: DeploymentConnectionModel<M>,
122
- where: OperatorPredicate<Filterable> | null,
128
+ where: OperatorPredicate<M> | null,
123
129
  ): DeploymentConnectionModel<M>
124
130
  /**
125
131
  * Creates a function that filters relations of the provided connections using the provided predicate.
@@ -130,13 +136,13 @@ export function applyPredicate<M extends AnyAux>(
130
136
  * @returns A function to create a filtered copy of connections
131
137
  */
132
138
  export function applyPredicate<M extends AnyAux>(
133
- where: OperatorPredicate<Filterable> | null,
139
+ where: OperatorPredicate<M> | null,
134
140
  ): (data: readonly DeploymentConnectionModel<M>[]) => readonly DeploymentConnectionModel<M>[]
135
141
  export function applyPredicate<M extends AnyAux>(
136
142
  ...args:
137
- | [readonly DeploymentConnectionModel<M>[], OperatorPredicate<Filterable> | null]
138
- | [OperatorPredicate<Filterable> | null]
139
- | [c: DeploymentConnectionModel<M>, OperatorPredicate<Filterable> | null]
143
+ | [readonly DeploymentConnectionModel<M>[], OperatorPredicate<M> | null]
144
+ | [OperatorPredicate<M> | null]
145
+ | [c: DeploymentConnectionModel<M>, OperatorPredicate<M> | null]
140
146
  ):
141
147
  | DeploymentConnectionModel<M>
142
148
  | readonly DeploymentConnectionModel<M>[]
@@ -172,7 +178,7 @@ export function applyPredicate<M extends AnyAux>(
172
178
  */
173
179
  export function applyElementPredicate<M extends AnyAux>(
174
180
  c: readonly DeploymentElementModel<M>[],
175
- where: OperatorPredicate<Filterable> | null,
181
+ where: OperatorPredicate<M> | null,
176
182
  ): readonly DeploymentElementModel<M>[]
177
183
  /**
178
184
  * Checks element using the provided predicate.
@@ -183,7 +189,7 @@ export function applyElementPredicate<M extends AnyAux>(
183
189
  */
184
190
  export function applyElementPredicate<M extends AnyAux, E extends DeploymentElementModel<M>>(
185
191
  c: E,
186
- where: OperatorPredicate<Filterable> | null,
192
+ where: OperatorPredicate<M> | null,
187
193
  ): boolean
188
194
  /**
189
195
  * Creates a function that filters elemetns using the provided predicate.
@@ -192,13 +198,13 @@ export function applyElementPredicate<M extends AnyAux, E extends DeploymentElem
192
198
  * @returns A function to filter elements
193
199
  */
194
200
  export function applyElementPredicate<M extends AnyAux, E extends DeploymentElementModel<M>>(
195
- where: OperatorPredicate<Filterable> | null,
201
+ where: OperatorPredicate<M> | null,
196
202
  ): (data: readonly E[]) => readonly E[]
197
203
  export function applyElementPredicate<M extends AnyAux, E extends DeploymentElementModel<M>>(
198
204
  ...args:
199
- | [readonly E[], OperatorPredicate<Filterable> | null]
200
- | [OperatorPredicate<Filterable> | null]
201
- | [c: E, OperatorPredicate<Filterable> | null]
205
+ | [readonly E[], OperatorPredicate<M> | null]
206
+ | [OperatorPredicate<M> | null]
207
+ | [c: E, OperatorPredicate<M> | null]
202
208
  ):
203
209
  | boolean
204
210
  | readonly E[]
@@ -219,8 +225,8 @@ export function applyElementPredicate<M extends AnyAux, E extends DeploymentElem
219
225
 
220
226
  export function matchConnections<M extends AnyAux>(
221
227
  connections: readonly DeploymentConnectionModel<M>[],
222
- where: OperatorPredicate<Filterable> | null,
223
- ): readonly DeploymentConnectionModel[] {
228
+ where: OperatorPredicate<M> | null,
229
+ ): readonly DeploymentConnectionModel<M>[] {
224
230
  if (!where) {
225
231
  return connections
226
232
  }
@@ -240,9 +246,9 @@ export function matchConnections<M extends AnyAux>(
240
246
  function toFilterable<M extends AnyAux>(
241
247
  relationEndpoint: ElementModel<M> | DeploymentRelationEndpoint<M>,
242
248
  connectionEndpoint: DeploymentRelationEndpoint<M>,
243
- ): Filterable {
244
- if (isElementModel(relationEndpoint)) { // Element itself. Extend with tags of the deployed instance (TODO)
245
- const deployedInstance = isDeploymentElementModel(connectionEndpoint) && isDeployedInstance(connectionEndpoint)
249
+ ): Filterable<M> {
250
+ if (isElementModel<M>(relationEndpoint)) { // Element itself. Extend with tags of the deployed instance (TODO)
251
+ const deployedInstance = isDeploymentElementModel<M>(connectionEndpoint) && isDeployedInstance(connectionEndpoint)
246
252
  ? connectionEndpoint
247
253
  : null
248
254
  return {
@@ -1,7 +1,7 @@
1
1
  import { map, pipe } from 'remeda'
2
- import { findConnectionsWithin } from '../../../model/connection/deployment'
3
2
  import type { FqnExpr } from '../../../types'
4
3
  import { type Elem, type PredicateExecutor } from '../_types'
4
+ import { findConnectionsWithin } from '../utils'
5
5
  import { applyElementPredicate } from './utils'
6
6
 
7
7
  export const WildcardPredicate: PredicateExecutor<FqnExpr.Wildcard> = {
@@ -16,7 +16,8 @@ export const WildcardPredicate: PredicateExecutor<FqnExpr.Wildcard> = {
16
16
  children.push(...root.children())
17
17
  }
18
18
  return root
19
- }))
19
+ }),
20
+ )
20
21
 
21
22
  stage.addExplicit(rootElements)
22
23
  if (children.length > 1) {
@@ -1,6 +1,6 @@
1
1
  import { forEach, only, pipe } from 'remeda'
2
- import { differenceConnections } from '../../../model/connection'
3
- import type { RelationshipModel } from '../../../model/RelationModel'
2
+ import { differenceConnections } from '../../../model'
3
+ import type { RelationshipModel } from '../../../model'
4
4
  import { isAncestor, sortByFqnHierarchically } from '../../../utils/fqn'
5
5
  import { ifilter, isome, toArray } from '../../../utils/iterable'
6
6
  import { DefaultMap } from '../../../utils/mnemonist'
@@ -1,10 +1,10 @@
1
1
  import { dropWhile, forEach, pipe, take, zip } from 'remeda'
2
- import { findConnection, findConnectionsBetween } from '../../../model/connection/deployment'
3
2
  import { isIterable } from '../../../utils'
4
3
  import { toArray } from '../../../utils/iterable'
5
4
  import { type CtxConnection, type CtxElement, AbstractStageInclude } from '../../memory'
6
5
  import { cleanCrossBoundary, cleanRedundantRelationships } from '../clean-connections'
7
6
  import { type Ctx } from '../memory/memory'
7
+ import { findConnection, findConnectionsBetween } from '../utils'
8
8
 
9
9
  type Elem = CtxElement<Ctx>
10
10
  type Connection = CtxConnection<Ctx>
@@ -1,34 +1,39 @@
1
- import { hasAtLeast, isEmpty, isNumber, isString } from 'remeda'
2
- import { invariant, nonexhaustive } from '../../errors'
3
- import type { LikeC4DeploymentModel } from '../../model'
4
- import type { DeploymentConnectionModel } from '../../model/connection/deployment'
5
- import type { ElementModel } from '../../model/ElementModel'
6
- import type { AnyAux } from '../../model/types'
1
+ import { hasAtLeast, isEmpty, unique } from 'remeda'
2
+ import type {
3
+ DeployedInstanceModel,
4
+ DeploymentConnectionModel,
5
+ DeploymentElementModel,
6
+ DeploymentNodeModel,
7
+ ElementModel,
8
+ LikeC4DeploymentModel,
9
+ } from '../../model'
10
+ import { deploymentConnection } from '../../model'
7
11
  import {
12
+ type AnyAux,
13
+ type aux,
8
14
  type ComputedEdge,
9
15
  type ComputedNode,
10
- type DeploymentNodeKind,
11
16
  type DeploymentViewRule,
12
- type Fqn,
13
- type NonEmptyArray,
14
- type Tag,
17
+ type scalar,
18
+ type Unknown,
15
19
  DefaultArrowType,
16
20
  FqnExpr,
17
21
  isViewRuleStyle,
18
22
  } from '../../types'
19
- import { nameFromFqn, parentFqn } from '../../utils'
23
+ import { invariant, nameFromFqn, nonexhaustive, parentFqn } from '../../utils'
20
24
  import { applyViewRuleStyle } from '../utils/applyViewRuleStyles'
21
25
  import { type ComputedNodeSource, buildComputedNodes } from '../utils/buildComputedNodes'
22
26
  import { mergePropsFromRelationships } from '../utils/merge-props-from-relationships'
23
- import { uniqueTags } from '../utils/uniqueTags'
24
- import type { Elem, Memory } from './_types'
27
+ import type { Memory } from './_types'
28
+
29
+ export const { findConnection, findConnectionsBetween, findConnectionsWithin } = deploymentConnection
25
30
 
26
31
  type Predicate<T> = (x: T) => boolean
27
32
 
28
- export function resolveElements(
29
- model: LikeC4DeploymentModel,
30
- expr: FqnExpr.DeploymentRef,
31
- ): Elem[] {
33
+ export function resolveElements<A extends AnyAux>(
34
+ model: LikeC4DeploymentModel<A>,
35
+ expr: FqnExpr.DeploymentRef<A>,
36
+ ): DeploymentElementModel<A>[] {
32
37
  const ref = model.element(expr.ref.deployment)
33
38
  if (ref.isDeploymentNode()) {
34
39
  if (expr.selector === 'children') {
@@ -44,10 +49,10 @@ export function resolveElements(
44
49
  return [ref]
45
50
  }
46
51
 
47
- export function resolveModelElements(
48
- model: LikeC4DeploymentModel,
49
- expr: FqnExpr.ModelRef,
50
- ): ElementModel[] {
52
+ export function resolveModelElements<A extends AnyAux>(
53
+ model: LikeC4DeploymentModel<A>,
54
+ expr: FqnExpr.ModelRef<A>,
55
+ ): ElementModel<A>[] {
51
56
  const ref = model.$model.element(expr.ref.model)
52
57
  if (expr.selector === 'children') {
53
58
  return [...ref.children()]
@@ -61,9 +66,12 @@ export function resolveModelElements(
61
66
  return [ref]
62
67
  }
63
68
 
64
- export function deploymentExpressionToPredicate<T extends { id: string; modelRef?: number | string }>(
65
- target: FqnExpr,
66
- ): Predicate<T> {
69
+ export function deploymentExpressionToPredicate<
70
+ A extends AnyAux,
71
+ N extends { id: string | aux.DeploymentFqn<A>; modelRef?: aux.Fqn<A> | undefined },
72
+ >(
73
+ target: FqnExpr<A>,
74
+ ): Predicate<N> {
67
75
  if (FqnExpr.isWildcard(target)) {
68
76
  return () => true
69
77
  }
@@ -86,21 +94,11 @@ export function deploymentExpressionToPredicate<T extends { id: string; modelRef
86
94
  return n => n.id === fqn
87
95
  }
88
96
  if (FqnExpr.isModelRef(target)) {
89
- const modelFqn = (node: T) => {
90
- if (isString(node.modelRef)) {
91
- return node.modelRef
92
- }
93
- if (isNumber(node.modelRef)) {
94
- return node.id
95
- }
96
- return null
97
- }
98
-
99
97
  const fqn = target.ref.model
100
98
  if (target.selector === 'expanded') {
101
99
  const fqnWithDot = fqn + '.'
102
- return (n) => {
103
- const m = modelFqn(n)
100
+ return (n: N) => {
101
+ const m = n.modelRef ?? null
104
102
  if (!m) {
105
103
  return true
106
104
  }
@@ -109,8 +107,8 @@ export function deploymentExpressionToPredicate<T extends { id: string; modelRef
109
107
  }
110
108
  if (target.selector === 'descendants') {
111
109
  const fqnWithDot = fqn + '.'
112
- return (n) => {
113
- const m = modelFqn(n)
110
+ return (n: N) => {
111
+ const m = n.modelRef ?? null
114
112
  if (!m) {
115
113
  return true
116
114
  }
@@ -118,16 +116,16 @@ export function deploymentExpressionToPredicate<T extends { id: string; modelRef
118
116
  }
119
117
  }
120
118
  if (target.selector === 'children') {
121
- return (n) => {
122
- const m = modelFqn(n)
119
+ return (n: N) => {
120
+ const m = n.modelRef ?? null
123
121
  if (!m) {
124
122
  return true
125
123
  }
126
124
  return parentFqn(m) === fqn
127
125
  }
128
126
  }
129
- return (n) => {
130
- const m = modelFqn(n)
127
+ return (n: N) => {
128
+ const m = n.modelRef ?? null
131
129
  if (!m) {
132
130
  return true
133
131
  }
@@ -137,15 +135,21 @@ export function deploymentExpressionToPredicate<T extends { id: string; modelRef
137
135
  nonexhaustive(target)
138
136
  }
139
137
 
140
- export function toNodeSource(el: Elem): ComputedNodeSource {
138
+ export function toNodeSource<A extends AnyAux>(
139
+ el: DeploymentNodeModel<A> | DeployedInstanceModel<A>,
140
+ ): ComputedNodeSource<A> {
141
141
  if (el.isDeploymentNode()) {
142
142
  const onlyOneInstance = el.onlyOneInstance()
143
143
  let { title, kind, id, ...$node } = el.$node
144
144
  const { icon, color, shape, ...style } = el.$node.style ?? {}
145
-
146
- // If there is only one instance and title was not overriden
147
- if (onlyOneInstance && title === nameFromFqn(el.id)) {
148
- title = onlyOneInstance.title
145
+ let tags = [...el.tags]
146
+ // If there is only one instance
147
+ if (onlyOneInstance) {
148
+ tags = unique([...tags, ...onlyOneInstance.tags])
149
+ // If title was not overriden
150
+ if (title === nameFromFqn(el.id)) {
151
+ title = onlyOneInstance.title
152
+ }
149
153
  }
150
154
 
151
155
  return {
@@ -158,41 +162,42 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
158
162
  ...(icon && { icon }),
159
163
  ...(color && { color }),
160
164
  ...(shape && { shape }),
165
+ tags,
161
166
  style: {
162
167
  ...style,
163
168
  },
164
- deploymentRef: 1,
169
+ deploymentRef: id,
165
170
  kind,
166
- id,
171
+ id: id as scalar.NodeId,
167
172
  }
168
173
  }
169
174
  invariant(el.isInstance(), 'Expected Instance')
170
175
  const instance = el.$instance
171
- const element = el.element.$element
176
+ const element = el.element
172
177
 
173
178
  const icon = instance.style?.icon ?? element.icon
174
179
  const color = instance.style?.color ?? element.color
175
180
  const shape = instance.style?.shape ?? element.shape
176
181
 
177
182
  const links = [
178
- ...(element.links ?? []),
183
+ ...element.links,
179
184
  ...(instance.links ?? []),
180
185
  ]
181
186
 
182
187
  const metadata = {
183
- ...element.metadata,
188
+ ...element.getMetadata(),
184
189
  ...instance.metadata,
185
190
  }
186
191
 
187
- const notation = instance.notation ?? element.notation
192
+ const notation = instance.notation ?? element.$element.notation
188
193
 
189
194
  return {
190
- id: el.id,
191
- kind: 'instance' as DeploymentNodeKind,
195
+ id: el.id as scalar.NodeId,
196
+ kind: 'instance' as unknown as aux.DeploymentKind<A>,
192
197
  title: instance.title ?? element.title,
193
198
  description: instance.description ?? element.description,
194
199
  technology: instance.technology ?? element.technology,
195
- tags: uniqueTags([element, instance]) as NonEmptyArray<Tag>,
200
+ tags: [...el.tags],
196
201
  links: hasAtLeast(links, 1) ? links : null,
197
202
  ...icon && { icon },
198
203
  ...color && { color },
@@ -201,16 +206,16 @@ export function toNodeSource(el: Elem): ComputedNodeSource {
201
206
  ...element.style,
202
207
  ...instance.style,
203
208
  },
204
- deploymentRef: el.id === instance.id ? 1 : instance.id,
205
- modelRef: el.id === element.id ? 1 : element.id,
209
+ deploymentRef: instance.id,
210
+ modelRef: element.id,
206
211
  ...notation && { notation },
207
212
  ...!isEmpty(metadata) && ({ metadata }),
208
213
  }
209
214
  }
210
215
 
211
- export function toComputedEdges<M extends AnyAux>(
212
- connections: ReadonlyArray<DeploymentConnectionModel<M>>,
213
- ): ComputedEdge[] {
216
+ export function toComputedEdges<A extends AnyAux>(
217
+ connections: ReadonlyArray<DeploymentConnectionModel<A>>,
218
+ ): ComputedEdge<A>[] {
214
219
  return connections.reduce((acc, e) => {
215
220
  // const modelRelations = []
216
221
  // const deploymentRelations = []
@@ -220,21 +225,21 @@ export function toComputedEdges<M extends AnyAux>(
220
225
  ]
221
226
  invariant(hasAtLeast(relations, 1), 'Edge must have at least one relation')
222
227
 
223
- const source = e.source.id
224
- const target = e.target.id
228
+ const source = e.source.id as scalar.NodeId
229
+ const target = e.target.id as scalar.NodeId
225
230
 
226
231
  const {
227
232
  title,
228
233
  ...props
229
234
  } = mergePropsFromRelationships(relations.map(r => r.$relationship)) // || relations.find(r => r.source === source && r.target === target)
230
235
 
231
- const edge: ComputedEdge = {
236
+ const edge: ComputedEdge<A> = {
232
237
  id: e.id,
233
- parent: e.boundary?.id ?? null,
238
+ parent: e.boundary?.id as scalar.NodeId ?? null,
234
239
  source,
235
240
  target,
236
241
  label: title ?? null,
237
- relations: relations.map((r) => r.id as M['RelationId']),
242
+ relations: relations.map((r) => r.id),
238
243
  ...props,
239
244
  }
240
245
 
@@ -257,17 +262,19 @@ export function toComputedEdges<M extends AnyAux>(
257
262
 
258
263
  acc.push(edge)
259
264
  return acc
260
- }, [] as ComputedEdge[])
265
+ }, [] as ComputedEdge<A>[])
261
266
  }
262
267
 
263
- export function buildNodes(memory: Memory): ReadonlyMap<Fqn, ComputedNode> {
268
+ export function buildNodes<A extends AnyAux = Unknown>(
269
+ memory: Memory,
270
+ ): ReadonlyMap<aux.NodeId, ComputedNode<A>> {
264
271
  return buildComputedNodes([...memory.final].map(toNodeSource))
265
272
  }
266
273
 
267
- export function applyDeploymentViewRuleStyles(
268
- rules: DeploymentViewRule[],
269
- nodes: ComputedNode[],
270
- ): ComputedNode[] {
274
+ export function applyDeploymentViewRuleStyles<A extends AnyAux>(
275
+ rules: DeploymentViewRule<A>[],
276
+ nodes: ComputedNode<A>[],
277
+ ): ComputedNode<A>[] {
271
278
  for (const rule of rules) {
272
279
  if (!isViewRuleStyle(rule) || rule.targets.length === 0) {
273
280
  continue
@@ -1,17 +1,24 @@
1
1
  import { partition } from 'remeda'
2
- import type { DynamicViewRule, DynamicViewStep, Fqn, ViewId, ViewRulePredicate } from '../../../types'
3
- import { type FakeElementIds, fakeModel } from '../../element-view/__test__/fixture'
2
+ import type {
3
+ DynamicViewIncludeRule,
4
+ DynamicViewRule,
5
+ DynamicViewStep,
6
+ ElementViewPredicate,
7
+ Fqn,
8
+ ParsedDynamicView as DynamicView,
9
+ ViewId,
10
+ } from '../../../types'
11
+ import { type $Aux, type FakeElementIds, fakeModel } from '../../element-view/__test__/fixture'
4
12
  import { computeDynamicView } from '../compute'
5
13
 
6
14
  const emptyView = {
7
- __: 'dynamic' as const,
15
+ _type: 'dynamic' as const,
8
16
  id: 'index' as ViewId,
9
17
  title: null,
10
18
  description: null,
11
19
  tags: null,
12
20
  links: null,
13
- customColorDefinitions: {},
14
- rules: []
21
+ rules: [],
15
22
  }
16
23
 
17
24
  type StepExpr = `${FakeElementIds} ${'->' | '<-'} ${FakeElementIds}`
@@ -25,7 +32,7 @@ export function $step(expr: StepExpr, props?: string | Partial<StepProps>): Dyna
25
32
  source: source as Fqn,
26
33
  target: target as Fqn,
27
34
  ...(typeof props === 'object' ? props : {}),
28
- title: title ?? null
35
+ title: title ?? null,
29
36
  }
30
37
  }
31
38
  if (expr.includes(' <- ')) {
@@ -35,24 +42,26 @@ export function $step(expr: StepExpr, props?: string | Partial<StepProps>): Dyna
35
42
  target: target as Fqn,
36
43
  ...(typeof props === 'object' ? props : {}),
37
44
  title: title ?? null,
38
- isBackward: true
45
+ isBackward: true,
39
46
  }
40
47
  }
41
48
  throw new Error(`Invalid step expression: ${expr}`)
42
49
  }
43
50
 
44
- export function compute(stepsAndRules: (DynamicViewStep | ViewRulePredicate)[]) {
51
+ export function compute(
52
+ stepsAndRules: (DynamicViewStep<$Aux> | ElementViewPredicate<$Aux> | DynamicViewIncludeRule<$Aux>)[],
53
+ ) {
45
54
  const [steps, rules] = partition(stepsAndRules, (s): s is DynamicViewStep => 'source' in s)
46
55
  let view = computeDynamicView(
47
56
  fakeModel,
48
57
  {
49
58
  ...emptyView,
50
59
  steps,
51
- rules: rules as DynamicViewRule[]
52
- }
60
+ rules: rules as DynamicViewRule[],
61
+ } as DynamicView,
53
62
  )
54
63
  return Object.assign(view, {
55
64
  nodeIds: view.nodes.map((node) => node.id) as string[],
56
- edgeIds: view.edges.map((edge) => edge.id) as string[]
65
+ edgeIds: view.edges.map((edge) => edge.id) as string[],
57
66
  })
58
67
  }