@likec4/core 1.18.0 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +1 -1
  2. package/dist/builder/index.d.mts +502 -0
  3. package/dist/builder/index.d.ts +502 -0
  4. package/dist/builder/index.js +871 -0
  5. package/dist/compute-view/index.d.mts +9 -78
  6. package/dist/compute-view/index.d.ts +9 -78
  7. package/dist/compute-view/index.js +78 -0
  8. package/dist/index.d.mts +9 -730
  9. package/dist/index.d.ts +9 -730
  10. package/dist/{index.mjs → index.js} +7 -784
  11. package/dist/model/index.d.mts +218 -606
  12. package/dist/model/index.d.ts +218 -606
  13. package/dist/model/index.js +1 -0
  14. package/dist/shared/chunk-RAAYCPUM.M-JWF7SS.js +21 -0
  15. package/dist/shared/core.BIfgabEw.d.ts +719 -0
  16. package/dist/shared/core.BZ9Msq7w.d.mts +719 -0
  17. package/dist/shared/{core.DMYY7C8s.d.mts → core.C05RDLhi.d.ts} +179 -230
  18. package/dist/shared/{core.DMYY7C8s.d.ts → core.CmYMqgha.d.mts} +179 -230
  19. package/dist/shared/core.D6-fWbM3.d.ts +127 -0
  20. package/dist/shared/core.D74xkKkG.d.mts +148 -0
  21. package/dist/shared/core.D74xkKkG.d.ts +148 -0
  22. package/dist/shared/core.sLaWHBjR.d.mts +127 -0
  23. package/dist/shared/index.DafVOuVd.js +7443 -0
  24. package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
  25. package/dist/shared/view.CyZrG8BJ.js +354 -0
  26. package/dist/types/index.d.mts +4 -2
  27. package/dist/types/index.d.ts +4 -2
  28. package/dist/types/index.js +20 -0
  29. package/dist/utils/index.d.mts +419 -0
  30. package/dist/utils/index.d.ts +419 -0
  31. package/dist/utils/index.js +347 -0
  32. package/package.json +47 -33
  33. package/src/builder/Builder-style1.test-d.ts +190 -0
  34. package/src/builder/Builder-style2.test-d.ts +175 -0
  35. package/src/builder/Builder.deployment.ts +25 -20
  36. package/src/builder/Builder.deploymentModel.ts +80 -55
  37. package/src/builder/Builder.element.ts +2 -0
  38. package/src/builder/Builder.model.ts +57 -43
  39. package/src/builder/Builder.ts +412 -431
  40. package/src/builder/Builder.view-common.ts +234 -0
  41. package/src/builder/Builder.view-deployment.ts +135 -0
  42. package/src/builder/Builder.view-element.ts +189 -0
  43. package/src/builder/Builder.views.ts +109 -33
  44. package/src/builder/Builder.with.ts +475 -0
  45. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +374 -0
  46. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +183 -0
  47. package/src/builder/__snapshots__/Builder.spec.ts.snap +374 -0
  48. package/src/builder/_types.ts +28 -5
  49. package/src/builder/index.ts +10 -4
  50. package/src/colors/index.ts +2 -2
  51. package/src/compute-view/compute-view.ts +45 -54
  52. package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
  53. package/src/compute-view/deployment-view/__test__/fixture.ts +50 -62
  54. package/src/compute-view/deployment-view/_types.ts +26 -18
  55. package/src/compute-view/deployment-view/clean-connections.ts +173 -164
  56. package/src/compute-view/deployment-view/compute.ts +51 -37
  57. package/src/compute-view/deployment-view/memory/index.ts +9 -0
  58. package/src/compute-view/deployment-view/memory/memory.ts +97 -0
  59. package/src/compute-view/deployment-view/predicates/elements.ts +144 -0
  60. package/src/compute-view/deployment-view/predicates/relation-direct.ts +183 -76
  61. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +38 -20
  62. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +72 -23
  63. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +61 -22
  64. package/src/compute-view/deployment-view/predicates/wildcard.ts +15 -15
  65. package/src/compute-view/deployment-view/stages/stage-exclude.ts +5 -0
  66. package/src/compute-view/deployment-view/stages/stage-final.ts +245 -0
  67. package/src/compute-view/deployment-view/stages/stage-include.ts +95 -0
  68. package/src/compute-view/deployment-view/utils.ts +95 -31
  69. package/src/compute-view/dynamic-view/__test__/fixture.ts +4 -4
  70. package/src/compute-view/dynamic-view/compute.ts +59 -45
  71. package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
  72. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +64 -62
  73. package/src/compute-view/element-view/__test__/fixture.ts +147 -117
  74. package/src/compute-view/element-view/_types.ts +48 -0
  75. package/src/compute-view/element-view/clean-connections.ts +113 -0
  76. package/src/compute-view/element-view/compute.ts +264 -683
  77. package/src/compute-view/element-view/memory/NodeGroup.ts +31 -0
  78. package/src/compute-view/element-view/memory/index.ts +10 -0
  79. package/src/compute-view/element-view/memory/memory.ts +177 -0
  80. package/src/compute-view/element-view/memory/stage-exclude.ts +59 -0
  81. package/src/compute-view/element-view/memory/stage-final.ts +129 -0
  82. package/src/compute-view/element-view/memory/stage-include.ts +128 -0
  83. package/src/compute-view/element-view/predicates/_utils.ts +86 -0
  84. package/src/compute-view/element-view/predicates/element-expand.ts +33 -0
  85. package/src/compute-view/element-view/predicates/element-kind-tag.ts +26 -0
  86. package/src/compute-view/element-view/predicates/element-ref.ts +37 -0
  87. package/src/compute-view/element-view/predicates/relation-direct.ts +309 -0
  88. package/src/compute-view/element-view/predicates/relation-in-out.ts +66 -0
  89. package/src/compute-view/element-view/predicates/relation-in.ts +118 -0
  90. package/src/compute-view/element-view/predicates/relation-out.ts +116 -0
  91. package/src/compute-view/element-view/predicates/wildcard.ts +88 -0
  92. package/src/compute-view/element-view/utils.ts +59 -0
  93. package/src/compute-view/index.ts +3 -4
  94. package/src/compute-view/memory/AbstractMemory.ts +45 -0
  95. package/src/compute-view/memory/AbstractStageExclude.ts +216 -0
  96. package/src/compute-view/memory/AbstractStageInclude.ts +200 -0
  97. package/src/compute-view/memory/_types.ts +147 -0
  98. package/src/compute-view/memory/index.ts +5 -0
  99. package/src/compute-view/memory/ops.ts +43 -0
  100. package/src/compute-view/utils/buildComputedNodes.ts +4 -4
  101. package/src/compute-view/utils/elementExpressionToPredicate.ts +1 -3
  102. package/src/compute-view/utils/link-nodes-with-edges.ts +3 -7
  103. package/src/compute-view/utils/{derive-edge-props-from-relationships.ts → merge-props-from-relationships.ts} +54 -23
  104. package/src/compute-view/utils/relationExpressionToPredicates.ts +2 -2
  105. package/src/compute-view/utils/resolve-extended-views.ts +44 -40
  106. package/src/compute-view/utils/resolve-global-rules.ts +6 -6
  107. package/src/compute-view/utils/topological-sort.ts +167 -71
  108. package/src/compute-view/utils/with-readable-edges.ts +14 -9
  109. package/src/index.ts +22 -16
  110. package/src/model/DeploymentElementModel.ts +150 -85
  111. package/src/model/DeploymentModel.ts +27 -21
  112. package/src/model/ElementModel.ts +51 -25
  113. package/src/model/LikeC4Model.test-d.ts +4 -3
  114. package/src/model/LikeC4Model.ts +98 -42
  115. package/src/model/RelationModel.ts +5 -4
  116. package/src/model/__test__/fixture.ts +5 -9
  117. package/src/model/connection/Connection.ts +72 -0
  118. package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
  119. package/src/model/connection/{deployment.ts → deployment/find.ts} +14 -18
  120. package/src/model/connection/deployment/index.ts +8 -0
  121. package/src/model/connection/index.ts +22 -0
  122. package/src/model/connection/model/ConnectionModel.ts +157 -0
  123. package/src/model/connection/{model.ts → model/find.ts} +43 -49
  124. package/src/model/connection/model/index.ts +8 -0
  125. package/src/model/connection/ops.ts +274 -0
  126. package/src/model/guards.ts +9 -0
  127. package/src/model/index.ts +45 -3
  128. package/src/model/types.ts +35 -18
  129. package/src/model/view/EdgeModel.ts +6 -6
  130. package/src/model/view/LikeC4ViewModel.ts +14 -8
  131. package/src/model/view/NodeModel.ts +6 -5
  132. package/src/types/_common.ts +53 -1
  133. package/src/types/deployments.ts +88 -156
  134. package/src/types/element.ts +2 -2
  135. package/src/types/expression-v2.ts +172 -0
  136. package/src/types/expression.ts +9 -5
  137. package/src/types/global.ts +3 -3
  138. package/src/types/index.ts +220 -13
  139. package/src/types/model.ts +28 -24
  140. package/src/types/operators.ts +1 -1
  141. package/src/types/relation.ts +14 -10
  142. package/src/types/theme.ts +0 -1
  143. package/src/types/view.ts +20 -18
  144. package/src/utils/const.ts +1 -0
  145. package/src/utils/fqn.ts +140 -49
  146. package/src/utils/getOrCreate.ts +1 -1
  147. package/src/utils/index.ts +75 -9
  148. package/src/utils/iterable/_types.ts +5 -0
  149. package/src/utils/iterable/filter.ts +55 -0
  150. package/src/utils/iterable/find.ts +36 -0
  151. package/src/utils/iterable/flat.ts +17 -0
  152. package/src/utils/iterable/index.ts +13 -0
  153. package/src/utils/iterable/map.ts +40 -0
  154. package/src/utils/iterable/reduce.ts +24 -0
  155. package/src/utils/iterable/some.ts +36 -0
  156. package/src/utils/iterable/to.ts +19 -0
  157. package/src/utils/iterable/unique.ts +29 -0
  158. package/src/utils/relations.ts +3 -64
  159. package/src/utils/set.ts +11 -9
  160. package/src/utils/string-hash.ts +1 -1
  161. package/dist/compute-view/index.mjs +0 -79
  162. package/dist/model/index.mjs +0 -2
  163. package/dist/shared/core.BBgiAAv1.mjs +0 -144
  164. package/dist/shared/core.BPyJvuMU.mjs +0 -2420
  165. package/dist/shared/core.BQ4AbfvB.mjs +0 -9228
  166. package/dist/shared/core.k12s_keD.mjs +0 -203
  167. package/dist/types/index.mjs +0 -21
  168. package/src/builder/Builder.test-d.ts +0 -124
  169. package/src/builder/Builder.view.ts +0 -543
  170. package/src/compute-view/LikeC4ModelGraph.ts +0 -330
  171. package/src/compute-view/deployment-view/Memory.ts +0 -108
  172. package/src/compute-view/deployment-view/Stage.ts +0 -145
  173. package/src/compute-view/deployment-view/predicates/deployment-ref.ts +0 -146
  174. package/src/compute-view/element-view/predicates.ts +0 -517
  175. package/src/compute-view/utils/sortNodes.ts +0 -101
  176. package/src/model/connection/ConnectionModel.ts +0 -94
  177. package/src/model/connection/DeploymentConnectionModel.ts +0 -99
