@likec4/core 1.18.0 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) 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 +9 -78
  6. package/dist/compute-view/index.d.ts +9 -78
  7. package/dist/compute-view/index.js +78 -0
  8. package/dist/index.d.mts +9 -730
  9. package/dist/index.d.ts +9 -730
  10. package/dist/{index.mjs → index.js} +7 -784
  11. package/dist/model/index.d.mts +218 -606
  12. package/dist/model/index.d.ts +218 -606
  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.DMYY7C8s.d.mts → core.C05RDLhi.d.ts} +179 -230
  18. package/dist/shared/{core.DMYY7C8s.d.ts → core.CmYMqgha.d.mts} +179 -230
  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.DafVOuVd.js +7443 -0
  24. package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
  25. package/dist/shared/view.CyZrG8BJ.js +354 -0
  26. package/dist/types/index.d.mts +4 -2
  27. package/dist/types/index.d.ts +4 -2
  28. package/dist/types/index.js +20 -0
  29. package/dist/utils/index.d.mts +419 -0
  30. package/dist/utils/index.d.ts +419 -0
  31. package/dist/utils/index.js +347 -0
  32. package/package.json +47 -33
  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 +25 -20
  36. package/src/builder/Builder.deploymentModel.ts +80 -55
  37. package/src/builder/Builder.element.ts +2 -0
  38. package/src/builder/Builder.model.ts +57 -43
  39. package/src/builder/Builder.ts +412 -431
  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 +28 -5
  49. package/src/builder/index.ts +10 -4
  50. package/src/colors/index.ts +2 -2
  51. package/src/compute-view/compute-view.ts +45 -54
  52. package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
  53. package/src/compute-view/deployment-view/__test__/fixture.ts +50 -62
  54. package/src/compute-view/deployment-view/_types.ts +26 -18
  55. package/src/compute-view/deployment-view/clean-connections.ts +173 -164
  56. package/src/compute-view/deployment-view/compute.ts +51 -37
  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 +183 -76
  61. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +38 -20
  62. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +72 -23
  63. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +61 -22
  64. package/src/compute-view/deployment-view/predicates/wildcard.ts +15 -15
  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 +95 -31
  69. package/src/compute-view/dynamic-view/__test__/fixture.ts +4 -4
  70. package/src/compute-view/dynamic-view/compute.ts +59 -45
  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 +64 -62
  73. package/src/compute-view/element-view/__test__/fixture.ts +147 -117
  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 +264 -683
  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 +3 -4
  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/buildComputedNodes.ts +4 -4
  101. package/src/compute-view/utils/elementExpressionToPredicate.ts +1 -3
  102. package/src/compute-view/utils/link-nodes-with-edges.ts +3 -7
  103. package/src/compute-view/utils/{derive-edge-props-from-relationships.ts → merge-props-from-relationships.ts} +54 -23
  104. package/src/compute-view/utils/relationExpressionToPredicates.ts +2 -2
  105. package/src/compute-view/utils/resolve-extended-views.ts +44 -40
  106. package/src/compute-view/utils/resolve-global-rules.ts +6 -6
  107. package/src/compute-view/utils/topological-sort.ts +167 -71
  108. package/src/compute-view/utils/with-readable-edges.ts +14 -9
  109. package/src/index.ts +22 -16
  110. package/src/model/DeploymentElementModel.ts +150 -85
  111. package/src/model/DeploymentModel.ts +27 -21
  112. package/src/model/ElementModel.ts +51 -25
  113. package/src/model/LikeC4Model.test-d.ts +4 -3
  114. package/src/model/LikeC4Model.ts +98 -42
  115. package/src/model/RelationModel.ts +5 -4
  116. package/src/model/__test__/fixture.ts +5 -9
  117. package/src/model/connection/Connection.ts +72 -0
  118. package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
  119. package/src/model/connection/{deployment.ts → deployment/find.ts} +14 -18
  120. package/src/model/connection/deployment/index.ts +8 -0
  121. package/src/model/connection/index.ts +22 -0
  122. package/src/model/connection/model/ConnectionModel.ts +157 -0
  123. package/src/model/connection/{model.ts → model/find.ts} +43 -49
  124. package/src/model/connection/model/index.ts +8 -0
  125. package/src/model/connection/ops.ts +274 -0
  126. package/src/model/guards.ts +9 -0
  127. package/src/model/index.ts +45 -3
  128. package/src/model/types.ts +35 -18
  129. package/src/model/view/EdgeModel.ts +6 -6
  130. package/src/model/view/LikeC4ViewModel.ts +14 -8
  131. package/src/model/view/NodeModel.ts +6 -5
  132. package/src/types/_common.ts +53 -1
  133. package/src/types/deployments.ts +88 -156
  134. package/src/types/element.ts +2 -2
  135. package/src/types/expression-v2.ts +172 -0
  136. package/src/types/expression.ts +9 -5
  137. package/src/types/global.ts +3 -3
  138. package/src/types/index.ts +220 -13
  139. package/src/types/model.ts +28 -24
  140. package/src/types/operators.ts +1 -1
  141. package/src/types/relation.ts +14 -10
  142. package/src/types/theme.ts +0 -1
  143. package/src/types/view.ts +20 -18
  144. package/src/utils/const.ts +1 -0
  145. package/src/utils/fqn.ts +140 -49
  146. package/src/utils/getOrCreate.ts +1 -1
  147. package/src/utils/index.ts +75 -9
  148. package/src/utils/iterable/_types.ts +5 -0
  149. package/src/utils/iterable/filter.ts +55 -0
  150. package/src/utils/iterable/find.ts +36 -0
  151. package/src/utils/iterable/flat.ts +17 -0
  152. package/src/utils/iterable/index.ts +13 -0
  153. package/src/utils/iterable/map.ts +40 -0
  154. package/src/utils/iterable/reduce.ts +24 -0
  155. package/src/utils/iterable/some.ts +36 -0
  156. package/src/utils/iterable/to.ts +19 -0
  157. package/src/utils/iterable/unique.ts +29 -0
  158. package/src/utils/relations.ts +3 -64
  159. package/src/utils/set.ts +11 -9
  160. package/src/utils/string-hash.ts +1 -1
  161. package/dist/compute-view/index.mjs +0 -79
  162. package/dist/model/index.mjs +0 -2
  163. package/dist/shared/core.BBgiAAv1.mjs +0 -144
  164. package/dist/shared/core.BPyJvuMU.mjs +0 -2420
  165. package/dist/shared/core.BQ4AbfvB.mjs +0 -9228
  166. package/dist/shared/core.k12s_keD.mjs +0 -203
  167. package/dist/types/index.mjs +0 -21
  168. package/src/builder/Builder.test-d.ts +0 -124
  169. package/src/builder/Builder.view.ts +0 -543
  170. package/src/compute-view/LikeC4ModelGraph.ts +0 -330
  171. package/src/compute-view/deployment-view/Memory.ts +0 -108
  172. package/src/compute-view/deployment-view/Stage.ts +0 -145
  173. package/src/compute-view/deployment-view/predicates/deployment-ref.ts +0 -146
  174. package/src/compute-view/element-view/predicates.ts +0 -517
  175. package/src/compute-view/utils/sortNodes.ts +0 -101
  176. package/src/model/connection/ConnectionModel.ts +0 -94
  177. package/src/model/connection/DeploymentConnectionModel.ts +0 -99
