@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.
- package/LICENSE +1 -1
- package/dist/builder/index.d.mts +502 -0
- package/dist/builder/index.d.ts +502 -0
- package/dist/builder/index.js +871 -0
- package/dist/compute-view/index.d.mts +9 -78
- package/dist/compute-view/index.d.ts +9 -78
- package/dist/compute-view/index.js +78 -0
- package/dist/index.d.mts +9 -730
- package/dist/index.d.ts +9 -730
- package/dist/{index.mjs → index.js} +7 -784
- package/dist/model/index.d.mts +218 -606
- package/dist/model/index.d.ts +218 -606
- package/dist/model/index.js +1 -0
- package/dist/shared/chunk-RAAYCPUM.M-JWF7SS.js +21 -0
- package/dist/shared/core.BIfgabEw.d.ts +719 -0
- package/dist/shared/core.BZ9Msq7w.d.mts +719 -0
- package/dist/shared/{core.DMYY7C8s.d.mts → core.C05RDLhi.d.ts} +179 -230
- package/dist/shared/{core.DMYY7C8s.d.ts → core.CmYMqgha.d.mts} +179 -230
- package/dist/shared/core.D6-fWbM3.d.ts +127 -0
- package/dist/shared/core.D74xkKkG.d.mts +148 -0
- package/dist/shared/core.D74xkKkG.d.ts +148 -0
- package/dist/shared/core.sLaWHBjR.d.mts +127 -0
- package/dist/shared/index.DafVOuVd.js +7443 -0
- package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
- package/dist/shared/view.CyZrG8BJ.js +354 -0
- package/dist/types/index.d.mts +4 -2
- package/dist/types/index.d.ts +4 -2
- package/dist/types/index.js +20 -0
- package/dist/utils/index.d.mts +419 -0
- package/dist/utils/index.d.ts +419 -0
- package/dist/utils/index.js +347 -0
- package/package.json +47 -33
- package/src/builder/Builder-style1.test-d.ts +190 -0
- package/src/builder/Builder-style2.test-d.ts +175 -0
- package/src/builder/Builder.deployment.ts +25 -20
- package/src/builder/Builder.deploymentModel.ts +80 -55
- package/src/builder/Builder.element.ts +2 -0
- package/src/builder/Builder.model.ts +57 -43
- package/src/builder/Builder.ts +412 -431
- package/src/builder/Builder.view-common.ts +234 -0
- package/src/builder/Builder.view-deployment.ts +135 -0
- package/src/builder/Builder.view-element.ts +189 -0
- package/src/builder/Builder.views.ts +109 -33
- package/src/builder/Builder.with.ts +475 -0
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +374 -0
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +183 -0
- package/src/builder/__snapshots__/Builder.spec.ts.snap +374 -0
- package/src/builder/_types.ts +28 -5
- package/src/builder/index.ts +10 -4
- package/src/colors/index.ts +2 -2
- package/src/compute-view/compute-view.ts +45 -54
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
- package/src/compute-view/deployment-view/__test__/fixture.ts +50 -62
- package/src/compute-view/deployment-view/_types.ts +26 -18
- package/src/compute-view/deployment-view/clean-connections.ts +173 -164
- package/src/compute-view/deployment-view/compute.ts +51 -37
- package/src/compute-view/deployment-view/memory/index.ts +9 -0
- package/src/compute-view/deployment-view/memory/memory.ts +97 -0
- package/src/compute-view/deployment-view/predicates/elements.ts +144 -0
- package/src/compute-view/deployment-view/predicates/relation-direct.ts +183 -76
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +38 -20
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +72 -23
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +61 -22
- package/src/compute-view/deployment-view/predicates/wildcard.ts +15 -15
- package/src/compute-view/deployment-view/stages/stage-exclude.ts +5 -0
- package/src/compute-view/deployment-view/stages/stage-final.ts +245 -0
- package/src/compute-view/deployment-view/stages/stage-include.ts +95 -0
- package/src/compute-view/deployment-view/utils.ts +95 -31
- package/src/compute-view/dynamic-view/__test__/fixture.ts +4 -4
- package/src/compute-view/dynamic-view/compute.ts +59 -45
- package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +64 -62
- package/src/compute-view/element-view/__test__/fixture.ts +147 -117
- package/src/compute-view/element-view/_types.ts +48 -0
- package/src/compute-view/element-view/clean-connections.ts +113 -0
- package/src/compute-view/element-view/compute.ts +264 -683
- package/src/compute-view/element-view/memory/NodeGroup.ts +31 -0
- package/src/compute-view/element-view/memory/index.ts +10 -0
- package/src/compute-view/element-view/memory/memory.ts +177 -0
- package/src/compute-view/element-view/memory/stage-exclude.ts +59 -0
- package/src/compute-view/element-view/memory/stage-final.ts +129 -0
- package/src/compute-view/element-view/memory/stage-include.ts +128 -0
- package/src/compute-view/element-view/predicates/_utils.ts +86 -0
- package/src/compute-view/element-view/predicates/element-expand.ts +33 -0
- package/src/compute-view/element-view/predicates/element-kind-tag.ts +26 -0
- package/src/compute-view/element-view/predicates/element-ref.ts +37 -0
- package/src/compute-view/element-view/predicates/relation-direct.ts +309 -0
- package/src/compute-view/element-view/predicates/relation-in-out.ts +66 -0
- package/src/compute-view/element-view/predicates/relation-in.ts +118 -0
- package/src/compute-view/element-view/predicates/relation-out.ts +116 -0
- package/src/compute-view/element-view/predicates/wildcard.ts +88 -0
- package/src/compute-view/element-view/utils.ts +59 -0
- package/src/compute-view/index.ts +3 -4
- package/src/compute-view/memory/AbstractMemory.ts +45 -0
- package/src/compute-view/memory/AbstractStageExclude.ts +216 -0
- package/src/compute-view/memory/AbstractStageInclude.ts +200 -0
- package/src/compute-view/memory/_types.ts +147 -0
- package/src/compute-view/memory/index.ts +5 -0
- package/src/compute-view/memory/ops.ts +43 -0
- package/src/compute-view/utils/buildComputedNodes.ts +4 -4
- package/src/compute-view/utils/elementExpressionToPredicate.ts +1 -3
- package/src/compute-view/utils/link-nodes-with-edges.ts +3 -7
- package/src/compute-view/utils/{derive-edge-props-from-relationships.ts → merge-props-from-relationships.ts} +54 -23
- package/src/compute-view/utils/relationExpressionToPredicates.ts +2 -2
- package/src/compute-view/utils/resolve-extended-views.ts +44 -40
- package/src/compute-view/utils/resolve-global-rules.ts +6 -6
- package/src/compute-view/utils/topological-sort.ts +167 -71
- package/src/compute-view/utils/with-readable-edges.ts +14 -9
- package/src/index.ts +22 -16
- package/src/model/DeploymentElementModel.ts +150 -85
- package/src/model/DeploymentModel.ts +27 -21
- package/src/model/ElementModel.ts +51 -25
- package/src/model/LikeC4Model.test-d.ts +4 -3
- package/src/model/LikeC4Model.ts +98 -42
- package/src/model/RelationModel.ts +5 -4
- package/src/model/__test__/fixture.ts +5 -9
- package/src/model/connection/Connection.ts +72 -0
- package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
- package/src/model/connection/{deployment.ts → deployment/find.ts} +14 -18
- package/src/model/connection/deployment/index.ts +8 -0
- package/src/model/connection/index.ts +22 -0
- package/src/model/connection/model/ConnectionModel.ts +157 -0
- package/src/model/connection/{model.ts → model/find.ts} +43 -49
- package/src/model/connection/model/index.ts +8 -0
- package/src/model/connection/ops.ts +274 -0
- package/src/model/guards.ts +9 -0
- package/src/model/index.ts +45 -3
- package/src/model/types.ts +35 -18
- package/src/model/view/EdgeModel.ts +6 -6
- package/src/model/view/LikeC4ViewModel.ts +14 -8
- package/src/model/view/NodeModel.ts +6 -5
- package/src/types/_common.ts +53 -1
- package/src/types/deployments.ts +88 -156
- package/src/types/element.ts +2 -2
- package/src/types/expression-v2.ts +172 -0
- package/src/types/expression.ts +9 -5
- package/src/types/global.ts +3 -3
- package/src/types/index.ts +220 -13
- package/src/types/model.ts +28 -24
- package/src/types/operators.ts +1 -1
- package/src/types/relation.ts +14 -10
- package/src/types/theme.ts +0 -1
- package/src/types/view.ts +20 -18
- package/src/utils/const.ts +1 -0
- package/src/utils/fqn.ts +140 -49
- package/src/utils/getOrCreate.ts +1 -1
- package/src/utils/index.ts +75 -9
- package/src/utils/iterable/_types.ts +5 -0
- package/src/utils/iterable/filter.ts +55 -0
- package/src/utils/iterable/find.ts +36 -0
- package/src/utils/iterable/flat.ts +17 -0
- package/src/utils/iterable/index.ts +13 -0
- package/src/utils/iterable/map.ts +40 -0
- package/src/utils/iterable/reduce.ts +24 -0
- package/src/utils/iterable/some.ts +36 -0
- package/src/utils/iterable/to.ts +19 -0
- package/src/utils/iterable/unique.ts +29 -0
- package/src/utils/relations.ts +3 -64
- package/src/utils/set.ts +11 -9
- package/src/utils/string-hash.ts +1 -1
- package/dist/compute-view/index.mjs +0 -79
- package/dist/model/index.mjs +0 -2
- package/dist/shared/core.BBgiAAv1.mjs +0 -144
- package/dist/shared/core.BPyJvuMU.mjs +0 -2420
- package/dist/shared/core.BQ4AbfvB.mjs +0 -9228
- package/dist/shared/core.k12s_keD.mjs +0 -203
- package/dist/types/index.mjs +0 -21
- package/src/builder/Builder.test-d.ts +0 -124
- package/src/builder/Builder.view.ts +0 -543
- package/src/compute-view/LikeC4ModelGraph.ts +0 -330
- package/src/compute-view/deployment-view/Memory.ts +0 -108
- package/src/compute-view/deployment-view/Stage.ts +0 -145
- package/src/compute-view/deployment-view/predicates/deployment-ref.ts +0 -146
- package/src/compute-view/element-view/predicates.ts +0 -517
- package/src/compute-view/utils/sortNodes.ts +0 -101
- package/src/model/connection/ConnectionModel.ts +0 -94
- 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
|
+
}
|
package/src/model/index.ts
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { ElementModel } from './ElementModel'
|
|
2
2
|
export { LikeC4Model } from './LikeC4Model'
|
|
3
|
-
export
|
|
4
|
-
|
|
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'
|
package/src/model/types.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
ViewType
|
|
39
|
+
View extends string,
|
|
40
|
+
ViewType,
|
|
41
41
|
> {
|
|
42
|
-
|
|
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:
|
|
46
|
-
Element: Element
|
|
48
|
+
Fqn: IsStringLiteral<Element> extends true ? Fqn<Element> : Fqn
|
|
47
49
|
ElementOrFqn: Element | WithId<this['Fqn']>
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
Deployment:
|
|
51
|
+
// Wrapped Deployment
|
|
52
|
+
DeploymentFqn: IsStringLiteral<Deployment> extends true ? Fqn<Deployment> : Fqn
|
|
51
53
|
DeploymentOrFqn: Deployment | WithId<this['DeploymentFqn']>
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
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<
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
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(
|
|
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,
|
|
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
|
|
package/src/types/_common.ts
CHANGED
|
@@ -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
|