@@ -0,0 +1,274 @@
1
+ import { map, pipe, prop } from 'remeda'
2
+ import { isString } from '../../utils'
3
+ import {
4
+ type IterableContainer,
5
+ type ReorderedArray,
6
+ isAncestor,
7
+ isDescendantOf,
8
+ sortNaturalByFqn,
9
+ } from '../../utils/fqn'
10
+ import type { Connection } from './Connection'
11
+
12
+ /**
13
+ * Check if connection is nested inside another connection
14
+ * (i.e. between descendants)
15
+ */
16
+ export function isNestedConnection<T extends { id: string }>(
17
+ parent: WithSourceTarget<NoInfer<T>>,
18
+ ): (nested: WithSourceTarget<T>) => boolean
19
+ export function isNestedConnection<T extends { id: string }>(
20
+ nested: WithSourceTarget<T>,
21
+ parent: WithSourceTarget<T>,
22
+ ): boolean
23
+ export function isNestedConnection<T extends { id: string }>(
24
+ nested: WithSourceTarget<T>,
25
+ parent?: WithSourceTarget<T>,
26
+ ) {
27
+ if (!parent) {
28
+ const p = nested
29
+ return (n: WithSourceTarget<T>) => isNestedConnection(n, p)
30
+ }
31
+ const isSameSource = nested.source === parent.source
32
+ const isSameTarget = nested.target === parent.target
33
+ if (isSameSource && isSameTarget) {
34
+ return false
35
+ }
36
+ const isSourceNested = isAncestor(parent.source.id, nested.source.id)
37
+ const isTargetNested = isAncestor(parent.target.id, nested.target.id)
38
+ return (
39
+ (isSourceNested && isTargetNested)
40
+ || (isSameSource && isTargetNested)
41
+ || (isSameTarget && isSourceNested)
42
+ )
43
+ }
44
+
45
+ type ConnectionElemId = Connection<{ readonly id: string }, any>
46
+
47
+ export function findDeepestNestedConnection<C extends ConnectionElemId>(
48
+ connections: ReadonlyArray<C>,
49
+ connection: C,
50
+ ): C | null {
51
+ let deepest = connection
52
+ for (const c of connections) {
53
+ if (isNestedConnection(c, deepest)) {
54
+ deepest = c
55
+ }
56
+ }
57
+ return deepest !== connection ? deepest : null
58
+ }
59
+
60
+ export function sortDeepestFirst<C extends ConnectionElemId>(
61
+ connections: ReadonlyArray<C>,
62
+ ): C[] {
63
+ const sorted = [] as C[]
64
+ const unsorted = connections.slice()
65
+ let next
66
+ while (next = unsorted.shift()) {
67
+ let deepest
68
+ while (deepest = findDeepestNestedConnection(unsorted, next)) {
69
+ const index = unsorted.indexOf(deepest)
70
+ sorted.push(unsorted.splice(index, 1)[0]!)
71
+ }
72
+ sorted.push(next)
73
+ }
74
+ return sorted
75
+ }
76
+
77
+ /**
78
+ * To make {@link sortConnectionsByBoundaryHierarchy} work correctly we add '.' to boundary
79
+ * Othwerwise connection without boundary will be considered same level as connection with top-level boundary
80
+ */
81
+ export const boundaryHierarchy = <C extends WithBoundary>(conn: C) => conn.boundary?.id ? `.${conn.boundary.id}` : ''
82
+
83
+ type WithBoundary = {
84
+ boundary: null | { id: string }
85
+ }
86
+ export function sortConnectionsByBoundaryHierarchy(
87
+ sort?: 'asc' | 'desc',
88
+ ): <T extends WithBoundary, A extends IterableContainer<T>>(array: A) => ReorderedArray<A>
89
+ export function sortConnectionsByBoundaryHierarchy<T extends WithBoundary, A extends IterableContainer<T>>(
90
+ array: A,
91
+ sort?: 'asc' | 'desc',
92
+ ): ReorderedArray<A>
93
+ export function sortConnectionsByBoundaryHierarchy<T extends WithBoundary, A extends IterableContainer<T>>(
94
+ connections?: A | 'asc' | 'desc',
95
+ sort?: 'asc' | 'desc',
96
+ ) {
97
+ if (!connections || isString(connections)) {
98
+ const dir = connections ?? 'asc'
99
+ return (arr: A) => _sortByBoundary(arr, dir)
100
+ }
101
+ return _sortByBoundary(connections, sort ?? 'asc')
102
+ }
103
+
104
+ function _sortByBoundary<C extends WithBoundary>(
105
+ connections: ReadonlyArray<C>,
106
+ order: 'asc' | 'desc',
107
+ ): C[] {
108
+ return pipe(
109
+ connections,
110
+ map(conn => ({
111
+ id: boundaryHierarchy(conn),
112
+ conn,
113
+ })),
114
+ sortNaturalByFqn(order),
115
+ map(prop('conn')),
116
+ )
117
+ }
118
+
119
+ /**
120
+ * Find connections that includes given connection (i.e between it's ancestors)
121
+ */
122
+ export function findAscendingConnections<C extends ConnectionElemId>(
123
+ connections: ReadonlyArray<C>,
124
+ connection: C,
125
+ ): Array<C> {
126
+ return connections.filter(c => isNestedConnection(connection, c))
127
+ }
128
+
129
+ /**
130
+ * Find connections that includes given connection (i.e between it's descendants)
131
+ */
132
+ export function findDescendantConnections<C extends ConnectionElemId>(
133
+ connections: ReadonlyArray<C>,
134
+ connection: C,
135
+ ): Array<C> {
136
+ return connections.filter(isNestedConnection(connection))
137
+ }
138
+
139
+ export function mergeConnections<C extends Connection>(
140
+ connections: ReadonlyArray<C>,
141
+ ): C[] {
142
+ const map = new Map<C['id'], C>()
143
+ for (const conn of connections) {
144
+ const existing = map.get(conn.id)
145
+ if (existing) {
146
+ map.set(conn.id, conn.mergeWith(existing) as C)
147
+ } else {
148
+ map.set(conn.id, conn)
149
+ }
150
+ }
151
+ return [...map.values()]
152
+ }
153
+
154
+ /**
155
+ * Excludes the values existing in `other` array.
156
+ * The output maintains the same order as the input.
157
+ */
158
+ export function differenceConnections<C extends Connection>(
159
+ source: Iterable<C>,
160
+ exclude: Iterable<C>,
161
+ ): C[] {
162
+ const minus = new Map([...exclude].map(c => [c.id, c]))
163
+ return [...source].reduce((acc, c) => {
164
+ const other = minus.get(c.id)
165
+ if (!other) {
166
+ acc.push(c)
167
+ return acc
168
+ }
169
+ const updated = c.difference(other) as C
170
+ if (updated.nonEmpty()) {
171
+ acc.push(updated)
172
+ }
173
+ return acc
174
+ }, [] as C[])
175
+ }
176
+
177
+ type WithSourceTarget<T = unknown> = {
178
+ source: T
179
+ target: T
180
+ }
181
+
182
+ export function hasSameSourceTarget<T>(a: WithSourceTarget<NoInfer<T>>): (b: WithSourceTarget<T>) => boolean
183
+ export function hasSameSourceTarget<T>(a: WithSourceTarget<T>, b: WithSourceTarget<T>): boolean
184
+ export function hasSameSourceTarget(a: WithSourceTarget, b?: WithSourceTarget) {
185
+ if (b) {
186
+ return a.source === b.source && a.target === b.target
187
+ }
188
+ return (b: WithSourceTarget) => a.source === b.source && a.target === b.target
189
+ }
190
+
191
+ export function hasSameSource<T>(a: WithSourceTarget<NoInfer<T>>): (b: WithSourceTarget<T>) => boolean
192
+ export function hasSameSource<T>(a: WithSourceTarget<T>, b: WithSourceTarget<T>): boolean
193
+ export function hasSameSource(a: WithSourceTarget, b?: WithSourceTarget) {
194
+ if (b) {
195
+ return a.source === b.source
196
+ }
197
+ return (b: WithSourceTarget) => a.source === b.source
198
+ }
199
+
200
+ export function hasSameTarget<T>(a: WithSourceTarget<NoInfer<T>>): (b: WithSourceTarget<T>) => boolean
201
+ export function hasSameTarget<T>(a: WithSourceTarget<T>, b: WithSourceTarget<T>): boolean
202
+ export function hasSameTarget(a: WithSourceTarget, b?: WithSourceTarget) {
203
+ if (b) {
204
+ return a.target === b.target
205
+ }
206
+ return (b: WithSourceTarget) => a.target === b.target
207
+ }
208
+
209
+ type WithId<T> = {
210
+ id: T
211
+ }
212
+ export function isOutgoing<T extends string>(source: WithId<NoInfer<T>>): (a: WithSourceTarget<WithId<T>>) => boolean
213
+ export function isOutgoing<T extends string>(a: WithSourceTarget<WithId<T>>, source: WithId<T>): boolean
214
+ export function isOutgoing<T extends string>(a: WithSourceTarget<WithId<T>> | WithId<T>, source?: WithId<T>) {
215
+ if (!source) {
216
+ const _source = a as WithId<T>
217
+ return (b: WithSourceTarget<WithId<T>>) => isOutgoing(b, _source)
218
+ }
219
+ const at = a as WithSourceTarget<WithId<T>>
220
+ return isDescendantOf(at.source, source) && !isDescendantOf(at.target, source)
221
+ }
222
+
223
+ export function isIncoming<T extends string>(target: WithId<NoInfer<T>>): (a: WithSourceTarget<WithId<T>>) => boolean
224
+ export function isIncoming<T extends string>(a: WithSourceTarget<WithId<T>>, target: WithId<T>): boolean
225
+ export function isIncoming<T extends string>(a: WithSourceTarget<WithId<T>> | WithId<T>, target?: WithId<T>) {
226
+ if (!target) {
227
+ const _target = a as WithId<T>
228
+ return (b: WithSourceTarget<WithId<T>>) => isIncoming(b, _target)
229
+ }
230
+ const at = a as WithSourceTarget<WithId<T>>
231
+ return isDescendantOf(at.target, target) && !isDescendantOf(at.source, target)
232
+ }
233
+
234
+ export function isAnyInOut<T extends string>(source: WithId<NoInfer<T>>): (a: WithSourceTarget<WithId<T>>) => boolean
235
+ export function isAnyInOut<T extends string>(a: WithSourceTarget<WithId<T>>, source: WithId<T>): boolean
236
+ export function isAnyInOut<T extends string>(a: WithSourceTarget<WithId<T>> | WithId<T>, source?: WithId<T>) {
237
+ if (!source) {
238
+ const _source = a as WithId<T>
239
+ return (b: WithSourceTarget<WithId<T>>) => isAnyInOut(b, _source)
240
+ }
241
+ const at = a as WithSourceTarget<WithId<T>>
242
+ return isDescendantOf(at.source, source) !== isDescendantOf(at.target, source)
243
+ }
244
+
245
+ export function isInside<T extends string>(source: WithId<NoInfer<T>>): (a: WithSourceTarget<WithId<T>>) => boolean
246
+ export function isInside<T extends string>(a: WithSourceTarget<WithId<T>>, source: WithId<T>): boolean
247
+ export function isInside<T extends string>(a: WithSourceTarget<WithId<T>> | WithId<T>, source?: WithId<T>) {
248
+ if (!source) {
249
+ const _source = a as WithId<T>
250
+ return (b: WithSourceTarget<WithId<T>>) => isInside(b, _source)
251
+ }
252
+ const at = a as WithSourceTarget<WithId<T>>
253
+ return isDescendantOf(at.source, source) && isDescendantOf(at.target, source)
254
+ }
255
+
256
+ // export function isIncoming<T>(target: NoInfer<T>): (a: WithSourceTarget<T>) => boolean
257
+ // export function isIncoming<T>(a: WithSourceTarget<T>, target: T): boolean
258
+ // export function isIncoming<T = unknown>(a: WithSourceTarget<T> | T, target?: T) {
259
+ // if (target) {
260
+ // return (a as WithSourceTarget<T>).target === target
261
+ // }
262
+ // const _target = a as T
263
+ // return (b: WithSourceTarget) => b.target === _target
264
+ // }
265
+
266
+ // export function isAnyInOut<T>(source: NoInfer<T>): (a: WithSourceTarget<T>) => boolean
267
+ // export function isAnyInOut<T>(a: WithSourceTarget<T>, source: T): boolean
268
+ // export function isAnyInOut<T = unknown>(a: WithSourceTarget<T> | T, source?: T) {
269
+ // if (source) {
270
+ // return hasSameSource(a as WithSourceTarget<T>, source) || hasSameTarget(a as WithSourceTarget<T>, source)
271
+ // }
272
+ // const _source = a as T
273
+ // return (b: WithSourceTarget) => hasSameSource(b, _source) || hasSameTarget(b, _source)
274
+ // }
@@ -0,0 +1,9 @@
1
+ import type { DeployedInstanceModel, DeploymentElementModel, DeploymentNodeModel } from './DeploymentElementModel'
2
+
3
+ export function isDeploymentNode(model: DeploymentElementModel): model is DeploymentNodeModel {
4
+ return model.isDeploymentNode()
5
+ }
6
+
7
+ export function isDeployedInstance(model: DeploymentElementModel): model is DeployedInstanceModel {
8
+ return model.isInstance()
9
+ }
@@ -1,5 +1,47 @@
1
- export { LikeC4DeploymentModel } from './DeploymentModel'
1
+ export { ElementModel } from './ElementModel'
2
2
  export { LikeC4Model } from './LikeC4Model'
