@likec4/core 1.47.0 → 1.48.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 (181) hide show
  1. package/LICENSE +1 -1
  2. package/dist/_chunks/Builder.view-element.mjs +3284 -0
  3. package/dist/_chunks/LikeC4Model.d.mts +1287 -0
  4. package/dist/_chunks/LikeC4Styles.mjs +691 -0
  5. package/dist/_chunks/RichText.d.mts +84 -0
  6. package/dist/_chunks/RichText.mjs +148 -0
  7. package/dist/_chunks/_aux.d.mts +289 -0
  8. package/dist/_chunks/_aux.mjs +18 -0
  9. package/dist/_chunks/_types.d.mts +781 -0
  10. package/dist/_chunks/_types2.d.mts +38 -0
  11. package/dist/_chunks/assignTagColors.mjs +24 -0
  12. package/dist/_chunks/calcDriftsFromSnapshot.mjs +379 -0
  13. package/dist/_chunks/connection.mjs +0 -0
  14. package/dist/_chunks/const.d.mts +43 -0
  15. package/dist/_chunks/const.mjs +33 -0
  16. package/dist/_chunks/expression-model.d.mts +192 -0
  17. package/dist/_chunks/expression-model.mjs +103 -0
  18. package/dist/_chunks/expression.d.mts +347 -0
  19. package/dist/_chunks/expression.mjs +107 -0
  20. package/dist/_chunks/find.d.mts +82 -0
  21. package/dist/_chunks/find.mjs +646 -0
  22. package/dist/_chunks/find2.d.mts +78 -0
  23. package/dist/_chunks/find2.mjs +287 -0
  24. package/dist/_chunks/fqnRef.d.mts +58 -0
  25. package/dist/_chunks/fqnRef.mjs +41 -0
  26. package/dist/_chunks/geometry.mjs +335 -0
  27. package/dist/_chunks/index.d.mts +169 -0
  28. package/dist/_chunks/index2.d.mts +937 -0
  29. package/dist/_chunks/index3.d.mts +146 -0
  30. package/dist/_chunks/index4.d.mts +62 -0
  31. package/dist/_chunks/index5.d.mts +42 -0
  32. package/dist/_chunks/index6.d.mts +43 -0
  33. package/dist/{shared/core.OtRNdMxy.d.mts → _chunks/index7.d.mts} +113 -197
  34. package/dist/_chunks/index8.d.mts +144 -0
  35. package/dist/_chunks/invariant.mjs +18 -0
  36. package/dist/_chunks/iterable.mjs +146 -0
  37. package/dist/_chunks/libs/@mantine/colors-generator.mjs +3416 -0
  38. package/dist/_chunks/libs/@ungap/structured-clone.mjs +213 -0
  39. package/dist/_chunks/libs/bail.mjs +14 -0
  40. package/dist/_chunks/libs/ccount.mjs +25 -0
  41. package/dist/_chunks/libs/character-entities-html4.mjs +263 -0
  42. package/dist/_chunks/libs/character-entities-legacy.mjs +117 -0
  43. package/dist/_chunks/libs/character-entities.mjs +2136 -0
  44. package/dist/_chunks/libs/comma-separated-tokens.mjs +18 -0
  45. package/dist/_chunks/libs/decode-named-character-reference.mjs +21 -0
  46. package/dist/_chunks/libs/defu.mjs +42 -0
  47. package/dist/_chunks/libs/devlop.mjs +5 -0
  48. package/dist/_chunks/libs/escape-string-regexp.mjs +8 -0
  49. package/dist/_chunks/libs/extend.mjs +77 -0
  50. package/dist/_chunks/libs/graphology-dag.mjs +703 -0
  51. package/dist/_chunks/libs/graphology-types.d.mts +601 -0
  52. package/dist/_chunks/libs/graphology.d.mts +6 -0
  53. package/dist/_chunks/libs/graphology.mjs +4565 -0
  54. package/dist/_chunks/libs/hast-util-sanitize.mjs +863 -0
  55. package/dist/_chunks/libs/hast-util-to-html.mjs +2696 -0
  56. package/dist/_chunks/libs/is-plain-obj.mjs +9 -0
  57. package/dist/_chunks/libs/longest-streak.mjs +30 -0
  58. package/dist/_chunks/libs/markdown-table.mjs +290 -0
  59. package/dist/_chunks/libs/mdast-util-find-and-replace.mjs +653 -0
  60. package/dist/_chunks/libs/mdast-util-from-markdown.mjs +8522 -0
  61. package/dist/_chunks/libs/mdast-util-gfm.mjs +2393 -0
  62. package/dist/_chunks/libs/mdast-util-to-hast.mjs +1803 -0
  63. package/dist/_chunks/libs/micromark-extension-gfm.mjs +2243 -0
  64. package/dist/_chunks/libs/mnemonist.d.mts +254 -0
  65. package/dist/_chunks/libs/mnemonist.mjs +1978 -0
  66. package/dist/_chunks/libs/natural-compare-lite.mjs +42 -0
  67. package/dist/_chunks/libs/rehype-sanitize.mjs +29 -0
  68. package/dist/_chunks/libs/rehype-stringify.mjs +34 -0
  69. package/dist/_chunks/libs/remark-gfm.mjs +36 -0
  70. package/dist/_chunks/libs/remark-github-blockquote-alert.mjs +100 -0
  71. package/dist/_chunks/libs/remark-parse.mjs +39 -0
  72. package/dist/_chunks/libs/remark-rehype.mjs +171 -0
  73. package/dist/_chunks/libs/remeda.mjs +702 -0
  74. package/dist/_chunks/libs/trough.mjs +158 -0
  75. package/dist/_chunks/libs/unified.mjs +2212 -0
  76. package/dist/_chunks/mnemonist.d.mts +1 -0
  77. package/dist/_chunks/mnemonist.mjs +0 -0
  78. package/dist/_chunks/model.mjs +1898 -0
  79. package/dist/_chunks/model2.mjs +0 -0
  80. package/dist/_chunks/relationships-view.mjs +132 -0
  81. package/dist/_chunks/rolldown-runtime.mjs +42 -0
  82. package/dist/{shared/core.C_3y3eqV.d.mts → _chunks/scalar.d.mts} +13 -43
  83. package/dist/_chunks/scalar.mjs +84 -0
  84. package/dist/_chunks/utils.mjs +483 -0
  85. package/dist/builder/index.d.mts +11 -775
  86. package/dist/builder/index.mjs +631 -1022
  87. package/dist/compute-view/index.d.mts +85 -56
  88. package/dist/compute-view/index.mjs +247 -214
  89. package/dist/compute-view/relationships-view/index.d.mts +16 -51
  90. package/dist/compute-view/relationships-view/index.mjs +6 -184
  91. package/dist/geometry/index.d.mts +2 -109
  92. package/dist/geometry/index.mjs +2 -327
  93. package/dist/index.d.mts +18 -20
  94. package/dist/index.mjs +27 -18
  95. package/dist/model/connection/deployment/index.d.mts +12 -15
  96. package/dist/model/connection/deployment/index.mjs +9 -2
  97. package/dist/model/connection/index.d.mts +14 -75
  98. package/dist/model/connection/index.mjs +10 -3
  99. package/dist/model/connection/model/index.d.mts +12 -15
  100. package/dist/model/connection/model/index.mjs +8 -2
  101. package/dist/model/index.d.mts +15 -57
  102. package/dist/model/index.mjs +11 -4
  103. package/dist/styles/index.d.mts +9 -117
  104. package/dist/styles/index.mjs +26 -59
  105. package/dist/types/RichText.d.mts +3 -0
  106. package/dist/types/RichText.mjs +7 -0
  107. package/dist/types/_aux.d.mts +3 -4
  108. package/dist/types/_aux.mjs +2 -7
  109. package/dist/types/expression-model.d.mts +6 -190
  110. package/dist/types/expression-model.mjs +6 -108
  111. package/dist/types/expression.d.mts +5 -6
  112. package/dist/types/expression.mjs +6 -112
  113. package/dist/types/fqnRef.d.mts +4 -60
  114. package/dist/types/fqnRef.mjs +6 -44
  115. package/dist/types/index.d.mts +9 -47
  116. package/dist/types/index.mjs +14 -16
  117. package/dist/types/scalar.d.mts +2 -2
  118. package/dist/types/scalar.mjs +7 -4
  119. package/dist/utils/graphology/index.d.mts +2 -1864
  120. package/dist/utils/graphology/index.mjs +3 -1
  121. package/dist/utils/index.d.mts +11 -124
  122. package/dist/utils/index.mjs +16 -43
  123. package/dist/utils/iterable/index.d.mts +9 -132
  124. package/dist/utils/iterable/index.mjs +2 -61
  125. package/dist/utils/mnemonist.d.mts +2 -0
  126. package/dist/utils/mnemonist.mjs +12 -0
  127. package/package.json +17 -22
  128. package/compute-view/relationships/package.json +0 -4
  129. package/dist/shared/core.3ZhnKAlZ.mjs +0 -106
  130. package/dist/shared/core.78IWAHAE.mjs +0 -332
  131. package/dist/shared/core.B85MJLTf.mjs +0 -5
  132. package/dist/shared/core.BFd1lU9R.mjs +0 -29
  133. package/dist/shared/core.BKlholso.mjs +0 -3
  134. package/dist/shared/core.BNN-3vPH.mjs +0 -1255
  135. package/dist/shared/core.BPGOjone.d.mts +0 -46
  136. package/dist/shared/core.BP_QHEXs.mjs +0 -785
  137. package/dist/shared/core.BbE4y-yl.mjs +0 -177
  138. package/dist/shared/core.Bdy3hhTc.mjs +0 -28382
  139. package/dist/shared/core.BfCKSW-g.d.mts +0 -1266
  140. package/dist/shared/core.BhNcrwzK.mjs +0 -7
  141. package/dist/shared/core.BkVA6gjl.mjs +0 -5
  142. package/dist/shared/core.BoYfZOBm.mjs +0 -3
  143. package/dist/shared/core.BsSXS-_R.mjs +0 -7
  144. package/dist/shared/core.C3JowhaZ.mjs +0 -32
  145. package/dist/shared/core.C4x8aaWa.mjs +0 -27
  146. package/dist/shared/core.CAgYpDtM.d.mts +0 -98
  147. package/dist/shared/core.CHf8VEa3.mjs +0 -1206
  148. package/dist/shared/core.CLSZtnFh.mjs +0 -69
  149. package/dist/shared/core.CbT8JVYL.mjs +0 -5
  150. package/dist/shared/core.CdNCAwq7.mjs +0 -176
  151. package/dist/shared/core.CmGY9blO.mjs +0 -6717
  152. package/dist/shared/core.CmPXpJ8l.mjs +0 -21
  153. package/dist/shared/core.Coi_LOUZ.mjs +0 -7
  154. package/dist/shared/core.CqAJJpK_.mjs +0 -3
  155. package/dist/shared/core.CywrQs86.d.mts +0 -31
  156. package/dist/shared/core.D00YbOhQ.d.mts +0 -300
  157. package/dist/shared/core.D0WZutNd.mjs +0 -94
  158. package/dist/shared/core.D4npX2q8.mjs +0 -18
  159. package/dist/shared/core.DB0Ue5Wx.d.mts +0 -70
  160. package/dist/shared/core.DC5IAaDT.d.mts +0 -334
  161. package/dist/shared/core.DE9qzhn8.d.mts +0 -83
  162. package/dist/shared/core.DGcIbsj4.mjs +0 -3946
  163. package/dist/shared/core.DH7TXqXf.mjs +0 -136
  164. package/dist/shared/core.DKhRkHRN.d.mts +0 -41
  165. package/dist/shared/core.DRJma0Ol.mjs +0 -22
  166. package/dist/shared/core.DU5SRqNF.mjs +0 -2209
  167. package/dist/shared/core.DXhDWKFZ.d.mts +0 -3
  168. package/dist/shared/core.DbfO90vF.mjs +0 -434
  169. package/dist/shared/core.DcS-0zys.mjs +0 -10
  170. package/dist/shared/core.Dh119QSP.mjs +0 -4995
  171. package/dist/shared/core.DjcWextK.mjs +0 -1371
  172. package/dist/shared/core.Dojz4bvg.d.mts +0 -504
  173. package/dist/shared/core.FZ305VYd.mjs +0 -21
  174. package/dist/shared/core.RfnaEmgA.mjs +0 -7
  175. package/dist/shared/core.btEq3i3f.mjs +0 -300
  176. package/dist/shared/core.oSV6SRfk.mjs +0 -13
  177. package/dist/shared/core.om36dXXW.mjs +0 -41
  178. package/dist/shared/core.osFs8tU7.d.mts +0 -466
  179. package/dist/shared/core.q10OP9oJ.mjs +0 -5
  180. package/dist/shared/core.tpvDGvdC.d.mts +0 -87
  181. package/dist/shared/core.uFk_o9X6.mjs +0 -13
