@likec4/core 1.31.0 → 1.32.1
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.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.DXzRBkuI.d.mts +1264 -0
- package/dist/shared/core.DoK86JEe.mjs +518 -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/shared/core.znRaUX_A.d.mts +920 -0
- 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 +16 -8
- 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/{theme.ts → styles.ts} +55 -15
- 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/view-notation.ts +0 -9
- package/src/utils/graphlib.ts +0 -10
- /package/src/{errors/index.ts → utils/invariant.ts} +0 -0
package/src/builder/Builder.ts
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import defu from 'defu'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
entries,
|
|
4
|
+
fromEntries,
|
|
5
|
+
hasAtLeast,
|
|
6
|
+
isFunction,
|
|
7
|
+
isNonNullish,
|
|
8
|
+
isNullish,
|
|
9
|
+
map,
|
|
10
|
+
mapToObj,
|
|
11
|
+
mapValues,
|
|
12
|
+
pickBy,
|
|
13
|
+
} from 'remeda'
|
|
3
14
|
import type { Writable } from 'type-fest'
|
|
4
|
-
import {
|
|
15
|
+
import { computeLikeC4Model } from '../compute-view/compute-view'
|
|
5
16
|
import { LikeC4Model } from '../model/LikeC4Model'
|
|
17
|
+
import type {
|
|
18
|
+
Any,
|
|
19
|
+
DeployedInstance,
|
|
20
|
+
DeploymentFqn,
|
|
21
|
+
ParsedElementView,
|
|
22
|
+
ParsedLikeC4ModelData,
|
|
23
|
+
Specification,
|
|
24
|
+
} from '../types'
|
|
6
25
|
import {
|
|
7
26
|
type Color,
|
|
27
|
+
type DeploymentElement,
|
|
8
28
|
type DeploymentRelation,
|
|
9
|
-
type DeploymentView,
|
|
10
29
|
type Element,
|
|
11
30
|
type ElementShape,
|
|
12
|
-
type ElementView,
|
|
13
31
|
type Fqn,
|
|
14
32
|
type IconUrl,
|
|
15
33
|
type LikeC4View,
|
|
@@ -17,13 +35,17 @@ import {
|
|
|
17
35
|
type ModelGlobals,
|
|
18
36
|
type ModelRelation,
|
|
19
37
|
type NonEmptyArray,
|
|
38
|
+
type ParsedDeploymentView as DeploymentView,
|
|
20
39
|
type RelationId,
|
|
21
|
-
|
|
40
|
+
_stage,
|
|
41
|
+
_type,
|
|
22
42
|
DefaultElementShape,
|
|
23
43
|
DefaultThemeColor,
|
|
24
|
-
|
|
25
|
-
|
|
44
|
+
FqnRef,
|
|
45
|
+
isDeployedInstance,
|
|
46
|
+
isElementView,
|
|
26
47
|
} from '../types'
|
|
48
|
+
import { invariant } from '../utils'
|
|
27
49
|
import { isSameHierarchy, nameFromFqn, parentFqn } from '../utils/fqn'
|
|
28
50
|
import type { AnyTypes, BuilderSpecification, Types } from './_types'
|
|
29
51
|
import type { AddDeploymentNode } from './Builder.deployment'
|
|
@@ -97,10 +119,11 @@ export interface Builder<T extends AnyTypes> extends BuilderMethods<T> {
|
|
|
97
119
|
* )
|
|
98
120
|
* )
|
|
99
121
|
*
|
|
122
|
+
* @example
|
|
100
123
|
* builder.deployment((_,d) =>
|
|
101
124
|
* d(
|
|
102
125
|
* _.node('node1'),
|
|
103
|
-
*
|
|
126
|
+
* _.node('node1.child1').with(
|
|
104
127
|
* _.instanceOf('model.element')
|
|
105
128
|
* )
|
|
106
129
|
* )
|
|
@@ -114,11 +137,34 @@ export interface Builder<T extends AnyTypes> extends BuilderMethods<T> {
|
|
|
114
137
|
* Adds views
|
|
115
138
|
*
|
|
116
139
|
* @example
|
|
117
|
-
* builder.views(({ view, $include }, _) =>
|
|
140
|
+
* builder.views(({ view, viewOf, deploymentView, $include, $style, $rules }, _) =>
|
|
118
141
|
* _(
|
|
119
|
-
* view('
|
|
142
|
+
* view('view1').with(
|
|
143
|
+
* $include('a -> b'),
|
|
144
|
+
* ),
|
|
145
|
+
* view('view2', {
|
|
146
|
+
* title: 'View 2',
|
|
147
|
+
* }).with(
|
|
148
|
+
* $include('*')
|
|
149
|
+
* ),
|
|
150
|
+
* view(
|
|
151
|
+
* 'view3',
|
|
152
|
+
* {
|
|
153
|
+
* title: 'View 3',
|
|
154
|
+
* },
|
|
155
|
+
* $rules(
|
|
156
|
+
* $include('*'),
|
|
157
|
+
* $style(['*', 'alice'], {
|
|
158
|
+
* color: 'red',
|
|
159
|
+
* }),
|
|
160
|
+
* ),
|
|
161
|
+
* ),
|
|
162
|
+
* viewOf('viewOfA', 'a').with(
|
|
163
|
+
* $include('*')
|
|
164
|
+
* ),
|
|
165
|
+
* deploymentView('deploymentView1').with(
|
|
120
166
|
* $include('a -> b')
|
|
121
|
-
* )
|
|
167
|
+
* ),
|
|
122
168
|
* )
|
|
123
169
|
* )
|
|
124
170
|
*/
|
|
@@ -131,12 +177,12 @@ export interface Builder<T extends AnyTypes> extends BuilderMethods<T> {
|
|
|
131
177
|
* Views are not computed or layouted
|
|
132
178
|
* {@link toLikeC4Model} should be used to get model with computed views
|
|
133
179
|
*/
|
|
134
|
-
build(): Types.
|
|
180
|
+
build(): ParsedLikeC4ModelData<Types.ToAux<T>>
|
|
135
181
|
|
|
136
182
|
/**
|
|
137
|
-
* Returns LikeC4Model
|
|
183
|
+
* Returns Computed LikeC4Model
|
|
138
184
|
*/
|
|
139
|
-
toLikeC4Model(): Types.
|
|
185
|
+
toLikeC4Model(): LikeC4Model.Computed<Types.ToAux<T>>
|
|
140
186
|
}
|
|
141
187
|
|
|
142
188
|
interface Internals<T extends AnyTypes> extends ViewsBuilder<T>, ModelBuilder<T>, DeploymentModelBuilder<T> {
|
|
@@ -144,9 +190,31 @@ interface Internals<T extends AnyTypes> extends ViewsBuilder<T>, ModelBuilder<T>
|
|
|
144
190
|
|
|
145
191
|
type Op<T> = (b: T) => T
|
|
146
192
|
|
|
193
|
+
function validateSpec(specification: BuilderSpecification) {
|
|
194
|
+
for (const [kind, spec] of entries(specification.elements)) {
|
|
195
|
+
if (spec.tags) {
|
|
196
|
+
for (const tag of spec.tags) {
|
|
197
|
+
invariant(specification.tags?.[tag], `Invalid specification for element kind "${kind}": tag "${tag}" not found`)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (specification.deployments) {
|
|
202
|
+
for (const [kind, spec] of entries(specification.deployments)) {
|
|
203
|
+
if (spec.tags) {
|
|
204
|
+
for (const tag of spec.tags) {
|
|
205
|
+
invariant(
|
|
206
|
+
specification.tags?.[tag],
|
|
207
|
+
`Invalid specification for deployment kind "${kind}": tag "${tag}" not found`,
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
147
215
|
function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
148
216
|
spec: Spec,
|
|
149
|
-
_elements = new Map<string, Element
|
|
217
|
+
_elements = new Map<string, Element<Any>>(),
|
|
150
218
|
_relations = [] as ModelRelation[],
|
|
151
219
|
_views = new Map<string, LikeC4View>(),
|
|
152
220
|
_globals = {
|
|
@@ -157,18 +225,26 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
157
225
|
_deployments = new Map<string, DeploymentElement>(),
|
|
158
226
|
_deploymentRelations = [] as DeploymentRelation[],
|
|
159
227
|
): Builder<T> {
|
|
160
|
-
const toLikeC4Specification = (): Types.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
228
|
+
const toLikeC4Specification = (): Specification<Types.ToAux<T>> => {
|
|
229
|
+
validateSpec(spec)
|
|
230
|
+
return ({
|
|
231
|
+
elements: {
|
|
232
|
+
...structuredClone(spec.elements) as any,
|
|
233
|
+
},
|
|
234
|
+
deployments: {
|
|
235
|
+
...structuredClone(spec.deployments) as any,
|
|
236
|
+
},
|
|
237
|
+
relationships: {
|
|
238
|
+
...structuredClone(spec.relationships) as any,
|
|
239
|
+
},
|
|
240
|
+
tags: mapValues(spec.tags ?? {}, (tagSpec) => ({
|
|
241
|
+
color: DefaultThemeColor,
|
|
242
|
+
...tagSpec,
|
|
243
|
+
})) as any,
|
|
244
|
+
...(!!spec.metadataKeys ? { metadataKeys: spec.metadataKeys as any } : {}),
|
|
245
|
+
customColors: {},
|
|
246
|
+
} as Specification<Types.ToAux<T>>)
|
|
247
|
+
}
|
|
172
248
|
|
|
173
249
|
const mapLinks = (links?: Array<string | { title?: string; url: string }>): NonEmptyArray<Link> | null => {
|
|
174
250
|
if (!links || !hasAtLeast(links, 1)) {
|
|
@@ -181,7 +257,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
181
257
|
id: string,
|
|
182
258
|
_props: T['NewViewProps'] | string | B | null,
|
|
183
259
|
builder: B,
|
|
184
|
-
): [Omit<LikeC4View, 'rules'>, B] => {
|
|
260
|
+
): [Omit<LikeC4View, 'rules' | '_type'>, B] => {
|
|
185
261
|
if (isFunction(_props)) {
|
|
186
262
|
builder = _props as B
|
|
187
263
|
_props = {}
|
|
@@ -191,7 +267,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
191
267
|
links: _links = [],
|
|
192
268
|
title = null,
|
|
193
269
|
description = null,
|
|
194
|
-
tags =
|
|
270
|
+
tags = [],
|
|
195
271
|
...props
|
|
196
272
|
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
197
273
|
|
|
@@ -202,7 +278,8 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
202
278
|
description,
|
|
203
279
|
tags,
|
|
204
280
|
links,
|
|
205
|
-
|
|
281
|
+
_stage: 'parsed',
|
|
282
|
+
// customColorDefinitions: {},
|
|
206
283
|
...props,
|
|
207
284
|
}, builder]
|
|
208
285
|
}
|
|
@@ -238,9 +315,9 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
238
315
|
return self
|
|
239
316
|
},
|
|
240
317
|
__addRelation(relation) {
|
|
241
|
-
const sourceEl = _elements.get(relation.source)
|
|
318
|
+
const sourceEl = _elements.get(FqnRef.flatten(relation.source))
|
|
242
319
|
invariant(sourceEl, `Element with id "${relation.source}" not found`)
|
|
243
|
-
const targetEl = _elements.get(relation.target)
|
|
320
|
+
const targetEl = _elements.get(FqnRef.flatten(relation.target))
|
|
244
321
|
invariant(targetEl, `Element with id "${relation.target}" not found`)
|
|
245
322
|
invariant(
|
|
246
323
|
!isSameHierarchy(sourceEl, targetEl),
|
|
@@ -252,13 +329,14 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
252
329
|
})
|
|
253
330
|
return self
|
|
254
331
|
},
|
|
255
|
-
/**
|
|
256
|
-
* Fully qualified name for nested elements
|
|
257
|
-
*/
|
|
258
332
|
__fqn(id) {
|
|
259
333
|
invariant(id.trim() !== '', 'Id must be non-empty')
|
|
260
334
|
return id as Fqn
|
|
261
335
|
},
|
|
336
|
+
__deploymentFqn(id) {
|
|
337
|
+
invariant(id.trim() !== '', 'Id must be non-empty')
|
|
338
|
+
return id as DeploymentFqn
|
|
339
|
+
},
|
|
262
340
|
__addSourcelessRelation() {
|
|
263
341
|
throw new Error('Can be called only in nested model')
|
|
264
342
|
},
|
|
@@ -266,7 +344,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
266
344
|
if (_views.has(view.id)) {
|
|
267
345
|
throw new Error(`View with id "${view.id}" already exists`)
|
|
268
346
|
}
|
|
269
|
-
if (
|
|
347
|
+
if (isElementView(view) && 'viewOf' in view) {
|
|
270
348
|
invariant(
|
|
271
349
|
_elements.get(view.viewOf),
|
|
272
350
|
`Invalid scoped view ${view.id}, wlement with id "${view.viewOf}" not found`,
|
|
@@ -287,7 +365,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
287
365
|
`Parent element with id "${parent}" not found for node with id "${node.id}"`,
|
|
288
366
|
)
|
|
289
367
|
}
|
|
290
|
-
if (
|
|
368
|
+
if (isDeployedInstance(node)) {
|
|
291
369
|
invariant(parent, `Instance ${node.id} of ${node.element} must be deployed under a parent node`)
|
|
292
370
|
invariant(
|
|
293
371
|
_elements.get(node.element),
|
|
@@ -299,17 +377,17 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
299
377
|
},
|
|
300
378
|
__addDeploymentRelation: (relation) => {
|
|
301
379
|
invariant(
|
|
302
|
-
!isSameHierarchy(relation.source.
|
|
380
|
+
!isSameHierarchy(relation.source.deployment, relation.target.deployment),
|
|
303
381
|
'Cannot create relationship between elements in the same hierarchy',
|
|
304
382
|
)
|
|
305
383
|
|
|
306
384
|
invariant(
|
|
307
|
-
_deployments.has(relation.source.
|
|
308
|
-
`Relation "${relation.source.
|
|
385
|
+
_deployments.has(relation.source.deployment),
|
|
386
|
+
`Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing source`,
|
|
309
387
|
)
|
|
310
388
|
invariant(
|
|
311
|
-
_deployments.has(relation.target.
|
|
312
|
-
`Relation "${relation.source.
|
|
389
|
+
_deployments.has(relation.target.deployment),
|
|
390
|
+
`Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing target`,
|
|
313
391
|
)
|
|
314
392
|
|
|
315
393
|
_deploymentRelations.push({
|
|
@@ -319,6 +397,8 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
319
397
|
return self
|
|
320
398
|
},
|
|
321
399
|
build: () => ({
|
|
400
|
+
[_stage]: 'parsed',
|
|
401
|
+
projectId: 'from-builder',
|
|
322
402
|
specification: toLikeC4Specification(),
|
|
323
403
|
elements: fromEntries(
|
|
324
404
|
structuredClone(
|
|
@@ -344,7 +424,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
344
424
|
} as any),
|
|
345
425
|
toLikeC4Model: () => {
|
|
346
426
|
const parsed = self.build()
|
|
347
|
-
return
|
|
427
|
+
return computeLikeC4Model(parsed)
|
|
348
428
|
},
|
|
349
429
|
helpers: () => ({
|
|
350
430
|
model: {
|
|
@@ -353,7 +433,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
353
433
|
return ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
|
|
354
434
|
}
|
|
355
435
|
},
|
|
356
|
-
rel: (source
|
|
436
|
+
rel: (source, target, _props?) => {
|
|
357
437
|
return <T extends AnyTypes>(b: ModelBuilder<T>) => {
|
|
358
438
|
const {
|
|
359
439
|
title = '',
|
|
@@ -365,8 +445,12 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
365
445
|
)
|
|
366
446
|
const links = mapLinks(_links)
|
|
367
447
|
b.__addRelation({
|
|
368
|
-
source:
|
|
369
|
-
|
|
448
|
+
source: {
|
|
449
|
+
model: source,
|
|
450
|
+
},
|
|
451
|
+
target: {
|
|
452
|
+
model: target,
|
|
453
|
+
},
|
|
370
454
|
title,
|
|
371
455
|
...(links && { links }),
|
|
372
456
|
...props,
|
|
@@ -386,7 +470,9 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
386
470
|
)
|
|
387
471
|
const links = mapLinks(_links)
|
|
388
472
|
b.__addSourcelessRelation({
|
|
389
|
-
target
|
|
473
|
+
target: {
|
|
474
|
+
model: target,
|
|
475
|
+
},
|
|
390
476
|
title,
|
|
391
477
|
...(links && { links }),
|
|
392
478
|
...props,
|
|
@@ -422,7 +508,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
422
508
|
title: title ?? nameFromFqn(_id),
|
|
423
509
|
description: null,
|
|
424
510
|
technology: null,
|
|
425
|
-
tags:
|
|
511
|
+
tags: [],
|
|
426
512
|
color: specStyle?.color ?? DefaultThemeColor as Color,
|
|
427
513
|
shape: specStyle?.shape ?? DefaultElementShape as ElementShape,
|
|
428
514
|
style: pickBy({
|
|
@@ -449,7 +535,9 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
449
535
|
b.__addSourcelessRelation = (relation) => {
|
|
450
536
|
return b.__addRelation({
|
|
451
537
|
...relation,
|
|
452
|
-
source:
|
|
538
|
+
source: {
|
|
539
|
+
model: __fqn(id),
|
|
540
|
+
},
|
|
453
541
|
})
|
|
454
542
|
}
|
|
455
543
|
ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
|
|
@@ -476,9 +564,9 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
476
564
|
_builder?: ElementViewRulesBuilder<any>,
|
|
477
565
|
) => {
|
|
478
566
|
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
479
|
-
const view: Writable<
|
|
567
|
+
const view: Writable<ParsedElementView> = {
|
|
480
568
|
...generic,
|
|
481
|
-
|
|
569
|
+
[_type]: 'element',
|
|
482
570
|
rules: [],
|
|
483
571
|
}
|
|
484
572
|
|
|
@@ -507,10 +595,10 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
507
595
|
_builder?: ElementViewRulesBuilder<any>,
|
|
508
596
|
) => {
|
|
509
597
|
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
510
|
-
const view: Writable<
|
|
598
|
+
const view: Writable<ParsedElementView> = {
|
|
511
599
|
...generic,
|
|
512
600
|
viewOf: viewOf as Fqn,
|
|
513
|
-
|
|
601
|
+
[_type]: 'element',
|
|
514
602
|
rules: [],
|
|
515
603
|
}
|
|
516
604
|
|
|
@@ -542,7 +630,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
542
630
|
const [generic, builder] = createGenericView(id, _props, _builder)
|
|
543
631
|
const view: Writable<DeploymentView> = {
|
|
544
632
|
...generic,
|
|
545
|
-
|
|
633
|
+
[_type]: 'deployment',
|
|
546
634
|
rules: [],
|
|
547
635
|
}
|
|
548
636
|
|
|
@@ -600,34 +688,34 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
600
688
|
title,
|
|
601
689
|
...props
|
|
602
690
|
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
603
|
-
const _id = b.
|
|
691
|
+
const _id = b.__deploymentFqn(id)
|
|
604
692
|
invariant(_elements.has(target), `Target element with id "${target}" not found`)
|
|
605
693
|
b.__addDeployment({
|
|
606
694
|
id: _id,
|
|
607
|
-
element: target as
|
|
695
|
+
element: target as Fqn,
|
|
608
696
|
...title && { title },
|
|
609
697
|
...links && { links: mapLinks(links) },
|
|
610
698
|
...props,
|
|
611
|
-
})
|
|
699
|
+
} as DeployedInstance)
|
|
612
700
|
return b as any
|
|
613
701
|
}
|
|
614
702
|
},
|
|
615
703
|
rel: (source: string, target: string, _props?: T['NewRelationshipProps'] | string) => {
|
|
616
704
|
return <T extends AnyTypes>(b: DeploymentModelBuilder<T>) => {
|
|
617
705
|
const {
|
|
618
|
-
title,
|
|
706
|
+
title = null,
|
|
619
707
|
links,
|
|
620
708
|
...props
|
|
621
709
|
} = typeof _props === 'string' ? { title: _props } : { ..._props }
|
|
622
710
|
|
|
623
711
|
b.__addDeploymentRelation({
|
|
624
712
|
source: {
|
|
625
|
-
|
|
713
|
+
deployment: source as any,
|
|
626
714
|
},
|
|
627
715
|
target: {
|
|
628
|
-
|
|
716
|
+
deployment: target as any,
|
|
629
717
|
},
|
|
630
|
-
|
|
718
|
+
title,
|
|
631
719
|
...links && { links: mapLinks(links) },
|
|
632
720
|
...props,
|
|
633
721
|
})
|
|
@@ -652,7 +740,7 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
652
740
|
|
|
653
741
|
const icon = _icon ?? specStyle?.icon
|
|
654
742
|
|
|
655
|
-
const _id = b.
|
|
743
|
+
const _id = b.__deploymentFqn(id)
|
|
656
744
|
|
|
657
745
|
b.__addDeployment({
|
|
658
746
|
id: _id,
|
|
@@ -661,18 +749,20 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
661
749
|
description: null,
|
|
662
750
|
technology: null,
|
|
663
751
|
tags: null,
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
752
|
+
style: {
|
|
753
|
+
...icon && { icon: icon as IconUrl },
|
|
754
|
+
color: specStyle?.color ?? DefaultThemeColor as Color,
|
|
755
|
+
shape: specStyle?.shape ?? DefaultElementShape as ElementShape,
|
|
756
|
+
...pickBy({
|
|
757
|
+
border: specStyle?.border,
|
|
758
|
+
opacity: specStyle?.opacity,
|
|
759
|
+
size: specStyle?.size,
|
|
760
|
+
padding: specStyle?.padding,
|
|
761
|
+
textSize: specStyle?.textSize,
|
|
762
|
+
...style,
|
|
763
|
+
}, isNonNullish),
|
|
764
|
+
},
|
|
674
765
|
...links && { links: mapLinks(links) },
|
|
675
|
-
...icon && { icon: icon as IconUrl },
|
|
676
766
|
...spec,
|
|
677
767
|
...props,
|
|
678
768
|
})
|
|
@@ -683,12 +773,12 @@ function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
|
|
|
683
773
|
(...ops: Array<(input: DeploymentModelBuilder<any>) => DeploymentModelBuilder<any>>) =>
|
|
684
774
|
(b: DeploymentModelBuilder<any>) => {
|
|
685
775
|
add(b)
|
|
686
|
-
const {
|
|
776
|
+
const { __deploymentFqn } = b
|
|
687
777
|
try {
|
|
688
|
-
b.
|
|
778
|
+
b.__deploymentFqn = (child) => `${__deploymentFqn(id)}.${child}` as DeploymentFqn
|
|
689
779
|
ops.reduce((b, op) => op(b), b as any as DeploymentModelBuilder<T>) as any
|
|
690
780
|
} finally {
|
|
691
|
-
b.
|
|
781
|
+
b.__deploymentFqn = __deploymentFqn
|
|
692
782
|
}
|
|
693
783
|
return b
|
|
694
784
|
}
|
|
@@ -740,6 +830,7 @@ export namespace Builder {
|
|
|
740
830
|
deployment: DeloymentModelHelpers<Types.FromSpecification<Spec>>
|
|
741
831
|
views: ViewsHelpers
|
|
742
832
|
} {
|
|
833
|
+
validateSpec(spec)
|
|
743
834
|
const b = builder<Spec, Types.FromSpecification<Spec>>(spec)
|
|
744
835
|
return {
|
|
745
836
|
...b.helpers(),
|
|
@@ -750,6 +841,7 @@ export namespace Builder {
|
|
|
750
841
|
export function specification<const Spec extends BuilderSpecification>(
|
|
751
842
|
spec: Spec,
|
|
752
843
|
): Builder<Types.FromSpecification<Spec>> {
|
|
844
|
+
validateSpec(spec)
|
|
753
845
|
return builder<Spec, Types.FromSpecification<Spec>>(spec)
|
|
754
846
|
}
|
|
755
847
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { isArray, isString, map } from 'remeda'
|
|
2
2
|
import type { LiteralUnion, Simplify } from 'type-fest'
|
|
3
3
|
import {
|
|
4
|
+
type Any,
|
|
5
|
+
type AnyAux,
|
|
6
|
+
type AnyViewRuleStyle as ViewRuleStyle,
|
|
4
7
|
type AutoLayoutDirection,
|
|
5
|
-
type
|
|
8
|
+
type Expression,
|
|
9
|
+
type ModelRelationExpr,
|
|
6
10
|
type NonEmptyArray,
|
|
7
|
-
type ViewRuleStyle,
|
|
8
11
|
type WhereOperator,
|
|
12
|
+
ModelFqnExpr,
|
|
9
13
|
} from '../types'
|
|
10
|
-
import {
|
|
11
|
-
import type { KindEqual, Participant, TagEqual } from '../types/operators'
|
|
14
|
+
import type { Participant, ParticipantOperator } from '../types/operators'
|
|
12
15
|
import type { AnyTypes, Types } from './_types'
|
|
13
16
|
|
|
14
17
|
export interface LikeC4ViewBuilder<
|
|
@@ -25,7 +28,7 @@ export interface LikeC4ViewBuilder<
|
|
|
25
28
|
$expr(expr: Expr | TypedExpr): TypedExpr
|
|
26
29
|
include(...exprs: Expr[]): this
|
|
27
30
|
exclude(...exprs: Expr[]): this
|
|
28
|
-
style(rule: ViewRuleStyle): this
|
|
31
|
+
style(rule: ViewRuleStyle<any>): this
|
|
29
32
|
autoLayout(layout: AutoLayoutDirection): this
|
|
30
33
|
}
|
|
31
34
|
|
|
@@ -85,7 +88,7 @@ export namespace ViewPredicate {
|
|
|
85
88
|
where?: ViewPredicate.WhereOperator<Types>
|
|
86
89
|
with?: Simplify<
|
|
87
90
|
Omit<
|
|
88
|
-
|
|
91
|
+
ModelFqnExpr.Custom['custom'] & ModelRelationExpr.Custom['customRelation'],
|
|
89
92
|
'expr' | 'relation' | 'navigateTo'
|
|
90
93
|
> & {
|
|
91
94
|
navigateTo?: Types['ViewId']
|
|
@@ -94,7 +97,7 @@ export namespace ViewPredicate {
|
|
|
94
97
|
}
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
function parseWhere(where: ViewPredicate.WhereOperator<AnyTypes>): WhereOperator<
|
|
100
|
+
function parseWhere(where: ViewPredicate.WhereOperator<AnyTypes>): WhereOperator<Any> {
|
|
98
101
|
if (isString(where)) {
|
|
99
102
|
const op = where as LiteralUnion<ViewPredicate.WhereEq<AnyTypes>, string>
|
|
100
103
|
switch (true) {
|
|
@@ -124,16 +127,16 @@ function parseWhere(where: ViewPredicate.WhereOperator<AnyTypes>): WhereOperator
|
|
|
124
127
|
}
|
|
125
128
|
case op.startsWith('source.'):
|
|
126
129
|
return {
|
|
127
|
-
operator: parseWhere(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
operator: parseWhere(
|
|
131
|
+
op.replace('source.', '') as ViewPredicate.WhereOperator<AnyTypes>,
|
|
132
|
+
) as ParticipantOperator<AnyAux>['operator'],
|
|
130
133
|
participant: 'source',
|
|
131
134
|
}
|
|
132
135
|
case op.startsWith('target.'):
|
|
133
136
|
return {
|
|
134
|
-
operator: parseWhere(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
operator: parseWhere(
|
|
138
|
+
op.replace('target.', '') as ViewPredicate.WhereOperator<AnyTypes>,
|
|
139
|
+
) as ParticipantOperator<AnyAux>['operator'],
|
|
137
140
|
participant: 'target',
|
|
138
141
|
}
|
|
139
142
|
default:
|
|
@@ -181,7 +184,7 @@ function $include<B extends LikeC4ViewBuilder<AnyTypes, any, any>>(
|
|
|
181
184
|
|
|
182
185
|
const custom = args[1].with
|
|
183
186
|
if (custom) {
|
|
184
|
-
const isElement =
|
|
187
|
+
const isElement = ModelFqnExpr.is(expr)
|
|
185
188
|
if (isElement) {
|
|
186
189
|
expr = {
|
|
187
190
|
custom: {
|
|
@@ -212,7 +215,7 @@ function $exclude<B extends LikeC4ViewBuilder<AnyTypes, any, any>>(
|
|
|
212
215
|
| [B['TypedExpr'], ViewPredicate.Custom<B['Types']>]
|
|
213
216
|
): (b: B) => B {
|
|
214
217
|
return (b) => {
|
|
215
|
-
let expr = b.$expr(args[0]) as
|
|
218
|
+
let expr = b.$expr(args[0]) as Expression
|
|
216
219
|
if (args.length === 2 && args[1].where) {
|
|
217
220
|
const condition = parseWhere(args[1].where)
|
|
218
221
|
expr = {
|
|
@@ -227,13 +230,28 @@ function $exclude<B extends LikeC4ViewBuilder<AnyTypes, any, any>>(
|
|
|
227
230
|
}
|
|
228
231
|
}
|
|
229
232
|
|
|
233
|
+
/**
|
|
234
|
+
* @example
|
|
235
|
+
* builder.views(({ view, $style }, _) =>
|
|
236
|
+
* _(
|
|
237
|
+
* view('view1').with(
|
|
238
|
+
* $style('*', {
|
|
239
|
+
* color: 'red',
|
|
240
|
+
* }),
|
|
241
|
+
* $style(['bob', 'alice'], {
|
|
242
|
+
* color: 'blue',
|
|
243
|
+
* }),
|
|
244
|
+
* ),
|
|
245
|
+
* )
|
|
246
|
+
* )
|
|
247
|
+
*/
|
|
230
248
|
function $style<B extends LikeC4ViewBuilder<AnyTypes, any, any>>(
|
|
231
249
|
element: B['ElementExpr'] | B['TypedExpr'] | NonEmptyArray<B['ElementExpr']>,
|
|
232
|
-
{ notation, ...style }: ViewRuleStyle['style'] & { notation?: string },
|
|
250
|
+
{ notation, ...style }: ViewRuleStyle<any>['style'] & { notation?: string },
|
|
233
251
|
): (b: B) => B {
|
|
234
252
|
return (b) =>
|
|
235
253
|
b.style({
|
|
236
|
-
targets: (isArray(element) ? element : [element]).map(e => b.$expr(e as any) as
|
|
254
|
+
targets: (isArray(element) ? element : [element]).map(e => b.$expr(e as any) as ModelFqnExpr),
|
|
237
255
|
...(notation ? { notation } : {}),
|
|
238
256
|
style: {
|
|
239
257
|
...style,
|