@likec4/core 1.31.0 → 1.32.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 (186) 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.CCWXGc6G.d.mts +920 -0
  18. package/dist/shared/core.CUYDgv2-.mjs +214 -0
  19. package/dist/shared/{core.Cu-UdkSl.mjs → core.CpXlRyE5.mjs} +7 -494
  20. package/dist/shared/{core.C-YXI-43.mjs → core.Cy9smucx.mjs} +3 -1
  21. package/dist/shared/core.CywrQs86.d.mts +31 -0
  22. package/dist/shared/core.DoK86JEe.mjs +518 -0
  23. package/dist/shared/core.Dpq3P3YJ.d.mts +1265 -0
  24. package/dist/shared/{core.D2830qgg.d.mts → core.Pf5I9o0e.d.mts} +1 -1
  25. package/dist/shared/core.cbA9VZ02.mjs +2681 -0
  26. package/dist/shared/{core.CQXU9DF7.mjs → core.rmvsy0n3.mjs} +23 -32
  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 +15 -7
  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/styles.ts +123 -0
  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/theme.ts +0 -82
  184. package/src/types/view-notation.ts +0 -9
  185. package/src/utils/graphlib.ts +0 -10
  186. /package/src/{errors/index.ts → utils/invariant.ts} +0 -0
@@ -1,44 +1,67 @@
1
- import { isEmpty } from 'remeda'
2
- import type { IteratorLike } from '../types/_common'
3
- import type { Link } from '../types/element'
1
+ import { isTruthy } from 'remeda'
2
+ import type { AnyAux, Color, IteratorLike, Link, scalar } from '../types'
4
3
  import {
5
- type ModelRelation,
4
+ type Relationship,
6
5
  type RelationshipLineType,
7
6
  DefaultLineStyle,
8
7
  DefaultRelationshipColor,
9
- } from '../types/relation'
10
- import type { Tag } from '../types/scalars'
11
- import type { Color } from '../types/theme'
8
+ FqnRef,
9
+ } from '../types'
10
+ import type * as aux from '../types/aux'
12
11
  import { commonAncestor } from '../utils/fqn'
13
12
  import type { DeploymentRelationModel } from './DeploymentElementModel'
14
13
  import type { ElementModel } from './ElementModel'
14
+ import type { isDeploymentRelationModel } from './guards'
15
15
  import type { LikeC4Model } from './LikeC4Model'
16
- import type { AnyAux } from './types'
17
16
  import type { LikeC4ViewModel, ViewsIterator } from './view/LikeC4ViewModel'
18
17
 
19
- export type RelationshipsIterator<M extends AnyAux> = IteratorLike<RelationshipModel<M>>
18
+ export type RelationshipsIterator<A extends AnyAux> = IteratorLike<RelationshipModel<A>>
19
+
20
+ /**
21
+ * A relationship between two elements (in logical or deployment model)
22
+ * use {@link isDeploymentRelationModel} guard to check if the relationship is a deployment relationship
23
+ */
24
+ export interface AnyRelationshipModel<A extends AnyAux> {
25
+ get id(): scalar.RelationId
26
+ get expression(): string
27
+ get title(): string | null
28
+ get technology(): string | null
29
+ get description(): string | null
30
+ get navigateTo(): LikeC4ViewModel<A> | null
31
+ get tags(): aux.Tags<A>
32
+ get kind(): aux.RelationKind<A> | null
33
+ get links(): ReadonlyArray<Link>
34
+ get color(): Color
35
+ get line(): RelationshipLineType
36
+ isDeploymentRelation(): this is DeploymentRelationModel<A>
37
+ isModelRelation(): this is RelationshipModel<A>
38
+ getMetadata(): aux.Metadata<A>
39
+ getMetadata(field: aux.MetadataKey<A>): string | undefined
40
+ views(): ViewsIterator<A>
41
+ isTagged(tag: aux.LooseTag<A>): boolean
42
+ }
20
43
 
