@likec4/core 1.17.1 → 1.19.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/LICENSE +1 -1
- package/dist/builder/index.d.mts +502 -0
- package/dist/builder/index.d.ts +502 -0
- package/dist/builder/index.js +871 -0
- package/dist/compute-view/index.d.mts +22 -0
- package/dist/compute-view/index.d.ts +22 -0
- package/dist/compute-view/index.js +78 -0
- package/dist/index.d.mts +10 -919
- package/dist/index.d.ts +10 -919
- package/dist/{index.mjs → index.js} +7 -1688
- package/dist/model/index.d.mts +254 -0
- package/dist/model/index.d.ts +254 -0
- package/dist/model/index.js +1 -0
- package/dist/shared/chunk-RAAYCPUM.M-JWF7SS.js +21 -0
- package/dist/shared/core.BIfgabEw.d.ts +719 -0
- package/dist/shared/core.BZ9Msq7w.d.mts +719 -0
- package/dist/shared/{core.CoLQkcYL.d.cts → core.C05RDLhi.d.ts} +460 -362
- package/dist/shared/{core.CoLQkcYL.d.mts → core.CmYMqgha.d.mts} +460 -362
- package/dist/shared/core.D6-fWbM3.d.ts +127 -0
- package/dist/shared/core.D74xkKkG.d.mts +148 -0
- package/dist/shared/core.D74xkKkG.d.ts +148 -0
- package/dist/shared/core.sLaWHBjR.d.mts +127 -0
- package/dist/shared/index.-BdzdI2C.js +7443 -0
- package/dist/shared/object_hash.CE_oF3I3.js +1222 -0
- package/dist/shared/{core.BXTs-8n7.mjs → view.CyZrG8BJ.js} +108 -47
- package/dist/types/index.d.mts +71 -1
- package/dist/types/index.d.ts +71 -1
- package/dist/types/index.js +20 -0
- package/dist/utils/index.d.mts +404 -0
- package/dist/utils/index.d.ts +404 -0
- package/dist/utils/index.js +330 -0
- package/package.json +59 -47
- package/src/builder/Builder-style1.test-d.ts +190 -0
- package/src/builder/Builder-style2.test-d.ts +175 -0
- package/src/builder/Builder.deployment.ts +224 -0
- package/src/builder/Builder.deploymentModel.ts +385 -0
- package/src/builder/Builder.element.ts +19 -19
- package/src/builder/Builder.model.ts +67 -42
- package/src/builder/Builder.ts +533 -367
- package/src/builder/Builder.view-common.ts +234 -0
- package/src/builder/Builder.view-deployment.ts +135 -0
- package/src/builder/Builder.view-element.ts +189 -0
- package/src/builder/Builder.views.ts +109 -33
- package/src/builder/Builder.with.ts +475 -0
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +374 -0
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +183 -0
- package/src/builder/__snapshots__/Builder.spec.ts.snap +374 -0
- package/src/builder/_types.ts +113 -18
- package/src/builder/index.ts +10 -4
- package/src/colors/index.ts +2 -2
- package/src/compute-view/compute-view.ts +83 -0
- package/src/compute-view/deployment-view/__test__/TestHelper.ts +236 -0
- package/src/compute-view/deployment-view/__test__/fixture.ts +198 -0
- package/src/compute-view/deployment-view/_types.ts +37 -0
- package/src/compute-view/deployment-view/clean-connections.ts +238 -0
- package/src/compute-view/deployment-view/compute.ts +125 -0
- package/src/compute-view/deployment-view/memory/index.ts +9 -0
- package/src/compute-view/deployment-view/memory/memory.ts +97 -0
- package/src/compute-view/deployment-view/predicates/elements.ts +144 -0
- package/src/compute-view/deployment-view/predicates/relation-direct.ts +237 -0
- package/src/compute-view/deployment-view/predicates/relation-in-out.ts +61 -0
- package/src/compute-view/deployment-view/predicates/relation-incoming.ts +95 -0
- package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +88 -0
- package/src/compute-view/deployment-view/predicates/wildcard.ts +29 -0
- package/src/compute-view/deployment-view/stages/stage-exclude.ts +5 -0
- package/src/compute-view/deployment-view/stages/stage-final.ts +245 -0
- package/src/compute-view/deployment-view/stages/stage-include.ts +95 -0
- package/src/compute-view/deployment-view/utils.ts +276 -0
- package/src/compute-view/dynamic-view/__test__/fixture.ts +58 -0
- package/src/compute-view/dynamic-view/compute.ts +324 -0
- package/src/compute-view/element-view/__test__/TestHelper.ts +258 -0
- package/src/compute-view/element-view/__test__/__snapshots__/legacy.spec.ts.snap +458 -0
- package/src/compute-view/element-view/__test__/fixture.ts +675 -0
- package/src/compute-view/element-view/_types.ts +48 -0
- package/src/compute-view/element-view/clean-connections.ts +113 -0
- package/src/compute-view/element-view/compute.ts +315 -0
- package/src/compute-view/element-view/memory/NodeGroup.ts +31 -0
- package/src/compute-view/element-view/memory/index.ts +10 -0
- package/src/compute-view/element-view/memory/memory.ts +177 -0
- package/src/compute-view/element-view/memory/stage-exclude.ts +59 -0
- package/src/compute-view/element-view/memory/stage-final.ts +129 -0
- package/src/compute-view/element-view/memory/stage-include.ts +128 -0
- package/src/compute-view/element-view/predicates/_utils.ts +86 -0
- package/src/compute-view/element-view/predicates/element-expand.ts +33 -0
- package/src/compute-view/element-view/predicates/element-kind-tag.ts +26 -0
- package/src/compute-view/element-view/predicates/element-ref.ts +37 -0
- package/src/compute-view/element-view/predicates/relation-direct.ts +309 -0
- package/src/compute-view/element-view/predicates/relation-in-out.ts +66 -0
- package/src/compute-view/element-view/predicates/relation-in.ts +118 -0
- package/src/compute-view/element-view/predicates/relation-out.ts +116 -0
- package/src/compute-view/element-view/predicates/wildcard.ts +88 -0
- package/src/compute-view/element-view/utils.ts +59 -0
- package/src/compute-view/index.ts +4 -0
- package/src/compute-view/memory/AbstractMemory.ts +45 -0
- package/src/compute-view/memory/AbstractStageExclude.ts +216 -0
- package/src/compute-view/memory/AbstractStageInclude.ts +200 -0
- package/src/compute-view/memory/_types.ts +147 -0
- package/src/compute-view/memory/index.ts +5 -0
- package/src/compute-view/memory/ops.ts +43 -0
- package/src/compute-view/utils/__snapshots__/sortNodes.spec.ts.snap +113 -0
- package/src/compute-view/utils/ancestorsOfNode.ts +19 -0
- package/src/compute-view/utils/applyCustomElementProperties.ts +66 -0
- package/src/compute-view/utils/applyCustomRelationProperties.ts +41 -0
- package/src/compute-view/utils/applyViewRuleStyles.ts +53 -0
- package/src/compute-view/utils/buildComputedNodes.ts +148 -0
- package/src/compute-view/utils/buildElementNotations.ts +63 -0
- package/src/compute-view/utils/elementExpressionToPredicate.ts +50 -0
- package/src/compute-view/utils/link-nodes-with-edges.ts +54 -0
- package/src/compute-view/utils/merge-props-from-relationships.ts +128 -0
- package/src/compute-view/utils/relationExpressionToPredicates.ts +55 -0
- package/src/compute-view/utils/resolve-extended-views.ts +69 -0
- package/src/compute-view/utils/resolve-global-rules.ts +83 -0
- package/src/compute-view/utils/topological-sort.ts +256 -0
- package/src/compute-view/utils/uniqueTags.test.ts +42 -0
- package/src/compute-view/utils/uniqueTags.ts +21 -0
- package/src/compute-view/utils/view-hash.ts +27 -0
- package/src/compute-view/utils/with-readable-edges.ts +36 -0
- package/src/index.ts +22 -12
- package/src/model/DeploymentElementModel.ts +599 -0
- package/src/model/DeploymentModel.ts +370 -0
- package/src/model/ElementModel.ts +221 -0
- package/src/model/LikeC4Model.test-d.ts +152 -0
- package/src/model/LikeC4Model.ts +336 -457
- package/src/model/RelationModel.ts +85 -0
- package/src/model/__test__/fixture.ts +149 -338
- package/src/model/connection/Connection.ts +72 -0
- package/src/model/connection/deployment/DeploymentConnectionModel.ts +178 -0
- package/src/model/connection/deployment/find.ts +120 -0
- package/src/model/connection/deployment/index.ts +8 -0
- package/src/model/connection/index.ts +22 -0
- package/src/model/connection/model/ConnectionModel.ts +157 -0
- package/src/model/connection/model/find.ts +117 -0
- package/src/model/connection/model/index.ts +8 -0
- package/src/model/connection/ops.ts +274 -0
- package/src/model/guards.ts +9 -0
- package/src/model/index.ts +46 -2
- package/src/model/types.ts +112 -15
- package/src/model/view/EdgeModel.ts +103 -0
- package/src/model/view/LikeC4ViewModel.ts +226 -0
- package/src/model/view/NodeModel.ts +229 -0
- package/src/types/_common.ts +55 -1
- package/src/types/deployments.ts +169 -0
- package/src/types/element.ts +9 -5
- package/src/types/expression-v2.ts +172 -0
- package/src/types/expression.ts +17 -11
- package/src/types/global.ts +3 -3
- package/src/types/index.ts +220 -12
- package/src/types/model.ts +75 -12
- package/src/types/operators.ts +1 -1
- package/src/types/overview-graph.ts +2 -2
- package/src/types/relation.ts +18 -14
- package/src/types/theme.ts +0 -1
- package/src/types/view-notation.ts +2 -2
- package/src/types/view.ts +117 -41
- package/src/utils/{commonHead.ts → common-head.ts} +2 -0
- package/src/utils/const.ts +1 -0
- package/src/utils/fqn.ts +203 -56
- package/src/utils/getOrCreate.ts +42 -0
- package/src/utils/graphlib.ts +10 -0
- package/src/utils/index.ts +74 -6
- package/src/utils/iterable/_types.ts +5 -0
- package/src/utils/iterable/filter.ts +55 -0
- package/src/utils/iterable/flat.ts +17 -0
- package/src/utils/iterable/index.ts +12 -0
- package/src/utils/iterable/map.ts +40 -0
- package/src/utils/iterable/reduce.ts +24 -0
- package/src/utils/iterable/some.ts +36 -0
- package/src/utils/iterable/to.ts +19 -0
- package/src/utils/iterable/unique.ts +29 -0
- package/src/utils/object-hash.ts +3 -0
- package/src/utils/relations.ts +3 -64
- package/src/utils/set.ts +78 -0
- package/src/utils/string-hash.ts +16 -0
- package/dist/index.cjs +0 -5452
- package/dist/index.d.cts +0 -1053
- package/dist/shared/core.CoLQkcYL.d.ts +0 -734
- package/dist/shared/core.DIYZvpVg.cjs +0 -353
- package/dist/types/index.cjs +0 -70
- package/dist/types/index.d.cts +0 -2
- package/dist/types/index.mjs +0 -1
- package/src/builder/Builder.test-d.ts +0 -69
- package/src/builder/Builder.view.ts +0 -358
- package/src/model/LikeC4DiagramModel.ts +0 -338
- package/src/model/LikeC4ViewModel.ts +0 -320
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { indexBy, isString, map, prop } from 'remeda'
|
|
2
|
+
import { LikeC4Model } from '../../../model'
|
|
3
|
+
import {
|
|
4
|
+
type BorderStyle,
|
|
5
|
+
type Color,
|
|
6
|
+
type ComputedView,
|
|
7
|
+
type CustomElementExpr as C4CustomElementExpr,
|
|
8
|
+
type CustomRelationExpr as C4CustomRelationExpr,
|
|
9
|
+
type Element,
|
|
10
|
+
type ElementExpression as C4ElementExpression,
|
|
11
|
+
type ElementKind,
|
|
12
|
+
type ElementShape,
|
|
13
|
+
type ElementWhereExpr,
|
|
14
|
+
type Expression as C4Expression,
|
|
15
|
+
type Fqn,
|
|
16
|
+
type GlobalPredicateId,
|
|
17
|
+
type GlobalStyleID,
|
|
18
|
+
type IconUrl,
|
|
19
|
+
type IncomingExpr as C4IncomingExpr,
|
|
20
|
+
type InOutExpr as C4InOutExpr,
|
|
21
|
+
isElementRef,
|
|
22
|
+
isElementWhere,
|
|
23
|
+
isRelationExpression,
|
|
24
|
+
isRelationWhere,
|
|
25
|
+
type ModelRelation,
|
|
26
|
+
type NonEmptyArray,
|
|
27
|
+
type OutgoingExpr as C4OutgoingExpr,
|
|
28
|
+
type RelationId,
|
|
29
|
+
type RelationshipArrowType,
|
|
30
|
+
type RelationshipLineType,
|
|
31
|
+
type RelationWhereExpr,
|
|
32
|
+
type Tag,
|
|
33
|
+
type ViewId,
|
|
34
|
+
type ViewRule,
|
|
35
|
+
type ViewRuleGlobalPredicateRef,
|
|
36
|
+
type ViewRuleGlobalStyle,
|
|
37
|
+
type ViewRuleGroup,
|
|
38
|
+
type ViewRulePredicate,
|
|
39
|
+
type ViewRuleStyle,
|
|
40
|
+
type WhereOperator,
|
|
41
|
+
} from '../../../types'
|
|
42
|
+
import { type DirectRelationExpr as C4RelationExpr } from '../../../types/expression'
|
|
43
|
+
import { withReadableEdges } from '../../utils/with-readable-edges'
|
|
44
|
+
import { computeElementView } from '../compute'
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
┌──────────────────────────────────────────────────┐
|
|
48
|
+
│ cloud │
|
|
49
|
+
│ ┌───────────────────────────────────────────┐ │
|
|
50
|
+
│ │ frontend │ │
|
|
51
|
+
┏━━━━━━━━━━┓ │ │ ┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓ │ │ ┏━━━━━━━━━━━┓
|
|
52
|
+
┃ ┃ │ │ ┃ ┃ ┃ ┃ │ │ ┃ ┃
|
|
53
|
+
┃ customer ┃──┼──┼──▶┃ dashboard ┃ ┃ adminpanel ┃◀───┼───┼───┃ support ┃
|
|
54
|
+
┃ ┃ │ │ ┃ ┃ ┃ ┃ │ │ ┃ ┃
|
|
55
|
+
┗━━━━━━━━━━┛ │ │ ┗━━━━━━┳━━━━━━┛ ┗━━━━━━━━┳━━━━━━━┛ │ │ ┗━━━━━━━━━━━┛
|
|
56
|
+
│ └──────────┼───────────────────┼────────────┘ │
|
|
57
|
+
│ ├───────────────────┘ │
|
|
58
|
+
│ │ │
|
|
59
|
+
│ ┌──────────┼────────────────────────────────┐ │
|
|
60
|
+
│ │ ▼ backend │ │
|
|
61
|
+
│ │ ┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ │ │
|
|
62
|
+
│ │ ┃ ┃ ┃ ┃ │ │
|
|
63
|
+
│ │ ┃ graphlql ┃──────▶┃ storage ┃ │ │
|
|
64
|
+
│ │ ┃ ┃ ┃ ┃ │ │
|
|
65
|
+
│ │ ┗━━━━━━━━━━━━━┛ ┗━━━━━━┳━━━━━━┛ │ │
|
|
66
|
+
│ └────────────────────────────────┼──────────┘ │
|
|
67
|
+
└───────────────────────────────────┼──────────────┘
|
|
68
|
+
│
|
|
69
|
+
┌─────────┼─────────┐
|
|
70
|
+
│ amazon │ │
|
|
71
|
+
│ ▼ │
|
|
72
|
+
│ ┏━━━━━━━━━━━━━━┓ │
|
|
73
|
+
│ ┃ ┃ │
|
|
74
|
+
│ ┃ s3 ┃ │
|
|
75
|
+
│ ┃ ┃ │
|
|
76
|
+
│ ┗━━━━━━━━━━━━━━┛ │
|
|
77
|
+
└───────────────────┘
|
|
78
|
+
|
|
79
|
+
specification {
|
|
80
|
+
element actor
|
|
81
|
+
element system
|
|
82
|
+
element container
|
|
83
|
+
element component
|
|
84
|
+
|
|
85
|
+
tag old
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
model {
|
|
89
|
+
|
|
90
|
+
actor customer
|
|
91
|
+
actor support
|
|
92
|
+
|
|
93
|
+
system cloud {
|
|
94
|
+
container backend {
|
|
95
|
+
component graphql
|
|
96
|
+
component storage {
|
|
97
|
+
#old
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
graphql -> storage
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
container frontend {
|
|
104
|
+
component dashboard {
|
|
105
|
+
-> graphql
|
|
106
|
+
}
|
|
107
|
+
component adminPanel {
|
|
108
|
+
#old
|
|
109
|
+
-> graphql
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
customer -> dashboard
|
|
115
|
+
support -> adminPanel
|
|
116
|
+
|
|
117
|
+
system amazon {
|
|
118
|
+
component s3
|
|
119
|
+
|
|
120
|
+
cloud.backend.storage -> s3
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
*/
|
|
126
|
+
type TestTag = 'old' | 'next' | 'aws' | 'storage' | 'communication' | 'legacy'
|
|
127
|
+
|
|
128
|
+
const el = ({
|
|
129
|
+
id,
|
|
130
|
+
kind,
|
|
131
|
+
title,
|
|
132
|
+
style,
|
|
133
|
+
tags,
|
|
134
|
+
...props
|
|
135
|
+
}: Partial<Omit<Element, 'id' | 'kind' | 'tags'>> & {
|
|
136
|
+
id: string
|
|
137
|
+
kind: string
|
|
138
|
+
tags?: NonEmptyArray<TestTag>
|
|
139
|
+
}): Element => ({
|
|
140
|
+
id: id as Fqn,
|
|
141
|
+
kind: kind as ElementKind,
|
|
142
|
+
title: title ?? id,
|
|
143
|
+
description: null,
|
|
144
|
+
technology: null,
|
|
145
|
+
tags: tags as NonEmptyArray<Tag> ?? null,
|
|
146
|
+
links: null,
|
|
147
|
+
style: {
|
|
148
|
+
...style,
|
|
149
|
+
},
|
|
150
|
+
...props,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
export const fakeElements = {
|
|
154
|
+
'customer': el({
|
|
155
|
+
id: 'customer',
|
|
156
|
+
kind: 'actor',
|
|
157
|
+
title: 'customer',
|
|
158
|
+
shape: 'person',
|
|
159
|
+
}),
|
|
160
|
+
'support': el({
|
|
161
|
+
id: 'support',
|
|
162
|
+
kind: 'actor',
|
|
163
|
+
title: 'support',
|
|
164
|
+
shape: 'person',
|
|
165
|
+
}),
|
|
166
|
+
'cloud': el({
|
|
167
|
+
id: 'cloud',
|
|
168
|
+
kind: 'system',
|
|
169
|
+
title: 'cloud',
|
|
170
|
+
icon: 'none',
|
|
171
|
+
tags: ['next', 'old'],
|
|
172
|
+
}),
|
|
173
|
+
'cloud.backend': el({
|
|
174
|
+
id: 'cloud.backend',
|
|
175
|
+
kind: 'container',
|
|
176
|
+
title: 'backend',
|
|
177
|
+
}),
|
|
178
|
+
'cloud.frontend': el({
|
|
179
|
+
id: 'cloud.frontend',
|
|
180
|
+
kind: 'container',
|
|
181
|
+
title: 'frontend',
|
|
182
|
+
shape: 'browser',
|
|
183
|
+
}),
|
|
184
|
+
'cloud.backend.graphql': el({
|
|
185
|
+
id: 'cloud.backend.graphql',
|
|
186
|
+
kind: 'component',
|
|
187
|
+
icon: 'tech:graphql' as IconUrl,
|
|
188
|
+
title: 'graphql',
|
|
189
|
+
}),
|
|
190
|
+
'email': el({
|
|
191
|
+
id: 'email',
|
|
192
|
+
kind: 'system',
|
|
193
|
+
title: 'email',
|
|
194
|
+
}),
|
|
195
|
+
'cloud.backend.storage': el({
|
|
196
|
+
id: 'cloud.backend.storage',
|
|
197
|
+
kind: 'component',
|
|
198
|
+
title: 'storage',
|
|
199
|
+
tags: ['storage', 'old'],
|
|
200
|
+
}),
|
|
201
|
+
'cloud.frontend.dashboard': el({
|
|
202
|
+
id: 'cloud.frontend.dashboard',
|
|
203
|
+
kind: 'component',
|
|
204
|
+
title: 'dashboard',
|
|
205
|
+
icon: 'tech:react' as IconUrl,
|
|
206
|
+
tags: ['next'],
|
|
207
|
+
}),
|
|
208
|
+
'cloud.frontend.supportPanel': el({
|
|
209
|
+
id: 'cloud.frontend.supportPanel',
|
|
210
|
+
kind: 'component',
|
|
211
|
+
title: 'adminPanel',
|
|
212
|
+
tags: ['old'],
|
|
213
|
+
}),
|
|
214
|
+
'amazon': el({
|
|
215
|
+
id: 'amazon',
|
|
216
|
+
kind: 'system',
|
|
217
|
+
title: 'amazon',
|
|
218
|
+
icon: 'tech:aws' as IconUrl,
|
|
219
|
+
tags: ['aws'],
|
|
220
|
+
}),
|
|
221
|
+
'amazon.s3': el({
|
|
222
|
+
id: 'amazon.s3',
|
|
223
|
+
kind: 'component',
|
|
224
|
+
title: 's3',
|
|
225
|
+
shape: 'storage',
|
|
226
|
+
icon: 'aws:s3' as IconUrl,
|
|
227
|
+
tags: ['aws', 'storage'],
|
|
228
|
+
}),
|
|
229
|
+
} satisfies Record<string, Element>
|
|
230
|
+
|
|
231
|
+
export type FakeElementIds = keyof typeof fakeElements
|
|
232
|
+
|
|
233
|
+
const rel = <Source extends FakeElementIds, Target extends FakeElementIds>({
|
|
234
|
+
source,
|
|
235
|
+
target,
|
|
236
|
+
title,
|
|
237
|
+
...props
|
|
238
|
+
}: {
|
|
239
|
+
source: Source
|
|
240
|
+
target: Target
|
|
241
|
+
title?: string
|
|
242
|
+
kind?: string
|
|
243
|
+
color?: Color
|
|
244
|
+
line?: RelationshipLineType
|
|
245
|
+
head?: RelationshipArrowType
|
|
246
|
+
tail?: RelationshipArrowType
|
|
247
|
+
tags?: NonEmptyArray<TestTag>
|
|
248
|
+
}) =>
|
|
249
|
+
({
|
|
250
|
+
id: `${source}:${target}` as RelationId,
|
|
251
|
+
title: title ?? '',
|
|
252
|
+
source: source as Fqn,
|
|
253
|
+
target: target as Fqn,
|
|
254
|
+
...(props as any),
|
|
255
|
+
}) as Omit<ModelRelation, 'id'> & { id: `${Source}:${Target}` }
|
|
256
|
+
|
|
257
|
+
export const fakeRelations = [
|
|
258
|
+
rel({
|
|
259
|
+
source: 'customer',
|
|
260
|
+
target: 'cloud.frontend.dashboard',
|
|
261
|
+
title: 'opens in browser',
|
|
262
|
+
}),
|
|
263
|
+
rel({
|
|
264
|
+
source: 'support',
|
|
265
|
+
target: 'cloud.frontend.supportPanel',
|
|
266
|
+
title: 'manages',
|
|
267
|
+
}),
|
|
268
|
+
rel({
|
|
269
|
+
source: 'cloud.backend.storage',
|
|
270
|
+
target: 'amazon.s3',
|
|
271
|
+
title: 'uploads',
|
|
272
|
+
tags: ['aws', 'storage', 'legacy'],
|
|
273
|
+
}),
|
|
274
|
+
rel({
|
|
275
|
+
source: 'customer',
|
|
276
|
+
target: 'cloud',
|
|
277
|
+
title: 'uses',
|
|
278
|
+
}),
|
|
279
|
+
rel({
|
|
280
|
+
source: 'cloud.backend.graphql',
|
|
281
|
+
target: 'cloud.backend.storage',
|
|
282
|
+
title: 'stores',
|
|
283
|
+
tags: ['old', 'storage'],
|
|
284
|
+
}),
|
|
285
|
+
rel({
|
|
286
|
+
source: 'cloud.frontend',
|
|
287
|
+
target: 'cloud.backend',
|
|
288
|
+
title: 'requests',
|
|
289
|
+
}),
|
|
290
|
+
rel({
|
|
291
|
+
source: 'cloud.frontend.dashboard',
|
|
292
|
+
target: 'cloud.backend.graphql',
|
|
293
|
+
kind: 'graphlql',
|
|
294
|
+
title: 'requests',
|
|
295
|
+
line: 'solid',
|
|
296
|
+
tags: ['next'],
|
|
297
|
+
}),
|
|
298
|
+
rel({
|
|
299
|
+
source: 'cloud.frontend.supportPanel',
|
|
300
|
+
target: 'cloud.backend.graphql',
|
|
301
|
+
kind: 'graphlql',
|
|
302
|
+
title: 'fetches',
|
|
303
|
+
line: 'dashed',
|
|
304
|
+
tail: 'odiamond',
|
|
305
|
+
tags: ['old'],
|
|
306
|
+
}),
|
|
307
|
+
rel({
|
|
308
|
+
source: 'cloud',
|
|
309
|
+
target: 'amazon',
|
|
310
|
+
title: 'uses',
|
|
311
|
+
head: 'diamond',
|
|
312
|
+
tail: 'odiamond',
|
|
313
|
+
tags: ['aws'],
|
|
314
|
+
}),
|
|
315
|
+
rel({
|
|
316
|
+
source: 'cloud.backend',
|
|
317
|
+
target: 'email',
|
|
318
|
+
title: 'schedule',
|
|
319
|
+
tags: ['communication'],
|
|
320
|
+
}),
|
|
321
|
+
rel({
|
|
322
|
+
source: 'cloud',
|
|
323
|
+
target: 'email',
|
|
324
|
+
title: 'uses',
|
|
325
|
+
tags: ['communication'],
|
|
326
|
+
}),
|
|
327
|
+
rel({
|
|
328
|
+
source: 'email',
|
|
329
|
+
target: 'cloud',
|
|
330
|
+
title: 'notifies',
|
|
331
|
+
tags: ['communication'],
|
|
332
|
+
}),
|
|
333
|
+
]
|
|
334
|
+
|
|
335
|
+
export const globalStyles = {
|
|
336
|
+
'mute_old': [{
|
|
337
|
+
targets: [$expr({
|
|
338
|
+
elementTag: 'old' as Tag,
|
|
339
|
+
isEqual: true,
|
|
340
|
+
})],
|
|
341
|
+
style: {
|
|
342
|
+
color: 'muted',
|
|
343
|
+
},
|
|
344
|
+
}],
|
|
345
|
+
'red_next': [{
|
|
346
|
+
targets: [$expr({
|
|
347
|
+
elementTag: 'next' as Tag,
|
|
348
|
+
isEqual: true,
|
|
349
|
+
})],
|
|
350
|
+
style: {
|
|
351
|
+
color: 'red',
|
|
352
|
+
},
|
|
353
|
+
}],
|
|
354
|
+
} as const
|
|
355
|
+
|
|
356
|
+
export type FakeRelationIds = (typeof fakeRelations)[number]['id']
|
|
357
|
+
const fakeParsedModel = {
|
|
358
|
+
elements: fakeElements,
|
|
359
|
+
relations: indexBy(fakeRelations, r => r.id),
|
|
360
|
+
deployments: {
|
|
361
|
+
elements: {},
|
|
362
|
+
relations: {},
|
|
363
|
+
},
|
|
364
|
+
views: {},
|
|
365
|
+
globals: {
|
|
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>>,
|
|
394
|
+
dynamicPredicates: {},
|
|
395
|
+
styles: globalStyles,
|
|
396
|
+
},
|
|
397
|
+
} as const
|
|
398
|
+
export const fakeModel = LikeC4Model.fromDump(fakeParsedModel)
|
|
399
|
+
|
|
400
|
+
const emptyView = {
|
|
401
|
+
__: 'element' as const,
|
|
402
|
+
id: 'index' as ViewId,
|
|
403
|
+
title: null,
|
|
404
|
+
description: null,
|
|
405
|
+
tags: null,
|
|
406
|
+
links: null,
|
|
407
|
+
customColorDefinitions: {},
|
|
408
|
+
rules: [],
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export const includeWildcard = {
|
|
412
|
+
include: [
|
|
413
|
+
{
|
|
414
|
+
wildcard: true,
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
} satisfies ViewRule
|
|
418
|
+
|
|
419
|
+
export type ElementRefExpr =
|
|
420
|
+
| '*'
|
|
421
|
+
| FakeElementIds
|
|
422
|
+
| `${FakeElementIds}.*`
|
|
423
|
+
| `${FakeElementIds}.**`
|
|
424
|
+
| `${FakeElementIds}._`
|
|
425
|
+
|
|
426
|
+
type InOutExpr = `-> ${ElementRefExpr} ->`
|
|
427
|
+
type IncomingExpr = `-> ${ElementRefExpr}`
|
|
428
|
+
type OutgoingExpr = `${ElementRefExpr} ->`
|
|
429
|
+
type RelationKeyword = '->' | '<->'
|
|
430
|
+
type RelationExpr = `${ElementRefExpr} ${RelationKeyword} ${ElementRefExpr}`
|
|
431
|
+
|
|
432
|
+
export type Expression =
|
|
433
|
+
| ElementRefExpr
|
|
434
|
+
| InOutExpr
|
|
435
|
+
| IncomingExpr
|
|
436
|
+
| OutgoingExpr
|
|
437
|
+
| RelationExpr
|
|
438
|
+
|
|
439
|
+
export function $custom(
|
|
440
|
+
expr: ElementRefExpr,
|
|
441
|
+
props: {
|
|
442
|
+
title?: string
|
|
443
|
+
description?: string
|
|
444
|
+
technology?: string
|
|
445
|
+
shape?: ElementShape
|
|
446
|
+
color?: Color
|
|
447
|
+
border?: BorderStyle
|
|
448
|
+
icon?: string
|
|
449
|
+
opacity?: number
|
|
450
|
+
navigateTo?: string
|
|
451
|
+
},
|
|
452
|
+
): C4CustomElementExpr {
|
|
453
|
+
return {
|
|
454
|
+
custom: {
|
|
455
|
+
expr: $expr(expr) as any,
|
|
456
|
+
...props as any,
|
|
457
|
+
},
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function $customRelation(
|
|
462
|
+
relation: RelationExpr,
|
|
463
|
+
props: Omit<C4CustomRelationExpr['customRelation'], 'relation'>,
|
|
464
|
+
): C4CustomRelationExpr {
|
|
465
|
+
return {
|
|
466
|
+
customRelation: {
|
|
467
|
+
relation: $expr(relation) as any,
|
|
468
|
+
...props,
|
|
469
|
+
},
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function $where(
|
|
474
|
+
expr: Expression | C4Expression,
|
|
475
|
+
operator: WhereOperator<TestTag, string>,
|
|
476
|
+
): ElementWhereExpr | RelationWhereExpr {
|
|
477
|
+
return {
|
|
478
|
+
where: {
|
|
479
|
+
expr: $expr(expr) as any,
|
|
480
|
+
condition: operator,
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export function $inout(
|
|
486
|
+
expr: InOutExpr | C4ElementExpression,
|
|
487
|
+
): C4InOutExpr {
|
|
488
|
+
const innerExpression = !isString(expr)
|
|
489
|
+
? expr as C4Expression
|
|
490
|
+
: $expr(expr.replace(/->/g, '').trim() as ElementRefExpr) as any
|
|
491
|
+
|
|
492
|
+
return { inout: innerExpression }
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function $incoming(
|
|
496
|
+
expr: IncomingExpr | C4ElementExpression,
|
|
497
|
+
): C4IncomingExpr {
|
|
498
|
+
const innerExpression = !isString(expr)
|
|
499
|
+
? expr as C4Expression
|
|
500
|
+
: $expr(expr.replace('-> ', '') as ElementRefExpr) as any
|
|
501
|
+
|
|
502
|
+
return { incoming: innerExpression }
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export function $outgoing(
|
|
506
|
+
expr: OutgoingExpr | C4ElementExpression,
|
|
507
|
+
): C4OutgoingExpr {
|
|
508
|
+
const innerExpression = !isString(expr)
|
|
509
|
+
? expr as C4Expression
|
|
510
|
+
: $expr(expr.replace(' ->', '') as ElementRefExpr) as any
|
|
511
|
+
|
|
512
|
+
return { outgoing: innerExpression }
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function $relation(
|
|
516
|
+
expr: RelationExpr,
|
|
517
|
+
): C4RelationExpr {
|
|
518
|
+
const [source, target] = expr.split(/ -> | <-> /)
|
|
519
|
+
const isBidirectional = expr.includes(' <-> ')
|
|
520
|
+
|
|
521
|
+
return {
|
|
522
|
+
source: $expr(source as ElementRefExpr) as any,
|
|
523
|
+
target: $expr(target as ElementRefExpr) as any,
|
|
524
|
+
...(isBidirectional && { isBidirectional }),
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export function $expr(expr: Expression | C4Expression): C4Expression {
|
|
529
|
+
if (!isString(expr)) {
|
|
530
|
+
return expr as C4Expression
|
|
531
|
+
}
|
|
532
|
+
if (expr === '*') {
|
|
533
|
+
return { wildcard: true }
|
|
534
|
+
}
|
|
535
|
+
if (expr.startsWith('->')) {
|
|
536
|
+
return expr.endsWith('->') ? $inout(expr as InOutExpr) : $incoming(expr as IncomingExpr)
|
|
537
|
+
}
|
|
538
|
+
if (expr.endsWith(' ->')) {
|
|
539
|
+
return $outgoing(expr as OutgoingExpr)
|
|
540
|
+
}
|
|
541
|
+
if (expr.includes(' -> ') || expr.includes(' <-> ')) {
|
|
542
|
+
return $relation(expr as RelationExpr)
|
|
543
|
+
}
|
|
544
|
+
if (expr.endsWith('._')) {
|
|
545
|
+
return {
|
|
546
|
+
expanded: expr.replace('._', '') as Fqn,
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (expr.endsWith('.*')) {
|
|
550
|
+
return {
|
|
551
|
+
element: expr.replace('.*', '') as Fqn,
|
|
552
|
+
isChildren: true,
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (expr.endsWith('.**')) {
|
|
556
|
+
return {
|
|
557
|
+
element: expr.replace('.**', '') as Fqn,
|
|
558
|
+
isDescendants: true,
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
element: expr as Fqn,
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
type CustomProps = {
|
|
567
|
+
where?: WhereOperator<TestTag, string>
|
|
568
|
+
with?: {
|
|
569
|
+
title?: string
|
|
570
|
+
description?: string
|
|
571
|
+
technology?: string
|
|
572
|
+
shape?: ElementShape
|
|
573
|
+
color?: Color
|
|
574
|
+
border?: BorderStyle
|
|
575
|
+
icon?: string
|
|
576
|
+
opacity?: number
|
|
577
|
+
navigateTo?: string
|
|
578
|
+
} & Omit<C4CustomRelationExpr['customRelation'], 'relation' | 'navigateTo'>
|
|
579
|
+
}
|
|
580
|
+
export function $include(expr: Expression | C4Expression, props?: CustomProps): ViewRulePredicate {
|
|
581
|
+
let _expr = props?.where ? $where(expr, props.where) : $expr(expr)
|
|
582
|
+
_expr = props?.with ? $with(_expr, props.with) : _expr
|
|
583
|
+
return {
|
|
584
|
+
include: [_expr],
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
export function $with(expr: C4Expression, props?: CustomProps['with']): C4CustomRelationExpr | C4CustomElementExpr {
|
|
588
|
+
if (isRelationExpression(expr) || isRelationWhere(expr)) {
|
|
589
|
+
return {
|
|
590
|
+
customRelation: {
|
|
591
|
+
relation: expr,
|
|
592
|
+
...props as any,
|
|
593
|
+
},
|
|
594
|
+
}
|
|
595
|
+
} else if (isElementRef(expr) || isElementWhere(expr)) {
|
|
596
|
+
return {
|
|
597
|
+
custom: {
|
|
598
|
+
expr: expr,
|
|
599
|
+
...props as any,
|
|
600
|
+
},
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
throw 'Unsupported type of internal expression'
|
|
605
|
+
}
|
|
606
|
+
export function $exclude(expr: Expression | C4Expression, where?: WhereOperator<TestTag, string>): ViewRulePredicate {
|
|
607
|
+
let _expr = where ? $where(expr, where) : $expr(expr)
|
|
608
|
+
return {
|
|
609
|
+
exclude: [_expr],
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
export function $group(groupRules: ViewRuleGroup['groupRules']): ViewRuleGroup {
|
|
613
|
+
return {
|
|
614
|
+
title: null,
|
|
615
|
+
groupRules,
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export function $style(element: ElementRefExpr, style: ViewRuleStyle['style']): ViewRuleStyle {
|
|
620
|
+
return {
|
|
621
|
+
targets: [$expr(element) as C4ElementExpression],
|
|
622
|
+
style: Object.assign({}, style),
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
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 {
|
|
630
|
+
const [_t, id] = expr.split(' ') as [string, string]
|
|
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}`)
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export function computeView(
|
|
646
|
+
...args: [FakeElementIds, ViewRule | ViewRule[]] | [ViewRule | ViewRule[]]
|
|
647
|
+
) {
|
|
648
|
+
let result: ComputedView
|
|
649
|
+
if (args.length === 1) {
|
|
650
|
+
result = computeElementView(
|
|
651
|
+
fakeModel,
|
|
652
|
+
{
|
|
653
|
+
...emptyView,
|
|
654
|
+
rules: [args[0]].flat(),
|
|
655
|
+
},
|
|
656
|
+
)
|
|
657
|
+
} else {
|
|
658
|
+
result = computeElementView(
|
|
659
|
+
fakeModel,
|
|
660
|
+
{
|
|
661
|
+
...emptyView,
|
|
662
|
+
id: 'index' as ViewId,
|
|
663
|
+
viewOf: args[0] as Fqn,
|
|
664
|
+
rules: [args[1]].flat(),
|
|
665
|
+
},
|
|
666
|
+
)
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
result = withReadableEdges(result)
|
|
670
|
+
|
|
671
|
+
return Object.assign(result, {
|
|
672
|
+
nodeIds: map(result.nodes, prop('id')) as string[],
|
|
673
|
+
edgeIds: map(result.edges, prop('id')) as string[],
|
|
674
|
+
})
|
|
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
|
+
}
|