@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,45 +1,41 @@
1
- import { isTruthy } from 'remeda'
1
+ import { isTruthy, unique } from 'remeda'
2
2
  import type { SetRequired } from 'type-fest'
3
- import type { IteratorLike } from '../types/_common'
3
+ import type { Any, AnyAux, Color, IteratorLike } from '../types'
4
4
  import {
5
5
  type Element as C4Element,
6
- type ElementKind as C4ElementKind,
7
6
  type ElementShape as C4ElementShape,
8
7
  type ElementStyle,
8
+ type IconUrl,
9
9
  type Link,
10
+ type ProjectId,
10
11
  DefaultElementShape,
11
12
  DefaultShapeSize,
12
13
  DefaultThemeColor,
13
- } from '../types/element'
14
- import {
15
- type IconUrl,
16
- type ProjectId,
17
- type Tag as C4Tag,
18
14
  splitGlobalFqn,
19
- } from '../types/scalars'
20
- import type { ThemeColor } from '../types/theme'
21
- import { commonAncestor, hierarchyLevel, isAncestor, sortNaturalByFqn } from '../utils'
15
+ } from '../types'
16
+ import * as aux from '../types/aux'
17
+ import { commonAncestor, hierarchyLevel, ihead, isAncestor, memoizeProp, sortNaturalByFqn } from '../utils'
22
18
  import { type DeployedInstancesIterator } from './DeploymentElementModel'
23
19
  import type { LikeC4Model } from './LikeC4Model'
24
20
  import type { RelationshipModel, RelationshipsIterator } from './RelationModel'
25
- import type { AnyAux, IncomingFilter, OutgoingFilter } from './types'
26
- import type { LikeC4ViewModel, ViewsIterator } from './view/LikeC4ViewModel'
21
+ import type { $ViewWithType, IncomingFilter, OutgoingFilter } from './types'
22
+ import type { LikeC4ViewModel } from './view/LikeC4ViewModel'
27
23
 
28
24
  export type ElementsIterator<M extends AnyAux> = IteratorLike<ElementModel<M>>
29
25
 
