@likec4/core 1.31.0 → 1.32.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/README.md +407 -5
- package/dist/builder/index.d.mts +221 -42
- package/dist/builder/index.mjs +118 -65
- package/dist/compute-view/index.d.mts +23 -7
- package/dist/compute-view/index.mjs +11 -6
- package/dist/compute-view/relationships-view/index.d.mts +9 -7
- package/dist/compute-view/relationships-view/index.mjs +3 -2
- package/dist/index.d.mts +10 -14
- package/dist/index.mjs +9 -6
- package/dist/model/index.d.mts +173 -19
- package/dist/model/index.mjs +6 -1
- package/dist/shared/core.BaYE_r29.d.mts +258 -0
- package/dist/shared/core.Bk7wEZFG.mjs +276 -0
- package/dist/shared/core.BrCnZFTn.mjs +32 -0
- package/dist/shared/core.BuO4ncfY.d.mts +146 -0
- package/dist/shared/{core.Bq753SYD.mjs → core.CBpKAlhj.mjs} +2012 -4422
- package/dist/shared/core.CCWXGc6G.d.mts +920 -0
- package/dist/shared/core.CUYDgv2-.mjs +214 -0
- package/dist/shared/{core.Cu-UdkSl.mjs → core.CpXlRyE5.mjs} +7 -494
- package/dist/shared/{core.C-YXI-43.mjs → core.Cy9smucx.mjs} +3 -1
- package/dist/shared/core.CywrQs86.d.mts +31 -0
- package/dist/shared/core.DoK86JEe.mjs +518 -0
- package/dist/shared/core.Dpq3P3YJ.d.mts +1265 -0
- package/dist/shared/{core.D2830qgg.d.mts → core.Pf5I9o0e.d.mts} +1 -1
- package/dist/shared/core.cbA9VZ02.mjs +2681 -0
- package/dist/shared/{core.CQXU9DF7.mjs → core.rmvsy0n3.mjs} +23 -32
- package/dist/types/aux.d.mts +3 -0
- package/dist/types/aux.mjs +1 -0
- package/dist/types/index.d.mts +7 -45
- package/dist/types/index.mjs +130 -3
- package/dist/utils/index.d.mts +221 -53
- package/dist/utils/index.mjs +14 -10
- package/package.json +15 -7
- package/src/builder/Builder.deploymentModel.ts +82 -18
- package/src/builder/Builder.element.ts +40 -20
- package/src/builder/Builder.model.ts +66 -17
- package/src/builder/Builder.ts +168 -76
- package/src/builder/Builder.view-common.ts +35 -17
- package/src/builder/Builder.view-deployment.ts +25 -25
- package/src/builder/Builder.view-element.ts +13 -12
- package/src/builder/Builder.views.ts +12 -7
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +62 -34
- package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +319 -0
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +45 -24
- package/src/builder/_types.ts +34 -27
- package/src/compute-view/compute-view.ts +31 -34
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +27 -14
- package/src/compute-view/deployment-view/__test__/fixture.ts +15 -13
- package/src/compute-view/deployment-view/_types.ts +10 -10
- package/src/compute-view/deployment-view/clean-connections.ts +5 -7
- package/src/compute-view/deployment-view/compute.ts +16 -13
- package/src/compute-view/deployment-view/memory/memory.ts +5 -6
- package/src/compute-view/deployment-view/predicates/deploymentRefs.ts +4 -5
- package/src/compute-view/deployment-view/predicates/relation-direct.ts +25 -50
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +5 -7
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +7 -11
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +7 -10
- package/src/compute-view/deployment-view/predicates/utils.ts +37 -31
- package/src/compute-view/deployment-view/predicates/wildcard.ts +3 -2
- package/src/compute-view/deployment-view/stages/stage-final.ts +2 -2
- package/src/compute-view/deployment-view/stages/stage-include.ts +1 -1
- package/src/compute-view/deployment-view/utils.ts +79 -72
- package/src/compute-view/dynamic-view/__test__/fixture.ts +20 -11
- package/src/compute-view/dynamic-view/compute.ts +60 -53
- package/src/compute-view/element-view/__test__/TestHelper.ts +53 -29
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +26 -26
- package/src/compute-view/element-view/__test__/fixture.ts +134 -83
- package/src/compute-view/element-view/_types.ts +14 -19
- package/src/compute-view/element-view/clean-connections.ts +12 -8
- package/src/compute-view/element-view/compute.ts +61 -51
- package/src/compute-view/element-view/memory/NodeGroup.ts +8 -9
- package/src/compute-view/element-view/memory/memory.ts +22 -22
- package/src/compute-view/element-view/memory/stage-include.ts +5 -3
- package/src/compute-view/element-view/predicates/_utils.ts +18 -14
- package/src/compute-view/element-view/predicates/element-expand.ts +4 -5
- package/src/compute-view/element-view/predicates/element-kind-tag.ts +3 -4
- package/src/compute-view/element-view/predicates/element-ref.ts +3 -4
- package/src/compute-view/element-view/predicates/relation-direct.ts +16 -12
- package/src/compute-view/element-view/predicates/relation-in-out.ts +7 -8
- package/src/compute-view/element-view/predicates/relation-in.ts +19 -26
- package/src/compute-view/element-view/predicates/relation-out.ts +20 -21
- package/src/compute-view/element-view/predicates/wildcard.ts +3 -3
- package/src/compute-view/element-view/utils.ts +25 -23
- package/src/compute-view/index.ts +1 -1
- package/src/compute-view/memory/AbstractStageExclude.ts +3 -4
- package/src/compute-view/memory/AbstractStageInclude.ts +1 -1
- package/src/compute-view/memory/_types.ts +3 -2
- package/src/compute-view/relationships-view/_types.ts +3 -4
- package/src/compute-view/relationships-view/compute.ts +8 -11
- package/src/compute-view/relationships-view/layout.ts +6 -6
- package/src/compute-view/relationships-view/utils.ts +4 -4
- package/src/compute-view/utils/ancestorsOfNode.ts +7 -7
- package/src/compute-view/utils/applyCustomElementProperties.ts +16 -8
- package/src/compute-view/utils/applyCustomRelationProperties.ts +19 -9
- package/src/compute-view/utils/applyViewRuleStyles.ts +18 -10
- package/src/compute-view/utils/buildComputedNodes.ts +40 -40
- package/src/compute-view/utils/buildElementNotations.ts +14 -14
- package/src/compute-view/utils/elementExpressionToPredicate.ts +14 -15
- package/src/compute-view/utils/link-nodes-with-edges.ts +6 -4
- package/src/compute-view/utils/merge-props-from-relationships.ts +52 -20
- package/src/compute-view/utils/relationExpressionToPredicates.ts +19 -19
- package/src/compute-view/utils/resolve-extended-views.ts +8 -7
- package/src/compute-view/utils/resolve-global-rules.ts +31 -26
- package/src/compute-view/utils/topological-sort.ts +14 -14
- package/src/compute-view/utils/view-hash.ts +2 -2
- package/src/compute-view/utils/with-readable-edges.ts +9 -5
- package/src/index.ts +0 -32
- package/src/model/DeploymentElementModel.ts +171 -144
- package/src/model/DeploymentModel.ts +88 -65
- package/src/model/ElementModel.ts +85 -74
- package/src/model/LikeC4Model.ts +430 -241
- package/src/model/RelationModel.ts +63 -29
- package/src/model/__test__/fixture.ts +50 -36
- package/src/model/connection/Connection.ts +2 -2
- package/src/model/connection/deployment/DeploymentConnectionModel.ts +21 -24
- package/src/model/connection/deployment/find.ts +1 -1
- package/src/model/connection/model/ConnectionModel.ts +21 -20
- package/src/model/connection/model/find.ts +7 -7
- package/src/model/connection/ops.ts +6 -6
- package/src/model/guards.ts +66 -14
- package/src/model/index.ts +20 -7
- package/src/model/types.ts +41 -97
- package/src/model/view/EdgeModel.ts +47 -41
- package/src/model/view/LikeC4ViewModel.ts +130 -80
- package/src/model/view/NodeModel.ts +102 -96
- package/src/theme/element.ts +1 -1
- package/src/theme/index.ts +9 -9
- package/src/theme/relationships.ts +1 -1
- package/src/types/_common.ts +21 -15
- package/src/types/aux.ts +285 -0
- package/src/types/const.ts +34 -0
- package/src/types/expression-model.ts +292 -0
- package/src/types/expression.ts +311 -0
- package/src/types/fqnRef.ts +88 -0
- package/src/types/geometry.ts +131 -0
- package/src/types/global.ts +10 -8
- package/src/types/index.ts +39 -201
- package/src/types/model-data.ts +52 -84
- package/src/types/model-deployment.ts +87 -0
- package/src/types/model-dump.ts +72 -0
- package/src/types/model-logical.ts +111 -0
- package/src/types/model-spec.ts +81 -0
- package/src/types/operators.ts +51 -52
- package/src/types/scalar.ts +114 -0
- package/src/types/styles.ts +123 -0
- package/src/types/view-changes.ts +4 -5
- package/src/types/view-common.ts +157 -0
- package/src/types/view-computed.ts +113 -0
- package/src/types/view-layouted.ts +82 -0
- package/src/types/view-parsed.deployment.ts +40 -0
- package/src/types/view-parsed.dynamic.ts +78 -0
- package/src/types/view-parsed.element.ts +65 -0
- package/src/types/view.ts +122 -542
- package/src/utils/compare-natural.ts +43 -1
- package/src/utils/getOrCreate.ts +0 -34
- package/src/utils/index.ts +7 -12
- package/src/utils/iterable/filter.ts +1 -1
- package/src/utils/iterable/find.ts +3 -1
- package/src/utils/iterable/head.ts +22 -0
- package/src/utils/iterable/index.ts +1 -0
- package/src/utils/iterable/map.ts +1 -1
- package/src/utils/iterable/reduce.ts +1 -1
- package/src/utils/iterable/some.ts +1 -1
- package/src/utils/memoize-prop.ts +30 -0
- package/src/utils/object-hash.ts +1 -1
- package/src/utils/relations.ts +14 -11
- package/src/utils/string-hash.ts +1 -1
- package/dist/shared/core.CQDU11hR.d.mts +0 -753
- package/dist/shared/core.DJvmfnEi.d.mts +0 -1153
- package/dist/shared/core.DgfwjBtu.mjs +0 -495
- package/dist/shared/core.Dx7siloV.d.mts +0 -146
- package/dist/shared/core.SjLhMA7a.d.mts +0 -62
- package/src/builder/__snapshots__/Builder.spec.ts.snap +0 -374
- package/src/compute-view/element-view/predicates.ts +0 -520
- package/src/compute-view/utils/uniqueTags.ts +0 -21
- package/src/types/deployments.ts +0 -170
- package/src/types/element.ts +0 -109
- package/src/types/expression-v2-model.ts +0 -314
- package/src/types/expression-v2.ts +0 -392
- package/src/types/overview-graph.ts +0 -43
- package/src/types/relation.ts +0 -61
- package/src/types/scalars.ts +0 -39
- package/src/types/theme.ts +0 -82
- package/src/types/view-notation.ts +0 -9
- package/src/utils/graphlib.ts +0 -10
- /package/src/{errors/index.ts → utils/invariant.ts} +0 -0
|
@@ -1,45 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type NodeId as C4NodeId,
|
|
14
|
-
isDeploymentView,
|
|
15
|
-
isDynamicView,
|
|
16
|
-
isElementView,
|
|
17
|
-
isScopedElementView,
|
|
18
|
-
} from '../../types/view'
|
|
19
|
-
import { DefaultMap, ifind } from '../../utils'
|
|
1
|
+
import { isTruthy } from 'remeda'
|
|
2
|
+
import type {
|
|
3
|
+
Any,
|
|
4
|
+
AnyView,
|
|
5
|
+
IteratorLike,
|
|
6
|
+
Link,
|
|
7
|
+
scalar,
|
|
8
|
+
ViewWithType,
|
|
9
|
+
} from '../../types'
|
|
10
|
+
import { _stage, _type } from '../../types'
|
|
11
|
+
import type * as aux from '../../types/aux'
|
|
12
|
+
import { DefaultMap, ifind, nonNullable } from '../../utils'
|
|
20
13
|
import type { ElementModel } from '../ElementModel'
|
|
21
14
|
import type { LikeC4Model } from '../LikeC4Model'
|
|
22
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
type $View,
|
|
17
|
+
type EdgeOrId,
|
|
18
|
+
type NodeOrId,
|
|
19
|
+
getId,
|
|
20
|
+
} from '../types'
|
|
23
21
|
import { type EdgesIterator, EdgeModel } from './EdgeModel'
|
|
24
22
|
import { type NodesIterator, NodeModel } from './NodeModel'
|
|
25
23
|
|
|
26
|
-
export type ViewsIterator<
|
|
27
|
-
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
readonly
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
export type ViewsIterator<A extends Any, V extends $View<A> = $View<A>> = IteratorLike<LikeC4ViewModel<A, V>>
|
|
25
|
+
|
|
26
|
+
export type InferViewType<V> = V extends AnyView<any> ? V[_type] : never
|
|
27
|
+
|
|
28
|
+
export class LikeC4ViewModel<A extends Any = Any, V extends $View<A> = $View<A>> {
|
|
29
|
+
/**
|
|
30
|
+
* Don't use in runtime, only for type inference
|
|
31
|
+
*/
|
|
32
|
+
readonly Aux!: A
|
|
33
|
+
|
|
34
|
+
readonly #rootnodes = new Set<NodeModel<A, V>>()
|
|
35
|
+
readonly #nodes = new Map<scalar.NodeId, NodeModel<A, V>>()
|
|
36
|
+
readonly #edges = new Map<scalar.EdgeId, EdgeModel<A, V>>()
|
|
37
|
+
readonly #includeElements = new Set<aux.Fqn<A>>()
|
|
38
|
+
readonly #includeDeployments = new Set<aux.DeploymentFqn<A>>()
|
|
39
|
+
readonly #includeRelations = new Set<scalar.RelationId>()
|
|
40
|
+
readonly #allTags = new DefaultMap((_key: aux.Tag<A>) => new Set<NodeModel<A, V> | EdgeModel<A, V>>())
|
|
41
|
+
|
|
42
|
+
public readonly $view: V
|
|
43
|
+
public readonly $model: LikeC4Model<A>
|
|
44
|
+
|
|
45
|
+
constructor(model: LikeC4Model<A>, view: V) {
|
|
46
|
+
this.$model = model
|
|
47
|
+
this.$view = view
|
|
48
|
+
for (const node of view.nodes) {
|
|
49
|
+
const el = new NodeModel<A, V>(this, Object.freeze(node))
|
|
43
50
|
this.#nodes.set(node.id, el)
|
|
44
51
|
if (!node.parent) {
|
|
45
52
|
this.#rootnodes.add(el)
|
|
@@ -55,7 +62,7 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
for (const edge of
|
|
65
|
+
for (const edge of view.edges) {
|
|
59
66
|
const edgeModel = new EdgeModel(
|
|
60
67
|
this,
|
|
61
68
|
Object.freeze(edge),
|
|
@@ -72,11 +79,11 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
|
|
75
|
-
get
|
|
76
|
-
return this.$view
|
|
82
|
+
get _type(): V[_type] {
|
|
83
|
+
return this.$view[_type]
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
get id():
|
|
86
|
+
get id(): aux.StrictViewId<A> {
|
|
80
87
|
return this.$view.id
|
|
81
88
|
}
|
|
82
89
|
|
|
@@ -84,7 +91,7 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
84
91
|
return this.$view.title
|
|
85
92
|
}
|
|
86
93
|
|
|
87
|
-
get tags():
|
|
94
|
+
get tags(): aux.Tags<A> {
|
|
88
95
|
return this.$view.tags ?? []
|
|
89
96
|
}
|
|
90
97
|
|
|
@@ -92,10 +99,10 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
92
99
|
return this.$view.links ?? []
|
|
93
100
|
}
|
|
94
101
|
|
|
95
|
-
get viewOf(): ElementModel<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return this.$model.element(
|
|
102
|
+
get viewOf(): ElementModel<A> | null {
|
|
103
|
+
if (this.isElementView()) {
|
|
104
|
+
const viewOf = this.$view.viewOf
|
|
105
|
+
return viewOf ? this.$model.element(viewOf) : null
|
|
99
106
|
}
|
|
100
107
|
return null
|
|
101
108
|
}
|
|
@@ -103,18 +110,18 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
103
110
|
/**
|
|
104
111
|
* All tags from nodes and edges.
|
|
105
112
|
*/
|
|
106
|
-
get includedTags():
|
|
107
|
-
return [...this.#allTags.keys()]
|
|
113
|
+
get includedTags(): aux.Tags<A> {
|
|
114
|
+
return [...this.#allTags.keys()] as unknown as aux.Tags<A>
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
public roots(): NodesIterator<
|
|
117
|
+
public roots(): NodesIterator<A, V> {
|
|
111
118
|
return this.#rootnodes.values()
|
|
112
119
|
}
|
|
113
120
|
|
|
114
121
|
/**
|
|
115
122
|
* Iterate over all nodes that have children.
|
|
116
123
|
*/
|
|
117
|
-
public *compounds(): NodesIterator<
|
|
124
|
+
public *compounds(): NodesIterator<A, V> {
|
|
118
125
|
for (const node of this.#nodes.values()) {
|
|
119
126
|
if (node.hasChildren()) {
|
|
120
127
|
yield node
|
|
@@ -127,7 +134,7 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
127
134
|
* Get node by id.
|
|
128
135
|
* @throws Error if node is not found.
|
|
129
136
|
*/
|
|
130
|
-
public node(node:
|
|
137
|
+
public node(node: NodeOrId): NodeModel<A, V> {
|
|
131
138
|
const nodeId = getId(node)
|
|
132
139
|
return nonNullable(this.#nodes.get(nodeId), `Node ${nodeId} not found in view ${this.$view.id}`)
|
|
133
140
|
}
|
|
@@ -135,19 +142,22 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
135
142
|
/**
|
|
136
143
|
* Find node by id.
|
|
137
144
|
*/
|
|
138
|
-
public findNode(node:
|
|
139
|
-
return this.#nodes.get(getId(node)
|
|
145
|
+
public findNode(node: NodeOrId): NodeModel<A, V> | null {
|
|
146
|
+
return this.#nodes.get(getId(node)) ?? null
|
|
140
147
|
}
|
|
141
148
|
|
|
142
|
-
public findNodeWithElement(
|
|
143
|
-
const
|
|
144
|
-
return
|
|
149
|
+
public findNodeWithElement(element: aux.LooseElementId<A> | { id: aux.Fqn<A> }): NodeModel.WithElement<A, V> | null {
|
|
150
|
+
const id = getId(element)
|
|
151
|
+
return ifind(
|
|
152
|
+
this.#nodes.values(),
|
|
153
|
+
(node): node is NodeModel.WithElement<A, V> => node.hasElement() && node.element.id === id,
|
|
154
|
+
) ?? null
|
|
145
155
|
}
|
|
146
156
|
|
|
147
157
|
/**
|
|
148
158
|
* Iterate over all nodes.
|
|
149
159
|
*/
|
|
150
|
-
public nodes(): NodesIterator<
|
|
160
|
+
public nodes(): NodesIterator<A, V> {
|
|
151
161
|
return this.#nodes.values()
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -156,24 +166,24 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
156
166
|
* @param edge Edge or id
|
|
157
167
|
* @returns EdgeModel
|
|
158
168
|
*/
|
|
159
|
-
public edge(edge:
|
|
160
|
-
const edgeId = getId(edge)
|
|
169
|
+
public edge(edge: EdgeOrId): EdgeModel<A, V> {
|
|
170
|
+
const edgeId = getId(edge)
|
|
161
171
|
return nonNullable(this.#edges.get(edgeId), `Edge ${edgeId} not found in view ${this.$view.id}`)
|
|
162
172
|
}
|
|
163
|
-
public findEdge(edge:
|
|
164
|
-
return this.#edges.get(getId(edge)
|
|
173
|
+
public findEdge(edge: EdgeOrId): EdgeModel<A, V> | null {
|
|
174
|
+
return this.#edges.get(getId(edge)) ?? null
|
|
165
175
|
}
|
|
166
176
|
/**
|
|
167
177
|
* Iterate over all edges.
|
|
168
178
|
*/
|
|
169
|
-
public edges(): EdgesIterator<
|
|
179
|
+
public edges(): EdgesIterator<A, V> {
|
|
170
180
|
return this.#edges.values()
|
|
171
181
|
}
|
|
172
182
|
|
|
173
183
|
/**
|
|
174
184
|
* Iterate over all edges.
|
|
175
185
|
*/
|
|
176
|
-
public *edgesWithRelation(relation:
|
|
186
|
+
public *edgesWithRelation(relation: aux.RelationId): EdgesIterator<A, V> {
|
|
177
187
|
for (const edge of this.#edges.values()) {
|
|
178
188
|
if (edge.includesRelation(relation)) {
|
|
179
189
|
yield edge
|
|
@@ -185,7 +195,7 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
185
195
|
/**
|
|
186
196
|
* Nodes that have references to elements from logical model.
|
|
187
197
|
*/
|
|
188
|
-
public *elements(): IteratorLike<NodeModel.WithElement<
|
|
198
|
+
public *elements(): IteratorLike<NodeModel.WithElement<A, V>> {
|
|
189
199
|
// return this.#nodes.values().filter(node => node.hasElement())
|
|
190
200
|
for (const node of this.#nodes.values()) {
|
|
191
201
|
if (node.hasElement()) {
|
|
@@ -195,38 +205,78 @@ export class LikeC4ViewModel<M extends AnyAux, V extends ComputedView | DiagramV
|
|
|
195
205
|
return
|
|
196
206
|
}
|
|
197
207
|
|
|
198
|
-
|
|
199
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Checks if the view has the given tag.
|
|
210
|
+
*/
|
|
211
|
+
public isTagged(tag: aux.LooseTag<A>): boolean {
|
|
212
|
+
return this.tags.includes(tag as aux.Tag<A>)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public includesElement(element: aux.LooseElementId<A> | { id: aux.Fqn<A> }): boolean {
|
|
216
|
+
return this.#includeElements.has(getId(element))
|
|
200
217
|
}
|
|
201
218
|
|
|
202
|
-
public includesDeployment(
|
|
203
|
-
return this.#includeDeployments.has(
|
|
219
|
+
public includesDeployment(deployment: aux.LooseDeploymentId<A> | { id: aux.DeploymentFqn<A> }): boolean {
|
|
220
|
+
return this.#includeDeployments.has(getId(deployment))
|
|
204
221
|
}
|
|
205
222
|
|
|
206
|
-
public includesRelation(
|
|
207
|
-
return this.#includeRelations.has(
|
|
223
|
+
public includesRelation(relation: scalar.RelationId | { id: scalar.RelationId }): boolean {
|
|
224
|
+
return this.#includeRelations.has(getId(relation))
|
|
208
225
|
}
|
|
209
226
|
|
|
210
227
|
/**
|
|
211
228
|
* Below are type guards.
|
|
212
229
|
*/
|
|
213
|
-
public isComputed(
|
|
214
|
-
|
|
230
|
+
public isComputed(
|
|
231
|
+
this: LikeC4ViewModel<any, any>,
|
|
232
|
+
): this is LikeC4ViewModel<aux.toComputed<A>> {
|
|
233
|
+
return this.$view[_stage] === 'computed'
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public isDiagram(
|
|
237
|
+
this: LikeC4ViewModel<any, any>,
|
|
238
|
+
): this is LikeC4ViewModel<aux.toLayouted<A>> {
|
|
239
|
+
return this.$view[_stage] === 'layouted'
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public isElementView(this: LikeC4ViewModel<any, any>): this is LikeC4ViewModel.ElementView<A, V> {
|
|
243
|
+
return this.$view[_type] === 'element'
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
public isScopedElementView(
|
|
247
|
+
this: LikeC4ViewModel<any, any>,
|
|
248
|
+
): this is LikeC4ViewModel.ScopedElementView<A, V> {
|
|
249
|
+
return this.$view[_type] === 'element' && isTruthy(this.$view.viewOf)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public isDeploymentView(this: LikeC4ViewModel<any, any>): this is LikeC4ViewModel.DeploymentView<A, V> {
|
|
253
|
+
return this.$view[_type] === 'deployment'
|
|
215
254
|
}
|
|
216
255
|
|
|
217
|
-
public
|
|
218
|
-
return
|
|
256
|
+
public isDynamicView(this: LikeC4ViewModel<any, any>): this is LikeC4ViewModel.DynamicView<A, V> {
|
|
257
|
+
return this.$view[_type] === 'dynamic'
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export namespace LikeC4ViewModel {
|
|
262
|
+
export interface ElementView<A extends Any, V extends $View<A> = $View<A>>
|
|
263
|
+
extends LikeC4ViewModel<A, ViewWithType<V, 'element'>>
|
|
264
|
+
{
|
|
219
265
|
}
|
|
220
266
|
|
|
221
|
-
|
|
222
|
-
|
|
267
|
+
export interface ScopedElementView<A extends Any, V extends $View<A> = $View<A>>
|
|
268
|
+
extends LikeC4ViewModel<A, ViewWithType<V, 'element'> & { viewOf: aux.StrictFqn<A> }>
|
|
269
|
+
{
|
|
270
|
+
viewOf: ElementModel<A>
|
|
223
271
|
}
|
|
224
272
|
|
|
225
|
-
|
|
226
|
-
|
|
273
|
+
export interface DeploymentView<A extends Any, V extends $View<A> = $View<A>>
|
|
274
|
+
extends LikeC4ViewModel<A, ViewWithType<V, 'deployment'>>
|
|
275
|
+
{
|
|
227
276
|
}
|
|
228
277
|
|
|
229
|
-
|
|
230
|
-
|
|
278
|
+
export interface DynamicView<A extends Any, V extends $View<A> = $View<A>>
|
|
279
|
+
extends LikeC4ViewModel<A, ViewWithType<V, 'dynamic'>>
|
|
280
|
+
{
|
|
231
281
|
}
|
|
232
282
|
}
|
|
@@ -1,129 +1,110 @@
|
|
|
1
|
+
import { isTruthy } from 'remeda'
|
|
1
2
|
import {
|
|
2
|
-
type
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type
|
|
3
|
+
type Any,
|
|
4
|
+
type Color,
|
|
5
|
+
type ComputedNode,
|
|
6
|
+
type DiagramNode,
|
|
6
7
|
type ElementShape as C4ElementShape,
|
|
7
8
|
type ElementStyle,
|
|
9
|
+
type ExtractOnStage,
|
|
8
10
|
type IconUrl,
|
|
9
11
|
type IteratorLike,
|
|
10
12
|
type Link,
|
|
11
|
-
type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
ElementKind,
|
|
13
|
+
type scalar,
|
|
14
|
+
GroupElementKind,
|
|
15
|
+
isGroupElementKind,
|
|
15
16
|
} from '../../types'
|
|
17
|
+
import type * as aux from '../../types/aux'
|
|
18
|
+
import { memoizeProp } from '../../utils'
|
|
16
19
|
import type { DeployedInstanceModel, DeploymentElementModel } from '../DeploymentElementModel'
|
|
17
20
|
import type { ElementModel } from '../ElementModel'
|
|
18
|
-
import type {
|
|
21
|
+
import type { $View, IncomingFilter, OutgoingFilter } from '../types'
|
|
19
22
|
import type { EdgesIterator } from './EdgeModel'
|
|
20
23
|
import type { LikeC4ViewModel } from './LikeC4ViewModel'
|
|
21
24
|
|
|
22
|
-
export type NodesIterator<M extends
|
|
25
|
+
export type NodesIterator<M extends Any, V extends $View<M>> = IteratorLike<NodeModel<M, V>>
|
|
23
26
|
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
parent: NodeModel<M, V>
|
|
27
|
-
}
|
|
28
|
-
export interface WithElement<M extends AnyAux, V extends ComputedView | DiagramView> extends NodeModel<M, V> {
|
|
29
|
-
kind: ElementKind
|
|
30
|
-
element: ElementModel<M>
|
|
31
|
-
}
|
|
32
|
-
export interface WithDeploymentElement<M extends AnyAux, V extends ComputedView | DiagramView>
|
|
33
|
-
extends NodeModel<M, V>
|
|
34
|
-
{
|
|
35
|
-
kind: DeploymentNodeKind
|
|
36
|
-
deployment: DeploymentElementModel<M>
|
|
37
|
-
}
|
|
38
|
-
export interface WithDeployedInstance<M extends AnyAux, V extends ComputedView | DiagramView>
|
|
39
|
-
extends NodeModel<M, V>
|
|
40
|
-
{
|
|
41
|
-
kind: 'instance'
|
|
42
|
-
element: ElementModel<M>
|
|
43
|
-
deployment: DeployedInstanceModel<M>
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface IsGroup<M extends AnyAux, V extends ComputedView | DiagramView> extends NodeModel<M, V> {
|
|
47
|
-
kind: typeof ElementKind.Group
|
|
48
|
-
element: null
|
|
49
|
-
deployment: null
|
|
50
|
-
}
|
|
51
|
-
}
|
|
27
|
+
export class NodeModel<A extends Any = Any, V extends $View<A> = $View<A>> {
|
|
28
|
+
#node: ComputedNode<A> | DiagramNode<A>
|
|
52
29
|
|
|
53
|
-
export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView = M['ViewType']> {
|
|
54
30
|
constructor(
|
|
55
|
-
public readonly $view: LikeC4ViewModel<
|
|
31
|
+
public readonly $view: LikeC4ViewModel<A, V>,
|
|
56
32
|
public readonly $node: V['nodes'][number],
|
|
57
33
|
) {
|
|
34
|
+
this.#node = $node
|
|
58
35
|
}
|
|
59
36
|
|
|
60
|
-
get id(): NodeId {
|
|
61
|
-
return this
|
|
37
|
+
get id(): scalar.NodeId {
|
|
38
|
+
return this.#node.id
|
|
62
39
|
}
|
|
63
40
|
|
|
64
41
|
get title(): string {
|
|
65
|
-
return this
|
|
42
|
+
return this.#node.title
|
|
66
43
|
}
|
|
67
44
|
|
|
68
|
-
get kind(): ElementKind |
|
|
69
|
-
return this
|
|
45
|
+
get kind(): aux.ElementKind<A> | aux.DeploymentKind<A> | typeof GroupElementKind | 'instance' {
|
|
46
|
+
return this.#node.kind as any
|
|
70
47
|
}
|
|
71
48
|
|
|
72
49
|
get description(): string | null {
|
|
73
|
-
return this
|
|
50
|
+
return this.#node.description ?? null
|
|
74
51
|
}
|
|
75
52
|
|
|
76
53
|
get technology(): string | null {
|
|
77
|
-
return this
|
|
54
|
+
return this.#node.technology ?? null
|
|
78
55
|
}
|
|
79
56
|
|
|
80
|
-
get parent(): NodeModel<
|
|
81
|
-
return this
|
|
57
|
+
get parent(): NodeModel<A, V> | null {
|
|
58
|
+
return this.#node.parent ? this.$view.node(this.#node.parent) : null
|
|
82
59
|
}
|
|
83
60
|
|
|
84
|
-
get element(): ElementModel<
|
|
85
|
-
const modelRef =
|
|
61
|
+
get element(): ElementModel<A> | null {
|
|
62
|
+
const modelRef = this.#node.modelRef
|
|
86
63
|
return modelRef ? this.$view.$model.element(modelRef) : null
|
|
87
64
|
}
|
|
88
65
|
|
|
89
|
-
get deployment(): DeploymentElementModel<
|
|
90
|
-
const modelRef =
|
|
66
|
+
get deployment(): DeploymentElementModel<A> | null {
|
|
67
|
+
const modelRef = this.#node.deploymentRef
|
|
91
68
|
return modelRef ? this.$view.$model.deployment.element(modelRef) : null
|
|
92
69
|
}
|
|
93
70
|
|
|
94
71
|
get shape(): C4ElementShape {
|
|
95
|
-
return this
|
|
72
|
+
return this.#node.shape
|
|
96
73
|
}
|
|
97
74
|
|
|
98
|
-
get color():
|
|
99
|
-
return this
|
|
75
|
+
get color(): Color {
|
|
76
|
+
return this.#node.color
|
|
100
77
|
}
|
|
101
78
|
|
|
102
79
|
get icon(): IconUrl | null {
|
|
103
|
-
return this
|
|
80
|
+
return this.#node.icon ?? null
|
|
104
81
|
}
|
|
105
82
|
|
|
106
|
-
get tags():
|
|
107
|
-
return this
|
|
83
|
+
get tags(): aux.Tags<A> {
|
|
84
|
+
return this.#node.tags
|
|
108
85
|
}
|
|
109
86
|
|
|
110
87
|
get links(): ReadonlyArray<Link> {
|
|
111
|
-
return this
|
|
88
|
+
return this.#node.links ?? []
|
|
112
89
|
}
|
|
113
90
|
|
|
114
|
-
get navigateTo(): LikeC4ViewModel<
|
|
115
|
-
return this
|
|
91
|
+
get navigateTo(): LikeC4ViewModel<A> | null {
|
|
92
|
+
return this.#node.navigateTo ? this.$view.$model.view(this.#node.navigateTo) : null
|
|
116
93
|
}
|
|
117
94
|
|
|
118
95
|
get style(): ElementStyle {
|
|
119
|
-
return this
|
|
96
|
+
return this.#node.style
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public children(): ReadonlySet<NodeModel<A, V>> {
|
|
100
|
+
return memoizeProp(this, 'children', () => new Set(this.#node.children.map((child) => this.$view.node(child))))
|
|
120
101
|
}
|
|
121
102
|
|
|
122
103
|
/**
|
|
123
104
|
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
124
105
|
* (from closest to root)
|
|
125
106
|
*/
|
|
126
|
-
public *ancestors(): NodesIterator<
|
|
107
|
+
public *ancestors(): NodesIterator<A, V> {
|
|
127
108
|
let parent = this.parent
|
|
128
109
|
while (parent) {
|
|
129
110
|
yield parent
|
|
@@ -132,25 +113,18 @@ export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView =
|
|
|
132
113
|
return
|
|
133
114
|
}
|
|
134
115
|
|
|
135
|
-
public *
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
public *sublings(): NodesIterator<M, V> {
|
|
143
|
-
const sublings = this.parent?.children() ?? this.$view.roots()
|
|
144
|
-
for (const subling of sublings) {
|
|
145
|
-
if (subling.id !== this.id) {
|
|
146
|
-
yield subling
|
|
116
|
+
public *siblings(): NodesIterator<A, V> {
|
|
117
|
+
const siblings = this.parent?.children() ?? this.$view.roots()
|
|
118
|
+
for (const sibling of siblings) {
|
|
119
|
+
if (sibling.id !== this.id) {
|
|
120
|
+
yield sibling
|
|
147
121
|
}
|
|
148
122
|
}
|
|
149
123
|
return
|
|
150
124
|
}
|
|
151
125
|
|
|
152
|
-
public *incoming(filter: IncomingFilter = 'all'): EdgesIterator<
|
|
153
|
-
for (const edgeId of this
|
|
126
|
+
public *incoming(filter: IncomingFilter = 'all'): EdgesIterator<A, V> {
|
|
127
|
+
for (const edgeId of this.#node.inEdges) {
|
|
154
128
|
const edge = this.$view.edge(edgeId)
|
|
155
129
|
switch (true) {
|
|
156
130
|
case filter === 'all':
|
|
@@ -163,8 +137,8 @@ export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView =
|
|
|
163
137
|
return
|
|
164
138
|
}
|
|
165
139
|
|
|
166
|
-
public *incomers(filter: IncomingFilter = 'all'): NodesIterator<
|
|
167
|
-
const unique = new Set<NodeId>()
|
|
140
|
+
public *incomers(filter: IncomingFilter = 'all'): NodesIterator<A, V> {
|
|
141
|
+
const unique = new Set<aux.NodeId>()
|
|
168
142
|
for (const r of this.incoming(filter)) {
|
|
169
143
|
if (unique.has(r.source.id)) {
|
|
170
144
|
continue
|
|
@@ -175,8 +149,8 @@ export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView =
|
|
|
175
149
|
return
|
|
176
150
|
}
|
|
177
151
|
|
|
178
|
-
public *outgoing(filter: OutgoingFilter = 'all'): EdgesIterator<
|
|
179
|
-
for (const edgeId of this
|
|
152
|
+
public *outgoing(filter: OutgoingFilter = 'all'): EdgesIterator<A, V> {
|
|
153
|
+
for (const edgeId of this.#node.outEdges) {
|
|
180
154
|
const edge = this.$view.edge(edgeId)
|
|
181
155
|
switch (true) {
|
|
182
156
|
case filter === 'all':
|
|
@@ -189,8 +163,8 @@ export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView =
|
|
|
189
163
|
return
|
|
190
164
|
}
|
|
191
165
|
|
|
192
|
-
public *outgoers(filter: OutgoingFilter = 'all'): NodesIterator<
|
|
193
|
-
const unique = new Set<NodeId>()
|
|
166
|
+
public *outgoers(filter: OutgoingFilter = 'all'): NodesIterator<A, V> {
|
|
167
|
+
const unique = new Set<aux.NodeId>()
|
|
194
168
|
for (const r of this.outgoing(filter)) {
|
|
195
169
|
if (unique.has(r.target.id)) {
|
|
196
170
|
continue
|
|
@@ -201,39 +175,71 @@ export class NodeModel<M extends AnyAux, V extends ComputedView | DiagramView =
|
|
|
201
175
|
return
|
|
202
176
|
}
|
|
203
177
|
|
|
204
|
-
public isDiagramNode(): this is NodeModel<
|
|
205
|
-
return 'width' in this
|
|
178
|
+
public isDiagramNode(this: NodeModel<any, any>): this is NodeModel<A, ExtractOnStage<V, 'layouted'>> {
|
|
179
|
+
return 'width' in this.#node && 'height' in this.#node
|
|
206
180
|
}
|
|
207
181
|
|
|
208
182
|
public hasChildren(): boolean {
|
|
209
|
-
return this
|
|
183
|
+
return this.#node.children.length > 0
|
|
210
184
|
}
|
|
211
185
|
|
|
212
|
-
public hasParent(): this is NodeModel.WithParent<
|
|
213
|
-
return this
|
|
186
|
+
public hasParent(): this is NodeModel.WithParent<A, V> {
|
|
187
|
+
return this.#node.parent !== null
|
|
214
188
|
}
|
|
215
189
|
|
|
216
190
|
/**
|
|
217
191
|
* Check if this node references to logical model element.
|
|
218
192
|
*/
|
|
219
|
-
public hasElement(): this is NodeModel.WithElement<
|
|
220
|
-
return
|
|
193
|
+
public hasElement(): this is NodeModel.WithElement<A, V> {
|
|
194
|
+
return isTruthy(this.#node.modelRef)
|
|
221
195
|
}
|
|
222
196
|
/**
|
|
223
197
|
* Check if this node references to deployment element (Node or Instance).
|
|
224
198
|
*/
|
|
225
|
-
public hasDeployment(): this is NodeModel.WithDeploymentElement<
|
|
226
|
-
return
|
|
199
|
+
public hasDeployment(): this is NodeModel.WithDeploymentElement<A, V> {
|
|
200
|
+
return isTruthy(this.#node.deploymentRef)
|
|
227
201
|
}
|
|
228
202
|
/**
|
|
229
203
|
* Check if this node references to deployed instance
|
|
230
204
|
* Deployed instance always references to element and deployment element.
|
|
231
205
|
*/
|
|
232
|
-
public hasDeployedInstance(): this is NodeModel.WithDeployedInstance<
|
|
206
|
+
public hasDeployedInstance(): this is NodeModel.WithDeployedInstance<A, V> {
|
|
233
207
|
return this.hasElement() && this.hasDeployment()
|
|
234
208
|
}
|
|
235
209
|
|
|
236
|
-
public isGroup(): this is NodeModel.IsGroup<
|
|
237
|
-
return
|
|
210
|
+
public isGroup(): this is NodeModel.IsGroup<A, V> {
|
|
211
|
+
return isGroupElementKind(this.#node)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Checks if the node has the given tag.
|
|
216
|
+
*/
|
|
217
|
+
public isTagged(tag: aux.LooseTag<A>): boolean {
|
|
218
|
+
return this.tags.includes(tag as aux.Tag<A>)
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export namespace NodeModel {
|
|
223
|
+
export interface WithParent<A extends Any = Any, V extends $View<A> = $View<A>> extends NodeModel<A, V> {
|
|
224
|
+
parent: NodeModel<A, V>
|
|
225
|
+
}
|
|
226
|
+
export interface WithElement<A extends Any = Any, V extends $View<A> = $View<A>> extends NodeModel<A, V> {
|
|
227
|
+
kind: aux.ElementKind<A>
|
|
228
|
+
element: ElementModel<A>
|
|
229
|
+
}
|
|
230
|
+
export interface WithDeploymentElement<A extends Any = Any, V extends $View<A> = $View<A>> extends NodeModel<A, V> {
|
|
231
|
+
kind: aux.DeploymentKind<A>
|
|
232
|
+
deployment: DeploymentElementModel<A>
|
|
233
|
+
}
|
|
234
|
+
export interface WithDeployedInstance<A extends Any = Any, V extends $View<A> = $View<A>> extends NodeModel<A, V> {
|
|
235
|
+
kind: 'instance'
|
|
236
|
+
element: ElementModel<A>
|
|
237
|
+
deployment: DeployedInstanceModel<A>
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface IsGroup<A extends Any = Any, V extends $View<A> = $View<A>> extends NodeModel<A, V> {
|
|
241
|
+
kind: typeof GroupElementKind
|
|
242
|
+
element: null
|
|
243
|
+
deployment: null
|
|
238
244
|
}
|
|
239
245
|
}
|
package/src/theme/element.ts
CHANGED