@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/builder/Builder.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import defu from 'defu'
|
|
2
|
-
import { fromEntries, hasAtLeast, isFunction, isNonNullish, map, mapToObj, mapValues, pickBy } from 'remeda'
|
|
2
|
+
import { fromEntries, hasAtLeast, isFunction, isNonNullish, isNullish, map, mapToObj, mapValues, pickBy } from 'remeda'
|
|
3
3
|
import type { Writable } from 'type-fest'
|
|
4
4
|
import { invariant } from '../errors'
|
|
5
|
+
import { LikeC4Model } from '../model/LikeC4Model'
|
|
5
6
|
import {
|
|
6
7
|
type Color,
|
|
7
8
|
DefaultElementShape,
|
|
8
9
|
DefaultThemeColor,
|
|
10
|
+
DeploymentElement,
|
|
11
|
+
type DeploymentRelation,
|
|
12
|
+
type DeploymentView,
|
|
9
13
|
type Element,
|
|
10
14
|
type ElementShape,
|
|
11
15
|
type ElementView,
|
|
@@ -15,30 +19,29 @@ import {
|
|
|
15
19
|
type LikeC4View,
|
|
16
20
|
type Link,
|
|
17
21
|
type ModelGlobals,
|
|
22
|
+
type ModelRelation,
|
|
18
23
|
type NonEmptyArray,
|
|
19
|
-
type
|
|
20
|
-
type
|
|
21
|
-
type Tag
|
|
24
|
+
type RelationId,
|
|
25
|
+
type Tag,
|
|
22
26
|
} from '../types'
|
|
23
|
-
import type { ParsedLikeC4Model } from '../types/model'
|
|
24
27
|
import { isSameHierarchy, nameFromFqn, parentFqn } from '../utils/fqn'
|
|
25
28
|
import type { AnyTypes, BuilderSpecification, Types } from './_types'
|
|
26
|
-
import type {
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} from './Builder.
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
export interface Builder<T extends AnyTypes> {
|
|
29
|
+
import type { AddDeploymentNode } from './Builder.deployment'
|
|
30
|
+
import type {
|
|
31
|
+
AddDeploymentNodeHelpers,
|
|
32
|
+
DeloymentModelBuildFunction,
|
|
33
|
+
DeloymentModelHelpers,
|
|
34
|
+
DeploymentModelBuilder,
|
|
35
|
+
} from './Builder.deploymentModel'
|
|
36
|
+
import type { AddElement } from './Builder.element'
|
|
37
|
+
import type { AddElementHelpers, ModelBuilder, ModelBuilderFunction, ModelHelpers } from './Builder.model'
|
|
38
|
+
import { $autoLayout, $exclude, $include, $rules, $style } from './Builder.view-common'
|
|
39
|
+
import type { DeploymentRulesBuilderOp } from './Builder.view-deployment'
|
|
40
|
+
import type { ElementViewRulesBuilder } from './Builder.view-element'
|
|
41
|
+
import { mkViewBuilder, type ViewsBuilder, type ViewsBuilderFunction, type ViewsHelpers } from './Builder.views'
|
|
42
|
+
import type { BuilderMethods } from './Builder.with'
|
|
43
|
+
|
|
44
|
+
export interface Builder<T extends AnyTypes> extends BuilderMethods<T> {
|
|
42
45
|
/**
|
|
43
46
|
* Only available in compile time
|
|
44
47
|
*/
|
|
@@ -51,190 +54,120 @@ export interface Builder<T extends AnyTypes> {
|
|
|
51
54
|
*/
|
|
52
55
|
helpers(): {
|
|
53
56
|
model: ModelHelpers<T>
|
|
54
|
-
views:
|
|
57
|
+
views: ViewsHelpers
|
|
58
|
+
deployment: DeloymentModelHelpers<T>
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
B extends AnyTypes,
|
|
137
|
-
C extends AnyTypes,
|
|
138
|
-
D extends AnyTypes,
|
|
139
|
-
E extends AnyTypes,
|
|
140
|
-
F extends AnyTypes,
|
|
141
|
-
G extends AnyTypes
|
|
142
|
-
>(
|
|
143
|
-
op1: (input: Builder<T>) => Builder<A>,
|
|
144
|
-
op2: (input: Builder<A>) => Builder<B>,
|
|
145
|
-
op3: (input: Builder<B>) => Builder<C>,
|
|
146
|
-
op4: (input: Builder<C>) => Builder<D>,
|
|
147
|
-
op5: (input: Builder<D>) => Builder<E>,
|
|
148
|
-
op6: (input: Builder<E>) => Builder<F>,
|
|
149
|
-
op7: (input: Builder<F>) => Builder<G>
|
|
150
|
-
): Builder<G>
|
|
151
|
-
|
|
152
|
-
with<
|
|
153
|
-
A extends AnyTypes,
|
|
154
|
-
B extends AnyTypes,
|
|
155
|
-
C extends AnyTypes,
|
|
156
|
-
D extends AnyTypes,
|
|
157
|
-
E extends AnyTypes,
|
|
158
|
-
F extends AnyTypes,
|
|
159
|
-
G extends AnyTypes,
|
|
160
|
-
H extends AnyTypes
|
|
161
|
-
>(
|
|
162
|
-
op1: (input: Builder<T>) => Builder<A>,
|
|
163
|
-
op2: (input: Builder<A>) => Builder<B>,
|
|
164
|
-
op3: (input: Builder<B>) => Builder<C>,
|
|
165
|
-
op4: (input: Builder<C>) => Builder<D>,
|
|
166
|
-
op5: (input: Builder<D>) => Builder<E>,
|
|
167
|
-
op6: (input: Builder<E>) => Builder<F>,
|
|
168
|
-
op7: (input: Builder<F>) => Builder<G>,
|
|
169
|
-
op8: (input: Builder<G>) => Builder<H>
|
|
170
|
-
): Builder<H>
|
|
171
|
-
|
|
172
|
-
with<
|
|
173
|
-
A extends AnyTypes,
|
|
174
|
-
B extends AnyTypes,
|
|
175
|
-
C extends AnyTypes,
|
|
176
|
-
D extends AnyTypes,
|
|
177
|
-
E extends AnyTypes,
|
|
178
|
-
F extends AnyTypes,
|
|
179
|
-
G extends AnyTypes,
|
|
180
|
-
H extends AnyTypes,
|
|
181
|
-
I extends AnyTypes
|
|
182
|
-
>(
|
|
183
|
-
op1: (input: Builder<T>) => Builder<A>,
|
|
184
|
-
op2: (input: Builder<A>) => Builder<B>,
|
|
185
|
-
op3: (input: Builder<B>) => Builder<C>,
|
|
186
|
-
op4: (input: Builder<C>) => Builder<D>,
|
|
187
|
-
op5: (input: Builder<D>) => Builder<E>,
|
|
188
|
-
op6: (input: Builder<E>) => Builder<F>,
|
|
189
|
-
op7: (input: Builder<F>) => Builder<G>,
|
|
190
|
-
op8: (input: Builder<G>) => Builder<H>,
|
|
191
|
-
op9: (input: Builder<H>) => Builder<I>
|
|
192
|
-
): Builder<I>
|
|
193
|
-
|
|
194
|
-
with<
|
|
195
|
-
A extends AnyTypes,
|
|
196
|
-
B extends AnyTypes,
|
|
197
|
-
C extends AnyTypes,
|
|
198
|
-
D extends AnyTypes,
|
|
199
|
-
E extends AnyTypes,
|
|
200
|
-
F extends AnyTypes,
|
|
201
|
-
G extends AnyTypes,
|
|
202
|
-
H extends AnyTypes,
|
|
203
|
-
I extends AnyTypes,
|
|
204
|
-
J extends AnyTypes
|
|
205
|
-
>(
|
|
206
|
-
op1: (input: Builder<T>) => Builder<A>,
|
|
207
|
-
op2: (input: Builder<A>) => Builder<B>,
|
|
208
|
-
op3: (input: Builder<B>) => Builder<C>,
|
|
209
|
-
op4: (input: Builder<C>) => Builder<D>,
|
|
210
|
-
op5: (input: Builder<D>) => Builder<E>,
|
|
211
|
-
op6: (input: Builder<E>) => Builder<F>,
|
|
212
|
-
op7: (input: Builder<F>) => Builder<G>,
|
|
213
|
-
op8: (input: Builder<G>) => Builder<H>,
|
|
214
|
-
op9: (input: Builder<H>) => Builder<I>,
|
|
215
|
-
op10: (input: Builder<I>) => Builder<J>
|
|
216
|
-
): Builder<J>
|
|
61
|
+
/**
|
|
62
|
+
* Adds model elements
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* builder.model(({ el }, _) =>
|
|
66
|
+
* _(
|
|
67
|
+
* el('a'),
|
|
68
|
+
* el('a.b').with(
|
|
69
|
+
* el('c')
|
|
70
|
+
* )
|
|
71
|
+
* )
|
|
72
|
+
* )
|
|
73
|
+
*
|
|
74
|
+
* builder.model((_, m) =>
|
|
75
|
+
* m(
|
|
76
|
+
* _.el('a'),
|
|
77
|
+
* _.el('a.b').with(
|
|
78
|
+
* _.el('c')
|
|
79
|
+
* )
|
|
80
|
+
* )
|
|
81
|
+
* )
|
|
82
|
+
*/
|
|
83
|
+
model<Out extends AnyTypes>(
|
|
84
|
+
callback: ModelBuilderFunction<T, Out>,
|
|
85
|
+
): Builder<Out>
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Adds deployment model
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* builder.deployment(({ node, instanceOf }, _) =>
|
|
92
|
+
* _(
|
|
93
|
+
* node('node1'),
|
|
94
|
+
* node('node1.child1').with(
|
|
95
|
+
* instanceOf('model.element')
|
|
96
|
+
* )
|
|
97
|
+
* )
|
|
98
|
+
* )
|
|
99
|
+
*
|
|
100
|
+
* builder.deployment((_,d) =>
|
|
101
|
+
* d(
|
|
102
|
+
* _.node('node1'),
|
|
103
|
+
* _.node('node1.child1').with(
|
|
104
|
+
* _.instanceOf('model.element')
|
|
105
|
+
* )
|
|
106
|
+
* )
|
|
107
|
+
* )
|
|
108
|
+
*/
|
|
109
|
+
deployment<Out extends AnyTypes>(
|
|
110
|
+
callback: DeloymentModelBuildFunction<T, Out>,
|
|
111
|
+
): Builder<Out>
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Adds views
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* builder.views(({ view, $include }, _) =>
|
|
118
|
+
* _(
|
|
119
|
+
* view('index').with(
|
|
120
|
+
* $include('a -> b')
|
|
121
|
+
* )
|
|
122
|
+
* )
|
|
123
|
+
* )
|
|
124
|
+
*/
|
|
125
|
+
views<Out extends AnyTypes>(
|
|
126
|
+
callback: ViewsBuilderFunction<T, Out>,
|
|
127
|
+
): Builder<Out>
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Returns model as result of parsing only
|
|
131
|
+
* Views are not computed or layouted
|
|
132
|
+
* {@link toLikeC4Model} should be used to get model with computed views
|
|
133
|
+
*/
|
|
134
|
+
build(): Types.ToParsedLikeC4Model<T>
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns LikeC4Model with computed views
|
|
138
|
+
*/
|
|
139
|
+
toLikeC4Model(): Types.ToLikeC4Model<T>
|
|
217
140
|
}
|
|
218
141
|
|
|
142
|
+
interface Internals<T extends AnyTypes> extends ViewsBuilder<T>, ModelBuilder<T>, DeploymentModelBuilder<T> {
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
type Op<T> = (b: T) => T
|
|
146
|
+
|
|
219
147
|
function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
220
148
|
spec: Spec,
|
|
221
149
|
_elements = new Map<string, Element>(),
|
|
222
|
-
_relations = [] as
|
|
150
|
+
_relations = [] as ModelRelation[],
|
|
223
151
|
_views = new Map<string, LikeC4View>(),
|
|
224
152
|
_globals = {
|
|
225
153
|
predicates: {},
|
|
226
154
|
dynamicPredicates: {},
|
|
227
|
-
styles: {}
|
|
228
|
-
} as ModelGlobals
|
|
155
|
+
styles: {},
|
|
156
|
+
} as ModelGlobals,
|
|
157
|
+
_deployments = new Map<string, DeploymentElement>(),
|
|
158
|
+
_deploymentRelations = [] as DeploymentRelation[],
|
|
229
159
|
): Builder<T> {
|
|
230
160
|
const toLikeC4Specification = (): Types.ToParsedLikeC4Model<T>['specification'] => ({
|
|
231
|
-
tags: (spec.tags ?? []) as Tag<T['Tag']>[],
|
|
232
161
|
elements: {
|
|
233
|
-
...spec.elements as any
|
|
162
|
+
...structuredClone(spec.elements) as any,
|
|
163
|
+
},
|
|
164
|
+
deployments: {
|
|
165
|
+
...structuredClone(spec.deployments) as any,
|
|
234
166
|
},
|
|
235
167
|
relationships: {
|
|
236
|
-
...spec.relationships
|
|
237
|
-
}
|
|
168
|
+
...structuredClone(spec.relationships) as any,
|
|
169
|
+
},
|
|
170
|
+
tags: (spec.tags ?? []) as Tag<T['Tag']>[],
|
|
238
171
|
})
|
|
239
172
|
|
|
240
173
|
const mapLinks = (links?: Array<string | { title?: string; url: string }>): NonEmptyArray<Link> | null => {
|
|
@@ -244,119 +177,179 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
244
177
|
return map(links, l => (typeof l === 'string' ? { url: l } : l))
|
|
245
178
|
}
|
|
246
179
|
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
exclude(expr) {
|
|
256
|
-
view.rules.push({
|
|
257
|
-
exclude: [expr]
|
|
258
|
-
})
|
|
259
|
-
return viewBuilder
|
|
260
|
-
},
|
|
261
|
-
include(expr) {
|
|
262
|
-
view.rules.push({
|
|
263
|
-
include: [expr]
|
|
264
|
-
})
|
|
265
|
-
return viewBuilder
|
|
266
|
-
},
|
|
267
|
-
style(rule) {
|
|
268
|
-
view.rules.push(rule)
|
|
269
|
-
return viewBuilder
|
|
270
|
-
}
|
|
271
|
-
// title(title: string) {
|
|
272
|
-
// view.title = title
|
|
273
|
-
// return viewBuilder
|
|
274
|
-
// },
|
|
275
|
-
// description(description: string) {
|
|
276
|
-
// view.description = description
|
|
277
|
-
// return viewBuilder
|
|
278
|
-
// }
|
|
180
|
+
const createGenericView = <B extends Op<any> | undefined>(
|
|
181
|
+
id: string,
|
|
182
|
+
_props: T['NewViewProps'] | string | B | null,
|
|
183
|
+
builder: B,
|
|
184
|
+
): [Omit<LikeC4View, 'rules'>, B] => {
|
|
185
|
+
if (isFunction(_props)) {
|
|
186
|
+
builder = _props as B
|
|
187
|
+
_props = {}
|
|
279
188
|
}
|
|
280
|
-
|
|
189
|
+
_props ??= {}
|
|
190
|
+
const {
|
|
191
|
+
links: _links = [],
|
|
192
|
+
title = null,
|
|
193
|
+
description = null,
|
|
194
|
+
tags = null,
|
|
195
|
+
...props
|
|
196
|
+
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
197
|
+
|
|
198
|
+
const links = mapLinks(_links)
|
|
199
|
+
return [{
|
|
200
|
+
id: id as any,
|
|
201
|
+
title,
|
|
202
|
+
description,
|
|
203
|
+
tags,
|
|
204
|
+
links,
|
|
205
|
+
customColorDefinitions: {},
|
|
206
|
+
...props,
|
|
207
|
+
}, builder]
|
|
281
208
|
}
|
|
282
209
|
|
|
283
|
-
const self: Builder<T> = {
|
|
210
|
+
const self: Builder<T> & Internals<T> = {
|
|
284
211
|
get Types(): T {
|
|
285
212
|
throw new Error('Types are not available in runtime')
|
|
286
213
|
},
|
|
287
|
-
clone: () =>
|
|
288
|
-
builder(
|
|
214
|
+
clone: () => {
|
|
215
|
+
return builder(
|
|
289
216
|
structuredClone(spec),
|
|
290
217
|
structuredClone(_elements),
|
|
291
218
|
structuredClone(_relations),
|
|
292
219
|
structuredClone(_views),
|
|
293
|
-
structuredClone(_globals)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
)
|
|
303
|
-
}
|
|
304
|
-
if (_elements.has(element.id)) {
|
|
305
|
-
throw new Error(`Element with id "${element.id}" already exists`)
|
|
306
|
-
}
|
|
307
|
-
_elements.set(element.id, element)
|
|
308
|
-
return self
|
|
309
|
-
},
|
|
310
|
-
addRelation(relation) {
|
|
311
|
-
const sourceEl = _elements.get(relation.source)
|
|
312
|
-
invariant(sourceEl, `Element with id "${relation.source}" not found`)
|
|
313
|
-
const targetEl = _elements.get(relation.target)
|
|
314
|
-
invariant(targetEl, `Element with id "${relation.target}" not found`)
|
|
220
|
+
structuredClone(_globals),
|
|
221
|
+
structuredClone(_deployments),
|
|
222
|
+
structuredClone(_deploymentRelations),
|
|
223
|
+
)
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
__addElement: (element) => {
|
|
227
|
+
const parent = parentFqn(element.id)
|
|
228
|
+
if (parent) {
|
|
315
229
|
invariant(
|
|
316
|
-
|
|
317
|
-
|
|
230
|
+
_elements.get(parent),
|
|
231
|
+
`Parent element with id "${parent}" not found for element with id "${element.id}"`,
|
|
318
232
|
)
|
|
319
|
-
_relations.push({
|
|
320
|
-
id: `rel${_relations.length + 1}` as RelationID,
|
|
321
|
-
...relation
|
|
322
|
-
})
|
|
323
|
-
return self
|
|
324
|
-
},
|
|
325
|
-
/**
|
|
326
|
-
* Fully qualified name for nested elements
|
|
327
|
-
*/
|
|
328
|
-
fqn(id) {
|
|
329
|
-
return id as Fqn
|
|
330
|
-
},
|
|
331
|
-
addSourcelessRelation() {
|
|
332
|
-
throw new Error('Can be called only in nested model')
|
|
333
233
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
addView: (view) => {
|
|
337
|
-
if (isScopedElementView(view)) {
|
|
338
|
-
invariant(_elements.get(view.viewOf), `Invalid view ${view.id}, wlement with id "${view.viewOf}" not found`)
|
|
339
|
-
}
|
|
340
|
-
_views.set(view.id, view)
|
|
341
|
-
return self
|
|
234
|
+
if (_elements.has(element.id)) {
|
|
235
|
+
throw new Error(`Element with id "${element.id}" already exists`)
|
|
342
236
|
}
|
|
343
|
-
|
|
237
|
+
_elements.set(element.id, element)
|
|
238
|
+
return self
|
|
239
|
+
},
|
|
240
|
+
__addRelation(relation) {
|
|
241
|
+
const sourceEl = _elements.get(relation.source)
|
|
242
|
+
invariant(sourceEl, `Element with id "${relation.source}" not found`)
|
|
243
|
+
const targetEl = _elements.get(relation.target)
|
|
244
|
+
invariant(targetEl, `Element with id "${relation.target}" not found`)
|
|
245
|
+
invariant(
|
|
246
|
+
!isSameHierarchy(sourceEl, targetEl),
|
|
247
|
+
'Cannot create relationship between elements in the same hierarchy',
|
|
248
|
+
)
|
|
249
|
+
_relations.push({
|
|
250
|
+
id: `rel${_relations.length + 1}` as RelationId,
|
|
251
|
+
...relation,
|
|
252
|
+
})
|
|
253
|
+
return self
|
|
254
|
+
},
|
|
255
|
+
/**
|
|
256
|
+
* Fully qualified name for nested elements
|
|
257
|
+
*/
|
|
258
|
+
__fqn(id) {
|
|
259
|
+
invariant(id.trim() !== '', 'Id must be non-empty')
|
|
260
|
+
return id as Fqn
|
|
261
|
+
},
|
|
262
|
+
__addSourcelessRelation() {
|
|
263
|
+
throw new Error('Can be called only in nested model')
|
|
264
|
+
},
|
|
265
|
+
__addView: (view) => {
|
|
266
|
+
if (_views.has(view.id)) {
|
|
267
|
+
throw new Error(`View with id "${view.id}" already exists`)
|
|
268
|
+
}
|
|
269
|
+
if (isScopedElementView(view)) {
|
|
270
|
+
invariant(
|
|
271
|
+
_elements.get(view.viewOf),
|
|
272
|
+
`Invalid scoped view ${view.id}, wlement with id "${view.viewOf}" not found`,
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
_views.set(view.id, view)
|
|
276
|
+
return self
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
__addDeployment: (node: DeploymentElement) => {
|
|
280
|
+
if (_deployments.has(node.id)) {
|
|
281
|
+
throw new Error(`Deployment with id "${node.id}" already exists`)
|
|
282
|
+
}
|
|
283
|
+
const parent = parentFqn(node.id)
|
|
284
|
+
if (parent) {
|
|
285
|
+
invariant(
|
|
286
|
+
_deployments.get(parent),
|
|
287
|
+
`Parent element with id "${parent}" not found for node with id "${node.id}"`,
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
if (DeploymentElement.isInstance(node)) {
|
|
291
|
+
invariant(parent, `Instance ${node.id} of ${node.element} must be deployed under a parent node`)
|
|
292
|
+
invariant(
|
|
293
|
+
_elements.get(node.element),
|
|
294
|
+
`Instance "${node.id}" references non-existing element "${node.element}"`,
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
_deployments.set(node.id, node)
|
|
298
|
+
return self
|
|
299
|
+
},
|
|
300
|
+
__addDeploymentRelation: (relation) => {
|
|
301
|
+
invariant(
|
|
302
|
+
!isSameHierarchy(relation.source.id, relation.target.id),
|
|
303
|
+
'Cannot create relationship between elements in the same hierarchy',
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
invariant(
|
|
307
|
+
_deployments.has(relation.source.id),
|
|
308
|
+
`Relation "${relation.source.id} -> ${relation.target.id}" references non-existing source`,
|
|
309
|
+
)
|
|
310
|
+
invariant(
|
|
311
|
+
_deployments.has(relation.target.id),
|
|
312
|
+
`Relation "${relation.source.id} -> ${relation.target.id}" references non-existing target`,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
_deploymentRelations.push({
|
|
316
|
+
id: `deploy_rel${_deploymentRelations.length + 1}` as RelationId,
|
|
317
|
+
...relation,
|
|
318
|
+
})
|
|
319
|
+
return self
|
|
320
|
+
},
|
|
344
321
|
build: () => ({
|
|
345
322
|
specification: toLikeC4Specification(),
|
|
346
|
-
elements: fromEntries(
|
|
347
|
-
|
|
323
|
+
elements: fromEntries(
|
|
324
|
+
structuredClone(
|
|
325
|
+
Array.from(_elements.entries()),
|
|
326
|
+
),
|
|
327
|
+
),
|
|
328
|
+
relations: mapToObj(_relations, r => [r.id, structuredClone(r)]),
|
|
348
329
|
globals: structuredClone(_globals),
|
|
349
|
-
|
|
350
|
-
|
|
330
|
+
deployments: {
|
|
331
|
+
elements: fromEntries(
|
|
332
|
+
structuredClone(
|
|
333
|
+
Array.from(_deployments.entries()),
|
|
334
|
+
),
|
|
335
|
+
),
|
|
336
|
+
relations: mapToObj(_deploymentRelations, r => [r.id, structuredClone(r)]),
|
|
337
|
+
},
|
|
338
|
+
views: fromEntries(
|
|
339
|
+
structuredClone(
|
|
340
|
+
Array.from(_views.entries()),
|
|
341
|
+
),
|
|
342
|
+
),
|
|
343
|
+
} as any),
|
|
344
|
+
toLikeC4Model: () => {
|
|
345
|
+
const parsed = self.build()
|
|
346
|
+
return LikeC4Model.compute(parsed)
|
|
347
|
+
},
|
|
351
348
|
helpers: () => ({
|
|
352
349
|
model: {
|
|
353
350
|
model: (...ops: ((b: ModelBuilder<T>) => ModelBuilder<T>)[]) => {
|
|
354
351
|
return (b: Builder<T>) => {
|
|
355
|
-
|
|
356
|
-
for (const op of ops) {
|
|
357
|
-
op(v)
|
|
358
|
-
}
|
|
359
|
-
return b
|
|
352
|
+
return ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
|
|
360
353
|
}
|
|
361
354
|
},
|
|
362
355
|
rel: (source: string, target: string, _props?: T['NewRelationshipProps'] | string) => {
|
|
@@ -367,15 +360,15 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
367
360
|
...props
|
|
368
361
|
} = defu(
|
|
369
362
|
typeof _props === 'string' ? { title: _props } : { ..._props },
|
|
370
|
-
{ title: null, links: null }
|
|
363
|
+
{ title: null, links: null },
|
|
371
364
|
)
|
|
372
365
|
const links = mapLinks(_links)
|
|
373
|
-
b.
|
|
366
|
+
b.__addRelation({
|
|
374
367
|
source: source as any,
|
|
375
368
|
target: target as any,
|
|
376
369
|
title,
|
|
377
370
|
...(links && { links }),
|
|
378
|
-
...props
|
|
371
|
+
...props,
|
|
379
372
|
})
|
|
380
373
|
return b
|
|
381
374
|
}
|
|
@@ -388,14 +381,14 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
388
381
|
...props
|
|
389
382
|
} = defu(
|
|
390
383
|
typeof _props === 'string' ? { title: _props } : { ..._props },
|
|
391
|
-
{ title: null, links: null }
|
|
384
|
+
{ title: null, links: null },
|
|
392
385
|
)
|
|
393
386
|
const links = mapLinks(_links)
|
|
394
|
-
b.
|
|
387
|
+
b.__addSourcelessRelation({
|
|
395
388
|
target,
|
|
396
389
|
title,
|
|
397
390
|
...(links && { links }),
|
|
398
|
-
...props
|
|
391
|
+
...props,
|
|
399
392
|
})
|
|
400
393
|
return b
|
|
401
394
|
}
|
|
@@ -405,7 +398,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
405
398
|
({ style: specStyle, ...spec }, kind) =>
|
|
406
399
|
<Id extends string>(
|
|
407
400
|
id: Id,
|
|
408
|
-
_props?: T['NewElementProps'] | string
|
|
401
|
+
_props?: T['NewElementProps'] | string,
|
|
409
402
|
): AddElement<Id> => {
|
|
410
403
|
const add = (<T extends AnyTypes>(b: ModelBuilder<T>) => {
|
|
411
404
|
const {
|
|
@@ -420,9 +413,9 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
420
413
|
|
|
421
414
|
const icon = _icon ?? specStyle?.icon
|
|
422
415
|
|
|
423
|
-
const _id = b.
|
|
416
|
+
const _id = b.__fqn(id)
|
|
424
417
|
|
|
425
|
-
b.
|
|
418
|
+
b.__addElement({
|
|
426
419
|
id: _id,
|
|
427
420
|
kind: kind as any,
|
|
428
421
|
title: title ?? nameFromFqn(_id),
|
|
@@ -434,149 +427,322 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
434
427
|
style: pickBy({
|
|
435
428
|
border: specStyle?.border,
|
|
436
429
|
opacity: specStyle?.opacity,
|
|
437
|
-
...style
|
|
430
|
+
...style,
|
|
438
431
|
}, isNonNullish),
|
|
439
432
|
links,
|
|
440
433
|
...icon && { icon: icon as IconUrl },
|
|
441
434
|
...spec,
|
|
442
|
-
...props
|
|
435
|
+
...props,
|
|
443
436
|
})
|
|
444
437
|
return b
|
|
445
438
|
}) as AddElement<Id>
|
|
446
439
|
|
|
447
440
|
add.with = (...ops: Array<(input: ModelBuilder<any>) => ModelBuilder<any>>) => (b: ModelBuilder<any>) => {
|
|
448
441
|
add(b)
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
return b.
|
|
442
|
+
const { __fqn, __addSourcelessRelation } = b
|
|
443
|
+
try {
|
|
444
|
+
b.__fqn = (child) => `${__fqn(id)}.${child}` as Fqn
|
|
445
|
+
b.__addSourcelessRelation = (relation) => {
|
|
446
|
+
return b.__addRelation({
|
|
454
447
|
...relation,
|
|
455
|
-
source:
|
|
448
|
+
source: __fqn(id),
|
|
456
449
|
})
|
|
457
450
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
451
|
+
ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
|
|
452
|
+
} finally {
|
|
453
|
+
b.__fqn = __fqn
|
|
454
|
+
b.__addSourcelessRelation = __addSourcelessRelation
|
|
461
455
|
}
|
|
462
456
|
return b
|
|
463
457
|
}
|
|
458
|
+
|
|
464
459
|
return add
|
|
465
|
-
}
|
|
466
|
-
) as AddElementHelpers<T
|
|
460
|
+
},
|
|
461
|
+
) as AddElementHelpers<T>,
|
|
467
462
|
},
|
|
468
463
|
views: {
|
|
469
464
|
views: (...ops: ((b: ViewsBuilder<T>) => ViewsBuilder<T>)[]) => {
|
|
470
465
|
return (b: Builder<T>) => {
|
|
471
|
-
|
|
472
|
-
for (const op of ops) {
|
|
473
|
-
op(v)
|
|
474
|
-
}
|
|
475
|
-
return b
|
|
466
|
+
return ops.reduce((b, op) => op(b), b as any as ViewsBuilder<T>) as any
|
|
476
467
|
}
|
|
477
468
|
},
|
|
478
|
-
view: (
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
469
|
+
view: (
|
|
470
|
+
id: string,
|
|
471
|
+
_props?: T['NewViewProps'] | string | ElementViewRulesBuilder<any>,
|
|
472
|
+
_builder?: ElementViewRulesBuilder<any>,
|
|
473
|
+
) => {
|
|
474
|
+
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
475
|
+
const view: Writable<ElementView> = {
|
|
476
|
+
...generic,
|
|
477
|
+
__: 'element',
|
|
478
|
+
rules: [],
|
|
482
479
|
}
|
|
483
|
-
return <T extends AnyTypes>(b: ViewsBuilder<T>): ViewsBuilder<T> => {
|
|
484
|
-
const {
|
|
485
|
-
links: _links = [],
|
|
486
|
-
title = null,
|
|
487
|
-
...props
|
|
488
|
-
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
489
|
-
|
|
490
|
-
const links = mapLinks(_links)
|
|
491
|
-
|
|
492
|
-
const view: Writable<ElementView> = {
|
|
493
|
-
id: id as any,
|
|
494
|
-
__: 'element',
|
|
495
|
-
title,
|
|
496
|
-
description: null,
|
|
497
|
-
tags: null,
|
|
498
|
-
rules: [],
|
|
499
|
-
links,
|
|
500
|
-
customColorDefinitions: {},
|
|
501
|
-
...props
|
|
502
|
-
}
|
|
503
|
-
b.addView(view)
|
|
504
480
|
|
|
481
|
+
const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
|
|
482
|
+
b.__addView(view)
|
|
505
483
|
if (builder) {
|
|
506
484
|
builder(mkViewBuilder(view))
|
|
507
485
|
}
|
|
508
|
-
|
|
509
486
|
return b
|
|
510
487
|
}
|
|
488
|
+
add.with = (...ops: ElementViewRulesBuilder<any>[]) => (b: ViewsBuilder<any>) => {
|
|
489
|
+
add(b)
|
|
490
|
+
const elementViewBuilder = mkViewBuilder(view)
|
|
491
|
+
for (const op of ops) {
|
|
492
|
+
op(elementViewBuilder)
|
|
493
|
+
}
|
|
494
|
+
return b
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return add
|
|
511
498
|
},
|
|
512
499
|
viewOf: (
|
|
513
500
|
id,
|
|
514
|
-
viewOf,
|
|
515
|
-
_props?: T['NewViewProps'] | string |
|
|
516
|
-
|
|
501
|
+
viewOf: string,
|
|
502
|
+
_props?: T['NewViewProps'] | string | ElementViewRulesBuilder<any>,
|
|
503
|
+
_builder?: ElementViewRulesBuilder<any>,
|
|
517
504
|
) => {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
505
|
+
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
506
|
+
const view: Writable<ElementView> = {
|
|
507
|
+
...generic,
|
|
508
|
+
viewOf: viewOf as Fqn,
|
|
509
|
+
__: 'element',
|
|
510
|
+
rules: [],
|
|
521
511
|
}
|
|
522
|
-
return <T extends AnyTypes>(b: ViewsBuilder<T>): ViewsBuilder<T> => {
|
|
523
|
-
const {
|
|
524
|
-
links: _links = [],
|
|
525
|
-
title = null,
|
|
526
|
-
...props
|
|
527
|
-
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
528
512
|
|
|
529
|
-
|
|
513
|
+
const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
|
|
514
|
+
b.__addView(view)
|
|
515
|
+
if (builder) {
|
|
516
|
+
builder(mkViewBuilder(view))
|
|
517
|
+
}
|
|
518
|
+
return b
|
|
519
|
+
}
|
|
530
520
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
description: null,
|
|
537
|
-
tags: null,
|
|
538
|
-
rules: [],
|
|
539
|
-
links,
|
|
540
|
-
customColorDefinitions: {},
|
|
541
|
-
...props
|
|
521
|
+
add.with = (...ops: ElementViewRulesBuilder<any>[]) => (b: ViewsBuilder<any>) => {
|
|
522
|
+
add(b)
|
|
523
|
+
const elementViewBuilder = mkViewBuilder(view)
|
|
524
|
+
for (const op of ops) {
|
|
525
|
+
op(elementViewBuilder)
|
|
542
526
|
}
|
|
543
|
-
b
|
|
527
|
+
return b
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return add
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
deploymentView: (
|
|
534
|
+
id: string,
|
|
535
|
+
_props?: T['NewViewProps'] | string | DeploymentRulesBuilderOp<any>,
|
|
536
|
+
_builder?: DeploymentRulesBuilderOp<any>,
|
|
537
|
+
) => {
|
|
538
|
+
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
539
|
+
const view: Writable<DeploymentView> = {
|
|
540
|
+
...generic,
|
|
541
|
+
__: 'deployment',
|
|
542
|
+
rules: [],
|
|
543
|
+
}
|
|
544
544
|
|
|
545
|
+
const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
|
|
546
|
+
b.__addView(view)
|
|
545
547
|
if (builder) {
|
|
546
548
|
builder(mkViewBuilder(view))
|
|
547
549
|
}
|
|
550
|
+
return b
|
|
551
|
+
}
|
|
548
552
|
|
|
553
|
+
add.with = (...ops: DeploymentRulesBuilderOp<any>[]) => (b: ViewsBuilder<any>) => {
|
|
554
|
+
add(b)
|
|
555
|
+
const elementViewBuilder = mkViewBuilder(view)
|
|
556
|
+
for (const op of ops) {
|
|
557
|
+
op(elementViewBuilder)
|
|
558
|
+
}
|
|
549
559
|
return b
|
|
550
560
|
}
|
|
561
|
+
|
|
562
|
+
return add
|
|
551
563
|
},
|
|
552
564
|
$autoLayout,
|
|
553
565
|
$exclude,
|
|
554
|
-
$expr,
|
|
555
566
|
$include,
|
|
556
567
|
$rules,
|
|
557
|
-
$style
|
|
558
|
-
}
|
|
568
|
+
$style,
|
|
569
|
+
},
|
|
570
|
+
deployment: {
|
|
571
|
+
deployment: (...ops: ((b: DeploymentModelBuilder<T>) => DeploymentModelBuilder<T>)[]) => {
|
|
572
|
+
return (b: Builder<T>) => {
|
|
573
|
+
return ops.reduce((b, op) => op(b), b as any as DeploymentModelBuilder<T>) as any
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
instanceOf: (
|
|
577
|
+
id: string,
|
|
578
|
+
target?: string | T['NewDeploymentNodeProps'],
|
|
579
|
+
_props?: string | T['NewDeploymentNodeProps'],
|
|
580
|
+
) => {
|
|
581
|
+
return <T extends AnyTypes>(
|
|
582
|
+
b: DeploymentModelBuilder<T>,
|
|
583
|
+
): DeploymentModelBuilder<Types.AddDeploymentFqn<T, any>> => {
|
|
584
|
+
if (isNullish(target)) {
|
|
585
|
+
target = id
|
|
586
|
+
id = nameFromFqn(id)
|
|
587
|
+
} else if (typeof target === 'string') {
|
|
588
|
+
_props ??= {}
|
|
589
|
+
} else {
|
|
590
|
+
_props = target
|
|
591
|
+
target = id
|
|
592
|
+
id = nameFromFqn(id)
|
|
593
|
+
}
|
|
594
|
+
const {
|
|
595
|
+
links,
|
|
596
|
+
title,
|
|
597
|
+
...props
|
|
598
|
+
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
599
|
+
const _id = b.__fqn(id)
|
|
600
|
+
invariant(_elements.has(target), `Target element with id "${target}" not found`)
|
|
601
|
+
b.__addDeployment({
|
|
602
|
+
id: _id,
|
|
603
|
+
element: target as any,
|
|
604
|
+
...title && { title },
|
|
605
|
+
...links && { links: mapLinks(links) },
|
|
606
|
+
...props,
|
|
607
|
+
})
|
|
608
|
+
return b as any
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
rel: (source: string, target: string, _props?: T['NewRelationshipProps'] | string) => {
|
|
612
|
+
return <T extends AnyTypes>(b: DeploymentModelBuilder<T>) => {
|
|
613
|
+
const {
|
|
614
|
+
title,
|
|
615
|
+
links,
|
|
616
|
+
...props
|
|
617
|
+
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
618
|
+
|
|
619
|
+
b.__addDeploymentRelation({
|
|
620
|
+
source: {
|
|
621
|
+
id: source as any,
|
|
622
|
+
},
|
|
623
|
+
target: {
|
|
624
|
+
id: target as any,
|
|
625
|
+
},
|
|
626
|
+
...title && { title },
|
|
627
|
+
...links && { links: mapLinks(links) },
|
|
628
|
+
...props,
|
|
629
|
+
})
|
|
630
|
+
return b
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
...mapValues(
|
|
634
|
+
spec.deployments ?? {},
|
|
635
|
+
({ style: specStyle, ...spec }, kind) =>
|
|
636
|
+
<Id extends string>(
|
|
637
|
+
id: Id,
|
|
638
|
+
_props?: T['NewDeploymentNodeProps'] | string,
|
|
639
|
+
): AddDeploymentNode<Id> => {
|
|
640
|
+
const add = (<T extends AnyTypes>(b: DeploymentModelBuilder<T>) => {
|
|
641
|
+
const {
|
|
642
|
+
links,
|
|
643
|
+
icon: _icon,
|
|
644
|
+
style,
|
|
645
|
+
title,
|
|
646
|
+
...props
|
|
647
|
+
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
648
|
+
|
|
649
|
+
const icon = _icon ?? specStyle?.icon
|
|
650
|
+
|
|
651
|
+
const _id = b.__fqn(id)
|
|
652
|
+
|
|
653
|
+
b.__addDeployment({
|
|
654
|
+
id: _id,
|
|
655
|
+
kind: kind as any,
|
|
656
|
+
title: title ?? nameFromFqn(_id),
|
|
657
|
+
description: null,
|
|
658
|
+
technology: null,
|
|
659
|
+
tags: null,
|
|
660
|
+
color: specStyle?.color ?? DefaultThemeColor as Color,
|
|
661
|
+
shape: specStyle?.shape ?? DefaultElementShape as ElementShape,
|
|
662
|
+
style: pickBy({
|
|
663
|
+
border: specStyle?.border,
|
|
664
|
+
opacity: specStyle?.opacity,
|
|
665
|
+
...style,
|
|
666
|
+
}, isNonNullish),
|
|
667
|
+
...links && { links: mapLinks(links) },
|
|
668
|
+
...icon && { icon: icon as IconUrl },
|
|
669
|
+
...spec,
|
|
670
|
+
...props,
|
|
671
|
+
})
|
|
672
|
+
return b
|
|
673
|
+
}) as AddDeploymentNode<Id>
|
|
674
|
+
|
|
675
|
+
add.with =
|
|
676
|
+
(...ops: Array<(input: DeploymentModelBuilder<any>) => DeploymentModelBuilder<any>>) =>
|
|
677
|
+
(b: DeploymentModelBuilder<any>) => {
|
|
678
|
+
add(b)
|
|
679
|
+
const { __fqn } = b
|
|
680
|
+
try {
|
|
681
|
+
b.__fqn = (child) => `${__fqn(id)}.${child}` as Fqn
|
|
682
|
+
ops.reduce((b, op) => op(b), b as any as DeploymentModelBuilder<T>) as any
|
|
683
|
+
} finally {
|
|
684
|
+
b.__fqn = __fqn
|
|
685
|
+
}
|
|
686
|
+
return b
|
|
687
|
+
}
|
|
688
|
+
return add
|
|
689
|
+
},
|
|
690
|
+
) as AddDeploymentNodeHelpers<T>,
|
|
691
|
+
},
|
|
692
|
+
} as {
|
|
693
|
+
model: ModelHelpers<T>
|
|
694
|
+
views: ViewsHelpers
|
|
695
|
+
deployment: DeloymentModelHelpers<T>
|
|
559
696
|
}),
|
|
560
697
|
with: (...ops: ((b: Builder<T>) => Builder<T>)[]) => {
|
|
561
|
-
return ops.reduce((b, op) => op(b), self).clone()
|
|
562
|
-
}
|
|
698
|
+
return ops.reduce((b, op) => op(b), self as Builder<T>).clone()
|
|
699
|
+
},
|
|
700
|
+
model: <Out extends AnyTypes>(cb: ModelBuilderFunction<T, Out>) => {
|
|
701
|
+
const b = self.clone()
|
|
702
|
+
const helpers = b.helpers().model
|
|
703
|
+
const _ = helpers.model as any
|
|
704
|
+
return cb({ ...helpers, _ }, _)(b as Internals<T>) as any
|
|
705
|
+
},
|
|
706
|
+
deployment: <Out extends AnyTypes>(cb: DeloymentModelBuildFunction<T, Out>) => {
|
|
707
|
+
const b = self.clone()
|
|
708
|
+
const helpers = b.helpers().deployment
|
|
709
|
+
const _ = helpers.deployment as any
|
|
710
|
+
return cb({ ...helpers, _ }, _)(b as Internals<T>) as any
|
|
711
|
+
},
|
|
712
|
+
views: <Out extends AnyTypes>(cb: ViewsBuilderFunction<T, Out>) => {
|
|
713
|
+
const b = self.clone()
|
|
714
|
+
const helpers = b.helpers().views
|
|
715
|
+
return cb({
|
|
716
|
+
...helpers,
|
|
717
|
+
_: helpers.views as any,
|
|
718
|
+
} as any, helpers.views as any)(b as Internals<T>) as any
|
|
719
|
+
},
|
|
563
720
|
}
|
|
564
721
|
|
|
565
722
|
return self
|
|
566
723
|
}
|
|
567
724
|
|
|
568
725
|
export namespace Builder {
|
|
726
|
+
export type Any = Builder<AnyTypes>
|
|
727
|
+
|
|
569
728
|
export function forSpecification<const Spec extends BuilderSpecification>(
|
|
570
|
-
spec: Spec
|
|
729
|
+
spec: Spec,
|
|
571
730
|
): {
|
|
572
731
|
builder: Builder<Types.FromSpecification<Spec>>
|
|
573
732
|
model: ModelHelpers<Types.FromSpecification<Spec>>
|
|
574
|
-
|
|
733
|
+
deployment: DeloymentModelHelpers<Types.FromSpecification<Spec>>
|
|
734
|
+
views: ViewsHelpers
|
|
575
735
|
} {
|
|
576
736
|
const b = builder<Spec, Types.FromSpecification<Spec>>(spec)
|
|
577
737
|
return {
|
|
578
738
|
...b.helpers(),
|
|
579
|
-
builder: b
|
|
739
|
+
builder: b,
|
|
580
740
|
}
|
|
581
741
|
}
|
|
742
|
+
|
|
743
|
+
export function specification<const Spec extends BuilderSpecification>(
|
|
744
|
+
spec: Spec,
|
|
745
|
+
): Builder<Types.FromSpecification<Spec>> {
|
|
746
|
+
return builder<Spec, Types.FromSpecification<Spec>>(spec)
|
|
747
|
+
}
|
|
582
748
|
}
|