@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
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
import { isArray, isString, map } from 'remeda'
|
|
2
|
-
import type { LiteralUnion, Simplify, Tagged } from 'type-fest'
|
|
3
|
-
import {
|
|
4
|
-
type AutoLayoutDirection,
|
|
5
|
-
type CustomElementExpr,
|
|
6
|
-
type CustomRelationExpr,
|
|
7
|
-
type ElementExpression as C4ElementExpression,
|
|
8
|
-
type Expression as C4Expression,
|
|
9
|
-
type Fqn,
|
|
10
|
-
isElementPredicateExpr,
|
|
11
|
-
type NonEmptyArray,
|
|
12
|
-
type ViewRuleStyle,
|
|
13
|
-
type WhereOperator
|
|
14
|
-
} from '../types'
|
|
15
|
-
import type { AnyTypes, Types } from './_types'
|
|
16
|
-
import type { views, ViewsBuilder as Builder } from './Builder.views'
|
|
17
|
-
|
|
18
|
-
export interface ViewBuilder<T extends AnyTypes> {
|
|
19
|
-
include(...exprs: C4Expression[]): ViewBuilder<T>
|
|
20
|
-
exclude(...exprs: C4Expression[]): ViewBuilder<T>
|
|
21
|
-
style(rule: ViewRuleStyle): ViewBuilder<T>
|
|
22
|
-
autoLayout(layout: AutoLayoutDirection): ViewBuilder<T>
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export namespace ViewPredicate {
|
|
26
|
-
export type ElementExpr<Fqn extends string> = '*' | Fqn | `${Fqn}.*` | `${Fqn}._`
|
|
27
|
-
|
|
28
|
-
type AllExpression<ElementExpr extends string> =
|
|
29
|
-
| ElementExpr
|
|
30
|
-
| `-> ${ElementExpr} ->`
|
|
31
|
-
| `-> ${ElementExpr}`
|
|
32
|
-
| `${ElementExpr} ->`
|
|
33
|
-
| `${ElementExpr} ${'->' | '<->'} ${ElementExpr}`
|
|
34
|
-
|
|
35
|
-
export type Expression<T extends AnyTypes> = T extends Types<any, infer F extends string, any, any, any, any>
|
|
36
|
-
? AllExpression<ViewPredicate.ElementExpr<F>>
|
|
37
|
-
: never
|
|
38
|
-
|
|
39
|
-
export type WhereTag<Tag extends string> = `tag ${'is' | 'is not'} #${Tag}`
|
|
40
|
-
export type WhereKind<Kind extends string> = `kind ${'is' | 'is not'} ${Kind}`
|
|
41
|
-
|
|
42
|
-
export type WhereEq<Types extends AnyTypes> =
|
|
43
|
-
| ViewPredicate.WhereTag<Types['Tag']>
|
|
44
|
-
| ViewPredicate.WhereKind<Types['ElementKind']>
|
|
45
|
-
|
|
46
|
-
export type WhereOperator<Types extends AnyTypes> = ViewPredicate.WhereEq<Types> | {
|
|
47
|
-
and: NonEmptyArray<ViewPredicate.WhereOperator<Types>>
|
|
48
|
-
or?: never
|
|
49
|
-
not?: never
|
|
50
|
-
} | {
|
|
51
|
-
or: NonEmptyArray<ViewPredicate.WhereOperator<Types>>
|
|
52
|
-
and?: never
|
|
53
|
-
not?: never
|
|
54
|
-
} | {
|
|
55
|
-
not: ViewPredicate.WhereOperator<Types>
|
|
56
|
-
and?: never
|
|
57
|
-
or?: never
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export type Custom<Types extends AnyTypes> = {
|
|
61
|
-
where?: ViewPredicate.WhereOperator<Types>
|
|
62
|
-
with?: Simplify<
|
|
63
|
-
Omit<CustomElementExpr['custom'] & CustomRelationExpr['customRelation'], 'expr' | 'relation' | 'navigateTo'> & {
|
|
64
|
-
navigateTo?: Types['ViewId']
|
|
65
|
-
}
|
|
66
|
-
>
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export type ViewRuleBuilderOp<Types extends AnyTypes> = (b: ViewBuilder<Types>) => ViewBuilder<Types>
|
|
71
|
-
|
|
72
|
-
export interface AddViewHelper<Props = unknown> {
|
|
73
|
-
// <
|
|
74
|
-
// const Id extends string,
|
|
75
|
-
// T extends AnyTypes
|
|
76
|
-
// >(
|
|
77
|
-
// id: Id
|
|
78
|
-
// ): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
const Id extends string,
|
|
82
|
-
T extends AnyTypes
|
|
83
|
-
>(
|
|
84
|
-
id: Id,
|
|
85
|
-
builder: (b: ViewBuilder<T>) => ViewBuilder<T>
|
|
86
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
87
|
-
|
|
88
|
-
<
|
|
89
|
-
const Id extends string,
|
|
90
|
-
T extends AnyTypes
|
|
91
|
-
>(
|
|
92
|
-
id: Id,
|
|
93
|
-
propsOrTitle: Props | string
|
|
94
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
const Id extends string,
|
|
98
|
-
T extends AnyTypes
|
|
99
|
-
>(
|
|
100
|
-
id: Id,
|
|
101
|
-
propsOrTitle: Props | string | undefined,
|
|
102
|
-
builder: (b: ViewBuilder<T>) => ViewBuilder<T>
|
|
103
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface AddViewOfHelper<Props = unknown> {
|
|
107
|
-
<
|
|
108
|
-
const Id extends string,
|
|
109
|
-
T extends AnyTypes,
|
|
110
|
-
Of extends string & T['Fqn']
|
|
111
|
-
>(
|
|
112
|
-
id: Id,
|
|
113
|
-
of: Of
|
|
114
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
const Id extends string,
|
|
118
|
-
T extends AnyTypes,
|
|
119
|
-
Of extends string & T['Fqn']
|
|
120
|
-
>(
|
|
121
|
-
id: Id,
|
|
122
|
-
of: Of,
|
|
123
|
-
builder: (b: ViewBuilder<T>) => ViewBuilder<T>
|
|
124
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
125
|
-
|
|
126
|
-
<
|
|
127
|
-
const Id extends string,
|
|
128
|
-
T extends AnyTypes,
|
|
129
|
-
Of extends string & T['Fqn']
|
|
130
|
-
>(
|
|
131
|
-
id: Id,
|
|
132
|
-
of: Of,
|
|
133
|
-
propsOrTitle: Props | string
|
|
134
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
135
|
-
|
|
136
|
-
<
|
|
137
|
-
const Id extends string,
|
|
138
|
-
T extends AnyTypes,
|
|
139
|
-
Of extends string & T['Fqn']
|
|
140
|
-
>(
|
|
141
|
-
id: Id,
|
|
142
|
-
of: Of,
|
|
143
|
-
propsOrTitle: Props | string | undefined,
|
|
144
|
-
builder: (b: ViewBuilder<T>) => ViewBuilder<T>
|
|
145
|
-
): (builder: Builder<T>) => Builder<Types.AddView<T, Id>>
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// To hook types
|
|
149
|
-
type TypedC4Expression<Types extends AnyTypes> = Tagged<C4Expression, 'typed', Types>
|
|
150
|
-
|
|
151
|
-
function parseWhere(where: ViewPredicate.WhereOperator<AnyTypes>): WhereOperator<any, any> {
|
|
152
|
-
if (isString(where)) {
|
|
153
|
-
const op = where as LiteralUnion<ViewPredicate.WhereEq<AnyTypes>, string>
|
|
154
|
-
switch (true) {
|
|
155
|
-
case op.startsWith('tag is not #'):
|
|
156
|
-
return {
|
|
157
|
-
tag: {
|
|
158
|
-
neq: op.replace('tag is not #', '')
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
case op.startsWith('tag is #'):
|
|
162
|
-
return {
|
|
163
|
-
tag: {
|
|
164
|
-
eq: op.replace('tag is #', '')
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
case op.startsWith('kind is not '):
|
|
168
|
-
return {
|
|
169
|
-
kind: {
|
|
170
|
-
neq: op.replace('kind is not ', '')
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
case op.startsWith('kind is '):
|
|
174
|
-
return {
|
|
175
|
-
kind: {
|
|
176
|
-
eq: op.replace('kind is ', '')
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
default:
|
|
180
|
-
throw new Error(`Unknown where operator: ${where}`)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (where.and) {
|
|
185
|
-
return {
|
|
186
|
-
and: map(where.and, parseWhere)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
if (where.or) {
|
|
190
|
-
return {
|
|
191
|
-
or: map(where.or, parseWhere)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
if (where.not) {
|
|
195
|
-
return {
|
|
196
|
-
not: parseWhere(where.not)
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
throw new Error(`Unknown where operator: ${where}`)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function $include<Types extends AnyTypes>(
|
|
204
|
-
...args:
|
|
205
|
-
| [ViewPredicate.Expression<Types>]
|
|
206
|
-
| [TypedC4Expression<Types>]
|
|
207
|
-
| [ViewPredicate.Expression<Types>, ViewPredicate.Custom<Types>]
|
|
208
|
-
): (b: ViewBuilder<Types>) => ViewBuilder<Types> {
|
|
209
|
-
return (b) => {
|
|
210
|
-
let expr = $expr(args[0]) as C4Expression
|
|
211
|
-
const isElement = isElementPredicateExpr(expr)
|
|
212
|
-
if (args.length === 2) {
|
|
213
|
-
const condition = args[1].where ? parseWhere(args[1].where) : undefined
|
|
214
|
-
if (condition) {
|
|
215
|
-
expr = {
|
|
216
|
-
where: {
|
|
217
|
-
expr: expr as any,
|
|
218
|
-
condition
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const custom = args[1].with
|
|
224
|
-
if (custom) {
|
|
225
|
-
if (isElement) {
|
|
226
|
-
expr = {
|
|
227
|
-
custom: {
|
|
228
|
-
...custom,
|
|
229
|
-
expr: expr as any
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
} else {
|
|
233
|
-
expr = {
|
|
234
|
-
customRelation: {
|
|
235
|
-
...custom,
|
|
236
|
-
relation: expr as any
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
b.include(expr)
|
|
243
|
-
return b
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
function $exclude<Types extends AnyTypes>(
|
|
248
|
-
...args:
|
|
249
|
-
| [ViewPredicate.Expression<Types>]
|
|
250
|
-
| [TypedC4Expression<Types>]
|
|
251
|
-
| [ViewPredicate.Expression<Types>, ViewPredicate.Custom<Types>]
|
|
252
|
-
): (b: ViewBuilder<Types>) => ViewBuilder<Types> {
|
|
253
|
-
return (b) => {
|
|
254
|
-
let expr = $expr(args[0]) as C4Expression
|
|
255
|
-
if (args.length === 2 && args[1].where) {
|
|
256
|
-
const condition = parseWhere(args[1].where)
|
|
257
|
-
expr = {
|
|
258
|
-
where: {
|
|
259
|
-
expr: expr as any,
|
|
260
|
-
condition
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
b.exclude(expr)
|
|
265
|
-
return b
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function $expr<Types extends AnyTypes>(expr: ViewPredicate.Expression<Types> | C4Expression): TypedC4Expression<Types> {
|
|
270
|
-
if (!isString(expr)) {
|
|
271
|
-
return expr as TypedC4Expression<Types>
|
|
272
|
-
}
|
|
273
|
-
if (expr === '*') {
|
|
274
|
-
return { wildcard: true } as TypedC4Expression<Types>
|
|
275
|
-
}
|
|
276
|
-
if (expr.startsWith('->')) {
|
|
277
|
-
if (expr.endsWith('->')) {
|
|
278
|
-
return {
|
|
279
|
-
inout: $expr(expr.replace(/->/g, '').trim()) as any
|
|
280
|
-
} as TypedC4Expression<Types>
|
|
281
|
-
}
|
|
282
|
-
return {
|
|
283
|
-
incoming: $expr(expr.replace('-> ', '')) as any
|
|
284
|
-
} as TypedC4Expression<Types>
|
|
285
|
-
}
|
|
286
|
-
if (expr.endsWith(' ->')) {
|
|
287
|
-
return {
|
|
288
|
-
outgoing: $expr(expr.replace(' ->', '')) as any
|
|
289
|
-
} as TypedC4Expression<Types>
|
|
290
|
-
}
|
|
291
|
-
if (expr.includes(' <-> ')) {
|
|
292
|
-
const [source, target] = expr.split(' <-> ')
|
|
293
|
-
return {
|
|
294
|
-
source: $expr(source) as any,
|
|
295
|
-
target: $expr(target) as any,
|
|
296
|
-
isBidirectional: true
|
|
297
|
-
} as TypedC4Expression<Types>
|
|
298
|
-
}
|
|
299
|
-
if (expr.includes(' -> ')) {
|
|
300
|
-
const [source, target] = expr.split(' -> ')
|
|
301
|
-
return {
|
|
302
|
-
source: $expr(source) as any,
|
|
303
|
-
target: $expr(target) as any
|
|
304
|
-
} as TypedC4Expression<Types>
|
|
305
|
-
}
|
|
306
|
-
if (expr.endsWith('._')) {
|
|
307
|
-
return {
|
|
308
|
-
expanded: expr.replace('._', '') as Fqn
|
|
309
|
-
} as TypedC4Expression<Types>
|
|
310
|
-
}
|
|
311
|
-
if (expr.endsWith('.*')) {
|
|
312
|
-
return {
|
|
313
|
-
element: expr.replace('.*', '') as Fqn,
|
|
314
|
-
isDescedants: true
|
|
315
|
-
} as TypedC4Expression<Types>
|
|
316
|
-
}
|
|
317
|
-
return {
|
|
318
|
-
element: expr as any as Fqn,
|
|
319
|
-
isDescedants: false
|
|
320
|
-
} as TypedC4Expression<Types>
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function $style<Types extends AnyTypes>(
|
|
324
|
-
element: ViewPredicate.ElementExpr<Types['Fqn']> | NonEmptyArray<ViewPredicate.ElementExpr<Types['Fqn']>>,
|
|
325
|
-
{ notation, ...style }: ViewRuleStyle['style'] & { notation?: string }
|
|
326
|
-
): (b: ViewBuilder<Types>) => ViewBuilder<Types> {
|
|
327
|
-
return (b) =>
|
|
328
|
-
b.style({
|
|
329
|
-
targets: (isArray(element) ? element : [element]).map(e => $expr(e) as C4ElementExpression),
|
|
330
|
-
...notation ? { notation } : {},
|
|
331
|
-
style: {
|
|
332
|
-
...style
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function $autoLayout<Types extends AnyTypes>(
|
|
338
|
-
layout: AutoLayoutDirection
|
|
339
|
-
): (b: ViewBuilder<Types>) => ViewBuilder<Types> {
|
|
340
|
-
return (b) => b.autoLayout(layout)
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function $rules<T extends AnyTypes>(...rules: ViewRuleBuilderOp<T>[]): (b: ViewBuilder<T>) => ViewBuilder<T> {
|
|
344
|
-
return (b) => rules.reduce((b, rule) => rule(b), b)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export { $autoLayout, $exclude, $expr, $include, $rules, $style }
|
|
348
|
-
|
|
349
|
-
export type ViewHelpers<T = unknown> = {
|
|
350
|
-
views: typeof views
|
|
351
|
-
view: AddViewHelper<T>
|
|
352
|
-
viewOf: AddViewOfHelper<T>
|
|
353
|
-
$include: typeof $include
|
|
354
|
-
$exclude: typeof $exclude
|
|
355
|
-
$style: typeof $style
|
|
356
|
-
$rules: typeof $rules
|
|
357
|
-
$autoLayout: typeof $autoLayout
|
|
358
|
-
}
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { isNullish } from 'remeda'
|
|
2
|
-
import { nonNullable } from '../errors'
|
|
3
|
-
import {
|
|
4
|
-
type ElementKind as C4ElementKind,
|
|
5
|
-
type ElementShape as C4ElementShape,
|
|
6
|
-
type Tag as C4Tag
|
|
7
|
-
} from '../types/element'
|
|
8
|
-
import { DefaultRelationshipColor } from '../types/relation'
|
|
9
|
-
import type { Color as C4Color } from '../types/theme'
|
|
10
|
-
import type { ComputedElementView, DiagramEdge, DiagramNode, DiagramView } from '../types/view'
|
|
11
|
-
import type { LikeC4Model } from './LikeC4Model'
|
|
12
|
-
import { type EdgeId, type ElementOrFqn, type Fqn, getId, type IncomingFilter, type OutgoingFilter } from './types'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* All methods are view-scoped, i.e. only return elements and connections in the view.
|
|
16
|
-
*/
|
|
17
|
-
export class LikeC4DiagramModel {
|
|
18
|
-
private readonly _rootElements = new Set<LikeC4DiagramModel.Element>()
|
|
19
|
-
|
|
20
|
-
private readonly _elements = new Map<Fqn, LikeC4DiagramModel.Element>()
|
|
21
|
-
|
|
22
|
-
private readonly _connections: Map<EdgeId, LikeC4DiagramModel.Connection>
|
|
23
|
-
|
|
24
|
-
constructor(
|
|
25
|
-
public readonly view: DiagramView,
|
|
26
|
-
public readonly model: LikeC4Model.Layouted
|
|
27
|
-
) {
|
|
28
|
-
for (const node of view.nodes) {
|
|
29
|
-
const el = new LikeC4DiagramModel.Element(node, this)
|
|
30
|
-
this._elements.set(node.id, el)
|
|
31
|
-
if (isNullish(node.parent)) {
|
|
32
|
-
this._rootElements.add(el)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
this._connections = new Map(view.edges.map(e => [e.id, new LikeC4DiagramModel.Connection(e, this)]))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get isDynamic() {
|
|
39
|
-
return this.view.__ === 'dynamic'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get id() {
|
|
43
|
-
return this.view.id
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
get title() {
|
|
47
|
-
return this.view.title
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get viewOf() {
|
|
51
|
-
if (isNullish(this.view.__) || this.view.__ === 'element') {
|
|
52
|
-
const computedView = this.view as ComputedElementView
|
|
53
|
-
return computedView.viewOf ? this.model.element(computedView.viewOf) : null
|
|
54
|
-
}
|
|
55
|
-
return null
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
get tags(): C4Tag[] {
|
|
59
|
-
return this.view.tags ?? []
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public roots(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
63
|
-
return [...this._rootElements]
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public elements(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
67
|
-
return [...this._elements.values()]
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public element(id: Fqn): LikeC4DiagramModel.Element {
|
|
71
|
-
return nonNullable(this._elements.get(id), `LikeC4DiagramModel.Element ${id} in view ${this.view.id} not found`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
public hasElement(id: Fqn): boolean {
|
|
75
|
-
return this._elements.has(id)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
public connections(): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
79
|
-
return [...this._connections.values()]
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
public connection(id: EdgeId): LikeC4DiagramModel.Connection {
|
|
83
|
-
return nonNullable(this._connections.get(id), `Connection ${id} in view ${this.view.id} not found`)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public findConnections(
|
|
87
|
-
source: ElementOrFqn,
|
|
88
|
-
target: ElementOrFqn,
|
|
89
|
-
direction: 'both' | 'direct' = 'direct'
|
|
90
|
-
): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
91
|
-
const sourceId = getId(source)
|
|
92
|
-
const targetId = getId(target)
|
|
93
|
-
return this.connections().filter(c =>
|
|
94
|
-
(c.source.id === sourceId && c.target.id === targetId)
|
|
95
|
-
|| (direction === 'both' && c.source.id === targetId && c.target.id === sourceId)
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public parent(element: ElementOrFqn): LikeC4DiagramModel.Element | null {
|
|
100
|
-
const el = this.element(getId(element))
|
|
101
|
-
return el.node.parent ? this.element(el.node.parent) : null
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
public children(element: ElementOrFqn): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
105
|
-
const el = this.element(getId(element))
|
|
106
|
-
return el.node.children.map(c => this.element(c))
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Get all sibling (i.e. same parent)
|
|
110
|
-
public siblings(element: ElementOrFqn): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
111
|
-
const id = getId(element)
|
|
112
|
-
const parent = this.parent(id)
|
|
113
|
-
const siblings = parent ? this.children(parent) : this.roots()
|
|
114
|
-
return siblings.filter(e => e.id !== id)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
119
|
-
* (from closest to root)
|
|
120
|
-
*/
|
|
121
|
-
public ancestors(element: ElementOrFqn): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
122
|
-
let id = getId(element)
|
|
123
|
-
const result = [] as LikeC4DiagramModel.Element[]
|
|
124
|
-
let parent
|
|
125
|
-
while (parent = this.parent(id)) {
|
|
126
|
-
result.push(parent)
|
|
127
|
-
id = parent.id
|
|
128
|
-
}
|
|
129
|
-
return result
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public descendants(element: ElementOrFqn): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
133
|
-
const children = this.children(element)
|
|
134
|
-
return children.flatMap(c => [c, ...this.descendants(c.id)])
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public incoming(
|
|
138
|
-
element: ElementOrFqn,
|
|
139
|
-
filter: IncomingFilter = 'all'
|
|
140
|
-
): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
141
|
-
const el = this.element(getId(element))
|
|
142
|
-
const edges = el.node.inEdges.map(e => this.connection(e))
|
|
143
|
-
|
|
144
|
-
if (filter === 'all' || edges.length === 0) {
|
|
145
|
-
return edges
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return edges.filter(rel => {
|
|
149
|
-
if (filter === 'direct') {
|
|
150
|
-
return rel.target.id === el.id
|
|
151
|
-
}
|
|
152
|
-
return rel.target.id !== el.id
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
public incomers(
|
|
157
|
-
element: ElementOrFqn,
|
|
158
|
-
filter: IncomingFilter = 'all'
|
|
159
|
-
): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
160
|
-
return this.incoming(element, filter).map(r => r.source)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Outgoing relationships from the element and its descendants
|
|
165
|
-
*/
|
|
166
|
-
public outgoing(
|
|
167
|
-
element: ElementOrFqn,
|
|
168
|
-
filter: OutgoingFilter = 'all'
|
|
169
|
-
): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
170
|
-
const el = this.element(getId(element))
|
|
171
|
-
const edges = el.node.outEdges.map(e => this.connection(e))
|
|
172
|
-
|
|
173
|
-
if (filter === 'all' || edges.length === 0) {
|
|
174
|
-
return edges
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return edges.filter(rel => {
|
|
178
|
-
if (filter === 'direct') {
|
|
179
|
-
return rel.source.id === el.id
|
|
180
|
-
}
|
|
181
|
-
return rel.source.id !== el.id
|
|
182
|
-
})
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
public outgoers(
|
|
186
|
-
element: ElementOrFqn,
|
|
187
|
-
filter: OutgoingFilter = 'all'
|
|
188
|
-
): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
189
|
-
return this.outgoing(element, filter).map(r => r.target)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export namespace LikeC4DiagramModel {
|
|
194
|
-
/**
|
|
195
|
-
* Represents an element in the view. (Diagram node)
|
|
196
|
-
* All methods are view-scoped, i.e. `children` returns only children of the element in the view.
|
|
197
|
-
*/
|
|
198
|
-
export class Element {
|
|
199
|
-
constructor(
|
|
200
|
-
public readonly node: DiagramNode,
|
|
201
|
-
private readonly view: LikeC4DiagramModel
|
|
202
|
-
) {
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
get id() {
|
|
206
|
-
return this.node.id
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
get title() {
|
|
210
|
-
return this.node.title
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
get kind(): C4ElementKind {
|
|
214
|
-
return this.node.kind
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
get isRoot(): boolean {
|
|
218
|
-
return isNullish(this.node.parent)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
get hasNested(): boolean {
|
|
222
|
-
return this.node.children.length > 0
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
get shape(): C4ElementShape {
|
|
226
|
-
return this.node.shape
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
get color(): C4Color {
|
|
230
|
-
return this.node.color
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
get tags(): C4Tag[] {
|
|
234
|
-
return this.node.tags ?? []
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
get level(): number {
|
|
238
|
-
return this.node.level
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
get depth(): number {
|
|
242
|
-
return this.node.depth ?? 0
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
public model(): LikeC4Model.ElementModel<LikeC4DiagramModel> {
|
|
246
|
-
return this.view.model.element(this.id)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
public parent(): LikeC4DiagramModel.Element | null {
|
|
250
|
-
return this.node.parent ? this.view.element(this.node.parent) : null
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
public metadata(key: string): string | undefined
|
|
254
|
-
public metadata(key: string, defaultValue: string): string
|
|
255
|
-
public metadata(key: string, defaultValue?: string): string | undefined {
|
|
256
|
-
return this.model().metadata(key) ?? defaultValue
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
public hasMetadata(key: string): boolean {
|
|
260
|
-
return this.model().hasMetadata(key)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
public ancestors(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
264
|
-
return this.view.ancestors(this)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
public siblings(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
268
|
-
return this.view.siblings(this)
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
public descendants(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
272
|
-
return this.view.descendants(this)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
public children(): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
276
|
-
return this.view.children(this)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
public incoming(filter: IncomingFilter = 'all'): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
280
|
-
return this.view.incoming(this, filter)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
public incomers(filter: IncomingFilter = 'all'): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
284
|
-
return this.view.incomers(this, filter)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
public outgoing(filter: OutgoingFilter = 'all'): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
288
|
-
return this.view.outgoing(this, filter)
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
public outgoers(filter: OutgoingFilter = 'all'): ReadonlyArray<LikeC4DiagramModel.Element> {
|
|
292
|
-
return this.view.outgoers(this, filter)
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
public connectionsTo(target: Fqn | LikeC4DiagramModel.Element): ReadonlyArray<LikeC4DiagramModel.Connection> {
|
|
296
|
-
return this.view.findConnections(this, target)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Represents a connection between two elements.
|
|
302
|
-
* May be source from multiple model relationships.
|
|
303
|
-
*/
|
|
304
|
-
export class Connection {
|
|
305
|
-
constructor(
|
|
306
|
-
public readonly edge: DiagramEdge,
|
|
307
|
-
private readonly view: LikeC4DiagramModel
|
|
308
|
-
) {
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
get id() {
|
|
312
|
-
return this.edge.id
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
get source(): LikeC4DiagramModel.Element {
|
|
316
|
-
return this.view.element(this.edge.source)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
get target(): LikeC4DiagramModel.Element {
|
|
320
|
-
return this.view.element(this.edge.target)
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
get tags(): C4Tag[] {
|
|
324
|
-
return this.edge.tags ?? []
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
get color(): C4Color {
|
|
328
|
-
return this.edge.color ?? DefaultRelationshipColor
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Model relationships
|
|
333
|
-
*/
|
|
334
|
-
relationships(): ReadonlyArray<LikeC4Model.Relationship<LikeC4DiagramModel>> {
|
|
335
|
-
return this.edge.relations.map(r => nonNullable(this.view.model.relationship(r)))
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|