@@ -1,1053 +1,662 @@
1
- import { d as defu } from '../shared/core.CLSZtnFh.mjs';
2
- import { t as t$4 } from '../shared/core.3ZhnKAlZ.mjs';
3
- import { t as t$1, a as t$8 } from '../shared/core.BsSXS-_R.mjs';
4
- import { t as t$6 } from '../shared/core.Coi_LOUZ.mjs';
5
- import { t as t$3, n } from '../shared/core.DjcWextK.mjs';
6
- import { t as t$7 } from '../shared/core.DGcIbsj4.mjs';
7
- import { k as e } from '../shared/core.om36dXXW.mjs';
8
- import { e as e$3 } from '../shared/core.DRJma0Ol.mjs';
9
- import { a as _type, u as e$2, _ as _stage, d as isDeployedInstance, p as isElementView } from '../shared/core.DH7TXqXf.mjs';
10
- import { t as t$2 } from '../shared/core.CbT8JVYL.mjs';
11
- import { a as t$5, d as computeLikeC4Model } from '../shared/core.Dh119QSP.mjs';
12
- import { assignTagColors } from '../styles/index.mjs';
13
- import { n as nameFromFqn, d as isSameHierarchy, p as parentFqn } from '../shared/core.CdNCAwq7.mjs';
14
- import { e as e$1 } from '../shared/core.CqAJJpK_.mjs';
15
- import { ModelFqnExpr } from '../types/expression-model.mjs';
16
- import { D as DefaultMap } from '../shared/core.BbE4y-yl.mjs';
17
- import { i as invariant } from '../shared/core.D4npX2q8.mjs';
18
- import { e as exact } from '../shared/core.CHf8VEa3.mjs';
19
- import { FqnRef } from '../types/fqnRef.mjs';
20
- import { b as isGlobalFqn, c as splitGlobalFqn } from '../shared/core.D0WZutNd.mjs';
21
-
22
- function t(...t){return t$1(Object.fromEntries,t)}
1
+ import { C as t$5, H as t$1, J as n, O as e, P as e$3, Q as t$6, S as t$7, U as t$4, Y as t$2, Z as t$3, j as e$2, w as t, z as e$1 } from "../_chunks/libs/remeda.mjs";
2
+ import { A as isDeployedInstance, I as exact, N as _stage, P as _type, g as isElementView } from "../_chunks/LikeC4Styles.mjs";
3
+ import "../_chunks/libs/natural-compare-lite.mjs";
4
+ import { D as parentFqn, E as nameFromFqn, T as isSameHierarchy } from "../_chunks/utils.mjs";
5
+ import { t as invariant } from "../_chunks/invariant.mjs";
6
+ import { t as assignTagColors } from "../_chunks/assignTagColors.mjs";
7
+ import "../_chunks/libs/@mantine/colors-generator.mjs";
8
+ import "../_chunks/libs/graphology-dag.mjs";
9
+ import { n as import_default_map } from "../_chunks/libs/mnemonist.mjs";
10
+ import { t as defu } from "../_chunks/libs/defu.mjs";
11
+ import "../_chunks/libs/extend.mjs";
12
+ import { m as isGlobalFqn, v as splitGlobalFqn } from "../_chunks/scalar.mjs";
13
+ import { t as FqnRef } from "../_chunks/fqnRef.mjs";
14
+ import { n as ModelFqnExpr } from "../_chunks/expression-model.mjs";
15
+ import { n as computeLikeC4Model, t as $expr } from "../_chunks/Builder.view-element.mjs";
16
+ import "../_chunks/libs/graphology.mjs";
23
17
 
18
+ //#region src/builder/Builder.view-common.ts
24
19
  function parseWhere(where) {
25
- if (e$1(where)) {
26
- const op = where;
27
- switch (true) {
28
- case op.startsWith("tag is not #"):
29
- return {
30
- tag: {
31
- neq: op.replace("tag is not #", "")
32
- }
33
- };
34
- case op.startsWith("tag is #"):
35
- return {
36
- tag: {
37
- eq: op.replace("tag is #", "")
38
- }
39
- };
40
- case op.startsWith("kind is not "):
41
- return {
42
- kind: {
43
- neq: op.replace("kind is not ", "")
44
- }
45
- };
46
- case op.startsWith("kind is "):
47
- return {
48
- kind: {
49
- eq: op.replace("kind is ", "")
50
- }
51
- };
52
- case op.startsWith("source."):
53
- return {
54
- operator: parseWhere(
55
- op.replace("source.", "")
56
- ),
57
- participant: "source"
58
- };
59
- case op.startsWith("target."):
60
- return {
61
- operator: parseWhere(
62
- op.replace("target.", "")
63
- ),
64
- participant: "target"
65
- };
66
- default:
67
- throw new Error(`Unknown where operator: ${where}`);
68
- }
69
- }
70
- if (where.and) {
71
- return {
72
- and: t$2(where.and, parseWhere)
73
- };
74
- }
75
- if (where.or) {
76
- return {
77
- or: t$2(where.or, parseWhere)
78
- };
79
- }
80
- if (where.not) {
81
- return {
82
- not: parseWhere(where.not)
83
- };
84
- }
85
- throw new Error(`Unknown where operator: ${where}`);
20
+ if (e(where)) {
21
+ const op = where;
22
+ switch (true) {
23
+ case op.startsWith("tag is not #"): return { tag: { neq: op.replace("tag is not #", "") } };
24
+ case op.startsWith("tag is #"): return { tag: { eq: op.replace("tag is #", "") } };
25
+ case op.startsWith("kind is not "): return { kind: { neq: op.replace("kind is not ", "") } };
26
+ case op.startsWith("kind is "): return { kind: { eq: op.replace("kind is ", "") } };
27
+ case op.startsWith("source."): return {
28
+ operator: parseWhere(op.replace("source.", "")),
29
+ participant: "source"
30
+ };
31
+ case op.startsWith("target."): return {
32
+ operator: parseWhere(op.replace("target.", "")),
33
+ participant: "target"
34
+ };
35
+ default: throw new Error(`Unknown where operator: ${where}`);
36
+ }
37
+ }
38
+ if (where.and) return { and: t(where.and, parseWhere) };
39
+ if (where.or) return { or: t(where.or, parseWhere) };
40
+ if (where.not) return { not: parseWhere(where.not) };
41
+ throw new Error(`Unknown where operator: ${where}`);
86
42
  }
