@likec4/core 1.17.1 → 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.
Files changed (184) hide show
  1. package/LICENSE +1 -1
  2. package/dist/builder/index.d.mts +502 -0
  3. package/dist/builder/index.d.ts +502 -0
  4. package/dist/builder/index.js +871 -0
  5. package/dist/compute-view/index.d.mts +22 -0
  6. package/dist/compute-view/index.d.ts +22 -0
  7. package/dist/compute-view/index.js +78 -0
  8. package/dist/index.d.mts +10 -919
  9. package/dist/index.d.ts +10 -919
  10. package/dist/{index.mjs → index.js} +7 -1688
  11. package/dist/model/index.d.mts +254 -0
  12. package/dist/model/index.d.ts +254 -0
  13. package/dist/model/index.js +1 -0
  14. package/dist/shared/chunk-RAAYCPUM.M-JWF7SS.js +21 -0
  15. package/dist/shared/core.BIfgabEw.d.ts +719 -0
  16. package/dist/shared/core.BZ9Msq7w.d.mts +719 -0
  17. package/dist/shared/{core.CoLQkcYL.d.cts → core.C05RDLhi.d.ts} +460 -362
  18. package/dist/shared/{core.CoLQkcYL.d.mts → core.CmYMqgha.d.mts} +460 -362
  19. package/dist/shared/core.D6-fWbM3.d.ts +127 -0
  20. package/dist/shared/core.D74xkKkG.d.mts +148 -0
  21. package/dist/shared/core.D74xkKkG.d.ts +148 -0
  22. package/dist/shared/core.sLaWHBjR.d.mts +127 -0
  23. package/dist/shared/index.-BdzdI2C.js +7443 -0
  24. package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
  25. package/dist/shared/{core.BXTs-8n7.mjs → view.CyZrG8BJ.js} +108 -47
  26. package/dist/types/index.d.mts +71 -1
  27. package/dist/types/index.d.ts +71 -1
  28. package/dist/types/index.js +20 -0
  29. package/dist/utils/index.d.mts +404 -0
  30. package/dist/utils/index.d.ts +404 -0
  31. package/dist/utils/index.js +330 -0
  32. package/package.json +59 -47
  33. package/src/builder/Builder-style1.test-d.ts +190 -0
  34. package/src/builder/Builder-style2.test-d.ts +175 -0
  35. package/src/builder/Builder.deployment.ts +224 -0
  36. package/src/builder/Builder.deploymentModel.ts +385 -0
  37. package/src/builder/Builder.element.ts +19 -19
  38. package/src/builder/Builder.model.ts +67 -42
  39. package/src/builder/Builder.ts +533 -367
  40. package/src/builder/Builder.view-common.ts +234 -0
  41. package/src/builder/Builder.view-deployment.ts +135 -0
  42. package/src/builder/Builder.view-element.ts +189 -0
  43. package/src/builder/Builder.views.ts +109 -33
  44. package/src/builder/Builder.with.ts +475 -0
  45. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +374 -0
  46. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +183 -0
  47. package/src/builder/__snapshots__/Builder.spec.ts.snap +374 -0
  48. package/src/builder/_types.ts +113 -18
  49. package/src/builder/index.ts +10 -4
  50. package/src/colors/index.ts +2 -2
  51. package/src/compute-view/compute-view.ts +83 -0
  52. package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
  53. package/src/compute-view/deployment-view/__test__/fixture.ts +198 -0
  54. package/src/compute-view/deployment-view/_types.ts +37 -0
  55. package/src/compute-view/deployment-view/clean-connections.ts +238 -0
  56. package/src/compute-view/deployment-view/compute.ts +125 -0
  57. package/src/compute-view/deployment-view/memory/index.ts +9 -0
  58. package/src/compute-view/deployment-view/memory/memory.ts +97 -0
  59. package/src/compute-view/deployment-view/predicates/elements.ts +144 -0
  60. package/src/compute-view/deployment-view/predicates/relation-direct.ts +237 -0
  61. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +61 -0
  62. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +95 -0
  63. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +88 -0
  64. package/src/compute-view/deployment-view/predicates/wildcard.ts +29 -0
  65. package/src/compute-view/deployment-view/stages/stage-exclude.ts +5 -0
  66. package/src/compute-view/deployment-view/stages/stage-final.ts +245 -0
  67. package/src/compute-view/deployment-view/stages/stage-include.ts +95 -0
  68. package/src/compute-view/deployment-view/utils.ts +276 -0
  69. package/src/compute-view/dynamic-view/__test__/fixture.ts +58 -0
  70. package/src/compute-view/dynamic-view/compute.ts +324 -0
  71. package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
  72. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +458 -0
  73. package/src/compute-view/element-view/__test__/fixture.ts +675 -0
  74. package/src/compute-view/element-view/_types.ts +48 -0
  75. package/src/compute-view/element-view/clean-connections.ts +113 -0
  76. package/src/compute-view/element-view/compute.ts +315 -0
  77. package/src/compute-view/element-view/memory/NodeGroup.ts +31 -0
  78. package/src/compute-view/element-view/memory/index.ts +10 -0
  79. package/src/compute-view/element-view/memory/memory.ts +177 -0
  80. package/src/compute-view/element-view/memory/stage-exclude.ts +59 -0
  81. package/src/compute-view/element-view/memory/stage-final.ts +129 -0
  82. package/src/compute-view/element-view/memory/stage-include.ts +128 -0
  83. package/src/compute-view/element-view/predicates/_utils.ts +86 -0
  84. package/src/compute-view/element-view/predicates/element-expand.ts +33 -0
  85. package/src/compute-view/element-view/predicates/element-kind-tag.ts +26 -0
  86. package/src/compute-view/element-view/predicates/element-ref.ts +37 -0
  87. package/src/compute-view/element-view/predicates/relation-direct.ts +309 -0
  88. package/src/compute-view/element-view/predicates/relation-in-out.ts +66 -0
  89. package/src/compute-view/element-view/predicates/relation-in.ts +118 -0
  90. package/src/compute-view/element-view/predicates/relation-out.ts +116 -0
  91. package/src/compute-view/element-view/predicates/wildcard.ts +88 -0
  92. package/src/compute-view/element-view/utils.ts +59 -0
  93. package/src/compute-view/index.ts +4 -0
  94. package/src/compute-view/memory/AbstractMemory.ts +45 -0
  95. package/src/compute-view/memory/AbstractStageExclude.ts +216 -0
  96. package/src/compute-view/memory/AbstractStageInclude.ts +200 -0
  97. package/src/compute-view/memory/_types.ts +147 -0
  98. package/src/compute-view/memory/index.ts +5 -0
  99. package/src/compute-view/memory/ops.ts +43 -0
  100. package/src/compute-view/utils/__snapshots__/sortNodes.spec.ts.snap +113 -0
  101. package/src/compute-view/utils/ancestorsOfNode.ts +19 -0
  102. package/src/compute-view/utils/applyCustomElementProperties.ts +66 -0
  103. package/src/compute-view/utils/applyCustomRelationProperties.ts +41 -0
  104. package/src/compute-view/utils/applyViewRuleStyles.ts +53 -0
  105. package/src/compute-view/utils/buildComputedNodes.ts +148 -0
  106. package/src/compute-view/utils/buildElementNotations.ts +63 -0
  107. package/src/compute-view/utils/elementExpressionToPredicate.ts +50 -0
  108. package/src/compute-view/utils/link-nodes-with-edges.ts +54 -0
  109. package/src/compute-view/utils/merge-props-from-relationships.ts +128 -0
  110. package/src/compute-view/utils/relationExpressionToPredicates.ts +55 -0
  111. package/src/compute-view/utils/resolve-extended-views.ts +69 -0
  112. package/src/compute-view/utils/resolve-global-rules.ts +83 -0
  113. package/src/compute-view/utils/topological-sort.ts +256 -0
  114. package/src/compute-view/utils/uniqueTags.test.ts +42 -0
  115. package/src/compute-view/utils/uniqueTags.ts +21 -0
  116. package/src/compute-view/utils/view-hash.ts +27 -0
  117. package/src/compute-view/utils/with-readable-edges.ts +36 -0
  118. package/src/index.ts +22 -12
  119. package/src/model/DeploymentElementModel.ts +599 -0
  120. package/src/model/DeploymentModel.ts +370 -0
  121. package/src/model/ElementModel.ts +221 -0
  122. package/src/model/LikeC4Model.test-d.ts +152 -0
  123. package/src/model/LikeC4Model.ts +336 -457
  124. package/src/model/RelationModel.ts +85 -0
  125. package/src/model/__test__/fixture.ts +149 -338
  126. package/src/model/connection/Connection.ts +72 -0
  127. package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
  128. package/src/model/connection/deployment/find.ts +120 -0
  129. package/src/model/connection/deployment/index.ts +8 -0
  130. package/src/model/connection/index.ts +22 -0
  131. package/src/model/connection/model/ConnectionModel.ts +157 -0
  132. package/src/model/connection/model/find.ts +117 -0
  133. package/src/model/connection/model/index.ts +8 -0
  134. package/src/model/connection/ops.ts +274 -0
  135. package/src/model/guards.ts +9 -0
  136. package/src/model/index.ts +46 -2
  137. package/src/model/types.ts +112 -15
  138. package/src/model/view/EdgeModel.ts +103 -0
  139. package/src/model/view/LikeC4ViewModel.ts +226 -0
  140. package/src/model/view/NodeModel.ts +229 -0
  141. package/src/types/_common.ts +55 -1
  142. package/src/types/deployments.ts +169 -0
  143. package/src/types/element.ts +9 -5
  144. package/src/types/expression-v2.ts +172 -0
  145. package/src/types/expression.ts +17 -11
  146. package/src/types/global.ts +3 -3
  147. package/src/types/index.ts +220 -12
  148. package/src/types/model.ts +75 -12
  149. package/src/types/operators.ts +1 -1
  150. package/src/types/overview-graph.ts +2 -2
  151. package/src/types/relation.ts +18 -14
  152. package/src/types/theme.ts +0 -1
  153. package/src/types/view-notation.ts +2 -2
  154. package/src/types/view.ts +117 -41
  155. package/src/utils/{commonHead.ts → common-head.ts} +2 -0
  156. package/src/utils/const.ts +1 -0
  157. package/src/utils/fqn.ts +203 -56
  158. package/src/utils/getOrCreate.ts +42 -0
  159. package/src/utils/graphlib.ts +10 -0
  160. package/src/utils/index.ts +74 -6
  161. package/src/utils/iterable/_types.ts +5 -0
  162. package/src/utils/iterable/filter.ts +55 -0
  163. package/src/utils/iterable/flat.ts +17 -0
  164. package/src/utils/iterable/index.ts +12 -0
  165. package/src/utils/iterable/map.ts +40 -0
  166. package/src/utils/iterable/reduce.ts +24 -0
  167. package/src/utils/iterable/some.ts +36 -0
  168. package/src/utils/iterable/to.ts +19 -0
  169. package/src/utils/iterable/unique.ts +29 -0
  170. package/src/utils/object-hash.ts +3 -0
  171. package/src/utils/relations.ts +3 -64
  172. package/src/utils/set.ts +78 -0
  173. package/src/utils/string-hash.ts +16 -0
  174. package/dist/index.cjs +0 -5452
  175. package/dist/index.d.cts +0 -1053
  176. package/dist/shared/core.CoLQkcYL.d.ts +0 -734
  177. package/dist/shared/core.DIYZvpVg.cjs +0 -353
  178. package/dist/types/index.cjs +0 -70
  179. package/dist/types/index.d.cts +0 -2
  180. package/dist/types/index.mjs +0 -1
  181. package/src/builder/Builder.test-d.ts +0 -69
  182. package/src/builder/Builder.view.ts +0 -358
  183. package/src/model/LikeC4DiagramModel.ts +0 -338
  184. package/src/model/LikeC4ViewModel.ts +0 -320
