@likec4/core 1.27.3 → 1.28.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 (71) hide show
  1. package/dist/builder/index.d.mts +6 -6
  2. package/dist/builder/index.mjs +23 -13
  3. package/dist/compute-view/index.d.mts +3 -3
  4. package/dist/compute-view/index.mjs +3 -3
  5. package/dist/compute-view/relationships-view/index.d.mts +3 -3
  6. package/dist/index.d.mts +6 -6
  7. package/dist/index.mjs +2 -2
  8. package/dist/model/index.d.mts +6 -6
  9. package/dist/model/index.mjs +1 -1
  10. package/dist/shared/{core.BpuZeqlX.d.mts → core.CZR9J1Qx.d.mts} +2 -2
  11. package/dist/shared/{core.Djro-kuQ.d.mts → core.CiFKryGW.d.mts} +7 -2
  12. package/dist/shared/{core.HKn0jlo_.d.mts → core.D2830qgg.d.mts} +1 -1
  13. package/dist/shared/{core.CFDwncxs.d.mts → core.DJvmfnEi.d.mts} +481 -186
  14. package/dist/shared/{core.BMep80lJ.mjs → core.DgfwjBtu.mjs} +198 -87
  15. package/dist/shared/core.SjLhMA7a.d.mts +62 -0
  16. package/dist/shared/{core.RjpTh3vE.mjs → core.w6BcP9z5.mjs} +263 -168
  17. package/dist/types/index.d.mts +4 -4
  18. package/dist/types/index.mjs +1 -1
  19. package/dist/utils/index.d.mts +2 -2
  20. package/package.json +7 -7
  21. package/src/builder/Builder.ts +1 -0
  22. package/src/builder/Builder.view-common.ts +10 -10
  23. package/src/builder/Builder.view-element.ts +26 -14
  24. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +23 -8
  25. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +9 -4
  26. package/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts +18 -0
  27. package/src/compute-view/deployment-view/predicates/relation-direct.ts +6 -0
  28. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +3 -0
  29. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +3 -0
  30. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +3 -0
  31. package/src/compute-view/deployment-view/predicates/utils.ts +10 -3
  32. package/src/compute-view/deployment-view/utils.ts +7 -4
  33. package/src/compute-view/element-view/__test__/fixture.ts +72 -65
  34. package/src/compute-view/element-view/_types.ts +13 -9
  35. package/src/compute-view/element-view/compute.ts +27 -27
  36. package/src/compute-view/element-view/memory/NodeGroup.ts +4 -3
  37. package/src/compute-view/element-view/memory/memory.ts +3 -2
  38. package/src/compute-view/element-view/memory/stage-include.ts +2 -2
  39. package/src/compute-view/element-view/predicates/_utils.ts +25 -24
  40. package/src/compute-view/element-view/predicates/element-expand.ts +7 -10
  41. package/src/compute-view/element-view/predicates/element-kind-tag.ts +5 -3
  42. package/src/compute-view/element-view/predicates/element-ref.ts +7 -19
  43. package/src/compute-view/element-view/predicates/relation-direct.ts +15 -13
  44. package/src/compute-view/element-view/predicates/relation-in-out.ts +5 -6
  45. package/src/compute-view/element-view/predicates/relation-in.ts +36 -32
  46. package/src/compute-view/element-view/predicates/relation-out.ts +37 -33
  47. package/src/compute-view/element-view/predicates/wildcard.ts +2 -2
  48. package/src/compute-view/utils/applyCustomElementProperties.ts +9 -4
  49. package/src/compute-view/utils/applyCustomRelationProperties.ts +10 -7
  50. package/src/compute-view/utils/elementExpressionToPredicate.ts +27 -26
  51. package/src/compute-view/utils/link-nodes-with-edges.ts +1 -1
  52. package/src/compute-view/utils/relationExpressionToPredicates.ts +10 -17
  53. package/src/compute-view/utils/uniqueTags.ts +3 -3
  54. package/src/index.ts +0 -2
  55. package/src/model/ElementModel.ts +25 -6
  56. package/src/model/LikeC4Model.ts +47 -6
  57. package/src/model/RelationModel.ts +4 -2
  58. package/src/model/view/LikeC4ViewModel.ts +3 -2
  59. package/src/types/_common.ts +0 -4
  60. package/src/types/deployments.ts +3 -2
  61. package/src/types/element.ts +2 -10
  62. package/src/types/expression-v2-model.ts +314 -0
  63. package/src/types/expression-v2.ts +238 -30
  64. package/src/types/index.ts +15 -46
  65. package/src/types/model-data.ts +4 -1
  66. package/src/types/relation.ts +2 -1
  67. package/src/types/scalars.ts +39 -0
  68. package/src/types/view-changes.ts +2 -1
  69. package/src/types/view.ts +7 -8
  70. package/dist/shared/core.30yYKXcZ.d.mts +0 -186
  71. package/src/types/expression.ts +0 -207