87
43
  function $include(...args) {
88
- return (b) => {
89
- let expr = b.$expr(args[0]);
90
- if (args.length === 2) {
91
- const condition = args[1].where ? parseWhere(args[1].where) : void 0;
92
- if (condition) {
93
- expr = {
94
- where: {
95
- expr,
96
- condition
97
- }
98
- };
99
- }
100
- const custom = args[1].with;
101
- if (custom) {
102
- const isElement = ModelFqnExpr.is(expr);
103
- if (isElement) {
104
- expr = {
105
- custom: {
106
- ...custom,
107
- expr
108
- }
109
- };
110
- } else {
111
- expr = {
112
- customRelation: {
113
- ...custom,
114
- expr
115
- }
116
- };
117
- }
118
- }
119
- }
120
- b.include(expr);
121
- return b;
122
- };
44
+ return (b) => {
45
+ let expr = b.$expr(args[0]);
46
+ if (args.length === 2) {
47
+ const condition = args[1].where ? parseWhere(args[1].where) : void 0;
48
+ if (condition) expr = { where: {
49
+ expr,
50
+ condition
51
+ } };
52
+ const custom = args[1].with;
53
+ if (custom) if (ModelFqnExpr.is(expr)) expr = { custom: {
54
+ ...custom,
55
+ expr
56
+ } };
57
+ else expr = { customRelation: {
58
+ ...custom,
59
+ expr
60
+ } };
61
+ }
62
+ b.include(expr);
63
+ return b;
64
+ };
123
65
  }
124
66
  function $exclude(...args) {
125
- return (b) => {
126
- let expr = b.$expr(args[0]);
127
- if (args.length === 2 && args[1].where) {
128
- const condition = parseWhere(args[1].where);
129
- expr = {
130
- where: {
131
- expr,
132
- condition
133
- }
134
- };
135
- }
136
- b.exclude(expr);
137
- return b;
138
- };
67
+ return (b) => {
68
+ let expr = b.$expr(args[0]);
69
+ if (args.length === 2 && args[1].where) {
70
+ const condition = parseWhere(args[1].where);
71
+ expr = { where: {
72
+ expr,
73
+ condition
74
+ } };
75
+ }
76
+ b.exclude(expr);
77
+ return b;
78
+ };
139
79
  }
80
+ /**
81
+ * @example
82
+ * builder.views(({ view, $style }, _) =>
83
+ * _(
84
+ * view('view1').with(
85
+ * $style('*', {
86
+ * color: 'red',
87
+ * }),
88
+ * $style(['bob', 'alice'], {
89
+ * color: 'blue',
90
+ * }),
91
+ * ),
92
+ * )
93
+ * )
94
+ */
140
95
  function $style(element, { notation, ...style }) {
141
- return (b) => b.style({
142
- targets: (e(element) ? element : [element]).map((e) => b.$expr(e)),
143
- ...notation ? { notation } : {},
144
- style: {
145
- ...style
146
- }
147
- });
96
+ return (b) => b.style({
97
+ targets: (e$1(element) ? element : [element]).map((e) => b.$expr(e)),
98
+ ...notation ? { notation } : {},
99
+ style: { ...style }
100
+ });
148
101
  }
149
102
  function $autoLayout(layout) {
150
- return (b) => b.autoLayout(layout);
103
+ return (b) => b.autoLayout(layout);
151
104
  }
152
105
  function $rules(...rules) {
153
- return (b) => rules.reduce((b2, rule) => rule(b2), b);
106
+ return (b) => rules.reduce((b, rule) => rule(b), b);
154
107
  }
155
108
 
109
+ //#endregion
110
+ //#region src/builder/Builder.view-deployment.ts
156
111
  function $deploymentExpr(expr) {
157
- if (!e$1(expr)) {
158
- return expr;
159
- }
160
- const asTypedDeploymentExpression = (expr2) => {
161
- return expr2;
162
- };
163
- if (expr === "*") {
164
- return asTypedDeploymentExpression({ wildcard: true });
165
- }
166
- if (expr.startsWith("->")) {
167
- if (expr.endsWith("->")) {
168
- return asTypedDeploymentExpression({
169
- inout: $deploymentExpr(expr.replace(/->/g, "").trim())
170
- });
171
- }
172
- return asTypedDeploymentExpression({
173
- incoming: $deploymentExpr(expr.replace("-> ", ""))
174
- });
175
- }
176
- if (expr.endsWith(" ->")) {
177
- return asTypedDeploymentExpression({
178
- outgoing: $deploymentExpr(expr.replace(" ->", ""))
179
- });
180
- }
181
- if (expr.includes(" <-> ")) {
182
- const [source, target] = expr.split(" <-> ");
183
- return asTypedDeploymentExpression({
184
- source: $deploymentExpr(source),
185
- target: $deploymentExpr(target),
186
- isBidirectional: true
187
- });
188
- }
189
- if (expr.includes(" -> ")) {
190
- const [source, target] = expr.split(" -> ");
191
- return asTypedDeploymentExpression({
192
- source: $deploymentExpr(source),
193
- target: $deploymentExpr(target)
194
- });
195
- }
196
- if (expr.endsWith("._")) {
197
- return asTypedDeploymentExpression({
198
- ref: {
199
- deployment: expr.replace("._", "")
200
- },
201
- selector: "expanded"
202
- });
203
- }
204
- if (expr.endsWith(".**")) {
205
- return asTypedDeploymentExpression({
206
- ref: {
207
- deployment: expr.replace(".**", "")
208
- },
209
- selector: "descendants"
210
- });
211
- }
212
- if (expr.endsWith(".*")) {
213
- return asTypedDeploymentExpression({
214
- ref: {
215
- deployment: expr.replace(".*", "")
216
- },
217
- selector: "children"
218
- });
219
- }
220
- return asTypedDeploymentExpression({
221
- ref: {
222
- deployment: expr
223
- }
224
- });
225
- }
226
-
227
- const asTypedExpr = (expr) => {
228
- return expr;
229
- };
230
- function $expr(expr) {
231
- if (!e$1(expr)) {
232
- return expr;
233
- }
234
- if (expr === "*") {
235
- return asTypedExpr({ wildcard: true });
236
- }
237
- if (expr.startsWith("->")) {
238
- if (expr.endsWith("->")) {
239
- return asTypedExpr({
240
- inout: $expr(expr.replace(/->/g, "").trim())
241
- });
242
- }
243
- return asTypedExpr({
244
- incoming: $expr(expr.replace("-> ", ""))
245
- });
246
- }
247
- if (expr.endsWith(" ->")) {
248
- return asTypedExpr({
249
- outgoing: $expr(expr.replace(" ->", ""))
250
- });
251
- }
252
- if (expr.includes(" <-> ")) {
253
- const [source, target] = expr.split(" <-> ");
254
- return asTypedExpr({
255
- source: $expr(source),
256
- target: $expr(target),
257
- isBidirectional: true
258
- });
259
- }
260
- if (expr.includes(" -> ")) {
261
- const [source, target] = expr.split(" -> ");
262
- return asTypedExpr({
263
- source: $expr(source),
264
- target: $expr(target)
265
- });
266
- }
267
- if (expr.endsWith("._")) {
268
- return asTypedExpr({
269
- ref: {
270
- model: expr.replace("._", "")
271
- },
272
- selector: "expanded"
273
- });
274
- }
275
- if (expr.endsWith(".**")) {
276
- return asTypedExpr({
277
- ref: {
278
- model: expr.replace(".**", "")
279
- },
280
- selector: "descendants"
281
- });
282
- }
283
- if (expr.endsWith(".*")) {
284
- return asTypedExpr({
285
- ref: {
286
- model: expr.replace(".*", "")
287
- },
288
- selector: "children"
289
- });
290
- }
291
- return asTypedExpr({
292
- ref: {
293
- model: expr
294
- }
295
- });
112
+ if (!e(expr)) return expr;
113
+ const asTypedDeploymentExpression = (expr) => {
114
+ return expr;
115
+ };
116
+ if (expr === "*") return asTypedDeploymentExpression({ wildcard: true });
117
+ if (expr.startsWith("->")) {
118
+ if (expr.endsWith("->")) return asTypedDeploymentExpression({ inout: $deploymentExpr(expr.replace(/->/g, "").trim()) });
119
+ return asTypedDeploymentExpression({ incoming: $deploymentExpr(expr.replace("-> ", "")) });
120
+ }
121
+ if (expr.endsWith(" ->")) return asTypedDeploymentExpression({ outgoing: $deploymentExpr(expr.replace(" ->", "")) });
122
+ if (expr.includes(" <-> ")) {
123
+ const [source, target] = expr.split(" <-> ");
124
+ return asTypedDeploymentExpression({
125
+ source: $deploymentExpr(source),
126
+ target: $deploymentExpr(target),
127
+ isBidirectional: true
128
+ });
129
+ }
130
+ if (expr.includes(" -> ")) {
131
+ const [source, target] = expr.split(" -> ");
132
+ return asTypedDeploymentExpression({
133
+ source: $deploymentExpr(source),
134
+ target: $deploymentExpr(target)
135
+ });
136
+ }
137
+ if (expr.endsWith("._")) return asTypedDeploymentExpression({
138
+ ref: { deployment: expr.replace("._", "") },
139
+ selector: "expanded"
140
+ });
141
+ if (expr.endsWith(".**")) return asTypedDeploymentExpression({
142
+ ref: { deployment: expr.replace(".**", "") },
143
+ selector: "descendants"
144
+ });
145
+ if (expr.endsWith(".*")) return asTypedDeploymentExpression({
146
+ ref: { deployment: expr.replace(".*", "") },
147
+ selector: "children"
148
+ });
149
+ return asTypedDeploymentExpression({ ref: { deployment: expr } });
296
150
  }