3
- export type * from './LikeC4Model'
4
- export type { Aux as LikeC4ModelAux } from './types'
3
+ export { RelationshipModel } from './RelationModel'
4
+
5
+ export {
6
+ Connection,
7
+ ConnectionModel,
8
+ deployment as deploymentConnection,
9
+ DeploymentConnectionModel,
10
+ differenceConnections,
11
+ findAscendingConnections,
12
+ findDeepestNestedConnection,
13
+ findDescendantConnections,
14
+ hasSameSource,
15
+ hasSameSourceTarget,
16
+ hasSameTarget,
17
+ isAnyInOut,
18
+ isIncoming,
19
+ isNestedConnection,
20
+ isOutgoing,
21
+ mergeConnections,
22
+ model as modelConnection,
23
+ sortConnectionsByBoundaryHierarchy,
24
+ sortDeepestFirst,
25
+ } from './connection'
26
+
27
+ export {
28
+ DeployedInstanceModel,
29
+ type DeploymentElementModel,
30
+ DeploymentNodeModel,
31
+ DeploymentRelationModel,
32
+ } from './DeploymentElementModel'
33
+ export { LikeC4DeploymentModel } from './DeploymentModel'
34
+
35
+ export { EdgeModel } from './view/EdgeModel'
5
36
  export { LikeC4ViewModel } from './view/LikeC4ViewModel'
