@likec4/core 1.41.0 → 1.42.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 (255) hide show
  1. package/builder/package.json +4 -0
  2. package/compute-view/package.json +4 -0
  3. package/compute-view/relationships/package.json +4 -0
  4. package/dist/builder/index.d.mts +13 -11
  5. package/dist/builder/index.mjs +111 -91
  6. package/dist/compute-view/index.d.mts +8 -7
  7. package/dist/compute-view/index.mjs +14 -11
  8. package/dist/compute-view/relationships-view/index.d.mts +9 -8
  9. package/dist/compute-view/relationships-view/index.mjs +6 -6
  10. package/dist/index.d.mts +7 -7
  11. package/dist/index.mjs +11 -11
  12. package/dist/model/connection/deployment/index.d.mts +11 -10
  13. package/dist/model/connection/deployment/index.mjs +2 -2
  14. package/dist/model/connection/index.d.mts +12 -11
  15. package/dist/model/connection/index.mjs +3 -3
  16. package/dist/model/connection/model/index.d.mts +11 -10
  17. package/dist/model/connection/model/index.mjs +2 -2
  18. package/dist/model/index.d.mts +14 -14
  19. package/dist/model/index.mjs +4 -5
  20. package/dist/shared/{core.Ae86Y3tB.mjs → core.01VTr9qu.mjs} +8 -26
  21. package/dist/shared/core.1vX5a9AY.mjs +86 -0
  22. package/dist/shared/{core.BVNaR17u.mjs → core.B7KhhkRY.mjs} +1 -1
  23. package/dist/shared/core.B85MJLTf.mjs +5 -0
  24. package/dist/shared/{core.DA5vzwZ9.mjs → core.BIqHjQiH.mjs} +56 -42
  25. package/dist/shared/core.BKlholso.mjs +3 -0
  26. package/dist/shared/core.BR4zXDH-.mjs +13 -0
  27. package/dist/shared/{core.CXy1NLUG.mjs → core.BYNkXQ8A.mjs} +21 -12
  28. package/dist/shared/{core.BuoXfSMj.mjs → core.BbE4y-yl.mjs} +1 -1
  29. package/dist/shared/core.BoYfZOBm.mjs +3 -0
  30. package/dist/shared/core.BsSXS-_R.mjs +7 -0
  31. package/dist/shared/{core.DJp8fgok.mjs → core.BzTakU3I.mjs} +14 -10
  32. package/dist/shared/{core.4u1dVmfX.mjs → core.C2TiyjI6.mjs} +2 -2
  33. package/dist/shared/{core.DLpidoWc.mjs → core.C3JowhaZ.mjs} +3 -3
  34. package/dist/shared/{core.CNGyqkJh.mjs → core.C4x8aaWa.mjs} +3 -1
  35. package/dist/shared/{core.BB6zA-UU.mjs → core.C8YY6Uub.mjs} +38 -9
  36. package/dist/shared/{core.Asc11Mjy.mjs → core.C8sl5Y8Z.mjs} +122 -58
  37. package/dist/shared/{core.BvMRMo7Z.mjs → core.CNgZvKb8.mjs} +3 -5198
  38. package/dist/shared/{core.CUG6vpyL.d.mts → core.CQngdcuj.d.mts} +85 -4
  39. package/dist/shared/{core.Be1n9a0i.mjs → core.C_Ni6yHl.mjs} +5 -4
  40. package/dist/shared/core.CbT8JVYL.mjs +5 -0
  41. package/dist/shared/core.CqAJJpK_.mjs +3 -0
  42. package/dist/shared/{core.BXsxn-hf.d.mts → core.D0PjZzIS.d.mts} +27 -15
  43. package/dist/shared/{core.DgesAwC8.d.mts → core.D5fzJWbF.d.mts} +2 -2
  44. package/dist/shared/{core.hfOE3RfK.d.mts → core.DACpKp35.d.mts} +5 -5
  45. package/dist/shared/core.DFi2dOTl.mjs +39548 -0
  46. package/dist/shared/{core.xSQO0XYD.d.mts → core.DIol3syK.d.mts} +2 -2
  47. package/dist/shared/{core.DlG1xWt2.mjs → core.DMMOWQqc.mjs} +3 -2
  48. package/dist/shared/core.DNbUPnve.mjs +3990 -0
  49. package/dist/shared/{core.CCD1ID81.mjs → core.DRJma0Ol.mjs} +4 -3
  50. package/dist/shared/{core.DgttqsJc.mjs → core.DRhg-gVU.mjs} +9 -9
  51. package/dist/shared/core.DSO_rTC2.mjs +5322 -0
  52. package/dist/shared/{core.FUPplpae.d.mts → core.D_vkffV4.d.mts} +4 -2
  53. package/dist/shared/core.DdMJk7nx.d.mts +476 -0
  54. package/dist/shared/{core.BhpgpOep.d.mts → core.Dgs6-nuz.d.mts} +2 -2
  55. package/dist/shared/{core.Be4Jy9Qx.mjs → core.FZ305VYd.mjs} +2 -2
  56. package/dist/shared/core.OHD4KXm9.mjs +5 -0
  57. package/dist/shared/{core.GTgsmXS_.mjs → core.QJD_fcrc.mjs} +2 -2
  58. package/dist/shared/core.RfnaEmgA.mjs +7 -0
  59. package/dist/shared/core.fHR_8Tnq.d.mts +450 -0
  60. package/dist/shared/{core.D0EgVMQK.mjs → core.lRvxPoao.mjs} +14 -12
  61. package/dist/shared/{core.CaT0SUUK.mjs → core.rCeaAqgW.mjs} +1 -84
  62. package/dist/shared/{core.zxTBF_PD.d.mts → core.s9uwOt60.d.mts} +4 -4
  63. package/dist/shared/core.yna0OdV5.d.mts +98 -0
  64. package/dist/styles/index.d.mts +106 -0
  65. package/dist/styles/index.mjs +1 -0
  66. package/dist/types/_aux.d.mts +2 -2
  67. package/dist/types/expression-model.d.mts +3 -4
  68. package/dist/types/expression.d.mts +3 -4
  69. package/dist/types/fqnRef.d.mts +2 -2
  70. package/dist/types/fqnRef.mjs +3 -3
  71. package/dist/types/index.d.mts +8 -8
  72. package/dist/types/index.mjs +150 -5
  73. package/dist/types/scalar.mjs +3 -2
  74. package/dist/utils/graphology/index.d.mts +1864 -0
  75. package/dist/utils/graphology/index.mjs +1 -0
  76. package/dist/utils/index.d.mts +11 -6
  77. package/dist/utils/index.mjs +21 -37
  78. package/dist/utils/iterable/index.d.mts +1 -1
  79. package/dist/utils/iterable/index.mjs +45 -7
  80. package/model/package.json +4 -0
  81. package/package.json +42 -24
  82. package/styles/package.json +4 -0
  83. package/types/package.json +4 -0
  84. package/utils/graphology/package.json +4 -0
  85. package/utils/package.json +4 -0
  86. package/dist/shared/core.6_Vp2iiN.mjs +0 -172
  87. package/dist/shared/core.CUw_2J9j.mjs +0 -47
  88. package/dist/shared/core.CzdwsPmY.d.mts +0 -69
  89. package/dist/shared/core.D-ZGWDDt.d.mts +0 -831
  90. package/dist/shared/core.DoM6aM9N.mjs +0 -7
  91. package/dist/shared/core.ILwny7BV.mjs +0 -38
  92. package/dist/theme/index.d.mts +0 -11
  93. package/dist/theme/index.mjs +0 -232
  94. package/src/builder/Builder.deployment.ts +0 -224
  95. package/src/builder/Builder.deploymentModel.ts +0 -449
  96. package/src/builder/Builder.element.ts +0 -241
  97. package/src/builder/Builder.model.ts +0 -494
  98. package/src/builder/Builder.ts +0 -946
  99. package/src/builder/Builder.view-common.ts +0 -273
  100. package/src/builder/Builder.view-deployment.ts +0 -135
  101. package/src/builder/Builder.view-element.ts +0 -202
  102. package/src/builder/Builder.views.ts +0 -399
  103. package/src/builder/Builder.with.ts +0 -156
  104. package/src/builder/_types.ts +0 -324
  105. package/src/builder/index.ts +0 -11
  106. package/src/compute-view/compute-view.ts +0 -80
  107. package/src/compute-view/deployment-view/_types.ts +0 -38
  108. package/src/compute-view/deployment-view/clean-connections.ts +0 -236
  109. package/src/compute-view/deployment-view/compute.ts +0 -94
  110. package/src/compute-view/deployment-view/memory/index.ts +0 -9
  111. package/src/compute-view/deployment-view/memory/memory.ts +0 -96
  112. package/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts +0 -18
  113. package/src/compute-view/deployment-view/predicates/deploymentRefs.ts +0 -154
  114. package/src/compute-view/deployment-view/predicates/index.ts +0 -8
  115. package/src/compute-view/deployment-view/predicates/relation-direct.ts +0 -243
  116. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +0 -70
  117. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +0 -101
  118. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +0 -95
  119. package/src/compute-view/deployment-view/predicates/relation-where.ts +0 -18
  120. package/src/compute-view/deployment-view/predicates/utils.ts +0 -282
  121. package/src/compute-view/deployment-view/predicates/wildcard.ts +0 -41
  122. package/src/compute-view/deployment-view/stages/stage-exclude.ts +0 -5
  123. package/src/compute-view/deployment-view/stages/stage-final.ts +0 -245
  124. package/src/compute-view/deployment-view/stages/stage-include.ts +0 -95
  125. package/src/compute-view/deployment-view/utils.ts +0 -297
  126. package/src/compute-view/dynamic-view/compute.ts +0 -312
  127. package/src/compute-view/element-view/_types.ts +0 -47
  128. package/src/compute-view/element-view/clean-connections.ts +0 -117
  129. package/src/compute-view/element-view/compute.ts +0 -324
  130. package/src/compute-view/element-view/memory/NodeGroup.ts +0 -31
  131. package/src/compute-view/element-view/memory/index.ts +0 -10
  132. package/src/compute-view/element-view/memory/memory.ts +0 -178
  133. package/src/compute-view/element-view/memory/stage-exclude.ts +0 -59
  134. package/src/compute-view/element-view/memory/stage-final.ts +0 -129
  135. package/src/compute-view/element-view/memory/stage-include.ts +0 -130
  136. package/src/compute-view/element-view/predicates/_utils.ts +0 -91
  137. package/src/compute-view/element-view/predicates/element-expand.ts +0 -29
  138. package/src/compute-view/element-view/predicates/element-kind-tag.ts +0 -27
  139. package/src/compute-view/element-view/predicates/element-ref.ts +0 -24
  140. package/src/compute-view/element-view/predicates/relation-direct.ts +0 -321
  141. package/src/compute-view/element-view/predicates/relation-in-out.ts +0 -64
  142. package/src/compute-view/element-view/predicates/relation-in.ts +0 -115
  143. package/src/compute-view/element-view/predicates/relation-out.ts +0 -119
  144. package/src/compute-view/element-view/predicates/wildcard.ts +0 -88
  145. package/src/compute-view/element-view/utils.ts +0 -65
  146. package/src/compute-view/index.ts +0 -4
  147. package/src/compute-view/memory/AbstractMemory.ts +0 -45
  148. package/src/compute-view/memory/AbstractStageExclude.ts +0 -215
  149. package/src/compute-view/memory/AbstractStageInclude.ts +0 -200
  150. package/src/compute-view/memory/_types.ts +0 -148
  151. package/src/compute-view/memory/index.ts +0 -5
  152. package/src/compute-view/memory/ops.ts +0 -43
  153. package/src/compute-view/relationships-view/_types.ts +0 -16
  154. package/src/compute-view/relationships-view/compute.ts +0 -159
  155. package/src/compute-view/relationships-view/index.ts +0 -3
  156. package/src/compute-view/relationships-view/layout.ts +0 -358
  157. package/src/compute-view/relationships-view/utils.ts +0 -73
  158. package/src/compute-view/utils/ancestorsOfNode.ts +0 -19
  159. package/src/compute-view/utils/applyCustomElementProperties.ts +0 -107
  160. package/src/compute-view/utils/applyCustomRelationProperties.ts +0 -58
  161. package/src/compute-view/utils/applyViewRuleStyles.ts +0 -73
  162. package/src/compute-view/utils/buildComputedNodes.ts +0 -166
  163. package/src/compute-view/utils/buildElementNotations.ts +0 -64
  164. package/src/compute-view/utils/elementExpressionToPredicate.ts +0 -50
  165. package/src/compute-view/utils/link-nodes-with-edges.ts +0 -56
  166. package/src/compute-view/utils/merge-props-from-relationships.ts +0 -161
  167. package/src/compute-view/utils/relationExpressionToPredicates.ts +0 -55
  168. package/src/compute-view/utils/resolve-extended-views.ts +0 -85
  169. package/src/compute-view/utils/resolve-global-rules.ts +0 -88
  170. package/src/compute-view/utils/topological-sort.ts +0 -256
  171. package/src/compute-view/utils/view-hash.ts +0 -45
  172. package/src/compute-view/utils/with-readable-edges.ts +0 -40
  173. package/src/index.ts +0 -32
  174. package/src/model/DeploymentElementModel.ts +0 -712
  175. package/src/model/DeploymentModel.ts +0 -393
  176. package/src/model/ElementModel.ts +0 -316
  177. package/src/model/LikeC4Model.ts +0 -882
  178. package/src/model/RelationModel.ts +0 -152
  179. package/src/model/connection/Connection.ts +0 -72
  180. package/src/model/connection/deployment/DeploymentConnectionModel.ts +0 -185
  181. package/src/model/connection/deployment/find.ts +0 -120
  182. package/src/model/connection/deployment/index.ts +0 -8
  183. package/src/model/connection/index.ts +0 -22
  184. package/src/model/connection/model/ConnectionModel.ts +0 -158
  185. package/src/model/connection/model/find.ts +0 -117
  186. package/src/model/connection/model/index.ts +0 -8
  187. package/src/model/connection/ops.ts +0 -276
  188. package/src/model/guards.ts +0 -77
  189. package/src/model/index.ts +0 -72
  190. package/src/model/types.ts +0 -67
  191. package/src/model/utils.ts +0 -66
  192. package/src/model/view/EdgeModel.ts +0 -121
  193. package/src/model/view/LikeC4ViewModel.ts +0 -361
  194. package/src/model/view/LikeC4ViewsFolder.ts +0 -151
  195. package/src/model/view/NodeModel.ts +0 -247
  196. package/src/theme/element.ts +0 -61
  197. package/src/theme/index.ts +0 -127
  198. package/src/theme/relationships.ts +0 -54
  199. package/src/types/RichText.ts +0 -205
  200. package/src/types/_aux.ts +0 -317
  201. package/src/types/_common.ts +0 -102
  202. package/src/types/const.ts +0 -34
  203. package/src/types/expression-model.ts +0 -294
  204. package/src/types/expression.ts +0 -313
  205. package/src/types/fqnRef.ts +0 -91
  206. package/src/types/geometry.ts +0 -159
  207. package/src/types/global.ts +0 -21
  208. package/src/types/index.ts +0 -44
  209. package/src/types/model-data.ts +0 -77
  210. package/src/types/model-deployment.ts +0 -78
  211. package/src/types/model-dump.ts +0 -79
  212. package/src/types/model-logical.ts +0 -126
  213. package/src/types/model-spec.ts +0 -88
  214. package/src/types/operators.ts +0 -156
  215. package/src/types/project.ts +0 -14
  216. package/src/types/scalar.ts +0 -162
  217. package/src/types/styles.ts +0 -122
  218. package/src/types/view-changes.ts +0 -32
  219. package/src/types/view-common.ts +0 -157
  220. package/src/types/view-computed.ts +0 -126
  221. package/src/types/view-layouted.ts +0 -94
  222. package/src/types/view-parsed.deployment.ts +0 -39
  223. package/src/types/view-parsed.dynamic.ts +0 -89
  224. package/src/types/view-parsed.element.ts +0 -65
  225. package/src/types/view.ts +0 -113
  226. package/src/utils/common-head.ts +0 -22
  227. package/src/utils/compare-natural.ts +0 -60
  228. package/src/utils/const.ts +0 -1
  229. package/src/utils/fqn.ts +0 -302
  230. package/src/utils/getOrCreate.ts +0 -8
  231. package/src/utils/guards.ts +0 -9
  232. package/src/utils/index.ts +0 -68
  233. package/src/utils/invariant.ts +0 -29
  234. package/src/utils/iterable/_types.ts +0 -5
  235. package/src/utils/iterable/filter.ts +0 -55
  236. package/src/utils/iterable/find.ts +0 -38
  237. package/src/utils/iterable/first.ts +0 -48
  238. package/src/utils/iterable/flat.ts +0 -17
  239. package/src/utils/iterable/head.ts +0 -22
  240. package/src/utils/iterable/index.ts +0 -15
  241. package/src/utils/iterable/map.ts +0 -40
  242. package/src/utils/iterable/reduce.ts +0 -24
  243. package/src/utils/iterable/some.ts +0 -36
  244. package/src/utils/iterable/to.ts +0 -19
  245. package/src/utils/iterable/unique.ts +0 -23
  246. package/src/utils/markdown/index.ts +0 -2
  247. package/src/utils/markdown/to-html.ts +0 -32
  248. package/src/utils/markdown/to-text.ts +0 -14
  249. package/src/utils/memoize-prop.ts +0 -30
  250. package/src/utils/mnemonist.ts +0 -9
  251. package/src/utils/object-hash.ts +0 -14
  252. package/src/utils/promises.ts +0 -24
  253. package/src/utils/relations.ts +0 -36
  254. package/src/utils/set.ts +0 -83
  255. package/src/utils/string-hash.ts +0 -16