297
151
 
152
+ //#endregion
153
+ //#region src/builder/Builder.views.ts
298
154
  function mkViewBuilder(view) {
299
- const viewBuilder = {
300
- $expr: view[_type] === "deployment" ? $deploymentExpr : $expr,
301
- autoLayout(autoLayout) {
302
- view.rules.push({
303
- direction: autoLayout
304
- });
305
- return viewBuilder;
306
- },
307
- exclude(expr) {
308
- view.rules.push({
309
- exclude: [expr]
310
- });
311
- return viewBuilder;
312
- },
313
- include(expr) {
314
- view.rules.push({
315
- include: [expr]
316
- });
317
- return viewBuilder;
318
- },
319
- style(rule) {
320
- view.rules.push(rule);
321
- return viewBuilder;
322
- }
323
- // title(title: string) {
324
- // view.title = title
325
- // return viewBuilder
326
- // },
327
- // description(description: string) {
328
- // view.description = description
329
- // return viewBuilder
330
- // }
331
- };
332
- return viewBuilder;
155
+ const viewBuilder = {
156
+ $expr: view[_type] === "deployment" ? $deploymentExpr : $expr,
157
+ autoLayout(autoLayout) {
158
+ view.rules.push({ direction: autoLayout });
159
+ return viewBuilder;
160
+ },
161
+ exclude(expr) {
162
+ view.rules.push({ exclude: [expr] });
163
+ return viewBuilder;
164
+ },
165
+ include(expr) {
166
+ view.rules.push({ include: [expr] });
167
+ return viewBuilder;
168
+ },
169
+ style(rule) {
170
+ view.rules.push(rule);
171
+ return viewBuilder;
172
+ }
173
+ };
174
+ return viewBuilder;
333
175
  }
334
176
 
177
+ //#endregion
178
+ //#region src/builder/Builder.ts
335
179
  function ensureObj(value) {
336
- return e(value) ? t$7(value, (_) => ({})) : value;
180
+ return e$1(value) ? t$1(value, (_) => ({})) : value;
337
181
  }
338
182
  function validateSpec({ tags, elements, deployments, relationships, ...specification }) {
339
- const spectags = {};
340
- if (tags) {
341
- Object.assign(
342
- spectags,
343
- ensureObj(tags)
344
- );
345
- }
346
- const _elements = ensureObj(elements);
347
- for (const [kind, spec] of t$6(_elements)) {
348
- if (spec.tags) {
349
- for (const tag of spec.tags) {
350
- invariant(tag in spectags, `Invalid specification for element kind "${kind}": tag "${tag}" not found`);
351
- }
352
- }
353
- }
354
- const _deployments = ensureObj(deployments ?? {});
355
- for (const [kind, spec] of t$6(_deployments)) {
356
- if (spec.tags) {
357
- for (const tag of spec.tags) {
358
- invariant(
359
- tag in spectags,
360
- `Invalid specification for deployment kind "${kind}": tag "${tag}" not found`
361
- );
362
- }
363
- }
364
- }
365
- return {
366
- ...specification,
367
- tags: spectags,
368
- elements: _elements,
369
- deployments: _deployments,
370
- relationships: ensureObj(relationships ?? {})
371
- };
183
+ const spectags = {};
184
+ if (tags) Object.assign(spectags, ensureObj(tags));
185
+ const _elements = ensureObj(elements);
186
+ for (const [kind, spec] of t$2(_elements)) if (spec.tags) for (const tag of spec.tags) invariant(tag in spectags, `Invalid specification for element kind "${kind}": tag "${tag}" not found`);
187
+ const _deployments = ensureObj(deployments ?? {});
188
+ for (const [kind, spec] of t$2(_deployments)) if (spec.tags) for (const tag of spec.tags) invariant(tag in spectags, `Invalid specification for deployment kind "${kind}": tag "${tag}" not found`);
189
+ return {
190
+ ...specification,
191
+ tags: spectags,
192
+ elements: _elements,
193
+ deployments: _deployments,
194
+ relationships: ensureObj(relationships ?? {})
195
+ };
372
196
  }
373
197
  function toMarkdownOrString(input) {
374
- if (e$2(input)) {
375
- return null;
376
- }
377
- if (typeof input === "string") {
378
- return { txt: input };
379
- }
380
- return input;
198
+ if (e$2(input)) return null;
199
+ if (typeof input === "string") return { txt: input };
200
+ return input;
381
201
  }