@@ -1,22 +1,11 @@
1
1
  import { findConnectionsWithin } from '../../../model/connection/model'
2
- import type { ElementRefExpr } from '../../../types/expression'
3
- import * as Expr from '../../../types/expression'
2
+ import { ModelLayer } from '../../../types/expression-v2-model'
4
3
  import type { Elem, PredicateExecutor } from '../_types'
4
+ import { resolveElements } from './_utils'
5
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)
6
+ export const ElementRefPredicate: PredicateExecutor<ModelLayer.FqnExpr.ModelRef> = {
7
+ include: ({ expr, model, stage, filterWhere }) => {
8
+ const elements = filterWhere(resolveElements(model, expr))
20
9
  if (elements.length === 0) {
21
10
  return
22
11
  }
@@ -28,10 +17,9 @@ export const ElementRefPredicate: PredicateExecutor<ElementRefExpr> = {
28
17
  return stage
29
18
  },
30
19
  exclude: ({ expr, model, stage, filterWhere }) => {
31
- const element = model.element(expr.element)
32
- const elements = filterWhere(applyElementSelector(element, expr))
20
+ const elements = filterWhere(resolveElements(model, expr))
33
21
  stage.exclude(elements)
34
22
 
35
23
  return stage
36
- }
24
+ },
37
25
  }