@@ -0,0 +1,129 @@
1
+ import { forEach, only, pipe } from 'remeda'
2
+ import { isAncestor, sortByFqnHierarchically } from '../../../utils/fqn'
3
+ import { isome, toArray } from '../../../utils/iterable'
4
+ import { difference, union } from '../../../utils/set'
5
+ import { treeFromMemoryState } from '../../memory/ops'
6
+ import type { Elem } from '../_types'
7
+ import { findRedundantConnections } from '../clean-connections'
8
+ import type { Ctx, Memory } from './memory'
9
+
10
+ /**
11
+ * This patch:
12
+ * 1. Keeps connections between leafs or having direct deployment relations
13
+ * 2. Removes cross-boundary model relations, that already exist inside boundaries
14
+ * (e.g. prefer relations inside same deployment node over relations between nodes)
15
+ * 3. Removes implicit connections between elements, if their descendants have same connection
16
+ */
17
+ export class StageFinal {
18
+ static for(memory: Memory) {
19
+ return new StageFinal(memory)
20
+ }
21
+
22
+ private constructor(
23
+ protected readonly memory: Memory,
24
+ ) {
25
+ }
26
+
27
+ public step1CleanConnections(memory: Memory): Memory {
28
+ if (memory.connections.length < 2) {
29
+ return memory
30
+ }
31
+
32
+ const connectionsToExclude = findRedundantConnections(memory.connections)
33
+ if (connectionsToExclude.length === 0) {
34
+ return memory
35
+ }
36
+ const stage = memory.stageExclude({} as any)
37
+
38
+ stage.excludeConnections(connectionsToExclude, true)
39
+
40
+ return stage.commit()
41
+ }
42
+
43
+ public step2ProcessImplicits(memory: Memory): Memory {
44
+ const implicits = union(this.memory.elements, memory.elements)
45
+ const final = union(memory.final, this.memory.explicits)
46
+
47
+ const snapshot = new Set(final)
48
+ const isFinalOrHasIncludedDescendant = (el: Elem) => {
49
+ for (const final of snapshot) {
50
+ if (el === final || isAncestor(el, final)) {
51
+ return true
52
+ }
53
+ }
54
+ return false
55
+ }
56
+
57
+ // Pick from implicit elements
58
+ pipe(
59
+ difference(implicits, snapshot),
60
+ toArray(),
61
+ sortByFqnHierarchically,
62
+ forEach((el) => {
63
+ // if (memory.scope && !memory.scope.isAncestorOf(el)) {
64
+ // return
65
+ // }
66
+ // If element has more 2 or more children included
67
+ // It can "box" around
68
+ const childrensToWrap = [...el.children()].filter(isFinalOrHasIncludedDescendant).length
69
+ if (childrensToWrap >= 2) {
70
+ final.add(el)
71
+ return
72
+ }
73
+ // If Element has only one child included
74
+ // and has "similar" sibling with included descendant
75
+ if (childrensToWrap === 1 && isome(el.siblings(), isFinalOrHasIncludedDescendant)) {
76
+ final.add(el)
77
+ }
78
+ }),
79
+ )
80
+
81
+ return memory.update({ final })
82
+ }
83
+
84
+ public step3ProcessBoundaries(memory: Memory): Memory {
85
+ const boundaries = new Set<Elem>()
86
+ for (const conn of memory.connections) {
87
+ if (conn.boundary && conn.boundary !== conn.source && conn.boundary !== conn.target) {
88
+ boundaries.add(conn.boundary)
89
+ }
90
+ }
91
+ const tree = treeFromMemoryState<Ctx>(memory, 'final')
92
+ const stage = memory.stageExclude({} as any)
93
+
94
+ const isRemovable = (el: Elem) =>
95
+ !(
96
+ boundaries.has(el)
97
+ || memory.explicits.has(el)
98
+ || tree.hasInOut(el)
99
+ || tree.root.has(el)
100
+ )
101
+
102
+ const singleRoot = only([...tree.root])
103
+ if (singleRoot && !memory.explicits.has(singleRoot)) {
104
+ stage.exclude(singleRoot)
105
+ }
106
+
107
+ for (const el of memory.final) {
108
+ const singleChild = only(tree.children(el))
109
+ if (singleChild && !tree.hasInOut(singleChild) && isRemovable(el)) {
110
+ stage.exclude(el)
111
+ }
112
+ }
113
+
114
+ if (stage.isDirty()) {
115
+ return stage.commit()
116
+ }
117
+ return memory
118
+ }
119
+
120
+ public commit(): Memory {
121
+ // return []
122
+ const step1 = this.step1CleanConnections(this.memory)
123
+ const step2 = this.step2ProcessImplicits(step1)
124
+ return this.step3ProcessBoundaries(step2)
125
+ // return step2memory
126
+ // const step3m?emory = this.step3FlatNodes(step2memory)
127
+ // return step3memory
128
+ }
129
+ }
@@ -0,0 +1,128 @@
1
+ import { dropWhile, forEach, pipe, take, zip } from 'remeda'
2
+ import { Expr } from '../../..'
3
+ import { findConnection, findConnectionsBetween } from '../../../model/connection/model'
4
+ import { difference, isAncestor, isIterable } from '../../../utils'
5
+ import { toArray } from '../../../utils/iterable'
6
+ import { type CtxConnection, type StageExpression, AbstractStageInclude } from '../../memory'
7
+ import { type ActiveGroupCtx, type ActiveGroupMemory, type Ctx } from './memory'
8
+
9
+ export type Elem = Ctx['Element']
10
+
11
+ export class StageInclude<C extends Ctx = Ctx> extends AbstractStageInclude<C> {
12
+ /**
13
+ * Connects elements with existing ones in the memory
14
+ */
15
+ public override connectWithExisting(
16
+ elements: Elem | Iterable<Elem>,
17
+ direction: 'in' | 'out' | 'both' = 'both',
18
+ ): boolean {
19
+ const before = this._connections.length
20
+ const hasChanged = () => this._connections.length > before
21
+ if (!isIterable(elements)) {
22
+ if (direction === 'in' || direction === 'both') {
23
+ for (const el of this.memory.elements) {
24
+ this.addConnections(
25
+ findConnection(el, elements, 'directed'),
26
+ )
27
+ }
28
+ }
29
+ if (direction === 'out' || direction === 'both') {
30
+ this.addConnections(
31
+ findConnectionsBetween(elements, this.memory.elements, 'directed'),
32
+ )
33
+ }
34
+ return hasChanged()
35
+ }
36
+
37
+ const targets = [...elements]
38
+ if (direction === 'in' || direction === 'both') {
39
+ for (const el of this.memory.elements) {
40
+ this.addConnections(
41
+ findConnectionsBetween(el, targets, 'directed'),
42
+ )
43
+ }
44
+ }
45
+ if (direction === 'out' || direction === 'both') {
46
+ for (const el of targets) {
47
+ this.addConnections(
48
+ findConnectionsBetween(el, this.memory.elements, 'directed'),
49
+ )
50
+ }
51
+ }
52
+ return hasChanged()
53
+ }
54
+
55
+ protected addImplicitWithinScope(element: Elem | undefined | null) {
56
+ if (!element) {
57
+ return
58
+ }
59
+ if (!this.memory.scope || isAncestor(this.memory.scope, element)) {
60
+ this.addImplicit(element)
61
+ }
62
+ }
63
+
64
+ protected override processConnections(connections: CtxConnection<Ctx>[]) {
65
+ if (Expr.isRelationPredicateExpr(this.expression)) {
66
+ return connections
67
+ }
68
+
69
+ pipe(
70
+ connections,
71
+ forEach(({ source, target, boundary }) => {
72
+ pipe(
73
+ zip(
74
+ [...toArray(source.ancestors()).reverse(), source],
75
+ [...toArray(target.ancestors()).reverse(), target],
76
+ ),
77
+ // Filter out common ancestors
78
+ dropWhile(([sourceAncestor, targetAncestor]) => sourceAncestor === targetAncestor),
79
+ take(1),
80
+ forEach(([sourceAncestor, targetAncestor]) => {
81
+ if (sourceAncestor === source && targetAncestor === target) {
82
+ this.addImplicitWithinScope(boundary)
83
+ return
84
+ }
85
+ if (sourceAncestor !== source) {
86
+ this.addImplicitWithinScope(sourceAncestor)
87
+ }
88
+ if (targetAncestor !== target) {
89
+ this.addImplicitWithinScope(targetAncestor)
90
+ }
91
+ }),
92
+ )
93
+ }),
94
+ )
95
+ return connections
96
+ }
97
+
98
+ protected override postcommit(state: ActiveGroupCtx['MutableState']) {
99
+ const newExplicits = difference(state.explicits, this.memory.explicits)
100
+ for (const explicit of newExplicits) {
101
+ state.explicitFirstSeenIn.set(explicit, '@root' as any)
102
+ }
103
+
104
+ return state
105
+ }
106
+ }
107
+
108
+ export class ActiveGroupStageInclude extends StageInclude<ActiveGroupCtx> {
109
+ constructor(
110
+ public override readonly memory: ActiveGroupMemory,
111
+ public override readonly expression: StageExpression<ActiveGroupCtx>,
112
+ ) {
113
+ super(memory, expression)
114
+ }
115
+
116
+ protected override postcommit(state: ActiveGroupCtx['MutableState']) {
117
+ const newExplicits = difference(state.explicits, this.memory.explicits)
118
+ for (const explicit of newExplicits) {
119
+ state.explicitFirstSeenIn.set(explicit, this.memory.activeGroupId)
120
+ }
121
+
122
+ for (const implicit of [...this.explicits, ...this.implicits]) {
123
+ state.lastSeenIn.set(implicit, this.memory.activeGroupId)
124
+ }
125
+
126
+ return state
127
+ }
128
+ }
@@ -0,0 +1,86 @@
1
+ import { anyPass } from 'remeda'
2
+ import { nonexhaustive } from '../../../errors'
3
+ import type { LikeC4Model } from '../../../model'
4
+ import * as Expr from '../../../types/expression'
5
+ import { isDescendantOf } from '../../../utils/fqn'
6
+ import { ifilter, toArray } from '../../../utils/iterable'
7
+ import type { Elem, Memory, PredicateCtx } from '../_types'
8
+
9
+ /**
10
+ * Resolve elements from the model based on the given expression
11
+ */
12
+
13
+ export function resolveElements(model: LikeC4Model, expr: Exclude<Expr.ElementExpression, Expr.WildcardExpr>): Elem[] {
14
+ switch (true) {
15
+ case Expr.isExpandedElementExpr(expr): {
16
+ const element = model.element(expr.expanded)
17
+ return [
18
+ element,
19
+ ...element.children(),
20
+ ]
21
+ }
22
+ case Expr.isElementRef(expr): {
23
+ const element = model.element(expr.element)
24
+ let children
25
+ if (expr.isChildren) {
26
+ children = toArray(element.children())
27
+ } else if (expr.isDescendants) {
28
+ children = toArray(element.descendants())
29
+ }
30
+ return children && children.length > 0 ? children : [element]
31
+ }
32
+ case Expr.isElementKindExpr(expr):
33
+ return [...ifilter(model.elements(), el => {
34
+ return expr.isEqual === (el.kind === expr.elementKind)
35
+ })]
36
+ case Expr.isElementTagExpr(expr):
37
+ return [...ifilter(model.elements(), el => {
38
+ return expr.isEqual === el.tags.includes(expr.elementTag)
39
+ })]
40
+ default:
41
+ nonexhaustive(expr)
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Include elements that are not in the given set but are descendants of the current set
47
+ * Consider the following example:
48
+ * a1.* -> b1
49
+ * If there are a1.a2.a3 and b1.b2 in the memory, but not connected yet - we connect them
50
+ */
51
+ export function includeDescendantsFromMemory(elements: Elem[], memory: Memory): Elem[] {
52
+ if (memory.isEmpty() || elements.length === 0) {
53
+ return elements
54
+ }
55
+ const descedantsOf = anyPass(elements.map(e => isDescendantOf(e)))
56
+ const fromMemory = toArray(
57
+ ifilter(
58
+ memory.elements,
59
+ el => !elements.includes(el) && descedantsOf(el),
60
+ ),
61
+ )
62
+ return [
63
+ ...elements,
64
+ ...fromMemory,
65
+ ]
66
+ }
67
+
68
+ /**
69
+ * Combination of `resolveElements` and `includeDescendantsFromMemory`
70
+ */
71
+ export function resolveAndIncludeFromMemory(
72
+ nonWildcard: Expr.NonWilcard,
73
+ { memory, model }: Pick<PredicateCtx, 'model' | 'memory'>,
74
+ ): Elem[] {
75
+ const resolved = resolveElements(model, nonWildcard)
76
+ // We include from memory only if the expression is:
77
+ // - expanded element
78
+ // - element reference with or with children (but not descendants - they are already included)
79
+ if (Expr.isExpandedElementExpr(nonWildcard) || Expr.isElementRef(nonWildcard)) {
80
+ if (nonWildcard.isDescendants === true) {
81
+ return resolved
82
+ }
83
+ return includeDescendantsFromMemory(resolved, memory)
84
+ }
85
+ return resolved
86
+ }
@@ -0,0 +1,33 @@
1
+ import { findConnectionsWithin } from '../../../model/connection/model'
2
+ import type * as Expr from '../../../types/expression'
3
+ import type { Elem, PredicateExecutor } from '../_types'
4
+
5
+ export const ExpandedElementPredicate: PredicateExecutor<Expr.ExpandedElementExpr> = {
6
+ include: ({ expr, model, stage, where }) => {
7
+ const parent = model.element(expr.expanded)
8
+ if (where(parent)) {
9
+ stage.addExplicit(parent)
10
+ stage.connectWithExisting(parent)
11
+ }
12
+
13
+ const children = [...parent.children()].filter(where)
14
+ const expanded = [] as Elem[]
15
+ for (const child of children) {
16
+ stage.addImplicit(child)
17
+ if (stage.connectWithExisting(child)) {
18
+ expanded.push(child)
19
+ }
20
+ }
21
+ stage.addConnections(findConnectionsWithin(expanded))
22
+ return stage
23
+ },
24
+ exclude: ({ expr, model, stage, where }) => {
25
+ const parent = model.element(expr.expanded)
26
+ const elements = [
27
+ parent,
28
+ ...parent.children()
29
+ ].filter(where)
30
+ stage.exclude(elements)
31
+ return stage
32
+ }
33
+ }
@@ -0,0 +1,26 @@
1
+ import { findConnectionsWithin } from '../../../model/connection/model'
2
+ import * as Expr from '../../../types/expression'
3
+ import type { PredicateExecutor } from '../_types'
4
+ import { resolveElements } from './_utils'
5
+
6
+ export const ElementKindOrTagPredicate: PredicateExecutor<Expr.ElementKindExpr | Expr.ElementTagExpr> = {
7
+ include: ({ expr, model, stage, filterWhere }) => {
8
+ const elements = filterWhere(resolveElements(model, expr))
9
+ if (elements.length === 0) {
10
+ return
11
+ }
12
+
13
+ stage.addExplicit(elements)
14
+ stage.connectWithExisting(elements)
15
+ stage.addConnections(findConnectionsWithin(elements))
16
+
17
+ return stage
18
+ },
19
+
20
+ exclude: ({ expr, model, stage, filterWhere }) => {
21
+ const elements = filterWhere(resolveElements(model, expr))
22
+ stage.exclude(elements)
23
+
24
+ return stage
25
+ }
26
+ }
@@ -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
+ }