382
202
  function builder(_spec, _elements = /* @__PURE__ */ new Map(), _relations = [], _views = /* @__PURE__ */ new Map(), _globals = {
383
- predicates: {},
384
- dynamicPredicates: {},
385
- styles: {}
386
- }, _deployments = /* @__PURE__ */ new Map(), _deploymentRelations = [], _imports = new DefaultMap(() => /* @__PURE__ */ new Map())) {
387
- const spec = validateSpec(_spec);
388
- const toLikeC4Specification = () => {
389
- return {
390
- elements: structuredClone(spec.elements),
391
- deployments: structuredClone(spec.deployments),
392
- relationships: structuredClone(spec.relationships),
393
- tags: assignTagColors(structuredClone(spec.tags)),
394
- ...spec.metadataKeys ? { metadataKeys: spec.metadataKeys } : {},
395
- customColors: {}
396
- };
397
- };
398
- const mapLinks = (links) => {
399
- if (!links || !t$8(links, 1)) {
400
- return void 0;
401
- }
402
- return t$2(links, (l) => typeof l === "string" ? { url: l } : l);
403
- };
404
- const createGenericView = (id, _props, builder2) => {
405
- if (e$3(_props)) {
406
- builder2 = _props;
407
- _props = {};
408
- }
409
- _props ??= {};
410
- const {
411
- links: _links = [],
412
- title = null,
413
- description = null,
414
- tags = [],
415
- ...props
416
- } = typeof _props === "string" ? { title: _props } : { ..._props };
417
- const links = mapLinks(_links);
418
- return [
419
- exact({
420
- id,
421
- title,
422
- description: toMarkdownOrString(description),
423
- tags,
424
- links,
425
- _stage: "parsed",
426
- ...props
427
- }),
428
- builder2
429
- ];
430
- };
431
- const checkElementExists = (id) => {
432
- const [project, fqn] = splitGlobalFqn(id);
433
- const lookup = project ? _imports.get(project) : _elements;
434
- const el = lookup.get(fqn);
435
- invariant(el, `Element with id "${id}" not found`);
436
- return el;
437
- };
438
- const parseRelEndpoint = (endpoint) => {
439
- if (typeof endpoint === "string") {
440
- const [project, model] = splitGlobalFqn(endpoint);
441
- if (project) {
442
- return { project, model };
443
- }
444
- return { model };
445
- }
446
- if ("project" in endpoint || "deployment" in endpoint) {
447
- return endpoint;
448
- }
449
- return parseRelEndpoint(endpoint.model);
450
- };
451
- const self = {
452
- get Types() {
453
- throw new Error("Types are not available in runtime");
454
- },
455
- clone: () => {
456
- const imports = new DefaultMap(() => /* @__PURE__ */ new Map());
457
- for (const [key, value] of _imports) {
458
- imports.set(key, structuredClone(value));
459
- }
460
- return builder(
461
- structuredClone(spec),
462
- structuredClone(_elements),
463
- structuredClone(_relations),
464
- structuredClone(_views),
465
- structuredClone(_globals),
466
- structuredClone(_deployments),
467
- structuredClone(_deploymentRelations),
468
- imports
469
- );
470
- },
471
- __addElement: (element) => {
472
- const [project, fqn] = splitGlobalFqn(element.id);
473
- const parent = parentFqn(fqn);
474
- const lookup = project ? _imports.get(project) : _elements;
475
- if (parent) {
476
- invariant(
477
- lookup.get(parent),
478
- `Parent element with id "${parent}" not found for element with id "${element.id}"`
479
- );
480
- }
481
- if (lookup.has(fqn)) {
482
- throw new Error(`Element with id "${element.id}" already exists`);
483
- }
484
- lookup.set(fqn, project ? { ...element, id: fqn } : element);
485
- return self;
486
- },
487
- __addRelation(relation) {
488
- const source = parseRelEndpoint(relation.source);
489
- const sourceFqn = FqnRef.flatten(source);
490
- const target = parseRelEndpoint(relation.target);
491
- const targetFqn = FqnRef.flatten(target);
492
- const sourceEl = checkElementExists(sourceFqn);
493
- const targetEl = checkElementExists(targetFqn);
494
- if (isGlobalFqn(sourceFqn) && isGlobalFqn(targetFqn)) {
495
- throw new Error("Cannot create relationship between global elements");
496
- }
497
- if (!isGlobalFqn(sourceFqn) && !isGlobalFqn(targetFqn)) {
498
- invariant(
499
- !isSameHierarchy(sourceEl, targetEl),
500
- "Cannot create relationship between elements in the same hierarchy"
501
- );
502
- }
503
- _relations.push({
504
- id: `rel${_relations.length + 1}`,
505
- ...relation,
506
- source,
507
- target
508
- });
509
- return self;
510
- },
511
- __fqn(id) {
512
- invariant(id.trim() !== "", "Id must be non-empty");
513
- return id;
514
- },
515
- __deploymentFqn(id) {
516
- invariant(id.trim() !== "", "Id must be non-empty");
517
- return id;
518
- },
519
- __addSourcelessRelation() {
520
- throw new Error("Can be called only in nested model");
521
- },
522
- __addView: (view) => {
523
- if (_views.has(view.id)) {
524
- throw new Error(`View with id "${view.id}" already exists`);
525
- }
526
- if (isElementView(view) && "viewOf" in view) {
527
- invariant(
528
- _elements.get(view.viewOf),
529
- `Invalid scoped view ${view.id}, wlement with id "${view.viewOf}" not found`
530
- );
531
- }
532
- _views.set(view.id, view);
533
- return self;
534
- },
535
- __addDeployment: (node) => {
536
- if (_deployments.has(node.id)) {
537
- throw new Error(`Deployment with id "${node.id}" already exists`);
538
- }
539
- const parent = parentFqn(node.id);
540
- if (parent) {
541
- invariant(
542
- _deployments.get(parent),
543
- `Parent element with id "${parent}" not found for node with id "${node.id}"`
544
- );
545
- }
546
- if (isDeployedInstance(node)) {
547
- invariant(parent, `Instance ${node.id} of ${node.element} must be deployed under a parent node`);
548
- invariant(
549
- _elements.get(node.element),
550
- `Instance "${node.id}" references non-existing element "${node.element}"`
551
- );
552
- }
553
- _deployments.set(node.id, node);
554
- return self;
555
- },
556
- __addDeploymentRelation: (relation) => {
557
- invariant(
558
- !isSameHierarchy(relation.source.deployment, relation.target.deployment),
559
- "Cannot create relationship between elements in the same hierarchy"
560
- );
561
- invariant(
562
- _deployments.has(relation.source.deployment),
563
- `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing source`
564
- );
565
- invariant(
566
- _deployments.has(relation.target.deployment),
567
- `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing target`
568
- );
569
- _deploymentRelations.push({
570
- id: `deploy_rel${_deploymentRelations.length + 1}`,
571
- ...relation
572
- });
573
- return self;
574
- },
575
- build: (project) => ({
576
- [_stage]: "parsed",
577
- projectId: typeof project === "string" ? project : project?.id ?? "from-builder",
578
- project: {
579
- id: typeof project === "string" ? project : "from-builder",
580
- ...typeof project === "object" && project !== null ? project : {}
581
- },
582
- specification: toLikeC4Specification(),
583
- elements: t(
584
- structuredClone(
585
- Array.from(_elements.entries())
586
- )
587
- ),
588
- relations: t$5(_relations, (r) => [r.id, structuredClone(r)]),
589
- globals: structuredClone(_globals),
590
- deployments: {
591
- elements: t(
592
- structuredClone(
593
- Array.from(_deployments.entries())
594
- )
595
- ),
596
- relations: t$5(_deploymentRelations, (r) => [r.id, structuredClone(r)])
597
- },
598
- views: t(
599
- structuredClone(
600
- Array.from(_views.entries())
601
- )
602
- ),
603
- imports: t$4(
604
- Array.from(_imports.entries()),
605
- t$2(([projectId, elementsMap]) => [projectId, structuredClone([...elementsMap.values()])]),
606
- n(([_, elements]) => elements.length > 0),
607
- t()
608
- )
609
- }),
610
- toLikeC4Model: (project) => {
611
- const parsed = self.build(project);
612
- return computeLikeC4Model(parsed);
613
- },
614
- helpers: () => ({
615
- model: {
616
- model: (...ops) => {
617
- return (b) => {
618
- return ops.reduce((b2, op) => op(b2), b);
619
- };
620
- },
621
- rel: (source, target, _props) => {
622
- return (b) => {
623
- const {
624
- title = "",
625
- links: _links = [],
626
- description = null,
627
- notes = null,
628
- ...props
629
- } = defu(
630
- typeof _props === "string" ? { title: _props } : { ..._props },
631
- { title: null, links: null }
632
- );
633
- const links = mapLinks(_links);
634
- b.__addRelation(exact({
635
- source: {
636
- model: source
637
- },
638
- target: {
639
- model: target
640
- },
641
- title,
642
- ...description && { description: toMarkdownOrString(description) },
643
- ...notes && { notes: toMarkdownOrString(notes) },
644
- links,
645
- ...props
646
- }));
647
- return b;
648
- };
649
- },
650
- relTo: (target, _props) => {
651
- return (b) => {
652
- const {
653
- title = "",
654
- links,
655
- description = null,
656
- notes = null,
657
- ...props
658
- } = defu(
659
- typeof _props === "string" ? { title: _props } : { ..._props },
660
- { title: null, links: null }
661
- );
662
- b.__addSourcelessRelation(exact({
663
- target: {
664
- model: target
665
- },
666
- title,
667
- ...description && { description: toMarkdownOrString(description) },
668
- ...notes && { notes: toMarkdownOrString(notes) },
669
- links: mapLinks(links),
670
- ...props
671
- }));
672
- return b;
673
- };
674
- },
675
- ...t$3(
676
- spec.elements,
677
- ({ style: specStyle, ...spec2 }, kind) => (id, _props) => {
678
- const add = ((b) => {
679
- const {
680
- links,
681
- icon: _icon,
682
- color,
683
- shape,
684
- style,
685
- title,
686
- description,
687
- summary,
688
- ...props
689
- } = typeof _props === "string" ? { title: _props } : { ..._props };
690
- const icon = _icon ?? specStyle?.icon;
691
- const _id = b.__fqn(id);
692
- b.__addElement(exact({
693
- id: _id,
694
- kind,
695
- title: title ?? nameFromFqn(_id),
696
- ...description && { description: toMarkdownOrString(description) },
697
- ...summary && { summary: toMarkdownOrString(summary) },
698
- style: exact({
699
- icon,
700
- color: color ?? specStyle?.color,
701
- shape: shape ?? specStyle?.shape,
702
- border: specStyle?.border,
703
- opacity: specStyle?.opacity,
704
- size: specStyle?.size,
705
- padding: specStyle?.padding,
706
- textSize: specStyle?.textSize,
707
- ...style
708
- }),
709
- links: mapLinks(links),
710
- ...spec2,
711
- ...props
712
- }));
713
- return b;
714
- });
715
- add.with = (...ops) => (b) => {
716
- add(b);
717
- const { __fqn, __addSourcelessRelation } = b;
718
- try {
719
- b.__fqn = (child) => `${__fqn(id)}.${child}`;
720
- b.__addSourcelessRelation = (relation) => {
721
- return b.__addRelation({
722
- ...relation,
723
- source: {
724
- model: __fqn(id)
725
- }
726
- });
727
- };
728
- ops.reduce((b2, op) => op(b2), b);
729
- } finally {
730
- b.__fqn = __fqn;
731
- b.__addSourcelessRelation = __addSourcelessRelation;
732
- }
733
- return b;
734
- };
735
- return add;
736
- }
737
- )
738
- },
739
- views: {
740
- views: (...ops) => {
741
- return (b) => {
742
- return ops.reduce((b2, op) => op(b2), b);
743
- };
744
- },
745
- view: (id, _props, _builder) => {
746
- const [generic, builder2] = createGenericView(id, _props, _builder);
747
- const view = {
748
- ...generic,
749
- [_type]: "element",
750
- rules: []
751
- };
752
- const add = (b) => {
753
- b.__addView(view);
754
- if (builder2) {
755
- builder2(mkViewBuilder(view));
756
- }
757
- return b;
758
- };
759
- add.with = (...ops) => (b) => {
760
- add(b);
761
- const elementViewBuilder = mkViewBuilder(view);
762
- for (const op of ops) {
763
- op(elementViewBuilder);
764
- }
765
- return b;
766
- };
767
- return add;
768
- },
769
- viewOf: (id, viewOf, _props, _builder) => {
770
- const [generic, builder2] = createGenericView(id, _props, _builder);
771
- const view = {
772
- ...generic,
773
- viewOf,
774
- [_type]: "element",
775
- rules: []
776
- };
777
- const add = (b) => {
778
- b.__addView(view);
779
- if (builder2) {
780
- builder2(mkViewBuilder(view));
781
- }
782
- return b;
783
- };
784
- add.with = (...ops) => (b) => {
785
- add(b);
786
- const elementViewBuilder = mkViewBuilder(view);
787
- for (const op of ops) {
788
- op(elementViewBuilder);
789
- }
790
- return b;
791
- };
792
- return add;
793
- },
794
- deploymentView: (id, _props, _builder) => {
795
- const [generic, builder2] = createGenericView(id, _props, _builder);
796
- const view = {
797
- ...generic,
798
- [_type]: "deployment",
799
- rules: []
800
- };
801
- const add = (b) => {
802
- b.__addView(view);
803
- if (builder2) {
804
- builder2(mkViewBuilder(view));
805
- }
806
- return b;
807
- };
808
- add.with = (...ops) => (b) => {
809
- add(b);
810
- const elementViewBuilder = mkViewBuilder(view);
811
- for (const op of ops) {
812
- op(elementViewBuilder);
813
- }
814
- return b;
815
- };
816
- return add;
817
- },
818
- $autoLayout,
819
- $exclude,
820
- $include,
821
- $rules,
822
- $style
823
- },
824
- deployment: {
825
- deployment: (...ops) => {
826
- return (b) => {
827
- return ops.reduce((b2, op) => op(b2), b);
828
- };
829
- },
830
- instanceOf: (id, target, _props) => {
831
- return (b) => {
832
- if (e$2(target)) {
833
- target = id;
834
- id = nameFromFqn(id);
835
- } else if (typeof target === "string") {
836
- _props ??= {};
837
- } else {
838
- _props = target;
839
- target = id;
840
- id = nameFromFqn(id);
841
- }
842
- const {
843
- links,
844
- title,
845
- description,
846
- summary,
847
- icon,
848
- color,
849
- shape,
850
- style,
851
- ...props
852
- } = typeof _props === "string" ? { title: _props } : { ..._props };
853
- const _id = b.__deploymentFqn(id);
854
- b.__addDeployment(
855
- exact({
856
- id: _id,
857
- element: target,
858
- ...title && { title },
859
- ...summary && { summary: toMarkdownOrString(summary) },
860
- ...description && { description: toMarkdownOrString(description) },
861
- style: exact({
862
- icon,
863
- color,
864
- shape,
865
- ...style
866
- }),
867
- links: mapLinks(links),
868
- ...props
869
- })
870
- );
871
- return b;
872
- };
873
- },
874
- rel: (source, target, _props) => {
875
- return (b) => {
876
- const {
877
- title = null,
878
- links,
879
- description = null,
880
- notes = null,
881
- ...props
882
- } = typeof _props === "string" ? { title: _props } : { ..._props };
883
- b.__addDeploymentRelation(exact({
884
- source: {
885
- deployment: source
886
- },
887
- target: {
888
- deployment: target
889
- },
890
- title,
891
- ...description && { description: toMarkdownOrString(description) },
892
- ...notes && { notes: toMarkdownOrString(notes) },
893
- links: mapLinks(links),
894
- ...props
895
- }));
896
- return b;
897
- };
898
- },
899
- ...t$3(
900
- spec.deployments ?? {},
901
- ({ style: specStyle, ...spec2 }, kind) => (id, _props) => {
902
- const add = ((b) => {
903
- const {
904
- links,
905
- icon: _icon,
906
- style,
907
- title,
908
- description,
909
- summary,
910
- color,
911
- shape,
912
- ...props
913
- } = typeof _props === "string" ? { title: _props } : { ..._props };
914
- const icon = _icon ?? specStyle?.icon;
915
- const _id = b.__deploymentFqn(id);
916
- b.__addDeployment(
917
- exact({
918
- id: _id,
919
- kind,
920
- title: title ?? nameFromFqn(_id),
921
- ...description && { description: toMarkdownOrString(description) },
922
- ...summary && { summary: toMarkdownOrString(summary) },
923
- style: exact({
924
- icon,
925
- color: color ?? specStyle?.color,
926
- shape: shape ?? specStyle?.shape,
927
- border: specStyle?.border,
928
- opacity: specStyle?.opacity,
929
- size: specStyle?.size,
930
- padding: specStyle?.padding,
931
- textSize: specStyle?.textSize,
932
- ...style
933
- }),
934
- links: mapLinks(links),
935
- ...spec2,
936
- ...props
937
- })
938
- );
939
- return b;
940
- });
941
- add.with = (...ops) => (b) => {
942
- add(b);
943
- const { __deploymentFqn } = b;
944
- try {
945
- b.__deploymentFqn = (child) => `${__deploymentFqn(id)}.${child}`;
946
- ops.reduce((b2, op) => op(b2), b);
947
- } finally {
948
- b.__deploymentFqn = __deploymentFqn;
949
- }
950
- return b;
951
- };
952
- return add;
953
- }
954
- )
955
- }
956
- }),
957
- with: (...ops) => {
958
- const b = self.clone();
959
- return ops.reduce((b2, op) => op(b2), b);
960
- },
961
- model: (cb) => {
962
- const b = self.clone();
963
- const helpers = b.helpers().model;
964
- const _ = helpers.model;
965
- return cb({ ...helpers, _ }, _)(b);
966
- },
967
- deployment: (cb) => {
968
- const b = self.clone();
969
- const helpers = b.helpers().deployment;
970
- const _ = helpers.deployment;
971
- return cb({ ...helpers, _ }, _)(b);
972
- },
973
- views: (cb) => {
974
- const b = self.clone();
975
- const helpers = b.helpers().views;
976
- return cb({
977
- ...helpers,
978
- _: helpers.views
979
- }, helpers.views)(b);
980
- }
981
- };
982
- return self;
203
+ predicates: {},
204
+ dynamicPredicates: {},
205
+ styles: {}
206
+ }, _deployments = /* @__PURE__ */ new Map(), _deploymentRelations = [], _imports = new import_default_map.default(() => /* @__PURE__ */ new Map())) {
207
+ const spec = validateSpec(_spec);
208
+ const toLikeC4Specification = () => {
209
+ return {
210
+ elements: structuredClone(spec.elements),
211
+ deployments: structuredClone(spec.deployments),
212
+ relationships: structuredClone(spec.relationships),
213
+ tags: assignTagColors(structuredClone(spec.tags)),
214
+ ...spec.metadataKeys ? { metadataKeys: spec.metadataKeys } : {},
215
+ customColors: {}
216
+ };
217
+ };
218
+ const mapLinks = (links) => {
219
+ if (!links || !t$3(links, 1)) return;
220
+ return t(links, (l) => typeof l === "string" ? { url: l } : l);
221
+ };
222
+ const createGenericView = (id, _props, builder) => {
223
+ if (e$3(_props)) {
224
+ builder = _props;
225
+ _props = {};
226
+ }
227
+ _props ??= {};
228
+ const { links: _links = [], title = null, description = null, tags = [], ...props } = typeof _props === "string" ? { title: _props } : { ..._props };
229
+ const links = mapLinks(_links);
230
+ return [exact({
231
+ id,
232
+ title,
233
+ description: toMarkdownOrString(description),
234
+ tags,
235
+ links,
236
+ _stage: "parsed",
237
+ ...props
238
+ }), builder];
239
+ };
240
+ const checkElementExists = (id) => {
241
+ const [project, fqn] = splitGlobalFqn(id);
242
+ const el = (project ? _imports.get(project) : _elements).get(fqn);
243
+ invariant(el, `Element with id "${id}" not found`);
244
+ return el;
245
+ };
246
+ const parseRelEndpoint = (endpoint) => {
247
+ if (typeof endpoint === "string") {
248
+ const [project, model] = splitGlobalFqn(endpoint);
249
+ if (project) return {
250
+ project,
251
+ model
252
+ };
253
+ return { model };
254
+ }
255
+ if ("project" in endpoint || "deployment" in endpoint) return endpoint;
256
+ return parseRelEndpoint(endpoint.model);
257
+ };
258
+ const self = {
259
+ get Types() {
260
+ throw new Error("Types are not available in runtime");
261
+ },
262
+ clone: () => {
263
+ const imports = new import_default_map.default(() => /* @__PURE__ */ new Map());
264
+ for (const [key, value] of _imports) imports.set(key, structuredClone(value));
265
+ return builder(structuredClone(spec), structuredClone(_elements), structuredClone(_relations), structuredClone(_views), structuredClone(_globals), structuredClone(_deployments), structuredClone(_deploymentRelations), imports);
266
+ },
267
+ __addElement: (element) => {
268
+ const [project, fqn] = splitGlobalFqn(element.id);
269
+ const parent = parentFqn(fqn);
270
+ const lookup = project ? _imports.get(project) : _elements;
271
+ if (parent) invariant(lookup.get(parent), `Parent element with id "${parent}" not found for element with id "${element.id}"`);
272
+ if (lookup.has(fqn)) throw new Error(`Element with id "${element.id}" already exists`);
273
+ lookup.set(fqn, project ? {
274
+ ...element,
275
+ id: fqn
276
+ } : element);
277
+ return self;
278
+ },
279
+ __addRelation(relation) {
280
+ const source = parseRelEndpoint(relation.source);
281
+ const sourceFqn = FqnRef.flatten(source);
282
+ const target = parseRelEndpoint(relation.target);
283
+ const targetFqn = FqnRef.flatten(target);
284
+ const sourceEl = checkElementExists(sourceFqn);
285
+ const targetEl = checkElementExists(targetFqn);
286
+ if (isGlobalFqn(sourceFqn) && isGlobalFqn(targetFqn)) throw new Error("Cannot create relationship between global elements");
287
+ if (!isGlobalFqn(sourceFqn) && !isGlobalFqn(targetFqn)) invariant(!isSameHierarchy(sourceEl, targetEl), "Cannot create relationship between elements in the same hierarchy");
288
+ _relations.push({
289
+ id: `rel${_relations.length + 1}`,
290
+ ...relation,
291
+ source,
292
+ target
293
+ });
294
+ return self;
295
+ },
296
+ __fqn(id) {
297
+ invariant(id.trim() !== "", "Id must be non-empty");
298
+ return id;
299
+ },
300
+ __deploymentFqn(id) {
301
+ invariant(id.trim() !== "", "Id must be non-empty");
302
+ return id;
303
+ },
304
+ __addSourcelessRelation() {
305
+ throw new Error("Can be called only in nested model");
306
+ },
307
+ __addView: (view) => {
308
+ if (_views.has(view.id)) throw new Error(`View with id "${view.id}" already exists`);
309
+ if (isElementView(view) && "viewOf" in view) invariant(_elements.get(view.viewOf), `Invalid scoped view ${view.id}, wlement with id "${view.viewOf}" not found`);
310
+ _views.set(view.id, view);
311
+ return self;
312
+ },
313
+ __addDeployment: (node) => {
314
+ if (_deployments.has(node.id)) throw new Error(`Deployment with id "${node.id}" already exists`);
315
+ const parent = parentFqn(node.id);
316
+ if (parent) invariant(_deployments.get(parent), `Parent element with id "${parent}" not found for node with id "${node.id}"`);
317
+ if (isDeployedInstance(node)) {
318
+ invariant(parent, `Instance ${node.id} of ${node.element} must be deployed under a parent node`);
319
+ invariant(_elements.get(node.element), `Instance "${node.id}" references non-existing element "${node.element}"`);
320
+ }
321
+ _deployments.set(node.id, node);
322
+ return self;
323
+ },
324
+ __addDeploymentRelation: (relation) => {
325
+ invariant(!isSameHierarchy(relation.source.deployment, relation.target.deployment), "Cannot create relationship between elements in the same hierarchy");
326
+ invariant(_deployments.has(relation.source.deployment), `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing source`);
327
+ invariant(_deployments.has(relation.target.deployment), `Relation "${relation.source.deployment} -> ${relation.target.deployment}" references non-existing target`);
328
+ _deploymentRelations.push({
329
+ id: `deploy_rel${_deploymentRelations.length + 1}`,
330
+ ...relation
331
+ });
332
+ return self;
333
+ },
334
+ build: (project) => ({
335
+ [_stage]: "parsed",
336
+ projectId: typeof project === "string" ? project : project?.id ?? "from-builder",
337
+ project: {
338
+ id: typeof project === "string" ? project : "from-builder",
339
+ ...typeof project === "object" && project !== null ? project : {}
340
+ },
341
+ specification: toLikeC4Specification(),
342
+ elements: t$4(structuredClone(Array.from(_elements.entries()))),
343
+ relations: t$5(_relations, (r) => [r.id, structuredClone(r)]),
344
+ globals: structuredClone(_globals),
345
+ deployments: {
346
+ elements: t$4(structuredClone(Array.from(_deployments.entries()))),
347
+ relations: t$5(_deploymentRelations, (r) => [r.id, structuredClone(r)])
348
+ },
349
+ views: t$4(structuredClone(Array.from(_views.entries()))),
350
+ imports: t$6(Array.from(_imports.entries()), t(([projectId, elementsMap]) => [projectId, structuredClone([...elementsMap.values()])]), n(([_, elements]) => elements.length > 0), t$4())
351
+ }),
352
+ toLikeC4Model: (project) => {
353
+ return computeLikeC4Model(self.build(project));
354
+ },
355
+ helpers: () => ({
356
+ model: {
357
+ model: (...ops) => {
358
+ return (b) => {
359
+ return ops.reduce((b, op) => op(b), b);
360
+ };
361
+ },
362
+ rel: (source, target, _props) => {
363
+ return (b) => {
364
+ const { title = "", links: _links = [], description = null, notes = null, ...props } = defu(typeof _props === "string" ? { title: _props } : { ..._props }, {
365
+ title: null,
366
+ links: null
367
+ });
368
+ const links = mapLinks(_links);
369
+ b.__addRelation(exact({
370
+ source: { model: source },
371
+ target: { model: target },
372
+ title,
373
+ ...description && { description: toMarkdownOrString(description) },
374
+ ...notes && { notes: toMarkdownOrString(notes) },
375
+ links,
376
+ ...props
377
+ }));
378
+ return b;
379
+ };
380
+ },
381
+ relTo: (target, _props) => {
382
+ return (b) => {
383
+ const { title = "", links, description = null, notes = null, ...props } = defu(typeof _props === "string" ? { title: _props } : { ..._props }, {
384
+ title: null,
385
+ links: null
386
+ });
387
+ b.__addSourcelessRelation(exact({
388
+ target: { model: target },
389
+ title,
390
+ ...description && { description: toMarkdownOrString(description) },
391
+ ...notes && { notes: toMarkdownOrString(notes) },
392
+ links: mapLinks(links),
393
+ ...props
394
+ }));
395
+ return b;
396
+ };
397
+ },
398
+ ...t$7(spec.elements, ({ style: specStyle, ...spec }, kind) => (id, _props) => {
399
+ const add = ((b) => {
400
+ const { links, icon: _icon, color, shape, style, title, description, summary, ...props } = typeof _props === "string" ? { title: _props } : { ..._props };
401
+ const icon = _icon ?? specStyle?.icon;
402
+ const _id = b.__fqn(id);
403
+ b.__addElement(exact({
404
+ id: _id,
405
+ kind,
406
+ title: title ?? nameFromFqn(_id),
407
+ ...description && { description: toMarkdownOrString(description) },
408
+ ...summary && { summary: toMarkdownOrString(summary) },
409
+ style: exact({
410
+ icon,
411
+ color: color ?? specStyle?.color,
412
+ shape: shape ?? specStyle?.shape,
413
+ border: specStyle?.border,
414
+ opacity: specStyle?.opacity,
415
+ size: specStyle?.size,
416
+ padding: specStyle?.padding,
417
+ textSize: specStyle?.textSize,
418
+ ...style
419
+ }),
420
+ links: mapLinks(links),
421
+ ...spec,
422
+ ...props
423
+ }));
424
+ return b;
425
+ });
426
+ add.with = (...ops) => (b) => {
427
+ add(b);
428
+ const { __fqn, __addSourcelessRelation } = b;
429
+ try {
430
+ b.__fqn = (child) => `${__fqn(id)}.${child}`;
431
+ b.__addSourcelessRelation = (relation) => {
432
+ return b.__addRelation({
433
+ ...relation,
434
+ source: { model: __fqn(id) }
435
+ });
436
+ };
437
+ ops.reduce((b, op) => op(b), b);
438
+ } finally {
439
+ b.__fqn = __fqn;
440
+ b.__addSourcelessRelation = __addSourcelessRelation;
441
+ }
442
+ return b;
443
+ };
444
+ return add;
445
+ })
446
+ },
447
+ views: {
448
+ views: (...ops) => {
449
+ return (b) => {
450
+ return ops.reduce((b, op) => op(b), b);
451
+ };
452
+ },
453
+ view: (id, _props, _builder) => {
454
+ const [generic, builder] = createGenericView(id, _props, _builder);
455
+ const view = {
456
+ ...generic,
457
+ [_type]: "element",
458
+ rules: []
459
+ };
460
+ const add = (b) => {
461
+ b.__addView(view);
462
+ if (builder) builder(mkViewBuilder(view));
463
+ return b;
464
+ };
465
+ add.with = (...ops) => (b) => {
466
+ add(b);
467
+ const elementViewBuilder = mkViewBuilder(view);
468
+ for (const op of ops) op(elementViewBuilder);
469
+ return b;
470
+ };
471
+ return add;
472
+ },
473
+ viewOf: (id, viewOf, _props, _builder) => {
474
+ const [generic, builder] = createGenericView(id, _props, _builder);
475
+ const view = {
476
+ ...generic,
477
+ viewOf,
478
+ [_type]: "element",
479
+ rules: []
480
+ };
481
+ const add = (b) => {
482
+ b.__addView(view);
483
+ if (builder) builder(mkViewBuilder(view));
484
+ return b;
485
+ };
486
+ add.with = (...ops) => (b) => {
487
+ add(b);
488
+ const elementViewBuilder = mkViewBuilder(view);
489
+ for (const op of ops) op(elementViewBuilder);
490
+ return b;
491
+ };
492
+ return add;
493
+ },
494
+ deploymentView: (id, _props, _builder) => {
495
+ const [generic, builder] = createGenericView(id, _props, _builder);
496
+ const view = {
497
+ ...generic,
498
+ [_type]: "deployment",
499
+ rules: []
500
+ };
501
+ const add = (b) => {
502
+ b.__addView(view);
503
+ if (builder) builder(mkViewBuilder(view));
504
+ return b;
505
+ };
506
+ add.with = (...ops) => (b) => {
507
+ add(b);
508
+ const elementViewBuilder = mkViewBuilder(view);
509
+ for (const op of ops) op(elementViewBuilder);
510
+ return b;
511
+ };
512
+ return add;
513
+ },
514
+ $autoLayout,
515
+ $exclude,
516
+ $include,
517
+ $rules,
518
+ $style
519
+ },
520
+ deployment: {
521
+ deployment: (...ops) => {
522
+ return (b) => {
523
+ return ops.reduce((b, op) => op(b), b);
524
+ };
525
+ },
526
+ instanceOf: (id, target, _props) => {
527
+ return (b) => {
528
+ if (e$2(target)) {
529
+ target = id;
530
+ id = nameFromFqn(id);
531
+ } else if (typeof target === "string") _props ??= {};
532
+ else {
533
+ _props = target;
534
+ target = id;
535
+ id = nameFromFqn(id);
536
+ }
537
+ const { links, title, description, summary, icon, color, shape, style, ...props } = typeof _props === "string" ? { title: _props } : { ..._props };
538
+ const _id = b.__deploymentFqn(id);
539
+ b.__addDeployment(exact({
540
+ id: _id,
541
+ element: target,
542
+ ...title && { title },
543
+ ...summary && { summary: toMarkdownOrString(summary) },
544
+ ...description && { description: toMarkdownOrString(description) },
545
+ style: exact({
546
+ icon,
547
+ color,
548
+ shape,
549
+ ...style
550
+ }),
551
+ links: mapLinks(links),
552
+ ...props
553
+ }));
554
+ return b;
555
+ };
556
+ },
557
+ rel: (source, target, _props) => {
558
+ return (b) => {
559
+ const { title = null, links, description = null, notes = null, ...props } = typeof _props === "string" ? { title: _props } : { ..._props };
560
+ b.__addDeploymentRelation(exact({
561
+ source: { deployment: source },
562
+ target: { deployment: target },
563
+ title,
564
+ ...description && { description: toMarkdownOrString(description) },
565
+ ...notes && { notes: toMarkdownOrString(notes) },
566
+ links: mapLinks(links),
567
+ ...props
568
+ }));
569
+ return b;
570
+ };
571
+ },
572
+ ...t$7(spec.deployments ?? {}, ({ style: specStyle, ...spec }, kind) => (id, _props) => {
573
+ const add = ((b) => {
574
+ const { links, icon: _icon, style, title, description, summary, color, shape, ...props } = typeof _props === "string" ? { title: _props } : { ..._props };
575
+ const icon = _icon ?? specStyle?.icon;
576
+ const _id = b.__deploymentFqn(id);
577
+ b.__addDeployment(exact({
578
+ id: _id,
579
+ kind,
580
+ title: title ?? nameFromFqn(_id),
581
+ ...description && { description: toMarkdownOrString(description) },
582
+ ...summary && { summary: toMarkdownOrString(summary) },
583
+ style: exact({
584
+ icon,
585
+ color: color ?? specStyle?.color,
586
+ shape: shape ?? specStyle?.shape,
587
+ border: specStyle?.border,
588
+ opacity: specStyle?.opacity,
589
+ size: specStyle?.size,
590
+ padding: specStyle?.padding,
591
+ textSize: specStyle?.textSize,
592
+ ...style
593
+ }),
594
+ links: mapLinks(links),
595
+ ...spec,
596
+ ...props
597
+ }));
598
+ return b;
599
+ });
600
+ add.with = (...ops) => (b) => {
601
+ add(b);
602
+ const { __deploymentFqn } = b;
603
+ try {
604
+ b.__deploymentFqn = (child) => `${__deploymentFqn(id)}.${child}`;
605
+ ops.reduce((b, op) => op(b), b);
606
+ } finally {
607
+ b.__deploymentFqn = __deploymentFqn;
608
+ }
609
+ return b;
610
+ };
611
+ return add;
612
+ })
613
+ }
614
+ }),
615
+ with: (...ops) => {
616
+ const b = self.clone();
617
+ return ops.reduce((b, op) => op(b), b);
618
+ },
619
+ model: (cb) => {
620
+ const b = self.clone();
621
+ const helpers = b.helpers().model;
622
+ const _ = helpers.model;
623
+ return cb({
624
+ ...helpers,
625
+ _
626
+ }, _)(b);
627
+ },
628
+ deployment: (cb) => {
629
+ const b = self.clone();
630
+ const helpers = b.helpers().deployment;
631
+ const _ = helpers.deployment;
632
+ return cb({
633
+ ...helpers,
634
+ _
635
+ }, _)(b);
636
+ },
637
+ views: (cb) => {
638
+ const b = self.clone();
639
+ const helpers = b.helpers().views;
640
+ return cb({
641
+ ...helpers,
642
+ _: helpers.views
643
+ }, helpers.views)(b);
644
+ }
645
+ };
646
+ return self;
983
647
  }
