@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
package/src/model/LikeC4Model.ts
CHANGED
|
@@ -1,305 +1,397 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import DefaultMap from 'mnemonist/default-map'
|
|
2
|
+
import { mapValues, pipe, sort, values } from 'remeda'
|
|
3
|
+
import type { LiteralUnion } from 'type-fest'
|
|
4
|
+
import { computeView, unsafeComputeView } from '../compute-view'
|
|
5
|
+
import type { ComputeViewResult } from '../compute-view/compute-view'
|
|
6
|
+
import { invariant, nonNullable } from '../errors'
|
|
7
|
+
import type { ComputedView, DiagramView, IteratorLike, LikeC4View, ModelGlobals } from '../types'
|
|
8
|
+
import type { Element } from '../types/element'
|
|
9
|
+
import { type Tag as C4Tag } from '../types/element'
|
|
10
|
+
import type { AnyParsedLikeC4Model, GenericLikeC4Model, LikeC4ModelDump } from '../types/model'
|
|
11
|
+
import type { ModelRelation } from '../types/relation'
|
|
12
|
+
import { compareNatural } from '../utils'
|
|
13
|
+
import { ancestorsFqn, commonAncestor, parentFqn } from '../utils/fqn'
|
|
4
14
|
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from '
|
|
10
|
-
import {
|
|
11
|
-
import type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from '
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
type PickBySource<Source> = Source extends LikeC4Model.Layouted.SourceModel ? LikeC4Model.Layouted
|
|
25
|
-
: Source extends LikeC4Model.Computed.SourceModel ? LikeC4Model.Computed
|
|
26
|
-
: never
|
|
27
|
-
|
|
28
|
-
export class LikeC4Model<M extends LikeC4Model.ViewModel = LikeC4Model.ViewModel> {
|
|
29
|
-
private _elements = new Map<Fqn, LikeC4Model.ElementModel<M>>()
|
|
15
|
+
DeployedInstanceModel,
|
|
16
|
+
DeploymentElementModel,
|
|
17
|
+
DeploymentNodeModel,
|
|
18
|
+
DeploymentRelationModel,
|
|
19
|
+
} from './DeploymentElementModel'
|
|
20
|
+
import { LikeC4DeploymentModel } from './DeploymentModel'
|
|
21
|
+
import { type ElementsIterator, ElementModel } from './ElementModel'
|
|
22
|
+
import { type RelationshipsIterator, RelationshipModel } from './RelationModel'
|
|
23
|
+
import { type AnyAux, type Aux, type IncomingFilter, type OutgoingFilter, getId } from './types'
|
|
24
|
+
import { EdgeModel } from './view/EdgeModel'
|
|
25
|
+
import { LikeC4ViewModel } from './view/LikeC4ViewModel'
|
|
26
|
+
import { NodeModel } from './view/NodeModel'
|
|
27
|
+
|
|
28
|
+
export class LikeC4Model<M extends AnyAux = LikeC4Model.Any> {
|
|
29
|
+
/**
|
|
30
|
+
* Only available in compile tim
|
|
31
|
+
*/
|
|
32
|
+
readonly Aux!: M
|
|
30
33
|
|
|
34
|
+
readonly #elements = new Map<M['Element'], ElementModel<M>>()
|
|
31
35
|
// Parent element for given FQN
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
readonly #parents = new Map<M['Element'], ElementModel<M>>()
|
|
34
37
|
// Children elements for given FQN
|
|
35
|
-
|
|
38
|
+
readonly #children = new DefaultMap<M['Element'], Set<ElementModel<M>>>(() => new Set())
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
readonly #rootElements = new Set<ElementModel<M>>()
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
readonly #relations = new Map<M['RelationId'], RelationshipModel<M>>()
|
|
40
43
|
|
|
41
44
|
// Incoming to an element or its descendants
|
|
42
|
-
|
|
45
|
+
readonly #incoming = new DefaultMap<M['Element'], Set<RelationshipModel<M>>>(() => new Set())
|
|
43
46
|
|
|
44
47
|
// Outgoing from an element or its descendants
|
|
45
|
-
|
|
48
|
+
readonly #outgoing = new DefaultMap<M['Element'], Set<RelationshipModel<M>>>(() => new Set())
|
|
46
49
|
|
|
47
50
|
// Relationships inside the element, among descendants
|
|
48
|
-
|
|
51
|
+
readonly #internal = new DefaultMap<M['Element'], Set<RelationshipModel<M>>>(() => new Set())
|
|
52
|
+
|
|
53
|
+
readonly #views = new Map<M['ViewId'], LikeC4ViewModel<M>>()
|
|
54
|
+
|
|
55
|
+
readonly #allTags = new DefaultMap<C4Tag, Set<ElementModel<M> | RelationshipModel<M> | LikeC4ViewModel<M>>>(() =>
|
|
56
|
+
new Set()
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
public readonly deployment: LikeC4DeploymentModel<M>
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Computes views from the parsed model
|
|
63
|
+
* Creates a new LikeC4Model instance from a parsed model.
|
|
64
|
+
*
|
|
65
|
+
* May throw an error if the model is invalid.
|
|
66
|
+
*
|
|
67
|
+
* @typeParam M - The type of the parsed LikeC4 model, must extend ParsedLikeC4Model
|
|
68
|
+
* @param parsed - The parsed LikeC4 model to compute from
|
|
69
|
+
* @returns A new LikeC4Model instance with computed relationships and structure
|
|
70
|
+
*/
|
|
71
|
+
static compute<const M extends AnyParsedLikeC4Model>(parsed: M): LikeC4Model<Aux.FromParsed<M>> {
|
|
72
|
+
let { views, ...rest } = parsed as Omit<M, '__'>
|
|
73
|
+
const model = new LikeC4Model({ ...rest, views: {} })
|
|
74
|
+
return new LikeC4Model({
|
|
75
|
+
...rest,
|
|
76
|
+
views: mapValues(views, view => unsafeComputeView(view as LikeC4View, model)),
|
|
77
|
+
} as any)
|
|
78
|
+
}
|
|
49
79
|
|
|
50
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Creates a function that computes a view using the data from the model.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* const compute = LikeC4Model.makeCompute(parsedModel);
|
|
85
|
+
* const result = compute(viewSource);
|
|
86
|
+
*/
|
|
87
|
+
static makeCompute<M extends AnyParsedLikeC4Model>(parsed: M): (viewsource: LikeC4View) => ComputeViewResult {
|
|
88
|
+
let { views, ...rest } = parsed as Omit<M, '__'>
|
|
89
|
+
const model = new LikeC4Model(structuredClone({ ...rest, views: {} }))
|
|
90
|
+
return (viewsource) => computeView(viewsource, model)
|
|
91
|
+
}
|
|
51
92
|
|
|
52
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Creates a new LikeC4Model instance from the provided model data.
|
|
95
|
+
*
|
|
96
|
+
* @typeParam M - Type parameter constrained to AnyLikeC4Model
|
|
97
|
+
* @param model - The model data to create a LikeC4Model from
|
|
98
|
+
* @returns A new LikeC4Model instance with the type derived from the input model
|
|
99
|
+
*/
|
|
100
|
+
static create<const M extends GenericLikeC4Model>(model: M): LikeC4Model<Aux.FromModel<M>> {
|
|
101
|
+
return new LikeC4Model(model as any)
|
|
102
|
+
}
|
|
53
103
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Creates a new LikeC4Model instance from a model dump.
|
|
106
|
+
*
|
|
107
|
+
* @typeParam M - A constant type parameter extending LikeC4ModelDump
|
|
108
|
+
* @param dump - The model dump to create the instance from
|
|
109
|
+
* @returns A new LikeC4Model instance with types inferred from the dump
|
|
110
|
+
*/
|
|
111
|
+
static fromDump<const M extends LikeC4ModelDump>(dump: M): LikeC4Model<Aux.FromDump<M>> {
|
|
112
|
+
return new LikeC4Model(dump as any)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private constructor(
|
|
116
|
+
public readonly $model: M['Model'],
|
|
61
117
|
) {
|
|
62
|
-
for (const
|
|
63
|
-
this.addElement(
|
|
118
|
+
for (const element of values($model.elements)) {
|
|
119
|
+
const el = this.addElement(element)
|
|
120
|
+
for (const tag of el.tags) {
|
|
121
|
+
this.#allTags.get(tag).add(el)
|
|
122
|
+
}
|
|
64
123
|
}
|
|
65
|
-
for (const
|
|
66
|
-
this.addRelation(
|
|
124
|
+
for (const relation of values($model.relations)) {
|
|
125
|
+
const el = this.addRelation(relation)
|
|
126
|
+
for (const tag of el.tags) {
|
|
127
|
+
this.#allTags.get(tag).add(el)
|
|
128
|
+
}
|
|
67
129
|
}
|
|
68
|
-
this.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
map(view => [view.id, new ViewModelClass(view, this)] as [Fqn, M])
|
|
73
|
-
)
|
|
130
|
+
this.deployment = new LikeC4DeploymentModel(this, $model.deployments)
|
|
131
|
+
const views = pipe(
|
|
132
|
+
values($model.views),
|
|
133
|
+
sort((a, b) => compareNatural(a.title ?? 'untitled', b.title ?? 'untitled')),
|
|
74
134
|
)
|
|
135
|
+
for (const view of views) {
|
|
136
|
+
const vm = new LikeC4ViewModel(this, Object.freeze(view as M['ViewType']))
|
|
137
|
+
this.#views.set(view.id, vm)
|
|
138
|
+
for (const tag of vm.tags) {
|
|
139
|
+
this.#allTags.get(tag).add(vm)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
75
142
|
}
|
|
76
143
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
144
|
+
get type(): 'computed' | 'layouted' {
|
|
145
|
+
return this.$model.__ ?? 'computed'
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public element(el: M['ElementOrFqn']): ElementModel<M> {
|
|
149
|
+
if (el instanceof ElementModel) {
|
|
150
|
+
return el
|
|
151
|
+
}
|
|
152
|
+
const id = getId(el)
|
|
153
|
+
return nonNullable(this.findElement(id), `Element ${getId(el)} not found`)
|
|
154
|
+
}
|
|
155
|
+
public findElement(el: LiteralUnion<M['Element'], string>): ElementModel<M> | null {
|
|
156
|
+
return this.#elements.get(el) ?? null
|
|
82
157
|
}
|
|
83
158
|
|
|
84
159
|
/**
|
|
85
|
-
* Returns
|
|
160
|
+
* Returns the root elements of the model.
|
|
86
161
|
*/
|
|
87
|
-
public
|
|
88
|
-
return
|
|
162
|
+
public roots(): ElementsIterator<M> {
|
|
163
|
+
return this.#rootElements.values()
|
|
89
164
|
}
|
|
90
165
|
|
|
91
166
|
/**
|
|
92
|
-
* Returns
|
|
167
|
+
* Returns all elements in the model.
|
|
93
168
|
*/
|
|
94
|
-
public
|
|
95
|
-
return
|
|
169
|
+
public elements(): ElementsIterator<M> {
|
|
170
|
+
return this.#elements.values()
|
|
96
171
|
}
|
|
97
172
|
|
|
98
173
|
/**
|
|
99
174
|
* Returns all relationships in the model.
|
|
100
175
|
*/
|
|
101
|
-
public relationships():
|
|
102
|
-
return
|
|
176
|
+
public relationships(): RelationshipsIterator<M> {
|
|
177
|
+
return this.#relations.values()
|
|
103
178
|
}
|
|
104
179
|
|
|
105
180
|
/**
|
|
106
181
|
* Returns a specific relationship by its ID.
|
|
182
|
+
* If the relationship is not found in the model, it will be searched in the deployment model.
|
|
183
|
+
* Search can be limited to the model or deployment model only.
|
|
107
184
|
*/
|
|
108
|
-
public relationship(id:
|
|
109
|
-
|
|
185
|
+
public relationship(id: M['RelationId'], type: 'model'): RelationshipModel<M>
|
|
186
|
+
public relationship(id: M['RelationId'], type: 'deployment'): DeploymentRelationModel<M>
|
|
187
|
+
public relationship(
|
|
188
|
+
id: M['RelationId'],
|
|
189
|
+
type?: 'model' | 'deployment',
|
|
190
|
+
): RelationshipModel<M> | DeploymentRelationModel<M>
|
|
191
|
+
public relationship(
|
|
192
|
+
id: M['RelationId'],
|
|
193
|
+
type: 'model' | 'deployment' | undefined,
|
|
194
|
+
): RelationshipModel<M> | DeploymentRelationModel<M> {
|
|
195
|
+
if (type === 'deployment') {
|
|
196
|
+
return this.deployment.relationship(id)
|
|
197
|
+
}
|
|
198
|
+
let model = this.#relations.get(id) ?? null
|
|
199
|
+
if (model || type === 'model') {
|
|
200
|
+
return nonNullable(model, `Model relation ${id} not found`)
|
|
201
|
+
}
|
|
202
|
+
// We did not find the relation in the model, let's search in the deployment
|
|
203
|
+
return nonNullable(this.deployment.findRelationship(id), `No model/deployment relation ${id} not found`)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public findRelationship(id: LiteralUnion<M['RelationId'], string>, type: 'model'): RelationshipModel<M> | null
|
|
207
|
+
public findRelationship(
|
|
208
|
+
id: LiteralUnion<M['RelationId'], string>,
|
|
209
|
+
type: 'deployment',
|
|
210
|
+
): DeploymentRelationModel<M> | null
|
|
211
|
+
public findRelationship(
|
|
212
|
+
id: LiteralUnion<M['RelationId'], string>,
|
|
213
|
+
type?: 'model' | 'deployment',
|
|
214
|
+
): RelationshipModel<M> | DeploymentRelationModel<M> | null
|
|
215
|
+
public findRelationship(
|
|
216
|
+
id: LiteralUnion<M['RelationId'], string>,
|
|
217
|
+
type: 'model' | 'deployment' | undefined,
|
|
218
|
+
): RelationshipModel<M> | DeploymentRelationModel<M> | null {
|
|
219
|
+
if (type === 'deployment') {
|
|
220
|
+
return this.deployment.findRelationship(id)
|
|
221
|
+
}
|
|
222
|
+
let model = this.#relations.get(id as M['RelationId']) ?? null
|
|
223
|
+
if (model || type === 'model') {
|
|
224
|
+
return model
|
|
225
|
+
}
|
|
226
|
+
return this.deployment.findRelationship(id)
|
|
110
227
|
}
|
|
111
228
|
|
|
112
229
|
/**
|
|
113
230
|
* Returns all views in the model.
|
|
114
231
|
*/
|
|
115
|
-
public views():
|
|
116
|
-
return
|
|
232
|
+
public views(): IteratorLike<LikeC4ViewModel<M>> {
|
|
233
|
+
return this.#views.values()
|
|
117
234
|
}
|
|
118
235
|
|
|
119
236
|
/**
|
|
120
237
|
* Returns a specific view by its ID.
|
|
121
238
|
*/
|
|
122
|
-
public view(viewId:
|
|
123
|
-
return nonNullable(this.
|
|
239
|
+
public view(viewId: M['View']): LikeC4ViewModel<M> {
|
|
240
|
+
return nonNullable(this.#views.get(viewId as any), `View ${viewId} not found`)
|
|
241
|
+
}
|
|
242
|
+
public findView(viewId: M['View']): LikeC4ViewModel<M> {
|
|
243
|
+
return nonNullable(this.#views.get(viewId as M['ViewId']), `View ${viewId} not found`)
|
|
124
244
|
}
|
|
125
245
|
|
|
126
246
|
/**
|
|
127
247
|
* Returns the parent element of given element.
|
|
128
248
|
* @see ancestors
|
|
129
249
|
*/
|
|
130
|
-
public parent(element: ElementOrFqn):
|
|
250
|
+
public parent(element: M['ElementOrFqn']): ElementModel<M> | null {
|
|
131
251
|
const id = getId(element)
|
|
132
|
-
return this.
|
|
252
|
+
return this.#parents.get(id) || null
|
|
133
253
|
}
|
|
134
254
|
|
|
135
255
|
/**
|
|
136
256
|
* Get all children of the element (only direct children),
|
|
137
257
|
* @see descendants
|
|
138
258
|
*/
|
|
139
|
-
public children(element: ElementOrFqn):
|
|
140
|
-
const id = getId(element)
|
|
141
|
-
return this.
|
|
259
|
+
public children(element: M['ElementOrFqn']): ReadonlySet<ElementModel<M>> {
|
|
260
|
+
const id = getId(element) as M['Fqn']
|
|
261
|
+
return this.#children.get(id)
|
|
142
262
|
}
|
|
143
263
|
|
|
144
264
|
/**
|
|
145
265
|
* Get all sibling (i.e. same parent)
|
|
146
266
|
*/
|
|
147
|
-
public siblings(element: ElementOrFqn):
|
|
148
|
-
const id = getId(element)
|
|
149
|
-
const parent = this.
|
|
150
|
-
const siblings = parent ? this.
|
|
151
|
-
|
|
267
|
+
public *siblings(element: M['ElementOrFqn']): ElementsIterator<M> {
|
|
268
|
+
const id = getId(element) as M['Fqn']
|
|
269
|
+
const parent = this.#parents.get(id)
|
|
270
|
+
const siblings = parent ? this.#children.get(parent.id).values() : this.roots()
|
|
271
|
+
for (const sibling of siblings) {
|
|
272
|
+
if (sibling.id !== id) {
|
|
273
|
+
yield sibling
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return
|
|
152
277
|
}
|
|
153
278
|
|
|
154
279
|
/**
|
|
155
280
|
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
156
281
|
* (from closest to root)
|
|
157
282
|
*/
|
|
158
|
-
public ancestors(element: ElementOrFqn):
|
|
159
|
-
let id =
|
|
160
|
-
const result = [] as LikeC4Model.ElementModel<M>[]
|
|
283
|
+
public *ancestors(element: M['ElementOrFqn']): ElementsIterator<M> {
|
|
284
|
+
let id = getId(element) as M['Fqn']
|
|
161
285
|
let parent
|
|
162
|
-
while (parent = this.
|
|
163
|
-
|
|
286
|
+
while (parent = this.#parents.get(id)) {
|
|
287
|
+
yield parent
|
|
164
288
|
id = parent.id
|
|
165
289
|
}
|
|
166
|
-
return
|
|
290
|
+
return
|
|
167
291
|
}
|
|
168
292
|
|
|
169
293
|
/**
|
|
170
294
|
* Get all descendant elements (i.e. children, children’s children, etc.)
|
|
171
295
|
*/
|
|
172
|
-
public descendants(element: ElementOrFqn):
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
296
|
+
public *descendants(element: M['ElementOrFqn']): ElementsIterator<M> {
|
|
297
|
+
for (const child of this.children(element)) {
|
|
298
|
+
yield child
|
|
299
|
+
yield* this.descendants(child.id)
|
|
300
|
+
}
|
|
301
|
+
return
|
|
176
302
|
}
|
|
177
303
|
|
|
178
304
|
/**
|
|
179
305
|
* Incoming relationships to the element and its descendants
|
|
180
306
|
* @see incomers
|
|
181
307
|
*/
|
|
182
|
-
public incoming(
|
|
183
|
-
element: ElementOrFqn,
|
|
184
|
-
filter: IncomingFilter = 'all'
|
|
185
|
-
):
|
|
308
|
+
public *incoming(
|
|
309
|
+
element: M['ElementOrFqn'],
|
|
310
|
+
filter: IncomingFilter = 'all',
|
|
311
|
+
): RelationshipsIterator<M> {
|
|
186
312
|
const id = getId(element)
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return rel.target.id === id
|
|
313
|
+
for (const rel of this.#incoming.get(id)) {
|
|
314
|
+
switch (true) {
|
|
315
|
+
case filter === 'all':
|
|
316
|
+
case filter === 'direct' && rel.target.id === id:
|
|
317
|
+
case filter === 'to-descendants' && rel.target.id !== id:
|
|
318
|
+
yield rel
|
|
319
|
+
break
|
|
195
320
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Source elements of incoming relationships
|
|
202
|
-
*/
|
|
203
|
-
public incomers(
|
|
204
|
-
element: ElementOrFqn,
|
|
205
|
-
filter: IncomingFilter = 'all'
|
|
206
|
-
): ReadonlyArray<LikeC4Model.ElementModel<M>> {
|
|
207
|
-
return [...new Set(this.incoming(element, filter).map(r => r.source))]
|
|
321
|
+
}
|
|
322
|
+
return
|
|
208
323
|
}
|
|
209
324
|
|
|
210
325
|
/**
|
|
211
326
|
* Outgoing relationships from the element and its descendants
|
|
212
327
|
* @see outgoers
|
|
213
328
|
*/
|
|
214
|
-
public outgoing(
|
|
215
|
-
element: ElementOrFqn,
|
|
216
|
-
filter: OutgoingFilter = 'all'
|
|
217
|
-
):
|
|
329
|
+
public *outgoing(
|
|
330
|
+
element: M['ElementOrFqn'],
|
|
331
|
+
filter: OutgoingFilter = 'all',
|
|
332
|
+
): RelationshipsIterator<M> {
|
|
218
333
|
const id = getId(element)
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
334
|
+
for (const rel of this.#outgoing.get(id)) {
|
|
335
|
+
switch (true) {
|
|
336
|
+
case filter === 'all':
|
|
337
|
+
case filter === 'direct' && rel.source.id === id:
|
|
338
|
+
case filter === 'from-descendants' && rel.source.id !== id:
|
|
339
|
+
yield rel
|
|
340
|
+
break
|
|
226
341
|
}
|
|
227
|
-
return rel.source.id !== id
|
|
228
|
-
})
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Target elements of outgoing relationships
|
|
233
|
-
*/
|
|
234
|
-
public outgoers(
|
|
235
|
-
element: ElementOrFqn,
|
|
236
|
-
filter: OutgoingFilter = 'all'
|
|
237
|
-
): ReadonlyArray<LikeC4Model.ElementModel<M>> {
|
|
238
|
-
return [...new Set(this.outgoing(element, filter).map(r => r.target))]
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Relationships inside the element, among descendants
|
|
243
|
-
*/
|
|
244
|
-
public internal(element: ElementOrFqn): ReadonlyArray<LikeC4Model.Relationship<M>> {
|
|
245
|
-
const id = getId(element)
|
|
246
|
-
return Array.from(this._internalOf(id))
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Resolve siblings of the element and siblings of ancestors
|
|
251
|
-
* (from closest to root)
|
|
252
|
-
*/
|
|
253
|
-
public ascendingSiblings(element: ElementOrFqn): ReadonlyArray<LikeC4Model.ElementModel<M>> {
|
|
254
|
-
const id = getId(element)
|
|
255
|
-
let siblings = this._cacheAscendingSiblings.get(id)
|
|
256
|
-
if (!siblings) {
|
|
257
|
-
siblings = [
|
|
258
|
-
...this.siblings(id),
|
|
259
|
-
...this.ancestors(id).flatMap(a => this.siblings(a.id))
|
|
260
|
-
]
|
|
261
|
-
this._cacheAscendingSiblings.set(id, siblings)
|
|
262
342
|
}
|
|
263
|
-
return
|
|
343
|
+
return
|
|
264
344
|
}
|
|
265
345
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
346
|
+
public globals(): ModelGlobals {
|
|
347
|
+
return {
|
|
348
|
+
predicates: {
|
|
349
|
+
...this.$model.globals?.predicates,
|
|
350
|
+
},
|
|
351
|
+
dynamicPredicates: {
|
|
352
|
+
...this.$model.globals?.dynamicPredicates,
|
|
353
|
+
},
|
|
354
|
+
styles: {
|
|
355
|
+
...this.$model.globals?.styles,
|
|
356
|
+
},
|
|
357
|
+
}
|
|
272
358
|
}
|
|
273
359
|
|
|
274
|
-
private addElement(
|
|
275
|
-
if (this.
|
|
276
|
-
throw new Error(`Element ${
|
|
360
|
+
private addElement(element: Element) {
|
|
361
|
+
if (this.#elements.has(element.id)) {
|
|
362
|
+
throw new Error(`Element ${element.id} already exists`)
|
|
277
363
|
}
|
|
278
|
-
const el = new
|
|
279
|
-
this.
|
|
364
|
+
const el = new ElementModel(this, Object.freeze(structuredClone(element)))
|
|
365
|
+
this.#elements.set(el.id, el)
|
|
280
366
|
const parentId = parentFqn(el.id)
|
|
281
367
|
if (parentId) {
|
|
282
|
-
this.
|
|
283
|
-
this.
|
|
368
|
+
invariant(this.#elements.has(parentId), `Parent ${parentId} of ${el.id} not found`)
|
|
369
|
+
this.#parents.set(el.id, this.element(parentId))
|
|
370
|
+
this.#children.get(parentId).add(el)
|
|
284
371
|
} else {
|
|
285
|
-
this.
|
|
372
|
+
this.#rootElements.add(el)
|
|
286
373
|
}
|
|
374
|
+
return el
|
|
287
375
|
}
|
|
288
376
|
|
|
289
|
-
private addRelation(relation:
|
|
290
|
-
if (this.
|
|
377
|
+
private addRelation(relation: ModelRelation) {
|
|
378
|
+
if (this.#relations.has(relation.id)) {
|
|
291
379
|
throw new Error(`Relation ${relation.id} already exists`)
|
|
292
380
|
}
|
|
293
|
-
const rel = new
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
381
|
+
const rel = new RelationshipModel(
|
|
382
|
+
this,
|
|
383
|
+
Object.freeze(structuredClone(relation)),
|
|
384
|
+
)
|
|
385
|
+
const { source, target } = rel
|
|
386
|
+
this.#relations.set(rel.id, rel)
|
|
387
|
+
this.#incoming.get(target.id).add(rel)
|
|
388
|
+
this.#outgoing.get(source.id).add(rel)
|
|
297
389
|
|
|
298
|
-
const relParent = commonAncestor(
|
|
390
|
+
const relParent = commonAncestor(source.id, target.id)
|
|
299
391
|
// Process internal relationships
|
|
300
392
|
if (relParent) {
|
|
301
393
|
for (const ancestor of [relParent, ...ancestorsFqn(relParent)]) {
|
|
302
|
-
this.
|
|
394
|
+
this.#internal.get(ancestor).add(rel)
|
|
303
395
|
}
|
|
304
396
|
}
|
|
305
397
|
// Process source hierarchy
|
|
@@ -307,285 +399,72 @@ export class LikeC4Model<M extends LikeC4Model.ViewModel = LikeC4Model.ViewModel
|
|
|
307
399
|
if (sourceAncestor === relParent) {
|
|
308
400
|
break
|
|
309
401
|
}
|
|
310
|
-
this.
|
|
402
|
+
this.#outgoing.get(sourceAncestor).add(rel)
|
|
311
403
|
}
|
|
312
404
|
// Process target hierarchy
|
|
313
405
|
for (const targetAncestor of ancestorsFqn(relation.target)) {
|
|
314
406
|
if (targetAncestor === relParent) {
|
|
315
407
|
break
|
|
316
408
|
}
|
|
317
|
-
this.
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
private _childrenOf(id: Fqn) {
|
|
322
|
-
let children = this._children.get(id)
|
|
323
|
-
if (!children) {
|
|
324
|
-
children = []
|
|
325
|
-
this._children.set(id, children)
|
|
409
|
+
this.#incoming.get(targetAncestor).add(rel)
|
|
326
410
|
}
|
|
327
|
-
return
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
private _incomingTo(id: Fqn) {
|
|
331
|
-
let incoming = this._incoming.get(id)
|
|
332
|
-
if (!incoming) {
|
|
333
|
-
incoming = new Set()
|
|
334
|
-
this._incoming.set(id, incoming)
|
|
335
|
-
}
|
|
336
|
-
return incoming
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
private _outgoingFrom(id: Fqn) {
|
|
340
|
-
let outgoing = this._outgoing.get(id)
|
|
341
|
-
if (!outgoing) {
|
|
342
|
-
outgoing = new Set()
|
|
343
|
-
this._outgoing.set(id, outgoing)
|
|
344
|
-
}
|
|
345
|
-
return outgoing
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
private _internalOf(id: Fqn) {
|
|
349
|
-
let internal = this._internal.get(id)
|
|
350
|
-
if (!internal) {
|
|
351
|
-
internal = new Set()
|
|
352
|
-
this._internal.set(id, internal)
|
|
353
|
-
}
|
|
354
|
-
return internal
|
|
411
|
+
return rel
|
|
355
412
|
}
|
|
356
413
|
}
|
|
357
414
|
|
|
358
415
|
export namespace LikeC4Model {
|
|
359
|
-
export
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
export
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
export type
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
export namespace Layouted {
|
|
414
|
-
export type ViewModel = LikeC4DiagramModel
|
|
415
|
-
export type SourceModel = LikeC4Model.SourceModel<ViewModel>
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
export type ModelType<M extends ViewModel = ViewModel> = M extends LikeC4DiagramModel ? 'layouted'
|
|
419
|
-
: M extends LikeC4ViewModel ? 'computed'
|
|
420
|
-
: never
|
|
421
|
-
|
|
422
|
-
export function isLayouted(model: LikeC4Model): model is Layouted {
|
|
423
|
-
return model.type === 'layouted'
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
export class Relationship<M extends ViewModel = ViewModel> {
|
|
427
|
-
constructor(
|
|
428
|
-
public readonly relationship: C4Relation,
|
|
429
|
-
private readonly model: LikeC4Model<M>
|
|
430
|
-
) {
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
get id() {
|
|
434
|
-
return this.relationship.id
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
get title() {
|
|
438
|
-
return this.relationship.title
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
get kind() {
|
|
442
|
-
return this.relationship.kind ?? null
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
get tags(): C4Tag[] {
|
|
446
|
-
return this.relationship.tags ?? []
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
get source() {
|
|
450
|
-
return this.model.element(this.relationship.source)
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
get target() {
|
|
454
|
-
return this.model.element(this.relationship.target)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
public metadata(key: string): string | undefined
|
|
458
|
-
public metadata(key: string, defaultValue: string): string
|
|
459
|
-
public metadata(key: string, defaultValue?: string): string | undefined {
|
|
460
|
-
return this.relationship.metadata?.[key] ?? defaultValue
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
public hasMetadata(key: string): boolean {
|
|
464
|
-
return isTruthy(this.relationship.metadata?.[key])
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Class renamed to ElementModel, otherwise generated DTS will be incorrect
|
|
469
|
-
export class ElementModel<M extends ViewModel = ViewModel> {
|
|
470
|
-
constructor(
|
|
471
|
-
public readonly element: C4Element,
|
|
472
|
-
private readonly model: LikeC4Model<M>
|
|
473
|
-
) {
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
get id() {
|
|
477
|
-
return this.element.id
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
get title() {
|
|
481
|
-
return this.element.title
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
get kind(): C4ElementKind {
|
|
485
|
-
return this.element.kind
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
get isRoot(): boolean {
|
|
489
|
-
return parentFqn(this.element.id) === null
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
get hasNested(): boolean {
|
|
493
|
-
return this.model.children(this).length > 0
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
get shape(): C4ElementShape {
|
|
497
|
-
return this.element.shape ?? DefaultElementShape
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
get color(): C4Color {
|
|
501
|
-
return this.element.color ?? DefaultThemeColor
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
get tags(): C4Tag[] {
|
|
505
|
-
return this.element.tags ?? []
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
public parent(): ElementModel<M> | null {
|
|
509
|
-
return this.model.parent(this)
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
public metadata(key: string): string | undefined
|
|
513
|
-
public metadata(key: string, defaultValue: string): string
|
|
514
|
-
public metadata(key: string, defaultValue?: string): string | undefined {
|
|
515
|
-
return this.element.metadata?.[key] ?? defaultValue
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
public hasMetadata(key: string): boolean {
|
|
519
|
-
return isTruthy(this.element.metadata?.[key])
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
public ancestors() {
|
|
523
|
-
return this.model.ancestors(this)
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
public siblings() {
|
|
527
|
-
return this.model.siblings(this)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
public descendants() {
|
|
531
|
-
return this.model.descendants(this)
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
public children() {
|
|
535
|
-
return this.model.children(this)
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* First 'view of' current element
|
|
540
|
-
*/
|
|
541
|
-
public viewOf() {
|
|
542
|
-
return this.model.views().find(v => v.viewOf?.id === this.id) ?? null
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* All views 'view of' current element
|
|
547
|
-
*/
|
|
548
|
-
public viewsOf() {
|
|
549
|
-
return this.model.views().filter(v => v.viewOf?.id === this.id)
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* Views that contain this element
|
|
554
|
-
*/
|
|
555
|
-
public views() {
|
|
556
|
-
return this.model.viewsWithElement(this)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
public incoming(filter?: IncomingFilter) {
|
|
560
|
-
return this.model.incoming(this, filter)
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
public incomers(filter?: IncomingFilter) {
|
|
564
|
-
return this.model.incomers(this, filter)
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
public outgoing(filter?: OutgoingFilter) {
|
|
568
|
-
return this.model.outgoing(this, filter)
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
public outgoers(filter?: OutgoingFilter) {
|
|
572
|
-
return this.model.outgoers(this, filter)
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
public internal() {
|
|
576
|
-
return this.model.internal(this)
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/**
|
|
580
|
-
* Resolve siblings of the element and siblings of ancestors
|
|
581
|
-
* (from closest to root)
|
|
582
|
-
*/
|
|
583
|
-
public ascendingSiblings() {
|
|
584
|
-
return this.model.ascendingSiblings(this)
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// public *descendants(): IterableIterator<LikeC4Element> {
|
|
588
|
-
// return
|
|
589
|
-
// }
|
|
590
|
-
}
|
|
416
|
+
export type Any = Aux<
|
|
417
|
+
string,
|
|
418
|
+
string,
|
|
419
|
+
string,
|
|
420
|
+
ComputedView | DiagramView
|
|
421
|
+
>
|
|
422
|
+
|
|
423
|
+
export type Element<M extends AnyAux = Any> = ElementModel<M>
|
|
424
|
+
|
|
425
|
+
// Relationship in logical model
|
|
426
|
+
export type Relation<M extends AnyAux = Any> = RelationshipModel<M>
|
|
427
|
+
|
|
428
|
+
// Relationship in logical or deployment model
|
|
429
|
+
export type AnyRelation<M extends AnyAux = Any> = RelationshipModel<M> | DeploymentRelationModel<M>
|
|
430
|
+
|
|
431
|
+
export type View<
|
|
432
|
+
M extends AnyAux = Any,
|
|
433
|
+
V extends ComputedView | DiagramView = M['ViewType'],
|
|
434
|
+
> = LikeC4ViewModel<M, V>
|
|
435
|
+
|
|
436
|
+
export type Node<
|
|
437
|
+
M extends AnyAux = Any,
|
|
438
|
+
V extends ComputedView | DiagramView = M['ViewType'],
|
|
439
|
+
> = NodeModel<M, V>
|
|
440
|
+
|
|
441
|
+
export type Edge<
|
|
442
|
+
M extends AnyAux = Any,
|
|
443
|
+
V extends ComputedView | DiagramView = M['ViewType'],
|
|
444
|
+
> = EdgeModel<M, V>
|
|
445
|
+
|
|
446
|
+
export type DeploymentModel<M extends AnyAux = AnyAux> = LikeC4DeploymentModel<M>
|
|
447
|
+
|
|
448
|
+
export type Deployment<M extends AnyAux = AnyAux> = DeploymentElementModel<M>
|
|
449
|
+
export type DeploymentNode<M extends AnyAux = AnyAux> = DeploymentNodeModel<M>
|
|
450
|
+
export type DeployedInstance<M extends AnyAux = AnyAux> = DeployedInstanceModel<M>
|
|
451
|
+
|
|
452
|
+
export type Typed<
|
|
453
|
+
Elements extends string = string,
|
|
454
|
+
Deployments extends string = string,
|
|
455
|
+
Views extends string = string,
|
|
456
|
+
ViewType = DiagramView<Views> | ComputedView<Views>,
|
|
457
|
+
> = Aux<Elements, Deployments, Views, ViewType>
|
|
458
|
+
|
|
459
|
+
export type Computed<
|
|
460
|
+
Elements extends string = string,
|
|
461
|
+
Deployments extends string = string,
|
|
462
|
+
Views extends string = string,
|
|
463
|
+
> = LikeC4Model<Typed<Elements, Deployments, Views, ComputedView<Views>>>
|
|
464
|
+
|
|
465
|
+
export type Layouted<
|
|
466
|
+
Elements extends string = string,
|
|
467
|
+
Deployments extends string = string,
|
|
468
|
+
Views extends string = string,
|
|
469
|
+
> = LikeC4Model<Typed<Elements, Deployments, Views, DiagramView<Views>>>
|
|
591
470
|
}
|