21
- export class RelationshipModel<M extends AnyAux = AnyAux> {
22
- public readonly source: ElementModel<M>
23
- public readonly target: ElementModel<M>
44
+ export class RelationshipModel<A extends AnyAux = AnyAux> implements AnyRelationshipModel<A> {
45
+ public readonly source: ElementModel<A>
46
+ public readonly target: ElementModel<A>
24
47
 
25
48
  /**
26
49
  * Common ancestor of the source and target elements.
27
50
  * Represents the boundary of the Relation.
28
51
  */
29
- public readonly boundary: ElementModel<M> | null
52
+ public readonly boundary: ElementModel<A> | null
30
53
 
31
54
  constructor(
32
- public readonly model: LikeC4Model<M>,
33
- public readonly $relationship: ModelRelation,
55
+ public readonly model: LikeC4Model<A>,
56
+ public readonly $relationship: Relationship<A>,
34
57
  ) {
35
- this.source = model.element($relationship.source)
36
- this.target = model.element($relationship.target)
58
+ this.source = model.element(FqnRef.flatten($relationship.source))
59
+ this.target = model.element(FqnRef.flatten($relationship.target))
37
60
  const parent = commonAncestor(this.source.id, this.target.id)
38
61
  this.boundary = parent ? this.model.element(parent) : null
39
62
  }
40
63
 
41
- get id(): M['RelationId'] {
64
+ get id(): scalar.RelationId {
42
65
  return this.$relationship.id
43
66
  }
44
67
 
@@ -47,35 +70,35 @@ export class RelationshipModel<M extends AnyAux = AnyAux> {
47
70
  }
48
71
 
49
72
  get title(): string | null {
50
- if (isEmpty(this.$relationship.title)) {
73
+ if (!isTruthy(this.$relationship.title)) {
51
74
  return null
52
75
  }
53
76
  return this.$relationship.title
54
77
  }
55
78
 
56
79
  get technology(): string | null {
57
- if (isEmpty(this.$relationship.technology)) {
80
+ if (!isTruthy(this.$relationship.technology)) {
58
81
  return null
59
82
  }
60
83
  return this.$relationship.technology
61
84
  }
62
85
 
63
86
  get description(): string | null {
64
- if (isEmpty(this.$relationship.description)) {
87
+ if (!isTruthy(this.$relationship.description)) {
65
88
  return null
66
89
  }
67
90
  return this.$relationship.description
68
91
  }
69
92
 
70
- get navigateTo(): LikeC4ViewModel<M> | null {
93
+ get navigateTo(): LikeC4ViewModel<A> | null {
71
94
  return this.$relationship.navigateTo ? this.model.view(this.$relationship.navigateTo) : null
72
95
  }
73
96
 
74
- get tags(): ReadonlyArray<Tag> {
97
+ get tags(): aux.Tags<A> {
75
98
  return this.$relationship.tags ?? []
76
99
  }
77
100
 
78
- get kind(): string | null {
101
+ get kind(): aux.RelationKind<A> | null {
79
102
  return this.$relationship.kind ?? null
80
103
  }
81
104
 
@@ -94,7 +117,7 @@ export class RelationshipModel<M extends AnyAux = AnyAux> {
94
117
  /**
95
118
  * Iterate over all views that include this relationship.
96
119
  */
97
- public *views(): ViewsIterator<M> {
120
+ public *views(): ViewsIterator<A> {
98
121
  for (const view of this.model.views()) {
99
122
  if (view.includesRelation(this.id)) {
100
123
  yield view
@@ -103,16 +126,27 @@ export class RelationshipModel<M extends AnyAux = AnyAux> {
103
126
  return
104
127
  }
105
128
 
106
- public isDeploymentRelation(): this is DeploymentRelationModel<M> {
129
+ public isDeploymentRelation(): this is DeploymentRelationModel<A> {
107
130
  return false
108
131
  }
109
132
 
110
- public getMetadata(): Record<string, string>
111
- public getMetadata(field: string): string | undefined
112
- public getMetadata(field?: string) {
133
+ public isModelRelation(): this is RelationshipModel<A> {
134
+ return true
135
+ }
136
+
137
+ public getMetadata(): aux.Metadata<A>
138
+ public getMetadata(field: aux.MetadataKey<A>): string | undefined
139
+ public getMetadata(field?: aux.MetadataKey<A>) {
113
140
  if (field) {
114
141
  return this.$relationship.metadata?.[field]
115
142
  }
116
143
  return this.$relationship.metadata ?? {}
117
144
  }
145
+
146
+ /**
147
+ * Checks if the relationship has the given tag.
148
+ */
149
+ public isTagged(tag: aux.LooseTag<A>): boolean {
150
+ return this.tags.includes(tag as aux.Tag<A>)
151
+ }
118
152
  }
@@ -1,5 +1,5 @@
1
1
  import { Builder } from '../../builder/Builder'
2
- import { computeViews } from '../../compute-view/compute-view'
2
+ import { computeParsedModelData } from '../../compute-view/compute-view'
3
3
  import { LikeC4Model } from '../LikeC4Model'
4
4
 
5
5
  const {
@@ -26,33 +26,40 @@ const {
26
26
  viewOf,
27
27
  deploymentView,
28
28
  $rules,
29
- $include
30
- }
29
+ $include,
30
+ },
31
31
  } = Builder.forSpecification({
32
32
  elements: {
33
33
  person: {
34
34
  style: {
35
- shape: 'person'
36
- }
35
+ shape: 'person',
36
+ },
37
37
  },
38
38
  system: {},
39
39
  component: {},
40
40
  webapp: {
41
+ tags: ['internal'],
41
42
  style: {
42
- shape: 'browser'
43
- }
43
+ shape: 'browser',
44
+ },
44
45
  },
45
46
  mobile: {
46
47
  style: {
47
- shape: 'mobile'
48
- }
49
- }
48
+ shape: 'mobile',
49
+ },
50
+ },
51
+ },
52
+ tags: {
53
+ internal: {},
54
+ external: {},
55
+ tag1: {},
56
+ tag2: {},
50
57
  },
51
58
  deployments: {
52
59
  env: {},
53
60
  zone: {},
54
- node: {}
55
- }
61
+ node: {},
62
+ },
56
63
  })
57
64
 
58
65
  const local = b
@@ -61,27 +68,34 @@ const local = b
61
68
  person('customer'),
62
69
  system('cloud').with(
63
70
  component('frontend').with(
64
- webapp('dashboard'),
65
- mobile('mobile')
71
+ webapp('dashboard', {
72
+ tags: ['tag1'],
73
+ }),
74
+ mobile('mobile'),
66
75
  ),
67
76
  component('auth'),
68
77
  component('backend').with(
69
78
  component('api'),
70
- component('graphql')
79
+ component('graphql'),
71
80
  ),
72
81
  component('media', {
73
- shape: 'storage'
74
- })
82
+ tags: ['tag2'],
83
+ shape: 'storage',
84
+ }),
75
85
  ),
76
86
  system('aws').with(
77
87
  component('rds', {
78
- shape: 'storage'
88
+ tags: ['tag2'],
89
+ shape: 'storage',
79
90
  }),
80
91
  component('s3', {
81
- shape: 'storage'
82
- })
92
+ tags: ['tag2'],
93
+ shape: 'storage',
94
+ }),
83
95
  ),
84
- system('email')
96
+ system('email', {
97
+ tags: ['external'],
98
+ }),
85
99
  ),
86
100
  $m.model(
87
101
  $m.rel('customer', 'cloud', 'uses services'),
@@ -93,7 +107,7 @@ const local = b
93
107
  $m.rel('cloud.frontend.mobile', 'cloud.auth', 'authenticates'),
94
108
  $m.rel('cloud.frontend.mobile', 'cloud.backend.api', 'fetches data'),
95
109
  $m.rel('cloud.frontend.mobile', 'cloud.media', 'fetches media'),
96
- $m.rel('cloud.frontend', 'cloud.backend')
110
+ $m.rel('cloud.frontend', 'cloud.backend'),
97
111
  ),
98
112
  $m.model(
99
113
  $m.rel('cloud.backend.api', 'cloud.auth', 'authorizes'),
@@ -102,30 +116,30 @@ const local = b
102
116
  $m.rel('cloud.backend.api', 'email', 'sends emails'),
103
117
  $m.rel('cloud', 'email', 'uses'),
104
118
  $m.rel('cloud.media', 'aws.s3', 'uploads'),
105
- $m.rel('email', 'customer', 'sends emails')
119
+ $m.rel('email', 'customer', 'sends emails'),
106
120
  ),
107
121
  deployment(
108
122
  node('customer').with(
109
- instanceOf('instance', 'customer')
123
+ instanceOf('instance', 'customer'),
110
124
  ),
111
125
  env('prod').with(
112
126
  zone('eu').with(
113
127
  zone('zone1').with(
114
128
  instanceOf('ui', 'cloud.frontend.dashboard'),
115
- instanceOf('api', 'cloud.backend.api')
129
+ instanceOf('api', 'cloud.backend.api'),
116
130
  ),
117
131
  zone('zone2').with(
118
132
  instanceOf('ui', 'cloud.frontend.dashboard'),
119
- instanceOf('api', 'cloud.backend.api')
133
+ instanceOf('api', 'cloud.backend.api'),
120
134
  ),
121
135
  instanceOf('media', 'cloud.media'),
122
- instanceOf('db', 'aws.rds')
136
+ instanceOf('db', 'aws.rds'),
123
137
  ),
124
138
  zone('us').with(
125
- instanceOf('db', 'aws.rds')
126
- )
139
+ instanceOf('db', 'aws.rds'),
140
+ ),
127
141
  ),
128
- $d.rel('prod.eu.db', 'prod.us.db', 'replicates')
142
+ $d.rel('prod.eu.db', 'prod.us.db', 'replicates'),
129
143
  ),
130
144
  views(
131
145
  view('index', $include('*')),
@@ -134,14 +148,14 @@ const local = b
134
148
  'cloud',
135
149
  $rules(
136
150
  $include('*'),
137
- $include('cloud.frontend.dashboard')
138
- )
151
+ $include('cloud.frontend.dashboard'),
152
+ ),
139
153
  ),
140
154
  deploymentView('prod').with(
141
155
  $include('customer.instance'),
142
- $include('prod.eu.zone1.ui')
143
- )
144
- )
156
+ $include('prod.eu.zone1.ui'),
157
+ ),
158
+ ),
145
159
  )