30
- export class ElementModel<M extends AnyAux = AnyAux> {
31
- readonly id: M['Fqn']
32
- readonly _literalId: M['Element']
26
+ export class ElementModel<A extends AnyAux = Any> {
27
+ readonly id: aux.Fqn<A>
28
+ readonly _literalId: aux.ElementId<A>
33
29
  readonly hierarchyLevel: number
34
30
 
35
31
  readonly imported: null | {
36
32
  from: ProjectId
37
- fqn: string
33
+ fqn: aux.Fqn<A>
38
34
  }
39
35
 
40
36
  constructor(
41
- public readonly $model: LikeC4Model<M>,
42
- public readonly $element: C4Element,
37
+ public readonly $model: LikeC4Model<A>,
38
+ public readonly $element: C4Element<A>,
43
39
  ) {
44
40
  this.id = this.$element.id
45
41
  this._literalId = this.$element.id
@@ -56,11 +52,11 @@ export class ElementModel<M extends AnyAux = AnyAux> {
56
52
  }
57
53
  }
58
54
 
59
- get parent(): ElementModel<M> | null {
55
+ get parent(): ElementModel<A> | null {
60
56
  return this.$model.parent(this)
61
57
  }
62
58
 
63
- get kind(): C4ElementKind {
59
+ get kind(): aux.ElementKind<A> {
64
60
  return this.$element.kind
65
61
  }
66
62
 
@@ -68,16 +64,25 @@ export class ElementModel<M extends AnyAux = AnyAux> {
68
64
  return this.$element.shape ?? DefaultElementShape
69
65
  }
70
66
 
71
- get color(): ThemeColor {
72
- return this.$element.color as ThemeColor ?? DefaultThemeColor
67
+ get color(): Color {
68
+ return this.$element.color as Color ?? DefaultThemeColor
73
69
  }
74
70
 
75
71
  get icon(): IconUrl | null {
76
72
  return this.$element.icon ?? null
77
73
  }
78
74
 
79
- get tags(): ReadonlyArray<C4Tag> {
80
- return this.$element.tags ?? []
75
+ /**
76
+ * Returns all tags of the element.
77
+ * It includes tags from the element and its kind.
78
+ */
79
+ get tags(): aux.Tags<A> {
80
+ return memoizeProp(this, Symbol.for('tags'), () => {
81
+ return unique([
82
+ ...(this.$element.tags ?? []),
83
+ ...(this.$model.specification.elements[this.$element.kind]?.tags ?? []),
84
+ ] as aux.Tags<A>)
85
+ })
81
86
  }
82
87
 
83
88
  get title(): string {
@@ -85,19 +90,19 @@ export class ElementModel<M extends AnyAux = AnyAux> {
85
90
  }
86
91
 
87
92
  get description(): string | null {
88
- return this.$element.description
93
+ return this.$element.description ?? null
89
94
  }
90
95
 
91
96
  get technology(): string | null {
92
- return this.$element.technology
97
+ return this.$element.technology ?? null
93
98
  }
94
99
 
95
100
  get links(): ReadonlyArray<Link> {
96
101
  return this.$element.links ?? []
97
102
  }
98
103
 
99
- get defaultView(): LikeC4ViewModel<M> | null {
100
- return this.scopedViews().next().value ?? null
104
+ get defaultView(): LikeC4ViewModel<A, $ViewWithType<A, 'element'> & { viewOf: aux.StrictFqn<A> }> | null {
105
+ return memoizeProp(this, Symbol.for('defaultView'), () => ihead(this.scopedViews()) ?? null)
101
106
  }
102
107
 
103
108
  get isRoot(): boolean {
@@ -111,11 +116,11 @@ export class ElementModel<M extends AnyAux = AnyAux> {
111
116
  }
112
117
  }
113
118
 
114
- public isAncestorOf(another: ElementModel<M>): boolean {
119
+ public isAncestorOf(another: ElementModel<A>): boolean {
115
120
  return isAncestor(this, another)
116
121
  }
117
122
 
118
- public isDescendantOf(another: ElementModel<M>): boolean {
123
+ public isDescendantOf(another: ElementModel<A>): boolean {
119
124
  return isAncestor(another, this)
120
125
  }
121
126
 
@@ -123,26 +128,26 @@ export class ElementModel<M extends AnyAux = AnyAux> {
123
128
  * Get all ancestor elements (i.e. parent, parent’s parent, etc.)
124
129
  * (from closest to root)
125
130
  */
126
- public ancestors(): ElementsIterator<M> {
131
+ public ancestors(): ElementsIterator<A> {
127
132
  return this.$model.ancestors(this)
128
133
  }
129
134
 
130
135
  /**
131
136
  * Returns the common ancestor of this element and another element.
132
137
  */
133
- public commonAncestor(another: ElementModel<M>): ElementModel<M> | null {
138
+ public commonAncestor(another: ElementModel<A>): ElementModel<A> | null {
134
139
  const common = commonAncestor(this.id, another.id)
135
140
  return common ? this.$model.element(common) : null
136
141
  }
137
142
 
138
- public children(): ReadonlySet<ElementModel<M>> {
143
+ public children(): ReadonlySet<ElementModel<A>> {
139
144
  return this.$model.children(this)
140
145
  }
141
146
 
142
147
  /**
143
148
  * Get all descendant elements (i.e. children, children’s children, etc.)
144
149
  */
145
- public descendants(sort?: 'asc' | 'desc'): ElementsIterator<M> {
150
+ public descendants(sort?: 'asc' | 'desc'): ElementsIterator<A> {
146
151
  if (sort) {
147
152
  const sorted = sortNaturalByFqn([...this.$model.descendants(this)], sort)
148
153
  return sorted[Symbol.iterator]()
@@ -153,15 +158,15 @@ export class ElementModel<M extends AnyAux = AnyAux> {
153
158
  /**
154
159
  * Get all sibling (i.e. same parent)
155
160
  */
156
- public siblings(): ElementsIterator<M> {
161
+ public siblings(): ElementsIterator<A> {
157
162
  return this.$model.siblings(this)
158
163
  }
159
164
 
160
165
  /**
161
166
  * Resolve siblings of the element and its ancestors
162
- * (from closest to root)
167
+ * (from closest parent to root)
163
168
  */
164
- public *ascendingSiblings(): ElementsIterator<M> {
169
+ public *ascendingSiblings(): ElementsIterator<A> {
165
170
  yield* this.siblings()
166
171
  for (const ancestor of this.ancestors()) {
167
172
  yield* ancestor.siblings()
@@ -173,7 +178,7 @@ export class ElementModel<M extends AnyAux = AnyAux> {
173
178
  * Resolve siblings of the element and its ancestors
174
179
  * (from root to closest)
175
180
  */
176
- public *descendingSiblings(): ElementsIterator<M> {
181
+ public *descendingSiblings(): ElementsIterator<A> {
177
182
  for (const ancestor of [...this.ancestors()].reverse()) {
178
183
  yield* ancestor.siblings()
179
184
  }
@@ -181,11 +186,11 @@ export class ElementModel<M extends AnyAux = AnyAux> {
181
186
  return
182
187
  }
183
188
 
184
- public incoming(filter: IncomingFilter = 'all'): RelationshipsIterator<M> {
189
+ public incoming(filter: IncomingFilter = 'all'): RelationshipsIterator<A> {
185
190
  return this.$model.incoming(this, filter)
186
191
  }
187
- public *incomers(filter: IncomingFilter = 'all'): ElementsIterator<M> {
188
- const unique = new Set<M['Fqn']>()
192
+ public *incomers(filter: IncomingFilter = 'all'): ElementsIterator<A> {
193
+ const unique = new Set<aux.StrictFqn<A>>()
189
194
  for (const r of this.incoming(filter)) {
190
195
  if (unique.has(r.source.id)) {
191
196
  continue
@@ -195,11 +200,11 @@ export class ElementModel<M extends AnyAux = AnyAux> {
195
200
  }
196
201
  return
197
202
  }
198
- public outgoing(filter: OutgoingFilter = 'all'): RelationshipsIterator<M> {
203
+ public outgoing(filter: OutgoingFilter = 'all'): RelationshipsIterator<A> {
199
204
  return this.$model.outgoing(this, filter)
200
205
  }
201
- public *outgoers(filter: OutgoingFilter = 'all'): ElementsIterator<M> {
202
- const unique = new Set<M['Fqn']>()
206
+ public *outgoers(filter: OutgoingFilter = 'all'): ElementsIterator<A> {
207
+ const unique = new Set<aux.StrictFqn<A>>()
203
208
  for (const r of this.outgoing(filter)) {
204
209
  if (unique.has(r.target.id)) {
205
210
  continue
@@ -210,65 +215,71 @@ export class ElementModel<M extends AnyAux = AnyAux> {
210
215
  return
211
216
  }
212
217
 
213
- protected cachedOutgoing: Set<RelationshipModel<M>> | null = null
214
- protected cachedIncoming: Set<RelationshipModel<M>> | null = null
215
-
216
- public get allOutgoing(): ReadonlySet<RelationshipModel<M>> {
217
- this.cachedOutgoing ??= new Set(this.outgoing())
218
- return this.cachedOutgoing
218
+ public get allOutgoing(): ReadonlySet<RelationshipModel<A>> {
219
+ return memoizeProp(this, Symbol.for('allOutgoing'), () => new Set(this.outgoing()))
219
220
  }
220
221
 
221
- public get allIncoming(): ReadonlySet<RelationshipModel<M>> {
222
- this.cachedIncoming ??= new Set(this.incoming())
223
- return this.cachedIncoming
222
+ public get allIncoming(): ReadonlySet<RelationshipModel<A>> {
223
+ return memoizeProp(this, Symbol.for('allIncoming'), () => new Set(this.incoming()))
224
224
  }
225
225
 
226
226
  /**
227
227
  * Iterate over all views that include this element.
228
228
  */
229
- public *views(): ViewsIterator<M> {
230
- for (const view of this.$model.views()) {
231
- if (view.includesElement(this.id)) {
232
- yield view
229
+ public views(): ReadonlySet<LikeC4ViewModel<A>> {
230
+ return memoizeProp(this, Symbol.for('views'), () => {
231
+ const views = new Set<LikeC4ViewModel<A>>()
232
+ for (const view of this.$model.views()) {
233
+ if (view.includesElement(this.id)) {
234
+ views.add(view)
235
+ }
233
236
  }
234
- }
235
- return
237
+ return views
238
+ })
236
239
  }
237
240
 
238
241
  /**
239
242
  * Iterate over all views that scope this element.
240
243
  * It is possible that element is not included in the view.
241
244
  */
242
- public *scopedViews(): ViewsIterator<M> {
243
- for (const vm of this.$model.views()) {
244
- if (vm.isElementView() && vm.$view.viewOf === this.id) {
245
- yield vm
245
+ public scopedViews(): ReadonlySet<
246
+ LikeC4ViewModel<A, $ViewWithType<A, 'element'> & { viewOf: aux.StrictFqn<A> }>
247
+ > {
248
+ return memoizeProp(this, Symbol.for('scopedViews'), () => {
249
+ const views = new Set<LikeC4ViewModel<A, $ViewWithType<A, 'element'> & { viewOf: aux.StrictFqn<A> }>>()
250
+ for (const vm of this.$model.views()) {
251
+ if (vm.isScopedElementView() && vm.viewOf.id === this.id) {
252
+ views.add(vm)
253
+ }
246
254
  }
247
- }
248
- return
255
+ return views
256
+ })
249
257
  }
250
258
 
251
259
  /**
252
260
  * @returns true if the element is deployed
253
261
  */
254
262
  public isDeployed(): boolean {
255
- return isTruthy(this.deployments().next().value)
263
+ return isTruthy(ihead(this.deployments()))
256
264
  }
257
265
 
258
- public deployments(): DeployedInstancesIterator<M> {
266
+ public deployments(): DeployedInstancesIterator<A> {
259
267
  return this.$model.deployment.instancesOf(this)
260
268
  }
261
269
 
262
- public getMetadata(): Record<string, string>
263
- public getMetadata(field: string): string | undefined
264
- public getMetadata(field?: string) {
270
+ public getMetadata(): aux.Metadata<A>
271
+ public getMetadata(field: aux.MetadataKey<A>): string | undefined
272
+ public getMetadata(field?: aux.MetadataKey<A>) {
265
273
  if (field) {
266
274
  return this.$element.metadata?.[field]
267
275
  }
268
276
  return this.$element.metadata ?? {}
269
277
  }
270
- }
271
278
 
272
- export function isElementModel<M extends AnyAux = AnyAux>(element: any): element is ElementModel<M> {
273
- return element instanceof ElementModel
279
+ /**
280
+ * Checks if the element has the given tag.
281
+ */
282
+ public isTagged(tag: aux.LooseTag<A>): boolean {
283
+ return this.tags.includes(tag as aux.Tag<A>)
284
+ }
274
285
  }