37
+ export { NodeModel } from './view/NodeModel'
38
+
39
+ export type {
40
+ AnyAux,
41
+ Aux,
42
+ } from './types'
43
+
44
+ export {
45
+ isDeployedInstance,
46
+ isDeploymentNode,
47
+ } from './guards'
@@ -1,16 +1,18 @@
1
- import type { IsLiteral, LiteralUnion, Simplify } from 'type-fest'
1
+ import type { IsStringLiteral, LiteralUnion, Simplify } from 'type-fest'
2
2
  import type {
3
- AnyLikeC4Model,
4
3
  ComputedView,
5
4
  DiagramView,
6
5
  EdgeId,
7
6
  Fqn,
7
+ GenericLikeC4Model,
8
+ IteratorLike,
8
9
  KeysOf,
9
10
  LayoutedLikeC4Model,
11
+ LikeC4ModelDump,
10
12
  NodeId,
11
- ParsedLikeC4ModelDump,
13
+ ParsedLikeC4Model,
12
14
  RelationId,
13
- ViewId
15
+ ViewId,
14
16
  } from '../types'
15
17
  import { isString } from '../utils/guards'
16
18
 
@@ -24,8 +26,6 @@ export function getId<Id extends string>(element: string | { id: Id }): Id {
24
26
  return isString(element) ? element as Id : element.id
25
27
  }
