@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,19 +1,19 @@
1
- import { forEach, indexBy, isString, map, mapToObj, prop, values } from 'remeda'
1
+ import { indexBy, isString, map, prop } from 'remeda'
2
+ import { LikeC4Model } from '../../../model'
2
3
  import {
3
4
  type BorderStyle,
4
5
  type Color,
5
6
  type ComputedView,
6
7
  type CustomElementExpr as C4CustomElementExpr,
7
8
  type CustomRelationExpr as C4CustomRelationExpr,
8
- type EdgeId,
9
9
  type Element,
10
10
  type ElementExpression as C4ElementExpression,
11
11
  type ElementKind,
12
12
  type ElementShape,
13
- type ElementView,
14
13
  type ElementWhereExpr,
15
14
  type Expression as C4Expression,
16
15
  type Fqn,
16
+ type GlobalPredicateId,
17
17
  type GlobalStyleID,
18
18
  type IconUrl,
19
19
  type IncomingExpr as C4IncomingExpr,
@@ -22,10 +22,9 @@ import {
22
22
  isElementWhere,
23
23
  isRelationExpression,
24
24
  isRelationWhere,
25
+ type ModelRelation,
25
26
  type NonEmptyArray,
26
27
  type OutgoingExpr as C4OutgoingExpr,
27
- type Relation,
28
- type RelationExpr as C4RelationExpr,
29
28
  type RelationId,
30
29
  type RelationshipArrowType,
31
30
  type RelationshipLineType,
@@ -33,19 +32,16 @@ import {
33
32
  type Tag,
34
33
  type ViewId,
35
34
  type ViewRule,
35
+ type ViewRuleGlobalPredicateRef,
36
36
  type ViewRuleGlobalStyle,
37
37
  type ViewRuleGroup,
38
38
  type ViewRulePredicate,
39
39
  type ViewRuleStyle,
40
- type WhereOperator
40
+ type WhereOperator,
41
41
  } from '../../../types'
42
- import { LikeC4ModelGraph } from '../../LikeC4ModelGraph'
42
+ import { type DirectRelationExpr as C4RelationExpr } from '../../../types/expression'
43
43
  import { withReadableEdges } from '../../utils/with-readable-edges'
44
- import { ComputeCtx } from '../compute'
45
-
46
- function computeElementView(view: ElementView, graph: LikeC4ModelGraph) {
47
- return ComputeCtx.elementView(view, graph)
48
- }
44
+ import { computeElementView } from '../compute'
49
45
 
50
46
  /**
51
47
  ┌──────────────────────────────────────────────────┐
@@ -149,9 +145,9 @@ const el = ({
149
145
  tags: tags as NonEmptyArray<Tag> ?? null,
150
146
  links: null,
151
147
  style: {
152
- ...style
148
+ ...style,
153
149
  },
154
- ...props
150
+ ...props,
155
151
  })
156
152
 
157
153
  export const fakeElements = {
@@ -159,68 +155,68 @@ export const fakeElements = {
159
155
  id: 'customer',
160
156
  kind: 'actor',
161
157
  title: 'customer',
162
- shape: 'person'
158
+ shape: 'person',
163
159
  }),
164
160
  'support': el({
165
161
  id: 'support',
166
162
  kind: 'actor',
167
163
  title: 'support',
168
- shape: 'person'
164
+ shape: 'person',
169
165
  }),
170
166
  'cloud': el({
171
167
  id: 'cloud',
172
168
  kind: 'system',
173
169
  title: 'cloud',
174
170
  icon: 'none',
175
- tags: ['next', 'old']
171
+ tags: ['next', 'old'],
176
172
  }),
177
173
  'cloud.backend': el({
178
174
  id: 'cloud.backend',
179
175
  kind: 'container',
180
- title: 'backend'
176
+ title: 'backend',
181
177
  }),
182
178
  'cloud.frontend': el({
183
179
  id: 'cloud.frontend',
184
180
  kind: 'container',
185
181
  title: 'frontend',
186
- shape: 'browser'
182
+ shape: 'browser',
187
183
  }),
188
184
  'cloud.backend.graphql': el({
189
185
  id: 'cloud.backend.graphql',
190
186
  kind: 'component',
191
187
  icon: 'tech:graphql' as IconUrl,
192
- title: 'graphql'
188
+ title: 'graphql',
193
189
  }),
194
190
  'email': el({
195
191
  id: 'email',
196
192
  kind: 'system',
197
- title: 'email'
193
+ title: 'email',
198
194
  }),
199
195
  'cloud.backend.storage': el({
200
196
  id: 'cloud.backend.storage',
201
197
  kind: 'component',
202
198
  title: 'storage',
203
- tags: ['storage', 'old']
204
- }),
205
- 'cloud.frontend.adminPanel': el({
206
- id: 'cloud.frontend.adminPanel',
207
- kind: 'component',
208
- title: 'adminPanel',
209
- tags: ['old']
199
+ tags: ['storage', 'old'],
210
200
  }),
211
201
  'cloud.frontend.dashboard': el({
212
202
  id: 'cloud.frontend.dashboard',
213
203
  kind: 'component',
214
204
  title: 'dashboard',
215
205
  icon: 'tech:react' as IconUrl,
216
- tags: ['next']
206
+ tags: ['next'],
207
+ }),
208
+ 'cloud.frontend.supportPanel': el({
209
+ id: 'cloud.frontend.supportPanel',
210
+ kind: 'component',
211
+ title: 'adminPanel',
212
+ tags: ['old'],
217
213
  }),
218
214
  'amazon': el({
219
215
  id: 'amazon',
220
216
  kind: 'system',
221
217
  title: 'amazon',
222
218
  icon: 'tech:aws' as IconUrl,
223
- tags: ['aws']
219
+ tags: ['aws'],
224
220
  }),
225
221
  'amazon.s3': el({
226
222
  id: 'amazon.s3',
@@ -228,8 +224,8 @@ export const fakeElements = {
228
224
  title: 's3',
229
225
  shape: 'storage',
230
226
  icon: 'aws:s3' as IconUrl,
231
- tags: ['aws', 'storage']
232
- })
227
+ tags: ['aws', 'storage'],
228
+ }),
233
229
  } satisfies Record<string, Element>
234
230
 
235
231
  export type FakeElementIds = keyof typeof fakeElements
@@ -255,51 +251,41 @@ const rel = <Source extends FakeElementIds, Target extends FakeElementIds>({
255
251
  title: title ?? '',
256
252
  source: source as Fqn,
257
253
  target: target as Fqn,
258
- ...(props as any)
259
- }) as Omit<Relation, 'id'> & { id: `${Source}:${Target}` }
254
+ ...(props as any),
255
+ }) as Omit<ModelRelation, 'id'> & { id: `${Source}:${Target}` }
260
256
 
261
257
  export const fakeRelations = [
262
258
  rel({
263
259
  source: 'customer',
264
260
  target: 'cloud.frontend.dashboard',
265
- title: 'opens in browser'
261
+ title: 'opens in browser',
266
262
  }),
267
263
  rel({
268
264
  source: 'support',
269
- target: 'cloud.frontend.adminPanel',
270
- title: 'manages'
265
+ target: 'cloud.frontend.supportPanel',
266
+ title: 'manages',
271
267
  }),
272
268
  rel({
273
269
  source: 'cloud.backend.storage',
274
270
  target: 'amazon.s3',
275
271
  title: 'uploads',
276
- tags: ['aws', 'storage', 'legacy']
272
+ tags: ['aws', 'storage', 'legacy'],
277
273
  }),
278
274
  rel({
279
275
  source: 'customer',
280
276
  target: 'cloud',
281
- title: 'uses'
277
+ title: 'uses',
282
278
  }),
283
279
  rel({
284
280
  source: 'cloud.backend.graphql',
285
281
  target: 'cloud.backend.storage',
286
282
  title: 'stores',
287
- tags: ['old', 'storage']
283
+ tags: ['old', 'storage'],
288
284
  }),
289
- // rel({
290
- // source: 'cloud.backend',
291
- // target: 'cloud.email',
292
- // title: 'schedule emails'
293
- // }),
294
- // rel({
295
- // source: 'cloud.email',
296
- // target: 'customer',
297
- // title: 'send emails'
298
- // }),
299
285
  rel({
300
286
  source: 'cloud.frontend',
301
287
  target: 'cloud.backend',
302
- title: 'requests'
288
+ title: 'requests',
303
289
  }),
304
290
  rel({
305
291
  source: 'cloud.frontend.dashboard',
@@ -307,16 +293,16 @@ export const fakeRelations = [
307
293
  kind: 'graphlql',
308
294
  title: 'requests',
309
295
  line: 'solid',
310
- tags: ['next']
296
+ tags: ['next'],
311
297
  }),
312
298
  rel({
313
- source: 'cloud.frontend.adminPanel',
299
+ source: 'cloud.frontend.supportPanel',
314
300
  target: 'cloud.backend.graphql',
315
301
  kind: 'graphlql',
316
302
  title: 'fetches',
317
303
  line: 'dashed',
318
304
  tail: 'odiamond',
319
- tags: ['old']
305
+ tags: ['old'],
320
306
  }),
321
307
  rel({
322
308
  source: 'cloud',
@@ -324,60 +310,92 @@ export const fakeRelations = [
324
310
  title: 'uses',
325
311
  head: 'diamond',
326
312
  tail: 'odiamond',
327
- tags: ['aws']
313
+ tags: ['aws'],
328
314
  }),
329
315
  rel({
330
316
  source: 'cloud.backend',
331
317
  target: 'email',
332
318
  title: 'schedule',
333
- tags: ['communication']
319
+ tags: ['communication'],
334
320
  }),
335
321
  rel({
336
322
  source: 'cloud',
337
323
  target: 'email',
338
324
  title: 'uses',
339
- tags: ['communication']
325
+ tags: ['communication'],
340
326
  }),
341
327
  rel({
342
328
  source: 'email',
343
329
  target: 'cloud',
344
330
  title: 'notifies',
345
- tags: ['communication']
346
- })
331
+ tags: ['communication'],
332
+ }),
347
333
  ]
348
334
 
349
335
  export const globalStyles = {
350
336
  'mute_old': [{
351
337
  targets: [$expr({
352
338
  elementTag: 'old' as Tag,
353
- isEqual: true
339
+ isEqual: true,
354
340
  })],
355
341
  style: {
356
- color: 'muted'
357
- }
342
+ color: 'muted',
343
+ },
358
344
  }],
359
345
  'red_next': [{
360
346
  targets: [$expr({
361
347
  elementTag: 'next' as Tag,
362
- isEqual: true
348
+ isEqual: true,
363
349
  })],
364
350
  style: {
365
- color: 'red'
366
- }
367
- }]
351
+ color: 'red',
352
+ },
353
+ }],
368
354
  } as const
369
355
 
370
356
  export type FakeRelationIds = (typeof fakeRelations)[number]['id']
371
-
372
- export const fakeModel = new LikeC4ModelGraph({
357
+ const fakeParsedModel = {
373
358
  elements: fakeElements,
374
359
  relations: indexBy(fakeRelations, r => r.id),
360
+ deployments: {
361
+ elements: {},
362
+ relations: {},
363
+ },
364
+ views: {},
375
365
  globals: {
376
- predicates: {},
366
+ predicates: {
367
+ 'remove_tag_old': [
368
+ $exclude('*', {
369
+ tag: { eq: 'old' },
370
+ }),
371
+ ],
372
+ 'remove_not_tag_old': [
373
+ $exclude('*', {
374
+ tag: { neq: 'old' },
375
+ }),
376
+ ],
377
+ 'include_next': [
378
+ $include('* -> *', {
379
+ where: {
380
+ and: [
381
+ {
382
+ or: [
383
+ { tag: { eq: 'communication' } },
384
+ { tag: { eq: 'next' } },
385
+ { tag: { eq: 'old' } },
386
+ ],
387
+ },
388
+ { tag: { neq: 'storage' } },
389
+ ],
390
+ },
391
+ }),
392
+ ],
393
+ } satisfies Record<string, NonEmptyArray<ViewRulePredicate>>,
377
394
  dynamicPredicates: {},
378
- styles: globalStyles
379
- }
380
- })
395
+ styles: globalStyles,
396
+ },
397
+ } as const
398
+ export const fakeModel = LikeC4Model.fromDump(fakeParsedModel)
381
399
 
382
400
  const emptyView = {
383
401
  __: 'element' as const,
@@ -387,18 +405,23 @@ const emptyView = {
387
405
  tags: null,
388
406
  links: null,
389
407
  customColorDefinitions: {},
390
- rules: []
408
+ rules: [],
391
409
  }
392
410
 
393
411
  export const includeWildcard = {
394
412
  include: [
395
413
  {
396
- wildcard: true
397
- }
398
- ]
414
+ wildcard: true,
415
+ },
416
+ ],
399
417
  } satisfies ViewRule
400
418
 
401
- export type ElementRefExpr = '*' | FakeElementIds | `${FakeElementIds}.*` | `${FakeElementIds}._`
419
+ export type ElementRefExpr =
420
+ | '*'
421
+ | FakeElementIds
422
+ | `${FakeElementIds}.*`
423
+ | `${FakeElementIds}.**`
424
+ | `${FakeElementIds}._`
402
425
 
403
426
  type InOutExpr = `-> ${ElementRefExpr} ->`
404
427
  type IncomingExpr = `-> ${ElementRefExpr}`
@@ -425,42 +448,42 @@ export function $custom(
425
448
  icon?: string
426
449
  opacity?: number
427
450
  navigateTo?: string
428
- }
451
+ },
429
452
  ): C4CustomElementExpr {
430
453
  return {
431
454
  custom: {
432
455
  expr: $expr(expr) as any,
433
- ...props as any
434
- }
456
+ ...props as any,
457
+ },
435
458
  }
436
459
  }
437
460
 
438
461
  export function $customRelation(
439
462
  relation: RelationExpr,
440
- props: Omit<C4CustomRelationExpr['customRelation'], 'relation'>
463
+ props: Omit<C4CustomRelationExpr['customRelation'], 'relation'>,
441
464
  ): C4CustomRelationExpr {
442
465
  return {
443
466
  customRelation: {
444
467
  relation: $expr(relation) as any,
445
- ...props
446
- }
468
+ ...props,
469
+ },
447
470
  }
448
471
  }
449
472
 
450
473
  export function $where(
451
474
  expr: Expression | C4Expression,
452
- operator: WhereOperator<TestTag, string>
475
+ operator: WhereOperator<TestTag, string>,
453
476
  ): ElementWhereExpr | RelationWhereExpr {
454
477
  return {
455
478
  where: {
456
479
  expr: $expr(expr) as any,
457
- condition: operator
458
- }
480
+ condition: operator,
481
+ },
459
482
  }
460
483
  }
461
484
 
462
485
  export function $inout(
463
- expr: InOutExpr | C4ElementExpression
486
+ expr: InOutExpr | C4ElementExpression,
464
487
  ): C4InOutExpr {
465
488
  const innerExpression = !isString(expr)
466
489
  ? expr as C4Expression
@@ -470,7 +493,7 @@ export function $inout(
470
493
  }
471
494
 
472
495
  export function $incoming(
473
- expr: IncomingExpr | C4ElementExpression
496
+ expr: IncomingExpr | C4ElementExpression,
474
497
  ): C4IncomingExpr {
475
498
  const innerExpression = !isString(expr)
476
499
  ? expr as C4Expression
@@ -480,7 +503,7 @@ export function $incoming(
480
503
  }
481
504
 
482
505
  export function $outgoing(
483
- expr: OutgoingExpr | C4ElementExpression
506
+ expr: OutgoingExpr | C4ElementExpression,
484
507
  ): C4OutgoingExpr {
485
508
  const innerExpression = !isString(expr)
486
509
  ? expr as C4Expression
@@ -490,7 +513,7 @@ export function $outgoing(
490
513
  }
491
514
 
492
515
  export function $relation(
493
- expr: RelationExpr
516
+ expr: RelationExpr,
494
517
  ): C4RelationExpr {
495
518
  const [source, target] = expr.split(/ -> | <-> /)
496
519
  const isBidirectional = expr.includes(' <-> ')
@@ -498,7 +521,7 @@ export function $relation(
498
521
  return {
499
522
  source: $expr(source as ElementRefExpr) as any,
500
523
  target: $expr(target as ElementRefExpr) as any,
501
- ...(isBidirectional && { isBidirectional })
524
+ ...(isBidirectional && { isBidirectional }),
502
525
  }
503
526
  }
504
527
 
@@ -520,23 +543,23 @@ export function $expr(expr: Expression | C4Expression): C4Expression {
520
543
  }
521
544
  if (expr.endsWith('._')) {
522
545
  return {
523
- expanded: expr.replace('._', '') as Fqn
546
+ expanded: expr.replace('._', '') as Fqn,
524
547
  }
525
548
  }
526
549
  if (expr.endsWith('.*')) {
527
550
  return {
528
551
  element: expr.replace('.*', '') as Fqn,
529
- isChildren: true
552
+ isChildren: true,
530
553
  }
531
554
  }
532
555
  if (expr.endsWith('.**')) {
533
556
  return {
534
- element: expr.replace('.*', '') as Fqn,
535
- isDescendants: true
557
+ element: expr.replace('.**', '') as Fqn,
558
+ isDescendants: true,
536
559
  }
537
560
  }
538
561
  return {
539
- element: expr as Fqn
562
+ element: expr as Fqn,
540
563
  }
541
564
  }
542
565
 
@@ -558,7 +581,7 @@ export function $include(expr: Expression | C4Expression, props?: CustomProps):
558
581
  let _expr = props?.where ? $where(expr, props.where) : $expr(expr)
559
582
  _expr = props?.with ? $with(_expr, props.with) : _expr
560
583
  return {
561
- include: [_expr]
584
+ include: [_expr],
562
585
  }
563
586
  }
564
587
  export function $with(expr: C4Expression, props?: CustomProps['with']): C4CustomRelationExpr | C4CustomElementExpr {
@@ -566,15 +589,15 @@ export function $with(expr: C4Expression, props?: CustomProps['with']): C4Custom
566
589
  return {
567
590
  customRelation: {
568
591
  relation: expr,
569
- ...props as any
570
- }
592
+ ...props as any,
593
+ },
571
594
  }
572
595
  } else if (isElementRef(expr) || isElementWhere(expr)) {
573
596
  return {
574
597
  custom: {
575
598
  expr: expr,
576
- ...props as any
577
- }
599
+ ...props as any,
600
+ },
578
601
  }
579
602
  }
580
603
 
@@ -583,33 +606,40 @@ export function $with(expr: C4Expression, props?: CustomProps['with']): C4Custom
583
606
  export function $exclude(expr: Expression | C4Expression, where?: WhereOperator<TestTag, string>): ViewRulePredicate {
584
607
  let _expr = where ? $where(expr, where) : $expr(expr)
585
608
  return {
586
- exclude: [_expr]
609
+ exclude: [_expr],
587
610
  }
588
611
  }
589
612
  export function $group(groupRules: ViewRuleGroup['groupRules']): ViewRuleGroup {
590
613
  return {
591
614
  title: null,
592
- groupRules
615
+ groupRules,
593
616
  }
594
617
  }
595
618
 
596
619
  export function $style(element: ElementRefExpr, style: ViewRuleStyle['style']): ViewRuleStyle {
597
620
  return {
598
621
  targets: [$expr(element) as C4ElementExpression],
599
- style: Object.assign({}, style)
622
+ style: Object.assign({}, style),
600
623
  }
601
624
  }
602
625
 
603
- type GlobalStyles = keyof typeof globalStyles
604
- type GlobalExpr = `style ${GlobalStyles}`
605
- export function $global(expr: GlobalExpr): ViewRuleGlobalStyle {
626
+ type GlobalStyles = `style ${keyof typeof globalStyles}`
627
+ type GlobalPredicate = `predicate ${keyof typeof fakeParsedModel.globals.predicates}`
628
+ type GlobalExpr = GlobalStyles | GlobalPredicate
629
+ export function $global(expr: GlobalExpr): ViewRuleGlobalStyle | ViewRuleGlobalPredicateRef {
606
630
  const [_t, id] = expr.split(' ') as [string, string]
607
- if (_t === 'style') {
608
- return {
609
- styleId: id as GlobalStyleID
610
- }
631
+ switch (_t) {
632
+ case 'predicate':
633
+ return {
634
+ predicateId: id as GlobalPredicateId,
635
+ }
636
+ case 'style':
637
+ return {
638
+ styleId: id as GlobalStyleID,
639
+ }
640
+ default:
641
+ throw new Error(`Invalid global expression: ${expr}`)
611
642
  }
612
- throw new Error('Invalid global expression')
613
643
  }
614
644
 
615
645
  export function computeView(
@@ -618,21 +648,21 @@ export function computeView(
618
648
  let result: ComputedView
619
649
  if (args.length === 1) {
620
650
  result = computeElementView(
651
+ fakeModel,
621
652
  {
622
653
  ...emptyView,
623
- rules: [args[0]].flat()
654
+ rules: [args[0]].flat(),
624
655
  },
625
- fakeModel
626
656
  )
627
657
  } else {
628
658
  result = computeElementView(
659
+ fakeModel,
629
660
  {
630
661
  ...emptyView,
631
662
  id: 'index' as ViewId,
632
663
  viewOf: args[0] as Fqn,
633
- rules: [args[1]].flat()
664
+ rules: [args[1]].flat(),
634
665
  },
635
- fakeModel
636
666
  )
637
667
  }
638
668
 
@@ -640,6 +670,6 @@ export function computeView(
640
670
 
641
671
  return Object.assign(result, {
642
672
  nodeIds: map(result.nodes, prop('id')) as string[],
643
- edgeIds: map(result.edges, prop('id')) as string[]
673
+ edgeIds: map(result.edges, prop('id')) as string[],
644
674
  })
645
675
  }
@@ -0,0 +1,48 @@
1
+ import { type LikeC4Model } from '../../model'
2
+ import type { ConnectionModel } from '../../model/connection/model'
3
+ import type { RelationshipModel } from '../../model/RelationModel'
4
+ import type { AnyAux } from '../../model/types'
5
+ import type { ElementExpression, Expression, RelationExpression } from '../../types/expression'
6
+
7
+ import type { Ctx, Memory, Stage, StageExclude, StageInclude } from './memory'
8
+
9
+ export type Where<T extends {}> = (x: T) => boolean
10
+
11
+ export type Elem = Ctx['Element']
12
+ export type Connection = Ctx['Connection']
13
+
14
+ export type ElementWhere = Where<Elem>
15
+ export type ElementWhereFilter = (elements: readonly Elem[]) => Elem[]
16
+ export type ConnectionWhere = Where<Connection>
17
+ export type RelationshipWhere = Where<RelationshipModel>
18
+ export type ConnectionWhereFilter = (connections: readonly Connection[]) => Connection[]
19
+
20
+ export { Memory } from './memory'
21
+
22
+ export type Connections = ReadonlyArray<ConnectionModel<AnyAux>>
23
+
24
+ export interface PredicateCtx<Expr extends Expression = Expression> {
25
+ expr: Expr
26
+ stage: Stage
27
+ // View scope
28
+ scope: Elem | null
29
+ model: LikeC4Model<AnyAux>
30
+ memory: Memory
31
+ where: Expr extends RelationExpression ? RelationshipWhere
32
+ : Expr extends ElementExpression ? ElementWhere
33
+ : never
34
+ filterWhere: Expr extends RelationExpression ? ConnectionWhereFilter
35
+ : Expr extends ElementExpression ? ElementWhereFilter
36
+ : never
37
+ }
38
+ export interface IncludePredicateCtx<Expr extends Expression = Expression> extends PredicateCtx<Expr> {
39
+ stage: StageInclude
40
+ }
41
+ export interface ExcludePredicateCtx<Expr extends Expression = Expression> extends PredicateCtx<Expr> {
42
+ stage: StageExclude
43
+ }
44
+
45
+ export interface PredicateExecutor<Expr extends Expression> {
46
+ include(ctx: IncludePredicateCtx<Expr>): StageInclude | undefined
47
+ exclude(ctx: ExcludePredicateCtx<Expr>): StageExclude | undefined
48
+ }