@likec4/core 1.40.0 → 1.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/builder/package.json +4 -0
  2. package/compute-view/package.json +4 -0
  3. package/compute-view/relationships/package.json +4 -0
  4. package/dist/builder/index.d.mts +83 -20
  5. package/dist/builder/index.mjs +210 -126
  6. package/dist/compute-view/index.d.mts +8 -7
  7. package/dist/compute-view/index.mjs +14 -11
  8. package/dist/compute-view/relationships-view/index.d.mts +9 -8
  9. package/dist/compute-view/relationships-view/index.mjs +6 -6
  10. package/dist/index.d.mts +7 -7
  11. package/dist/index.mjs +12 -12
  12. package/dist/model/connection/deployment/index.d.mts +11 -10
  13. package/dist/model/connection/deployment/index.mjs +2 -2
  14. package/dist/model/connection/index.d.mts +12 -11
  15. package/dist/model/connection/index.mjs +3 -3
  16. package/dist/model/connection/model/index.d.mts +11 -10
  17. package/dist/model/connection/model/index.mjs +2 -2
  18. package/dist/model/index.d.mts +14 -14
  19. package/dist/model/index.mjs +4 -5
  20. package/dist/shared/{core.DHQ32OHa.mjs → core.01VTr9qu.mjs} +10 -29
  21. package/dist/shared/core.1vX5a9AY.mjs +86 -0
  22. package/dist/shared/{core.BVNaR17u.mjs → core.B7KhhkRY.mjs} +1 -1
  23. package/dist/shared/core.B85MJLTf.mjs +5 -0
  24. package/dist/shared/{core.BIAlzwKc.mjs → core.BIqHjQiH.mjs} +85 -45
  25. package/dist/shared/core.BKlholso.mjs +3 -0
  26. package/dist/shared/core.BR4zXDH-.mjs +13 -0
  27. package/dist/shared/{core.yHe79zEl.mjs → core.BYNkXQ8A.mjs} +21 -12
  28. package/dist/shared/core.BazD6cot.mjs +14 -0
  29. package/dist/shared/{core.BuoXfSMj.mjs → core.BbE4y-yl.mjs} +1 -1
  30. package/dist/shared/core.BoYfZOBm.mjs +3 -0
  31. package/dist/shared/core.BsSXS-_R.mjs +7 -0
  32. package/dist/shared/{core.T-eLZTW_.mjs → core.BzTakU3I.mjs} +15 -7
  33. package/dist/shared/{core.4u1dVmfX.mjs → core.C2TiyjI6.mjs} +2 -2
  34. package/dist/shared/{core.DLpidoWc.mjs → core.C3JowhaZ.mjs} +3 -3
  35. package/dist/shared/{core.CNGyqkJh.mjs → core.C4x8aaWa.mjs} +3 -1
  36. package/dist/shared/{core.BB6zA-UU.mjs → core.C8YY6Uub.mjs} +38 -9
  37. package/dist/shared/{core.FPITT8Vx.mjs → core.C8sl5Y8Z.mjs} +144 -61
  38. package/dist/shared/{core.DuR3R-xJ.mjs → core.CNgZvKb8.mjs} +3 -5176
  39. package/dist/shared/{core.BbThmf6M.d.mts → core.CQngdcuj.d.mts} +85 -4
  40. package/dist/shared/{core.Be1n9a0i.mjs → core.C_Ni6yHl.mjs} +5 -4
  41. package/dist/shared/core.CbT8JVYL.mjs +5 -0
  42. package/dist/shared/core.CqAJJpK_.mjs +3 -0
  43. package/dist/shared/{core.CySf-2gP.d.mts → core.D0PjZzIS.d.mts} +52 -15
  44. package/dist/shared/{core.DrvfVXkh.d.mts → core.D5fzJWbF.d.mts} +11 -2
  45. package/dist/shared/{core.DrVOJuxX.d.mts → core.DACpKp35.d.mts} +5 -5
  46. package/dist/shared/core.DFi2dOTl.mjs +39548 -0
  47. package/dist/shared/{core.D704WZES.d.mts → core.DIol3syK.d.mts} +2 -2
  48. package/dist/shared/{core.DlG1xWt2.mjs → core.DMMOWQqc.mjs} +3 -2
  49. package/dist/shared/core.DNbUPnve.mjs +3990 -0
  50. package/dist/shared/{core.CCD1ID81.mjs → core.DRJma0Ol.mjs} +4 -3
  51. package/dist/shared/{core.DgttqsJc.mjs → core.DRhg-gVU.mjs} +9 -9
  52. package/dist/shared/core.DSO_rTC2.mjs +5322 -0
  53. package/dist/shared/{core.vWJTxpLV.d.mts → core.D_vkffV4.d.mts} +4 -2
  54. package/dist/shared/core.DdMJk7nx.d.mts +476 -0
  55. package/dist/shared/{core.D_fI5Lf6.d.mts → core.Dgs6-nuz.d.mts} +24 -4
  56. package/dist/shared/{core.Be4Jy9Qx.mjs → core.FZ305VYd.mjs} +2 -2
  57. package/dist/shared/core.OHD4KXm9.mjs +5 -0
  58. package/dist/shared/{core.GTgsmXS_.mjs → core.QJD_fcrc.mjs} +2 -2
  59. package/dist/shared/core.RfnaEmgA.mjs +7 -0
  60. package/dist/shared/core.fHR_8Tnq.d.mts +450 -0
  61. package/dist/shared/{core.D0EgVMQK.mjs → core.lRvxPoao.mjs} +14 -12
  62. package/dist/shared/{core.CaT0SUUK.mjs → core.rCeaAqgW.mjs} +1 -84
  63. package/dist/shared/{core.kxeJe0OY.d.mts → core.s9uwOt60.d.mts} +4 -4
  64. package/dist/shared/core.yna0OdV5.d.mts +98 -0
  65. package/dist/styles/index.d.mts +106 -0
  66. package/dist/styles/index.mjs +1 -0
  67. package/dist/types/_aux.d.mts +2 -2
  68. package/dist/types/_aux.mjs +1 -5
  69. package/dist/types/expression-model.d.mts +3 -4
  70. package/dist/types/expression.d.mts +3 -4
  71. package/dist/types/fqnRef.d.mts +2 -2
  72. package/dist/types/fqnRef.mjs +3 -3
  73. package/dist/types/index.d.mts +8 -8
  74. package/dist/types/index.mjs +151 -6
  75. package/dist/types/scalar.mjs +3 -2
  76. package/dist/utils/graphology/index.d.mts +1864 -0
  77. package/dist/utils/graphology/index.mjs +1 -0
  78. package/dist/utils/index.d.mts +11 -6
  79. package/dist/utils/index.mjs +21 -37
  80. package/dist/utils/iterable/index.d.mts +1 -1
  81. package/dist/utils/iterable/index.mjs +45 -7
  82. package/model/package.json +4 -0
  83. package/package.json +42 -24
  84. package/styles/package.json +4 -0
  85. package/types/package.json +4 -0
  86. package/utils/graphology/package.json +4 -0
  87. package/utils/package.json +4 -0
  88. package/dist/shared/core.6_Vp2iiN.mjs +0 -172
  89. package/dist/shared/core.Bpou6c2f.d.mts +0 -850
  90. package/dist/shared/core.CUw_2J9j.mjs +0 -47
  91. package/dist/shared/core.CzdwsPmY.d.mts +0 -69
  92. package/dist/shared/core.DoM6aM9N.mjs +0 -7
  93. package/dist/shared/core.ILwny7BV.mjs +0 -38
  94. package/dist/theme/index.d.mts +0 -11
  95. package/dist/theme/index.mjs +0 -232
  96. package/src/builder/Builder.deployment.ts +0 -224
  97. package/src/builder/Builder.deploymentModel.ts +0 -449
  98. package/src/builder/Builder.element.ts +0 -241
  99. package/src/builder/Builder.model.ts +0 -494
  100. package/src/builder/Builder.ts +0 -870
  101. package/src/builder/Builder.view-common.ts +0 -273
  102. package/src/builder/Builder.view-deployment.ts +0 -135
  103. package/src/builder/Builder.view-element.ts +0 -202
  104. package/src/builder/Builder.views.ts +0 -399
  105. package/src/builder/Builder.with.ts +0 -156
  106. package/src/builder/_types.ts +0 -320
  107. package/src/builder/index.ts +0 -11
  108. package/src/compute-view/compute-view.ts +0 -80
  109. package/src/compute-view/deployment-view/_types.ts +0 -38
  110. package/src/compute-view/deployment-view/clean-connections.ts +0 -236
  111. package/src/compute-view/deployment-view/compute.ts +0 -94
  112. package/src/compute-view/deployment-view/memory/index.ts +0 -9
  113. package/src/compute-view/deployment-view/memory/memory.ts +0 -96
  114. package/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts +0 -18
  115. package/src/compute-view/deployment-view/predicates/deploymentRefs.ts +0 -154
  116. package/src/compute-view/deployment-view/predicates/index.ts +0 -8
  117. package/src/compute-view/deployment-view/predicates/relation-direct.ts +0 -243
  118. package/src/compute-view/deployment-view/predicates/relation-in-out.ts +0 -70
  119. package/src/compute-view/deployment-view/predicates/relation-incoming.ts +0 -101
  120. package/src/compute-view/deployment-view/predicates/relation-outgoing.ts +0 -95
  121. package/src/compute-view/deployment-view/predicates/relation-where.ts +0 -18
  122. package/src/compute-view/deployment-view/predicates/utils.ts +0 -282
  123. package/src/compute-view/deployment-view/predicates/wildcard.ts +0 -41
  124. package/src/compute-view/deployment-view/stages/stage-exclude.ts +0 -5
  125. package/src/compute-view/deployment-view/stages/stage-final.ts +0 -245
  126. package/src/compute-view/deployment-view/stages/stage-include.ts +0 -95
  127. package/src/compute-view/deployment-view/utils.ts +0 -286
  128. package/src/compute-view/dynamic-view/compute.ts +0 -312
  129. package/src/compute-view/element-view/_types.ts +0 -47
  130. package/src/compute-view/element-view/clean-connections.ts +0 -117
  131. package/src/compute-view/element-view/compute.ts +0 -324
  132. package/src/compute-view/element-view/memory/NodeGroup.ts +0 -31
  133. package/src/compute-view/element-view/memory/index.ts +0 -10
  134. package/src/compute-view/element-view/memory/memory.ts +0 -178
  135. package/src/compute-view/element-view/memory/stage-exclude.ts +0 -59
  136. package/src/compute-view/element-view/memory/stage-final.ts +0 -129
  137. package/src/compute-view/element-view/memory/stage-include.ts +0 -130
  138. package/src/compute-view/element-view/predicates/_utils.ts +0 -91
  139. package/src/compute-view/element-view/predicates/element-expand.ts +0 -29
  140. package/src/compute-view/element-view/predicates/element-kind-tag.ts +0 -27
  141. package/src/compute-view/element-view/predicates/element-ref.ts +0 -24
  142. package/src/compute-view/element-view/predicates/relation-direct.ts +0 -321
  143. package/src/compute-view/element-view/predicates/relation-in-out.ts +0 -64
  144. package/src/compute-view/element-view/predicates/relation-in.ts +0 -115
  145. package/src/compute-view/element-view/predicates/relation-out.ts +0 -119
  146. package/src/compute-view/element-view/predicates/wildcard.ts +0 -88
  147. package/src/compute-view/element-view/utils.ts +0 -65
  148. package/src/compute-view/index.ts +0 -4
  149. package/src/compute-view/memory/AbstractMemory.ts +0 -45
  150. package/src/compute-view/memory/AbstractStageExclude.ts +0 -215
  151. package/src/compute-view/memory/AbstractStageInclude.ts +0 -200
  152. package/src/compute-view/memory/_types.ts +0 -148
  153. package/src/compute-view/memory/index.ts +0 -5
  154. package/src/compute-view/memory/ops.ts +0 -43
  155. package/src/compute-view/relationships-view/_types.ts +0 -16
  156. package/src/compute-view/relationships-view/compute.ts +0 -159
  157. package/src/compute-view/relationships-view/index.ts +0 -3
  158. package/src/compute-view/relationships-view/layout.ts +0 -357
  159. package/src/compute-view/relationships-view/utils.ts +0 -73
  160. package/src/compute-view/utils/ancestorsOfNode.ts +0 -19
  161. package/src/compute-view/utils/applyCustomElementProperties.ts +0 -107
  162. package/src/compute-view/utils/applyCustomRelationProperties.ts +0 -58
  163. package/src/compute-view/utils/applyViewRuleStyles.ts +0 -73
  164. package/src/compute-view/utils/buildComputedNodes.ts +0 -153
  165. package/src/compute-view/utils/buildElementNotations.ts +0 -63
  166. package/src/compute-view/utils/elementExpressionToPredicate.ts +0 -50
  167. package/src/compute-view/utils/link-nodes-with-edges.ts +0 -56
  168. package/src/compute-view/utils/merge-props-from-relationships.ts +0 -161
  169. package/src/compute-view/utils/relationExpressionToPredicates.ts +0 -55
  170. package/src/compute-view/utils/resolve-extended-views.ts +0 -85
  171. package/src/compute-view/utils/resolve-global-rules.ts +0 -88
  172. package/src/compute-view/utils/topological-sort.ts +0 -256
  173. package/src/compute-view/utils/view-hash.ts +0 -45
  174. package/src/compute-view/utils/with-readable-edges.ts +0 -40
  175. package/src/index.ts +0 -32
  176. package/src/model/DeploymentElementModel.ts +0 -682
  177. package/src/model/DeploymentModel.ts +0 -393
  178. package/src/model/ElementModel.ts +0 -293
  179. package/src/model/LikeC4Model.ts +0 -882
  180. package/src/model/RelationModel.ts +0 -152
  181. package/src/model/connection/Connection.ts +0 -72
  182. package/src/model/connection/deployment/DeploymentConnectionModel.ts +0 -185
  183. package/src/model/connection/deployment/find.ts +0 -120
  184. package/src/model/connection/deployment/index.ts +0 -8
  185. package/src/model/connection/index.ts +0 -22
  186. package/src/model/connection/model/ConnectionModel.ts +0 -158
  187. package/src/model/connection/model/find.ts +0 -117
  188. package/src/model/connection/model/index.ts +0 -8
  189. package/src/model/connection/ops.ts +0 -276
  190. package/src/model/guards.ts +0 -77
  191. package/src/model/index.ts +0 -72
  192. package/src/model/types.ts +0 -67
  193. package/src/model/utils.ts +0 -66
  194. package/src/model/view/EdgeModel.ts +0 -120
  195. package/src/model/view/LikeC4ViewModel.ts +0 -361
  196. package/src/model/view/LikeC4ViewsFolder.ts +0 -151
  197. package/src/model/view/NodeModel.ts +0 -247
  198. package/src/theme/element.ts +0 -61
  199. package/src/theme/index.ts +0 -127
  200. package/src/theme/relationships.ts +0 -54
  201. package/src/types/RichText.ts +0 -206
  202. package/src/types/_aux.ts +0 -291
  203. package/src/types/_common.ts +0 -80
  204. package/src/types/const.ts +0 -34
  205. package/src/types/expression-model.ts +0 -294
  206. package/src/types/expression.ts +0 -313
  207. package/src/types/fqnRef.ts +0 -91
  208. package/src/types/geometry.ts +0 -159
  209. package/src/types/global.ts +0 -21
  210. package/src/types/index.ts +0 -42
  211. package/src/types/model-data.ts +0 -77
  212. package/src/types/model-deployment.ts +0 -88
  213. package/src/types/model-dump.ts +0 -79
  214. package/src/types/model-logical.ts +0 -135
  215. package/src/types/model-spec.ts +0 -85
  216. package/src/types/operators.ts +0 -156
  217. package/src/types/project.ts +0 -14
  218. package/src/types/scalar.ts +0 -162
  219. package/src/types/styles.ts +0 -122
  220. package/src/types/view-changes.ts +0 -32
  221. package/src/types/view-common.ts +0 -157
  222. package/src/types/view-computed.ts +0 -118
  223. package/src/types/view-layouted.ts +0 -98
  224. package/src/types/view-parsed.deployment.ts +0 -39
  225. package/src/types/view-parsed.dynamic.ts +0 -89
  226. package/src/types/view-parsed.element.ts +0 -65
  227. package/src/types/view.ts +0 -113
  228. package/src/utils/common-head.ts +0 -22
  229. package/src/utils/compare-natural.ts +0 -60
  230. package/src/utils/const.ts +0 -1
  231. package/src/utils/fqn.ts +0 -302
  232. package/src/utils/getOrCreate.ts +0 -8
  233. package/src/utils/guards.ts +0 -9
  234. package/src/utils/index.ts +0 -68
  235. package/src/utils/invariant.ts +0 -29
  236. package/src/utils/iterable/_types.ts +0 -5
  237. package/src/utils/iterable/filter.ts +0 -55
  238. package/src/utils/iterable/find.ts +0 -38
  239. package/src/utils/iterable/first.ts +0 -48
  240. package/src/utils/iterable/flat.ts +0 -17
  241. package/src/utils/iterable/head.ts +0 -22
  242. package/src/utils/iterable/index.ts +0 -15
  243. package/src/utils/iterable/map.ts +0 -40
  244. package/src/utils/iterable/reduce.ts +0 -24
  245. package/src/utils/iterable/some.ts +0 -36
  246. package/src/utils/iterable/to.ts +0 -19
  247. package/src/utils/iterable/unique.ts +0 -23
  248. package/src/utils/markdown/index.ts +0 -2
  249. package/src/utils/markdown/to-html.ts +0 -32
  250. package/src/utils/markdown/to-text.ts +0 -14
  251. package/src/utils/memoize-prop.ts +0 -30
  252. package/src/utils/mnemonist.ts +0 -9
  253. package/src/utils/object-hash.ts +0 -14
  254. package/src/utils/promises.ts +0 -24
  255. package/src/utils/relations.ts +0 -36
  256. package/src/utils/set.ts +0 -83
  257. package/src/utils/string-hash.ts +0 -16
