@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,144 @@
|
|
|
1
|
+
import { pipe, reduce } from 'remeda'
|
|
2
|
+
import { isDeployedInstance } from '../../../model'
|
|
3
|
+
import { findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/deployment'
|
|
4
|
+
import type { DeploymentElementModel, DeploymentNodeModel } from '../../../model/DeploymentElementModel'
|
|
5
|
+
import type { FqnExpr } from '../../../types'
|
|
6
|
+
import type { Elem, IncludePredicateCtx, PredicateExecutor } from '../_types'
|
|
7
|
+
import { cleanCrossBoundary, cleanRedundantRelationships } from '../clean-connections'
|
|
8
|
+
import type { StageInclude } from '../memory'
|
|
9
|
+
import { deploymentExpressionToPredicate } from '../utils'
|
|
10
|
+
|
|
11
|
+
export const DeploymentRefPredicate: PredicateExecutor<FqnExpr.DeploymentRef> = {
|
|
12
|
+
include: (ctx) => {
|
|
13
|
+
const { expr } = ctx
|
|
14
|
+
const el = ctx.model.element(expr.ref.deployment)
|
|
15
|
+
|
|
16
|
+
if (isDeployedInstance(el)) {
|
|
17
|
+
ctx.stage.addExplicit(el)
|
|
18
|
+
ctx.stage.connectWithExisting(el)
|
|
19
|
+
return ctx.stage
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
switch (true) {
|
|
23
|
+
case expr.selector === 'expanded':
|
|
24
|
+
includeDeployedNodeWithExpanded(el, ctx)
|
|
25
|
+
break
|
|
26
|
+
case expr.selector === 'children':
|
|
27
|
+
includeDeployedNodeChildren(el, ctx)
|
|
28
|
+
break
|
|
29
|
+
case expr.selector === 'descendants':
|
|
30
|
+
includeDeployedNodeDescendants(el, ctx)
|
|
31
|
+
break
|
|
32
|
+
default: {
|
|
33
|
+
ctx.stage.addExplicit(el)
|
|
34
|
+
ctx.stage.connectWithExisting(el)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return ctx.stage
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
exclude: ({ expr, stage, memory }) => {
|
|
41
|
+
const exprPredicate = deploymentExpressionToPredicate(expr)
|
|
42
|
+
stage.exclude([...memory.elements].filter(exprPredicate))
|
|
43
|
+
return stage
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* include node.*
|
|
49
|
+
*/
|
|
50
|
+
function includeDeployedNodeChildren(
|
|
51
|
+
node: DeploymentNodeModel,
|
|
52
|
+
{ stage }: IncludePredicateCtx,
|
|
53
|
+
) {
|
|
54
|
+
const children = [...node.children()]
|
|
55
|
+
if (children.length === 0) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
stage.addImplicit(node)
|
|
59
|
+
|
|
60
|
+
stage.addConnections(findConnectionsWithin(children))
|
|
61
|
+
stage.connectWithExisting(children)
|
|
62
|
+
|
|
63
|
+
stage.addExplicit(children)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* include node._
|
|
68
|
+
*/
|
|
69
|
+
function includeDeployedNodeWithExpanded(
|
|
70
|
+
node: DeploymentNodeModel,
|
|
71
|
+
{ memory, stage }: IncludePredicateCtx,
|
|
72
|
+
) {
|
|
73
|
+
const children = [...node.children()]
|
|
74
|
+
stage.addImplicit(node)
|
|
75
|
+
stage.connectWithExisting(node)
|
|
76
|
+
|
|
77
|
+
let hasConnectionsWithVisible = false
|
|
78
|
+
for (const child of children) {
|
|
79
|
+
if (findConnectionsBetween(child, memory.elements).length > 0) {
|
|
80
|
+
hasConnectionsWithVisible = true
|
|
81
|
+
break
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (hasConnectionsWithVisible) {
|
|
86
|
+
stage.connectWithExisting(children, 'in')
|
|
87
|
+
stage.addConnections(findConnectionsWithin(children))
|
|
88
|
+
stage.connectWithExisting(children, 'out')
|
|
89
|
+
}
|
|
90
|
+
stage.addImplicit(children)
|
|
91
|
+
|
|
92
|
+
if (stage.connections.length > 0) {
|
|
93
|
+
stage.addExplicit(node)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* include node.**
|
|
99
|
+
*/
|
|
100
|
+
function includeDeployedNodeDescendants(
|
|
101
|
+
node: DeploymentNodeModel,
|
|
102
|
+
{ stage }: IncludePredicateCtx,
|
|
103
|
+
) {
|
|
104
|
+
const dfs = (node: DeploymentNodeModel): DeploymentElementModel[] => {
|
|
105
|
+
const children = [] as DeploymentElementModel[]
|
|
106
|
+
for (const child of node.children()) {
|
|
107
|
+
if (child.isDeploymentNode()) {
|
|
108
|
+
children.push(...dfs(child))
|
|
109
|
+
}
|
|
110
|
+
children.push(child)
|
|
111
|
+
}
|
|
112
|
+
stage.connectWithExisting(children, 'in')
|
|
113
|
+
stage.addConnections(findConnectionsWithin(children))
|
|
114
|
+
stage.addImplicit(children)
|
|
115
|
+
return children
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const descendants = dfs(node)
|
|
119
|
+
if (descendants.length === 0) {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
stage.connectWithExisting(descendants, 'out')
|
|
123
|
+
// stage.addImplicit(descendants)
|
|
124
|
+
|
|
125
|
+
const allconnected = findConnectedElements(stage)
|
|
126
|
+
descendants.forEach((desc) => {
|
|
127
|
+
if (allconnected.has(desc)) {
|
|
128
|
+
stage.addExplicit(desc)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function findConnectedElements(stage: StageInclude) {
|
|
134
|
+
return pipe(
|
|
135
|
+
stage.mergedConnections(),
|
|
136
|
+
cleanCrossBoundary,
|
|
137
|
+
cleanRedundantRelationships,
|
|
138
|
+
reduce((acc, c) => {
|
|
139
|
+
acc.add(c.source)
|
|
140
|
+
acc.add(c.target)
|
|
141
|
+
return acc
|
|
142
|
+
}, new Set<Elem>()),
|
|
143
|
+
)
|
|
144
|
+
}
|
|
@@ -1,130 +1,237 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { filter, flatMap, isNonNullish, map, pipe } from 'remeda'
|
|
2
2
|
import { invariant } from '../../../errors'
|
|
3
3
|
import type { LikeC4DeploymentModel } from '../../../model'
|
|
4
|
-
import { findConnectionsBetween } from '../../../model/connection/deployment'
|
|
5
4
|
import type { DeploymentConnectionModel } from '../../../model/connection/deployment'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
5
|
+
import { findConnection, findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/deployment'
|
|
6
|
+
import { findConnectionsBetween as findModelConnectionsBetween } from '../../../model/connection/model'
|
|
7
|
+
import type { ConnectionModel } from '../../../model/connection/model/ConnectionModel'
|
|
8
|
+
import type { DeploymentElementModel } from '../../../model/DeploymentElementModel'
|
|
9
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
10
|
+
import type { AnyAux } from '../../../model/types'
|
|
11
|
+
import { type RelationExpr, FqnExpr } from '../../../types'
|
|
12
|
+
import { hasIntersection, intersection } from '../../../utils/set'
|
|
13
|
+
import type { ExcludePredicateCtx, PredicateExecutor } from '../_types'
|
|
14
|
+
import type { StageExclude } from '../memory'
|
|
15
|
+
import { deploymentExpressionToPredicate, resolveElements, resolveModelElements } from '../utils'
|
|
16
|
+
import { filterIncomingConnections, resolveAllImcomingRelations } from './relation-incoming'
|
|
17
|
+
import { filterOutgoingConnections, resolveAllOutgoingRelations } from './relation-outgoing'
|
|
11
18
|
|
|
12
|
-
const isRef = DeploymentElementExpression.isRef
|
|
19
|
+
// const isRef = DeploymentElementExpression.isRef
|
|
13
20
|
|
|
14
21
|
export const resolveAscendingSiblings = (element: DeploymentElementModel) => {
|
|
15
22
|
const siblings = new Set<DeploymentElementModel>()
|
|
16
|
-
for (let sibling of element.
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
for (let sibling of element.descendingSiblings()) {
|
|
24
|
+
// TODO: investigate if this is necessary
|
|
25
|
+
// if (element.isInstance() && sibling.isDeploymentNode()) {
|
|
26
|
+
// // we flatten nodes that contain only one instance
|
|
27
|
+
// sibling = sibling.onlyOneInstance() ?? sibling
|
|
28
|
+
// }
|
|
21
29
|
siblings.add(sibling)
|
|
22
30
|
}
|
|
23
31
|
return siblings
|
|
24
32
|
}
|
|
25
33
|
|
|
26
|
-
const
|
|
34
|
+
const resolveWildcard = (model: LikeC4DeploymentModel, nonWildcard: FqnExpr.DeploymentRef) => {
|
|
27
35
|
const sources = resolveElements(model, nonWildcard)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
return [sources, []] as const
|
|
36
|
+
return sources.map(source => {
|
|
37
|
+
const targets = resolveAscendingSiblings(source)
|
|
38
|
+
return [source, targets] as const
|
|
39
|
+
})
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
export const DirectRelationPredicate: PredicateExecutor<
|
|
37
|
-
include: (expr
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
export const DirectRelationPredicate: PredicateExecutor<RelationExpr.Direct> = {
|
|
43
|
+
include: ({ expr: { source, target, isBidirectional = false }, model, stage }) => {
|
|
44
|
+
invariant(!FqnExpr.isModelRef(source), 'Invalid source model ref in direct relation')
|
|
45
|
+
invariant(!FqnExpr.isModelRef(target), 'Invalid target model ref in direct relation')
|
|
46
|
+
const sourceIsWildcard = FqnExpr.isWildcard(source)
|
|
47
|
+
const targetIsWildcard = FqnExpr.isWildcard(target)
|
|
48
|
+
|
|
49
|
+
const dir = isBidirectional ? 'both' : 'directed'
|
|
40
50
|
|
|
41
|
-
let
|
|
51
|
+
let connections
|
|
42
52
|
|
|
43
53
|
switch (true) {
|
|
54
|
+
// * -> *
|
|
44
55
|
case sourceIsWildcard && targetIsWildcard: {
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
connections = findConnectionsWithin(model.instances()).map(c => {
|
|
57
|
+
stage.addImplicit(c.boundary)
|
|
58
|
+
return c
|
|
59
|
+
})
|
|
47
60
|
break
|
|
48
61
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
|
|
63
|
+
// source -> *; source <-> *
|
|
64
|
+
case !sourceIsWildcard && targetIsWildcard: {
|
|
65
|
+
const sources = resolveElements(model, source)
|
|
66
|
+
const isSource = filterOutgoingConnections(sources)
|
|
67
|
+
|
|
68
|
+
let postFilter = isSource
|
|
69
|
+
if (isBidirectional) {
|
|
70
|
+
const isTarget = filterIncomingConnections(sources)
|
|
71
|
+
postFilter = c => isSource(c) !== isTarget(c)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
connections = sources
|
|
75
|
+
.flatMap(source => {
|
|
76
|
+
const targets = resolveAscendingSiblings(source)
|
|
77
|
+
return findConnectionsBetween(source, targets, dir)
|
|
78
|
+
})
|
|
79
|
+
.filter(postFilter)
|
|
56
80
|
break
|
|
57
81
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
// * -> target; * <-> target
|
|
83
|
+
case sourceIsWildcard && !targetIsWildcard: {
|
|
84
|
+
const targets = resolveElements(model, target)
|
|
85
|
+
const isTarget = filterIncomingConnections(targets)
|
|
86
|
+
|
|
87
|
+
let postFilter = isTarget
|
|
88
|
+
if (isBidirectional) {
|
|
89
|
+
const isSource = filterOutgoingConnections(targets)
|
|
90
|
+
postFilter = c => isSource(c) !== isTarget(c)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
connections = targets
|
|
94
|
+
.flatMap(target => {
|
|
95
|
+
const sources = resolveAscendingSiblings(target)
|
|
96
|
+
return [...sources].flatMap(source => findConnection(source, target, dir))
|
|
97
|
+
})
|
|
98
|
+
.filter(postFilter)
|
|
66
99
|
break
|
|
67
100
|
}
|
|
68
101
|
default: {
|
|
69
|
-
invariant(
|
|
70
|
-
invariant(
|
|
71
|
-
sources = resolveElements(model,
|
|
72
|
-
targets = resolveElements(model,
|
|
73
|
-
}
|
|
74
|
-
}
|
|
102
|
+
invariant(!sourceIsWildcard, 'Inferrence failed - source should be a deployment ref')
|
|
103
|
+
invariant(!targetIsWildcard, 'Inferrence failed - target should be a deployment ref')
|
|
104
|
+
const sources = resolveElements(model, source)
|
|
105
|
+
const targets = resolveElements(model, target)
|
|
75
106
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
107
|
+
const isSource = filterOutgoingConnections(sources)
|
|
108
|
+
const isTarget = filterIncomingConnections(targets)
|
|
79
109
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
110
|
+
connections = pipe(
|
|
111
|
+
sources,
|
|
112
|
+
flatMap(s => findConnectionsBetween(s, targets, dir)),
|
|
113
|
+
filter(c => isSource(c) && isTarget(c)),
|
|
114
|
+
)
|
|
115
|
+
}
|
|
83
116
|
}
|
|
84
117
|
|
|
85
|
-
|
|
86
|
-
return identity()
|
|
87
|
-
}
|
|
118
|
+
stage.addConnections(connections)
|
|
88
119
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
stage.addImplicit(c.boundary)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (isRef(expr.source) && isNonNullish(expr.source.selector)) {
|
|
95
|
-
stage.addImplicit(model.element(expr.source.ref))
|
|
120
|
+
if (FqnExpr.isDeploymentRef(source) && isNonNullish(source.selector)) {
|
|
121
|
+
stage.addImplicit(model.element(source.ref.deployment))
|
|
96
122
|
}
|
|
97
|
-
if (
|
|
98
|
-
stage.addImplicit(model.element(
|
|
123
|
+
if (FqnExpr.isDeploymentRef(target) && isNonNullish(target.selector)) {
|
|
124
|
+
stage.addImplicit(model.element(target.ref.deployment))
|
|
99
125
|
}
|
|
100
126
|
|
|
101
|
-
return stage
|
|
127
|
+
return stage
|
|
102
128
|
},
|
|
103
|
-
exclude: (expr,
|
|
129
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
104
130
|
// * -> *
|
|
105
131
|
// Exclude all connections
|
|
106
132
|
if (
|
|
107
|
-
|
|
108
|
-
&&
|
|
133
|
+
FqnExpr.isWildcard(expr.source)
|
|
134
|
+
&& FqnExpr.isWildcard(expr.target)
|
|
109
135
|
) {
|
|
110
136
|
stage.excludeConnections(memory.connections)
|
|
111
|
-
return stage
|
|
137
|
+
return stage
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (FqnExpr.isModelRef(expr.source) && FqnExpr.isModelRef(expr.target)) {
|
|
141
|
+
const toExclude = resolveRelationsBetweenModelElements({
|
|
142
|
+
source: expr.source,
|
|
143
|
+
target: expr.target,
|
|
144
|
+
expr,
|
|
145
|
+
model,
|
|
146
|
+
})
|
|
147
|
+
return excludeModelRelations(toExclude, { stage, memory })
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (FqnExpr.isModelRef(expr.source)) {
|
|
151
|
+
if (FqnExpr.isWildcard(expr.target)) {
|
|
152
|
+
const toExclude = resolveAllOutgoingRelations(model, expr.source)
|
|
153
|
+
return excludeModelRelations(toExclude, { stage, memory })
|
|
154
|
+
}
|
|
155
|
+
const allOutgoing = resolveAllOutgoingRelations(model, expr.source)
|
|
156
|
+
const isTarget = deploymentExpressionToPredicate(expr.target)
|
|
157
|
+
return excludeModelRelations(
|
|
158
|
+
allOutgoing,
|
|
159
|
+
{ stage, memory },
|
|
160
|
+
c => isTarget(c.target),
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (FqnExpr.isModelRef(expr.target)) {
|
|
165
|
+
const toExclude = resolveAllImcomingRelations(model, expr.target)
|
|
166
|
+
const isSource = deploymentExpressionToPredicate(expr.source)
|
|
167
|
+
return excludeModelRelations(
|
|
168
|
+
toExclude,
|
|
169
|
+
{ stage, memory },
|
|
170
|
+
c => isSource(c.source),
|
|
171
|
+
)
|
|
112
172
|
}
|
|
113
173
|
|
|
114
174
|
const isSource = deploymentExpressionToPredicate(expr.source)
|
|
115
175
|
const isTarget = deploymentExpressionToPredicate(expr.target)
|
|
116
176
|
|
|
117
177
|
const satisfies = (connection: DeploymentConnectionModel) => {
|
|
118
|
-
return isSource(connection.source) && isTarget(connection.target)
|
|
178
|
+
return (isSource(connection.source) && isTarget(connection.target))
|
|
119
179
|
|| (expr.isBidirectional && isSource(connection.target) && isTarget(connection.source))
|
|
120
180
|
}
|
|
121
181
|
|
|
122
182
|
const toExclude = memory.connections.filter(satisfies)
|
|
123
|
-
if (toExclude.length === 0) {
|
|
124
|
-
return identity()
|
|
125
|
-
}
|
|
126
183
|
|
|
127
184
|
stage.excludeConnections(toExclude)
|
|
128
|
-
return stage
|
|
185
|
+
return stage
|
|
186
|
+
},
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function excludeModelRelations(
|
|
190
|
+
relationsToExclude: ReadonlySet<RelationshipModel<AnyAux>>,
|
|
191
|
+
{ stage, memory }: Pick<ExcludePredicateCtx, 'stage' | 'memory'>,
|
|
192
|
+
// Optional filter to scope the connections to exclude
|
|
193
|
+
filterConnections: (c: DeploymentConnectionModel) => boolean = () => true,
|
|
194
|
+
): StageExclude {
|
|
195
|
+
if (relationsToExclude.size === 0) {
|
|
196
|
+
return stage
|
|
197
|
+
}
|
|
198
|
+
const toExclude = pipe(
|
|
199
|
+
memory.connections,
|
|
200
|
+
// Find connections that have at least one relation in common with the excluded relations
|
|
201
|
+
filter(c => filterConnections(c) && hasIntersection(c.relations.model, relationsToExclude)),
|
|
202
|
+
map(c =>
|
|
203
|
+
c.update({
|
|
204
|
+
deployment: null,
|
|
205
|
+
model: intersection(c.relations.model, relationsToExclude),
|
|
206
|
+
})
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
if (toExclude.length === 0) {
|
|
210
|
+
return stage
|
|
211
|
+
}
|
|
212
|
+
return stage.excludeConnections(toExclude)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function resolveRelationsBetweenModelElements({
|
|
216
|
+
source,
|
|
217
|
+
target,
|
|
218
|
+
expr,
|
|
219
|
+
model,
|
|
220
|
+
}: {
|
|
221
|
+
source: FqnExpr.ModelRef
|
|
222
|
+
target: FqnExpr.ModelRef
|
|
223
|
+
expr: RelationExpr.Direct
|
|
224
|
+
model: LikeC4DeploymentModel
|
|
225
|
+
}) {
|
|
226
|
+
const sources = resolveModelElements(model, source)
|
|
227
|
+
const targets = resolveModelElements(model, target)
|
|
228
|
+
|
|
229
|
+
const dir = expr.isBidirectional ? 'both' : 'directed'
|
|
230
|
+
|
|
231
|
+
const modelConnections = [] as ConnectionModel[]
|
|
232
|
+
for (const source of sources) {
|
|
233
|
+
modelConnections.push(...findModelConnectionsBetween(source, targets, dir))
|
|
129
234
|
}
|
|
235
|
+
|
|
236
|
+
return new Set(modelConnections.flatMap(c => [...c.relations]))
|
|
130
237
|
}
|
|
@@ -1,43 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { DeploymentConnectionModel } from '../../../model/connection/deployment'
|
|
1
|
+
import { invariant } from '../../../errors'
|
|
3
2
|
import { findConnectionsBetween } from '../../../model/connection/deployment'
|
|
4
|
-
import {
|
|
3
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
4
|
+
import type { AnyAux } from '../../../model/types'
|
|
5
|
+
import { FqnExpr, type RelationExpr } from '../../../types/expression-v2'
|
|
6
|
+
import { union } from '../../../utils/set'
|
|
5
7
|
import type { PredicateExecutor } from '../_types'
|
|
6
|
-
import {
|
|
7
|
-
import { resolveAscendingSiblings } from './relation-direct'
|
|
8
|
+
import { resolveElements, resolveModelElements } from '../utils'
|
|
9
|
+
import { excludeModelRelations, resolveAscendingSiblings } from './relation-direct'
|
|
10
|
+
import { filterIncomingConnections } from './relation-incoming'
|
|
11
|
+
import { filterOutgoingConnections } from './relation-outgoing'
|
|
8
12
|
|
|
9
13
|
//
|
|
10
|
-
export const InOutRelationPredicate: PredicateExecutor<
|
|
11
|
-
include: (expr,
|
|
14
|
+
export const InOutRelationPredicate: PredicateExecutor<RelationExpr.InOut> = {
|
|
15
|
+
include: ({ expr, model, memory, stage }) => {
|
|
12
16
|
const sources = [...memory.elements]
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
if (FqnExpr.isWildcard(expr.inout)) {
|
|
14
19
|
for (const source of sources) {
|
|
15
20
|
const targets = [...resolveAscendingSiblings(source)]
|
|
16
21
|
stage.addConnections(findConnectionsBetween(source, targets, 'both'))
|
|
17
22
|
}
|
|
18
|
-
return stage
|
|
23
|
+
return stage
|
|
19
24
|
}
|
|
25
|
+
invariant(FqnExpr.isDeploymentRef(expr.inout), 'Only deployment refs are supported in include')
|
|
20
26
|
|
|
21
27
|
const targets = resolveElements(model, expr.inout)
|
|
22
28
|
for (const source of sources) {
|
|
23
29
|
stage.addConnections(findConnectionsBetween(source, targets, 'both'))
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
return stage
|
|
32
|
+
return stage
|
|
27
33
|
},
|
|
28
|
-
exclude: (expr,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
35
|
+
// Exclude all connections that have model relationshps with the elements
|
|
36
|
+
if (FqnExpr.isModelRef(expr.inout)) {
|
|
37
|
+
const elements = resolveModelElements(model, expr.inout)
|
|
38
|
+
if (elements.length === 0) {
|
|
39
|
+
return stage
|
|
40
|
+
}
|
|
41
|
+
const excludedRelations = union(
|
|
42
|
+
new Set<RelationshipModel<AnyAux>>(),
|
|
43
|
+
...elements.flatMap(e => [e.allIncoming, e.allOutgoing]),
|
|
44
|
+
)
|
|
45
|
+
return excludeModelRelations(excludedRelations, { stage, memory })
|
|
33
46
|
}
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return
|
|
48
|
+
if (FqnExpr.isWildcard(expr.inout)) {
|
|
49
|
+
// non-sense
|
|
50
|
+
return stage
|
|
38
51
|
}
|
|
39
52
|
|
|
53
|
+
const elements = resolveElements(model, expr.inout)
|
|
54
|
+
const isIncoming = filterIncomingConnections(elements)
|
|
55
|
+
const isOutgoing = filterOutgoingConnections(elements)
|
|
56
|
+
|
|
57
|
+
const toExclude = memory.connections.filter(c => isIncoming(c) !== isOutgoing(c))
|
|
40
58
|
stage.excludeConnections(toExclude)
|
|
41
|
-
return stage
|
|
42
|
-
}
|
|
59
|
+
return stage
|
|
60
|
+
},
|
|
43
61
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { anyPass } from 'remeda'
|
|
2
|
+
import { invariant } from '../../../errors'
|
|
3
|
+
import { findConnectionsBetween } from '../../../model/connection/deployment'
|
|
4
|
+
import type { LikeC4DeploymentModel } from '../../../model/DeploymentModel'
|
|
5
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
6
|
+
import type { AnyAux } from '../../../model/types'
|
|
7
|
+
import { FqnExpr, type RelationExpr } from '../../../types'
|
|
8
|
+
import { isAncestor } from '../../../utils/fqn'
|
|
9
|
+
import type { Connection, Elem, PredicateExecutor } from '../_types'
|
|
10
|
+
import { resolveElements, resolveModelElements } from '../utils'
|
|
11
|
+
import { excludeModelRelations, resolveAscendingSiblings } from './relation-direct'
|
|
8
12
|
|
|
9
13
|
// from visible element incoming to this
|
|
10
|
-
export const IncomingRelationPredicate: PredicateExecutor<
|
|
11
|
-
include: (expr,
|
|
14
|
+
export const IncomingRelationPredicate: PredicateExecutor<RelationExpr.Incoming> = {
|
|
15
|
+
include: ({ expr, model, memory, stage }) => {
|
|
12
16
|
const sources = [...memory.elements]
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
if (FqnExpr.isWildcard(expr.incoming)) {
|
|
14
19
|
for (const source of sources) {
|
|
15
20
|
if (source.allOutgoing.isEmpty) {
|
|
16
21
|
continue
|
|
@@ -18,29 +23,73 @@ export const IncomingRelationPredicate: PredicateExecutor<DeploymentRelationExpr
|
|
|
18
23
|
const targets = [...resolveAscendingSiblings(source)]
|
|
19
24
|
stage.addConnections(findConnectionsBetween(source, targets, 'directed'))
|
|
20
25
|
}
|
|
21
|
-
return stage
|
|
26
|
+
return stage
|
|
22
27
|
}
|
|
28
|
+
invariant(FqnExpr.isDeploymentRef(expr.incoming), 'Only deployment refs are supported in include')
|
|
23
29
|
|
|
24
30
|
const targets = resolveElements(model, expr.incoming)
|
|
25
31
|
for (const source of sources) {
|
|
26
32
|
stage.addConnections(findConnectionsBetween(source, targets, 'directed'))
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
return stage
|
|
35
|
+
return stage
|
|
30
36
|
},
|
|
31
|
-
exclude: (expr,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return
|
|
37
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
38
|
+
// Exclude all connections that have model relationshps with the elements
|
|
39
|
+
if (FqnExpr.isModelRef(expr.incoming)) {
|
|
40
|
+
const excludedRelations = resolveAllImcomingRelations(model, expr.incoming)
|
|
41
|
+
return excludeModelRelations(excludedRelations, { stage, memory })
|
|
36
42
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return identity()
|
|
43
|
+
if (FqnExpr.isWildcard(expr.incoming)) {
|
|
44
|
+
// non-sense
|
|
45
|
+
return stage
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
const isIncoming = filterIncomingConnections(resolveElements(model, expr.incoming))
|
|
49
|
+
const toExclude = memory.connections.filter(isIncoming)
|
|
43
50
|
stage.excludeConnections(toExclude)
|
|
44
|
-
return stage
|
|
45
|
-
}
|
|
51
|
+
return stage
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function filterIncomingConnections(
|
|
56
|
+
targets: Elem[],
|
|
57
|
+
): (connection: Connection) => boolean {
|
|
58
|
+
return anyPass(
|
|
59
|
+
targets.map(target => {
|
|
60
|
+
const satisfies = (el: Elem) => el === target || isAncestor(target, el)
|
|
61
|
+
return (connection: Connection) => {
|
|
62
|
+
return !satisfies(connection.source) && satisfies(connection.target)
|
|
63
|
+
}
|
|
64
|
+
}),
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
// model: LikeC4DeploymentModel,
|
|
68
|
+
// model: LikeC4DeploymentModel,
|
|
69
|
+
// expr: FqnExpr.DeploymentRef
|
|
70
|
+
// ): (connection: Connection) => boolean {
|
|
71
|
+
// if (FqnExpr.isWildcard(expr)) {
|
|
72
|
+
// return () => true
|
|
73
|
+
// }
|
|
74
|
+
// if (isNullish(expr.selector)) {
|
|
75
|
+
// // -> element
|
|
76
|
+
// const target = model.element(expr.ref.deployment)
|
|
77
|
+
// const isInside = (el: Elem) => el === target || isAncestor(target, el)
|
|
78
|
+
// return (connection) => {
|
|
79
|
+
// return !isInside(connection.source) && isInside(connection.target)
|
|
80
|
+
// }
|
|
81
|
+
// }
|
|
82
|
+
|
|
83
|
+
// const isTarget = deploymentExpressionToPredicate(expr)
|
|
84
|
+
// return (connection) => {
|
|
85
|
+
// return isTarget(connection.target)
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
export function resolveAllImcomingRelations(
|
|
90
|
+
model: LikeC4DeploymentModel,
|
|
91
|
+
moodelRef: FqnExpr.ModelRef,
|
|
92
|
+
): Set<RelationshipModel<AnyAux>> {
|
|
93
|
+
const targets = resolveModelElements(model, moodelRef)
|
|
94
|
+
return new Set(targets.flatMap(e => [...e.allIncoming]))
|
|
46
95
|
}
|