984
648
  const Builder = {
985
- /**
986
- * Creates a builder with compositional methods
987
- *
988
- * @example
989
- * ```ts
990
- * const {
991
- * model: { model, system, component, relTo },
992
- * deployment: { env, vm},
993
- * views: { view, $include },
994
- * builder,
995
- * } = Builder.forSpecification({
996
- * elements: {
997
- * system: {},
998
- * component: {},
999
- * },
1000
- * deployments: ['env', 'vm'],
1001
- * })
1002
- *
1003
- * const b = builder
1004
- * .with(
1005
- * model(
1006
- * system('cloud').with(
1007
- * component('backend'),
1008
- * component('backend.api'),
1009
- * component('frontend').with(
1010
- * relTo('cloud.backend.api'),
1011
- * ),
1012
- * ),
1013
- * ),
1014
- * )
1015
- * ```
1016
- */
1017
- forSpecification(spec) {
1018
- const b = builder(spec);
1019
- return {
1020
- ...b.helpers(),
1021
- builder: b
1022
- };
1023
- },
1024
- /**
1025
- * Creates a builder with chainable methods
1026
- *
1027
- * @example
1028
- * ```ts
1029
- * const b = Builder
1030
- * .specification({
1031
- * elements: ['system', 'component'],
1032
- * deployments: ['env', 'vm'],
1033
- * })
1034
- * .model(({ system, component, relTo }, _) =>
1035
- * _(
1036
- * system('cloud').with(
1037
- * component('backend').with(
1038
- * component('api'),
1039
- * ),
1040
- * component('frontend').with(
1041
- * relTo('cloud.backend.api'),
1042
- * )
1043
- * )
1044
- * )
1045
- * )
1046
- * ```
1047
- */
1048
- specification(spec) {
1049
- return builder(spec);
1050
- }
649
+ forSpecification(spec) {
650
+ const b = builder(spec);
651
+ return {
652
+ ...b.helpers(),
653
+ builder: b
654
+ };
655
+ },
656
+ specification(spec) {
657
+ return builder(spec);
658
+ }
1051
659
  };
1052
660
 
1053
- export { Builder };
661
+ //#endregion
662
+ export { Builder };