@@ -3,7 +3,7 @@ import { invariant } from '../../../errors'
3
3
  import { ConnectionModel, findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/model'
4
4
  import type { RelationshipModel } from '../../../model/RelationModel'
5
5
  import type { AnyAux } from '../../../model/types'
6
- import * as Expr from '../../../types/expression'
6
+ import { ModelLayer } from '../../../types/expression-v2-model'
7
7
  import { isSameHierarchy } from '../../../utils'
8
8
  import { ifilter, iflat, iunique, toArray, toSet } from '../../../utils/iterable'
9
9
  import { intersection, union } from '../../../utils/set'
@@ -11,10 +11,12 @@ import type { Elem, PredicateCtx, PredicateExecutor } from '../_types'
11
11
  import { NoWhere } from '../utils'
12
12
  import { includeDescendantsFromMemory, resolveAndIncludeFromMemory, resolveElements } from './_utils'
13
13
 
14
- export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationExpr> = {
14
+ const isWildcard = ModelLayer.FqnExpr.isWildcard
15
+
16
+ export const DirectRelationExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Direct> = {
15
17
  include: ({ expr: { source, target, isBidirectional = false }, memory, model, stage, where, filterWhere }) => {
16
- const sourceIsWildcard = Expr.isWildcard(source)
17
- const targetIsWildcard = Expr.isWildcard(target)
18
+ const sourceIsWildcard = isWildcard(source)
19
+ const targetIsWildcard = isWildcard(target)
18
20
 
19
21
  const connections = [] as ConnectionModel<AnyAux>[]
20
22
  switch (true) {
@@ -166,8 +168,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
166
168
  }
167
169
 
168
170
  default: {
169
- invariant(!Expr.isWildcard(source), 'Inference failed - source must be not a wildcard')
170
- invariant(!Expr.isWildcard(target), 'Inference failed - target must be not a wildcard')
171
+ invariant(!isWildcard(source), 'Inference failed - source must be not a wildcard')
172
+ invariant(!isWildcard(target), 'Inference failed - target must be not a wildcard')
171
173
  const sources = resolveAndIncludeFromMemory(source, { memory, model })
172
174
  const targets = resolveAndIncludeFromMemory(target, { memory, model })
173
175
  const dir = isBidirectional ? 'both' : 'directed'
@@ -186,8 +188,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
186
188
  return stage
187
189
  },
188
190
  exclude: ({ expr: { source, target, isBidirectional }, model, memory, stage, where }) => {
189
- const sourceIsWildcard = Expr.isWildcard(source)
190
- const targetIsWildcard = Expr.isWildcard(target)
191
+ const sourceIsWildcard = isWildcard(source)
192
+ const targetIsWildcard = isWildcard(target)
191
193
 
192
194
  let relations: Set<RelationshipModel<AnyAux>>
193
195
 
@@ -249,8 +251,8 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
249
251
  }
250
252
 
251
253
  default: {
252
- invariant(!Expr.isWildcard(source), 'Inferrence failed - source must be not a wildcard')
253
- invariant(!Expr.isWildcard(target), 'Inferrence failed - target must be not a wildcard')
254
+ invariant(!isWildcard(source), 'Inferrence failed - source must be not a wildcard')
255
+ invariant(!isWildcard(target), 'Inferrence failed - target must be not a wildcard')
254
256
  const sources = resolveElements(model, source)
255
257
  const targets = resolveElements(model, target)
256
258
 
@@ -281,7 +283,7 @@ export const DirectRelationExprPredicate: PredicateExecutor<Expr.DirectRelationE
281
283
  * Resolve elements for both source and target, when one of them is a wildcard
282
284
  */
283
285
  function resolveWildcard(
284
- nonWildcard: Expr.NonWilcard,
286
+ nonWildcard: ModelLayer.FqnExpr.NonWildcard,
285
287
  { memory, model }: Pick<PredicateCtx, 'model' | 'memory'>,
286
288
  ): [elements: Elem[], wildcard: Elem[]] {
287
289
  let sources = resolveElements(model, nonWildcard)
@@ -289,8 +291,8 @@ function resolveWildcard(
289
291
  return [[], []]
290
292
  }
291
293
 
292
- if (Expr.isExpandedElementExpr(nonWildcard) || Expr.isElementRef(nonWildcard)) {
293
- const parent = model.element(nonWildcard.element ?? nonWildcard.expanded)
294
+ if (ModelLayer.FqnExpr.isModelRef(nonWildcard)) {
295
+ const parent = model.element(ModelLayer.FqnRef.toFqn(nonWildcard.ref))
294
296
  const targets = toArray(parent.ascendingSiblings())
295
297
  return [
296
298
  includeDescendantsFromMemory(sources, memory),
@@ -2,16 +2,15 @@ import { unique } from 'remeda'
2
2
  import { type ConnectionModel, findConnectionsBetween } from '../../../model/connection/model'
3
3
  import type { RelationshipModel } from '../../../model/RelationModel'
4
4
  import type { AnyAux } from '../../../model/types'
5
- import * as Expr from '../../../types/expression'
6
- import { toArray } from '../../../utils/iterable'
7
- import { toSet } from '../../../utils/iterable/to'
5
+ import { ModelLayer } from '../../../types/expression-v2-model'
6
+ import { toArray, toSet } from '../../../utils/iterable/to'
8
7
  import type { PredicateExecutor } from '../_types'
9
8
  import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
10
9
 
11
- export const InOutRelationPredicate: PredicateExecutor<Expr.InOutExpr> = {
10
+ export const InOutRelationPredicate: PredicateExecutor<ModelLayer.RelationExpr.InOut> = {
12
11
  include: ({ expr: { inout }, scope, model, memory, stage, filterWhere }) => {
13
12
  const connections = [] as ConnectionModel<AnyAux>[]
14
- if (Expr.isWildcard(inout)) {
13
+ if (ModelLayer.FqnExpr.isWildcard(inout)) {
15
14
  if (!scope) {
16
15
  return
17
16
  }
@@ -47,7 +46,7 @@ export const InOutRelationPredicate: PredicateExecutor<Expr.InOutExpr> = {
47
46
  },
48
47
  exclude: ({ expr: { inout }, model, scope, stage, where }) => {
49
48
  const excluded = [] as RelationshipModel[]
50
- if (Expr.isWildcard(inout)) {
49
+ if (ModelLayer.FqnExpr.isWildcard(inout)) {
51
50
  if (!scope) {
52
51
  return
53
52
  }
@@ -2,23 +2,23 @@ import { anyPass, unique } from 'remeda'
2
2
  import { nonexhaustive } from '../../../errors'
3
3
  import type { LikeC4Model } from '../../../model'
4
4
  import {
5
- Connection,
6
5
  type ConnectionModel,
6
+ Connection,
7
7
  findConnection,
8
- findConnectionsBetween
8
+ findConnectionsBetween,
9
9
  } from '../../../model/connection/model'
10
10
  import type { RelationshipModel } from '../../../model/RelationModel'
11
11
  import type { AnyAux } from '../../../model/types'
12
- import * as Expr from '../../../types/expression'
12
+ import { ModelLayer } from '../../../types/expression-v2-model'
13
13
  import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
14
14
  import type { ConnectionWhere, PredicateExecutor } from '../_types'
15
15
  import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
16
16
 
17
- export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
17
+ export const IncomingExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Incoming> = {
18
18
  include: ({ expr, scope, model, memory, stage, filterWhere }) => {
19
19
  const target = expr.incoming
20
20
  const connections = [] as ConnectionModel<AnyAux>[]
21
- if (Expr.isWildcard(target)) {
21
+ if (ModelLayer.FqnExpr.isWildcard(target)) {
22
22
  if (!scope) {
23
23
  return
24
24
  }
@@ -27,8 +27,8 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
27
27
  ...findConnection(
28
28
  sibling,
29
29
  scope,
30
- 'directed'
31
- )
30
+ 'directed',
31
+ ),
32
32
  )
33
33
  }
34
34
  } else {
@@ -37,8 +37,8 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
37
37
  if (visibleElements.length === 0) {
38
38
  visibleElements.push(
39
39
  ...unique(
40
- targets.flatMap(el => [...el.ascendingSiblings()])
41
- )
40
+ targets.flatMap(el => [...el.ascendingSiblings()]),
41
+ ),
42
42
  )
43
43
  }
44
44
  const ensureIncoming = incomingConnectionPredicate(model, target)
@@ -47,21 +47,21 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
47
47
  ...findConnectionsBetween(
48
48
  visible,
49
49
  targets,
50
- 'directed'
51
- ).filter(ensureIncoming)
50
+ 'directed',
51
+ ).filter(ensureIncoming),
52
52
  )
53
53
  }
54
54
  }
55
55
 
56
56
  stage.addConnections(
57
- filterWhere(connections)
57
+ filterWhere(connections),
58
58
  )
59
59
 
60
60
  return stage
61
61
  },
62
62
  exclude: ({ expr: { incoming }, model, scope, stage, where }) => {
63
63
  const excluded = [] as RelationshipModel[]
64
- if (Expr.isWildcard(incoming)) {
64
+ if (ModelLayer.FqnExpr.isWildcard(incoming)) {
65
65
  if (!scope) {
66
66
  return
67
67
  }
@@ -69,48 +69,52 @@ export const IncomingExprPredicate: PredicateExecutor<Expr.IncomingExpr> = {
69
69
  } else {
70
70
  const elements = resolveElements(model, incoming)
71
71
  excluded.push(
72
- ...elements.flatMap(e => [...e.allIncoming])
72
+ ...elements.flatMap(e => [...e.allIncoming]),
73
73
  )
74
74
  }
75
75
  stage.excludeRelations(new Set(excluded.filter(where)))
76
76
 
77
77
  return stage
78
- }
78
+ },
79
79
  }
80
80
 
81
81
  export function incomingConnectionPredicate(
82
82
  model: LikeC4Model,
83
- expr: Exclude<Expr.ElementExpression, Expr.WildcardExpr>
83
+ expr: ModelLayer.FqnExpr.NonWildcard,
84
84
  ): ConnectionWhere {
85
85
  switch (true) {
86
- case Expr.isElementKindExpr(expr):
87
- case Expr.isElementTagExpr(expr): {
86
+ case ModelLayer.FqnExpr.isElementKindExpr(expr):
87
+ case ModelLayer.FqnExpr.isElementTagExpr(expr): {
88
88
  const isElement = elementExprToPredicate(expr)
89
89
  return (connection) => isElement(connection.target)
90
90
  }
91
- case Expr.isElementRef(expr) && expr.isChildren: {
91
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'children': {
92
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
92
93
  return anyPass(
93
- [...model.children(expr.element)].map(
94
- el => Connection.isIncoming(el.id)
95
- )
94
+ [...model.children(fqn)].map(
95
+ el => Connection.isIncoming(el.id),
96
+ ),
96
97
  )
97
98
  }
98
- case Expr.isElementRef(expr) && expr.isDescendants: {
99
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'descendants': {
100
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
99
101
  return anyPass([
100
- Connection.isInside(expr.element),
101
- ...[...model.children(expr.element)].map(
102
- el => Connection.isIncoming(el.id)
103
- )
102
+ Connection.isInside(fqn),
103
+ ...[...model.children(fqn)].map(
104
+ el => Connection.isIncoming(el.id),
105
+ ),
104
106
  ])
105
107
  }
106
- case Expr.isExpandedElementExpr(expr): {
108
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'expanded': {
109
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
107
110
  return anyPass([
108
- Connection.isIncoming(expr.expanded),
109
- Connection.isInside(expr.expanded)
111
+ Connection.isIncoming(fqn),
112
+ Connection.isInside(fqn),
110
113
  ])
111
114
  }
112
- case Expr.isElementRef(expr): {
113
- return Connection.isIncoming(expr.element)
115
+ case ModelLayer.FqnExpr.isModelRef(expr): {
116
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
117
+ return Connection.isIncoming(fqn)
114
118
  }
115
119
  default:
116
120
  nonexhaustive(expr)
@@ -1,20 +1,20 @@
1
1
  import { anyPass, unique } from 'remeda'
2
2
  import { nonexhaustive } from '../../../errors'
3
- import type { LikeC4Model } from '../../../model'
4
- import { Connection, type ConnectionModel, findConnectionsBetween } from '../../../model/connection/model'
3
+ import { type ConnectionModel, Connection, findConnectionsBetween } from '../../../model/connection/model'
4
+ import type { LikeC4Model } from '../../../model/LikeC4Model'
5
5
  import type { RelationshipModel } from '../../../model/RelationModel'
6
6
  import type { AnyAux } from '../../../model/types'
7
- import * as Expr from '../../../types/expression'
7
+ import { ModelLayer } from '../../../types/expression-v2-model'
8
8
  import { toSet } from '../../../utils/iterable/to'
9
9
  import { elementExprToPredicate } from '../../utils/elementExpressionToPredicate'
10
10
  import type { ConnectionWhere, PredicateExecutor } from '../_types'
11
11
  import { resolveAndIncludeFromMemory, resolveElements } from './_utils'
12
12
 
13
- export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
13
+ export const OutgoingExprPredicate: PredicateExecutor<ModelLayer.RelationExpr.Outgoing> = {
14
14
  include: ({ expr, scope, model, memory, stage, filterWhere }) => {
15
15
  const target = expr.outgoing
16
16
  const connections = [] as ConnectionModel<AnyAux>[]
17
- if (Expr.isWildcard(target)) {
17
+ if (ModelLayer.FqnExpr.isWildcard(target)) {
18
18
  if (!scope) {
19
19
  return
20
20
  }
@@ -23,8 +23,8 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
23
23
  ...findConnectionsBetween(
24
24
  scope,
25
25
  scope.ascendingSiblings(),
26
- 'directed'
27
- )
26
+ 'directed',
27
+ ),
28
28
  )
29
29
  } else {
30
30
  const elements = resolveAndIncludeFromMemory(target, { memory, model })
@@ -32,8 +32,8 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
32
32
  if (visibleElements.length === 0) {
33
33
  visibleElements.push(
34
34
  ...unique(
35
- elements.flatMap(el => [...el.ascendingSiblings()])
36
- )
35
+ elements.flatMap(el => [...el.ascendingSiblings()]),
36
+ ),
37
37
  )
38
38
  }
39
39
  const ensureOutgoing = outgoingConnectionPredicate(model, target)
@@ -43,21 +43,21 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
43
43
  ...findConnectionsBetween(
44
44
  source,
45
45
  visibleElements,
46
- 'directed'
47
- ).filter(ensureOutgoing)
46
+ 'directed',
47
+ ).filter(ensureOutgoing),
48
48
  )
49
49
  }
50
50
  }
51
51
 
52
52
  stage.addConnections(
53
- filterWhere(connections)
53
+ filterWhere(connections),
54
54
  )
55
55
 
56
56
  return stage
57
57
  },
58
58
  exclude: ({ expr: { outgoing }, model, scope, stage, where }) => {
59
59
  const excluded = [] as RelationshipModel[]
60
- if (Expr.isWildcard(outgoing)) {
60
+ if (ModelLayer.FqnExpr.isWildcard(outgoing)) {
61
61
  if (!scope) {
62
62
  return
63
63
  }
@@ -65,50 +65,54 @@ export const OutgoingExprPredicate: PredicateExecutor<Expr.OutgoingExpr> = {
65
65
  } else {
66
66
  const elements = resolveElements(model, outgoing)
67
67
  excluded.push(
68
- ...elements.flatMap(e => [...e.allOutgoing])
68
+ ...elements.flatMap(e => [...e.allOutgoing]),
69
69
  )
70
70
  }
71
71
  stage.excludeRelations(
72
- toSet(excluded.filter(where))
72
+ toSet(excluded.filter(where)),
73
73
  )
74
74
 
75
75
  return stage
76
- }
76
+ },
77
77
  }
78
78
 
79
79
  export function outgoingConnectionPredicate(
80
80
  model: LikeC4Model,
81
- expr: Exclude<Expr.ElementExpression, Expr.WildcardExpr>
81
+ expr: ModelLayer.FqnExpr.NonWildcard,
82
82
  ): ConnectionWhere {
83
83
  switch (true) {
84
- case Expr.isElementKindExpr(expr):
85
- case Expr.isElementTagExpr(expr): {
84
+ case ModelLayer.FqnExpr.isElementKindExpr(expr):
85
+ case ModelLayer.FqnExpr.isElementTagExpr(expr): {
86
86
  const isElement = elementExprToPredicate(expr)
87
87
  return (connection) => isElement(connection.source)
88
88
  }
89
- case Expr.isElementRef(expr) && expr.isChildren: {
89
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'children': {
90
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
90
91
  return anyPass(
91
- [...model.children(expr.element)].map(
92
- el => Connection.isOutgoing(el.id)
93
- )
92
+ [...model.children(fqn)].map(
93
+ el => Connection.isOutgoing(el.id),
94
+ ),
94
95
  )
95
96
  }
96
- case Expr.isElementRef(expr) && expr.isDescendants: {
97
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'descendants': {
98
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
97
99
  return anyPass([
98
- Connection.isInside(expr.element),
99
- ...[...model.children(expr.element)].map(
100
- el => Connection.isOutgoing(el.id)
101
- )
100
+ Connection.isInside(fqn),
101
+ ...[...model.children(fqn)].map(
102
+ el => Connection.isOutgoing(el.id),
103
+ ),
102
104
  ])
103
105
  }
104
- case Expr.isExpandedElementExpr(expr): {
106
+ case ModelLayer.FqnExpr.isModelRef(expr) && expr.selector === 'expanded': {
107
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
105
108
  return anyPass([
106
- Connection.isOutgoing(expr.expanded),
107
- Connection.isInside(expr.expanded)
109
+ Connection.isOutgoing(fqn),
110
+ Connection.isInside(fqn),
108
111
  ])
109
112
  }
110
- case Expr.isElementRef(expr): {
111
- return Connection.isOutgoing(expr.element)
113
+ case ModelLayer.FqnExpr.isModelRef(expr): {
114
+ const fqn = ModelLayer.FqnRef.toFqn(expr.ref)
115
+ return Connection.isOutgoing(fqn)
112
116
  }
113
117
  default:
114
118
  nonexhaustive(expr)
@@ -1,12 +1,12 @@
1
1
  import { filter } from 'remeda'
2
2
  import { findConnectionsBetween, findConnectionsWithin } from '../../../model/connection/model'
3
- import type { WildcardExpr } from '../../../types/expression'
3
+ import type { ModelLayer } from '../../../types/expression-v2-model'
4
4
  import { ifilter, toArray } from '../../../utils/iterable'
5
5
  import { toSet } from '../../../utils/iterable/to'
6
6
  import { type PredicateExecutor, Memory } from '../_types'
7
7
  import { NoWhere } from '../utils'
8
8
 
9
- export const WildcardPredicate: PredicateExecutor<WildcardExpr> = {
9
+ export const WildcardPredicate: PredicateExecutor<ModelLayer.FqnExpr.Wildcard> = {
10
10
  include: ({ scope, model, stage, memory, where }) => {
11
11
  if (!scope) {
12
12
  const rootElements = [...model.roots()].filter(where)
@@ -1,9 +1,14 @@
1
1
  import { isEmpty, isNullish, omitBy } from 'remeda'
2
- import { type ViewRule, ComputedNode, isCustomElement, isViewRuleGroup, isViewRulePredicate } from '../../types'
3
- import type { Expression } from '../../types/expression'
2
+ import {
3
+ type ViewRule,
4
+ ComputedNode,
5
+ isViewRuleGroup,
6
+ isViewRulePredicate,
7
+ ModelLayer,
8
+ } from '../../types'
4
9
  import { elementExprToPredicate } from './elementExpressionToPredicate'
5
10
 
6
- export function flattenGroupRules<T extends Expression>(guard: (expr: Expression) => expr is T) {
11
+ export function flattenGroupRules<T extends ModelLayer.Expression>(guard: (expr: ModelLayer.Expression) => expr is T) {
7
12
  return (rule: ViewRule): Array<T> => {
8
13
  if (isViewRuleGroup(rule)) {
9
14
  return rule.groupRules.flatMap(flattenGroupRules(guard))
@@ -17,7 +22,7 @@ export function flattenGroupRules<T extends Expression>(guard: (expr: Expression
17
22
  }
18
23
 
19
24
  export function applyCustomElementProperties(_rules: ViewRule[], _nodes: ComputedNode[]) {
20
- const rules = _rules.flatMap(flattenGroupRules(isCustomElement))
25
+ const rules = _rules.flatMap(flattenGroupRules(ModelLayer.FqnExpr.isCustom))
21
26
  if (rules.length === 0) {
22
27
  return _nodes
23
28
  }
@@ -1,26 +1,29 @@
1
1
  import { isNullish, omitBy, pick } from 'remeda'
2
- import type { ComputedEdge, ComputedNode, ViewRule } from '../../types'
3
- import * as Expr from '../../types/expression'
2
+ import { type ComputedEdge, type ComputedNode, type ViewRule, ModelLayer } from '../../types'
4
3
  import { flattenGroupRules } from './applyCustomElementProperties'
5
4
  import { relationExpressionToPredicates } from './relationExpressionToPredicates'
6
5
 
7
6
  export function applyCustomRelationProperties(
8
7
  _rules: ViewRule[],
9
8
  nodes: ComputedNode[],
10
- _edges: Iterable<ComputedEdge>
9
+ _edges: Iterable<ComputedEdge>,
11
10
  ): ComputedEdge[] {
12
- const rules = _rules.flatMap(flattenGroupRules(Expr.isCustomRelationExpr))
11
+ const rules = _rules.flatMap(flattenGroupRules(ModelLayer.RelationExpr.isCustom))
13
12
  const edges = Array.from(_edges)
14
13
  if (rules.length === 0 || edges.length === 0) {
15
14
  return edges
16
15
  }
17
16
  for (
18
17
  const {
19
- customRelation: { relation, title, ...customprops }
18
+ customRelation: {
19
+ expr,
20
+ title,
21
+ ...customprops
22
+ },
20
23
  } of rules
21
24
  ) {
22
25
  const props = omitBy(customprops, isNullish)
23
- const satisfies = relationExpressionToPredicates(relation)
26
+ const satisfies = relationExpressionToPredicates(expr)
24
27
  edges.forEach((edge, i) => {
25
28
  const source = nodes.find(n => n.id === edge.source)
26
29
  const target = nodes.find(n => n.id === edge.target)
@@ -32,7 +35,7 @@ export function applyCustomRelationProperties(
32
35
  ...edge,
33
36
  ...props,
34
37
  label: title ?? edge.label,
35
- isCustomized: true
38
+ isCustomized: true,
36
39
  }
37
40
  }
38
41
  })
@@ -1,50 +1,51 @@
1
1
  import { isNullish } from 'remeda'
2
2
  import { nonexhaustive } from '../../errors'
3
3
  import {
4
- type ElementPredicateExpression,
5
- isCustomElement,
6
- isElementKindExpr,
7
- isElementRef,
8
- isElementTagExpr,
9
- isElementWhere,
10
- isExpandedElementExpr,
11
- isWildcard,
12
- whereOperatorAsPredicate
4
+ ModelLayer,
5
+ whereOperatorAsPredicate,
13
6
  } from '../../types'
14
7
  import { parentFqn } from '../../utils'
15
8
 
16
9
  type Predicate<T> = (x: T) => boolean
17
10
 
18
11
  export function elementExprToPredicate<T extends { id: string; tags?: readonly string[] | null; kind: string }>(
19
- target: ElementPredicateExpression
12
+ target: ModelLayer.AnyFqnExpr,
20
13
  ): Predicate<T> {
21
- if (isElementWhere(target)) {
14
+ if (ModelLayer.FqnExpr.isCustom(target)) {
15
+ return elementExprToPredicate(target.custom.expr)
16
+ }
17
+ if (ModelLayer.FqnExpr.isWhere(target)) {
22
18
  const predicate = elementExprToPredicate(target.where.expr)
23
19
  const where = whereOperatorAsPredicate(target.where.condition)
24
20
  return n => predicate(n) && where(n)
25
21
  }
26
- if (isWildcard(target)) {
27
- return () => true
28
- }
29
- if (isElementKindExpr(target)) {
22
+ if (ModelLayer.FqnExpr.isElementKindExpr(target)) {
30
23
  return target.isEqual ? n => n.kind === target.elementKind : n => n.kind !== target.elementKind
31
24
  }
32
- if (isElementTagExpr(target)) {
25
+ if (ModelLayer.FqnExpr.isElementTagExpr(target)) {
33
26
  return target.isEqual
34
27
  ? ({ tags }) => !!tags && tags.includes(target.elementTag)
35
28
  : ({ tags }) => isNullish(tags) || !tags.includes(target.elementTag)
36
29
  }
37
- if (isExpandedElementExpr(target)) {
38
- return n => n.id === target.expanded || parentFqn(n.id) === target.expanded
39
- }
40
- if (isElementRef(target)) {
41
- const { element, isChildren, isDescendants } = target
42
- return isChildren || isDescendants
43
- ? n => n.id.startsWith(element + '.')
44
- : n => (n.id as string) === element
30
+ if (ModelLayer.FqnExpr.isWildcard(target)) {
31
+ return () => true
45
32
  }
46
- if (isCustomElement(target)) {
47
- return elementExprToPredicate(target.custom.expr)
33
+ if (ModelLayer.FqnExpr.isModelRef(target)) {
34
+ const fqn = ModelLayer.FqnRef.toFqn(target.ref)
35
+ if (target.selector === 'expanded') {
36
+ return (n) => {
37
+ return n.id === fqn || parentFqn(n.id) === fqn
38
+ }
39
+ }
40
+ if (target.selector === 'descendants' || target.selector === 'children') {
41
+ const fqnWithDot = fqn + '.'
42
+ return (n) => {
43
+ return n.id.startsWith(fqnWithDot)
44
+ }
45
+ }
46
+ return (n) => {
47
+ return n.id === fqn
48
+ }
48
49
  }
49
50
  nonexhaustive(target)
50
51
  }
@@ -1,6 +1,6 @@
1
1
  import { last, reverse } from 'remeda'
2
2
  import { invariant } from '../../errors'
3
- import type { Fqn } from '../../types/element'
3
+ import type { Fqn } from '../../types'
4
4
  import type { ComputedEdge, ComputedNode } from '../../types/view'
5
5
  import { commonHead } from '../../utils/common-head'
6
6
  import { ancestorsOfNode } from './ancestorsOfNode'