@@ -1,146 +0,0 @@
1
- import { hasAtLeast } from 'remeda'
2
- import { invariant } from '../../../errors'
3
- import { findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/deployment'
4
- import type { DeploymentConnectionModel } from '../../../model/connection/deployment'
5
- import type { DeployedInstanceModel, DeploymentNodeModel } from '../../../model/DeploymentElementModel'
6
- import type { DeploymentElementExpression } from '../../../types'
7
- import type { PredicateCtx, PredicateExecutor } from '../_types'
8
- import { deploymentExpressionToPredicate } from '../utils'
9
-
10
- export const DeploymentRefPredicate: PredicateExecutor<DeploymentElementExpression.Ref> = {
11
- include: (expr, ctx) => {
12
- const el = ctx.model.element(expr.ref.id)
13
-
14
- if (el.isInstance()) {
15
- includeDeployedInstance(el, ctx)
16
- return ctx.stage.patch()
17
- }
18
- invariant(el.isDeploymentNode(), 'Type inference failed')
19
- switch (true) {
20
- case expr.selector === 'expanded':
21
- includeDeployedNodeWithExpanded(el, ctx)
22
- break
23
- case expr.selector === 'children':
24
- includeDeployedNodeChildren(el, ctx)
25
- break
26
- case expr.selector === 'descendants':
27
- includeDeployedNodeDescendants(el, ctx)
28
- break
29
- default:
30
- includeDeployedNode(el, ctx)
31
- break
32
- }
33
- return ctx.stage.patch()
34
- },
35
-
36
- exclude: (expr, { stage, memory }) => {
37
- const exprPredicate = deploymentExpressionToPredicate(expr)
38
- stage.exclude([...memory.elements].filter(exprPredicate))
39
- return stage.patch()
40
- }
41
- }
42
-
43
- function includeDeployedInstance(
44
- instance: DeployedInstanceModel,
45
- { memory, stage }: PredicateCtx
46
- ) {
47
- stage.addExplicit(instance)
48
- stage.addConnections(findConnectionsBetween(instance, memory.elements))
49
- }
50
-
51
- /**
52
- * include node
53
- */
54
- function includeDeployedNode(
55
- node: DeploymentNodeModel,
56
- { memory, stage }: PredicateCtx
57
- ) {
58
- stage.addExplicit(node)
59
- stage.addConnections(findConnectionsBetween(node, memory.elements))
60
- }
61
-
62
- /**
63
- * include node.*
64
- */
65
- function includeDeployedNodeChildren(
66
- node: DeploymentNodeModel,
67
- { memory, stage }: PredicateCtx
68
- ) {
69
- const children = [...node.children()]
70
- if (children.length === 0) {
71
- return
72
- }
73
- stage.addExplicit(children)
74
-
75
- if (hasAtLeast(children, 2)) {
76
- stage.addConnections(findConnectionsWithin(children))
77
- }
78
- for (const child of children) {
79
- stage.addConnections(findConnectionsBetween(child, memory.elements))
80
- }
81
- }
82
-
83
- /**
84
- * include node._
85
- */
86
- function includeDeployedNodeWithExpanded(
87
- node: DeploymentNodeModel,
88
- { memory, stage }: PredicateCtx
89
- ) {
90
- const children = [...node.children()]
91
- stage.addImplicit(node)
92
-
93
- const connections = [] as DeploymentConnectionModel[]
94
-
95
- for (const child of children) {
96
- const found = findConnectionsBetween(child, memory.elements)
97
- if (found.length > 0) {
98
- // on first connection, add node as explicit
99
- if (connections.length === 0) {
100
- stage.addExplicit(node)
101
- }
102
- stage.addExplicit(child)
103
- connections.push(...found)
104
- }
105
- }
106
-
107
- if (connections.length > 0) {
108
- // First connections inside
109
- stage.addConnections([
110
- ...findConnectionsWithin(children),
111
- ...connections
112
- ])
113
- }
114
-
115
- stage.addConnections(
116
- findConnectionsBetween(node, memory.elements)
117
- )
118
- }
119
-
120
- /**
121
- * include node.**
122
- */
123
- function includeDeployedNodeDescendants(
124
- node: DeploymentNodeModel,
125
- { memory, stage }: PredicateCtx
126
- ) {
127
- const descendants = [...node.descendants()]
128
- if (descendants.length === 0) {
129
- return
130
- }
131
- for (const child of descendants) {
132
- if (child.isInstance()) {
133
- stage.addExplicit(child)
134
- } else {
135
- stage.addImplicit(child)
136
- }
137
- }
138
-
139
- if (hasAtLeast(descendants, 2)) {
140
- stage.addConnections(findConnectionsWithin(descendants))
141
- }
142
-
143
- for (const child of descendants) {
144
- stage.addConnections(findConnectionsBetween(child, memory.elements))
145
- }
146
- }
@@ -1,517 +0,0 @@
1
- import { allPass, filter as remedaFilter, flatMap, isNullish as isNil, map, pipe, unique } from 'remeda'
2
- import type { Writable } from 'type-fest'
3
- import { nonexhaustive } from '../../errors'
4
- import type { Element, Relation } from '../../types'
5
- import * as Expr from '../../types/expression'
6
- import { isAncestor, parentFqn } from '../../utils/fqn'
7
- import { elementExprToPredicate } from '../utils/elementExpressionToPredicate'
8
- import type { ComputeCtx } from './compute'
9
-
10
- type Predicate<T> = (x: T) => boolean
11
- export type ElementPredicateFn = Predicate<Element>
12
- export type RelationPredicateFn = Predicate<Relation>
13
- // // type ElementPredicate = Predicate<Element>
14
- // type ElementPredicates<T> = T extends Element[] ? (x: T) => T : (T extends Element ? (x: T) => (Element | null) : never)
15
- // type ElementPredicate = ElementPredicates<Element | Element[]>
16
-
17
- const NoFilter: ElementPredicateFn = () => true
18
- const Identity = <T>(x: T) => x
19
- const filterBy = <T>(pred: Predicate<T>) => pred === NoFilter ? Identity : remedaFilter(pred)
20
- const filterOne = <T>(pred: Predicate<T>) => pred === NoFilter ? Identity : (x: T) => pred(x) ? x : null
21
-
22
- export function expandWildcardRef(this: ComputeCtx, expr: Expr.ElementRefExpr) {
23
- if (expr.isChildren) {
24
- const children = this.graph.children(expr.element)
25
- return children.length > 0 ? children : [this.graph.element(expr.element)]
26
- } else if (expr.isDescendants) {
27
- return this.graph.descendants(expr.element)
28
- } else {
29
- return [this.graph.element(expr.element)]
30
- }
31
- }
32
-
33
- export function includeElementRef(this: ComputeCtx, expr: Expr.ElementRefExpr, where = NoFilter) {
34
- // Get the elements that are already in the Ctx before any mutations
35
- // Because we need to add edges between them and the new elements
36
- const currentElements = [...this.resolvedElements]
37
- const filter = filterBy(where)
38
-
39
- const elements = filter(expandWildcardRef.call(this, expr))
40
- if (elements.length === 0) {
41
- return
42
- }
43
-
44
- this.addElement(...elements)
45
-
46
- if (elements.length > 1) {
47
- this.addEdges(this.graph.edgesWithin(elements))
48
- }
49
-
50
- if (currentElements.length > 0 && elements.length > 0) {
51
- for (const el of elements) {
52
- this.addEdges(this.graph.anyEdgesBetween(el, currentElements))
53
- }
54
- }
55
- }
56
-
57
- export function excludeElementRef(this: ComputeCtx, expr: Expr.ElementRefExpr, where = NoFilter) {
58
- const elements = [...this.resolvedElements].filter(allPass([
59
- elementExprToPredicate(expr),
60
- where
61
- ]))
62
- this.excludeElement(...elements)
63
- }
64
-
65
- export function includeWildcardRef(this: ComputeCtx, _expr: Expr.WildcardExpr, where = NoFilter) {
66
- const root = this.root
67
- if (!root) {
68
- // Take root elements
69
- const elements = this.graph.rootElements.filter(where)
70
- if (elements.length <= 0) {
71
- return
72
- }
73
- const currentElements = [...this.resolvedElements]
74
- this.addElement(...elements)
75
- this.addEdges(this.graph.edgesWithin(elements))
76
- if (currentElements.length > 0) {
77
- for (const el of elements) {
78
- this.addEdges(this.graph.anyEdgesBetween(el, currentElements))
79
- }
80
- }
81
- return
82
- }
83
-
84
- const currentElements = [...this.resolvedElements]
85
- const _elRoot = filterOne(where)(this.graph.element(root))
86
- if (_elRoot) {
87
- this.addElement(_elRoot)
88
- }
89
- const filter = filterBy(where)
90
-
91
- const children = filter(this.graph.children(root))
92
- const hasChildren = children.length > 0
93
- if (hasChildren) {
94
- this.addElement(...children)
95
- this.addEdges(this.graph.edgesWithin(children))
96
- } else if (_elRoot) {
97
- children.push(_elRoot)
98
- }
99
-
100
- // All neighbours that may have relations with root or its children
101
- const neighbours = [
102
- ...currentElements,
103
- ...filter([
104
- ...this.graph.siblings(root),
105
- ...this.graph.ancestors(root).flatMap(a => this.graph.siblings(a.id))
106
- ])
107
- ]
108
-
109
- for (const el of children) {
110
- this.addEdges(this.graph.anyEdgesBetween(el, neighbours)).forEach(edge => {
111
- this.addImplicit(edge.source, edge.target)
112
- })
113
- }
114
-
115
- // If root has no children
116
- if (!hasChildren && _elRoot) {
117
- // Any edges with siblings?
118
- const edgesWithSiblings = this.graph.anyEdgesBetween(_elRoot, this.graph.siblings(root))
119
- if (edgesWithSiblings.length === 0) {
120
- // If no edges with siblings, i.e. root is orphan
121
- // Lets add parent for better view
122
- const _parentId = parentFqn(root)
123
- const parent = _parentId && this.graph.element(_parentId)
124
- if (parent && where(parent)) {
125
- this.addElement(parent)
126
- }
127
- }
128
- }
129
- }
130
-
131
- export function excludeWildcardRef(this: ComputeCtx, _expr: Expr.WildcardExpr, where = NoFilter) {
132
- if (where !== NoFilter) {
133
- const elements = [...this.resolvedElements].filter(where)
134
- this.excludeElement(...elements)
135
- return
136
- }
137
- const root = this.root
138
- if (root) {
139
- this.excludeElement(
140
- this.graph.element(root),
141
- ...this.graph.children(root)
142
- )
143
- this.excludeRelation(
144
- ...this.graph.connectedRelations(root)
145
- )
146
- } else {
147
- this.reset()
148
- }
149
- }
150
-
151
- export function includeExpandedElementExpr(
152
- this: ComputeCtx,
153
- expr: Expr.ExpandedElementExpr,
154
- where = NoFilter
155
- ) {
156
- const filter = filterBy(where)
157
- const currentElements = [...this.resolvedElements]
158
-
159
- // Always add parent
160
- const parent = this.graph.element(expr.expanded)
161
- if (where(parent)) {
162
- this.addElement(parent)
163
- const anyEdgesBetween = this.graph.anyEdgesBetween(parent, currentElements)
164
- this.addEdges(anyEdgesBetween)
165
- }
166
-
167
- const expanded = [] as Element[]
168
-
169
- for (const el of filter(this.graph.children(expr.expanded))) {
170
- this.addImplicit(el)
171
- const edges = this.graph.anyEdgesBetween(el, currentElements)
172
- if (edges.length > 0) {
173
- this.addEdges(edges)
174
- expanded.push(el)
175
- }
176
- }
177
- if (expanded.length > 1) {
178
- this.addEdges(this.graph.edgesWithin(expanded))
179
- }
180
- }
181
-
182
- export function excludeExpandedElementExpr(
183
- this: ComputeCtx,
184
- expr: Expr.ExpandedElementExpr,
185
- where = NoFilter
186
- ) {
187
- const elements = [...this.resolvedElements].filter(allPass([
188
- elementExprToPredicate(expr),
189
- where
190
- ]))
191
- this.excludeElement(...elements)
192
- }
193
-
194
- const asElementPredicate = (
195
- expr: Expr.ElementKindExpr | Expr.ElementTagExpr
196
- ): Predicate<Element> => {
197
- if (expr.isEqual) {
198
- if (Expr.isElementKindExpr(expr)) {
199
- return e => e.kind === expr.elementKind
200
- } else {
201
- return ({ tags }) => !!tags && tags.includes(expr.elementTag)
202
- }
203
- } else {
204
- if (Expr.isElementKindExpr(expr)) {
205
- return e => e.kind !== expr.elementKind
206
- } else {
207
- return ({ tags }) => isNil(tags) || tags.length === 0 || !tags.includes(expr.elementTag)
208
- }
209
- }
210
- }
211
- export function includeElementKindOrTag(
212
- this: ComputeCtx,
213
- expr: Expr.ElementKindExpr | Expr.ElementTagExpr,
214
- where = NoFilter
215
- ) {
216
- const elements = this.graph.elements.filter(asElementPredicate(expr)).filter(where)
217
- if (elements.length > 0) {
218
- const currentElements = [...this.resolvedElements]
219
- this.addElement(...elements)
220
- this.addEdges(this.graph.edgesWithin(elements))
221
- for (const el of elements) {
222
- this.addEdges(this.graph.anyEdgesBetween(el, currentElements))
223
- }
224
- }
225
- }
226
-
227
- export function excludeElementKindOrTag(
228
- this: ComputeCtx,
229
- expr: Expr.ElementKindExpr | Expr.ElementTagExpr,
230
- where = NoFilter
231
- ) {
232
- const elements = [...this.resolvedElements].filter(asElementPredicate(expr)).filter(where)
233
- if (elements.length > 0) {
234
- this.excludeElement(...elements)
235
- }
236
- }
237
-
238
- function resolveNeighbours(this: ComputeCtx, expr: Expr.ElementExpression): Element[] {
239
- if (Expr.isElementRef(expr)) {
240
- return this.graph.ascendingSiblings(expr.element) as Writable<Element[]>
241
- }
242
- return this.root ? this.graph.ascendingSiblings(this.root) as Writable<Element[]> : this.graph.rootElements
243
- }
244
-
245
- function resolveElements(this: ComputeCtx, expr: Expr.ElementExpression): Element[] {
246
- if (Expr.isWildcard(expr)) {
247
- if (this.root) {
248
- return [...this.graph.children(this.root), this.graph.element(this.root)]
249
- } else {
250
- return this.graph.rootElements
251
- }
252
- }
253
- if (Expr.isElementKindExpr(expr)) {
254
- return this.graph.elements.filter(el => {
255
- if (expr.isEqual) {
256
- return el.kind === expr.elementKind
257
- }
258
- return el.kind !== expr.elementKind
259
- })
260
- }
261
- if (Expr.isElementTagExpr(expr)) {
262
- return this.graph.elements.filter(el => {
263
- const tags = el.tags
264
- if (expr.isEqual) {
265
- return !!tags && tags.includes(expr.elementTag)
266
- }
267
- return isNil(tags) || tags.length === 0 || !tags.includes(expr.elementTag)
268
- })
269
- }
270
- if (Expr.isExpandedElementExpr(expr)) {
271
- return [this.graph.element(expr.expanded)]
272
- }
273
-
274
- // Type guard
275
- if (!Expr.isElementRef(expr)) {
276
- return nonexhaustive(expr)
277
- }
278
-
279
- if (this.root === expr.element && expr.isChildren !== true && expr.isDescendants !== true) {
280
- return [...this.graph.children(this.root), this.graph.element(this.root)]
281
- }
282
-
283
- return expandWildcardRef.call(this, expr)
284
- }
285
-
286
- // --------------------------------
287
- // Incoming Expr
288
-
289
- function edgesIncomingExpr(this: ComputeCtx, expr: Expr.ElementExpression) {
290
- if (Expr.isWildcard(expr)) {
291
- if (!this.root) {
292
- return []
293
- }
294
- const sources = this.graph.ascendingSiblings(this.root)
295
- const targets = [...this.graph.children(this.root), this.graph.element(this.root)]
296
- return this.graph.edgesBetween(sources, targets)
297
- }
298
- const targets = resolveElements.call(this, expr)
299
- if (targets.length === 0) {
300
- return []
301
- }
302
- let sources = [...this.resolvedElements]
303
- if (Expr.isElementRef(expr) || Expr.isExpandedElementExpr(expr)) {
304
- const exprElement = expr.element ?? expr.expanded
305
- const isChildren = expr.isChildren ?? false
306
- sources = sources.filter(el =>
307
- // allow elements, that are not nested or are direct children
308
- !isAncestor(exprElement, el.id) || (isChildren && parentFqn(el.id) === exprElement)
309
- )
310
- }
311
- if (sources.length === 0) {
312
- sources = resolveNeighbours.call(this, expr)
313
- }
314
- return this.graph.edgesBetween(sources, targets)
315
- }
316
-
317
- const filterEdges = (edges: ReadonlyArray<ComputeCtx.Edge>, where?: RelationPredicateFn) => {
318
- if (!where) {
319
- return edges as ComputeCtx.Edge[]
320
- }
321
- return pipe(
322
- edges,
323
- map(e => ({ ...e, relations: e.relations.filter(where) })),
324
- remedaFilter(e => e.relations.length > 0)
325
- ) as ComputeCtx.Edge[]
326
- }
327
-
328
- const filterRelations = (edges: ComputeCtx.Edge[], where?: RelationPredicateFn) => {
329
- return pipe(
330
- edges,
331
- flatMap(e => e.relations),
332
- where ? remedaFilter(where) : Identity,
333
- unique()
334
- )
335
- }
336
-
337
- export function includeIncomingExpr(this: ComputeCtx, expr: Expr.IncomingExpr, where?: RelationPredicateFn) {
338
- const edges = filterEdges(edgesIncomingExpr.call(this, expr.incoming), where)
339
- if (edges.length === 0) {
340
- return
341
- }
342
- this.addEdges(edges).forEach(edge => {
343
- this.addImplicit(edge.target)
344
- })
345
- }
346
- export function excludeIncomingExpr(this: ComputeCtx, expr: Expr.IncomingExpr, where?: RelationPredicateFn) {
347
- let relations = filterRelations(edgesIncomingExpr.call(this, expr.incoming), where)
348
- this.excludeRelation(...relations)
349
- }
350
-
351
- // --------------------------------
352
- // Outgoing Expr
353
-
354
- function edgesOutgoingExpr(this: ComputeCtx, expr: Expr.ElementExpression) {
355
- if (Expr.isWildcard(expr)) {
356
- if (!this.root) {
357
- return []
358
- }
359
- const targets = this.graph.ascendingSiblings(this.root)
360
- const sources = [...this.graph.children(this.root), this.graph.element(this.root)]
361
- return this.graph.edgesBetween(sources, targets)
362
- }
363
- const sources = resolveElements.call(this, expr)
364
- if (sources.length === 0) {
365
- return []
366
- }
367
- let targets = [...this.resolvedElements]
368
- if (Expr.isElementRef(expr) || Expr.isExpandedElementExpr(expr)) {
369
- const sourceElement = expr.element ?? expr.expanded
370
- const isChildren = expr.isChildren ?? false
371
- targets = targets.filter(el =>
372
- // allow elements, that are not nested or are direct children
373
- !isAncestor(sourceElement, el.id) || (isChildren && parentFqn(el.id) === sourceElement)
374
- )
375
- }
376
- if (targets.length === 0) {
377
- targets = [...resolveNeighbours.call(this, expr)]
378
- }
379
- return this.graph.edgesBetween(sources, targets)
380
- }
381
-
382
- export function includeOutgoingExpr(this: ComputeCtx, expr: Expr.OutgoingExpr, where?: RelationPredicateFn) {
383
- const edges = filterEdges(edgesOutgoingExpr.call(this, expr.outgoing), where)
384
- if (edges.length === 0) {
385
- return
386
- }
387
- this.addEdges(edges).forEach(edge => {
388
- this.addImplicit(edge.source)
389
- })
390
- }
391
- export function excludeOutgoingExpr(this: ComputeCtx, expr: Expr.OutgoingExpr, where?: RelationPredicateFn) {
392
- const relations = filterRelations(edgesOutgoingExpr.call(this, expr.outgoing), where)
393
- this.excludeRelation(...relations)
394
- }
395
-
396
- // --------------------------------
397
- // InOut Expr
398
- type EdgePredicateResult = {
399
- implicits: Element[]
400
- edges: ComputeCtx.Edge[]
401
- }
402
-
403
- namespace EdgePredicateResult {
404
- export const Empty: EdgePredicateResult = {
405
- implicits: [],
406
- edges: []
407
- }
408
- }
409
- function edgesInOutExpr(this: ComputeCtx, { inout }: Expr.InOutExpr, where?: RelationPredicateFn): EdgePredicateResult {
410
- if (Expr.isWildcard(inout)) {
411
- if (!this.root) {
412
- return EdgePredicateResult.Empty
413
- }
414
- const neighbours = this.graph.ascendingSiblings(this.root)
415
- return {
416
- edges: filterEdges(this.graph.anyEdgesBetween(this.graph.element(this.root), neighbours), where),
417
- implicits: []
418
- }
419
- }
420
- const elements = resolveElements.call(this, inout)
421
- if (elements.length === 0) {
422
- return EdgePredicateResult.Empty
423
- }
424
- let currentElements = [...this.resolvedElements]
425
-
426
- if (Expr.isElementRef(inout) || Expr.isExpandedElementExpr(inout)) {
427
- const exprElement = inout.element ?? inout.expanded
428
- const isChildren = inout.isChildren ?? false
429
- currentElements = currentElements.filter(el =>
430
- // allow elements, that are not nested or are direct children
431
- !isAncestor(exprElement, el.id) || (isChildren && parentFqn(el.id) === exprElement)
432
- )
433
- }
434
- if (currentElements.length === 0) {
435
- currentElements = resolveNeighbours.call(this, inout)
436
- }
437
- return elements.reduce((acc, el) => {
438
- const edges = filterEdges(this.graph.anyEdgesBetween(el, currentElements), where)
439
- if (edges.length > 0) {
440
- acc.implicits.push(el)
441
- acc.edges.push(...edges)
442
- }
443
- return acc
444
- }, { implicits: [], edges: [] } as EdgePredicateResult)
445
- }
446
-
447
- export function includeInOutExpr(this: ComputeCtx, expr: Expr.InOutExpr, where?: RelationPredicateFn) {
448
- const { implicits, edges } = edgesInOutExpr.call(this, expr, where)
449
- this.addEdges(edges)
450
- this.addImplicit(...implicits)
451
- }
452
- export function excludeInOutExpr(this: ComputeCtx, expr: Expr.InOutExpr, where?: RelationPredicateFn) {
453
- const { edges } = edgesInOutExpr.call(this, expr, where)
454
- this.excludeRelation(...edges.flatMap(e => e.relations))
455
- }
456
-
457
- /**
458
- * Expand element to its children and itself, if it is the root (and not ".*")
459
- * Example:
460
- *
461
- * view of api {
462
- * include some -> api
463
- * }
464
- *
465
- * Transform to:
466
- *
467
- * view of api {
468
- * include some -> api.*, some -> api
469
- * }
470
- */
471
- function resolveRelationExprElements(this: ComputeCtx, expr: Expr.ElementExpression) {
472
- if (
473
- Expr.isElementRef(expr) && this.root === expr.element && expr.isChildren !== true && expr.isDescendants !== true
474
- ) {
475
- return [...this.graph.children(expr.element), this.graph.element(expr.element)]
476
- }
477
- if (Expr.isExpandedElementExpr(expr) && this.root === expr.expanded) {
478
- return [...this.graph.children(expr.expanded), this.graph.element(expr.expanded)]
479
- }
480
- return resolveElements.call(this, expr)
481
- }
482
-
483
- export function includeRelationExpr(this: ComputeCtx, expr: Expr.RelationExpr, where?: RelationPredicateFn) {
484
- let sources, targets
485
- if (Expr.isWildcard(expr.source) && !Expr.isWildcard(expr.target)) {
486
- sources = resolveNeighbours.call(this, expr.target)
487
- targets = resolveRelationExprElements.call(this, expr.target)
488
- } else if (!Expr.isWildcard(expr.source) && Expr.isWildcard(expr.target)) {
489
- sources = resolveRelationExprElements.call(this, expr.source)
490
- targets = resolveNeighbours.call(this, expr.source)
491
- } else {
492
- sources = resolveRelationExprElements.call(this, expr.source)
493
- targets = resolveRelationExprElements.call(this, expr.target)
494
- }
495
- const edges = this.graph.edgesBetween(sources, targets)
496
- if (expr.isBidirectional === true) {
497
- edges.push(...this.graph.edgesBetween(targets, sources))
498
- }
499
- this.addEdges(filterEdges(edges, where)).forEach(edge => {
500
- this.activeGroup.addImplicit(edge.source, edge.target)
501
- })
502
- }
503
-
504
- export function excludeRelationExpr(this: ComputeCtx, expr: Expr.RelationExpr, where?: RelationPredicateFn) {
505
- const isSource = elementExprToPredicate(expr.source)
506
- const isTarget = elementExprToPredicate(expr.target)
507
- const satisfies = (edge: ComputeCtx.Edge) => {
508
- let result = isSource(edge.source) && isTarget(edge.target)
509
- if (!result && expr.isBidirectional) {
510
- result = isSource(edge.target) && isTarget(edge.source)
511
- }
512
- return result
513
- }
514
- const edges = this.edges.filter(satisfies)
515
- const relations = filterRelations(edges, where)
516
- this.excludeRelation(...relations)
517
- }