@likec4/core 1.18.0 → 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 +9 -78
- package/dist/compute-view/index.d.ts +9 -78
- package/dist/compute-view/index.js +78 -0
- package/dist/index.d.mts +9 -730
- package/dist/index.d.ts +9 -730
- package/dist/{index.mjs → index.js} +7 -784
- package/dist/model/index.d.mts +218 -606
- package/dist/model/index.d.ts +218 -606
- 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.DMYY7C8s.d.mts → core.C05RDLhi.d.ts} +179 -230
- package/dist/shared/{core.DMYY7C8s.d.ts → core.CmYMqgha.d.mts} +179 -230
- 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/view.CyZrG8BJ.js +354 -0
- package/dist/types/index.d.mts +4 -2
- package/dist/types/index.d.ts +4 -2
- 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 +47 -33
- 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 +25 -20
- package/src/builder/Builder.deploymentModel.ts +80 -55
- package/src/builder/Builder.element.ts +2 -0
- package/src/builder/Builder.model.ts +57 -43
- package/src/builder/Builder.ts +412 -431
- 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 +28 -5
- package/src/builder/index.ts +10 -4
- package/src/colors/index.ts +2 -2
- package/src/compute-view/compute-view.ts +45 -54
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
- package/src/compute-view/deployment-view/__test__/fixture.ts +50 -62
- package/src/compute-view/deployment-view/_types.ts +26 -18
- package/src/compute-view/deployment-view/clean-connections.ts +173 -164
- package/src/compute-view/deployment-view/compute.ts +51 -37
- 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 +183 -76
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +38 -20
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +72 -23
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +61 -22
- package/src/compute-view/deployment-view/predicates/wildcard.ts +15 -15
- 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 +95 -31
- package/src/compute-view/dynamic-view/__test__/fixture.ts +4 -4
- package/src/compute-view/dynamic-view/compute.ts +59 -45
- package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +64 -62
- package/src/compute-view/element-view/__test__/fixture.ts +147 -117
- 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 +264 -683
- 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 +3 -4
- 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/buildComputedNodes.ts +4 -4
- package/src/compute-view/utils/elementExpressionToPredicate.ts +1 -3
- package/src/compute-view/utils/link-nodes-with-edges.ts +3 -7
- package/src/compute-view/utils/{derive-edge-props-from-relationships.ts → merge-props-from-relationships.ts} +54 -23
- package/src/compute-view/utils/relationExpressionToPredicates.ts +2 -2
- package/src/compute-view/utils/resolve-extended-views.ts +44 -40
- package/src/compute-view/utils/resolve-global-rules.ts +6 -6
- package/src/compute-view/utils/topological-sort.ts +167 -71
- package/src/compute-view/utils/with-readable-edges.ts +14 -9
- package/src/index.ts +22 -16
- package/src/model/DeploymentElementModel.ts +150 -85
- package/src/model/DeploymentModel.ts +27 -21
- package/src/model/ElementModel.ts +51 -25
- package/src/model/LikeC4Model.test-d.ts +4 -3
- package/src/model/LikeC4Model.ts +98 -42
- package/src/model/RelationModel.ts +5 -4
- package/src/model/__test__/fixture.ts +5 -9
- package/src/model/connection/Connection.ts +72 -0
- package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
- package/src/model/connection/{deployment.ts → deployment/find.ts} +14 -18
- 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.ts → model/find.ts} +43 -49
- 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 +45 -3
- package/src/model/types.ts +35 -18
- package/src/model/view/EdgeModel.ts +6 -6
- package/src/model/view/LikeC4ViewModel.ts +14 -8
- package/src/model/view/NodeModel.ts +6 -5
- package/src/types/_common.ts +53 -1
- package/src/types/deployments.ts +88 -156
- package/src/types/element.ts +2 -2
- package/src/types/expression-v2.ts +172 -0
- package/src/types/expression.ts +9 -5
- package/src/types/global.ts +3 -3
- package/src/types/index.ts +220 -13
- package/src/types/model.ts +28 -24
- package/src/types/operators.ts +1 -1
- package/src/types/relation.ts +14 -10
- package/src/types/theme.ts +0 -1
- package/src/types/view.ts +20 -18
- package/src/utils/const.ts +1 -0
- package/src/utils/fqn.ts +140 -49
- package/src/utils/getOrCreate.ts +1 -1
- package/src/utils/index.ts +74 -9
- 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/relations.ts +3 -64
- package/src/utils/set.ts +11 -9
- package/src/utils/string-hash.ts +1 -1
- package/dist/compute-view/index.mjs +0 -79
- package/dist/model/index.mjs +0 -2
- package/dist/shared/core.BBgiAAv1.mjs +0 -144
- package/dist/shared/core.BPyJvuMU.mjs +0 -2420
- package/dist/shared/core.BQ4AbfvB.mjs +0 -9228
- package/dist/shared/core.k12s_keD.mjs +0 -203
- package/dist/types/index.mjs +0 -21
- package/src/builder/Builder.test-d.ts +0 -124
- package/src/builder/Builder.view.ts +0 -543
- package/src/compute-view/LikeC4ModelGraph.ts +0 -330
- package/src/compute-view/deployment-view/Memory.ts +0 -108
- package/src/compute-view/deployment-view/Stage.ts +0 -145
- package/src/compute-view/deployment-view/predicates/deployment-ref.ts +0 -146
- package/src/compute-view/element-view/predicates.ts +0 -517
- package/src/compute-view/utils/sortNodes.ts +0 -101
- package/src/model/connection/ConnectionModel.ts +0 -94
- package/src/model/connection/DeploymentConnectionModel.ts +0 -99
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { findConnectionsWithin } from '../../../model/connection/model'
|
|
2
|
+
import type { ElementRefExpr } from '../../../types/expression'
|
|
3
|
+
import * as Expr from '../../../types/expression'
|
|
4
|
+
import type { Elem, PredicateExecutor } from '../_types'
|
|
5
|
+
|
|
6
|
+
function applyElementSelector(elem: Elem, expr: Expr.ElementRefExpr) {
|
|
7
|
+
let children
|
|
8
|
+
if (expr.isChildren) {
|
|
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)
|
|
20
|
+
if (elements.length === 0) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
stage.addExplicit(elements)
|
|
25
|
+
stage.connectWithExisting(elements)
|
|
26
|
+
stage.addConnections(findConnectionsWithin(elements))
|
|
27
|
+
|
|
28
|
+
return stage
|
|
29
|
+
},
|
|
30
|
+
exclude: ({ expr, model, stage, filterWhere }) => {
|
|
31
|
+
const element = model.element(expr.element)
|
|
32
|
+
const elements = filterWhere(applyElementSelector(element, expr))
|
|
33
|
+
stage.exclude(elements)
|
|
34
|
+
|
|
35
|
+
return stage
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { concat, constant, flatMap, hasAtLeast, map, partition, pipe, piped, prop, when } from 'remeda'
|
|
2
|
+
import { invariant } from '../../../errors'
|
|
3
|
+
import { ConnectionModel, findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/model'
|
|
4
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
5
|
+
import type { AnyAux } from '../../../model/types'
|
|
6
|
+
import * as Expr from '../../../types/expression'
|
|
7
|
+
import { isSameHierarchy } from '../../../utils'
|
|
8
|
+
import { ifilter, iflat, iunique, toArray, toSet } from '../../../utils/iterable'
|
|
9
|
+
import { intersection, union } from '../../../utils/set'
|
|
10
|
+
import type { Elem, PredicateCtx, PredicateExecutor } from '../_types'
|
|
11
|
+
import { NoWhere } from '../utils'
|
|
12
|
+
import { includeDescendantsFromMemory, resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
13
|
+
|
|
14
|
+
export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationExpr> = {
|
|
15
|
+
include: ({ expr: { source, target, isBidirectional = false }, memory, model, stage, where, filterWhere }) => {
|
|
16
|
+
const sourceIsWildcard = Expr.isWildcard(source)
|
|
17
|
+
const targetIsWildcard = Expr.isWildcard(target)
|
|
18
|
+
|
|
19
|
+
const connections = [] as ConnectionModel<AnyAux>[]
|
|
20
|
+
switch (true) {
|
|
21
|
+
// This is a special case, we look for all relationships that satisfy the where clause
|
|
22
|
+
// * -> * ; Empty memory; Where clause
|
|
23
|
+
case sourceIsWildcard && targetIsWildcard && memory.isEmpty() && where !== NoWhere: {
|
|
24
|
+
const connections = pipe(
|
|
25
|
+
model.relationships(),
|
|
26
|
+
ifilter(where),
|
|
27
|
+
toArray(),
|
|
28
|
+
map(r => new ConnectionModel(r.source, r.target, new Set([r]))),
|
|
29
|
+
)
|
|
30
|
+
stage.addConnections(connections)
|
|
31
|
+
return stage
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// This is a special case, we look for all relationships between elements that satisfy the where clause
|
|
35
|
+
// * -> *; Not empty memory; Where clause
|
|
36
|
+
case sourceIsWildcard && targetIsWildcard && !memory.isEmpty() && where !== NoWhere: {
|
|
37
|
+
connections.push(
|
|
38
|
+
...findConnectionsWithin(memory.elements),
|
|
39
|
+
)
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// * -> *
|
|
44
|
+
case sourceIsWildcard && targetIsWildcard: {
|
|
45
|
+
connections.push(
|
|
46
|
+
...findConnectionsWithin(model.roots()),
|
|
47
|
+
)
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// This is a special case, we look for all relationships that satisfy the where clause
|
|
52
|
+
// element -> *; Where clause
|
|
53
|
+
case !sourceIsWildcard && targetIsWildcard && where !== NoWhere: {
|
|
54
|
+
const sources = resolveElements(model, source)
|
|
55
|
+
const connections = pipe(
|
|
56
|
+
sources,
|
|
57
|
+
flatMap(source =>
|
|
58
|
+
pipe(
|
|
59
|
+
source,
|
|
60
|
+
when(constant(isBidirectional === true), {
|
|
61
|
+
onTrue: s => union(s.allIncoming, s.allOutgoing),
|
|
62
|
+
onFalse: s => s.allOutgoing,
|
|
63
|
+
}),
|
|
64
|
+
ifilter(where),
|
|
65
|
+
iunique(),
|
|
66
|
+
toArray(),
|
|
67
|
+
partition(r => r.source === source),
|
|
68
|
+
([outgoing, incoming]) =>
|
|
69
|
+
concat(
|
|
70
|
+
pipe(
|
|
71
|
+
outgoing,
|
|
72
|
+
map(outgoing =>
|
|
73
|
+
new ConnectionModel(
|
|
74
|
+
source,
|
|
75
|
+
outgoing.target,
|
|
76
|
+
new Set([outgoing]),
|
|
77
|
+
)
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
pipe(
|
|
81
|
+
incoming,
|
|
82
|
+
map(incoming =>
|
|
83
|
+
new ConnectionModel(
|
|
84
|
+
incoming.source,
|
|
85
|
+
source,
|
|
86
|
+
new Set([incoming]),
|
|
87
|
+
)
|
|
88
|
+
),
|
|
89
|
+
),
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
stage.addConnections(connections)
|
|
95
|
+
return stage
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// element -> *
|
|
99
|
+
case !sourceIsWildcard && targetIsWildcard: {
|
|
100
|
+
const [sources, targets] = resolveWildcard(source, { memory, model })
|
|
101
|
+
const dir = isBidirectional ? 'both' : 'directed'
|
|
102
|
+
for (const source of sources) {
|
|
103
|
+
connections.push(
|
|
104
|
+
...findConnectionsBetween(source, targets, dir),
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
break
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// This is a special case, we look for all relationships that satisfy the where clause
|
|
111
|
+
// * -> element; Where clause
|
|
112
|
+
case sourceIsWildcard && !targetIsWildcard && where !== NoWhere: {
|
|
113
|
+
const targets = resolveElements(model, target)
|
|
114
|
+
const connections = pipe(
|
|
115
|
+
targets,
|
|
116
|
+
flatMap(target =>
|
|
117
|
+
pipe(
|
|
118
|
+
target,
|
|
119
|
+
when(constant(isBidirectional === true), {
|
|
120
|
+
onTrue: s => union(s.allIncoming, s.allOutgoing),
|
|
121
|
+
onFalse: s => s.allIncoming,
|
|
122
|
+
}),
|
|
123
|
+
ifilter(where),
|
|
124
|
+
toArray(),
|
|
125
|
+
partition(r => r.target === target),
|
|
126
|
+
([incoming, outgoing]) =>
|
|
127
|
+
concat(
|
|
128
|
+
pipe(
|
|
129
|
+
outgoing,
|
|
130
|
+
map(outgoing =>
|
|
131
|
+
new ConnectionModel(
|
|
132
|
+
target,
|
|
133
|
+
outgoing.target,
|
|
134
|
+
new Set([outgoing]),
|
|
135
|
+
)
|
|
136
|
+
),
|
|
137
|
+
),
|
|
138
|
+
pipe(
|
|
139
|
+
incoming,
|
|
140
|
+
map(incoming =>
|
|
141
|
+
new ConnectionModel(
|
|
142
|
+
incoming.source,
|
|
143
|
+
target,
|
|
144
|
+
new Set([incoming]),
|
|
145
|
+
)
|
|
146
|
+
),
|
|
147
|
+
),
|
|
148
|
+
),
|
|
149
|
+
)
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
stage.addConnections(connections)
|
|
153
|
+
return stage
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// * -> element
|
|
157
|
+
case sourceIsWildcard && !targetIsWildcard: {
|
|
158
|
+
const [targets, sources] = resolveWildcard(target, { memory, model })
|
|
159
|
+
const dir = isBidirectional ? 'both' : 'directed'
|
|
160
|
+
for (const source of sources) {
|
|
161
|
+
connections.push(
|
|
162
|
+
...findConnectionsBetween(source, targets, dir),
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
default: {
|
|
169
|
+
invariant(!Expr.isWildcard(source), 'Inference failed - source must be not a wildcard')
|
|
170
|
+
invariant(!Expr.isWildcard(target), 'Inference failed - target must be not a wildcard')
|
|
171
|
+
const sources = resolveAndIncludeFromMemory(source, { memory, model })
|
|
172
|
+
const targets = resolveAndIncludeFromMemory(target, { memory, model })
|
|
173
|
+
const dir = isBidirectional ? 'both' : 'directed'
|
|
174
|
+
for (const source of sources) {
|
|
175
|
+
connections.push(
|
|
176
|
+
...findConnectionsBetween(source, targets, dir),
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
stage.addConnections(
|
|
183
|
+
filterWhere(connections),
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return stage
|
|
187
|
+
},
|
|
188
|
+
exclude: ({ expr: { source, target, isBidirectional }, model, memory, stage, where }) => {
|
|
189
|
+
const sourceIsWildcard = Expr.isWildcard(source)
|
|
190
|
+
const targetIsWildcard = Expr.isWildcard(target)
|
|
191
|
+
|
|
192
|
+
let relations: Set<RelationshipModel<AnyAux>>
|
|
193
|
+
|
|
194
|
+
switch (true) {
|
|
195
|
+
// * -> *
|
|
196
|
+
case sourceIsWildcard && targetIsWildcard: {
|
|
197
|
+
relations = pipe(
|
|
198
|
+
memory.connections,
|
|
199
|
+
flatMap(piped(
|
|
200
|
+
prop('relations'),
|
|
201
|
+
ifilter(where),
|
|
202
|
+
toArray(),
|
|
203
|
+
)),
|
|
204
|
+
toSet(),
|
|
205
|
+
)
|
|
206
|
+
break
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// element -> *
|
|
210
|
+
case !sourceIsWildcard && targetIsWildcard: {
|
|
211
|
+
const sources = resolveElements(model, source)
|
|
212
|
+
relations = pipe(
|
|
213
|
+
sources,
|
|
214
|
+
flatMap(source =>
|
|
215
|
+
pipe(
|
|
216
|
+
source,
|
|
217
|
+
when(constant(isBidirectional === true), {
|
|
218
|
+
onTrue: s => union(s.allIncoming, s.allOutgoing),
|
|
219
|
+
onFalse: s => s.allOutgoing,
|
|
220
|
+
}),
|
|
221
|
+
ifilter(where),
|
|
222
|
+
toArray(),
|
|
223
|
+
)
|
|
224
|
+
),
|
|
225
|
+
toSet(),
|
|
226
|
+
)
|
|
227
|
+
break
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// * -> element
|
|
231
|
+
case sourceIsWildcard && !targetIsWildcard: {
|
|
232
|
+
const targets = resolveElements(model, target)
|
|
233
|
+
relations = pipe(
|
|
234
|
+
targets,
|
|
235
|
+
flatMap(target =>
|
|
236
|
+
pipe(
|
|
237
|
+
target,
|
|
238
|
+
when(constant(isBidirectional === true), {
|
|
239
|
+
onTrue: s => union(s.allIncoming, s.allOutgoing),
|
|
240
|
+
onFalse: s => s.allIncoming,
|
|
241
|
+
}),
|
|
242
|
+
ifilter(where),
|
|
243
|
+
toArray(),
|
|
244
|
+
)
|
|
245
|
+
),
|
|
246
|
+
toSet(),
|
|
247
|
+
)
|
|
248
|
+
break
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
default: {
|
|
252
|
+
invariant(!Expr.isWildcard(source), 'Inferrence failed - source must be not a wildcard')
|
|
253
|
+
invariant(!Expr.isWildcard(target), 'Inferrence failed - target must be not a wildcard')
|
|
254
|
+
const sources = resolveElements(model, source)
|
|
255
|
+
const targets = resolveElements(model, target)
|
|
256
|
+
|
|
257
|
+
let accum = new Set<RelationshipModel<AnyAux>>()
|
|
258
|
+
for (const source of sources) {
|
|
259
|
+
for (const target of targets) {
|
|
260
|
+
if (isSameHierarchy(source, target)) {
|
|
261
|
+
continue
|
|
262
|
+
}
|
|
263
|
+
accum = union(
|
|
264
|
+
accum,
|
|
265
|
+
intersection(source.allOutgoing, target.allIncoming),
|
|
266
|
+
isBidirectional ? intersection(target.allOutgoing, source.allIncoming) : new Set(),
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
relations = toSet(ifilter(accum, where))
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
stage.excludeRelations(relations)
|
|
276
|
+
return stage
|
|
277
|
+
},
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Resolve elements for both source and target, when one of them is a wildcard
|
|
282
|
+
*/
|
|
283
|
+
function resolveWildcard(
|
|
284
|
+
nonWildcard: Expr.NonWilcard,
|
|
285
|
+
{ memory, model }: Pick<PredicateCtx, 'model' | 'memory'>,
|
|
286
|
+
): [elements: Elem[], wildcard: Elem[]] {
|
|
287
|
+
let sources = resolveElements(model, nonWildcard)
|
|
288
|
+
if (!hasAtLeast(sources, 1)) {
|
|
289
|
+
return [[], []]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (Expr.isExpandedElementExpr(nonWildcard) || Expr.isElementRef(nonWildcard)) {
|
|
293
|
+
const parent = model.element(nonWildcard.element ?? nonWildcard.expanded)
|
|
294
|
+
const targets = toArray(parent.ascendingSiblings())
|
|
295
|
+
return [
|
|
296
|
+
includeDescendantsFromMemory(sources, memory),
|
|
297
|
+
includeDescendantsFromMemory(targets, memory),
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
const targets = pipe(
|
|
301
|
+
sources,
|
|
302
|
+
map(el => el.ascendingSiblings()),
|
|
303
|
+
iflat(),
|
|
304
|
+
iunique(),
|
|
305
|
+
toArray(),
|
|
306
|
+
all => includeDescendantsFromMemory(all, memory),
|
|
307
|
+
)
|
|
308
|
+
return [sources, targets]
|
|
309
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { unique } from 'remeda'
|
|
2
|
+
import { type ConnectionModel, findConnectionsBetween } from '../../../model/connection/model'
|
|
3
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
4
|
+
import type { AnyAux } from '../../../model/types'
|
|
5
|
+
import * as Expr from '../../../types/expression'
|
|
6
|
+
import { toArray } from '../../../utils/iterable'
|
|
7
|
+
import { toSet } from '../../../utils/iterable/to'
|
|
8
|
+
import type { PredicateExecutor } from '../_types'
|
|
9
|
+
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
10
|
+
|
|
11
|
+
export const InOutRelationPredicate: PredicateExecutor<Expr.InOutExpr> = {
|
|
12
|
+
include: ({ expr: { inout }, scope, model, memory, stage, filterWhere }) => {
|
|
13
|
+
const connections = [] as ConnectionModel<AnyAux>[]
|
|
14
|
+
if (Expr.isWildcard(inout)) {
|
|
15
|
+
if (!scope) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
connections.push(
|
|
19
|
+
...findConnectionsBetween(
|
|
20
|
+
scope,
|
|
21
|
+
scope.ascendingSiblings(),
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
} else {
|
|
25
|
+
const elements = resolveAndIncludeFromMemory(inout, { memory, model })
|
|
26
|
+
let visibleElements = [...memory.elements]
|
|
27
|
+
if (visibleElements.length === 0) {
|
|
28
|
+
visibleElements = unique(
|
|
29
|
+
elements.flatMap(el => toArray(el.ascendingSiblings())),
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
for (const el of elements) {
|
|
33
|
+
connections.push(
|
|
34
|
+
...findConnectionsBetween(
|
|
35
|
+
el,
|
|
36
|
+
visibleElements,
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
stage.addConnections(
|
|
43
|
+
filterWhere(connections),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return stage
|
|
47
|
+
},
|
|
48
|
+
exclude: ({ expr: { inout }, model, scope, stage, where }) => {
|
|
49
|
+
const excluded = [] as RelationshipModel[]
|
|
50
|
+
if (Expr.isWildcard(inout)) {
|
|
51
|
+
if (!scope) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
excluded.push(...scope.allOutgoing)
|
|
55
|
+
excluded.push(...scope.allIncoming)
|
|
56
|
+
} else {
|
|
57
|
+
const elements = resolveElements(model, inout)
|
|
58
|
+
excluded.push(
|
|
59
|
+
...elements.flatMap(e => [...e.allOutgoing, ...e.allIncoming]),
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
stage.excludeRelations(toSet(excluded.filter(where)))
|
|
63
|
+
|
|
64
|
+
return stage
|
|
65
|
+
},
|
|
66
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { anyPass, unique } from 'remeda'
|
|
2
|
+
import { nonexhaustive } from '../../../errors'
|
|
3
|
+
import type { LikeC4Model } from '../../../model'
|
|
4
|
+
import {
|
|
5
|
+
Connection,
|
|
6
|
+
type ConnectionModel,
|
|
7
|
+
findConnection,
|
|
8
|
+
findConnectionsBetween
|
|
9
|
+
} from '../../../model/connection/model'
|
|
10
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
11
|
+
import type { AnyAux } from '../../../model/types'
|
|
12
|
+
import * as Expr from '../../../types/expression'
|
|
13
|
+
import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
|
|
14
|
+
import type { ConnectionWhere, PredicateExecutor } from '../_types'
|
|
15
|
+
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
16
|
+
|
|
17
|
+
export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
|
|
18
|
+
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
19
|
+
const target = expr.incoming
|
|
20
|
+
const connections = [] as ConnectionModel<AnyAux>[]
|
|
21
|
+
if (Expr.isWildcard(target)) {
|
|
22
|
+
if (!scope) {
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
for (const sibling of scope.ascendingSiblings()) {
|
|
26
|
+
connections.push(
|
|
27
|
+
...findConnection(
|
|
28
|
+
sibling,
|
|
29
|
+
scope,
|
|
30
|
+
'directed'
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
const targets = resolveAndIncludeFromMemory(target, { memory, model })
|
|
36
|
+
const visibleElements = [...memory.elements]
|
|
37
|
+
if (visibleElements.length === 0) {
|
|
38
|
+
visibleElements.push(
|
|
39
|
+
...unique(
|
|
40
|
+
targets.flatMap(el => [...el.ascendingSiblings()])
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
const ensureIncoming = incomingConnectionPredicate(model, target)
|
|
45
|
+
for (const visible of visibleElements) {
|
|
46
|
+
connections.push(
|
|
47
|
+
...findConnectionsBetween(
|
|
48
|
+
visible,
|
|
49
|
+
targets,
|
|
50
|
+
'directed'
|
|
51
|
+
).filter(ensureIncoming)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
stage.addConnections(
|
|
57
|
+
filterWhere(connections)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return stage
|
|
61
|
+
},
|
|
62
|
+
exclude: ({ expr: { incoming }, model, scope, stage, where }) => {
|
|
63
|
+
const excluded = [] as RelationshipModel[]
|
|
64
|
+
if (Expr.isWildcard(incoming)) {
|
|
65
|
+
if (!scope) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
excluded.push(...scope.allIncoming)
|
|
69
|
+
} else {
|
|
70
|
+
const elements = resolveElements(model, incoming)
|
|
71
|
+
excluded.push(
|
|
72
|
+
...elements.flatMap(e => [...e.allIncoming])
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
stage.excludeRelations(new Set(excluded.filter(where)))
|
|
76
|
+
|
|
77
|
+
return stage
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function incomingConnectionPredicate(
|
|
82
|
+
model: LikeC4Model,
|
|
83
|
+
expr: Exclude<Expr.ElementExpression, Expr.WildcardExpr>
|
|
84
|
+
): ConnectionWhere {
|
|
85
|
+
switch (true) {
|
|
86
|
+
case Expr.isElementKindExpr(expr):
|
|
87
|
+
case Expr.isElementTagExpr(expr): {
|
|
88
|
+
const isElement = elementExprToPredicate(expr)
|
|
89
|
+
return (connection) => isElement(connection.target)
|
|
90
|
+
}
|
|
91
|
+
case Expr.isElementRef(expr) && expr.isChildren: {
|
|
92
|
+
return anyPass(
|
|
93
|
+
[...model.children(expr.element)].map(
|
|
94
|
+
el => Connection.isIncoming(el.id)
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
case Expr.isElementRef(expr) && expr.isDescendants: {
|
|
99
|
+
return anyPass([
|
|
100
|
+
Connection.isInside(expr.element),
|
|
101
|
+
...[...model.children(expr.element)].map(
|
|
102
|
+
el => Connection.isIncoming(el.id)
|
|
103
|
+
)
|
|
104
|
+
])
|
|
105
|
+
}
|
|
106
|
+
case Expr.isExpandedElementExpr(expr): {
|
|
107
|
+
return anyPass([
|
|
108
|
+
Connection.isIncoming(expr.expanded),
|
|
109
|
+
Connection.isInside(expr.expanded)
|
|
110
|
+
])
|
|
111
|
+
}
|
|
112
|
+
case Expr.isElementRef(expr): {
|
|
113
|
+
return Connection.isIncoming(expr.element)
|
|
114
|
+
}
|
|
115
|
+
default:
|
|
116
|
+
nonexhaustive(expr)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { anyPass, unique } from 'remeda'
|
|
2
|
+
import { nonexhaustive } from '../../../errors'
|
|
3
|
+
import type { LikeC4Model } from '../../../model'
|
|
4
|
+
import { Connection, type ConnectionModel, findConnectionsBetween } from '../../../model/connection/model'
|
|
5
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
6
|
+
import type { AnyAux } from '../../../model/types'
|
|
7
|
+
import * as Expr from '../../../types/expression'
|
|
8
|
+
import { toSet } from '../../../utils/iterable/to'
|
|
9
|
+
import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
|
|
10
|
+
import type { ConnectionWhere, PredicateExecutor } from '../_types'
|
|
11
|
+
import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
|
|
12
|
+
|
|
13
|
+
export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
|
|
14
|
+
include: ({ expr, scope, model, memory, stage, filterWhere }) => {
|
|
15
|
+
const target = expr.outgoing
|
|
16
|
+
const connections = [] as ConnectionModel<AnyAux>[]
|
|
17
|
+
if (Expr.isWildcard(target)) {
|
|
18
|
+
if (!scope) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
connections.push(
|
|
23
|
+
...findConnectionsBetween(
|
|
24
|
+
scope,
|
|
25
|
+
scope.ascendingSiblings(),
|
|
26
|
+
'directed'
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
} else {
|
|
30
|
+
const elements = resolveAndIncludeFromMemory(target, { memory, model })
|
|
31
|
+
const visibleElements = [...memory.elements]
|
|
32
|
+
if (visibleElements.length === 0) {
|
|
33
|
+
visibleElements.push(
|
|
34
|
+
...unique(
|
|
35
|
+
elements.flatMap(el => [...el.ascendingSiblings()])
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
const ensureOutgoing = outgoingConnectionPredicate(model, target)
|
|
40
|
+
|
|
41
|
+
for (const source of elements) {
|
|
42
|
+
connections.push(
|
|
43
|
+
...findConnectionsBetween(
|
|
44
|
+
source,
|
|
45
|
+
visibleElements,
|
|
46
|
+
'directed'
|
|
47
|
+
).filter(ensureOutgoing)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
stage.addConnections(
|
|
53
|
+
filterWhere(connections)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return stage
|
|
57
|
+
},
|
|
58
|
+
exclude: ({ expr: { outgoing }, model, scope, stage, where }) => {
|
|
59
|
+
const excluded = [] as RelationshipModel[]
|
|
60
|
+
if (Expr.isWildcard(outgoing)) {
|
|
61
|
+
if (!scope) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
excluded.push(...scope.allOutgoing)
|
|
65
|
+
} else {
|
|
66
|
+
const elements = resolveElements(model, outgoing)
|
|
67
|
+
excluded.push(
|
|
68
|
+
...elements.flatMap(e => [...e.allOutgoing])
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
stage.excludeRelations(
|
|
72
|
+
toSet(excluded.filter(where))
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return stage
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function outgoingConnectionPredicate(
|
|
80
|
+
model: LikeC4Model,
|
|
81
|
+
expr: Exclude<Expr.ElementExpression, Expr.WildcardExpr>
|
|
82
|
+
): ConnectionWhere {
|
|
83
|
+
switch (true) {
|
|
84
|
+
case Expr.isElementKindExpr(expr):
|
|
85
|
+
case Expr.isElementTagExpr(expr): {
|
|
86
|
+
const isElement = elementExprToPredicate(expr)
|
|
87
|
+
return (connection) => isElement(connection.source)
|
|
88
|
+
}
|
|
89
|
+
case Expr.isElementRef(expr) && expr.isChildren: {
|
|
90
|
+
return anyPass(
|
|
91
|
+
[...model.children(expr.element)].map(
|
|
92
|
+
el => Connection.isOutgoing(el.id)
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
case Expr.isElementRef(expr) && expr.isDescendants: {
|
|
97
|
+
return anyPass([
|
|
98
|
+
Connection.isInside(expr.element),
|
|
99
|
+
...[...model.children(expr.element)].map(
|
|
100
|
+
el => Connection.isOutgoing(el.id)
|
|
101
|
+
)
|
|
102
|
+
])
|
|
103
|
+
}
|
|
104
|
+
case Expr.isExpandedElementExpr(expr): {
|
|
105
|
+
return anyPass([
|
|
106
|
+
Connection.isOutgoing(expr.expanded),
|
|
107
|
+
Connection.isInside(expr.expanded)
|
|
108
|
+
])
|
|
109
|
+
}
|
|
110
|
+
case Expr.isElementRef(expr): {
|
|
111
|
+
return Connection.isOutgoing(expr.element)
|
|
112
|
+
}
|
|
113
|
+
default:
|
|
114
|
+
nonexhaustive(expr)
|
|
115
|
+
}
|
|
116
|
+
}
|