@likec4/core 1.38.1 → 1.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/builder/index.d.mts +6 -3
  2. package/dist/builder/index.mjs +55 -111
  3. package/dist/compute-view/index.d.mts +6 -3
  4. package/dist/compute-view/index.mjs +33 -34
  5. package/dist/compute-view/relationships-view/index.d.mts +6 -3
  6. package/dist/compute-view/relationships-view/index.mjs +6 -6
  7. package/dist/index.d.mts +8 -5
  8. package/dist/index.mjs +15 -24
  9. package/dist/model/connection/deployment/index.d.mts +8 -5
  10. package/dist/model/connection/deployment/index.mjs +7 -9
  11. package/dist/model/connection/index.d.mts +10 -7
  12. package/dist/model/connection/index.mjs +10 -14
  13. package/dist/model/connection/model/index.d.mts +8 -5
  14. package/dist/model/connection/model/index.mjs +7 -10
  15. package/dist/model/index.d.mts +13 -10
  16. package/dist/model/index.mjs +17 -20
  17. package/dist/shared/core.20m8Um0g.d.mts +253 -0
  18. package/dist/shared/{core.CpwrZi3D.mjs → core.4u1dVmfX.mjs} +3 -5
  19. package/dist/shared/{core.Bp-IQmJR.mjs → core.BB6zA-UU.mjs} +9 -214
  20. package/dist/shared/{core.BH0VqY-7.mjs → core.BVNaR17u.mjs} +1 -1
  21. package/dist/shared/{core.BL_xjl90.mjs → core.Be1n9a0i.mjs} +4 -5
  22. package/dist/shared/{core.BoyJPEen.mjs → core.Be4Jy9Qx.mjs} +2 -2
  23. package/dist/shared/{core.H8NbNp2X.mjs → core.BqVo8LrH.mjs} +1 -1
  24. package/dist/shared/{core.DDoAFHHp.mjs → core.BuoXfSMj.mjs} +1 -1
  25. package/dist/shared/{core.DhDo8LAz.d.mts → core.C7pZp1nR.d.mts} +3 -3
  26. package/dist/shared/{core.BH9nN-_I.mjs → core.CCD1ID81.mjs} +3 -4
  27. package/dist/shared/{core.8KM0D6va.mjs → core.CNGyqkJh.mjs} +1 -9
  28. package/dist/shared/{core.B0oEIXqd.mjs → core.CUw_2J9j.mjs} +1 -1
  29. package/dist/shared/{core.C4Cn4Jy_.mjs → core.CWv15GLo.mjs} +11 -15
  30. package/dist/shared/{core.Bf5zKDK1.d.mts → core.CXCmvCws.d.mts} +2 -2
  31. package/dist/shared/core.CaT0SUUK.mjs +201 -0
  32. package/dist/shared/{core.Dtw1SBlz.d.mts → core.ClpXZ4Ib.d.mts} +3 -3
  33. package/dist/shared/{core.DC6zzxS0.mjs → core.CsbOakly.mjs} +13 -22
  34. package/dist/shared/{core.Btl47GOn.mjs → core.DLpidoWc.mjs} +2 -2
  35. package/dist/shared/{core.wwaSalox.d.mts → core.DM3vdkO_.d.mts} +1 -1
  36. package/dist/shared/core.DXhDWKFZ.d.mts +3 -0
  37. package/dist/shared/{core.O6FG0HF9.d.mts → core.DdzRtJ9d.d.mts} +1 -1
  38. package/dist/shared/{core.OUoo2ohq.mjs → core.DgttqsJc.mjs} +5 -9
  39. package/dist/shared/{core.Dhc0yIwT.mjs → core.DlG1xWt2.mjs} +3 -43
  40. package/dist/shared/core.DnRszv-l.mjs +11982 -0
  41. package/dist/shared/core.DoM6aM9N.mjs +7 -0
  42. package/dist/shared/{core.CzHQRs5x.mjs → core.DozSPE83.mjs} +43 -60
  43. package/dist/shared/{core.DsMrjY2q.mjs → core.GTgsmXS_.mjs} +2 -2
  44. package/dist/shared/core.ILwny7BV.mjs +38 -0
  45. package/dist/shared/core.PHwHXzkG.d.mts +213 -0
  46. package/dist/shared/core.T-eLZTW_.mjs +59 -0
  47. package/dist/shared/{core.CE_hG7EJ.d.mts → core.aWJgARyY.d.mts} +10 -486
  48. package/dist/shared/{core.BvlHvikl.d.mts → core.v1iEaXaR.d.mts} +5 -3
  49. package/dist/shared/core.yHe79zEl.mjs +98 -0
  50. package/dist/theme/index.d.mts +3 -126
  51. package/dist/theme/index.mjs +2 -3
  52. package/dist/types/_aux.d.mts +1 -1
  53. package/dist/types/expression-model.d.mts +191 -0
  54. package/dist/types/expression-model.mjs +112 -0
  55. package/dist/types/expression.d.mts +7 -0
  56. package/dist/types/expression.mjs +116 -0
  57. package/dist/types/fqnRef.d.mts +61 -0
  58. package/dist/types/fqnRef.mjs +46 -0
  59. package/dist/types/index.d.mts +6 -3
  60. package/dist/types/index.mjs +9 -9
  61. package/dist/types/scalar.mjs +2 -3
  62. package/dist/utils/index.d.mts +6 -428
  63. package/dist/utils/index.mjs +56 -15
  64. package/dist/utils/iterable/index.d.mts +2 -3
  65. package/dist/utils/iterable/index.mjs +9 -44
  66. package/package.json +8 -7
  67. package/src/index.ts +24 -1
  68. package/src/model/RelationModel.ts +1 -1
  69. package/src/model/index.ts +1 -1
  70. package/src/theme/element.ts +2 -2
  71. package/src/theme/relationships.ts +2 -2
  72. package/src/types/RichText.ts +1 -1
  73. package/src/types/expression-model.ts +3 -1
  74. package/src/types/expression.ts +3 -1
  75. package/src/types/fqnRef.ts +4 -1
  76. package/src/utils/guards.ts +0 -1
  77. package/src/utils/index.ts +0 -1
  78. package/dist/shared/core.BW8K1y6R.mjs +0 -278
  79. package/dist/shared/core.BgvIuGGU.mjs +0 -3
  80. package/dist/shared/core.BpJu1RrF.mjs +0 -5
  81. package/dist/shared/core.ByrmCl9I.mjs +0 -5
  82. package/dist/shared/core.CnIyafWn.mjs +0 -3
  83. package/dist/shared/core.DK6I-Nr7.mjs +0 -149
  84. package/dist/shared/core.DbRvwARP.mjs +0 -5
  85. package/dist/shared/core.Dw47t7nG.mjs +0 -5236
  86. package/dist/shared/core.zLlww-07.mjs +0 -3
  87. package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +0 -425
  88. package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +0 -318
  89. package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +0 -221
  90. package/src/compute-view/deployment-view/__test__/TestHelper.ts +0 -249
  91. package/src/compute-view/deployment-view/__test__/fixture.ts +0 -238
  92. package/src/compute-view/dynamic-view/__test__/fixture.ts +0 -67
  93. package/src/compute-view/element-view/__test__/TestHelper.ts +0 -282
  94. package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +0 -458
  95. package/src/compute-view/element-view/__test__/fixture.ts +0 -749
  96. package/src/compute-view/utils/__snapshots__/sortNodes.spec.ts.snap +0 -113
  97. package/src/model/__test__/fixture.ts +0 -168
  98. package/src/theme/__test__/theme-index.ts +0 -29
