@likec4/core 1.17.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +22 -0
- package/dist/compute-view/index.d.ts +22 -0
- package/dist/compute-view/index.js +78 -0
- package/dist/index.d.mts +10 -919
- package/dist/index.d.ts +10 -919
- package/dist/{index.mjs → index.js} +7 -1688
- package/dist/model/index.d.mts +254 -0
- package/dist/model/index.d.ts +254 -0
- 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.CoLQkcYL.d.cts → core.C05RDLhi.d.ts} +460 -362
- package/dist/shared/{core.CoLQkcYL.d.mts → core.CmYMqgha.d.mts} +460 -362
- 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.-BdzdI2C.js +7443 -0
- package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
- package/dist/shared/{core.BXTs-8n7.mjs → view.CyZrG8BJ.js} +108 -47
- package/dist/types/index.d.mts +71 -1
- package/dist/types/index.d.ts +71 -1
- package/dist/types/index.js +20 -0
- package/dist/utils/index.d.mts +404 -0
- package/dist/utils/index.d.ts +404 -0
- package/dist/utils/index.js +330 -0
- package/package.json +59 -47
- 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 +224 -0
- package/src/builder/Builder.deploymentModel.ts +385 -0
- package/src/builder/Builder.element.ts +19 -19
- package/src/builder/Builder.model.ts +67 -42
- package/src/builder/Builder.ts +533 -367
- 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 +113 -18
- package/src/builder/index.ts +10 -4
- package/src/colors/index.ts +2 -2
- package/src/compute-view/compute-view.ts +83 -0
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
- package/src/compute-view/deployment-view/__test__/fixture.ts +198 -0
- package/src/compute-view/deployment-view/_types.ts +37 -0
- package/src/compute-view/deployment-view/clean-connections.ts +238 -0
- package/src/compute-view/deployment-view/compute.ts +125 -0
- 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 +237 -0
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +61 -0
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +95 -0
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +88 -0
- package/src/compute-view/deployment-view/predicates/wildcard.ts +29 -0
- 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 +276 -0
- package/src/compute-view/dynamic-view/__test__/fixture.ts +58 -0
- package/src/compute-view/dynamic-view/compute.ts +324 -0
- package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +458 -0
- package/src/compute-view/element-view/__test__/fixture.ts +675 -0
- 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 +315 -0
- 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 +4 -0
- 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/__snapshots__/sortNodes.spec.ts.snap +113 -0
- package/src/compute-view/utils/ancestorsOfNode.ts +19 -0
- package/src/compute-view/utils/applyCustomElementProperties.ts +66 -0
- package/src/compute-view/utils/applyCustomRelationProperties.ts +41 -0
- package/src/compute-view/utils/applyViewRuleStyles.ts +53 -0
- package/src/compute-view/utils/buildComputedNodes.ts +148 -0
- package/src/compute-view/utils/buildElementNotations.ts +63 -0
- package/src/compute-view/utils/elementExpressionToPredicate.ts +50 -0
- package/src/compute-view/utils/link-nodes-with-edges.ts +54 -0
- package/src/compute-view/utils/merge-props-from-relationships.ts +128 -0
- package/src/compute-view/utils/relationExpressionToPredicates.ts +55 -0
- package/src/compute-view/utils/resolve-extended-views.ts +69 -0
- package/src/compute-view/utils/resolve-global-rules.ts +83 -0
- package/src/compute-view/utils/topological-sort.ts +256 -0
- package/src/compute-view/utils/uniqueTags.test.ts +42 -0
- package/src/compute-view/utils/uniqueTags.ts +21 -0
- package/src/compute-view/utils/view-hash.ts +27 -0
- package/src/compute-view/utils/with-readable-edges.ts +36 -0
- package/src/index.ts +22 -12
- package/src/model/DeploymentElementModel.ts +599 -0
- package/src/model/DeploymentModel.ts +370 -0
- package/src/model/ElementModel.ts +221 -0
- package/src/model/LikeC4Model.test-d.ts +152 -0
- package/src/model/LikeC4Model.ts +336 -457
- package/src/model/RelationModel.ts +85 -0
- package/src/model/__test__/fixture.ts +149 -338
- package/src/model/connection/Connection.ts +72 -0
- package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
- package/src/model/connection/deployment/find.ts +120 -0
- 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/find.ts +117 -0
- 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 +46 -2
- package/src/model/types.ts +112 -15
- package/src/model/view/EdgeModel.ts +103 -0
- package/src/model/view/LikeC4ViewModel.ts +226 -0
- package/src/model/view/NodeModel.ts +229 -0
- package/src/types/_common.ts +55 -1
- package/src/types/deployments.ts +169 -0
- package/src/types/element.ts +9 -5
- package/src/types/expression-v2.ts +172 -0
- package/src/types/expression.ts +17 -11
- package/src/types/global.ts +3 -3
- package/src/types/index.ts +220 -12
- package/src/types/model.ts +75 -12
- package/src/types/operators.ts +1 -1
- package/src/types/overview-graph.ts +2 -2
- package/src/types/relation.ts +18 -14
- package/src/types/theme.ts +0 -1
- package/src/types/view-notation.ts +2 -2
- package/src/types/view.ts +117 -41
- package/src/utils/{commonHead.ts → common-head.ts} +2 -0
- package/src/utils/const.ts +1 -0
- package/src/utils/fqn.ts +203 -56
- package/src/utils/getOrCreate.ts +42 -0
- package/src/utils/graphlib.ts +10 -0
- package/src/utils/index.ts +74 -6
- package/src/utils/iterable/_types.ts +5 -0
- package/src/utils/iterable/filter.ts +55 -0
- package/src/utils/iterable/flat.ts +17 -0
- package/src/utils/iterable/index.ts +12 -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/object-hash.ts +3 -0
- package/src/utils/relations.ts +3 -64
- package/src/utils/set.ts +78 -0
- package/src/utils/string-hash.ts +16 -0
- package/dist/index.cjs +0 -5452
- package/dist/index.d.cts +0 -1053
- package/dist/shared/core.CoLQkcYL.d.ts +0 -734
- package/dist/shared/core.DIYZvpVg.cjs +0 -353
- package/dist/types/index.cjs +0 -70
- package/dist/types/index.d.cts +0 -2
- package/dist/types/index.mjs +0 -1
- package/src/builder/Builder.test-d.ts +0 -69
- package/src/builder/Builder.view.ts +0 -358
- package/src/model/LikeC4DiagramModel.ts +0 -338
- package/src/model/LikeC4ViewModel.ts +0 -320
|
@@ -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,3 +1,47 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { ElementModel } from './ElementModel'
|
|
2
2
|
export { LikeC4Model } from './LikeC4Model'
|
|
3
|
-
export {
|
|
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'
|
|
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,23 +1,120 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import type { IsStringLiteral, LiteralUnion, Simplify } from 'type-fest'
|
|
2
|
+
import type {
|
|
3
|
+
ComputedView,
|
|
4
|
+
DiagramView,
|
|
5
|
+
EdgeId,
|
|
6
|
+
Fqn,
|
|
7
|
+
GenericLikeC4Model,
|
|
8
|
+
IteratorLike,
|
|
9
|
+
KeysOf,
|
|
10
|
+
LayoutedLikeC4Model,
|
|
11
|
+
LikeC4ModelDump,
|
|
12
|
+
NodeId,
|
|
13
|
+
ParsedLikeC4Model,
|
|
14
|
+
RelationId,
|
|
15
|
+
ViewId,
|
|
16
|
+
} from '../types'
|
|
17
|
+
import { isString } from '../utils/guards'
|
|
12
18
|
|
|
13
19
|
export type IncomingFilter = 'all' | 'direct' | 'to-descendants'
|
|
14
20
|
export type OutgoingFilter = 'all' | 'direct' | 'from-descendants'
|
|
15
21
|
|
|
16
|
-
export type ElementOrFqn = Fqn | { id: Fqn }
|
|
17
|
-
|
|
18
22
|
/**
|
|
19
23
|
* Utility function to extract `id` from the given element.
|
|
20
24
|
*/
|
|
21
|
-
export function getId(element:
|
|
22
|
-
return isString(element) ? element : element.id
|
|
25
|
+
export function getId<Id extends string>(element: string | { id: Id }): Id {
|
|
26
|
+
return isString(element) ? element as Id : element.id
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type WithId<Id> = { id: Id }
|
|
30
|
+
|
|
31
|
+
type WithViews<Id extends string, ViewType> = { views: Record<Id, ViewType> }
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Auxilary type to keep track
|
|
35
|
+
*/
|
|
36
|
+
export interface Aux<
|
|
37
|
+
Element extends string,
|
|
38
|
+
Deployment extends string,
|
|
39
|
+
View extends string,
|
|
40
|
+
ViewType,
|
|
41
|
+
> {
|
|
42
|
+
Element: Element
|
|
43
|
+
Deployment: Deployment
|
|
44
|
+
View: View
|
|
45
|
+
|
|
46
|
+
// Wrapped Element
|
|
47
|
+
// If Fqn is just a string, then we use generic Fqn to have better hints in the editor
|
|
48
|
+
Fqn: IsStringLiteral<Element> extends true ? Fqn<Element> : Fqn
|
|
49
|
+
ElementOrFqn: Element | WithId<this['Fqn']>
|
|
50
|
+
|
|
51
|
+
// Wrapped Deployment
|
|
52
|
+
DeploymentFqn: IsStringLiteral<Deployment> extends true ? Fqn<Deployment> : Fqn
|
|
53
|
+
DeploymentOrFqn: Deployment | WithId<this['DeploymentFqn']>
|
|
54
|
+
|
|
55
|
+
// Wrapped View
|
|
56
|
+
ViewId: IsStringLiteral<View> extends true ? ViewId<View> : ViewId
|
|
57
|
+
|
|
58
|
+
ViewType: ViewType
|
|
59
|
+
|
|
60
|
+
RelationId: RelationId
|
|
61
|
+
NodeId: NodeId
|
|
62
|
+
NodeIdLiteral: string
|
|
63
|
+
EdgeId: EdgeId
|
|
64
|
+
EdgeIdLiteral: string
|
|
65
|
+
|
|
66
|
+
NodeOrId: LiteralUnion<this['NodeIdLiteral'], string> | WithId<this['NodeId']>
|
|
67
|
+
EdgeOrId: LiteralUnion<this['EdgeIdLiteral'], string> | WithId<this['EdgeId']>
|
|
68
|
+
|
|
69
|
+
Model: Simplify<Omit<GenericLikeC4Model, 'views'> & WithViews<this['ViewId'], ViewType>>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type AnyAux = Aux<
|
|
73
|
+
string,
|
|
74
|
+
string,
|
|
75
|
+
string,
|
|
76
|
+
any
|
|
77
|
+
>
|
|
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
|
+
|
|
85
|
+
export namespace 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<
|
|
95
|
+
KeysOf<M['elements']>,
|
|
96
|
+
KeysOf<M['deployments']['elements']>,
|
|
97
|
+
KeysOf<M['views']>,
|
|
98
|
+
M extends LayoutedLikeC4Model ? DiagramView<ViewId<KeysOf<M['views']>>, string>
|
|
99
|
+
: ComputedView<ViewId<KeysOf<M['views']>>, string>
|
|
100
|
+
>
|
|
101
|
+
: never
|
|
102
|
+
|
|
103
|
+
export type FromDump<M> = M extends LikeC4ModelDump ? Aux<
|
|
104
|
+
KeysOf<M['elements']>,
|
|
105
|
+
KeysOf<M['deployments']['elements']>,
|
|
106
|
+
KeysOf<M['views']>,
|
|
107
|
+
DiagramView<ViewId<KeysOf<M['views']>>, string>
|
|
108
|
+
>
|
|
109
|
+
: never
|
|
23
110
|
}
|
|
111
|
+
|
|
112
|
+
// export type FromModel<M> = LikeC4Model<
|
|
113
|
+
// M extends AnyLikeC4Model<
|
|
114
|
+
// infer Fqn extends string,
|
|
115
|
+
// infer Deployment extends string,
|
|
116
|
+
// infer ViewId extends string,
|
|
117
|
+
// any
|
|
118
|
+
// > ? Aux<Fqn, Deployment, ViewId, M>
|
|
119
|
+
// : Aux<KeysOf<>, string, string, ComputedLikeC4Model | LayoutedLikeC4Model>
|
|
120
|
+
// >
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { isNonNullish } from 'remeda'
|
|
2
|
+
import type { LiteralUnion } from 'type-fest'
|
|
3
|
+
import {
|
|
4
|
+
type ComputedDynamicView,
|
|
5
|
+
type ComputedView,
|
|
6
|
+
type DiagramView,
|
|
7
|
+
type IteratorLike,
|
|
8
|
+
type RelationId as C4RelationID,
|
|
9
|
+
type StepEdgeId,
|
|
10
|
+
type Tag as C4Tag,
|
|
11
|
+
extractStep,
|
|
12
|
+
isStepEdgeId,
|
|
13
|
+
} from '../../types'
|
|
14
|
+
import type { DeploymentRelationModel } from '../DeploymentElementModel'
|
|
15
|
+
import type { LikeC4Model } from '../LikeC4Model'
|
|
16
|
+
import type { RelationshipModel } from '../RelationModel'
|
|
17
|
+
import type { AnyAux } from '../types'
|
|
18
|
+
import type { LikeC4ViewModel } from './LikeC4ViewModel'
|
|
19
|
+
import type { NodeModel } from './NodeModel'
|
|
20
|
+
|
|
21
|
+
export type EdgesIterator<M extends AnyAux, V extends ComputedView | DiagramView> = IteratorLike<EdgeModel<M, V>>
|
|
22
|
+
|
|
23
|
+
export class EdgeModel<M extends AnyAux, V extends ComputedView | DiagramView = M['ViewType']> {
|
|
24
|
+
constructor(
|
|
25
|
+
public readonly view: LikeC4ViewModel<M, V>,
|
|
26
|
+
public readonly $edge: V['edges'][number],
|
|
27
|
+
public readonly source: NodeModel<M, V>,
|
|
28
|
+
public readonly target: NodeModel<M, V>,
|
|
29
|
+
) {
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get id(): M['EdgeId'] {
|
|
33
|
+
return this.$edge.id
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get parent(): NodeModel<M, V> | null {
|
|
37
|
+
return this.$edge.parent ? this.view.node(this.$edge.parent) : null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get label(): string | null {
|
|
41
|
+
return this.$edge.label
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get description(): string | null {
|
|
45
|
+
return this.$edge.description ?? null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get technology(): string | null {
|
|
49
|
+
return this.$edge.technology ?? null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public hasParent(): this is EdgeModel.WithParent<M, V> {
|
|
53
|
+
return this.$edge.parent !== null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get tags(): ReadonlyArray<C4Tag> {
|
|
57
|
+
return this.$edge.tags ?? []
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get stepNumber(): number | null {
|
|
61
|
+
return this.isStep() ? extractStep(this.id) : null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get navigateTo(): LikeC4ViewModel<M> | null {
|
|
65
|
+
return this.$edge.navigateTo ? this.view.$model.view(this.$edge.navigateTo) : null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public isStep(): this is EdgeModel.StepEdge<M, ComputedDynamicView> {
|
|
69
|
+
return isStepEdgeId(this.id)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public relationships(type: 'model'): IteratorLike<RelationshipModel<M>>
|
|
73
|
+
public relationships(type: 'deployment'): IteratorLike<DeploymentRelationModel<M>>
|
|
74
|
+
public relationships(type?: 'model' | 'deployment'): IteratorLike<LikeC4Model.AnyRelation<M>>
|
|
75
|
+
public *relationships(type: 'model' | 'deployment' | undefined): IteratorLike<LikeC4Model.AnyRelation<M>> {
|
|
76
|
+
for (const id of this.$edge.relations) {
|
|
77
|
+
// if type is provided, then we need to filter relationships
|
|
78
|
+
if (type) {
|
|
79
|
+
const rel = this.view.$model.findRelationship(id, type)
|
|
80
|
+
if (rel) {
|
|
81
|
+
yield rel
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
yield this.view.$model.relationship(id)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public includesRelation(rel: M['RelationId']): boolean {
|
|
91
|
+
return this.$edge.relations.includes(rel as C4RelationID)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
namespace EdgeModel {
|
|
96
|
+
export interface StepEdge<M extends AnyAux, V extends ComputedView | DiagramView> extends EdgeModel<M, V> {
|
|
97
|
+
id: StepEdgeId
|
|
98
|
+
stepNumber: number
|
|
99
|
+
}
|
|
100
|
+
export interface WithParent<M extends AnyAux, V extends ComputedView | DiagramView> extends EdgeModel<M, V> {
|
|
101
|
+
parent: NodeModel<M, V>
|
|
102
|
+
}
|
|
103
|
+
}
|