26
28
 
27
- export type IteratorLike<T> = IteratorObject<T, BuiltinIteratorReturn>
28
-
29
29
  type WithId<Id> = { id: Id }
30
30
 
31
31
  type WithViews<Id extends string, ViewType> = { views: Record<Id, ViewType> }
@@ -36,22 +36,25 @@ type WithViews<Id extends string, ViewType> = { views: Record<Id, ViewType> }
36
36
  export interface Aux<
37
37
  Element extends string,
38
38
  Deployment extends string,
39
- Views extends string,
40
- ViewType
39
+ View extends string,
40
+ ViewType,
41
41
  > {
42
- // Model: Model
42
+ Element: Element
43
+ Deployment: Deployment
44
+ View: View
43
45
 
46
+ // Wrapped Element
44
47
  // If Fqn is just a string, then we use generic Fqn to have better hints in the editor
45
- Fqn: IsLiteral<Element> extends true ? Fqn<Element> : Fqn
46
- Element: Element
48
+ Fqn: IsStringLiteral<Element> extends true ? Fqn<Element> : Fqn
47
49
  ElementOrFqn: Element | WithId<this['Fqn']>
48
50
 
49
- DeploymentFqn: IsLiteral<Deployment> extends true ? Fqn<Deployment> : Fqn
50
- Deployment: Deployment
51
+ // Wrapped Deployment
52
+ DeploymentFqn: IsStringLiteral<Deployment> extends true ? Fqn<Deployment> : Fqn
51
53
  DeploymentOrFqn: Deployment | WithId<this['DeploymentFqn']>
52
54
 
53
- ViewId: IsLiteral<Views> extends true ? ViewId<Views> : ViewId
54
- ViewIdLiteral: Views
55
+ // Wrapped View
56
+ ViewId: IsStringLiteral<View> extends true ? ViewId<View> : ViewId
57
+
55
58
  ViewType: ViewType
56
59
 
57
60
  RelationId: RelationId
@@ -63,7 +66,7 @@ export interface Aux<
63
66
  NodeOrId: LiteralUnion<this['NodeIdLiteral'], string> | WithId<this['NodeId']>
64
67
  EdgeOrId: LiteralUnion<this['EdgeIdLiteral'], string> | WithId<this['EdgeId']>
65
68
 
66
- Model: Simplify<Omit<AnyLikeC4Model, 'views'> & WithViews<this['ViewId'], ViewType>>
69
+ Model: Simplify<Omit<GenericLikeC4Model, 'views'> & WithViews<this['ViewId'], ViewType>>
67
70
  }