@@ -1,393 +0,0 @@
1
- import { values } from 'remeda'
2
- import {
3
- type Any,
4
- type DeploymentElement,
5
- type DeploymentRelationship,
6
- type IteratorLike,
7
- FqnRef,
8
- isDeploymentNode,
9
- } from '../types'
10
- import * as aux from '../types/_aux'
11
- import { invariant, nonNullable } from '../utils'
12
- import { ancestorsFqn, parentFqn, sortParentsFirst } from '../utils/fqn'
13
- import { getOrCreate } from '../utils/getOrCreate'
14
- import { DefaultMap } from '../utils/mnemonist'
15
- import {
16
- type DeployedInstancesIterator,
17
- type DeploymentElementModel,
18
- type DeploymentElementsIterator,
19
- type DeploymentNodesIterator,
20
- DeployedInstanceModel,
21
- DeploymentNodeModel,
22
- DeploymentRelationModel,
23
- NestedElementOfDeployedInstanceModel,
24
- } from './DeploymentElementModel'
25
- import type { LikeC4Model } from './LikeC4Model'
26
- import {
27
- type $ModelData,
28
- type DeploymentOrFqn,
29
- type ElementOrFqn,
30
- type IncomingFilter,
31
- type OutgoingFilter,
32
- type RelationOrId,
33
- } from './types'
34
- import { getId } from './utils'
35
- import type { LikeC4ViewModel } from './view/LikeC4ViewModel'
36
-
37
- export class LikeC4DeploymentModel<A extends Any = Any> {
38
- readonly #elements = new Map<aux.DeploymentFqn<A>, DeploymentElementModel<A>>()
39
- // Parent element for given FQN
40
- readonly #parents = new Map<aux.DeploymentFqn<A>, DeploymentNodeModel<A>>()
41
- // Children elements for given FQN
42
- readonly #children = new DefaultMap<aux.DeploymentFqn<A>, Set<DeploymentElementModel<A>>>(() => new Set())
43
-
44
- // Keep track of instances of the logical element
45
- readonly #instancesOf = new DefaultMap<aux.Fqn<A>, Set<DeployedInstanceModel<A>>>(() => new Set())
46
-
47
- readonly #rootElements = new Set<DeploymentNodeModel<A>>()
48
-
49
- readonly #relations = new Map<aux.RelationId, DeploymentRelationModel<A>>()
50
-
51
- // Incoming to an element or its descendants
52
- readonly #incoming = new DefaultMap<aux.DeploymentFqn<A>, Set<DeploymentRelationModel<A>>>(() => new Set())
53
-
54
- // Outgoing from an element or its descendants
55
- readonly #outgoing = new DefaultMap<aux.DeploymentFqn<A>, Set<DeploymentRelationModel<A>>>(() => new Set())
56
-
57
- // Relationships inside the element, among descendants
58
- readonly #internal = new DefaultMap<aux.DeploymentFqn<A>, Set<DeploymentRelationModel<A>>>(() => new Set())
59
-
60
- // readonly #views = new Map<ViewID, LikeC4ViewModel<A>>()
61
-
62
- readonly #allTags = new DefaultMap<aux.Tag<A>, Set<DeploymentElementModel<A> | DeploymentRelationModel<A>>>(
63
- () => new Set(),
64
- )
65
-
66
- readonly #nestedElementsOfDeployment = new Map<
67
- `${aux.DeploymentId<A>}@${aux.ElementId<A>}`,
68
- NestedElementOfDeployedInstanceModel<A>
69
- >()
70
-
71
- public readonly $deployments: $ModelData<A>['deployments']
72
-
73
- constructor(
74
- public readonly $model: LikeC4Model<A>,
75
- ) {
76
- const $deployments = this.$deployments = $model.$data.deployments
77
- const elements = values($deployments.elements as Record<string, DeploymentElement<A>>)
78
- for (const element of sortParentsFirst(elements)) {
79
- const el = this.addElement(element)
80
- for (const tag of el.tags) {
81
- this.#allTags.get(tag).add(el)
82
- }
83
- if (el.isInstance()) {
84
- this.#instancesOf.get(el.element.id).add(el)
85
- }
86
- }
87
- for (const relation of values($deployments.relations)) {
88
- const el = this.addRelation(relation)
89
- for (const tag of el.tags) {
90
- this.#allTags.get(tag).add(el)
91
- }
92
- }
93
- }
94
-
95
- public element(el: DeploymentOrFqn<A>): DeploymentElementModel<A> {
96
- if (el instanceof DeploymentNodeModel || el instanceof DeployedInstanceModel) {
97
- return el
98
- }
99
- const id = getId(el)
100
- return nonNullable(this.#elements.get(id), `Element ${id} not found`)
101
- }
102
- public findElement(el: aux.LooseDeploymentId<A>): DeploymentElementModel<A> | null {
103
- return this.#elements.get(el as aux.DeploymentFqn<A>) ?? null
104
- }
105
-
106
- public node(el: DeploymentOrFqn<A>): DeploymentNodeModel<A> {
107
- const element = this.element(el)
108
- invariant(element.isDeploymentNode(), `Element ${element.id} is not a deployment node`)
109
- return element
110
- }
111
- public findNode(el: aux.LooseDeploymentId<A>): DeploymentNodeModel<A> | null {
112
- const element = this.findElement(el)
113
- if (!element) {
114
- return null
115
- }
116
- invariant(element.isDeploymentNode(), `Element ${element?.id} is not a deployment node`)
117
- return element
118
- }
119
-
120
- public instance(el: DeploymentOrFqn<A>): DeployedInstanceModel<A> {
121
- const element = this.element(el)
122
- invariant(element.isInstance(), `Element ${element.id} is not a deployed instance`)
123
- return element
124
- }
125
- public findInstance(el: aux.LooseDeploymentId<A>): DeployedInstanceModel<A> | null {
126
- const element = this.findElement(el)
127
- if (!element) {
128
- return null
129
- }
130
- invariant(element.isInstance(), `Element ${element?.id} is not a deployed instance`)
131
- return element
132
- }
133
-
134
- /**
135
- * Returns the root elements of the model.
136
- */
137
- public roots(): DeploymentNodesIterator<A> {
138
- return this.#rootElements.values()
139
- }
140
-
141
- /**
142
- * Returns all elements in the model.
143
- */
144
- public elements(): DeploymentElementsIterator<A> {
145
- return this.#elements.values()
146
- }
147
-
148
- /**
149
- * Returns all elements in the model.
150
- */
151
- public *nodes(): DeploymentNodesIterator<A> {
152
- for (const element of this.#elements.values()) {
153
- if (element.isDeploymentNode()) {
154
- yield element
155
- }
156
- }
157
- return
158
- }
159
-
160
- public *nodesOfKind(kind: aux.DeploymentKind<A>): DeploymentNodesIterator<A> {
161
- for (const node of this.#elements.values()) {
162
- if (node.isDeploymentNode() && node.kind === kind) {
163
- yield node
164
- }
165
- }
166
- return
167
- }
168
-
169
- public *instances(): DeployedInstancesIterator<A> {
170
- for (const element of this.#elements.values()) {
171
- if (element.isInstance()) {
172
- yield element
173
- }
174
- }
175
- return
176
- }
177
-
178
- /**
179
- * Iterate over all instances of the given logical element.
180
- */
181
- public *instancesOf(element: ElementOrFqn<A>): DeployedInstancesIterator<A> {
182
- const id = getId(element)
183
- const instances = this.#instancesOf.get(id)
184
- if (instances) {
185
- yield* instances
186
- }
187
- return
188
- }
189
-
190
- public deploymentRef(
191
- ref: FqnRef.DeploymentRef<A>,
192
- ): DeploymentElementModel<A> | NestedElementOfDeployedInstanceModel<A> {
193
- if (FqnRef.isInsideInstanceRef(ref)) {
194
- const { deployment, element } = ref
195
- return getOrCreate(this.#nestedElementsOfDeployment, `${deployment}@${element}`, () => {
196
- return new NestedElementOfDeployedInstanceModel(this.instance(deployment), this.$model.element(element))
197
- })
198
- }
199
- return this.element(ref.deployment)
200
- }
201
-
202
- /**
203
- * Returns all relationships in the model.
204
- */
205
- public relationships(): IteratorLike<DeploymentRelationModel<A>> {
206
- return this.#relations.values()
207
- }
208
-
209
- /**
210
- * Returns a specific relationship by its ID.
211
- */
212
- public relationship(id: RelationOrId): DeploymentRelationModel<A> {
213
- return nonNullable(this.#relations.get(getId(id)), `DeploymentRelationModel ${id} not found`)
214
- }
215
- public findRelationship(id: string): DeploymentRelationModel<A> | null {
216
- return this.#relations.get(id as aux.RelationId) ?? null
217
- }
218
-
219
- /**
220
- * Returns all deployment views in the model.
221
- */
222
- public *views(): IteratorLike<LikeC4ViewModel.DeploymentView<A>> {
223
- for (const view of this.$model.views()) {
224
- if (view.isDeploymentView()) {
225
- yield view
226
- }
227
- }
228
- return
229
- }
230
-
231
- /**
232
- * Returns the parent element of given element.
233
- * @see ancestors
234
- */
235
- public parent(element: DeploymentOrFqn<A>): DeploymentNodeModel<A> | null {
236
- const id = getId(element)
237
- return this.#parents.get(id) || null
238
- }
239
-
240
- /**
241
- * Get all children of the element (only direct children),
242
- * @see descendants
243
- */
244
- public children(element: DeploymentOrFqn<A>): ReadonlySet<DeploymentElementModel<A>> {
245
- const id = getId(element)
246
- return this.#children.get(id)
247
- }
248
-
249
- /**
250
- * Get all sibling (i.e. same parent)
251
- */
252
- public *siblings(element: DeploymentOrFqn<A>): DeploymentElementsIterator<A> {
253
- const id = getId(element)
254
- const siblings = this.parent(element)?.children() ?? this.roots()
255
- for (const sibling of siblings) {
256
- if (sibling.id !== id) {
257
- yield sibling
258
- }
259
- }
260
- return
261
- }
262
-
263
- /**
264
- * Get all ancestor elements (i.e. parent, parent’s parent, etc.)
265
- * (from closest to root)
266
- */
267
- public *ancestors(element: DeploymentOrFqn<A>): DeploymentNodesIterator<A> {
268
- let id = getId(element)
269
- let parent
270
- while (parent = this.#parents.get(id)) {
271
- yield parent
272
- id = parent.id
273
- }
274
- return
275
- }
276
-
277
- /**
278
- * Get all descendant elements (i.e. children, children’s children, etc.)
279
- */
280
- public *descendants(
281
- element: DeploymentOrFqn<A>,
282
- sort: 'asc' | 'desc' = 'desc',
283
- ): DeploymentElementsIterator<A> {
284
- for (const child of this.children(element)) {
285
- if (sort === 'asc') {
286
- yield child
287
- yield* this.descendants(child.id)
288
- } else {
289
- yield* this.descendants(child.id)
290
- yield child
291
- }
292
- }
293
- return
294
- }
295
-
296
- /**
297
- * Incoming relationships to the element and its descendants
298
- * @see incomers
299
- */
300
- public *incoming(
301
- element: DeploymentOrFqn<A>,
302
- filter: IncomingFilter = 'all',
303
- ): IteratorLike<DeploymentRelationModel<A>> {
304
- const id = getId(element)
305
- for (const rel of this.#incoming.get(id)) {
306
- switch (true) {
307
- case filter === 'all':
308
- case filter === 'direct' && rel.target.id === id:
309
- case filter === 'to-descendants' && rel.target.id !== id:
310
- yield rel
311
- break
312
- }
313
- }
314
- return
315
- }
316
-
317
- /**
318
- * Outgoing relationships from the element and its descendants
319
- * @see outgoers
320
- */
321
- public *outgoing(
322
- element: DeploymentOrFqn<A>,
323
- filter: OutgoingFilter = 'all',
324
- ): IteratorLike<DeploymentRelationModel<A>> {
325
- const id = getId(element)
326
- for (const rel of this.#outgoing.get(id)) {
327
- switch (true) {
328
- case filter === 'all':
329
- case filter === 'direct' && rel.source.id === id:
330
- case filter === 'from-descendants' && rel.source.id !== id:
331
- yield rel
332
- break
333
- }
334
- }
335
- return
336
- }
337
-
338
- private addElement(element: DeploymentElement<A>) {
339
- if (this.#elements.has(element.id)) {
340
- throw new Error(`Element ${element.id} already exists`)
341
- }
342
- const el = isDeploymentNode(element)
343
- ? new DeploymentNodeModel(this, Object.freeze(element))
344
- : new DeployedInstanceModel(this, Object.freeze(element), this.$model.element(element.element))
345
- this.#elements.set(el.id, el)
346
- const parentId = parentFqn(el.id)
347
- if (parentId) {
348
- invariant(this.#elements.has(parentId), `Parent ${parentId} of ${el.id} not found`)
349
- this.#parents.set(el.id, this.node(parentId))
350
- this.#children.get(parentId).add(el)
351
- } else {
352
- invariant(el.isDeploymentNode(), `Root element ${el.id} is not a deployment node`)
353
- this.#rootElements.add(el)
354
- }
355
- return el
356
- }
357
-
358
- private addRelation(relation: DeploymentRelationship<A>) {
359
- if (this.#relations.has(relation.id)) {
360
- throw new Error(`Relation ${relation.id} already exists`)
361
- }
362
- const rel = new DeploymentRelationModel(
363
- this,
364
- Object.freeze(relation),
365
- )
366
- this.#relations.set(rel.id, rel)
367
- this.#incoming.get(rel.target.id).add(rel)
368
- this.#outgoing.get(rel.source.id).add(rel)
369
-
370
- const relParent = rel.boundary?.id ?? null
371
- // Process internal relationships
372
- if (relParent) {
373
- for (const ancestor of [relParent, ...ancestorsFqn(relParent)]) {
374
- this.#internal.get(ancestor).add(rel)
375
- }
376
- }
377
- // Process source hierarchy
378
- for (const sourceAncestor of ancestorsFqn(rel.source.id)) {
379
- if (sourceAncestor === relParent) {
380
- break
381
- }
382
- this.#outgoing.get(sourceAncestor).add(rel)
383
- }
384
- // Process target hierarchy
385
- for (const targetAncestor of ancestorsFqn(rel.target.id)) {
386
- if (targetAncestor === relParent) {
387
- break
388
- }
389
- this.#incoming.get(targetAncestor).add(rel)
390
- }
391
- return rel
392
- }
393
- }
@@ -1,316 +0,0 @@
1
- import { isEmpty, isShallowEqual, isTruthy, unique } from 'remeda'
2
- import type { SetRequired } from 'type-fest'
3
- import type { Any, AnyAux, Color, IteratorLike } from '../types'
4
- import {
5
- type Element as C4Element,
6
- type ElementShape as C4ElementShape,
7
- type ElementStyle,
8
- type IconUrl,
9
- type Link,
10
- type ProjectId,
11
- type RichTextOrEmpty,
12
- DefaultElementShape,
13
- DefaultShapeSize,
14
- DefaultThemeColor,
15
- preferDescription,
16
- preferSummary,
17
- RichText,
18
- splitGlobalFqn,
19
- } from '../types'
20
- import * as aux from '../types/_aux'
21
- import { commonAncestor, hierarchyLevel, ihead, isAncestor, memoizeProp, nameFromFqn, sortNaturalByFqn } from '../utils'
22
- import { type DeployedInstancesIterator } from './DeploymentElementModel'
23
- import type { LikeC4Model } from './LikeC4Model'
24
- import type { RelationshipModel, RelationshipsIterator } from './RelationModel'
25
- import type { IncomingFilter, OutgoingFilter, WithMetadata, WithTags } from './types'
26
- import type { LikeC4ViewModel } from './view/LikeC4ViewModel'
27
-
28
- export type ElementsIterator<M extends AnyAux> = IteratorLike<ElementModel<M>>
29
-
30
- export class ElementModel<A extends AnyAux = Any> implements WithTags<A>, WithMetadata<A> {
31
- readonly id: aux.Fqn<A>
32
- readonly _literalId: aux.ElementId<A>
33
- readonly hierarchyLevel: number
34
-
35
- readonly imported: null | {
36
- from: ProjectId
37
- fqn: aux.Fqn<A>
38
- }
39
-
40
- constructor(
41
- public readonly $model: LikeC4Model<A>,
42
- public readonly $element: C4Element<A>,
43
- ) {
44
- this.id = this.$element.id
45
- this._literalId = this.$element.id
46
- const [projectId, fqn] = splitGlobalFqn(this.id)
47
- if (projectId) {
48
- this.imported = {
49
- from: projectId,
50
- fqn,
51
- }
52
- this.hierarchyLevel = hierarchyLevel(fqn)
53
- } else {
54
- this.imported = null
55
- this.hierarchyLevel = hierarchyLevel(this.id)
56
- }
57
- }
58
-
59
- get name(): string {
60
- return nameFromFqn(this.id)
61
- }
62
-
63
- get parent(): ElementModel<A> | null {
64
- return this.$model.parent(this)
65
- }
66
-
67
- get kind(): aux.ElementKind<A> {
68
- return this.$element.kind
69
- }
70
-
71
- get shape(): C4ElementShape {
72
- return this.$element.shape ?? DefaultElementShape
73
- }
74
-
75
- get color(): Color {
76
- return this.$element.color as Color ?? DefaultThemeColor
77
- }
78
-
79
- get icon(): IconUrl | null {
80
- return this.$element.icon ?? null
81
- }
82
-
83
- /**
84
- * Returns all tags of the element.
85
- * It includes tags from the element and its kind.
86
- */
87
- get tags(): aux.Tags<A> {
88
- return memoizeProp(this, Symbol.for('tags'), () => {
89
- return unique([
90
- ...(this.$element.tags ?? []),
91
- ...(this.$model.specification.elements[this.$element.kind]?.tags ?? []),
92
- ] as aux.Tags<A>)
93
- })
94
- }
95
-
96
- get title(): string {
97
- return this.$element.title
98
- }
99
-
100
- /**
101
- * Returns true if the element has a summary and a description
102
- * (if one is missing - it falls back to another)
103
- */
104
- get hasSummary(): boolean {
105
- return !!this.$element.summary && !!this.$element.description &&
106
- !isShallowEqual(this.$element.summary, this.$element.description)
107
- }
108
-
109
- /**
110
- * Short description of the element.
111
- * Falls back to description if summary is not provided.
112
- */
113
- get summary(): RichTextOrEmpty {
114
- return RichText.memoize(this, 'summary', preferSummary(this.$element))
115
- }
116
-
117
- /**
118
- * Long description of the element.
119
- * Falls back to summary if description is not provided.
120
- */
121
- get description(): RichTextOrEmpty {
122
- return RichText.memoize(this, 'description', preferDescription(this.$element))
123
- }
124
-
125
- get technology(): string | null {
126
- return this.$element.technology ?? null
127
- }
128
-
129
- get links(): ReadonlyArray<Link> {
130
- return this.$element.links ?? []
131
- }
132
-
133
- get defaultView(): LikeC4ViewModel.ScopedElementView<A> | null {
134
- return memoizeProp(this, Symbol.for('defaultView'), () => ihead(this.scopedViews()) ?? null)
135
- }
136
-
137
- get isRoot(): boolean {
138
- return this.parent === null
139
- }
140
-
141
- get style(): SetRequired<ElementStyle, 'size'> {
142
- return {
143
- size: DefaultShapeSize,
144
- ...this.$element.style,
145
- }
146
- }
147
-
148
- public isAncestorOf(another: ElementModel<A>): boolean {
149
- return isAncestor(this, another)
150
- }
151
-
152
- public isDescendantOf(another: ElementModel<A>): boolean {
153
- return isAncestor(another, this)
154
- }
155
-
156
- /**
157
- * Get all ancestor elements (i.e. parent, parent’s parent, etc.)
158
- * (from closest to root)
159
- */
160
- public ancestors(): ElementsIterator<A> {
161
- return this.$model.ancestors(this)
162
- }
163
-
164
- /**
165
- * Returns the common ancestor of this element and another element.
166
- */
167
- public commonAncestor(another: ElementModel<A>): ElementModel<A> | null {
168
- const common = commonAncestor(this.id, another.id)
169
- return common ? this.$model.element(common) : null
170
- }
171
-
172
- public children(): ReadonlySet<ElementModel<A>> {
173
- return this.$model.children(this)
174
- }
175
-
176
- /**
177
- * Get all descendant elements (i.e. children, children’s children, etc.)
178
- */
179
- public descendants(sort?: 'asc' | 'desc'): ElementsIterator<A> {
180
- if (sort) {
181
- const sorted = sortNaturalByFqn([...this.$model.descendants(this)], sort)
182
- return sorted[Symbol.iterator]()
183
- }
184
- return this.$model.descendants(this)
185
- }
186
-
187
- /**
188
- * Get all sibling (i.e. same parent)
189
- */
190
- public siblings(): ElementsIterator<A> {
191
- return this.$model.siblings(this)
192
- }
193
-
194
- /**
195
- * Resolve siblings of the element and its ancestors
196
- * (from closest parent to root)
197
- */
198
- public *ascendingSiblings(): ElementsIterator<A> {
199
- yield* this.siblings()
200
- for (const ancestor of this.ancestors()) {
201
- yield* ancestor.siblings()
202
- }
203
- return
204
- }
205
-
206
- /**
207
- * Resolve siblings of the element and its ancestors
208
- * (from root to closest)
209
- */
210
- public *descendingSiblings(): ElementsIterator<A> {
211
- for (const ancestor of [...this.ancestors()].reverse()) {
212
- yield* ancestor.siblings()
213
- }
214
- yield* this.siblings()
215
- return
216
- }
217
-
218
- public incoming(filter: IncomingFilter = 'all'): RelationshipsIterator<A> {
219
- return this.$model.incoming(this, filter)
220
- }
221
- public *incomers(filter: IncomingFilter = 'all'): ElementsIterator<A> {
222
- const unique = new Set<aux.StrictFqn<A>>()
223
- for (const r of this.incoming(filter)) {
224
- if (unique.has(r.source.id)) {
225
- continue
226
- }
227
- unique.add(r.source.id)
228
- yield r.source
229
- }
230
- return
231
- }
232
- public outgoing(filter: OutgoingFilter = 'all'): RelationshipsIterator<A> {
233
- return this.$model.outgoing(this, filter)
234
- }
235
- public *outgoers(filter: OutgoingFilter = 'all'): ElementsIterator<A> {
236
- const unique = new Set<aux.StrictFqn<A>>()
237
- for (const r of this.outgoing(filter)) {
238
- if (unique.has(r.target.id)) {
239
- continue
240
- }
241
- unique.add(r.target.id)
242
- yield r.target
243
- }
244
- return
245
- }
246
-
247
- public get allOutgoing(): ReadonlySet<RelationshipModel<A>> {
248
- return memoizeProp(this, Symbol.for('allOutgoing'), () => new Set(this.outgoing()))
249
- }
250
-
251
- public get allIncoming(): ReadonlySet<RelationshipModel<A>> {
252
- return memoizeProp(this, Symbol.for('allIncoming'), () => new Set(this.incoming()))
253
- }
254
-
255
- /**
256
- * Iterate over all views that include this element.
257
- */
258
- public views(): ReadonlySet<LikeC4ViewModel<A>> {
259
- return memoizeProp(this, Symbol.for('views'), () => {
260
- const views = new Set<LikeC4ViewModel<A>>()
261
- for (const view of this.$model.views()) {
262
- if (view.includesElement(this.id)) {
263
- views.add(view)
264
- }
265
- }
266
- return views
267
- })
268
- }
269
-
270
- /**
271
- * Iterate over all views that scope this element.
272
- * It is possible that element is not included in the view.
273
- */
274
- public scopedViews(): ReadonlySet<LikeC4ViewModel.ScopedElementView<A>> {
275
- return memoizeProp(this, Symbol.for('scopedViews'), () => {
276
- const views = new Set<LikeC4ViewModel.ScopedElementView<A>>()
277
- for (const vm of this.$model.views()) {
278
- if (vm.isScopedElementView() && vm.viewOf.id === this.id) {
279
- views.add(vm)
280
- }
281
- }
282
- return views
283
- })
284
- }
285
-
286
- /**
287
- * @returns true if the element is deployed
288
- */
289
- public isDeployed(): boolean {
290
- return isTruthy(ihead(this.deployments()))
291
- }
292
-
293
- public deployments(): DeployedInstancesIterator<A> {
294
- return this.$model.deployment.instancesOf(this)
295
- }
296
-
297
- public hasMetadata(): boolean {
298
- return !!this.$element.metadata && !isEmpty(this.$element.metadata)
299
- }
300
-
301
- public getMetadata(): aux.Metadata<A>
302
- public getMetadata(field: aux.MetadataKey<A>): string | undefined
303
- public getMetadata(field?: aux.MetadataKey<A>) {
304
- if (field) {
305
- return this.$element.metadata?.[field]
306
- }
307
- return this.$element.metadata ?? {}
308
- }
309
-
310
- /**
311
- * Checks if the element has the given tag.
312
- */
313
- public isTagged(tag: aux.LooseTag<A>): boolean {
314
- return this.tags.includes(tag as aux.Tag<A>)
315
- }
316
- }