@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.
- package/dist/builder/index.d.mts +6 -3
- package/dist/builder/index.mjs +55 -111
- package/dist/compute-view/index.d.mts +6 -3
- package/dist/compute-view/index.mjs +33 -34
- package/dist/compute-view/relationships-view/index.d.mts +6 -3
- package/dist/compute-view/relationships-view/index.mjs +6 -6
- package/dist/index.d.mts +8 -5
- package/dist/index.mjs +15 -24
- package/dist/model/connection/deployment/index.d.mts +8 -5
- package/dist/model/connection/deployment/index.mjs +7 -9
- package/dist/model/connection/index.d.mts +10 -7
- package/dist/model/connection/index.mjs +10 -14
- package/dist/model/connection/model/index.d.mts +8 -5
- package/dist/model/connection/model/index.mjs +7 -10
- package/dist/model/index.d.mts +13 -10
- package/dist/model/index.mjs +17 -20
- package/dist/shared/core.20m8Um0g.d.mts +253 -0
- package/dist/shared/{core.CpwrZi3D.mjs → core.4u1dVmfX.mjs} +3 -5
- package/dist/shared/{core.Bp-IQmJR.mjs → core.BB6zA-UU.mjs} +9 -214
- package/dist/shared/{core.BH0VqY-7.mjs → core.BVNaR17u.mjs} +1 -1
- package/dist/shared/{core.BL_xjl90.mjs → core.Be1n9a0i.mjs} +4 -5
- package/dist/shared/{core.BoyJPEen.mjs → core.Be4Jy9Qx.mjs} +2 -2
- package/dist/shared/{core.H8NbNp2X.mjs → core.BqVo8LrH.mjs} +1 -1
- package/dist/shared/{core.DDoAFHHp.mjs → core.BuoXfSMj.mjs} +1 -1
- package/dist/shared/{core.DhDo8LAz.d.mts → core.C7pZp1nR.d.mts} +3 -3
- package/dist/shared/{core.BH9nN-_I.mjs → core.CCD1ID81.mjs} +3 -4
- package/dist/shared/{core.8KM0D6va.mjs → core.CNGyqkJh.mjs} +1 -9
- package/dist/shared/{core.B0oEIXqd.mjs → core.CUw_2J9j.mjs} +1 -1
- package/dist/shared/{core.C4Cn4Jy_.mjs → core.CWv15GLo.mjs} +11 -15
- package/dist/shared/{core.Bf5zKDK1.d.mts → core.CXCmvCws.d.mts} +2 -2
- package/dist/shared/core.CaT0SUUK.mjs +201 -0
- package/dist/shared/{core.Dtw1SBlz.d.mts → core.ClpXZ4Ib.d.mts} +3 -3
- package/dist/shared/{core.DC6zzxS0.mjs → core.CsbOakly.mjs} +13 -22
- package/dist/shared/{core.Btl47GOn.mjs → core.DLpidoWc.mjs} +2 -2
- package/dist/shared/{core.wwaSalox.d.mts → core.DM3vdkO_.d.mts} +1 -1
- package/dist/shared/core.DXhDWKFZ.d.mts +3 -0
- package/dist/shared/{core.O6FG0HF9.d.mts → core.DdzRtJ9d.d.mts} +1 -1
- package/dist/shared/{core.OUoo2ohq.mjs → core.DgttqsJc.mjs} +5 -9
- package/dist/shared/{core.Dhc0yIwT.mjs → core.DlG1xWt2.mjs} +3 -43
- package/dist/shared/core.DnRszv-l.mjs +11982 -0
- package/dist/shared/core.DoM6aM9N.mjs +7 -0
- package/dist/shared/{core.CzHQRs5x.mjs → core.DozSPE83.mjs} +43 -60
- package/dist/shared/{core.DsMrjY2q.mjs → core.GTgsmXS_.mjs} +2 -2
- package/dist/shared/core.ILwny7BV.mjs +38 -0
- package/dist/shared/core.PHwHXzkG.d.mts +213 -0
- package/dist/shared/core.T-eLZTW_.mjs +59 -0
- package/dist/shared/{core.CE_hG7EJ.d.mts → core.aWJgARyY.d.mts} +10 -486
- package/dist/shared/{core.BvlHvikl.d.mts → core.v1iEaXaR.d.mts} +5 -3
- package/dist/shared/core.yHe79zEl.mjs +98 -0
- package/dist/theme/index.d.mts +3 -126
- package/dist/theme/index.mjs +2 -3
- package/dist/types/_aux.d.mts +1 -1
- package/dist/types/expression-model.d.mts +191 -0
- package/dist/types/expression-model.mjs +112 -0
- package/dist/types/expression.d.mts +7 -0
- package/dist/types/expression.mjs +116 -0
- package/dist/types/fqnRef.d.mts +61 -0
- package/dist/types/fqnRef.mjs +46 -0
- package/dist/types/index.d.mts +6 -3
- package/dist/types/index.mjs +9 -9
- package/dist/types/scalar.mjs +2 -3
- package/dist/utils/index.d.mts +6 -428
- package/dist/utils/index.mjs +56 -15
- package/dist/utils/iterable/index.d.mts +2 -3
- package/dist/utils/iterable/index.mjs +9 -44
- package/package.json +8 -7
- package/src/index.ts +24 -1
- package/src/model/RelationModel.ts +1 -1
- package/src/model/index.ts +1 -1
- package/src/theme/element.ts +2 -2
- package/src/theme/relationships.ts +2 -2
- package/src/types/RichText.ts +1 -1
- package/src/types/expression-model.ts +3 -1
- package/src/types/expression.ts +3 -1
- package/src/types/fqnRef.ts +4 -1
- package/src/utils/guards.ts +0 -1
- package/src/utils/index.ts +0 -1
- package/dist/shared/core.BW8K1y6R.mjs +0 -278
- package/dist/shared/core.BgvIuGGU.mjs +0 -3
- package/dist/shared/core.BpJu1RrF.mjs +0 -5
- package/dist/shared/core.ByrmCl9I.mjs +0 -5
- package/dist/shared/core.CnIyafWn.mjs +0 -3
- package/dist/shared/core.DK6I-Nr7.mjs +0 -149
- package/dist/shared/core.DbRvwARP.mjs +0 -5
- package/dist/shared/core.Dw47t7nG.mjs +0 -5236
- package/dist/shared/core.zLlww-07.mjs +0 -3
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +0 -425
- package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +0 -318
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +0 -221
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +0 -249
- package/src/compute-view/deployment-view/__test__/fixture.ts +0 -238
- package/src/compute-view/dynamic-view/__test__/fixture.ts +0 -67
- package/src/compute-view/element-view/__test__/TestHelper.ts +0 -282
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +0 -458
- package/src/compute-view/element-view/__test__/fixture.ts +0 -749
- package/src/compute-view/utils/__snapshots__/sortNodes.spec.ts.snap +0 -113
- package/src/model/__test__/fixture.ts +0 -168
- 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
|
-
}
|