@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,161 +0,0 @@
1
- import { isDeepEqual, isTruthy, only, pickBy, pipe, reduce, unique } from 'remeda'
2
- import type {
3
- AnyAux,
4
- aux,
5
- Color,
6
- DeploymentRelationship,
7
- Link,
8
- NonEmptyArray,
9
- Relationship,
10
- RelationshipArrowType,
11
- RelationshipLineType,
12
- scalar,
13
- } from '../../types'
14
- import { isNonEmptyArray } from '../../utils'
15
-
16
- function pickRelationshipProps<A extends AnyAux>(relation: Relationship<A> | DeploymentRelationship<A>): {
17
- title?: string
18
- description?: scalar.MarkdownOrString | null
19
- technology: string | null
20
- kind: aux.RelationKind<A> | null
21
- color: Color | null
22
- line: RelationshipLineType | null
23
- head: RelationshipArrowType | null
24
- tail: RelationshipArrowType | null
25
- navigateTo: aux.StrictViewId<A> | null
26
- } {
27
- const {
28
- title,
29
- description = null,
30
- technology = null,
31
- kind = null,
32
- color = null,
33
- line = null,
34
- head = null,
35
- tail = null,
36
- navigateTo = null,
37
- } = relation
38
- return {
39
- // Pick description only if title is present
40
- ...(title && {
41
- title,
42
- description,
43
- }),
44
- technology,
45
- kind: kind as aux.RelationKind<A> | null,
46
- color,
47
- line,
48
- head,
49
- tail,
50
- navigateTo: navigateTo as aux.StrictViewId<A> | null,
51
- }
52
- }
53
-
54
- export type MergedRelationshipProps<A extends AnyAux> = {
55
- title?: string | null
56
- description?: scalar.MarkdownOrString | null
57
- technology?: string
58
- kind?: aux.RelationKind<A>
59
- color?: Color
60
- line?: RelationshipLineType
61
- head?: RelationshipArrowType
62
- tail?: RelationshipArrowType
63
- navigateTo?: aux.StrictViewId<A>
64
- tags?: NonEmptyArray<aux.Tag<A>>
65
- links?: NonEmptyArray<Link>
66
- }
67
-
68
- /**
69
- * Merges properties from multiple relationships into a single object.
70
- * @param relations - The relationships to merge.
71
- * @param prefer - The relationship to prefer when merging.
72
- */
73
- export function mergePropsFromRelationships<A extends AnyAux>(
74
- relations: Array<Relationship<A> | DeploymentRelationship<A>>,
75
- prefer?: Relationship<A> | DeploymentRelationship<A>,
76
- ): MergedRelationshipProps<A> {
77
- const allprops = pipe(
78
- relations,
79
- reduce(
80
- (acc, r) => {
81
- if (isTruthy(r.title) && !acc.title.includes(r.title)) {
82
- acc.title.push(r.title)
83
- }
84
- if (isTruthy(r.description) && !acc.description.some(isDeepEqual(r.description))) {
85
- acc.description.push(r.description)
86
- }
87
- if (isTruthy(r.technology) && !acc.technology.includes(r.technology)) {
88
- acc.technology.push(r.technology)
89
- }
90
- if (isTruthy(r.kind) && !acc.kind.includes(r.kind)) {
91
- acc.kind.push(r.kind)
92
- }
93
- if (isTruthy(r.color) && !acc.color.includes(r.color)) {
94
- acc.color.push(r.color)
95
- }
96
- if (isTruthy(r.line) && !acc.line.includes(r.line)) {
97
- acc.line.push(r.line)
98
- }
99
- if (isTruthy(r.head) && !acc.head.includes(r.head)) {
100
- acc.head.push(r.head)
101
- }
102
- if (isTruthy(r.tail) && !acc.tail.includes(r.tail)) {
103
- acc.tail.push(r.tail)
104
- }
105
- if (isTruthy(r.navigateTo) && !acc.navigateTo.includes(r.navigateTo)) {
106
- acc.navigateTo.push(r.navigateTo)
107
- }
108
- if (r.tags) {
109
- acc.tags.push(...r.tags)
110
- }
111
- if (r.links) {
112
- acc.links.push(...r.links)
113
- }
114
- return acc
115
- },
116
- {
117
- title: [] as string[],
118
- description: [] as scalar.MarkdownOrString[],
119
- technology: [] as string[],
120
- kind: [] as aux.RelationKind<A>[],
121
- head: [] as RelationshipArrowType[],
122
- tail: [] as RelationshipArrowType[],
123
- color: [] as Color[],
124
- tags: [] as aux.Tag<A>[],
125
- links: [] as Link[],
126
- line: [] as RelationshipLineType[],
127
- navigateTo: [] as aux.ViewId<A>[],
128
- },
129
- ),
130
- )
131
-
132
- let technology = only(allprops.technology)
133
- let title = only(allprops.title) ?? (allprops.title.length > 1 ? '[...]' : null)
134
-
135
- const tags = unique(allprops.tags)
136
- let merged = pickBy(
137
- {
138
- // If there is no title, but there is technology, use technology as title
139
- title: title ?? (technology ? `[${technology}]` : null),
140
- description: only(allprops.description),
141
- technology,
142
- kind: only(allprops.kind),
143
- head: only(allprops.head),
144
- tail: only(allprops.tail),
145
- color: only(allprops.color),
146
- line: only(allprops.line),
147
- navigateTo: only(allprops.navigateTo),
148
- ...isNonEmptyArray(allprops.links) && { links: allprops.links },
149
- ...isNonEmptyArray(tags) && { tags },
150
- },
151
- isTruthy,
152
- )
153
-
154
- if (prefer) {
155
- return {
156
- ...merged,
157
- ...pickBy(pickRelationshipProps(prefer), isTruthy),
158
- }
159
- }
160
- return merged
161
- }
@@ -1,55 +0,0 @@
1
- import type { AnyAux, aux, ComputedNode } from '../../types'
2
- import { ModelRelationExpr, whereOperatorAsPredicate } from '../../types'
3
- import { nonexhaustive } from '../../utils'
4
- import { elementExprToPredicate } from './elementExpressionToPredicate'
5
-
6
- type Predicate<T> = (x: T) => boolean
7
- export type FilterableEdge<A extends AnyAux> = {
8
- tags?: aux.Tags<A> | null | undefined
9
- kind?: string
10
- source: ComputedNode<A>
11
- target: ComputedNode<A>
12
- }
13
-
14
- export function relationExpressionToPredicates<A extends AnyAux, T extends FilterableEdge<A>>(
15
- expr: ModelRelationExpr.Any<A>,
16
- ): Predicate<T> {
17
- switch (true) {
18
- case ModelRelationExpr.isCustom(expr): {
19
- return relationExpressionToPredicates(expr.customRelation.expr)
20
- }
21
- case ModelRelationExpr.isWhere(expr): {
22
- const predicate = relationExpressionToPredicates(expr.where.expr)
23
- const where = whereOperatorAsPredicate(expr.where.condition)
24
- return e =>
25
- predicate(e) && where({
26
- source: { tags: e.source.tags, kind: e.source.kind as aux.AllKinds<A> },
27
- target: { tags: e.target.tags, kind: e.target.kind as aux.AllKinds<A> },
28
- ...(e.tags && { tags: e.tags }),
29
- ...(e.kind && { kind: e.kind as aux.AllKinds<A> }),
30
- })
31
- }
32
- case ModelRelationExpr.isDirect(expr): {
33
- const isSource = elementExprToPredicate(expr.source)
34
- const isTarget = elementExprToPredicate(expr.target)
35
- return edge => {
36
- return (isSource(edge.source) && isTarget(edge.target))
37
- || (!!expr.isBidirectional && isSource(edge.target) && isTarget(edge.source))
38
- }
39
- }
40
- case ModelRelationExpr.isInOut(expr): {
41
- const isInOut = elementExprToPredicate(expr.inout)
42
- return edge => isInOut(edge.source) || isInOut(edge.target)
43
- }
44
- case ModelRelationExpr.isIncoming(expr): {
45
- const isTarget = elementExprToPredicate(expr.incoming)
46
- return edge => isTarget(edge.target)
47
- }
48
- case ModelRelationExpr.isOutgoing(expr): {
49
- const isSource = elementExprToPredicate(expr.outgoing)
50
- return edge => isSource(edge.source)
51
- }
52
- default:
53
- nonexhaustive(expr)
54
- }
55
- }
@@ -1,85 +0,0 @@
1
- import { unique, values } from 'remeda'
2
- import { type LikeC4View, isElementView, isExtendsElementView } from '../../types/view'
3
-
4
- import Graph from 'graphology'
5
- import { topologicalSort } from 'graphology-dag/topological-sort'
6
- import willCreateCycle from 'graphology-dag/will-create-cycle'
7
- import type { AnyAux, aux, ParsedElementView } from '../../types'
8
- import { isNonEmptyArray } from '../../utils'
9
- /**
10
- * Resolve rules of extended views
11
- * (Removes invalid views)
12
- */
13
- export function resolveRulesExtendedViews<A extends AnyAux, V extends Record<any, LikeC4View<A>>>(
14
- unresolvedViews: V,
15
- ): V {
16
- const g = new Graph<{ view: LikeC4View<A> }>({
17
- type: 'directed',
18
- })
19
- const extendedViews = [] as ParsedElementView<A>[]
20
- for (const view of values(unresolvedViews)) {
21
- g.addNode(view.id, { view })
22
- if (isExtendsElementView(view)) {
23
- extendedViews.push(view)
24
- }
25
- }
26
-
27
- if (extendedViews.length === 0) {
28
- return unresolvedViews
29
- }
30
-
31
- for (const view of extendedViews) {
32
- if (!g.hasNode(view.extends)) {
33
- console.warn(`View "${view.id}" extends from "${view.extends}" which does not exist`)
34
- continue
35
- }
36
- if (willCreateCycle(g, view.id, view.extends)) {
37
- console.warn(`View "${view.id}" extends from "${view.extends}" which creates a cycle`)
38
- continue
39
- }
40
-
41
- // view -> parent
42
- g.addDirectedEdge(view.id, view.extends)
43
- }
44
-
45
- const sorted = topologicalSort(g).reverse()
46
- return sorted.reduce((acc, id) => {
47
- const view = g.getNodeAttribute(id, 'view')
48
- if (!isExtendsElementView(view)) {
49
- acc[view.id] = view
50
- return acc
51
- }
52
-
53
- const extendsFrom = acc[view.extends]
54
- if (!extendsFrom || !isElementView(extendsFrom)) {
55
- return acc
56
- }
57
-
58
- const tags = unique([
59
- ...(extendsFrom.tags ?? []),
60
- ...(view.tags ?? []),
61
- ]) as aux.Tags<A>
62
-
63
- const links = [
64
- ...(extendsFrom.links ?? []),
65
- ...(view.links ?? []),
66
- ]
67
-
68
- acc[view.id] = {
69
- ...extendsFrom,
70
- ...view,
71
- title: view.title ?? extendsFrom.title ?? null,
72
- description: view.description ?? extendsFrom.description ?? null,
73
- tags,
74
- links: isNonEmptyArray(links) ? links : null,
75
- rules: [...extendsFrom.rules, ...view.rules],
76
- }
77
- return acc
78
- }, {} as Record<string, LikeC4View<A>>) as V
79
-
80
- // forEachNodeInTopologicalOrder(g, (_id, { view }) => {
81
-
82
- // })
83
-
84
- // return ordered as V
85
- }
@@ -1,88 +0,0 @@
1
- import { isNullish } from 'remeda'
2
- import {
3
- type AnyAux,
4
- type DynamicViewIncludeRule,
5
- type DynamicViewRule,
6
- type ElementViewPredicate,
7
- type ElementViewRule,
8
- type ModelGlobals,
9
- type ParsedDynamicView,
10
- type ParsedElementView,
11
- type ViewRuleGlobalPredicateRef,
12
- type ViewRuleGlobalStyle,
13
- isDynamicView,
14
- isElementView,
15
- isViewRuleGlobalPredicateRef,
16
- isViewRuleGlobalStyle,
17
- } from '../../types'
18
- import { nonexhaustive } from '../../utils'
19
-
20
- export function resolveGlobalRules<A extends AnyAux>(
21
- view: ParsedElementView<A> | ParsedDynamicView<A>,
22
- globals: ModelGlobals<A>,
23
- ) {
24
- if (isElementView(view)) {
25
- return {
26
- ...view,
27
- rules: resolveGlobalRulesInElementView(view.rules, globals),
28
- }
29
- }
30
-
31
- if (isDynamicView(view)) {
32
- return {
33
- ...view,
34
- rules: resolveGlobalRulesInDynamicView(view.rules, globals),
35
- }
36
- }
37
- nonexhaustive(view)
38
- }
39
-
40
- type ViewRuleGlobal = ViewRuleGlobalPredicateRef | ViewRuleGlobalStyle
41
-
42
- export function resolveGlobalRulesInElementView<M extends AnyAux>(
43
- rules: ElementViewRule<M>[],
44
- globals: ModelGlobals<M>,
45
- ): Array<Exclude<ElementViewRule<M>, ViewRuleGlobal>> {
46
- return rules.reduce((acc, rule) => {
47
- if (isViewRuleGlobalPredicateRef(rule)) {
48
- const globalPredicates = globals.predicates[rule.predicateId]
49
- if (isNullish(globalPredicates)) {
50
- return acc
51
- }
52
- return acc.concat(globalPredicates as ElementViewPredicate<M>[])
53
- }
54
- if (isViewRuleGlobalStyle(rule)) {
55
- const globalStyles = globals.styles[rule.styleId]
56
- if (isNullish(globalStyles)) {
57
- return acc
58
- }
59
- return acc.concat(globalStyles)
60
- }
61
- acc.push(rule)
62
- return acc
63
- }, [] as Array<Exclude<ElementViewRule<M>, ViewRuleGlobal>>)
64
- }
65
-
66
- export function resolveGlobalRulesInDynamicView<M extends AnyAux>(
67
- rules: DynamicViewRule<M>[],
68
- globals: ModelGlobals<M>,
69
- ): Array<Exclude<DynamicViewRule<M>, ViewRuleGlobal>> {
70
- return rules.reduce((acc, rule) => {
71
- if (isViewRuleGlobalPredicateRef(rule)) {
72
- const globalPredicates = globals.dynamicPredicates[rule.predicateId]
73
- if (isNullish(globalPredicates)) {
74
- return acc
75
- }
76
- return acc.concat(globalPredicates as DynamicViewIncludeRule<M>[])
77
- }
78
- if (isViewRuleGlobalStyle(rule)) {
79
- const globalStyles = globals.styles[rule.styleId]
80
- if (isNullish(globalStyles)) {
81
- return acc
82
- }
83
- return acc.concat(globalStyles)
84
- }
85
- acc.push(rule)
86
- return acc
87
- }, [] as Array<Exclude<DynamicViewRule<M>, ViewRuleGlobal>>)
88
- }
@@ -1,256 +0,0 @@
1
- import Graph from 'graphology'
2
- import { topologicalSort as topsort } from 'graphology-dag/topological-sort'
3
- import willCreateCycle from 'graphology-dag/will-create-cycle'
4
- import { forEach, map, partition, pipe, takeWhile } from 'remeda'
5
- import type { AnyAux, ComputedEdge, ComputedNode, NodeId } from '../../types'
6
- import { invariant, nonNullable } from '../../utils'
7
- import { ancestorsOfNode } from './ancestorsOfNode'
8
-
9
- /**
10
- * Keeps initial order of the elements, but ensures parents are placed before children
11
- */
12
- function ensureParentsFirst<T extends { id: string; parent: string | null }>(
13
- array: ReadonlyArray<T>,
14
- ): Array<T> {
15
- const result = [] as T[]
16
- const items = [...array]
17
- let item
18
- while ((item = items.shift())) {
19
- let parent = item.parent
20
- if (parent) {
21
- const ancestors = [] as T[]
22
- while (parent) {
23
- const parentIndx = items.findIndex(i => i.id === parent)
24
- if (parentIndx < 0) {
25
- break
26
- }
27
- const [parentItem] = items.splice(parentIndx, 1)
28
- if (!parentItem) {
29
- throw new Error('Invalid state, should not happen')
30
- }
31
- ancestors.unshift(parentItem)
32
- parent = parentItem.parent
33
- }
34
- result.push(...ancestors)
35
- }
36
- result.push(item)
37
- }
38
- return result as Array<T>
39
- }
40
-
41
- /**
42
- * Side effect, mutates node.children field to preserve same order as in the input
43
- */
44
- function updateChildren<A extends AnyAux = AnyAux>(nodes: ComputedNode<A>[]): ComputedNode<A>[] {
45
- nodes.forEach(parent => {
46
- if (parent.children.length > 0) {
47
- parent.children = nodes.reduce((acc, n) => {
48
- if (n.parent === parent.id) {
49
- acc.push(n.id)
50
- }
51
- return acc
52
- }, [] as NodeId[])
53
- }
54
- })
55
- return nodes
56
- }
57
-
58
- type TopologicalSortParam<A extends AnyAux> = {
59
- nodes: ReadonlyMap<string, ComputedNode<A>>
60
- edges: Iterable<ComputedEdge<A>>
61
- }
62
- export function topologicalSort<A extends AnyAux>(
63
- param: TopologicalSortParam<A>,
64
- ): {
65
- nodes: ComputedNode<A>[]
66
- edges: ComputedEdge<A>[]
67
- } {
68
- let nodes = ensureParentsFirst([...param.nodes.values()])
69
- let edges = [...param.edges]
70
- if (nodes.length < 2 || edges.length === 0) {
71
- return {
72
- nodes,
73
- edges,
74
- }
75
- }
76
-
77
- const getNode = (id: string) => nonNullable(param.nodes.get(id))
78
- // const nodeLevel = (id: string) => getNode(id).level + 1
79
- //
80
-
81
- const g = new Graph({
82
- multi: true,
83
- allowSelfLoops: true,
84
- type: 'directed',
85
- })
86
-
87
- const enrichedEdges = pipe(
88
- edges,
89
- map((edge, __dirname) => {
90
- const source = getNode(edge.source),
91
- target = getNode(edge.target),
92
- parent = edge.parent ? getNode(edge.parent) : null
93
- return ({
94
- id: edge.id,
95
- edge,
96
- parent,
97
- source,
98
- target,
99
- })
100
- }),
101
- // sortBy(
102
- // [prop('sourceIndex'), 'asc'],
103
- // // [prop('sourceInCount'), 'asc'],
104
- // // [prop('sourceLevel'), 'asc'],
105
- // ),
106
- )
107
-
108
- const [edgesBetweenLeafs, edgesWithCompounds] = partition(
109
- enrichedEdges,
110
- ({ source, target }) => source.children.length === 0 && target.children.length === 0,
111
- )
112
-
113
- // edgesBetweenLeafs.sort((a, b) => {
114
- // if (a.source === b.source) {
115
- // return 0
116
- // }
117
- // if (a.source.level === 0 && b.source.level === 0) {
118
- // return 0
119
- // }
120
- // if (isSameHierarchy(a.source, b.target) || isSameHierarchy(a.target, b.source)) {
121
- // return edges.indexOf(a.edge) - edges.indexOf(b.edge)
122
- // }
123
- // const aLevel = a.parent ? a.parent.level + 1 - a.source.level : a.source.level
124
- // const bLevel = b.parent ? b.parent.level + 1 - b.source.level : b.source.level
125
- // return aLevel - bLevel
126
- // // if (a.source.level === 0 && b.source.level === 0) {
127
-
128
- // // // if (a.source.depth)
129
- // // return nodes.indexOf(a.target) - nodes.indexOf(b.target)
130
- // // }
131
- // // if (a.source.level === 0 && b.source.level > 0) {
132
- // // return -1
133
- // // }
134
- // // if (a.parent && b.parent && a.parent !== b.parent) {
135
- // // if (a.parent.level !== b.parent.level) {
136
- // // return b.parent.level - a.parent.level
137
- // // } else {
138
- // // return nodes.indexOf(a.parent) - nodes.indexOf(b.parent)
139
- // // }
140
- // // }
141
- // // return Math.min(nodes.indexOf(a.source), nodes.indexOf(a.target)) - Math.min(nodes.indexOf(b.source), nodes.indexOf(b.target))
142
- // })
143
- const sortedEdges = [] as ComputedEdge<A>[]
144
-
145
- const addEdgeToGraph = (edge: ComputedEdge<A>) => {
146
- g.mergeNode(edge.source)
147
- g.mergeNode(edge.target)
148
- sortedEdges.push(edge)
149
- if (!willCreateCycle(g, edge.source, edge.target)) {
150
- g.mergeDirectedEdge(edge.source, edge.target)
151
- }
152
- }
153
-
154
- for (const { edge, source, target } of edgesBetweenLeafs) {
155
- addEdgeToGraph(edge)
156
- // Strengthen the graph by adding edges to parents
157
- if (target.parent && target.parent !== edge.parent) {
158
- pipe(
159
- ancestorsOfNode(target, param.nodes),
160
- takeWhile(ancestor => ancestor.inEdges.includes(edge.id)),
161
- forEach(ancestor => {
162
- g.mergeNode(ancestor.id)
163
- if (!willCreateCycle(g, edge.source, ancestor.id)) {
164
- g.mergeDirectedEdge(edge.source, ancestor.id)
165
- }
166
- if (!willCreateCycle(g, ancestor.id, edge.target)) {
167
- g.mergeDirectedEdge(ancestor.id, edge.target)
168
- }
169
- }),
170
- )
171
- }
172
- if (source.parent) {
173
- const sourceParent = getNode(source.parent)
174
- g.mergeNode(sourceParent.id)
175
- if (!willCreateCycle(g, sourceParent.id, source.id)) {
176
- g.mergeDirectedEdge(sourceParent.id, source.id)
177
- }
178
- if (target.parent && target.parent !== source.parent) {
179
- if (!willCreateCycle(g, sourceParent.id, target.parent)) {
180
- g.mergeDirectedEdge(sourceParent.id, target.parent)
181
- }
182
- }
183
- }
184
-
185
- // addEdgeToGraph(edge)
186
- }
187
- for (const { edge } of edgesWithCompounds) {
188
- addEdgeToGraph(edge)
189
- }
190
-
191
- invariant(sortedEdges.length === edges.length, 'Not all edges were added to the graph')
192
-
193
- // for (const compound of nodes) {
194
- // if (compound.children.length === 0 || compound.inEdges.length === 0) {
195
- // continue
196
- // }
197
- // // g.mergeNode(compound.id)
198
- // for (const inEdge of compound.inEdges) {
199
- // const { edge, source } = getEdge(inEdge)
200
- // // ignore if this edge is coming from compound node
201
- // if (source.children.length > 0) {
202
- // continue
203
- // }
204
- // // if this edge is coming to the compound node directly
205
- // if (edge.target === compound.id) {
206
- // // for (const child of compound.children) {
207
- // // // g.mergeNode(child)
208
- // // if (!willCreateCycle(g, edge.source, child)) {
209
- // // g.mergeDirectedEdge(edge.source, child)
210
- // // }
211
- // // }
212
- // } else {
213
- // if (!willCreateCycle(g, edge.source, compound.id)) {
214
- // g.mergeDirectedEdge(edge.source, compound.id)
215
- // }
216
- // if (!willCreateCycle(g, compound.id, edge.target)) {
217
- // g.mergeDirectedEdge(compound.id, edge.target)
218
- // }
219
- // }
220
- // }
221
- // }
222
-
223
- const sortedIds = topsort(g)
224
- let sorted = [] as ComputedNode<A>[]
225
- let unsorted = nodes.slice()
226
- for (const sortedId of sortedIds) {
227
- const indx = unsorted.findIndex(n => n.id === sortedId)
228
- invariant(indx >= 0, `Node "${sortedId}" not found`)
229
- sorted.push(...unsorted.splice(indx, 1))
230
- }
231
- // Merge unsorted nodes, keeping their initial order
232
- if (unsorted.length > 0 && sorted.length > 0) {
233
- sorted = sorted.flatMap(node => {
234
- if (unsorted.length === 0) {
235
- return node
236
- }
237
- const wereBefore = nodes
238
- .slice(0, nodes.indexOf(node))
239
- .filter(n => unsorted.includes(n))
240
- if (wereBefore.length > 0) {
241
- unsorted = unsorted.filter(n => !wereBefore.includes(n))
242
- return [...wereBefore, node]
243
- }
244
-
245
- return node
246
- })
247
- }
248
- // Add remaining unsorted nodes
249
- sorted.push(...unsorted)
250
- return {
251
- nodes: updateChildren(
252
- ensureParentsFirst(sorted),
253
- ),
254
- edges: sortedEdges,
255
- }
256
- }
@@ -1,45 +0,0 @@
1
- import { isTruthy, map, mapToObj, pick, pipe } from 'remeda'
2
- import type { SetOptional } from 'type-fest'
3
- import type { ComputedView } from '../../types'
4
- import { objectHash } from '../../utils'
5
-
6
- export function calcViewLayoutHash<V extends ComputedView>(view: SetOptional<V, 'hash'>): V {
7
- const tohash = {
8
- id: view.id,
9
- __: view._type ?? 'element',
10
- autoLayout: view.autoLayout,
11
- nodes: pipe(
12
- view.nodes,
13
- map(n => ({
14
- id: n.id,
15
- icon: isTruthy(n.icon) ? 'Y' : 'N',
16
- title: n.title,
17
- description: n.description?.md ?? n.description?.txt ?? null,
18
- technology: n.technology ?? null,
19
- shape: n.shape,
20
- size: n.style.size ?? null,
21
- textSize: n.style.textSize ?? null,
22
- padding: n.style.padding ?? null,
23
- children: n.children,
24
- })),
25
- mapToObj(({ id, ...node }) => [id, node]),
26
- ),
27
- edges: pipe(
28
- view.edges,
29
- map(e => ({
30
- source: e.source,
31
- target: e.target,
32
- label: e.label,
33
- description: e.description?.md ?? e.description?.txt ?? null,
34
- technology: e.technology ?? null,
35
- dir: e.dir,
36
- head: e.head,
37
- tail: e.tail,
38
- line: e.line,
39
- })),
40
- mapToObj(({ source, target, ...edge }) => [`${source}:${target}`, edge]),
41
- ),
42
- }
43
- view.hash = objectHash(tohash)
44
- return view as unknown as V
45
- }