@@ -1,870 +0,0 @@
1
- import defu from 'defu'
2
- import {
3
- entries,
4
- fromEntries,
5
- hasAtLeast,
6
- isFunction,
7
- isNonNullish,
8
- isNullish,
9
- map,
10
- mapToObj,
11
- mapValues,
12
- pickBy,
13
- } from 'remeda'
14
- import type { Writable } from 'type-fest'
15
- import { computeLikeC4Model } from '../compute-view/compute-view'
16
- import { LikeC4Model } from '../model/LikeC4Model'
17
- import type {
18
- Any,
19
- aux,
20
- DeployedInstance,
21
- DeploymentFqn,
22
- LikeC4Project,
23
- ParsedElementView,
24
- ParsedLikeC4ModelData,
25
- Specification,
26
- } from '../types'
27
- import {
28
- type Color,
29
- type DeploymentElement,
30
- type DeploymentRelation,
31
- type Element,
32
- type ElementShape,
33
- type Fqn,
34
- type IconUrl,
35
- type LikeC4View,
36
- type Link,
37
- type ModelGlobals,
38
- type ModelRelation,
39
- type NonEmptyArray,
40
- type ParsedDeploymentView as DeploymentView,
41
- type RelationId,
42
- _stage,
43
- _type,
44
- DefaultElementShape,
45
- DefaultThemeColor,
46
- FqnRef,
47
- isDeployedInstance,
48
- isElementView,
49
- } from '../types'
50
- import { invariant } from '../utils'
51
- import { isSameHierarchy, nameFromFqn, parentFqn } from '../utils/fqn'
52
- import type { AnyTypes, BuilderProjectSpecification, BuilderSpecification, Types } from './_types'
53
- import type { AddDeploymentNode } from './Builder.deployment'
54
- import type {
55
- AddDeploymentNodeHelpers,
56
- DeloymentModelBuildFunction,
57
- DeloymentModelHelpers,
58
- DeploymentModelBuilder,
59
- } from './Builder.deploymentModel'
60
- import type { AddElement } from './Builder.element'
61
- import type { AddElementHelpers, ModelBuilder, ModelBuilderFunction, ModelHelpers } from './Builder.model'
62
- import { $autoLayout, $exclude, $include, $rules, $style } from './Builder.view-common'
63
- import type { DeploymentRulesBuilderOp } from './Builder.view-deployment'
64
- import type { ElementViewRulesBuilder } from './Builder.view-element'
65
- import { type ViewsBuilder, type ViewsBuilderFunction, type ViewsHelpers, mkViewBuilder } from './Builder.views'
66
- import type { BuilderMethods } from './Builder.with'
67
-
68
- export interface Builder<T extends AnyTypes> extends BuilderMethods<T> {
69
- /**
70
- * Only available in compile time
71
- */
72
- readonly Types: T
73
-
74
- clone(): Builder<T>
75
-
76
- /**
77
- * Builders for each element kind
78
- */
79
- helpers(): {
80
- model: ModelHelpers<T>
81
- views: ViewsHelpers
82
- deployment: DeloymentModelHelpers<T>
83
- }
84
-
85
- /**
86
- * Adds model elements
87
- *
88
- * @example
89
- * builder.model(({ el }, _) =>
90
- * _(
91
- * el('a'),
92
- * el('a.b').with(
93
- * el('c')
94
- * )
95
- * )
96
- * )
97
- *
98
- * builder.model((_, m) =>
99
- * m(
100
- * _.el('a'),
101
- * _.el('a.b').with(
102
- * _.el('c')
103
- * )
104
- * )
105
- * )
106
- */
107
- model<Out extends AnyTypes>(
108
- callback: ModelBuilderFunction<T, Out>,
109
- ): Builder<Out>
110
-
111
- /**
112
- * Adds deployment model
113
- *
114
- * @example
115
- * builder.deployment(({ node, instanceOf }, _) =>
116
- * _(
117
- * node('node1'),
118
- * node('node1.child1').with(
119
- * instanceOf('model.element')
120
- * )
121
- * )
122
- * )
123
- *
124
- * @example
125
- * builder.deployment((_,d) =>
126
- * d(
127
- * _.node('node1'),
128
- * _.node('node1.child1').with(
129
- * _.instanceOf('model.element')
130
- * )
131
- * )
132
- * )
133
- */
134
- deployment<Out extends AnyTypes>(
135
- callback: DeloymentModelBuildFunction<T, Out>,
136
- ): Builder<Out>
137
-
138
- /**
139
- * Adds views
140
- *
141
- * @example
142
- * builder.views(({ view, viewOf, deploymentView, $include, $style, $rules }, _) =>
143
- * _(
144
- * view('view1').with(
145
- * $include('a -> b'),
146
- * ),
147
- * view('view2', {
148
- * title: 'View 2',
149
- * }).with(
150
- * $include('*')
151
- * ),
152
- * view(
153
- * 'view3',
154
- * {
155
- * title: 'View 3',
156
- * },
157
- * $rules(
158
- * $include('*'),
159
- * $style(['*', 'alice'], {
160
- * color: 'red',
161
- * }),
162
- * ),
163
- * ),
164
- * viewOf('viewOfA', 'a').with(
165
- * $include('*')
166
- * ),
167
- * deploymentView('deploymentView1').with(
168
- * $include('a -> b')
169
- * ),
170
- * )
171
- * )
172
- */
173
- views<Out extends AnyTypes>(
174
- callback: ViewsBuilderFunction<T, Out>,
175
- ): Builder<Out>
176
-
177
- /**
178
- * Returns model as result of parsing only
179
- * Views are not computed or layouted
180
- * {@link toLikeC4Model} should be used to get model with computed views
181
- */
182
- build<const Project extends BuilderProjectSpecification>(
183
- project: Project,
184
- ): ParsedLikeC4ModelData<aux.setProject<Types.ToAux<T>, Project['id']>>
185
-
186
- build(): ParsedLikeC4ModelData<Types.ToAux<T>>
187
-
188
- /**
189
- * Returns Computed LikeC4Model
190
- */
191
- toLikeC4Model<const Project extends BuilderProjectSpecification>(
192
- project: Project,
193
- ): LikeC4Model.Computed<aux.setProject<Types.ToAux<T>, Project['id']>>
194
-
195
- toLikeC4Model(): LikeC4Model.Computed<Types.ToAux<T>>
196
- }
197
-
198
- interface Internals<T extends AnyTypes> extends ViewsBuilder<T>, ModelBuilder<T>, DeploymentModelBuilder<T> {
199
- }
200
-
201
- type Op<T> = (b: T) => T
202
-
203
- function validateSpec(specification: BuilderSpecification) {
204
- for (const [kind, spec] of entries(specification.elements)) {
205
- if (spec.tags) {
206
- for (const tag of spec.tags) {
207
- invariant(specification.tags?.[tag], `Invalid specification for element kind "${kind}": tag "${tag}" not found`)
208
- }
209
- }
210
- }
211
- if (specification.deployments) {
212
- for (const [kind, spec] of entries(specification.deployments)) {
213
- if (spec.tags) {
214
- for (const tag of spec.tags) {
215
- invariant(
216
- specification.tags?.[tag],
217
- `Invalid specification for deployment kind "${kind}": tag "${tag}" not found`,
218
- )
219
- }
220
- }
221
- }
222
- }
223
- }
224
-
225
- function builder<Spec extends BuilderSpecification, T extends AnyTypes>(
226
- spec: Spec,
227
- _elements = new Map<string, Element<Any>>(),
228
- _relations = [] as ModelRelation[],
229
- _views = new Map<string, LikeC4View>(),
230
- _globals = {
231
- predicates: {},
232
- dynamicPredicates: {},
233
- styles: {},
234
- } as ModelGlobals,
235
- _deployments = new Map<string, DeploymentElement>(),
236
- _deploymentRelations = [] as DeploymentRelation[],
237
- ): Builder<T> {
238
- const toLikeC4Specification = (): Specification<Types.ToAux<T>> => {
239
- validateSpec(spec)
240
- return ({
241
- elements: {
242
- ...structuredClone(spec.elements) as any,
243
- },
244
- deployments: {
245
- ...structuredClone(spec.deployments) as any,
246
- },
247
- relationships: {
248
- ...structuredClone(spec.relationships) as any,
249
- },
250
- tags: mapValues(spec.tags ?? {}, (tagSpec) => ({
251
- color: DefaultThemeColor,
252
- ...tagSpec,
253
- })) as any,
254
- ...(!!spec.metadataKeys ? { metadataKeys: spec.metadataKeys as any } : {}),
255
- customColors: {},
256
- } as Specification<Types.ToAux<T>>)
257
- }
258
-
259
- const mapLinks = (links?: Array<string | { title?: string; url: string }>): NonEmptyArray<Link> | null => {
260
- if (!links || !hasAtLeast(links, 1)) {
261
- return null
262
- }
263
- return map(links, l => (typeof l === 'string' ? { url: l } : l))
264
- }
265
-
266
- const createGenericView = <B extends Op<any> | undefined>(
267
- id: string,
268
- _props: T['NewViewProps'] | string | B | null,
269
- builder: B,
270
- ): [Omit<LikeC4View, 'rules' | '_type'>, B] => {
271
- if (isFunction(_props)) {
272
- builder = _props as B
273
- _props = {}
274
- }
275
- _props ??= {}
276
- const {
277
- links: _links = [],
278
- title = null,
279
- description = null,
280
- tags = [],
281
- ...props
282
- } = typeof _props === 'string' ? { title: _props } : { ..._props }
283
-
284
- const links = mapLinks(_links)
285
- return [{
286
- id: id as any,
287
- title,
288
- description: description ? { txt: description } : null,
289
- tags,
290
- links,
291
- _stage: 'parsed',
292
- ...props,
293
- }, builder]
294
- }
295
-
296
- const self: Builder<T> & Internals<T> = {
297
- get Types(): T {
298
- throw new Error('Types are not available in runtime')
299
- },
300
- clone: () => {
301
- return builder(
302
- structuredClone(spec),
303
- structuredClone(_elements),
304
- structuredClone(_relations),
305
- structuredClone(_views),
306
- structuredClone(_globals),
307
- structuredClone(_deployments),
308
- structuredClone(_deploymentRelations),
309
- )
310
- },
311
-
312
- __addElement: (element) => {
313
- const parent = parentFqn(element.id)
314
- if (parent) {
315
- invariant(
316
- _elements.get(parent),
317
- `Parent element with id "${parent}" not found for element with id "${element.id}"`,
318
- )
319
- }
320
- if (_elements.has(element.id)) {
321
- throw new Error(`Element with id "${element.id}" already exists`)
322
- }
323
- _elements.set(element.id, element)
324
- return self
325
- },
326
- __addRelation(relation) {
327
- const sourceEl = _elements.get(FqnRef.flatten(relation.source))
328
- invariant(sourceEl, `Element with id "${relation.source}" not found`)
329
- const targetEl = _elements.get(FqnRef.flatten(relation.target))
330
- invariant(targetEl, `Element with id "${relation.target}" not found`)
331
- invariant(
332
- !isSameHierarchy(sourceEl, targetEl),
333
- 'Cannot create relationship between elements in the same hierarchy',
334
- )
335
- _relations.push({
336
- id: `rel${_relations.length + 1}` as RelationId,
337
- ...relation,
338
- })
339
- return self
340
- },
341
- __fqn(id) {
342
- invariant(id.trim() !== '', 'Id must be non-empty')
343
- return id as Fqn
344
- },
345
- __deploymentFqn(id) {
346
- invariant(id.trim() !== '', 'Id must be non-empty')
347
- return id as DeploymentFqn
348
- },
349
- __addSourcelessRelation() {
350
- throw new Error('Can be called only in nested model')
351
- },
352
- __addView: (view) => {
353
- if (_views.has(view.id)) {
354
- throw new Error(`View with id "${view.id}" already exists`)
355
- }
356
- if (isElementView(view) && 'viewOf' in view) {
357
- invariant(
358
- _elements.get(view.viewOf),
359
- `Invalid scoped view ${view.id}, wlement with id "${view.viewOf}" not found`,
360
- )
361
- }
362
- _views.set(view.id, view)
363
- return self
364
- },
365
-
366
- __addDeployment: (node: DeploymentElement) => {
367
- if (_deployments.has(node.id)) {
368
- throw new Error(`Deployment with id "${node.id}" already exists`)
369
- }
370
- const parent = parentFqn(node.id)
371
- if (parent) {
372
- invariant(
373
- _deployments.get(parent),
374
- `Parent element with id "${parent}" not found for node with id "${node.id}"`,
375
- )
376
- }
377
- if (isDeployedInstance(node)) {
378
- invariant(parent, `Instance ${node.id} of ${node.element} must be deployed under a parent node`)
379
- invariant(
380
- _elements.get(node.element),
381
- `Instance "${node.id}" references non-existing element "${node.element}"`,
382
- )
383
- }
384
- _deployments.set(node.id, node)
385
- return self
386
- },
387
- __addDeploymentRelation: (relation) => {
388
- invariant(
389
- !isSameHierarchy(relation.source.deployment, relation.target.deployment),
390
- 'Cannot create relationship between elements in the same hierarchy',
391
- )
392
-
393
- invariant(
394
- _deployments.has(relation.source.deployment),
395
- `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing source`,
396
- )
397
- invariant(
398
- _deployments.has(relation.target.deployment),
399
- `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing target`,
400
- )
401
-
402
- _deploymentRelations.push({
403
- id: `deploy_rel${_deploymentRelations.length + 1}` as RelationId,
404
- ...relation,
405
- })
406
- return self
407
- },
408
- build: (project?: LikeC4Project) => ({
409
- [_stage]: 'parsed',
410
- projectId: project?.id ?? 'from-builder',
411
- project: {
412
- id: 'from-builder',
413
- ...project,
414
- },
415
- specification: toLikeC4Specification(),
416
- elements: fromEntries(
417
- structuredClone(
418
- Array.from(_elements.entries()),
419
- ),
420
- ),
421
- relations: mapToObj(_relations, r => [r.id, structuredClone(r)]),
422
- globals: structuredClone(_globals),
423
- deployments: {
424
- elements: fromEntries(
425
- structuredClone(
426
- Array.from(_deployments.entries()),
427
- ),
428
- ),
429
- relations: mapToObj(_deploymentRelations, r => [r.id, structuredClone(r)]),
430
- },
431
- views: fromEntries(
432
- structuredClone(
433
- Array.from(_views.entries()),
434
- ),
435
- ),
436
- imports: {},
437
- } as any),
438
- toLikeC4Model: (project?: LikeC4Project) => {
439
- const parsed = self.build(project as any)
440
- return computeLikeC4Model(parsed) as any
441
- },
442
- helpers: () => ({
443
- model: {
444
- model: (...ops: ((b: ModelBuilder<T>) => ModelBuilder<T>)[]) => {
445
- return (b: Builder<T>) => {
446
- return ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
447
- }
448
- },
449
- rel: (source, target, _props?) => {
450
- return <T extends AnyTypes>(b: ModelBuilder<T>) => {
451
- const {
452
- title = '',
453
- links: _links = [],
454
- description = null,
455
- ...props
456
- } = defu(
457
- typeof _props === 'string' ? { title: _props } : { ..._props },
458
- { title: null, links: null },
459
- )
460
- const links = mapLinks(_links)
461
- b.__addRelation({
462
- source: {
463
- model: source,
464
- },
465
- target: {
466
- model: target,
467
- },
468
- title,
469
- ...(description && { description: { txt: description } }),
470
- ...(links && { links }),
471
- ...props,
472
- })
473
- return b
474
- }
475
- },
476
- relTo: (target, _props?) => {
477
- return <T extends AnyTypes>(b: ModelBuilder<T>) => {
478
- const {
479
- title = '',
480
- links: _links = [],
481
- description = null,
482
- ...props
483
- } = defu(
484
- typeof _props === 'string' ? { title: _props } : { ..._props },
485
- { title: null, links: null },
486
- )
487
- const links = mapLinks(_links)
488
- b.__addSourcelessRelation({
489
- target: {
490
- model: target,
491
- },
492
- title,
493
- ...(description && { description: { txt: description } }),
494
- ...(links && { links }),
495
- ...props,
496
- })
497
- return b
498
- }
499
- },
500
- ...mapValues(
501
- spec.elements,
502
- ({ style: specStyle, ...spec }, kind) =>
503
- <Id extends string>(
504
- id: Id,
505
- _props?: T['NewElementProps'] | string,
506
- ): AddElement<Id> => {
507
- const add = (<T extends AnyTypes>(b: ModelBuilder<T>) => {
508
- const {
509
- links: _links,
510
- icon: _icon,
511
- style,
512
- title,
513
- description = null,
514
- ...props
515
- } = typeof _props === 'string' ? { title: _props } : { ..._props }
516
-
517
- const links = mapLinks(_links)
518
-
519
- const icon = _icon ?? specStyle?.icon
520
-
521
- const _id = b.__fqn(id)
522
-
523
- b.__addElement({
524
- id: _id,
525
- kind: kind as any,
526
- title: title ?? nameFromFqn(_id),
527
- ...(description && { description: { txt: description } }),
528
- technology: null,
529
- tags: [],
530
- color: specStyle?.color ?? DefaultThemeColor as Color,
531
- shape: specStyle?.shape ?? DefaultElementShape as ElementShape,
532
- style: pickBy({
533
- border: specStyle?.border,
534
- opacity: specStyle?.opacity,
535
- size: specStyle?.size,
536
- padding: specStyle?.padding,
537
- textSize: specStyle?.textSize,
538
- ...style,
539
- }, isNonNullish),
540
- links,
541
- ...icon && { icon: icon as IconUrl },
542
- ...spec,
543
- ...props,
544
- })
545
- return b
546
- }) as AddElement<Id>
547
-
548
- add.with = (...ops: Array<(input: ModelBuilder<any>) => ModelBuilder<any>>) => (b: ModelBuilder<any>) => {
549
- add(b)
550
- const { __fqn, __addSourcelessRelation } = b
551
- try {
552
- b.__fqn = (child) => `${__fqn(id)}.${child}` as Fqn
553
- b.__addSourcelessRelation = (relation) => {
554
- return b.__addRelation({
555
- ...relation,
556
- source: {
557
- model: __fqn(id),
558
- },
559
- })
560
- }
561
- ops.reduce((b, op) => op(b), b as any as ModelBuilder<T>) as any
562
- } finally {
563
- b.__fqn = __fqn
564
- b.__addSourcelessRelation = __addSourcelessRelation
565
- }
566
- return b
567
- }
568
-
569
- return add
570
- },
571
- ) as AddElementHelpers<T>,
572
- },
573
- views: {
574
- views: (...ops: ((b: ViewsBuilder<T>) => ViewsBuilder<T>)[]) => {
575
- return (b: Builder<T>) => {
576
- return ops.reduce((b, op) => op(b), b as any as ViewsBuilder<T>) as any
577
- }
578
- },
579
- view: (
580
- id: string,
581
- _props?: T['NewViewProps'] | string | ElementViewRulesBuilder<any>,
582
- _builder?: ElementViewRulesBuilder<any>,
583
- ) => {
584
- const [generic, builder] = createGenericView(id, _props, _builder)
585
- const view: Writable<ParsedElementView> = {
586
- ...generic,
587
- [_type]: 'element',
588
- rules: [],
589
- }
590
-
591
- const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
592
- b.__addView(view)
593
- if (builder) {
594
- builder(mkViewBuilder(view))
595
- }
596
- return b
597
- }
598
- add.with = (...ops: ElementViewRulesBuilder<any>[]) => (b: ViewsBuilder<any>) => {
599
- add(b)
600
- const elementViewBuilder = mkViewBuilder(view)
601
- for (const op of ops) {
602
- op(elementViewBuilder)
603
- }
604
- return b
605
- }
606
-
607
- return add
608
- },
609
- viewOf: (
610
- id,
611
- viewOf: string,
612
- _props?: T['NewViewProps'] | string | ElementViewRulesBuilder<any>,
613
- _builder?: ElementViewRulesBuilder<any>,
614
- ) => {
615
- const [generic, builder] = createGenericView(id, _props, _builder)
616
- const view: Writable<ParsedElementView> = {
617
- ...generic,
618
- viewOf: viewOf as Fqn,
619
- [_type]: 'element',
620
- rules: [],
621
- }
622
-
623
- const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
624
- b.__addView(view)
625
- if (builder) {
626
- builder(mkViewBuilder(view))
627
- }
628
- return b
629
- }
630
-
631
- add.with = (...ops: ElementViewRulesBuilder<any>[]) => (b: ViewsBuilder<any>) => {
632
- add(b)
633
- const elementViewBuilder = mkViewBuilder(view)
634
- for (const op of ops) {
635
- op(elementViewBuilder)
636
- }
637
- return b
638
- }
639
-
640
- return add
641
- },
642
-
643
- deploymentView: (
644
- id: string,
645
- _props?: T['NewViewProps'] | string | DeploymentRulesBuilderOp<any>,
646
- _builder?: DeploymentRulesBuilderOp<any>,
647
- ) => {
648
- const [generic, builder] = createGenericView(id, _props, _builder)
649
- const view: Writable<DeploymentView> = {
650
- ...generic,
651
- [_type]: 'deployment',
652
- rules: [],
653
- }
654
-
655
- const add = (b: ViewsBuilder<any>): ViewsBuilder<any> => {
656
- b.__addView(view)
657
- if (builder) {
658
- builder(mkViewBuilder(view))
659
- }
660
- return b
661
- }
662
-
663
- add.with = (...ops: DeploymentRulesBuilderOp<any>[]) => (b: ViewsBuilder<any>) => {
664
- add(b)
665
- const elementViewBuilder = mkViewBuilder(view)
666
- for (const op of ops) {
667
- op(elementViewBuilder)
668
- }
669
- return b
670
- }
671
-
672
- return add
673
- },
674
- $autoLayout,
675
- $exclude,
676
- $include,
677
- $rules,
678
- $style,
679
- },
680
- deployment: {
681
- deployment: (...ops: ((b: DeploymentModelBuilder<T>) => DeploymentModelBuilder<T>)[]) => {
682
- return (b: Builder<T>) => {
683
- return ops.reduce((b, op) => op(b), b as any as DeploymentModelBuilder<T>) as any
684
- }
685
- },
686
- instanceOf: (
687
- id: string,
688
- target?: string | T['NewDeploymentNodeProps'],
689
- _props?: string | T['NewDeploymentNodeProps'],
690
- ) => {
691
- return <T extends AnyTypes>(
692
- b: DeploymentModelBuilder<T>,
693
- ): DeploymentModelBuilder<Types.AddDeploymentFqn<T, any>> => {
694
- if (isNullish(target)) {
695
- target = id
696
- id = nameFromFqn(id)
697
- } else if (typeof target === 'string') {
698
- _props ??= {}
699
- } else {
700
- _props = target
701
- target = id
702
- id = nameFromFqn(id)
703
- }
704
- const {
705
- links,
706
- title,
707
- description = null,
708
- ...props
709
- } = typeof _props === 'string' ? { title: _props } : { ..._props }
710
- const _id = b.__deploymentFqn(id)
711
- invariant(_elements.has(target), `Target element with id "${target}" not found`)
712
- b.__addDeployment({
713
- id: _id,
714
- element: target as Fqn,
715
- ...title && { title },
716
- ...(description && { description: { txt: description } }),
717
- ...links && { links: mapLinks(links) },
718
- ...props,
719
- } as DeployedInstance)
720
- return b as any
721
- }
722
- },
723
- rel: (source: string, target: string, _props?: T['NewRelationshipProps'] | string) => {
724
- return <T extends AnyTypes>(b: DeploymentModelBuilder<T>) => {
725
- const {
726
- title = null,
727
- links,
728
- description = null,
729
- ...props
730
- } = typeof _props === 'string' ? { title: _props } : { ..._props }
731
-
732
- b.__addDeploymentRelation({
733
- source: {
734
- deployment: source as any,
735
- },
736
- target: {
737
- deployment: target as any,
738
- },
739
- title,
740
- ...description && { description: { txt: description } },
741
- ...links && { links: mapLinks(links) },
742
- ...props,
743
- })
744
- return b
745
- }
746
- },
747
- ...mapValues(
748
- spec.deployments ?? {},
749
- ({ style: specStyle, ...spec }, kind) =>
750
- <Id extends string>(
751
- id: Id,
752
- _props?: T['NewDeploymentNodeProps'] | string,
753
- ): AddDeploymentNode<Id> => {
754
- const add = (<T extends AnyTypes>(b: DeploymentModelBuilder<T>) => {
755
- const {
756
- links,
757
- icon: _icon,
758
- style,
759
- title,
760
- description = null,
761
- ...props
762
- } = typeof _props === 'string' ? { title: _props } : { ..._props }
763
-
764
- const icon = _icon ?? specStyle?.icon
765
-
766
- const _id = b.__deploymentFqn(id)
767
-
768
- b.__addDeployment({
769
- id: _id,
770
- kind: kind as any,
771
- title: title ?? nameFromFqn(_id),
772
- ...(description && { description: { txt: description } }),
773
- technology: null,
774
- tags: null,
775
- style: {
776
- ...icon && { icon: icon as IconUrl },
777
- color: specStyle?.color ?? DefaultThemeColor as Color,
778
- shape: specStyle?.shape ?? DefaultElementShape as ElementShape,
779
- ...pickBy({
780
- border: specStyle?.border,
781
- opacity: specStyle?.opacity,
782
- size: specStyle?.size,
783
- padding: specStyle?.padding,
784
- textSize: specStyle?.textSize,
785
- ...style,
786
- }, isNonNullish),
787
- },
788
- ...links && { links: mapLinks(links) },
789
- ...spec,
790
- ...props,
791
- })
792
- return b
793
- }) as AddDeploymentNode<Id>
794
-
795
- add.with =
796
- (...ops: Array<(input: DeploymentModelBuilder<any>) => DeploymentModelBuilder<any>>) =>
797
- (b: DeploymentModelBuilder<any>) => {
798
- add(b)
799
- const { __deploymentFqn } = b
800
- try {
801
- b.__deploymentFqn = (child) => `${__deploymentFqn(id)}.${child}` as DeploymentFqn
802
- ops.reduce((b, op) => op(b), b as any as DeploymentModelBuilder<T>) as any
803
- } finally {
804
- b.__deploymentFqn = __deploymentFqn
805
- }
806
- return b
807
- }
808
- return add
809
- },
810
- ) as AddDeploymentNodeHelpers<T>,
811
- },
812
- } as {
813
- model: ModelHelpers<T>
814
- views: ViewsHelpers
815
- deployment: DeloymentModelHelpers<T>
816
- }),
817
- with: (...ops: ((b: Builder<T>) => Builder<T>)[]) => {
818
- return ops.reduce((b, op) => op(b), self as Builder<T>).clone()
819
- },
820
- model: <Out extends AnyTypes>(cb: ModelBuilderFunction<T, Out>) => {
821
- const b = self.clone()
822
- const helpers = b.helpers().model
823
- const _ = helpers.model as any
824
- return cb({ ...helpers, _ }, _)(b as Internals<T>) as any
825
- },
826
- deployment: <Out extends AnyTypes>(cb: DeloymentModelBuildFunction<T, Out>) => {
827
- const b = self.clone()
828
- const helpers = b.helpers().deployment
829
- const _ = helpers.deployment as any
830
- return cb({ ...helpers, _ }, _)(b as Internals<T>) as any
831
- },
832
- views: <Out extends AnyTypes>(cb: ViewsBuilderFunction<T, Out>) => {
833
- const b = self.clone()
834
- const helpers = b.helpers().views
835
- return cb({
836
- ...helpers,
837
- _: helpers.views as any,
838
- } as any, helpers.views as any)(b as Internals<T>) as any
839
- },
840
- }
841
-
842
- return self
843
- }
844
-
845
- export namespace Builder {
846
- export type Any = Builder<AnyTypes>
847
-
848
- export function forSpecification<const Spec extends BuilderSpecification>(
849
- spec: Spec,
850
- ): {
851
- builder: Builder<Types.FromSpecification<Spec>>
852
- model: ModelHelpers<Types.FromSpecification<Spec>>
853
- deployment: DeloymentModelHelpers<Types.FromSpecification<Spec>>
854
- views: ViewsHelpers
855
- } {
856
- validateSpec(spec)
857
- const b = builder<Spec, Types.FromSpecification<Spec>>(spec)
858
- return {
859
- ...b.helpers(),
860
- builder: b,
861
- }
862
- }
863
-
864
- export function specification<const Spec extends BuilderSpecification>(
865
- spec: Spec,
866
- ): Builder<Types.FromSpecification<Spec>> {
867
- validateSpec(spec)
868
- return builder<Spec, Types.FromSpecification<Spec>>(spec)
869
- }
870
- }