68
71
 
69
72
  export type AnyAux = Aux<
@@ -73,8 +76,22 @@ export type AnyAux = Aux<
73
76
  any
74
77
  >
75
78
 
79
+ export namespace Strict {
80
+ export type Fqn<A extends AnyAux> = A['Element']
81
+ export type Deployment<A extends AnyAux> = A['Deployment']
82
+ export type ViewId<A extends AnyAux> = A['View']
83
+ }
84
+
76
85
  export namespace Aux {
77
- export type FromModel<M> = M extends AnyLikeC4Model ? Aux<
86
+ export type FromParsed<M> = M extends ParsedLikeC4Model ? Aux<
87
+ KeysOf<M['elements']>,
88
+ KeysOf<M['deployments']['elements']>,
89
+ KeysOf<M['views']>,
90
+ ComputedView<ViewId<KeysOf<M['views']>>, string>
91
+ >
92
+ : never
93
+
94
+ export type FromModel<M> = M extends GenericLikeC4Model ? Aux<
78
95
  KeysOf<M['elements']>,
79
96
  KeysOf<M['deployments']['elements']>,
80
97
  KeysOf<M['views']>,
@@ -83,7 +100,7 @@ export namespace Aux {
83
100
  >
84
101
  : never
85
102
 
86
- export type FromDump<M> = M extends ParsedLikeC4ModelDump ? Aux<
103
+ export type FromDump<M> = M extends LikeC4ModelDump ? Aux<
87
104
  KeysOf<M['elements']>,
88
105
  KeysOf<M['deployments']['elements']>,
89
106
  KeysOf<M['views']>,
@@ -4,16 +4,17 @@ import {
4
4
  type ComputedDynamicView,
5
5
  type ComputedView,
6
6
  type DiagramView,
7
- extractStep,
8
- isStepEdgeId,
7
+ type IteratorLike,
9
8
  type RelationId as C4RelationID,
10
9
  type StepEdgeId,
11
- type Tag as C4Tag
10
+ type Tag as C4Tag,
11
+ extractStep,
12
+ isStepEdgeId,
12
13
  } from '../../types'
13
14
  import type { DeploymentRelationModel } from '../DeploymentElementModel'
14
15
  import type { LikeC4Model } from '../LikeC4Model'
15
16
  import type { RelationshipModel } from '../RelationModel'
16
- import type { AnyAux, IteratorLike } from '../types'
17
+ import type { AnyAux } from '../types'
17
18
  import type { LikeC4ViewModel } from './LikeC4ViewModel'
18
19
  import type { NodeModel } from './NodeModel'
19
20
 
@@ -24,7 +25,7 @@ export class EdgeModel<M extends AnyAux, V extends ComputedView | DiagramView =
24
25
  public readonly view: LikeC4ViewModel<M, V>,
25
26
  public readonly $edge: V['edges'][number],
26
27
  public readonly source: NodeModel<M, V>,
27
- public readonly target: NodeModel<M, V>
28
+ public readonly target: NodeModel<M, V>,
28
29
  ) {
29
30
  }
30
31
 
@@ -75,7 +76,6 @@ export class EdgeModel<M extends AnyAux, V extends ComputedView | DiagramView =
75
76
  for (const id of this.$edge.relations) {
76
77
  // if type is provided, then we need to filter relationships
77
78
  if (type) {
78
- yield this.view.$model.relationship(id, type)
79
79
  const rel = this.view.$model.findRelationship(id, type)
80
80
  if (rel) {
81
81
  yield rel
@@ -1,5 +1,6 @@
1
1
  import { sort } from 'remeda'
2
2
  import { nonNullable } from '../../errors'
3
+ import type { IteratorLike } from '../../types'
3
4
  import type { Link, Tag } from '../../types/element'
4
5
  import {
5
6
  type ComputedDeploymentView,
@@ -8,19 +9,19 @@ import {
8
9
  type ComputedView,
9
10
  type DiagramView,
10
11
  type EdgeId as C4EdgeId,
12
+ type LikeC4View,
13
+ type NodeId as C4NodeId,
11
14
  isDeploymentView,
12
15
  isDynamicView,
13
16
  isElementView,
14
17
  isScopedElementView,
15
- type LikeC4View,
16
- type NodeId as C4NodeId
17
18
  } from '../../types/view'
18
19
  import { compareByFqnHierarchically, getOrCreate } from '../../utils'
19
20
  import type { ElementModel } from '../ElementModel'
20
21
  import type { LikeC4Model } from '../LikeC4Model'
21
- import { type AnyAux, getId, type IteratorLike } from '../types'
22
- import { EdgeModel, type EdgesIterator } from './EdgeModel'
23
- import { NodeModel, type NodesIterator } from './NodeModel'
22
+ import { type AnyAux, getId } from '../types'
23
+ import { type EdgesIterator, EdgeModel } from './EdgeModel'
24
+ import { type NodesIterator, NodeModel } from './NodeModel'
24
25
 
25
26
  export type ViewsIterator<M extends AnyAux> = IteratorLike<LikeC4ViewModel<M>>
26
27
 
@@ -35,10 +36,10 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
35
36
 
36
37
  constructor(
37
38
  public readonly $model: LikeC4Model<M>,
38
- public readonly $view: V
39
+ public readonly $view: V,
39
40
  ) {
40
41
  for (const node of sort($view.nodes, compareByFqnHierarchically)) {
41
- const el = new NodeModel(this, node)
42
+ const el = new NodeModel(this, Object.freeze(node))
42
43
  this.#nodes.set(node.id, el)
43
44
  if (!node.parent) {
44
45
  this.#rootnodes.add(el)
@@ -55,7 +56,12 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
55
56
  }
56
57
 
57
58
  for (const edge of $view.edges) {
58
- const edgeModel = new EdgeModel(this, edge, this.node(edge.source), this.node(edge.target))
59
+ const edgeModel = new EdgeModel(
60
+ this,
61
+ Object.freeze(edge),
62
+ this.node(edge.source),
63
+ this.node(edge.target),
64
+ )
59
65
  for (const tag of edgeModel.tags) {
60
66
  getOrCreate(this.#allTags, tag, () => new Set()).add(edgeModel)
61
67
  }
@@ -1,18 +1,19 @@
1
1
  import {
2
2
  type Color as C4Color,
3
- ComputedNode,
4
3
  type ComputedView,
5
4
  type DeploymentNodeKind,
6
5
  type DiagramView,
7
- ElementKind,
8
6
  type ElementShape as C4ElementShape,
7
+ type IteratorLike,
9
8
  type Link,
10
9
  type NodeId,
11
- type Tag as C4Tag
10
+ type Tag as C4Tag,
11
+ ComputedNode,
12
+ ElementKind,
12
13
  } from '../../types'
13
14
  import type { DeployedInstanceModel, DeploymentElementModel } from '../DeploymentElementModel'
14
15
  import type { ElementModel } from '../ElementModel'
15
- import type { AnyAux, IncomingFilter, IteratorLike, OutgoingFilter } from '../types'
16
+ import type { AnyAux, IncomingFilter, OutgoingFilter } from '../types'
16
17
  import type { EdgesIterator } from './EdgeModel'
17
18
  import type { LikeC4ViewModel } from './LikeC4ViewModel'
18
19
 
@@ -50,7 +51,7 @@ export namespace NodeModel {
50
51
  export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView = M['ViewType']> {
51
52
  constructor(
52
53
  public readonly $view: LikeC4ViewModel<M, V>,
53
- public readonly $node: V['nodes'][number]
54
+ public readonly $node: V['nodes'][number],
54
55
  ) {
55
56
  }
56
57
 
@@ -1,4 +1,4 @@
1
- import type { Tagged } from 'type-fest'
1
+ import type { Simplify, Tagged, UnionToIntersection } from 'type-fest'
2
2
 
3
3
  export type NonEmptyArray<T> = [T, ...T[]]
4
4
 
@@ -16,3 +16,55 @@ export interface XYPoint {
16
16
  }
17
17
 
18
18
  export type KeysOf<T> = keyof T extends infer K extends string ? K : never
19
+
20
+ type AllNever<Expressions> = UnionToIntersection<
21
+ {
22
+ [Name in keyof Expressions]: {
23
+ -readonly [Key in keyof Expressions[Name]]?: never
24
+ }
25
+ }[keyof Expressions]
26
+ >
27
+
28
+ /**
29
+ * @example
30
+ * type Variant1 = {
31
+ * a: string
32
+ * }
33
+ * type Variant2 = {
34
+ * b: number
35
+ * }
36
+ *
37
+ * type Variants = ExclusiveUnion<{
38
+ * Variant1: Variant1,
39
+ * Variant2: Variant2
40
+ * }>
41
+ *
42
+ * Fail here
43
+ * const variant1: Variants = {
44
+ * a: 'one',
45
+ * b: 1
46
+ * }
47
+ */
48
+
49
+ export type ExclusiveUnion<Expressions> = Expressions extends object ? {
50
+ [Name in keyof Expressions]: Simplify<Omit<AllNever<Expressions>, keyof Expressions[Name]> & Expressions[Name]>
51
+ }[keyof Expressions]
52
+ : Expressions
53
+
54
+ /**
55
+ * Copy from https://github.com/remeda/remeda/blob/main/src/internal/types/NTuple.ts
56
+ * An array with *exactly* N elements in it.
57
+ *
58
+ * Only literal N values are supported. For very large N the type might result
59
+ * in a recurse depth error. For negative N the type would result in an infinite
60
+ * recursion. None of these have protections because this is an internal type!
61
+ */
62
+ export type NTuple<
63
+ T,
64
+ N extends number,
65
+ Result extends Array<unknown> = [],
66
+ > = Result['length'] extends N ? Result : NTuple<T, N, [...Result, T]>
67
+
68
+ export type IteratorLike<T> = IteratorObject<T, BuiltinIteratorReturn>
69
+
70
+ export type Predicate<T> = (x: T) => boolean