146
160
 
147
161
  export const builder = local.clone()
@@ -149,6 +163,6 @@ export const builder = local.clone()
149
163
  export const parsed = local.build()
150
164
  export type TestFqn = typeof local.Types.Fqn
151
165
 
152
- export const computed = computeViews(parsed)
166
+ export const computed = computeParsedModelData(parsed)
153
167
 
154
168
  export const model = LikeC4Model.create(computed)
@@ -1,9 +1,9 @@
1
- import type { Fqn } from '../../types'
1
+ import type { AnyAux, Fqn } from '../../types'
2
2
  import { isAncestor } from '../../utils'
3
3
  import type { DeploymentElementModel } from '../DeploymentElementModel'
4
4
  import type { ElementModel } from '../ElementModel'
5
5
 
6
- export interface Connection<Elem = ElementModel | DeploymentElementModel, Id = string> {
6
+ export interface Connection<Elem = ElementModel<AnyAux> | DeploymentElementModel<AnyAux>, Id = string> {
7
7
  readonly id: Id
8
8
  readonly source: Elem
9
9
  readonly target: Elem
@@ -1,36 +1,33 @@
1
- import { invariant } from '../../../errors'
2
- import type { IteratorLike } from '../../../types'
3
- import { stringHash } from '../../../utils'
1
+ import type { AnyAux, aux, IteratorLike } from '../../../types'
2
+ import { invariant, stringHash } from '../../../utils'
4
3
  import { customInspectSymbol } from '../../../utils/const'
5
4
  import { equals } from '../../../utils/set'
6
5
  import {
7
- type DeployedInstanceModel,
8
6
  type DeploymentElementModel,
9
7
  type DeploymentRelationModel,
10
8
  DeploymentNodeModel,
11
9
  RelationshipsAccum,
12
10
  } from '../../DeploymentElementModel'
13
11
  import type { RelationshipModel } from '../../RelationModel'
14
- import type { AnyAux } from '../../types'
15
12
  import type { Connection } from '../Connection'
16
13
 
17
14
  /**
18
15
  * Connection is ephemeral entity, result of a resolving relationships between source and target.
19
16
  * Includes direct relationships and/or between their nested elements.
20
17
  */
21
- export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
22
- implements Connection<DeploymentElementModel<M>, M['EdgeId']>
18
+ export class DeploymentConnectionModel<A extends AnyAux = AnyAux>
19
+ implements Connection<DeploymentElementModel<A>, aux.EdgeId>
23
20
  {
21
+ readonly id: aux.EdgeId
22
+
24
23
  constructor(
25
- public readonly source: DeploymentNodeModel<M> | DeployedInstanceModel<M>,
26
- public readonly target: DeploymentNodeModel<M> | DeployedInstanceModel<M>,
27
- public readonly relations: RelationshipsAccum<M>,
24
+ public readonly source: DeploymentElementModel<A>,
25
+ public readonly target: DeploymentElementModel<A>,
26
+ public readonly relations: RelationshipsAccum<A>,
28
27
  ) {
29
- this.id = stringHash(`deployment:${source.id}:${target.id}`) as M['EdgeId']
28
+ this.id = stringHash(`deployment:${source.id}:${target.id}`) as aux.EdgeId
30
29
  }
31
30
 
32
- readonly id: M['EdgeId']
33
-
34
31
  /**
35
32
  * Human readable expression of the connection
36
33
  * Mostly used for testing and debugging
@@ -39,12 +36,12 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
39
36
  return `${this.source.id} -> ${this.target.id}`
40
37
  }
41
38
 
42
- private _boundary: DeploymentNodeModel<M> | null | undefined
39
+ private _boundary: DeploymentNodeModel<A> | null | undefined
43
40
  /**
44
41
  * Common ancestor of the source and target elements.
45
42
  * Represents the boundary of the connection.
46
43
  */
47
- get boundary(): DeploymentNodeModel<M> | null {
44
+ get boundary(): DeploymentNodeModel<A> | null {
48
45
  this._boundary ??= this.source.commonAncestor(this.target)
49
46
  return this._boundary
50
47
  }
@@ -105,7 +102,7 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
105
102
  return false
106
103
  }
107
104
 
108
- public *values(): IteratorLike<RelationshipModel<M> | DeploymentRelationModel<M>> {
105
+ public *values(): IteratorLike<RelationshipModel<A> | DeploymentRelationModel<A>> {
109
106
  yield* this.relations.model
110
107
  yield* this.relations.deployment
111
108
  }
@@ -114,13 +111,13 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
114
111
  * Merge with another connections, if it has the same source and target.
115
112
  * Returns new connection with union of relationships.
116
113
  */
117
- public mergeWith(others: DeploymentConnectionModel<M>[]): DeploymentConnectionModel<M>
114
+ public mergeWith(others: DeploymentConnectionModel<A>[]): DeploymentConnectionModel<A>
118
115
  /**
119
116
  * Merge with another connection, if it has the same source and target.
120
117
  * Returns new connection with union of relationships.
121
118
  */
122
- public mergeWith(other: DeploymentConnectionModel<M>): DeploymentConnectionModel<M>
123
- public mergeWith(other: DeploymentConnectionModel<M> | DeploymentConnectionModel<M>[]): DeploymentConnectionModel<M> {
119
+ public mergeWith(other: DeploymentConnectionModel<A>): DeploymentConnectionModel<A>
120
+ public mergeWith(other: DeploymentConnectionModel<A> | DeploymentConnectionModel<A>[]): DeploymentConnectionModel<A> {
124
121
  if (Array.isArray(other)) {
125
122
  return other.reduce((acc, o) => acc.mergeWith(o), this)
126
123
  }
@@ -134,7 +131,7 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
134
131
  )
135
132
  }
136
133
 
137
- public difference(other: DeploymentConnectionModel<M>) {
134
+ public difference(other: DeploymentConnectionModel<A>) {
138
135
  return new DeploymentConnectionModel(
139
136
  this.source,
140
137
  this.target,
@@ -142,7 +139,7 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
142
139
  )
143
140
  }
144
141
 
145
- public intersect(other: DeploymentConnectionModel<M>) {
142
+ public intersect(other: DeploymentConnectionModel<A>) {
146
143
  return new DeploymentConnectionModel(
147
144
  this.source,
148
145
  this.target,
@@ -164,9 +161,9 @@ export class DeploymentConnectionModel<M extends AnyAux = AnyAux>
164
161
  * if `null` is provided in overrides, the corresponding relation set will be empty.
165
162
  */
166
163
  public update(overrides?: {
167
- model?: ReadonlySet<RelationshipModel<M>> | null
168
- deployment?: ReadonlySet<DeploymentRelationModel<M>> | null
169
- }): DeploymentConnectionModel<M> {
164
+ model?: ReadonlySet<RelationshipModel<A>> | null
165
+ deployment?: ReadonlySet<DeploymentRelationModel<A>> | null
166
+ }): DeploymentConnectionModel<A> {
170
167
  if (overrides) {
171
168
  overrides = {
172
169
  model: this.relations.model,
@@ -1,6 +1,6 @@
1
+ import type { AnyAux } from '../../../types'
1
2
  import { isSameHierarchy } from '../../../utils'
2
3
  import type { DeploymentElementModel } from '../../DeploymentElementModel'
3
- import type { AnyAux } from '../../types'
4
4
  import { DeploymentConnectionModel } from './DeploymentConnectionModel'
5
5
 
6
6
  /**
@@ -1,12 +1,12 @@
1
1
  import { isNot } from 'remeda'
2
- import { invariant } from '../../../errors'
2
+ import type { AnyAux, aux, Unknown } from '../../../types'
3
+ import { invariant } from '../../../utils'
3
4
  import { customInspectSymbol } from '../../../utils/const'
4
5
  import { ifilter, isome } from '../../../utils/iterable'
5
6
  import { difference, equals, intersection, union } from '../../../utils/set'
6
7
  import { stringHash } from '../../../utils/string-hash'
7
8
  import type { ElementModel } from '../../ElementModel'
8
9
  import type { RelationshipModel } from '../../RelationModel'
9
- import type { AnyAux } from '../../types'
10
10
  import type { Connection } from '../Connection'
11
11
  import { hasSameSourceTarget } from '../ops'
12
12
  import { findConnection } from './find'
@@ -17,23 +17,23 @@ import { findConnection } from './find'
17
17
  *
18
18
  * Merges relationships together to an single edge on the diagram.
19
19
  */
20
- export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<ElementModel<M>, M['EdgeId']> {
21
- public readonly id: M['EdgeId']
20
+ export class ConnectionModel<A extends AnyAux = Unknown> implements Connection<ElementModel<A>, aux.EdgeId> {
21
+ public readonly id: aux.EdgeId
22
22
 
23
23
  constructor(
24
- public readonly source: ElementModel<M>,
25
- public readonly target: ElementModel<M>,
26
- public readonly relations: ReadonlySet<RelationshipModel<M>> = new Set(),
24
+ public readonly source: ElementModel<A>,
25
+ public readonly target: ElementModel<A>,
26
+ public readonly relations: ReadonlySet<RelationshipModel<A>> = new Set(),
27
27
  ) {
28
- this.id = stringHash(`model:${source.id}:${target.id}`) as M['EdgeId']
28
+ this.id = stringHash(`model:${source.id}:${target.id}`) as aux.EdgeId
29
29
  }
30
30
 
31
- private _boundary: ElementModel<M> | null | undefined
31
+ private _boundary: ElementModel<A> | null | undefined
32
32
  /**
33
33
  * Common ancestor of the source and target elements.
34
34
  * Represents the boundary of the connection.
35
35
  */
36
- get boundary(): ElementModel<M> | null {
36
+ get boundary(): ElementModel<A> | null {
37
37
  return this._boundary ??= this.source.commonAncestor(this.target)
38
38
  }
39
39
 
@@ -59,7 +59,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
59
59
  return this.nonEmpty() && isome(this.relations, isNot(hasSameSourceTarget(this)))
60
60
  }
61
61
 
62
- get directRelations(): ReadonlySet<RelationshipModel<M>> {
62
+ get directRelations(): ReadonlySet<RelationshipModel<A>> {
63
63
  return new Set(ifilter(this.relations, hasSameSourceTarget(this)))
64
64
  }
65
65
 
@@ -67,7 +67,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
67
67
  return this.relations.size > 0
68
68
  }
69
69
 
70
- mergeWith(other: ConnectionModel<M>) {
70
+ mergeWith(other: ConnectionModel<A>) {
71
71
  invariant(this.source.id === other.source.id, 'Cannot merge connections with different sources')
72
72
  invariant(this.target.id === other.target.id, 'Cannot merge connections with different targets')
73
73
  return new ConnectionModel(
@@ -77,7 +77,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
77
77
  )
78
78
  }
79
79
 
80
- difference(other: ConnectionModel<M>) {
80
+ difference(other: ConnectionModel<A>) {
81
81
  return new ConnectionModel(
82
82
  this.source,
83
83
  this.target,
@@ -85,7 +85,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
85
85
  )
86
86
  }
87
87
 
88
- intersect(other: ConnectionModel<M>) {
88
+ intersect(other: ConnectionModel<A>) {
89
89
  invariant(other instanceof ConnectionModel, 'Cannot intersect connection with different type')
90
90
  return new ConnectionModel(
91
91
  this.source,
@@ -96,10 +96,11 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
96
96
 
97
97
  equals(other: Connection): boolean {
98
98
  invariant(other instanceof ConnectionModel, 'Cannot merge connection with different type')
99
- return this.id === other.id
100
- && this.source.id === other.source.id
101
- && this.target.id === other.target.id
102
- && equals(this.relations, other.relations)
99
+ const _other = other as ConnectionModel<A>
100
+ return this.id === _other.id
101
+ && this.source.id === _other.source.id
102
+ && this.target.id === _other.target.id
103
+ && equals(this.relations, _other.relations)
103
104
  }
104
105
 
105
106
  /**
@@ -108,7 +109,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
108
109
  * @param relations - A readonly set of `RelationshipModel` instances representing the new relations.
109
110
  * @returns A new `ConnectionModel` instance with the updated relations.
110
111
  */
111
- update(relations: ReadonlySet<RelationshipModel<M>>): ConnectionModel<M> {
112
+ update(relations: ReadonlySet<RelationshipModel<A>>): ConnectionModel<A> {
112
113
  return new ConnectionModel(
113
114
  this.source,
114
115
  this.target,
@@ -147,7 +148,7 @@ export class ConnectionModel<M extends AnyAux = AnyAux> implements Connection<El
147
148
  * Creates a new connection with reversed direction (target becomes source and vice versa)
148
149
  * @param search - When true, attempts to find an existing connection between the reversed nodes
149
150
  */
150
- reversed(search = false): ConnectionModel<M> {
151
+ reversed(search = false): ConnectionModel<A> {
151
152
  if (!search) {
152
153
  return new ConnectionModel(this.target, this.source)
153
154
  }
@@ -1,7 +1,7 @@
1
+ import type { AnyAux } from '../../../types'
1
2
  import { isSameHierarchy } from '../../../utils/fqn'
2
3
  import { intersection } from '../../../utils/set'
3
4
  import type { ElementModel } from '../../ElementModel'
4
- import type { AnyAux } from '../../types'
5
5
  import { ConnectionModel } from './ConnectionModel'
6
6
 
7
7
  /**
@@ -10,13 +10,13 @@ import { ConnectionModel } from './ConnectionModel'
10
10
  * @param direction - if 'both', also returns connection from target to source
11
11
  * @default `directed`
12
12
  */
13
- export function findConnection<M extends AnyAux>(
14
- source: ElementModel<M>,
15
- target: ElementModel<M>,
13
+ export function findConnection<A extends AnyAux>(
14
+ source: ElementModel<A>,
15
+ target: ElementModel<A>,
16
16
  direction: 'directed' | 'both' = 'directed',
17
17
  ):
18
- | [ConnectionModel<M>, ConnectionModel<M>]
19
- | [ConnectionModel<M>]
18
+ | [ConnectionModel<A>, ConnectionModel<A>]
19
+ | [ConnectionModel<A>]
20
20
  | []
21
21
  {
22
22
  if (source === target) {
@@ -69,7 +69,7 @@ export function findConnection<M extends AnyAux>(
69
69
  */
70
70
  export function findConnectionsBetween<M extends AnyAux>(
71
71
  element: ElementModel<M>,
72
- others: Iterable<ElementModel<NoInfer<M>>>,
72
+ others: Iterable<ElementModel<M>>,
73
73
  direction: 'directed' | 'both' = 'both',
74
74
  ): readonly ConnectionModel<M>[] {
75
75
  if (element.allIncoming.size === 0 && element.allOutgoing.size === 0) {
@@ -136,14 +136,14 @@ export function findDescendantConnections<C extends ConnectionElemId>(
136
136
  return connections.filter(isNestedConnection(connection))
137
137
  }
138
138
 
139
- export function mergeConnections<C extends Connection>(
140
- connections: ReadonlyArray<C>,
141
- ): C[] {
142
- const map = new Map<C['id'], C>()
139
+ export function mergeConnections<C extends IterableContainer<Connection<any, any>>>(
140
+ connections: C,
141
+ ): Array<C[number]> {
142
+ const map = new Map<C[number]['id'], C[number]>()
143
143
  for (const conn of connections) {
144
144
  const existing = map.get(conn.id)
145
145
  if (existing) {
146
- map.set(conn.id, conn.mergeWith(existing) as C)
146
+ map.set(conn.id, conn.mergeWith(existing))
147
147
  } else {
148
148
  map.set(conn.id, conn)
149
149
  }
@@ -155,7 +155,7 @@ export function mergeConnections<C extends Connection>(
155
155
  * Excludes the values existing in `other` array.
156
156
  * The output maintains the same order as the input.
157
157
  */
158
- export function differenceConnections<C extends Connection>(
158
+ export function differenceConnections<C extends Connection<any, any>>(
159
159
  source: Iterable<C>,
160
160
  exclude: Iterable<C>,
161
161
  ): C[] {