@likec4/core 1.27.3 → 1.28.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/dist/builder/index.d.mts +6 -6
- package/dist/builder/index.mjs +23 -13
- package/dist/compute-view/index.d.mts +3 -3
- package/dist/compute-view/index.mjs +3 -3
- package/dist/compute-view/relationships-view/index.d.mts +3 -3
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +2 -2
- package/dist/model/index.d.mts +6 -6
- package/dist/model/index.mjs +1 -1
- package/dist/shared/{core.BpuZeqlX.d.mts → core.CZR9J1Qx.d.mts} +2 -2
- package/dist/shared/{core.Djro-kuQ.d.mts → core.CiFKryGW.d.mts} +7 -2
- package/dist/shared/{core.HKn0jlo_.d.mts → core.D2830qgg.d.mts} +1 -1
- package/dist/shared/{core.CFDwncxs.d.mts → core.DJvmfnEi.d.mts} +481 -186
- package/dist/shared/{core.BMep80lJ.mjs → core.DgfwjBtu.mjs} +198 -87
- package/dist/shared/core.SjLhMA7a.d.mts +62 -0
- package/dist/shared/{core.RjpTh3vE.mjs → core.w6BcP9z5.mjs} +263 -168
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/utils/index.d.mts +2 -2
- package/package.json +7 -7
- package/src/builder/Builder.ts +1 -0
- package/src/builder/Builder.view-common.ts +10 -10
- package/src/builder/Builder.view-element.ts +26 -14
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +23 -8
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +9 -4
- package/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts +18 -0
- package/src/compute-view/deployment-view/predicates/relation-direct.ts +6 -0
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +3 -0
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +3 -0
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +3 -0
- package/src/compute-view/deployment-view/predicates/utils.ts +10 -3
- package/src/compute-view/deployment-view/utils.ts +7 -4
- package/src/compute-view/element-view/__test__/fixture.ts +72 -65
- package/src/compute-view/element-view/_types.ts +13 -9
- package/src/compute-view/element-view/compute.ts +27 -27
- package/src/compute-view/element-view/memory/NodeGroup.ts +4 -3
- package/src/compute-view/element-view/memory/memory.ts +3 -2
- package/src/compute-view/element-view/memory/stage-include.ts +2 -2
- package/src/compute-view/element-view/predicates/_utils.ts +25 -24
- package/src/compute-view/element-view/predicates/element-expand.ts +7 -10
- package/src/compute-view/element-view/predicates/element-kind-tag.ts +5 -3
- package/src/compute-view/element-view/predicates/element-ref.ts +7 -19
- package/src/compute-view/element-view/predicates/relation-direct.ts +15 -13
- package/src/compute-view/element-view/predicates/relation-in-out.ts +5 -6
- package/src/compute-view/element-view/predicates/relation-in.ts +36 -32
- package/src/compute-view/element-view/predicates/relation-out.ts +37 -33
- package/src/compute-view/element-view/predicates/wildcard.ts +2 -2
- package/src/compute-view/utils/applyCustomElementProperties.ts +9 -4
- package/src/compute-view/utils/applyCustomRelationProperties.ts +10 -7
- package/src/compute-view/utils/elementExpressionToPredicate.ts +27 -26
- package/src/compute-view/utils/link-nodes-with-edges.ts +1 -1
- package/src/compute-view/utils/relationExpressionToPredicates.ts +10 -17
- package/src/compute-view/utils/uniqueTags.ts +3 -3
- package/src/index.ts +0 -2
- package/src/model/ElementModel.ts +25 -6
- package/src/model/LikeC4Model.ts +47 -6
- package/src/model/RelationModel.ts +4 -2
- package/src/model/view/LikeC4ViewModel.ts +3 -2
- package/src/types/_common.ts +0 -4
- package/src/types/deployments.ts +3 -2
- package/src/types/element.ts +2 -10
- package/src/types/expression-v2-model.ts +314 -0
- package/src/types/expression-v2.ts +238 -30
- package/src/types/index.ts +15 -46
- package/src/types/model-data.ts +4 -1
- package/src/types/relation.ts +2 -1
- package/src/types/scalars.ts +39 -0
- package/src/types/view-changes.ts +2 -1
- package/src/types/view.ts +7 -8
- package/dist/shared/core.30yYKXcZ.d.mts +0 -186
- package/src/types/expression.ts +0 -207
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { findConnectionsWithin } from '../../../model/connection/model'
|
|
2
|
-
import
|
|
3
|
-
import * as Expr from '../../../types/expression'
|
|
2
|
+
import { ModelLayer } from '../../../types/expression-v2-model'
|
|
4
3
|
import type { Elem, PredicateExecutor } from '../_types'
|
|
4
|
+
import { resolveElements } from './_utils'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
children = [...elem.children()]
|
|
10
|
-
} else if (expr.isDescendants) {
|
|
11
|
-
children = [...elem.descendants()]
|
|
12
|
-
}
|
|
13
|
-
return children && children.length > 0 ? children : [elem]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const ElementRefPredicate: PredicateExecutor<ElementRefExpr> = {
|
|
17
|
-
include: ({ expr, model, stage, where }) => {
|
|
18
|
-
const element = model.element(expr.element)
|
|
19
|
-
const elements = applyElementSelector(element, expr).filter(where)
|
|
6
|
+
export const ElementRefPredicate: PredicateExecutor<ModelLayer.FqnExpr.ModelRef> = {
|
|
7
|
+
include: ({ expr, model, stage, filterWhere }) => {
|
|
8
|
+
const elements = filterWhere(resolveElements(model, expr))
|
|
20
9
|
if (elements.length === 0) {
|
|
21
10
|
return
|
|
22
11
|
}
|
|
@@ -28,10 +17,9 @@ export const ElementRefPredicate: PredicateExecutor<ElementRefExpr> = {
|
|
|
28
17
|
return stage
|
|
29
18
|
},
|
|
30
19
|
exclude: ({ expr, model, stage, filterWhere }) => {
|
|
31
|
-
const
|
|
32
|
-
const elements = filterWhere(applyElementSelector(element, expr))
|
|
20
|
+
const elements = filterWhere(resolveElements(model, expr))
|
|
33
21
|
stage.exclude(elements)
|
|
34
22
|
|
|
35
23
|
return stage
|
|
36
|
-
}
|
|
24
|
+
},
|
|
37
25
|
}
|
|
@@ -3,7 +3,7 @@ import { invariant } from '../../../errors'
|
|
|
3
3
|
import { ConnectionModel, findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/model'
|
|
4
4
|
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
5
5
|
import type { AnyAux } from '../../../model/types'
|
|
6
|
-
import
|
|
6
|
+
import { ModelLayer } from '../../../types/expression-v2-model'
|
|
7
7
|
import { isSameHierarchy } from '../../../utils'
|
|
8
8
|
import { ifilter, iflat, iunique, toArray, toSet } from '../../../utils/iterable'
|
|
9
9
|
import { intersection, union } from '../../../utils/set'
|
|
@@ -11,10 +11,12 @@ import type { Elem, PredicateCtx, PredicateExecutor } from '../_types'
|
|
|
11
11
|
import { NoWhere } from '../utils'
|
|
12
12
|
import { includeDescendantsFromMemory, resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const isWildcard = ModelLayer.FqnExpr.isWildcard
|
|
15
|
+
|
|
16
|
+
export const DirectRelationExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Direct> = {
|
|
15
17
|
include: ({ expr: { source, target, isBidirectional = false }, memory, model, stage, where, filterWhere }) => {
|
|
16
|
-
const sourceIsWildcard =
|
|
17
|
-
const targetIsWildcard =
|
|
18
|
+
const sourceIsWildcard = isWildcard(source)
|
|
19
|
+
const targetIsWildcard = isWildcard(target)
|
|
18
20
|
|
|
19
21
|
const connections = [] as ConnectionModel<AnyAux>[]
|
|
20
22
|
switch (true) {
|
|
@@ -166,8 +168,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
default: {
|
|
169
|
-
invariant(!
|
|
170
|
-
invariant(!
|
|
171
|
+
invariant(!isWildcard(source), 'Inference failed - source must be not a wildcard')
|
|
172
|
+
invariant(!isWildcard(target), 'Inference failed - target must be not a wildcard')
|
|
171
173
|
const sources = resolveAndIncludeFromMemory(source, { memory, model })
|
|
172
174
|
const targets = resolveAndIncludeFromMemory(target, { memory, model })
|
|
173
175
|
const dir = isBidirectional ? 'both' : 'directed'
|
|
@@ -186,8 +188,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
|
|
|
186
188
|
return stage
|
|
187
189
|
},
|
|
188
190
|
exclude: ({ expr: { source, target, isBidirectional }, model, memory, stage, where }) => {
|
|
189
|
-
const sourceIsWildcard =
|
|
190
|
-
const targetIsWildcard =
|
|
191
|
+
const sourceIsWildcard = isWildcard(source)
|
|
192
|
+
const targetIsWildcard = isWildcard(target)
|
|
191
193
|
|
|
192
194
|
let relations: Set<RelationshipModel<AnyAux>>
|
|
193
195
|
|
|
@@ -249,8 +251,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
|
|
|
249
251
|
}
|
|
250
252
|
|
|
251
253
|
default: {
|
|
252
|
-
invariant(!
|
|
253
|
-
invariant(!
|
|
254
|
+
invariant(!isWildcard(source), 'Inferrence failed - source must be not a wildcard')
|
|
255
|
+
invariant(!isWildcard(target), 'Inferrence failed - target must be not a wildcard')
|
|
254
256
|
const sources = resolveElements(model, source)
|
|
255
257
|
const targets = resolveElements(model, target)
|
|
256
258
|
|
|
@@ -281,7 +283,7 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
|
|
|
281
283
|
* Resolve elements for both source and target, when one of them is a wildcard
|
|
282
284
|
*/
|
|
283
285
|
function resolveWildcard(
|
|
284
|
-
nonWildcard:
|
|
286
|
+
nonWildcard: ModelLayer.FqnExpr.NonWildcard,
|
|
285
287
|
{ memory, model }: Pick<PredicateCtx, 'model' | 'memory'>,
|
|
286
288
|
): [elements: Elem[], wildcard: Elem[]] {
|
|
287
289
|
let sources = resolveElements(model, nonWildcard)
|
|
@@ -289,8 +291,8 @@ function resolveWildcard(
|
|
|
289
291
|
return [[], []]
|
|
290
292
|
}
|
|
291
293
|
|
|
292
|
-
if (
|
|
293
|
-
const parent = model.element(
|
|
294
|
+
if (ModelLayer.FqnExpr.isModelRef(nonWildcard)) {
|
|
295
|
+
const parent = model.element(ModelLayer.FqnRef.toFqn(nonWildcard.ref))
|
|
294
296
|
const targets = toArray(parent.ascendingSiblings())
|
|
295
297
|
return [
|
|
296
298
|
includeDescendantsFromMemory(sources, memory),
|
|
@@ -2,16 +2,15 @@ import { unique } from 'remeda'
|
|
|
2
2
|
import { type ConnectionModel, findConnectionsBetween } from '../../../model/connection/model'
|
|
3
3
|
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
4
4
|
import type { AnyAux } from '../../../model/types'
|
|
5
|
-
import
|
|
6
|
-
import { toArray } from '../../../utils/iterable'
|
|
7
|
-
import { toSet } from '../../../utils/iterable/to'
|
|
5
|
+
import { ModelLayer } from '../../../types/expression-v2-model'
|
|
6
|
+
import { toArray, toSet } from '../../../utils/iterable/to'
|
|
8
7
|
import type { PredicateExecutor } from '../_types'
|
|
9
8
|
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
10
9
|
|
|
11
|
-
export const InOutRelationPredicate: PredicateExecutor<
|
|
10
|
+
export const InOutRelationPredicate: PredicateExecutor<ModelLayer.RelationExpr.InOut> = {
|
|
12
11
|
include: ({ expr: { inout }, scope, model, memory, stage, filterWhere }) => {
|
|
13
12
|
const connections = [] as ConnectionModel<AnyAux>[]
|
|
14
|
-
if (
|
|
13
|
+
if (ModelLayer.FqnExpr.isWildcard(inout)) {
|
|
15
14
|
if (!scope) {
|
|
16
15
|
return
|
|
17
16
|
}
|
|
@@ -47,7 +46,7 @@ export const InOutRelationPredicate: PredicateExecutor<Expr.InOutExpr> = {
|
|
|
47
46
|
},
|
|
48
47
|
exclude: ({ expr: { inout }, model, scope, stage, where }) => {
|
|
49
48
|
const excluded = [] as RelationshipModel[]
|
|
50
|
-
if (
|
|
49
|
+
if (ModelLayer.FqnExpr.isWildcard(inout)) {
|
|
51
50
|
if (!scope) {
|
|
52
51
|
return
|
|
53
52
|
}
|
|
@@ -2,23 +2,23 @@ import { anyPass, unique } from 'remeda'
|
|
|
2
2
|
import { nonexhaustive } from '../../../errors'
|
|
3
3
|
import type { LikeC4Model } from '../../../model'
|
|
4
4
|
import {
|
|
5
|
-
Connection,
|
|
6
5
|
type ConnectionModel,
|
|
6
|
+
Connection,
|
|
7
7
|
findConnection,
|
|
8
|
-
findConnectionsBetween
|
|
8
|
+
findConnectionsBetween,
|
|
9
9
|
} from '../../../model/connection/model'
|
|
10
10
|
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
11
11
|
import type { AnyAux } from '../../../model/types'
|
|
12
|
-
import
|
|
12
|
+
import { ModelLayer } from '../../../types/expression-v2-model'
|
|
13
13
|
import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
|
|
14
14
|
import type { ConnectionWhere, PredicateExecutor } from '../_types'
|
|
15
15
|
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
16
16
|
|
|
17
|
-
export const IncomingExprPredicate: PredicateExecutor<
|
|
17
|
+
export const IncomingExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Incoming> = {
|
|
18
18
|
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
19
19
|
const target = expr.incoming
|
|
20
20
|
const connections = [] as ConnectionModel<AnyAux>[]
|
|
21
|
-
if (
|
|
21
|
+
if (ModelLayer.FqnExpr.isWildcard(target)) {
|
|
22
22
|
if (!scope) {
|
|
23
23
|
return
|
|
24
24
|
}
|
|
@@ -27,8 +27,8 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
|
|
|
27
27
|
...findConnection(
|
|
28
28
|
sibling,
|
|
29
29
|
scope,
|
|
30
|
-
'directed'
|
|
31
|
-
)
|
|
30
|
+
'directed',
|
|
31
|
+
),
|
|
32
32
|
)
|
|
33
33
|
}
|
|
34
34
|
} else {
|
|
@@ -37,8 +37,8 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
|
|
|
37
37
|
if (visibleElements.length === 0) {
|
|
38
38
|
visibleElements.push(
|
|
39
39
|
...unique(
|
|
40
|
-
targets.flatMap(el => [...el.ascendingSiblings()])
|
|
41
|
-
)
|
|
40
|
+
targets.flatMap(el => [...el.ascendingSiblings()]),
|
|
41
|
+
),
|
|
42
42
|
)
|
|
43
43
|
}
|
|
44
44
|
const ensureIncoming = incomingConnectionPredicate(model, target)
|
|
@@ -47,21 +47,21 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
|
|
|
47
47
|
...findConnectionsBetween(
|
|
48
48
|
visible,
|
|
49
49
|
targets,
|
|
50
|
-
'directed'
|
|
51
|
-
).filter(ensureIncoming)
|
|
50
|
+
'directed',
|
|
51
|
+
).filter(ensureIncoming),
|
|
52
52
|
)
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
stage.addConnections(
|
|
57
|
-
filterWhere(connections)
|
|
57
|
+
filterWhere(connections),
|
|
58
58
|
)
|
|
59
59
|
|
|
60
60
|
return stage
|
|
61
61
|
},
|
|
62
62
|
exclude: ({ expr: { incoming }, model, scope, stage, where }) => {
|
|
63
63
|
const excluded = [] as RelationshipModel[]
|
|
64
|
-
if (
|
|
64
|
+
if (ModelLayer.FqnExpr.isWildcard(incoming)) {
|
|
65
65
|
if (!scope) {
|
|
66
66
|
return
|
|
67
67
|
}
|
|
@@ -69,48 +69,52 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
|
|
|
69
69
|
} else {
|
|
70
70
|
const elements = resolveElements(model, incoming)
|
|
71
71
|
excluded.push(
|
|
72
|
-
...elements.flatMap(e => [...e.allIncoming])
|
|
72
|
+
...elements.flatMap(e => [...e.allIncoming]),
|
|
73
73
|
)
|
|
74
74
|
}
|
|
75
75
|
stage.excludeRelations(new Set(excluded.filter(where)))
|
|
76
76
|
|
|
77
77
|
return stage
|
|
78
|
-
}
|
|
78
|
+
},
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
export function incomingConnectionPredicate(
|
|
82
82
|
model: LikeC4Model,
|
|
83
|
-
expr:
|
|
83
|
+
expr: ModelLayer.FqnExpr.NonWildcard,
|
|
84
84
|
): ConnectionWhere {
|
|
85
85
|
switch (true) {
|
|
86
|
-
case
|
|
87
|
-
case
|
|
86
|
+
case ModelLayer.FqnExpr.isElementKindExpr(expr):
|
|
87
|
+
case ModelLayer.FqnExpr.isElementTagExpr(expr): {
|
|
88
88
|
const isElement = elementExprToPredicate(expr)
|
|
89
89
|
return (connection) => isElement(connection.target)
|
|
90
90
|
}
|
|
91
|
-
case
|
|
91
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'children': {
|
|
92
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
92
93
|
return anyPass(
|
|
93
|
-
[...model.children(
|
|
94
|
-
el => Connection.isIncoming(el.id)
|
|
95
|
-
)
|
|
94
|
+
[...model.children(fqn)].map(
|
|
95
|
+
el => Connection.isIncoming(el.id),
|
|
96
|
+
),
|
|
96
97
|
)
|
|
97
98
|
}
|
|
98
|
-
case
|
|
99
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'descendants': {
|
|
100
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
99
101
|
return anyPass([
|
|
100
|
-
Connection.isInside(
|
|
101
|
-
...[...model.children(
|
|
102
|
-
el => Connection.isIncoming(el.id)
|
|
103
|
-
)
|
|
102
|
+
Connection.isInside(fqn),
|
|
103
|
+
...[...model.children(fqn)].map(
|
|
104
|
+
el => Connection.isIncoming(el.id),
|
|
105
|
+
),
|
|
104
106
|
])
|
|
105
107
|
}
|
|
106
|
-
case
|
|
108
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'expanded': {
|
|
109
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
107
110
|
return anyPass([
|
|
108
|
-
Connection.isIncoming(
|
|
109
|
-
Connection.isInside(
|
|
111
|
+
Connection.isIncoming(fqn),
|
|
112
|
+
Connection.isInside(fqn),
|
|
110
113
|
])
|
|
111
114
|
}
|
|
112
|
-
case
|
|
113
|
-
|
|
115
|
+
case ModelLayer.FqnExpr.isModelRef(expr): {
|
|
116
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
117
|
+
return Connection.isIncoming(fqn)
|
|
114
118
|
}
|
|
115
119
|
default:
|
|
116
120
|
nonexhaustive(expr)
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { anyPass, unique } from 'remeda'
|
|
2
2
|
import { nonexhaustive } from '../../../errors'
|
|
3
|
-
import type
|
|
4
|
-
import
|
|
3
|
+
import { type ConnectionModel, Connection, findConnectionsBetween } from '../../../model/connection/model'
|
|
4
|
+
import type { LikeC4Model } from '../../../model/LikeC4Model'
|
|
5
5
|
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
6
6
|
import type { AnyAux } from '../../../model/types'
|
|
7
|
-
import
|
|
7
|
+
import { ModelLayer } from '../../../types/expression-v2-model'
|
|
8
8
|
import { toSet } from '../../../utils/iterable/to'
|
|
9
9
|
import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
|
|
10
10
|
import type { ConnectionWhere, PredicateExecutor } from '../_types'
|
|
11
11
|
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
12
12
|
|
|
13
|
-
export const OutgoingExprPredicate: PredicateExecutor<
|
|
13
|
+
export const OutgoingExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Outgoing> = {
|
|
14
14
|
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
15
15
|
const target = expr.outgoing
|
|
16
16
|
const connections = [] as ConnectionModel<AnyAux>[]
|
|
17
|
-
if (
|
|
17
|
+
if (ModelLayer.FqnExpr.isWildcard(target)) {
|
|
18
18
|
if (!scope) {
|
|
19
19
|
return
|
|
20
20
|
}
|
|
@@ -23,8 +23,8 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
|
|
|
23
23
|
...findConnectionsBetween(
|
|
24
24
|
scope,
|
|
25
25
|
scope.ascendingSiblings(),
|
|
26
|
-
'directed'
|
|
27
|
-
)
|
|
26
|
+
'directed',
|
|
27
|
+
),
|
|
28
28
|
)
|
|
29
29
|
} else {
|
|
30
30
|
const elements = resolveAndIncludeFromMemory(target, { memory, model })
|
|
@@ -32,8 +32,8 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
|
|
|
32
32
|
if (visibleElements.length === 0) {
|
|
33
33
|
visibleElements.push(
|
|
34
34
|
...unique(
|
|
35
|
-
elements.flatMap(el => [...el.ascendingSiblings()])
|
|
36
|
-
)
|
|
35
|
+
elements.flatMap(el => [...el.ascendingSiblings()]),
|
|
36
|
+
),
|
|
37
37
|
)
|
|
38
38
|
}
|
|
39
39
|
const ensureOutgoing = outgoingConnectionPredicate(model, target)
|
|
@@ -43,21 +43,21 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
|
|
|
43
43
|
...findConnectionsBetween(
|
|
44
44
|
source,
|
|
45
45
|
visibleElements,
|
|
46
|
-
'directed'
|
|
47
|
-
).filter(ensureOutgoing)
|
|
46
|
+
'directed',
|
|
47
|
+
).filter(ensureOutgoing),
|
|
48
48
|
)
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
stage.addConnections(
|
|
53
|
-
filterWhere(connections)
|
|
53
|
+
filterWhere(connections),
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
return stage
|
|
57
57
|
},
|
|
58
58
|
exclude: ({ expr: { outgoing }, model, scope, stage, where }) => {
|
|
59
59
|
const excluded = [] as RelationshipModel[]
|
|
60
|
-
if (
|
|
60
|
+
if (ModelLayer.FqnExpr.isWildcard(outgoing)) {
|
|
61
61
|
if (!scope) {
|
|
62
62
|
return
|
|
63
63
|
}
|
|
@@ -65,50 +65,54 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
|
|
|
65
65
|
} else {
|
|
66
66
|
const elements = resolveElements(model, outgoing)
|
|
67
67
|
excluded.push(
|
|
68
|
-
...elements.flatMap(e => [...e.allOutgoing])
|
|
68
|
+
...elements.flatMap(e => [...e.allOutgoing]),
|
|
69
69
|
)
|
|
70
70
|
}
|
|
71
71
|
stage.excludeRelations(
|
|
72
|
-
toSet(excluded.filter(where))
|
|
72
|
+
toSet(excluded.filter(where)),
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
return stage
|
|
76
|
-
}
|
|
76
|
+
},
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
export function outgoingConnectionPredicate(
|
|
80
80
|
model: LikeC4Model,
|
|
81
|
-
expr:
|
|
81
|
+
expr: ModelLayer.FqnExpr.NonWildcard,
|
|
82
82
|
): ConnectionWhere {
|
|
83
83
|
switch (true) {
|
|
84
|
-
case
|
|
85
|
-
case
|
|
84
|
+
case ModelLayer.FqnExpr.isElementKindExpr(expr):
|
|
85
|
+
case ModelLayer.FqnExpr.isElementTagExpr(expr): {
|
|
86
86
|
const isElement = elementExprToPredicate(expr)
|
|
87
87
|
return (connection) => isElement(connection.source)
|
|
88
88
|
}
|
|
89
|
-
case
|
|
89
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'children': {
|
|
90
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
90
91
|
return anyPass(
|
|
91
|
-
[...model.children(
|
|
92
|
-
el => Connection.isOutgoing(el.id)
|
|
93
|
-
)
|
|
92
|
+
[...model.children(fqn)].map(
|
|
93
|
+
el => Connection.isOutgoing(el.id),
|
|
94
|
+
),
|
|
94
95
|
)
|
|
95
96
|
}
|
|
96
|
-
case
|
|
97
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'descendants': {
|
|
98
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
97
99
|
return anyPass([
|
|
98
|
-
Connection.isInside(
|
|
99
|
-
...[...model.children(
|
|
100
|
-
el => Connection.isOutgoing(el.id)
|
|
101
|
-
)
|
|
100
|
+
Connection.isInside(fqn),
|
|
101
|
+
...[...model.children(fqn)].map(
|
|
102
|
+
el => Connection.isOutgoing(el.id),
|
|
103
|
+
),
|
|
102
104
|
])
|
|
103
105
|
}
|
|
104
|
-
case
|
|
106
|
+
case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'expanded': {
|
|
107
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
105
108
|
return anyPass([
|
|
106
|
-
Connection.isOutgoing(
|
|
107
|
-
Connection.isInside(
|
|
109
|
+
Connection.isOutgoing(fqn),
|
|
110
|
+
Connection.isInside(fqn),
|
|
108
111
|
])
|
|
109
112
|
}
|
|
110
|
-
case
|
|
111
|
-
|
|
113
|
+
case ModelLayer.FqnExpr.isModelRef(expr): {
|
|
114
|
+
const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
|
|
115
|
+
return Connection.isOutgoing(fqn)
|
|
112
116
|
}
|
|
113
117
|
default:
|
|
114
118
|
nonexhaustive(expr)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { filter } from 'remeda'
|
|
2
2
|
import { findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/model'
|
|
3
|
-
import type {
|
|
3
|
+
import type { ModelLayer } from '../../../types/expression-v2-model'
|
|
4
4
|
import { ifilter, toArray } from '../../../utils/iterable'
|
|
5
5
|
import { toSet } from '../../../utils/iterable/to'
|
|
6
6
|
import { type PredicateExecutor, Memory } from '../_types'
|
|
7
7
|
import { NoWhere } from '../utils'
|
|
8
8
|
|
|
9
|
-
export const WildcardPredicate: PredicateExecutor<
|
|
9
|
+
export const WildcardPredicate: PredicateExecutor<ModelLayer.FqnExpr.Wildcard> = {
|
|
10
10
|
include: ({ scope, model, stage, memory, where }) => {
|
|
11
11
|
if (!scope) {
|
|
12
12
|
const rootElements = [...model.roots()].filter(where)
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { isEmpty, isNullish, omitBy } from 'remeda'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
type ViewRule,
|
|
4
|
+
ComputedNode,
|
|
5
|
+
isViewRuleGroup,
|
|
6
|
+
isViewRulePredicate,
|
|
7
|
+
ModelLayer,
|
|
8
|
+
} from '../../types'
|
|
4
9
|
import { elementExprToPredicate } from './elementExpressionToPredicate'
|
|
5
10
|
|
|
6
|
-
export function flattenGroupRules<T extends Expression>(guard: (expr: Expression) => expr is T) {
|
|
11
|
+
export function flattenGroupRules<T extends ModelLayer.Expression>(guard: (expr: ModelLayer.Expression) => expr is T) {
|
|
7
12
|
return (rule: ViewRule): Array<T> => {
|
|
8
13
|
if (isViewRuleGroup(rule)) {
|
|
9
14
|
return rule.groupRules.flatMap(flattenGroupRules(guard))
|
|
@@ -17,7 +22,7 @@ export function flattenGroupRules<T extends Expression>(guard: (expr: Expression
|
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
export function applyCustomElementProperties(_rules: ViewRule[], _nodes: ComputedNode[]) {
|
|
20
|
-
const rules = _rules.flatMap(flattenGroupRules(
|
|
25
|
+
const rules = _rules.flatMap(flattenGroupRules(ModelLayer.FqnExpr.isCustom))
|
|
21
26
|
if (rules.length === 0) {
|
|
22
27
|
return _nodes
|
|
23
28
|
}
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { isNullish, omitBy, pick } from 'remeda'
|
|
2
|
-
import type
|
|
3
|
-
import * as Expr from '../../types/expression'
|
|
2
|
+
import { type ComputedEdge, type ComputedNode, type ViewRule, ModelLayer } from '../../types'
|
|
4
3
|
import { flattenGroupRules } from './applyCustomElementProperties'
|
|
5
4
|
import { relationExpressionToPredicates } from './relationExpressionToPredicates'
|
|
6
5
|
|
|
7
6
|
export function applyCustomRelationProperties(
|
|
8
7
|
_rules: ViewRule[],
|
|
9
8
|
nodes: ComputedNode[],
|
|
10
|
-
_edges: Iterable<ComputedEdge
|
|
9
|
+
_edges: Iterable<ComputedEdge>,
|
|
11
10
|
): ComputedEdge[] {
|
|
12
|
-
const rules = _rules.flatMap(flattenGroupRules(
|
|
11
|
+
const rules = _rules.flatMap(flattenGroupRules(ModelLayer.RelationExpr.isCustom))
|
|
13
12
|
const edges = Array.from(_edges)
|
|
14
13
|
if (rules.length === 0 || edges.length === 0) {
|
|
15
14
|
return edges
|
|
16
15
|
}
|
|
17
16
|
for (
|
|
18
17
|
const {
|
|
19
|
-
customRelation: {
|
|
18
|
+
customRelation: {
|
|
19
|
+
expr,
|
|
20
|
+
title,
|
|
21
|
+
...customprops
|
|
22
|
+
},
|
|
20
23
|
} of rules
|
|
21
24
|
) {
|
|
22
25
|
const props = omitBy(customprops, isNullish)
|
|
23
|
-
const satisfies = relationExpressionToPredicates(
|
|
26
|
+
const satisfies = relationExpressionToPredicates(expr)
|
|
24
27
|
edges.forEach((edge, i) => {
|
|
25
28
|
const source = nodes.find(n => n.id === edge.source)
|
|
26
29
|
const target = nodes.find(n => n.id === edge.target)
|
|
@@ -32,7 +35,7 @@ export function applyCustomRelationProperties(
|
|
|
32
35
|
...edge,
|
|
33
36
|
...props,
|
|
34
37
|
label: title ?? edge.label,
|
|
35
|
-
isCustomized: true
|
|
38
|
+
isCustomized: true,
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
})
|
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
import { isNullish } from 'remeda'
|
|
2
2
|
import { nonexhaustive } from '../../errors'
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
isElementKindExpr,
|
|
7
|
-
isElementRef,
|
|
8
|
-
isElementTagExpr,
|
|
9
|
-
isElementWhere,
|
|
10
|
-
isExpandedElementExpr,
|
|
11
|
-
isWildcard,
|
|
12
|
-
whereOperatorAsPredicate
|
|
4
|
+
ModelLayer,
|
|
5
|
+
whereOperatorAsPredicate,
|
|
13
6
|
} from '../../types'
|
|
14
7
|
import { parentFqn } from '../../utils'
|
|
15
8
|
|
|
16
9
|
type Predicate<T> = (x: T) => boolean
|
|
17
10
|
|
|
18
11
|
export function elementExprToPredicate<T extends { id: string; tags?: readonly string[] | null; kind: string }>(
|
|
19
|
-
target:
|
|
12
|
+
target: ModelLayer.AnyFqnExpr,
|
|
20
13
|
): Predicate<T> {
|
|
21
|
-
if (
|
|
14
|
+
if (ModelLayer.FqnExpr.isCustom(target)) {
|
|
15
|
+
return elementExprToPredicate(target.custom.expr)
|
|
16
|
+
}
|
|
17
|
+
if (ModelLayer.FqnExpr.isWhere(target)) {
|
|
22
18
|
const predicate = elementExprToPredicate(target.where.expr)
|
|
23
19
|
const where = whereOperatorAsPredicate(target.where.condition)
|
|
24
20
|
return n => predicate(n) && where(n)
|
|
25
21
|
}
|
|
26
|
-
if (
|
|
27
|
-
return () => true
|
|
28
|
-
}
|
|
29
|
-
if (isElementKindExpr(target)) {
|
|
22
|
+
if (ModelLayer.FqnExpr.isElementKindExpr(target)) {
|
|
30
23
|
return target.isEqual ? n => n.kind === target.elementKind : n => n.kind !== target.elementKind
|
|
31
24
|
}
|
|
32
|
-
if (isElementTagExpr(target)) {
|
|
25
|
+
if (ModelLayer.FqnExpr.isElementTagExpr(target)) {
|
|
33
26
|
return target.isEqual
|
|
34
27
|
? ({ tags }) => !!tags && tags.includes(target.elementTag)
|
|
35
28
|
: ({ tags }) => isNullish(tags) || !tags.includes(target.elementTag)
|
|
36
29
|
}
|
|
37
|
-
if (
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
if (isElementRef(target)) {
|
|
41
|
-
const { element, isChildren, isDescendants } = target
|
|
42
|
-
return isChildren || isDescendants
|
|
43
|
-
? n => n.id.startsWith(element + '.')
|
|
44
|
-
: n => (n.id as string) === element
|
|
30
|
+
if (ModelLayer.FqnExpr.isWildcard(target)) {
|
|
31
|
+
return () => true
|
|
45
32
|
}
|
|
46
|
-
if (
|
|
47
|
-
|
|
33
|
+
if (ModelLayer.FqnExpr.isModelRef(target)) {
|
|
34
|
+
const fqn = ModelLayer.FqnRef.toFqn(target.ref)
|
|
35
|
+
if (target.selector === 'expanded') {
|
|
36
|
+
return (n) => {
|
|
37
|
+
return n.id === fqn || parentFqn(n.id) === fqn
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (target.selector === 'descendants' || target.selector === 'children') {
|
|
41
|
+
const fqnWithDot = fqn + '.'
|
|
42
|
+
return (n) => {
|
|
43
|
+
return n.id.startsWith(fqnWithDot)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return (n) => {
|
|
47
|
+
return n.id === fqn
|
|
48
|
+
}
|
|
48
49
|
}
|
|
49
50
|
nonexhaustive(target)
|
|
50
51
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { last, reverse } from 'remeda'
|
|
2
2
|
import { invariant } from '../../errors'
|
|
3
|
-
import type { Fqn } from '../../types
|
|
3
|
+
import type { Fqn } from '../../types'
|
|
4
4
|
import type { ComputedEdge, ComputedNode } from '../../types/view'
|
|
5
5
|
import { commonHead } from '../../utils/common-head'
|
|
6
6
|
import { ancestorsOfNode } from './ancestorsOfNode'
|