@@ -1,249 +0,0 @@
1
- import { indexBy, isArray, isString, map, mapValues, pipe, prop } from 'remeda'
2
- import type { Writable } from 'type-fest'
3
- import type { ExpectStatic } from 'vitest'
4
- import { expect as vitestExpect } from 'vitest'
5
- import {
6
- type AnyTypes,
7
- type Builder,
8
- type DeploymentRulesBuilderOp,
9
- type Types,
10
- type ViewPredicate,
11
- } from '../../../builder'
12
- import * as viewhelpers from '../../../builder/Builder.view-common'
13
- import { mkViewBuilder } from '../../../builder/Builder.views'
14
- import type { AnyAux, LikeC4Model } from '../../../model'
15
- import { differenceConnections } from '../../../model/connection'
16
- import {
17
- type ComputedDeploymentView,
18
- type DeploymentViewRule,
19
- type ParsedDeploymentView as DeploymentView,
20
- type ViewId,
21
- _stage,
22
- _type,
23
- } from '../../../types'
24
- import { difference as differenceSet, imap, invariant, toArray } from '../../../utils'
25
- import { withReadableEdges } from '../../utils/with-readable-edges'
26
- import { processPredicates as processPredicatesImpl } from '../compute'
27
- import { Memory } from '../memory'
28
-
29
- type ConnectionExpression<T extends AnyTypes> = `${T['DeploymentFqn']} -> ${T['DeploymentFqn']}`
30
-
31
- type ConnectionsDeepMatcher<M extends string, D extends string> = {
32
- [K in `${D} -> ${D}`]?: {
33
- model?: Array<`${M} -> ${M}`>
34
- deployment?: Array<`${D} -> ${D}`>
35
- }
36
- }
37
-
38
- type ToDeepMatcher<T extends AnyTypes> = ConnectionsDeepMatcher<T['Fqn'], T['DeploymentFqn']>
39
-
40
- type ConnectionEqual<T extends AnyTypes> = [ToDeepMatcher<T>] | [ConnectionExpression<T>, ...ConnectionExpression<T>[]]
41
-
42
- type Elem = Memory['Ctx']['Element']
43
- type Connection = Memory['Ctx']['Connection']
44
-
45
- export class TestHelper<T extends AnyTypes> {
46
- Aux!: Types.ToAux<T>
47
-
48
- model: LikeC4Model.Computed<typeof this.Aux>
49
-
50
- static $include = viewhelpers.$include
51
- static $exclude = viewhelpers.$exclude
52
- static $style = viewhelpers.$style
53
-
54
- $include = viewhelpers.$include
55
- $exclude = viewhelpers.$exclude
56
- $style = viewhelpers.$style
57
-
58
- static from<const T extends AnyTypes>(builder: Builder<T>, expect = vitestExpect): TestHelper<T> {
59
- return new TestHelper(builder, expect)
60
- }
61
-
62
- constructor(
63
- private builder: Builder<T>,
64
- private _expect: ExpectStatic,
65
- ) {
66
- this.model = builder.toLikeC4Model()
67
- }
68
-
69
- computeView = (...rules: DeploymentRulesBuilderOp<T>[]) => {
70
- const view = this.builder
71
- .clone()
72
- .views(_ => _.deploymentView('dev').with(...rules))
73
- .toLikeC4Model()
74
- .view('dev')
75
- invariant(view.isDeploymentView())
76
- return withReadableEdges(
77
- view.$view,
78
- ' -> ',
79
- )
80
- }
81
-
82
- processPredicates(...rules: DeploymentRulesBuilderOp<T>[]) {
83
- return ProcessPredicates.execute(this, ...rules)
84
- }
85
-
86
- expectView(view: ComputedDeploymentView) {
87
- return {
88
- toHave: (nodesAndEdges: { nodes: Array<T['DeploymentFqn']>; edges: Array<ConnectionExpression<T>> }) => {
89
- const actual = {
90
- nodes: view.nodes.map(prop('id')),
91
- edges: view.edges.map(prop('id')),
92
- }
93
- this._expect(actual).toEqual(nodesAndEdges)
94
- },
95
- toHaveNodes: <Id extends T['DeploymentFqn']>(...nodes: Id[]) => {
96
- this._expect(view.nodes.map(prop('id'))).toEqual(nodes)
97
- },
98
- toHaveEdges: <Id extends ConnectionExpression<T>>(...edges: Id[]) => {
99
- this._expect(view.edges.map(prop('id'))).toEqual(edges)
100
- },
101
- }
102
- }
103
-
104
- expectComputedView(...rules: DeploymentRulesBuilderOp<T>[]) {
105
- return this.expectView(this.computeView(...rules))
106
- }
107
-
108
- expectMemory = (memory: Memory) => ({
109
- toHaveAllElements: <Id extends T['DeploymentFqn']>(...ids: Id[]) => {
110
- this._expect(map([...memory.elements], prop('id'))).toEqual(ids)
111
- },
112
- toHaveElements: <Id extends T['DeploymentFqn']>(...ids: Id[]) => {
113
- this._expect(map([...memory.final], prop('id'))).toEqual(ids)
114
- },
115
- toHaveConnections: (...matchers: ConnectionEqual<T>) => {
116
- this.expectConnections(memory.connections).toEqual(...matchers)
117
- },
118
- })
119
-
120
- expectElements = (elements: ReadonlySet<Elem>) => ({
121
- toEqual: <const Id extends ViewPredicate.DeploymentConnectionExpression<T>>(...ids: Id[]) => {
122
- this._expect(toArray(imap(elements, prop('id')))).toEqual(ids)
123
- },
124
- })
125
-
126
- expectConnections = (connections: ReadonlyArray<Connection>) => ({
127
- toBeEmpty: () => {
128
- this._expect(connections.map(c => c.expression)).to.be.empty
129
- },
130
- toEqual: (...matchers: ConnectionEqual<T>) => {
131
- const [matcher, ...rest] = matchers
132
- if (isString(matcher)) {
133
- this._expect(connections.map(c => c.expression)).toEqual([matcher, ...rest])
134
- return
135
- }
136
- const obj = pipe(
137
- connections,
138
- indexBy(prop('expression')),
139
- mapValues(c => ({
140
- model: toArray(imap(c.relations.model, prop('expression'))).sort(),
141
- deployment: toArray(imap(c.relations.deployment, prop('expression'))).sort(),
142
- })),
143
- )
144
- const expected = mapValues(matcher, (v: any) => ({
145
- ...v,
146
- model: v.model ? [...v.model].sort() : [],
147
- deployment: v.deployment ? [...v.deployment].sort() : [],
148
- }))
149
- this._expect(obj).toEqual(expected)
150
- },
151
- })
152
-
153
- expectStep = (step: ProcessPredicates<T>) => ({
154
- ...this.expectMemory(step.memory),
155
- })
156
-
157
- expect(value: ComputedDeploymentView): ReturnType<typeof this['expectView']>
158
- expect(value: Set<Elem>): ReturnType<typeof this['expectElements']>
159
- expect(value: ReadonlyArray<Connection>): ReturnType<typeof this['expectConnections']>
160
- expect(value: Memory | ProcessPredicates<T>): ReturnType<typeof this['expectMemory']>
161
- expect(value: Memory | ProcessPredicates<T> | Set<Elem> | ComputedDeploymentView | ReadonlyArray<Connection>) {
162
- if (value instanceof Memory) {
163
- return this.expectMemory(value)
164
- }
165
- if (value instanceof ProcessPredicates) {
166
- return this.expectStep(value)
167
- }
168
- if (value instanceof Set) {
169
- return this.expectElements(value)
170
- }
171
- if (isArray(value)) {
172
- return this.expectConnections(value)
173
- }
174
- return this.expectView(value)
175
- }
176
- }
177
-
178
- class ProcessPredicates<T extends AnyTypes> {
179
- static execute<A extends AnyTypes>(
180
- test: TestHelper<A>,
181
- ...rules: DeploymentRulesBuilderOp<A>[]
182
- ): ProcessPredicates<A> {
183
- const processor = new ProcessPredicates(test)
184
- processor.next(...rules)
185
- return processor
186
- }
187
-
188
- public viewrules: ReadonlyArray<DeploymentViewRule<AnyAux>> = []
189
-
190
- public previousMemory: Memory = Memory.empty()
191
- public memory: Memory = Memory.empty()
192
- public predicates: DeploymentRulesBuilderOp<T>[] = []
193
-
194
- constructor(
195
- public readonly t: TestHelper<T>,
196
- protected age = 0,
197
- ) {}
198
-
199
- get elements() {
200
- return toArray(imap(this.memory.elements, prop('id')))
201
- }
202
-
203
- get connections() {
204
- return this.memory.connections.map(c => c.expression)
205
- }
206
-
207
- diff() {
208
- const prevState = this.previousMemory
209
- const state = this.memory
210
- return {
211
- added: this.memory.update({
212
- elements: differenceSet(state.elements, prevState.elements),
213
- explicits: differenceSet(state.explicits, prevState.explicits),
214
- final: differenceSet(state.final, prevState.final),
215
- connections: differenceConnections(state.connections, prevState.connections),
216
- }),
217
- removed: this.memory.update({
218
- elements: differenceSet(prevState.elements, state.elements),
219
- explicits: differenceSet(prevState.explicits, state.explicits),
220
- final: differenceSet(prevState.final, state.final),
221
- connections: differenceConnections(prevState.connections, state.connections),
222
- }),
223
- }
224
- }
225
-
226
- next(...predicates: DeploymentRulesBuilderOp<T>[]): this {
227
- const view = {
228
- id: 'test' as ViewId,
229
- [_stage]: 'parsed',
230
- [_type]: 'deployment',
231
- rules: [],
232
- title: null,
233
- description: null,
234
- } as Writable<DeploymentView<typeof this.t.model.Aux>>
235
- let vb = mkViewBuilder(view) as any
236
- this.predicates = [
237
- ...this.predicates,
238
- ...predicates,
239
- ]
240
- for (const rule of this.predicates) {
241
- rule(vb)
242
- }
243
- this.previousMemory = this.memory
244
- this.viewrules = view.rules
245
- this.memory = processPredicatesImpl(this.t.model.deployment, view.rules)
246
- this.age++
247
- return this
248
- }
249
- }
@@ -1,238 +0,0 @@
1
- import { map, prop } from 'remeda'
2
- import type { DeploymentRulesBuilderOp } from '../../../builder'
3
- import { Builder } from '../../../builder'
4
- import { LikeC4Model } from '../../../model'
5
- import type { ParsedDeploymentView as DeploymentView } from '../../../types'
6
- import { withReadableEdges } from '../../utils/with-readable-edges'
7
- import { computeDeploymentView } from '../compute'
8
-
9
- const {
10
- builder: b,
11
- model: {
12
- model,
13
- person,
14
- system,
15
- component,
16
- webapp,
17
- mobile,
18
- ...$m
19
- },
20
- deployment: {
21
- deployment,
22
- env,
23
- node,
24
- zone,
25
- instanceOf,
26
- ...$d
27
- },
28
- views: {
29
- views,
30
- deploymentView,
31
- $rules,
32
- $include,
33
- $exclude,
34
- },
35
- } = Builder.forSpecification({
36
- elements: {
37
- person: {
38
- style: {
39
- shape: 'person',
40
- },
41
- },
42
- system: {},
43
- component: {},
44
- webapp: {
45
- style: {
46
- shape: 'browser',
47
- },
48
- },
49
- mobile: {
50
- style: {
51
- shape: 'mobile',
52
- },
53
- },
54
- },
55
- deployments: {
56
- env: {},
57
- zone: {},
58
- node: {},
59
- },
60
- tags: {
61
- old: {
62
- color: 'red',
63
- },
64
- next: {
65
- color: 'green',
66
- },
67
- temp: {
68
- color: 'blue',
69
- },
70
- },
71
- relationships: { 'https': {} },
72
- })
73
-
74
- export const builder = b
75
- .with(
76
- model(
77
- person('customer', {
78
- title: 'Happy Customer',
79
- }),
80
- system('cloud').with(
81
- component('frontend').with(
82
- webapp('dashboard', {
83
- title: 'Dashboard',
84
- }),
85
- mobile('mobile', {
86
- title: 'Mobile',
87
- }),
88
- ),
89
- component('auth'),
90
- component('backend').with(
91
- component('api'),
92
- ),
93
- component('media', {
94
- shape: 'storage',
95
- }),
96
- ),
97
- system('aws').with(
98
- component('rds', {
99
- shape: 'storage',
100
- }),
101
- component('s3', {
102
- shape: 'storage',
103
- }),
104
- ),
105
- system('email'),
106
- ),
107
- model(
108
- $m.rel('customer', 'cloud', 'uses services'),
109
- $m.rel('customer', 'cloud.frontend.mobile', 'opens mobile app'),
110
- $m.rel('customer', 'cloud.frontend.dashboard', {
111
- title: 'opens in browser',
112
- tags: ['old'],
113
- }),
114
- $m.rel('cloud.frontend.dashboard', 'cloud.auth', {
115
- title: 'authenticates',
116
- color: 'green',
117
- }),
118
- $m.rel('cloud.frontend.dashboard', 'cloud.backend.api', {
119
- title: 'fetches data',
120
- tags: ['old'],
121
- }),
122
- $m.rel('cloud.frontend.dashboard', 'cloud.media', {
123
- title: 'fetches media',
124
- tags: ['temp'],
125
- }),
126
- $m.rel('cloud.frontend.mobile', 'cloud.auth', {
127
- title: 'authenticates',
128
- color: 'amber',
129
- }),
130
- $m.rel('cloud.frontend.mobile', 'cloud.backend.api', 'fetches data'),
131
- $m.rel('cloud.frontend.mobile', 'cloud.media', 'fetches media'),
132
- $m.rel('cloud.backend.api', 'cloud.auth', 'authorizes'),
133
- $m.rel('cloud.backend.api', 'cloud.media', 'uploads media'),
134
- $m.rel('cloud.backend.api', 'aws.rds', 'reads/writes'),
135
- $m.rel('cloud.backend.api', 'email', 'sends emails'),
136
- $m.rel('cloud.media', 'aws.s3', 'uploads'),
137
- $m.rel('email', 'customer', 'sends emails'),
138
- ),
139
- deployment(
140
- node('customer').with(
141
- instanceOf('instance', 'customer'),
142
- ),
143
- env('prod').with(
144
- zone('eu').with(
145
- zone('zone1').with(
146
- instanceOf('api', 'cloud.backend.api'),
147
- instanceOf('ui', 'cloud.frontend.dashboard', {
148
- title: 'prod.eu.zone1/dashboard',
149
- }),
150
- ),
151
- zone('zone2').with(
152
- instanceOf('api', 'cloud.backend.api'),
153
- instanceOf('ui', 'cloud.frontend.dashboard', {
154
- title: 'prod.eu.zone2/dashboard',
155
- }),
156
- ),
157
- instanceOf('auth', 'cloud.auth'),
158
- instanceOf('media', 'cloud.media'),
159
- instanceOf('db', 'aws.rds'),
160
- ),
161
- zone('us').with(
162
- zone('zone1').with(
163
- instanceOf('api', 'cloud.backend.api'),
164
- instanceOf('ui', 'cloud.frontend.dashboard', {
165
- title: 'prod.us.zone1/dashboard',
166
- }),
167
- ),
168
- instanceOf('db', 'aws.rds'),
169
- ),
170
- ),
171
- env('dev').with(
172
- node('devCustomer').with(
173
- instanceOf('instance', 'customer'),
174
- ),
175
- node('devCloud').with(
176
- instanceOf('instance', 'cloud'),
177
- ),
178
- ),
179
- env('acc').with(
180
- node('testCustomer').with(
181
- instanceOf('instance', 'customer'),
182
- ),
183
- zone('eu').with(
184
- instanceOf('api', 'cloud.backend.api'),
185
- instanceOf('ui', 'cloud.frontend.dashboard'),
186
- instanceOf('auth', 'cloud.auth'),
187
- instanceOf('db', 'aws.rds'),
188
- ),
189
- ),
190
- env('global').with(
191
- instanceOf('email', 'email'),
192
- ),
193
- $d.rel('prod.eu.db', 'prod.us.db', {
194
- title: 'replicates',
195
- color: 'green',
196
- }),
197
- $d.rel('prod.us.db', 'prod.eu.db', {
198
- title: 'replicates',
199
- color: 'amber',
200
- }),
201
- ),
202
- )
203
- .clone()
204
-
205
- export type Types = typeof builder['Types']
206
-
207
- export { $exclude, $include }
208
-
209
- export function computeView(...rules: DeploymentRulesBuilderOp<Types>[]) {
210
- const modelsource = builder.clone()
211
- .with(
212
- views(
213
- deploymentView('index', $rules(...rules)),
214
- ),
215
- ).build()
216
-
217
- const model = LikeC4Model.fromParsed(modelsource)
218
-
219
- const view = withReadableEdges(computeDeploymentView(model, modelsource.views.index as DeploymentView<any>))
220
-
221
- return Object.assign(view, {
222
- nodeIds: map(view.nodes, prop('id')) as string[],
223
- edgeIds: map(view.edges, prop('id')) as string[],
224
- })
225
- }
226
-
227
- export function computeNodesAndEdges(...rules: DeploymentRulesBuilderOp<Types>[]) {
228
- const { nodeIds, edgeIds } = computeView(...rules)
229
- return {
230
- // Starts with capital letter to be first in snapshot
231
- Nodes: nodeIds,
232
- edges: edgeIds,
233
- }
234
- }
235
-
236
- export function createModel() {
237
- return LikeC4Model.fromParsed(builder.build())
238
- }
@@ -1,67 +0,0 @@
1
- import { partition } from 'remeda'
2
- import type {
3
- DynamicViewIncludeRule,
4
- DynamicViewRule,
5
- DynamicViewStep,
6
- ElementViewPredicate,
7
- Fqn,
8
- ParsedDynamicView as DynamicView,
9
- ViewId,
10
- } from '../../../types'
11
- import { type $Aux, type FakeElementIds, fakeModel } from '../../element-view/__test__/fixture'
12
- import { computeDynamicView } from '../compute'
13
-
14
- const emptyView = {
15
- _type: 'dynamic' as const,
16
- id: 'index' as ViewId,
17
- title: null,
18
- description: null,
19
- tags: null,
20
- links: null,
21
- rules: [],
22
- }
23
-
24
- type StepExpr = `${FakeElementIds} ${'->' | '<-'} ${FakeElementIds}`
25
- type StepProps = Omit<DynamicViewStep, 'source' | 'target' | 'isBackward'>
26
-
27
- export function $step(expr: StepExpr, props?: string | Partial<StepProps>): DynamicViewStep {
28
- const title = typeof props === 'string' ? props : props?.title
29
- if (expr.includes(' -> ')) {
30
- const [source, target] = expr.split(' -> ')
31
- return {
32
- source: source as Fqn,
33
- target: target as Fqn,
34
- ...(typeof props === 'object' ? props : {}),
35
- title: title ?? null,
36
- }
37
- }
38
- if (expr.includes(' <- ')) {
39
- const [target, source] = expr.split(' <- ')
40
- return {
41
- source: source as Fqn,
42
- target: target as Fqn,
43
- ...(typeof props === 'object' ? props : {}),
44
- title: title ?? null,
45
- isBackward: true,
46
- }
47
- }
48
- throw new Error(`Invalid step expression: ${expr}`)
49
- }
50
-
51
- export function compute(
52
- stepsAndRules: (DynamicViewStep<$Aux> | ElementViewPredicate<$Aux> | DynamicViewIncludeRule<$Aux>)[],
53
- ) {
54
- const [steps, rules] = partition(stepsAndRules, (s): s is DynamicViewStep => 'source' in s)
55
- let view = computeDynamicView(
56
- fakeModel,
57
- {
58
- ...emptyView,
59
- steps,
60
- rules: rules as DynamicViewRule[],
61
- } as DynamicView,
62
- )
63
- return Object.assign(view, {
64
- nodeIds: view.nodes.map((node) => node.id) as string[],
65
- edgeIds: view.edges.map((edge) => edge.id) as string[],
66
- })
67
- }