@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,36 @@
|
|
|
1
|
+
import { map, mapToObj, mapValues, omit } from 'remeda'
|
|
2
|
+
import type { ComputedLikeC4Model } from '../../types'
|
|
3
|
+
import type { ComputedView, EdgeId } from '../../types/view'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert hashed edge ids to human-readable
|
|
7
|
+
* Mostly for testing purposes
|
|
8
|
+
*/
|
|
9
|
+
export function withReadableEdges<T extends ComputedView>({ edges, nodes, ...view }: T, separator = ':'): T & {
|
|
10
|
+
nodeIds: string[]
|
|
11
|
+
edgeIds: string[]
|
|
12
|
+
} {
|
|
13
|
+
const edgeids = mapToObj(edges, e => [e.id, `${e.source}${separator}${e.target}` as EdgeId])
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
...view,
|
|
17
|
+
edges: edges.map(e => ({
|
|
18
|
+
...e,
|
|
19
|
+
id: edgeids[e.id]!,
|
|
20
|
+
})),
|
|
21
|
+
nodes: nodes.map(n => ({
|
|
22
|
+
...n,
|
|
23
|
+
inEdges: map(n.inEdges, e => edgeids[e]!),
|
|
24
|
+
outEdges: map(n.outEdges, e => edgeids[e]!),
|
|
25
|
+
})),
|
|
26
|
+
nodeIds: nodes.map(n => n.id),
|
|
27
|
+
edgeIds: edges.map(e => edgeids[e.id]!),
|
|
28
|
+
} as any
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function viewsWithReadableEdges<M extends ComputedLikeC4Model>({ views, ...model }: M): M {
|
|
32
|
+
return {
|
|
33
|
+
...model,
|
|
34
|
+
views: mapValues(views, v => omit(withReadableEdges(v), ['nodeIds', 'edgeIds'])),
|
|
35
|
+
} as any
|
|
36
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export {
|
|
2
|
+
computeColorValues,
|
|
3
|
+
defaultTheme,
|
|
4
|
+
ElementColors,
|
|
5
|
+
RelationshipColors,
|
|
6
|
+
} from './colors'
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
invariant,
|
|
10
|
+
nonexhaustive,
|
|
11
|
+
nonNullable,
|
|
12
|
+
} from './errors'
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
type AnyAux,
|
|
16
|
+
type Aux,
|
|
17
|
+
LikeC4DeploymentModel,
|
|
18
|
+
LikeC4Model,
|
|
19
|
+
LikeC4ViewModel,
|
|
20
|
+
} from './model'
|
|
7
21
|
|
|
8
22
|
export * from './types'
|
|
9
|
-
|
|
10
|
-
export * from './utils
|
|
11
|
-
export * from './utils/fqn'
|
|
12
|
-
export * from './utils/guards'
|
|
13
|
-
export * from './utils/promises'
|
|
14
|
-
export { compareRelations } from './utils/relations'
|
|
23
|
+
|
|
24
|
+
export * from './utils'
|
|
15
25
|
|
|
16
26
|
export * as Expr from './types/expression'
|
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import { isEmpty, only } from 'remeda'
|
|
2
|
+
import type { SetRequired } from 'type-fest'
|
|
3
|
+
import { nonNullable } from '../errors'
|
|
4
|
+
import {
|
|
5
|
+
type ComputedDeploymentView,
|
|
6
|
+
type DeployedInstance,
|
|
7
|
+
type DeploymentElementStyle,
|
|
8
|
+
type DeploymentNode,
|
|
9
|
+
type DeploymentNodeKind,
|
|
10
|
+
type DeploymentRelation,
|
|
11
|
+
type ElementShape as C4ElementShape,
|
|
12
|
+
type IteratorLike,
|
|
13
|
+
type Link,
|
|
14
|
+
type Tag,
|
|
15
|
+
type Tag as C4Tag,
|
|
16
|
+
type ThemeColor,
|
|
17
|
+
DefaultElementShape,
|
|
18
|
+
DefaultThemeColor,
|
|
19
|
+
} from '../types'
|
|
20
|
+
import { commonAncestor, hierarchyLevel } from '../utils'
|
|
21
|
+
import { difference, intersection, union } from '../utils/set'
|
|
22
|
+
import type { LikeC4DeploymentModel } from './DeploymentModel'
|
|
23
|
+
import type { ElementModel } from './ElementModel'
|
|
24
|
+
import type { RelationshipModel, RelationshipsIterator } from './RelationModel'
|
|
25
|
+
import type { AnyAux, IncomingFilter, OutgoingFilter } from './types'
|
|
26
|
+
import type { LikeC4ViewModel } from './view/LikeC4ViewModel'
|
|
27
|
+
|
|
28
|
+
export type DeploymentElementsIterator<M extends AnyAux> = IteratorLike<
|
|
29
|
+
DeploymentNodeModel<M> | DeployedInstanceModel<M>
|
|
30
|
+
>
|
|
31
|
+
export type DeployedInstancesIterator<M extends AnyAux> = IteratorLike<DeployedInstanceModel<M>>
|
|
32
|
+
export type DeploymentNodesIterator<M extends AnyAux> = IteratorLike<DeploymentNodeModel<M>>
|
|
33
|
+
|
|
34
|
+
export type DeploymentElementModel<M extends AnyAux = AnyAux> = DeploymentNodeModel<M> | DeployedInstanceModel<M>
|
|
35
|
+
|
|
36
|
+
abstract class AbstractDeploymentElementModel<M extends AnyAux = AnyAux> {
|
|
37
|
+
abstract readonly id: M['DeploymentFqn']
|
|
38
|
+
abstract readonly parent: DeploymentNodeModel<M> | null
|
|
39
|
+
abstract readonly title: string
|
|
40
|
+
abstract readonly hierarchyLevel: number
|
|
41
|
+
|
|
42
|
+
abstract readonly $model: LikeC4DeploymentModel<M>
|
|
43
|
+
abstract readonly $node: DeploymentNode | DeployedInstance
|
|
44
|
+
|
|
45
|
+
get style(): SetRequired<DeploymentElementStyle, 'shape' | 'color'> {
|
|
46
|
+
return {
|
|
47
|
+
shape: DefaultElementShape,
|
|
48
|
+
color: DefaultThemeColor,
|
|
49
|
+
...this.$node.style,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get shape(): C4ElementShape {
|
|
54
|
+
return this.$node.style?.shape ?? DefaultElementShape
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get color(): ThemeColor {
|
|
58
|
+
return this.$node.style?.color as ThemeColor ?? DefaultThemeColor
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get tags(): ReadonlyArray<C4Tag> {
|
|
62
|
+
return this.$node.tags ?? []
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get description(): string | null {
|
|
66
|
+
return this.$node.description ?? null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get technology(): string | null {
|
|
70
|
+
return this.$node.technology ?? null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get links(): ReadonlyArray<Link> {
|
|
74
|
+
return this.$node.links ?? []
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
79
|
+
* (from closest to root)
|
|
80
|
+
*/
|
|
81
|
+
public ancestors(): DeploymentNodesIterator<M> {
|
|
82
|
+
return this.$model.ancestors(this)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns the common ancestor of this element and another element.
|
|
87
|
+
*/
|
|
88
|
+
public commonAncestor(another: DeploymentElementModel<M>): DeploymentNodeModel<M> | null {
|
|
89
|
+
const common = commonAncestor(this.id, another.id)
|
|
90
|
+
return common ? this.$model.node(common) : null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get all sibling (i.e. same parent)
|
|
95
|
+
*/
|
|
96
|
+
public siblings(): DeploymentElementsIterator<M> {
|
|
97
|
+
return this.$model.siblings(this)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if the element is a sibling of another element
|
|
102
|
+
*/
|
|
103
|
+
public isSibling(other: DeploymentElementModel<M>): boolean {
|
|
104
|
+
return this.parent === other.parent
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Resolve siblings of the element and its ancestors
|
|
109
|
+
* (from closest to root)
|
|
110
|
+
*/
|
|
111
|
+
public *ascendingSiblings(): DeploymentElementsIterator<M> {
|
|
112
|
+
yield* this.siblings()
|
|
113
|
+
for (const ancestor of this.ancestors()) {
|
|
114
|
+
yield* ancestor.siblings()
|
|
115
|
+
}
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Resolve siblings of the element and its ancestors
|
|
121
|
+
* (from root to closest)
|
|
122
|
+
*/
|
|
123
|
+
public *descendingSiblings(): DeploymentElementsIterator<M> {
|
|
124
|
+
for (const ancestor of [...this.ancestors()].reverse()) {
|
|
125
|
+
yield* ancestor.siblings()
|
|
126
|
+
}
|
|
127
|
+
yield* this.siblings()
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public incoming(filter: IncomingFilter = 'all'): IteratorLike<DeploymentRelationModel<M>> {
|
|
132
|
+
return this.$model.incoming(this, filter)
|
|
133
|
+
}
|
|
134
|
+
public outgoing(filter: OutgoingFilter = 'all'): IteratorLike<DeploymentRelationModel<M>> {
|
|
135
|
+
return this.$model.outgoing(this, filter)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public *incomers(filter: IncomingFilter = 'all'): IteratorLike<DeploymentRelationEndpoint<M>> {
|
|
139
|
+
const unique = new Set<M['Deployment']>()
|
|
140
|
+
for (const r of this.incoming(filter)) {
|
|
141
|
+
if (unique.has(r.source.id)) {
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
unique.add(r.source.id)
|
|
145
|
+
yield r.source
|
|
146
|
+
}
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
public *outgoers(filter: OutgoingFilter = 'all'): IteratorLike<DeploymentRelationEndpoint<M>> {
|
|
150
|
+
const unique = new Set<M['Deployment']>()
|
|
151
|
+
for (const r of this.outgoing(filter)) {
|
|
152
|
+
if (unique.has(r.target.id)) {
|
|
153
|
+
continue
|
|
154
|
+
}
|
|
155
|
+
unique.add(r.target.id)
|
|
156
|
+
yield r.target
|
|
157
|
+
}
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Iterate over all views that include this deployment element.
|
|
163
|
+
*/
|
|
164
|
+
public *views(): IteratorLike<LikeC4ViewModel<M, ComputedDeploymentView>> {
|
|
165
|
+
for (const view of this.$model.views()) {
|
|
166
|
+
if (!view.isDeploymentView()) {
|
|
167
|
+
continue
|
|
168
|
+
}
|
|
169
|
+
if (view.includesDeployment(this.id)) {
|
|
170
|
+
yield view
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// type guard
|
|
176
|
+
public isDeploymentNode(): this is DeploymentNodeModel<M> {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
// type guard
|
|
180
|
+
public isInstance(): this is DeployedInstanceModel<M> {
|
|
181
|
+
return false
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public abstract outgoingModelRelationships(): RelationshipsIterator<M>
|
|
185
|
+
public abstract incomingModelRelationships(): RelationshipsIterator<M>
|
|
186
|
+
|
|
187
|
+
protected cachedOutgoing: RelationshipsAccum<M> | null = null
|
|
188
|
+
protected cachedIncoming: RelationshipsAccum<M> | null = null
|
|
189
|
+
|
|
190
|
+
public get allOutgoing(): RelationshipsAccum<M> {
|
|
191
|
+
this.cachedOutgoing ??= RelationshipsAccum.from(
|
|
192
|
+
new Set(this.outgoingModelRelationships()),
|
|
193
|
+
new Set(this.outgoing()),
|
|
194
|
+
)
|
|
195
|
+
return this.cachedOutgoing
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public get allIncoming(): RelationshipsAccum<M> {
|
|
199
|
+
this.cachedIncoming ??= RelationshipsAccum.from(
|
|
200
|
+
new Set(this.incomingModelRelationships()),
|
|
201
|
+
new Set(this.incoming()),
|
|
202
|
+
)
|
|
203
|
+
return this.cachedIncoming
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export class DeploymentNodeModel<M extends AnyAux = AnyAux> extends AbstractDeploymentElementModel<M> {
|
|
208
|
+
override id: M['DeploymentFqn']
|
|
209
|
+
override title: string
|
|
210
|
+
override hierarchyLevel: number
|
|
211
|
+
|
|
212
|
+
constructor(
|
|
213
|
+
public readonly $model: LikeC4DeploymentModel<M>,
|
|
214
|
+
public readonly $node: DeploymentNode,
|
|
215
|
+
) {
|
|
216
|
+
super()
|
|
217
|
+
this.id = $node.id
|
|
218
|
+
this.title = $node.title
|
|
219
|
+
this.hierarchyLevel = hierarchyLevel($node.id)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
get parent(): DeploymentNodeModel<M> | null {
|
|
223
|
+
return this.$model.parent(this)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
get kind(): DeploymentNodeKind {
|
|
227
|
+
return this.$node.kind
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
public children(): ReadonlySet<DeploymentElementModel<M>> {
|
|
231
|
+
return this.$model.children(this)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public descendants(sort: 'asc' | 'desc' = 'desc'): DeploymentElementsIterator<M> {
|
|
235
|
+
return this.$model.descendants(this, sort)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public override isDeploymentNode(): this is DeploymentNodeModel<M> {
|
|
239
|
+
return true
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Iterate over all instances nested in this deployment node.
|
|
244
|
+
*/
|
|
245
|
+
public *instances(): DeployedInstancesIterator<M> {
|
|
246
|
+
for (const nested of this.descendants('desc')) {
|
|
247
|
+
if (nested.isInstance()) {
|
|
248
|
+
yield nested
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Returns deployed instance inside this deployment node
|
|
256
|
+
* if only there are no more instances
|
|
257
|
+
*/
|
|
258
|
+
public onlyOneInstance(): DeployedInstanceModel<M> | null {
|
|
259
|
+
const children = this.children()
|
|
260
|
+
if (children.size !== 1) {
|
|
261
|
+
return null
|
|
262
|
+
}
|
|
263
|
+
const child = only([...children])
|
|
264
|
+
return child?.isInstance() ? child : null
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Cached result of relationships from instances
|
|
269
|
+
*/
|
|
270
|
+
private _relationshipsFromInstances: {
|
|
271
|
+
outgoing: ReadonlySet<RelationshipModel<M>>
|
|
272
|
+
incoming: ReadonlySet<RelationshipModel<M>>
|
|
273
|
+
} | null = null
|
|
274
|
+
|
|
275
|
+
private relationshipsFromInstances() {
|
|
276
|
+
if (this._relationshipsFromInstances) {
|
|
277
|
+
return this._relationshipsFromInstances
|
|
278
|
+
}
|
|
279
|
+
const {
|
|
280
|
+
outgoing,
|
|
281
|
+
incoming,
|
|
282
|
+
} = (this._relationshipsFromInstances = {
|
|
283
|
+
outgoing: new Set<RelationshipModel<M>>(),
|
|
284
|
+
incoming: new Set<RelationshipModel<M>>(),
|
|
285
|
+
})
|
|
286
|
+
for (const instance of this.instances()) {
|
|
287
|
+
for (const r of instance.element.outgoing()) {
|
|
288
|
+
outgoing.add(r)
|
|
289
|
+
}
|
|
290
|
+
for (const r of instance.element.incoming()) {
|
|
291
|
+
incoming.add(r)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return this._relationshipsFromInstances
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* We return only relationships that are not already present in nested instances
|
|
299
|
+
*/
|
|
300
|
+
public override outgoingModelRelationships(): RelationshipsIterator<M> {
|
|
301
|
+
return this.relationshipsFromInstances().outgoing.values()
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* We return only relationships that are not already present in nested instances
|
|
306
|
+
*/
|
|
307
|
+
public override incomingModelRelationships(): RelationshipsIterator<M> {
|
|
308
|
+
return this.relationshipsFromInstances().incoming.values()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Returns an iterator of relationships between nested instances
|
|
313
|
+
*/
|
|
314
|
+
public internalModelRelationships(): ReadonlySet<RelationshipModel<M>> {
|
|
315
|
+
const {
|
|
316
|
+
outgoing,
|
|
317
|
+
incoming,
|
|
318
|
+
} = this.relationshipsFromInstances()
|
|
319
|
+
return intersection(incoming, outgoing)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export class DeployedInstanceModel<M extends AnyAux = AnyAux> extends AbstractDeploymentElementModel<M> {
|
|
324
|
+
override readonly id: M['DeploymentFqn']
|
|
325
|
+
override readonly title: string
|
|
326
|
+
override readonly hierarchyLevel: number
|
|
327
|
+
|
|
328
|
+
constructor(
|
|
329
|
+
public readonly $model: LikeC4DeploymentModel<M>,
|
|
330
|
+
public readonly $instance: DeployedInstance,
|
|
331
|
+
public readonly element: ElementModel<M>,
|
|
332
|
+
) {
|
|
333
|
+
super()
|
|
334
|
+
this.id = $instance.id
|
|
335
|
+
this.title = $instance.title ?? element.title
|
|
336
|
+
this.hierarchyLevel = hierarchyLevel($instance.id)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
get $node(): DeployedInstance {
|
|
340
|
+
return this.$instance
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
get parent(): DeploymentNodeModel<M> {
|
|
344
|
+
return nonNullable(this.$model.parent(this), `Parent of ${this.id} not found`)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
override get style(): SetRequired<DeploymentElementStyle, 'shape' | 'color'> {
|
|
348
|
+
const { icon, style } = this.element.$element
|
|
349
|
+
return {
|
|
350
|
+
shape: this.element.shape,
|
|
351
|
+
color: this.element.color,
|
|
352
|
+
...icon && { icon },
|
|
353
|
+
...style,
|
|
354
|
+
...this.$instance.style,
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
override get shape(): C4ElementShape {
|
|
359
|
+
return this.$instance.style?.shape ?? this.element.shape
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
override get color(): ThemeColor {
|
|
363
|
+
return this.$instance.style?.color as ThemeColor ?? this.element.color
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
override get tags(): ReadonlyArray<C4Tag> {
|
|
367
|
+
return this.$instance.tags ?? []
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
override get description(): string | null {
|
|
371
|
+
return this.$instance.description ?? this.element.description
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
override get technology(): string | null {
|
|
375
|
+
return this.$instance.technology ?? this.element.technology
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
override get links(): ReadonlyArray<Link> {
|
|
379
|
+
return this.$instance.links ?? this.element.links
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
public override isInstance(): this is DeployedInstanceModel<M> {
|
|
383
|
+
return true
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
public override outgoingModelRelationships(): RelationshipsIterator<M> {
|
|
387
|
+
return this.element.outgoing()
|
|
388
|
+
}
|
|
389
|
+
public override incomingModelRelationships(): RelationshipsIterator<M> {
|
|
390
|
+
return this.element.incoming()
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Iterate over all views that include this instance.
|
|
395
|
+
* (Some views may include the parent deployment node instead of the instance.)
|
|
396
|
+
*/
|
|
397
|
+
public override *views(): IteratorLike<LikeC4ViewModel<M, ComputedDeploymentView>> {
|
|
398
|
+
for (const view of this.$model.views()) {
|
|
399
|
+
if (!view.isDeploymentView()) {
|
|
400
|
+
continue
|
|
401
|
+
}
|
|
402
|
+
if (view.includesDeployment(this.id)) {
|
|
403
|
+
yield view
|
|
404
|
+
continue
|
|
405
|
+
}
|
|
406
|
+
// check if the view includes parent referecing this element
|
|
407
|
+
if (
|
|
408
|
+
view.includesDeployment(this.parent.id)
|
|
409
|
+
&& this.parent.onlyOneInstance()
|
|
410
|
+
) {
|
|
411
|
+
yield view
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export class NestedElementOfDeployedInstanceModel<M extends AnyAux> {
|
|
418
|
+
constructor(
|
|
419
|
+
public readonly instance: DeployedInstanceModel<M>,
|
|
420
|
+
public readonly element: ElementModel<M>,
|
|
421
|
+
) {
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
get id(): M['DeploymentFqn'] {
|
|
425
|
+
return this.instance.id
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
get style(): SetRequired<DeploymentElementStyle, 'shape' | 'color'> {
|
|
429
|
+
const { icon, style } = this.element.$element
|
|
430
|
+
return {
|
|
431
|
+
shape: this.element.shape,
|
|
432
|
+
color: this.element.color,
|
|
433
|
+
...icon && { icon },
|
|
434
|
+
...style,
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
get shape(): C4ElementShape {
|
|
439
|
+
return this.element.shape
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
get color(): ThemeColor {
|
|
443
|
+
return this.element.color
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
get title(): string {
|
|
447
|
+
return this.element.title
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
get description(): string | null {
|
|
451
|
+
return this.element.description
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
get technology(): string | null {
|
|
455
|
+
return this.element.technology
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
public isDeploymentNode(): this is DeploymentNodeModel<M> {
|
|
459
|
+
return false
|
|
460
|
+
}
|
|
461
|
+
public isInstance(): this is DeployedInstanceModel<M> {
|
|
462
|
+
return false
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export type DeploymentRelationEndpoint<M extends AnyAux> =
|
|
467
|
+
| DeploymentElementModel<M>
|
|
468
|
+
| NestedElementOfDeployedInstanceModel<M>
|
|
469
|
+
|
|
470
|
+
export class DeploymentRelationModel<M extends AnyAux = AnyAux> {
|
|
471
|
+
public boundary: DeploymentNodeModel<M> | null
|
|
472
|
+
public source: DeploymentRelationEndpoint<M>
|
|
473
|
+
public target: DeploymentRelationEndpoint<M>
|
|
474
|
+
|
|
475
|
+
constructor(
|
|
476
|
+
public readonly $model: LikeC4DeploymentModel<M>,
|
|
477
|
+
public readonly $relationship: DeploymentRelation,
|
|
478
|
+
) {
|
|
479
|
+
this.source = $model.deploymentRef($relationship.source)
|
|
480
|
+
this.target = $model.deploymentRef($relationship.target)
|
|
481
|
+
const parent = commonAncestor(this.source.id, this.target.id)
|
|
482
|
+
this.boundary = parent ? this.$model.node(parent) : null
|
|
483
|
+
}
|
|
484
|
+
get id(): M['RelationId'] {
|
|
485
|
+
return this.$relationship.id
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
get expression(): string {
|
|
489
|
+
return `${this.source.id} -> ${this.target.id}`
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
get title(): string | null {
|
|
493
|
+
if (isEmpty(this.$relationship.title)) {
|
|
494
|
+
return null
|
|
495
|
+
}
|
|
496
|
+
return this.$relationship.title
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
get technology(): string | null {
|
|
500
|
+
if (isEmpty(this.$relationship.technology)) {
|
|
501
|
+
return null
|
|
502
|
+
}
|
|
503
|
+
return this.$relationship.technology
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
get description(): string | null {
|
|
507
|
+
if (isEmpty(this.$relationship.description)) {
|
|
508
|
+
return null
|
|
509
|
+
}
|
|
510
|
+
return this.$relationship.description
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
get tags(): ReadonlyArray<Tag> {
|
|
514
|
+
return this.$relationship.tags ?? []
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
get navigateTo(): LikeC4ViewModel<M> | null {
|
|
518
|
+
return this.$relationship.navigateTo ? this.$model.$model.view(this.$relationship.navigateTo) : null
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
get links(): ReadonlyArray<Link> {
|
|
522
|
+
return this.$relationship.links ?? []
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
public *views(): IteratorLike<LikeC4ViewModel<M, ComputedDeploymentView>> {
|
|
526
|
+
for (const view of this.$model.views()) {
|
|
527
|
+
if (view.includesRelation(this.id)) {
|
|
528
|
+
yield view
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export class RelationshipsAccum<M extends AnyAux> {
|
|
536
|
+
static empty<M extends AnyAux>(): RelationshipsAccum<M> {
|
|
537
|
+
return new RelationshipsAccum()
|
|
538
|
+
}
|
|
539
|
+
static from<M extends AnyAux>(
|
|
540
|
+
model: Iterable<RelationshipModel<M>> | undefined,
|
|
541
|
+
deployment?: Iterable<DeploymentRelationModel<M>>,
|
|
542
|
+
): RelationshipsAccum<M> {
|
|
543
|
+
return new RelationshipsAccum(
|
|
544
|
+
new Set(model),
|
|
545
|
+
new Set(deployment),
|
|
546
|
+
)
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* @param model relationships from logical model
|
|
550
|
+
* @param deployment relationships from deployment model
|
|
551
|
+
*/
|
|
552
|
+
constructor(
|
|
553
|
+
public readonly model: ReadonlySet<RelationshipModel<M>> = new Set(),
|
|
554
|
+
public readonly deployment: ReadonlySet<DeploymentRelationModel<M>> = new Set(),
|
|
555
|
+
) {
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
get isEmpty(): boolean {
|
|
559
|
+
return this.model.size === 0 && this.deployment.size === 0
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
get nonEmpty(): boolean {
|
|
563
|
+
return this.model.size > 0 || this.deployment.size > 0
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
get size(): number {
|
|
567
|
+
return this.model.size + this.deployment.size
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Returns new Accum containing all the elements which are both in this and otherAccum
|
|
572
|
+
*/
|
|
573
|
+
public intersect(otherAccum: RelationshipsAccum<M>): RelationshipsAccum<M> {
|
|
574
|
+
return RelationshipsAccum.from(
|
|
575
|
+
intersection(this.model, otherAccum.model),
|
|
576
|
+
intersection(this.deployment, otherAccum.deployment),
|
|
577
|
+
)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Returns new Accum containing all the elements which are both in this and otherAccum
|
|
582
|
+
*/
|
|
583
|
+
public difference(otherAccum: RelationshipsAccum<M>): RelationshipsAccum<M> {
|
|
584
|
+
return RelationshipsAccum.from(
|
|
585
|
+
difference(this.model, otherAccum.model),
|
|
586
|
+
difference(this.deployment, otherAccum.deployment),
|
|
587
|
+
)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Returns new Accum containing all the elements from both
|
|
592
|
+
*/
|
|
593
|
+
public union(otherAccum: RelationshipsAccum<M>): RelationshipsAccum<M> {
|
|
594
|
+
return RelationshipsAccum.from(
|
|
595
|
+
union(this.model, otherAccum.model),
|
|
596
|
+
union(this.deployment, otherAccum.deployment),
|
|
597
|
+
)
|
|
598
|
+
}
|
|
599
|
+
}
|