@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
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { anyPass } from 'remeda'
|
|
2
|
+
import { invariant } from '../../../errors'
|
|
3
|
+
import type { LikeC4DeploymentModel } from '../../../model'
|
|
2
4
|
import { findConnection, findConnectionsBetween } from '../../../model/connection/deployment'
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
6
|
+
import { FqnExpr, type RelationExpr } from '../../../types'
|
|
7
|
+
import { isAncestor } from '../../../utils'
|
|
8
|
+
import type { Connection, Elem, PredicateExecutor } from '../_types'
|
|
9
|
+
import { resolveElements, resolveModelElements } from '../utils'
|
|
10
|
+
import { excludeModelRelations, resolveAscendingSiblings } from './relation-direct'
|
|
8
11
|
|
|
9
|
-
export const OutgoingRelationPredicate: PredicateExecutor<
|
|
10
|
-
include: (expr,
|
|
12
|
+
export const OutgoingRelationPredicate: PredicateExecutor<RelationExpr.Outgoing> = {
|
|
13
|
+
include: ({ expr, model, memory, stage }) => {
|
|
11
14
|
const targets = [...memory.elements]
|
|
12
15
|
|
|
13
16
|
// * -> (to visible elements)
|
|
14
17
|
// outgoing from wildcard to visible element
|
|
15
|
-
if (
|
|
18
|
+
if (FqnExpr.isWildcard(expr.outgoing)) {
|
|
16
19
|
for (const target of targets) {
|
|
17
20
|
if (target.allIncoming.isEmpty) {
|
|
18
21
|
continue
|
|
@@ -21,29 +24,65 @@ export const OutgoingRelationPredicate: PredicateExecutor<DeploymentRelationExpr
|
|
|
21
24
|
stage.addConnections(findConnection(source, target, 'directed'))
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
return stage
|
|
27
|
+
return stage
|
|
25
28
|
}
|
|
29
|
+
invariant(FqnExpr.isDeploymentRef(expr.outgoing), 'Only deployment refs are supported in include')
|
|
26
30
|
|
|
27
31
|
const sources = resolveElements(model, expr.outgoing)
|
|
28
32
|
for (const source of sources) {
|
|
29
33
|
stage.addConnections(findConnectionsBetween(source, targets, 'directed'))
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
return stage
|
|
36
|
+
return stage
|
|
33
37
|
},
|
|
34
|
-
exclude: (expr,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return
|
|
38
|
+
exclude: ({ expr, model, memory, stage }) => {
|
|
39
|
+
// Exclude all connections that have model relationshps with the elements
|
|
40
|
+
if (FqnExpr.isModelRef(expr.outgoing)) {
|
|
41
|
+
const excludedRelations = resolveAllOutgoingRelations(model, expr.outgoing)
|
|
42
|
+
return excludeModelRelations(excludedRelations, { stage, memory })
|
|
39
43
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return identity()
|
|
44
|
+
if (FqnExpr.isWildcard(expr.outgoing)) {
|
|
45
|
+
// non-sense
|
|
46
|
+
return stage
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
const isOutgoing = filterOutgoingConnections(resolveElements(model, expr.outgoing))
|
|
50
|
+
const toExclude = memory.connections.filter(isOutgoing)
|
|
46
51
|
stage.excludeConnections(toExclude)
|
|
47
|
-
return stage
|
|
48
|
-
}
|
|
52
|
+
return stage
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function filterOutgoingConnections(
|
|
57
|
+
sources: Elem[],
|
|
58
|
+
): (connection: Connection) => boolean {
|
|
59
|
+
return anyPass(
|
|
60
|
+
sources.map(source => {
|
|
61
|
+
const satisfies = (el: Elem) => el === source || isAncestor(source, el)
|
|
62
|
+
return (connection: Connection) => {
|
|
63
|
+
return satisfies(connection.source) && !satisfies(connection.target)
|
|
64
|
+
}
|
|
65
|
+
}),
|
|
66
|
+
)
|
|
67
|
+
// if (FqnExpr.isDeploymentRef(expr) && isNullish(expr.selector)) {
|
|
68
|
+
// // element ->
|
|
69
|
+
// const source = model.element(expr.ref.deployment)
|
|
70
|
+
// const isInside = (el: Elem) => el === source || isAncestor(source, el)
|
|
71
|
+
// return (connection: Connection) => {
|
|
72
|
+
// return isInside(connection.source) && !isInside(connection.target)
|
|
73
|
+
// }
|
|
74
|
+
// } else {
|
|
75
|
+
// const isSource = deploymentExpressionToPredicate(expr)
|
|
76
|
+
// return (connection: Connection) => {
|
|
77
|
+
// return isSource(connection.source)
|
|
78
|
+
// }
|
|
79
|
+
// }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function resolveAllOutgoingRelations(
|
|
83
|
+
model: LikeC4DeploymentModel,
|
|
84
|
+
moodelRef: FqnExpr.ModelRef,
|
|
85
|
+
): Set<RelationshipModel> {
|
|
86
|
+
const targets = resolveModelElements(model, moodelRef)
|
|
87
|
+
return new Set(targets.flatMap(e => [...e.allOutgoing]))
|
|
49
88
|
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { findConnectionsWithin } from '../../../model/connection/deployment'
|
|
2
|
-
import type {
|
|
3
|
-
import type
|
|
4
|
-
import { MutableMemory } from '../Memory'
|
|
2
|
+
import type { FqnExpr } from '../../../types'
|
|
3
|
+
import { type Elem, type PredicateExecutor } from '../_types'
|
|
5
4
|
|
|
6
|
-
export const WildcardPredicate: PredicateExecutor<
|
|
7
|
-
include: (
|
|
5
|
+
export const WildcardPredicate: PredicateExecutor<FqnExpr.Wildcard> = {
|
|
6
|
+
include: ({ model, stage }) => {
|
|
8
7
|
const children = [] as Elem[]
|
|
9
8
|
|
|
10
9
|
const rootElements = [...model.roots()].map(root => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
children.push(onlyOneInstance)
|
|
14
|
-
return onlyOneInstance
|
|
10
|
+
if (!root.onlyOneInstance()) {
|
|
11
|
+
children.push(...root.children())
|
|
15
12
|
}
|
|
16
|
-
children.push(...root.children())
|
|
17
13
|
return root
|
|
18
14
|
})
|
|
19
15
|
|
|
20
16
|
stage.addExplicit(rootElements)
|
|
21
17
|
if (children.length > 1) {
|
|
22
|
-
stage.addConnections(findConnectionsWithin(
|
|
18
|
+
stage.addConnections(findConnectionsWithin([
|
|
19
|
+
...rootElements,
|
|
20
|
+
...children,
|
|
21
|
+
]))
|
|
23
22
|
}
|
|
24
|
-
return stage
|
|
23
|
+
return stage
|
|
24
|
+
},
|
|
25
|
+
exclude: ({ stage, memory }) => {
|
|
26
|
+
stage.exclude(memory.elements)
|
|
27
|
+
return stage
|
|
25
28
|
},
|
|
26
|
-
exclude: () => {
|
|
27
|
-
return () => MutableMemory.empty()
|
|
28
|
-
}
|
|
29
29
|
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import DefaultMap from 'mnemonist/default-map'
|
|
2
|
+
import { forEach, only, pipe } from 'remeda'
|
|
3
|
+
import { differenceConnections } from '../../../model/connection'
|
|
4
|
+
import type { RelationshipModel } from '../../../model/RelationModel'
|
|
5
|
+
import { isAncestor, sortByFqnHierarchically } from '../../../utils/fqn'
|
|
6
|
+
import { ifilter, isome, toArray } from '../../../utils/iterable'
|
|
7
|
+
import { difference, union } from '../../../utils/set'
|
|
8
|
+
import { treeFromMemoryState } from '../../memory'
|
|
9
|
+
import { cleanCrossBoundary, cleanRedundantRelationships } from '../clean-connections'
|
|
10
|
+
import type { Ctx, Memory } from '../memory'
|
|
11
|
+
|
|
12
|
+
type Elem = Ctx['Element']
|
|
13
|
+
/**
|
|
14
|
+
* This patch:
|
|
15
|
+
* 1. Keeps connections between leafs or having direct deployment relations
|
|
16
|
+
* 2. Removes cross-boundary model relations, that already exist inside boundaries
|
|
17
|
+
* (e.g. prefer relations inside same deployment node over relations between nodes)
|
|
18
|
+
* 3. Removes implicit connections between elements, if their descendants have same connection
|
|
19
|
+
*/
|
|
20
|
+
export class StageFinal {
|
|
21
|
+
static for(memory: Memory) {
|
|
22
|
+
return new StageFinal(memory)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private constructor(
|
|
26
|
+
protected readonly memory: Memory,
|
|
27
|
+
) {
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public step1CleanConnections(memory: Memory): Memory {
|
|
31
|
+
if (memory.connections.length < 2) {
|
|
32
|
+
return memory
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// const leafs = new Set<Elem>()
|
|
36
|
+
|
|
37
|
+
// for (const element of memory.final) {
|
|
38
|
+
// // Instance is always leaf
|
|
39
|
+
// if (element.isInstance()) {
|
|
40
|
+
// leafs.add(element)
|
|
41
|
+
// continue
|
|
42
|
+
// }
|
|
43
|
+
// // Check if element is ancestor of any element in elements
|
|
44
|
+
// let isLeaf = true
|
|
45
|
+
// for (const el of memory.final) {
|
|
46
|
+
// if (isAncestor(element.id, el.id)) {
|
|
47
|
+
// isLeaf = false
|
|
48
|
+
// break
|
|
49
|
+
// }
|
|
50
|
+
// }
|
|
51
|
+
// if (isLeaf) {
|
|
52
|
+
// leafs.add(element)
|
|
53
|
+
// }
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
const connections = pipe(
|
|
57
|
+
memory.connections,
|
|
58
|
+
// Keep connections
|
|
59
|
+
// - between leafs
|
|
60
|
+
// - has direct deployment relation
|
|
61
|
+
// filter(c => {
|
|
62
|
+
// return (leafs.has(c.source) && leafs.has(c.target)) || c.hasDirectDeploymentRelation()
|
|
63
|
+
// }),
|
|
64
|
+
cleanCrossBoundary,
|
|
65
|
+
cleanRedundantRelationships,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const connectionsToExclude = differenceConnections(
|
|
69
|
+
memory.connections,
|
|
70
|
+
connections,
|
|
71
|
+
)
|
|
72
|
+
if (connectionsToExclude.length === 0) {
|
|
73
|
+
return memory
|
|
74
|
+
}
|
|
75
|
+
const stage = memory.stageExclude({} as any)
|
|
76
|
+
stage.excludeConnections(connectionsToExclude, true)
|
|
77
|
+
return stage.commit()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public step2ProcessImplicits(memory: Memory): Memory {
|
|
81
|
+
const implicits = union(this.memory.elements, memory.elements)
|
|
82
|
+
const final = union(memory.final, this.memory.explicits)
|
|
83
|
+
|
|
84
|
+
// Find connections based on same relation but different boundaries
|
|
85
|
+
const groupedByRelation = new DefaultMap<RelationshipModel, Set<Elem>>(() => new Set())
|
|
86
|
+
for (const conn of memory.connections) {
|
|
87
|
+
if (conn.boundary) {
|
|
88
|
+
for (const relation of conn.relations.model) {
|
|
89
|
+
groupedByRelation.get(relation).add(conn.boundary)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const [_, boundaries] of groupedByRelation) {
|
|
94
|
+
if (boundaries.size < 2) {
|
|
95
|
+
continue
|
|
96
|
+
}
|
|
97
|
+
for (const boundary of boundaries) {
|
|
98
|
+
if (implicits.delete(boundary)) {
|
|
99
|
+
final.add(boundary)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const snapshot = new Set(final)
|
|
105
|
+
const isFinalOrHasIncludedDescendant = (el: Elem) => {
|
|
106
|
+
for (const final of snapshot) {
|
|
107
|
+
if (el === final || isAncestor(el, final)) {
|
|
108
|
+
return true
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Pick from implicit elements
|
|
115
|
+
pipe(
|
|
116
|
+
difference(implicits, snapshot),
|
|
117
|
+
ifilter(e => e.isDeploymentNode()),
|
|
118
|
+
toArray(),
|
|
119
|
+
sortByFqnHierarchically,
|
|
120
|
+
forEach((el) => {
|
|
121
|
+
// If element has more 2 or more children included
|
|
122
|
+
// It can "box" around
|
|
123
|
+
const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length
|
|
124
|
+
if (childrensToWrap >= 2) {
|
|
125
|
+
final.add(el)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
// If Element has only one child included
|
|
129
|
+
// and has "similar" sibling with included descendant
|
|
130
|
+
if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) {
|
|
131
|
+
final.add(el)
|
|
132
|
+
}
|
|
133
|
+
}),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return memory.update({ final })
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public step3ProcessBoundaries(memory: Memory): Memory {
|
|
140
|
+
const boundaries = new Set<Elem>()
|
|
141
|
+
for (const conn of memory.connections) {
|
|
142
|
+
if (conn.boundary) {
|
|
143
|
+
boundaries.add(conn.boundary)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const tree = treeFromMemoryState<Ctx>(memory, 'final')
|
|
147
|
+
const stage = memory.stageExclude({} as any)
|
|
148
|
+
|
|
149
|
+
const isRemovable = (el: Elem) =>
|
|
150
|
+
!(
|
|
151
|
+
boundaries.has(el)
|
|
152
|
+
|| memory.explicits.has(el)
|
|
153
|
+
|| tree.hasInOut(el)
|
|
154
|
+
|| tree.root.has(el)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const singleRoot = only([...tree.root])
|
|
158
|
+
if (singleRoot && !memory.explicits.has(singleRoot)) {
|
|
159
|
+
stage.exclude(singleRoot)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const el of memory.final) {
|
|
163
|
+
const singleChild = only(tree.children(el))
|
|
164
|
+
if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) {
|
|
165
|
+
stage.exclude(el)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (stage.isDirty()) {
|
|
170
|
+
return stage.commit()
|
|
171
|
+
}
|
|
172
|
+
return memory
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// TODO: Lot of corner cases to cover, skip for now
|
|
176
|
+
// public step3FlatNodes(memory: Memory): Memory {
|
|
177
|
+
// // final implicits
|
|
178
|
+
// const explicits = new Set<Elem>([
|
|
179
|
+
// ...memory.explicits,
|
|
180
|
+
// ...memory.connections.flatMap(c => [c.source, c.target]),
|
|
181
|
+
// ])
|
|
182
|
+
// const sorted = sortParentsFirst(toArray(memory.final))
|
|
183
|
+
|
|
184
|
+
// const toplevel = new Set<Elem>(sorted)
|
|
185
|
+
// const children = sorted.reduce((acc, el, index, all) => {
|
|
186
|
+
// acc.set(
|
|
187
|
+
// el,
|
|
188
|
+
// new Set(
|
|
189
|
+
// all
|
|
190
|
+
// .slice(index + 1)
|
|
191
|
+
// .filter(e => isAncestor(el, e))
|
|
192
|
+
// .reduce((acc, el) => {
|
|
193
|
+
// if (!acc.some(e => isAncestor(e, el))) {
|
|
194
|
+
// toplevel.delete(el)
|
|
195
|
+
// acc.push(el)
|
|
196
|
+
// }
|
|
197
|
+
// return acc
|
|
198
|
+
// }, [] as Elem[]),
|
|
199
|
+
// ),
|
|
200
|
+
// )
|
|
201
|
+
// return acc
|
|
202
|
+
// }, new DefaultMap<Elem, Set<Elem>>(() => new Set()))
|
|
203
|
+
|
|
204
|
+
// const state = memory.mutableState()
|
|
205
|
+
|
|
206
|
+
// function flattenNode(node: Elem) {
|
|
207
|
+
// const _children = [...children.get(node)]
|
|
208
|
+
// if (_children.length > 1) {
|
|
209
|
+
// for (const child of _children) {
|
|
210
|
+
// flattenNode(child)
|
|
211
|
+
// }
|
|
212
|
+
// return !explicits.has(node)
|
|
213
|
+
// }
|
|
214
|
+
// if (hasAtLeast(_children, 1)) {
|
|
215
|
+
// if (flattenNode(_children[0])) {
|
|
216
|
+
// state.final.delete(_children[0])
|
|
217
|
+
// }
|
|
218
|
+
// }
|
|
219
|
+
// return !explicits.has(node)
|
|
220
|
+
// }
|
|
221
|
+
|
|
222
|
+
// const root = [...toplevel]
|
|
223
|
+
// for (const node of root) {
|
|
224
|
+
// flattenNode(node)
|
|
225
|
+
// if (!explicits.has(node) && children.get(node).size === 1) {
|
|
226
|
+
// state.final.delete(node)
|
|
227
|
+
// }
|
|
228
|
+
// }
|
|
229
|
+
// if (root.length === 1 && !explicits.has(root[0]!)) {
|
|
230
|
+
// state.final.delete(root[0]!)
|
|
231
|
+
// }
|
|
232
|
+
|
|
233
|
+
// return memory.update(state)
|
|
234
|
+
// }
|
|
235
|
+
|
|
236
|
+
public commit(): Memory {
|
|
237
|
+
// return []
|
|
238
|
+
const step1 = this.step1CleanConnections(this.memory)
|
|
239
|
+
const step2 = this.step2ProcessImplicits(step1)
|
|
240
|
+
return this.step3ProcessBoundaries(step2)
|
|
241
|
+
// return step2memory
|
|
242
|
+
// const step3m?emory = this.step3FlatNodes(step2memory)
|
|
243
|
+
// return step3memory
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { dropWhile, forEach, pipe, take, zip } from 'remeda'
|
|
2
|
+
import { findConnection, findConnectionsBetween } from '../../../model/connection/deployment'
|
|
3
|
+
import { isIterable } from '../../../utils'
|
|
4
|
+
import { toArray } from '../../../utils/iterable'
|
|
5
|
+
import { type CtxConnection, type CtxElement, AbstractStageInclude } from '../../memory'
|
|
6
|
+
import { cleanCrossBoundary, cleanRedundantRelationships } from '../clean-connections'
|
|
7
|
+
import { type Ctx } from '../memory/memory'
|
|
8
|
+
|
|
9
|
+
type Elem = CtxElement<Ctx>
|
|
10
|
+
type Connection = CtxConnection<Ctx>
|
|
11
|
+
|
|
12
|
+
export class StageInclude extends AbstractStageInclude<Ctx> {
|
|
13
|
+
/**
|
|
14
|
+
* Connects elements with existing ones in the memory
|
|
15
|
+
*/
|
|
16
|
+
public override connectWithExisting(
|
|
17
|
+
elements: Elem | Iterable<Elem>,
|
|
18
|
+
direction: 'in' | 'out' | 'both' = 'both',
|
|
19
|
+
): boolean {
|
|
20
|
+
const before = this._connections.length
|
|
21
|
+
const hasChanged = () => this._connections.length > before
|
|
22
|
+
if (!isIterable(elements)) {
|
|
23
|
+
if (direction === 'in' || direction === 'both') {
|
|
24
|
+
for (const el of this.memory.elements) {
|
|
25
|
+
this.addConnections(
|
|
26
|
+
findConnection(el, elements, 'directed'),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (direction === 'out' || direction === 'both') {
|
|
31
|
+
this.addConnections(
|
|
32
|
+
findConnectionsBetween(elements, this.memory.elements, 'directed'),
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
return hasChanged()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const targets = [...elements]
|
|
39
|
+
if (direction === 'in' || direction === 'both') {
|
|
40
|
+
for (const el of this.memory.elements) {
|
|
41
|
+
this.addConnections(
|
|
42
|
+
findConnectionsBetween(el, targets, 'directed'),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (direction === 'out' || direction === 'both') {
|
|
47
|
+
for (const el of targets) {
|
|
48
|
+
this.addConnections(
|
|
49
|
+
findConnectionsBetween(el, this.memory.elements, 'directed'),
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return hasChanged()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected override processConnections(connections: Connection[]) {
|
|
57
|
+
const clean = pipe(
|
|
58
|
+
connections,
|
|
59
|
+
cleanCrossBoundary,
|
|
60
|
+
cleanRedundantRelationships,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
pipe(
|
|
64
|
+
clean,
|
|
65
|
+
// Process only connection from this stage
|
|
66
|
+
// filter(c => this._connections.some(c2 => c2.id === c.id)),
|
|
67
|
+
forEach(({ source, target, boundary }) => {
|
|
68
|
+
pipe(
|
|
69
|
+
zip(
|
|
70
|
+
[...toArray(source.ancestors()).reverse(), source],
|
|
71
|
+
[...toArray(target.ancestors()).reverse(), target],
|
|
72
|
+
),
|
|
73
|
+
// Filter out common ancestors
|
|
74
|
+
dropWhile(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor),
|
|
75
|
+
take(1),
|
|
76
|
+
forEach(([sourceAncestor, targetAncestor]) => {
|
|
77
|
+
if (source === sourceAncestor && target === targetAncestor) {
|
|
78
|
+
this.addImplicit(boundary)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if (sourceAncestor !== source && sourceAncestor.isDeploymentNode() && !sourceAncestor.onlyOneInstance()) {
|
|
82
|
+
// state.final.add(source)
|
|
83
|
+
this.addImplicit(sourceAncestor)
|
|
84
|
+
}
|
|
85
|
+
if (targetAncestor !== target && targetAncestor.isDeploymentNode() && !targetAncestor.onlyOneInstance()) {
|
|
86
|
+
// state.final.add(source)
|
|
87
|
+
this.addImplicit(targetAncestor)
|
|
88
|
+
}
|
|
89
|
+
}),
|
|
90
|
+
)
|
|
91
|
+
}),
|
|
92
|
+
)
|
|
93
|
+
return clean
|
|
94
|
+
}
|
|
95
|
+
}
|