@likec4/core 1.12.1 → 1.13.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 (35) hide show
  1. package/dist/index.cjs +777 -251
  2. package/dist/index.d.cts +301 -32
  3. package/dist/index.d.mts +301 -32
  4. package/dist/index.d.ts +301 -32
  5. package/dist/index.mjs +774 -252
  6. package/dist/shared/{core.BvFch1jG.mjs → core.BJDxVHFh.mjs} +19 -19
  7. package/dist/shared/{core.dY8efyk0.d.ts → core.C4jDMQ1i.d.cts} +242 -238
  8. package/dist/shared/{core.dY8efyk0.d.cts → core.C4jDMQ1i.d.mts} +242 -238
  9. package/dist/shared/{core.dY8efyk0.d.mts → core.C4jDMQ1i.d.ts} +242 -238
  10. package/dist/shared/{core.CTiE4teS.cjs → core.IR7XOEkQ.cjs} +19 -18
  11. package/dist/types/index.cjs +1 -1
  12. package/dist/types/index.d.cts +1 -1
  13. package/dist/types/index.d.mts +1 -1
  14. package/dist/types/index.d.ts +1 -1
  15. package/dist/types/index.mjs +1 -1
  16. package/package.json +4 -3
  17. package/src/builder/Builder.element.ts +221 -0
  18. package/src/builder/Builder.model.ts +346 -0
  19. package/src/builder/Builder.test-d.ts +69 -0
  20. package/src/builder/Builder.ts +574 -0
  21. package/src/builder/Builder.view.ts +358 -0
  22. package/src/builder/Builder.views.ts +318 -0
  23. package/src/builder/_types.ts +195 -0
  24. package/src/builder/index.ts +5 -0
  25. package/src/index.ts +4 -0
  26. package/src/model/LikeC4DiagramModel.ts +5 -5
  27. package/src/model/LikeC4Model.ts +63 -46
  28. package/src/model/LikeC4ViewModel.ts +7 -7
  29. package/src/model/__test__/fixture.ts +5 -0
  30. package/src/types/element.ts +19 -11
  31. package/src/types/model.ts +13 -8
  32. package/src/types/relation.ts +1 -1
  33. package/src/types/view-changes.ts +6 -2
  34. package/src/types/view.ts +53 -22
  35. package/src/utils/fqn.ts +12 -11
package/dist/index.cjs CHANGED
@@ -1,6 +1,725 @@
1
1
  'use strict';
2
2
 
3
- const types_index = require('./shared/core.CTiE4teS.cjs');
3
+ const types_index = require('./shared/core.IR7XOEkQ.cjs');
4
+ const defu = require('defu');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
7
+
8
+ const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
9
+
10
+ function r$1(...n){return types_index.u(Object.values,n)}
11
+
12
+ function i$2(...e){return types_index.u(r,e)}var r=(e,t)=>e.length>=t;
13
+
14
+ function o$2(r,n){let e=Math.ceil(r),t=Math.floor(n);if(t<e)throw new RangeError(`randomInteger: The range [${r.toString()},${n.toString()}] contains no integer`);return Math.floor(Math.random()*(t-e+1)+e)}
15
+
16
+ function i$1(...e){return types_index.u(u,e)}function u(e,o){let t={};for(let[r,n]of Object.entries(e))o(n,r,e)&&(t[r]=n);return t}
17
+
18
+ function m(...a){return types_index.u(o$1,a,p)}var o$1=(a,e)=>a.map(e),p=a=>(e,r,t)=>({done:!1,hasNext:!0,next:a(e,r,t)});
19
+
20
+ function l$1(...n){return types_index.u(d,n)}function d(n,o){let e={};for(let[a,t]of n.entries()){let[y,u]=o(t,a,n);e[y]=u;}return e}
21
+
22
+ function i(...e){return types_index.u(o,e)}function o(e,u){let a={};for(let[n,r]of Object.entries(e)){let l=u(r,n,e);a[n]=l;}return a}
23
+
24
+ function t$1(r){return typeof r=="string"}
25
+
26
+ function n$1(e){return !!e}
27
+
28
+ function t(n){return typeof n=="function"}
29
+
30
+ function l(n){return n!=null}
31
+
32
+ function n(...r){return types_index.u(Object.fromEntries,r)}
33
+
34
+ function getDefaultExportFromCjs (x) {
35
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
36
+ }
37
+
38
+ var naturalCompareLite = {exports: {}};
39
+
40
+ var hasRequiredNaturalCompareLite;
41
+
42
+ function requireNaturalCompareLite () {
43
+ if (hasRequiredNaturalCompareLite) return naturalCompareLite.exports;
44
+ hasRequiredNaturalCompareLite = 1;
45
+ /*
46
+ * @version 1.4.0
47
+ * @date 2015-10-26
48
+ * @stability 3 - Stable
49
+ * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
50
+ * @license MIT License
51
+ */
52
+
53
+
54
+ var naturalCompare = function(a, b) {
55
+ var i, codeA
56
+ , codeB = 1
57
+ , posA = 0
58
+ , posB = 0
59
+ , alphabet = String.alphabet;
60
+
61
+ function getCode(str, pos, code) {
62
+ if (code) {
63
+ for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
64
+ return +str.slice(pos - 1, i)
65
+ }
66
+ code = alphabet && alphabet.indexOf(str.charAt(pos));
67
+ return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code
68
+ : code < 46 ? 65 // -
69
+ : code < 48 ? code - 1
70
+ : code < 58 ? code + 18 // 0-9
71
+ : code < 65 ? code - 11
72
+ : code < 91 ? code + 11 // A-Z
73
+ : code < 97 ? code - 37
74
+ : code < 123 ? code + 5 // a-z
75
+ : code - 63
76
+ }
77
+
78
+
79
+ if ((a+="") != (b+="")) for (;codeB;) {
80
+ codeA = getCode(a, posA++);
81
+ codeB = getCode(b, posB++);
82
+
83
+ if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
84
+ codeA = getCode(a, posA, posA);
85
+ codeB = getCode(b, posB, posA = i);
86
+ posB = i;
87
+ }
88
+
89
+ if (codeA != codeB) return (codeA < codeB) ? -1 : 1
90
+ }
91
+ return 0
92
+ };
93
+
94
+ try {
95
+ naturalCompareLite.exports = naturalCompare;
96
+ } catch (e) {
97
+ String.naturalCompare = naturalCompare;
98
+ }
99
+ return naturalCompareLite.exports;
100
+ }
101
+
102
+ var naturalCompareLiteExports = requireNaturalCompareLite();
103
+ const compare = /*@__PURE__*/getDefaultExportFromCjs(naturalCompareLiteExports);
104
+
105
+ function compareNatural(a, b) {
106
+ if (a === b) return 0;
107
+ if (t$1(a)) {
108
+ if (t$1(b)) {
109
+ return compare(a, b);
110
+ }
111
+ return 1;
112
+ }
113
+ return t$1(b) ? -1 : 0;
114
+ }
115
+
116
+ function isString(value) {
117
+ return value != null && typeof value === "string";
118
+ }
119
+ function isNonEmptyArray(arr) {
120
+ return !!arr && Array.isArray(arr) && arr.length > 0;
121
+ }
122
+
123
+ function nameFromFqn(fqn) {
124
+ const lastDot = fqn.lastIndexOf(".");
125
+ if (lastDot > 0) {
126
+ return fqn.slice(lastDot + 1);
127
+ } else {
128
+ return fqn;
129
+ }
130
+ }
131
+ function isAncestor(...args) {
132
+ const ancestor = isString(args[0]) ? args[0] : args[0].id;
133
+ const another = isString(args[1]) ? args[1] : args[1].id;
134
+ return another.startsWith(ancestor + ".");
135
+ }
136
+ function isSameHierarchy(one, another) {
137
+ const first = isString(one) ? one : one.id;
138
+ const second = isString(another) ? another : another.id;
139
+ return first === second || second.startsWith(first + ".") || first.startsWith(second + ".");
140
+ }
141
+ function isDescendantOf(ancestors) {
142
+ const predicates = ancestors.flatMap((a) => [(e) => e.id === a.id, (e) => isAncestor(a, e)]);
143
+ return (e) => predicates.some((p) => p(e));
144
+ }
145
+ function notDescendantOf(ancestors) {
146
+ const isDescendant = isDescendantOf(ancestors);
147
+ return (e) => !isDescendant(e);
148
+ }
149
+ function commonAncestor(first, second) {
150
+ const parentA = parentFqn(first);
151
+ const parentB = parentFqn(second);
152
+ if (parentA === parentB) {
153
+ return parentA;
154
+ }
155
+ if (!parentA || !parentB) {
156
+ return null;
157
+ }
158
+ const a = first.split(".");
159
+ const b = second.split(".");
160
+ let ancestor = null;
161
+ while (a.length > 1 && b.length > 1 && !!a[0] && a[0] === b[0]) {
162
+ ancestor = ancestor ? `${ancestor}.${a[0]}` : a[0];
163
+ a.shift();
164
+ b.shift();
165
+ }
166
+ return ancestor;
167
+ }
168
+ function parentFqn(fqn) {
169
+ const lastDot = fqn.lastIndexOf(".");
170
+ if (lastDot > 0) {
171
+ return fqn.slice(0, lastDot);
172
+ }
173
+ return null;
174
+ }
175
+ function parentFqnPredicate(parent) {
176
+ const prefix = parent + ".";
177
+ return (e) => !!e.parent && (e.parent === parent || e.parent.startsWith(prefix));
178
+ }
179
+ function ancestorsFqn(fqn) {
180
+ const path = fqn.split(".");
181
+ path.pop();
182
+ if (path.length === 0) {
183
+ return [];
184
+ }
185
+ return path.reduce((acc, part, idx) => {
186
+ if (idx === 0) {
187
+ acc.push(part);
188
+ return acc;
189
+ }
190
+ acc.unshift(`${acc[0]}.${part}`);
191
+ return acc;
192
+ }, []);
193
+ }
194
+ function compareFqnHierarchically(a, b) {
195
+ const depthA = a.split(".").length;
196
+ const depthB = b.split(".").length;
197
+ switch (true) {
198
+ case depthA > depthB: {
199
+ return 1;
200
+ }
201
+ case depthA < depthB: {
202
+ return -1;
203
+ }
204
+ default: {
205
+ return 0;
206
+ }
207
+ }
208
+ }
209
+ function compareByFqnHierarchically(a, b) {
210
+ return compareFqnHierarchically(a.id, b.id);
211
+ }
212
+ function sortByFqnHierarchically(array) {
213
+ return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
214
+ return a.fqn.length - b.fqn.length;
215
+ }).map(({ item }) => item);
216
+ }
217
+ function sortNaturalByFqn(array) {
218
+ return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
219
+ if (a.fqn.length !== b.fqn.length) {
220
+ return a.fqn.length - b.fqn.length;
221
+ }
222
+ for (let i = 0; i < a.fqn.length; i++) {
223
+ const compare = compareNatural(a.fqn[i], b.fqn[i]);
224
+ if (compare !== 0) {
225
+ return compare;
226
+ }
227
+ }
228
+ return 0;
229
+ }).map(({ item }) => item);
230
+ }
231
+
232
+ function parseWhere(where) {
233
+ if (t$1(where)) {
234
+ const op = where;
235
+ switch (true) {
236
+ case op.startsWith("tag is not #"):
237
+ return {
238
+ tag: {
239
+ neq: op.replace("tag is not #", "")
240
+ }
241
+ };
242
+ case op.startsWith("tag is #"):
243
+ return {
244
+ tag: {
245
+ eq: op.replace("tag is #", "")
246
+ }
247
+ };
248
+ case op.startsWith("kind is not "):
249
+ return {
250
+ kind: {
251
+ neq: op.replace("kind is not ", "")
252
+ }
253
+ };
254
+ case op.startsWith("kind is "):
255
+ return {
256
+ kind: {
257
+ eq: op.replace("kind is ", "")
258
+ }
259
+ };
260
+ default:
261
+ throw new Error(`Unknown where operator: ${where}`);
262
+ }
263
+ }
264
+ if (where.and) {
265
+ return {
266
+ and: m(where.and, parseWhere)
267
+ };
268
+ }
269
+ if (where.or) {
270
+ return {
271
+ or: m(where.or, parseWhere)
272
+ };
273
+ }
274
+ if (where.not) {
275
+ return {
276
+ not: parseWhere(where.not)
277
+ };
278
+ }
279
+ throw new Error(`Unknown where operator: ${where}`);
280
+ }
281
+ function $include(...args) {
282
+ return (b) => {
283
+ let expr = $expr(args[0]);
284
+ const isElement = types_index.isElementPredicateExpr(expr);
285
+ if (args.length === 2) {
286
+ const condition = args[1].where ? parseWhere(args[1].where) : void 0;
287
+ if (condition) {
288
+ expr = {
289
+ where: {
290
+ expr,
291
+ condition
292
+ }
293
+ };
294
+ }
295
+ const custom = args[1].with;
296
+ if (custom) {
297
+ if (isElement) {
298
+ expr = {
299
+ custom: {
300
+ ...custom,
301
+ expr
302
+ }
303
+ };
304
+ } else {
305
+ expr = {
306
+ customRelation: {
307
+ ...custom,
308
+ relation: expr
309
+ }
310
+ };
311
+ }
312
+ }
313
+ }
314
+ b.include(expr);
315
+ return b;
316
+ };
317
+ }
318
+ function $exclude(...args) {
319
+ return (b) => {
320
+ let expr = $expr(args[0]);
321
+ if (args.length === 2 && args[1].where) {
322
+ const condition = parseWhere(args[1].where);
323
+ expr = {
324
+ where: {
325
+ expr,
326
+ condition
327
+ }
328
+ };
329
+ }
330
+ b.exclude(expr);
331
+ return b;
332
+ };
333
+ }
334
+ function $expr(expr) {
335
+ if (!t$1(expr)) {
336
+ return expr;
337
+ }
338
+ if (expr === "*") {
339
+ return { wildcard: true };
340
+ }
341
+ if (expr.startsWith("->")) {
342
+ if (expr.endsWith("->")) {
343
+ return {
344
+ inout: $expr(expr.replace(/->/g, "").trim())
345
+ };
346
+ }
347
+ return {
348
+ incoming: $expr(expr.replace("-> ", ""))
349
+ };
350
+ }
351
+ if (expr.endsWith(" ->")) {
352
+ return {
353
+ outgoing: $expr(expr.replace(" ->", ""))
354
+ };
355
+ }
356
+ if (expr.includes(" <-> ")) {
357
+ const [source, target] = expr.split(" <-> ");
358
+ return {
359
+ source: $expr(source),
360
+ target: $expr(target),
361
+ isBidirectional: true
362
+ };
363
+ }
364
+ if (expr.includes(" -> ")) {
365
+ const [source, target] = expr.split(" -> ");
366
+ return {
367
+ source: $expr(source),
368
+ target: $expr(target)
369
+ };
370
+ }
371
+ if (expr.endsWith("._")) {
372
+ return {
373
+ expanded: expr.replace("._", "")
374
+ };
375
+ }
376
+ if (expr.endsWith(".*")) {
377
+ return {
378
+ element: expr.replace(".*", ""),
379
+ isDescedants: true
380
+ };
381
+ }
382
+ return {
383
+ element: expr,
384
+ isDescedants: false
385
+ };
386
+ }
387
+ function $style(element, { notation, ...style }) {
388
+ return (b) => b.style({
389
+ targets: (types_index.n(element) ? element : [element]).map((e) => $expr(e)),
390
+ ...notation ? { notation } : {},
391
+ style: {
392
+ ...style
393
+ }
394
+ });
395
+ }
396
+ function $autoLayout(layout) {
397
+ return (b) => b.autoLayout(layout);
398
+ }
399
+ function $rules(...rules) {
400
+ return (b) => rules.reduce((b2, rule) => rule(b2), b);
401
+ }
402
+
403
+ function builder(spec, _elements = /* @__PURE__ */ new Map(), _relations = [], _views = /* @__PURE__ */ new Map()) {
404
+ const toLikeC4Specification = () => ({
405
+ tags: spec.tags ?? [],
406
+ elements: {
407
+ ...spec.elements
408
+ },
409
+ relationships: {
410
+ ...spec.relationships
411
+ }
412
+ });
413
+ const mapLinks = (links) => {
414
+ if (!links || !i$2(links, 1)) {
415
+ return null;
416
+ }
417
+ return m(links, (l) => typeof l === "string" ? { url: l } : l);
418
+ };
419
+ const mkViewBuilder = (view) => {
420
+ const viewBuilder = {
421
+ autoLayout(autoLayout) {
422
+ view.rules.push({
423
+ direction: autoLayout
424
+ });
425
+ return viewBuilder;
426
+ },
427
+ exclude(expr) {
428
+ view.rules.push({
429
+ exclude: [expr]
430
+ });
431
+ return viewBuilder;
432
+ },
433
+ include(expr) {
434
+ view.rules.push({
435
+ include: [expr]
436
+ });
437
+ return viewBuilder;
438
+ },
439
+ style(rule) {
440
+ view.rules.push(rule);
441
+ return viewBuilder;
442
+ }
443
+ // title(title: string) {
444
+ // view.title = title
445
+ // return viewBuilder
446
+ // },
447
+ // description(description: string) {
448
+ // view.description = description
449
+ // return viewBuilder
450
+ // }
451
+ };
452
+ return viewBuilder;
453
+ };
454
+ const self = {
455
+ get Types() {
456
+ throw new Error("Types are not available in runtime");
457
+ },
458
+ clone: () => builder(
459
+ structuredClone(spec),
460
+ structuredClone(_elements),
461
+ structuredClone(_relations),
462
+ structuredClone(_views)
463
+ ),
464
+ __model: () => ({
465
+ addElement: (element) => {
466
+ const parent = parentFqn(element.id);
467
+ if (parent) {
468
+ types_index.invariant(
469
+ _elements.get(parent),
470
+ `Parent element with id "${parent}" not found for element with id "${element.id}"`
471
+ );
472
+ }
473
+ if (_elements.has(element.id)) {
474
+ throw new Error(`Element with id "${element.id}" already exists`);
475
+ }
476
+ _elements.set(element.id, element);
477
+ return self;
478
+ },
479
+ addRelation(relation) {
480
+ const sourceEl = _elements.get(relation.source);
481
+ types_index.invariant(sourceEl, `Element with id "${relation.source}" not found`);
482
+ const targetEl = _elements.get(relation.target);
483
+ types_index.invariant(targetEl, `Element with id "${relation.target}" not found`);
484
+ types_index.invariant(
485
+ !isSameHierarchy(sourceEl, targetEl),
486
+ "Cannot create relationship between elements in the same hierarchy"
487
+ );
488
+ _relations.push({
489
+ id: `rel${_relations.length + 1}`,
490
+ ...relation
491
+ });
492
+ return self;
493
+ },
494
+ /**
495
+ * Fully qualified name for nested elements
496
+ */
497
+ fqn(id) {
498
+ return id;
499
+ },
500
+ addSourcelessRelation() {
501
+ throw new Error("Can be called only in nested model");
502
+ }
503
+ }),
504
+ __views: () => ({
505
+ addView: (view) => {
506
+ if (types_index.isScopedElementView(view)) {
507
+ types_index.invariant(_elements.get(view.viewOf), `Invalid view ${view.id}, wlement with id "${view.viewOf}" not found`);
508
+ }
509
+ _views.set(view.id, view);
510
+ return self;
511
+ }
512
+ }),
513
+ build: () => ({
514
+ specification: toLikeC4Specification(),
515
+ elements: n(Array.from(_elements.entries())),
516
+ relations: l$1(_relations, (r) => [r.id, r]),
517
+ views: n(Array.from(_views.entries()))
518
+ }),
519
+ helpers: () => ({
520
+ model: {
521
+ model: (...ops) => {
522
+ return (b) => {
523
+ const v = b.__model();
524
+ for (const op of ops) {
525
+ op(v);
526
+ }
527
+ return b;
528
+ };
529
+ },
530
+ rel: (source, target, _props) => {
531
+ return (b) => {
532
+ const {
533
+ title = "",
534
+ links: _links = [],
535
+ ...props
536
+ } = defu__default(
537
+ typeof _props === "string" ? { title: _props } : { ..._props },
538
+ { title: null, links: null }
539
+ );
540
+ const links = mapLinks(_links);
541
+ b.addRelation({
542
+ source,
543
+ target,
544
+ title,
545
+ ...links && { links },
546
+ ...props
547
+ });
548
+ return b;
549
+ };
550
+ },
551
+ relTo: (target, _props) => {
552
+ return (b) => {
553
+ const {
554
+ title = "",
555
+ links: _links = [],
556
+ ...props
557
+ } = defu__default(
558
+ typeof _props === "string" ? { title: _props } : { ..._props },
559
+ { title: null, links: null }
560
+ );
561
+ const links = mapLinks(_links);
562
+ b.addSourcelessRelation({
563
+ target,
564
+ title,
565
+ ...links && { links },
566
+ ...props
567
+ });
568
+ return b;
569
+ };
570
+ },
571
+ ...i(
572
+ spec.elements,
573
+ ({ style: specStyle, ...spec2 }, kind) => (id, _props) => {
574
+ const add = (b) => {
575
+ const {
576
+ links: _links,
577
+ icon: _icon,
578
+ style,
579
+ title,
580
+ ...props
581
+ } = typeof _props === "string" ? { title: _props } : { ..._props };
582
+ const links = mapLinks(_links);
583
+ const icon = _icon ?? specStyle?.icon;
584
+ const _id = b.fqn(id);
585
+ b.addElement({
586
+ id: _id,
587
+ kind,
588
+ title: title ?? nameFromFqn(_id),
589
+ description: null,
590
+ technology: null,
591
+ tags: null,
592
+ color: specStyle?.color ?? types_index.DefaultThemeColor,
593
+ shape: specStyle?.shape ?? types_index.DefaultElementShape,
594
+ style: i$1({
595
+ border: specStyle?.border,
596
+ opacity: specStyle?.opacity,
597
+ ...style
598
+ }, l),
599
+ links,
600
+ ...icon && { icon },
601
+ ...spec2,
602
+ ...props
603
+ });
604
+ return b;
605
+ };
606
+ add.with = (...ops) => (b) => {
607
+ add(b);
608
+ const nestedBuilder = {
609
+ ...b,
610
+ fqn: (child) => `${b.fqn(id)}.${child}`,
611
+ addSourcelessRelation: (relation) => {
612
+ return b.addRelation({
613
+ ...relation,
614
+ source: b.fqn(id)
615
+ });
616
+ }
617
+ };
618
+ for (const op of ops) {
619
+ op(nestedBuilder);
620
+ }
621
+ return b;
622
+ };
623
+ return add;
624
+ }
625
+ )
626
+ },
627
+ views: {
628
+ views: (...ops) => {
629
+ return (b) => {
630
+ const v = b.__views();
631
+ for (const op of ops) {
632
+ op(v);
633
+ }
634
+ return b;
635
+ };
636
+ },
637
+ view: (id, _props, builder2) => {
638
+ if (t(_props)) {
639
+ builder2 = _props;
640
+ _props = {};
641
+ }
642
+ return (b) => {
643
+ const {
644
+ links: _links = [],
645
+ title = null,
646
+ ...props
647
+ } = typeof _props === "string" ? { title: _props } : { ..._props };
648
+ const links = mapLinks(_links);
649
+ const view = {
650
+ id,
651
+ __: "element",
652
+ title,
653
+ description: null,
654
+ tags: null,
655
+ rules: [],
656
+ links,
657
+ customColorDefinitions: {},
658
+ ...props
659
+ };
660
+ b.addView(view);
661
+ if (builder2) {
662
+ builder2(mkViewBuilder(view));
663
+ }
664
+ return b;
665
+ };
666
+ },
667
+ viewOf: (id, viewOf, _props, builder2) => {
668
+ if (t(_props)) {
669
+ builder2 = _props;
670
+ _props = {};
671
+ }
672
+ return (b) => {
673
+ const {
674
+ links: _links = [],
675
+ title = null,
676
+ ...props
677
+ } = typeof _props === "string" ? { title: _props } : { ..._props };
678
+ const links = mapLinks(_links);
679
+ const view = {
680
+ id,
681
+ __: "element",
682
+ viewOf,
683
+ title,
684
+ description: null,
685
+ tags: null,
686
+ rules: [],
687
+ links,
688
+ customColorDefinitions: {},
689
+ ...props
690
+ };
691
+ b.addView(view);
692
+ if (builder2) {
693
+ builder2(mkViewBuilder(view));
694
+ }
695
+ return b;
696
+ };
697
+ },
698
+ $autoLayout,
699
+ $exclude,
700
+ $expr,
701
+ $include,
702
+ $rules,
703
+ $style
704
+ }
705
+ }),
706
+ with: (...ops) => {
707
+ return ops.reduce((b, op) => op(b), self).clone();
708
+ }
709
+ };
710
+ return self;
711
+ }
712
+ exports.Builder = void 0;
713
+ ((Builder2) => {
714
+ function forSpecification(spec) {
715
+ const b = builder(spec);
716
+ return {
717
+ ...b.helpers(),
718
+ builder: b
719
+ };
720
+ }
721
+ Builder2.forSpecification = forSpecification;
722
+ })(exports.Builder || (exports.Builder = {}));
4
723
 
5
724
  const { min: min$4, max: max$4 } = Math;
6
725
 
@@ -3656,18 +4375,8 @@ function computeColorValues(color) {
3656
4375
  }
3657
4376
  }
3658
4377
 
3659
- function r$1(...n){return types_index.u(Object.values,n)}
3660
-
3661
- function i(...e){return types_index.u(r,e)}var r=(e,t)=>e.length>=t;
3662
-
3663
- function o(r,n){let e=Math.ceil(r),t=Math.floor(n);if(t<e)throw new RangeError(`randomInteger: The range [${r.toString()},${n.toString()}] contains no integer`);return Math.floor(Math.random()*(t-e+1)+e)}
3664
-
3665
- function t(r){return typeof r=="string"}
3666
-
3667
- function n(e){return !!e}
3668
-
3669
4378
  function getId(element) {
3670
- return t(element) ? element : element.id;
4379
+ return t$1(element) ? element : element.id;
3671
4380
  }
3672
4381
 
3673
4382
  class LikeC4DiagramModel {
@@ -3906,204 +4615,6 @@ class LikeC4DiagramModel {
3906
4615
  LikeC4DiagramModel2.Connection = Connection;
3907
4616
  })(LikeC4DiagramModel || (LikeC4DiagramModel = {}));
3908
4617
 
3909
- function getDefaultExportFromCjs (x) {
3910
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
3911
- }
3912
-
3913
- var naturalCompareLite = {exports: {}};
3914
-
3915
- var hasRequiredNaturalCompareLite;
3916
-
3917
- function requireNaturalCompareLite () {
3918
- if (hasRequiredNaturalCompareLite) return naturalCompareLite.exports;
3919
- hasRequiredNaturalCompareLite = 1;
3920
- /*
3921
- * @version 1.4.0
3922
- * @date 2015-10-26
3923
- * @stability 3 - Stable
3924
- * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
3925
- * @license MIT License
3926
- */
3927
-
3928
-
3929
- var naturalCompare = function(a, b) {
3930
- var i, codeA
3931
- , codeB = 1
3932
- , posA = 0
3933
- , posB = 0
3934
- , alphabet = String.alphabet;
3935
-
3936
- function getCode(str, pos, code) {
3937
- if (code) {
3938
- for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
3939
- return +str.slice(pos - 1, i)
3940
- }
3941
- code = alphabet && alphabet.indexOf(str.charAt(pos));
3942
- return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code
3943
- : code < 46 ? 65 // -
3944
- : code < 48 ? code - 1
3945
- : code < 58 ? code + 18 // 0-9
3946
- : code < 65 ? code - 11
3947
- : code < 91 ? code + 11 // A-Z
3948
- : code < 97 ? code - 37
3949
- : code < 123 ? code + 5 // a-z
3950
- : code - 63
3951
- }
3952
-
3953
-
3954
- if ((a+="") != (b+="")) for (;codeB;) {
3955
- codeA = getCode(a, posA++);
3956
- codeB = getCode(b, posB++);
3957
-
3958
- if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
3959
- codeA = getCode(a, posA, posA);
3960
- codeB = getCode(b, posB, posA = i);
3961
- posB = i;
3962
- }
3963
-
3964
- if (codeA != codeB) return (codeA < codeB) ? -1 : 1
3965
- }
3966
- return 0
3967
- };
3968
-
3969
- try {
3970
- naturalCompareLite.exports = naturalCompare;
3971
- } catch (e) {
3972
- String.naturalCompare = naturalCompare;
3973
- }
3974
- return naturalCompareLite.exports;
3975
- }
3976
-
3977
- var naturalCompareLiteExports = requireNaturalCompareLite();
3978
- const compare = /*@__PURE__*/getDefaultExportFromCjs(naturalCompareLiteExports);
3979
-
3980
- function compareNatural(a, b) {
3981
- if (a === b) return 0;
3982
- if (t(a)) {
3983
- if (t(b)) {
3984
- return compare(a, b);
3985
- }
3986
- return 1;
3987
- }
3988
- return t(b) ? -1 : 0;
3989
- }
3990
-
3991
- function isString(value) {
3992
- return value != null && typeof value === "string";
3993
- }
3994
- function isNonEmptyArray(arr) {
3995
- return !!arr && Array.isArray(arr) && arr.length > 0;
3996
- }
3997
-
3998
- function nameFromFqn(fqn) {
3999
- const lastDot = fqn.lastIndexOf(".");
4000
- if (lastDot > 0) {
4001
- return fqn.slice(lastDot + 1);
4002
- } else {
4003
- return fqn;
4004
- }
4005
- }
4006
- function isAncestor(...args) {
4007
- const ancestor = isString(args[0]) ? args[0] : args[0].id;
4008
- const another = isString(args[1]) ? args[1] : args[1].id;
4009
- return another.startsWith(ancestor + ".");
4010
- }
4011
- function isSameHierarchy(one, another) {
4012
- const first = isString(one) ? one : one.id;
4013
- const second = isString(another) ? another : another.id;
4014
- return first === second || second.startsWith(first + ".") || first.startsWith(second + ".");
4015
- }
4016
- function isDescendantOf(ancestors) {
4017
- const predicates = ancestors.flatMap((a) => [(e) => e.id === a.id, (e) => isAncestor(a, e)]);
4018
- return (e) => predicates.some((p) => p(e));
4019
- }
4020
- function notDescendantOf(ancestors) {
4021
- const isDescendant = isDescendantOf(ancestors);
4022
- return (e) => !isDescendant(e);
4023
- }
4024
- function commonAncestor(first, second) {
4025
- const parentA = parentFqn(first);
4026
- const parentB = parentFqn(second);
4027
- if (parentA === parentB) {
4028
- return parentA;
4029
- }
4030
- if (!parentA || !parentB) {
4031
- return null;
4032
- }
4033
- const a = first.split(".");
4034
- const b = second.split(".");
4035
- let ancestor = null;
4036
- while (a.length > 1 && b.length > 1 && !!a[0] && a[0] === b[0]) {
4037
- ancestor = ancestor ? `${ancestor}.${a[0]}` : a[0];
4038
- a.shift();
4039
- b.shift();
4040
- }
4041
- return ancestor;
4042
- }
4043
- function parentFqn(fqn) {
4044
- const lastDot = fqn.lastIndexOf(".");
4045
- if (lastDot > 0) {
4046
- return fqn.slice(0, lastDot);
4047
- }
4048
- return null;
4049
- }
4050
- function parentFqnPredicate(parent) {
4051
- const prefix = parent + ".";
4052
- return (e) => !!e.parent && (e.parent === parent || e.parent.startsWith(prefix));
4053
- }
4054
- function ancestorsFqn(fqn) {
4055
- const path = fqn.split(".");
4056
- path.pop();
4057
- if (path.length === 0) {
4058
- return [];
4059
- }
4060
- return path.reduce((acc, part, idx) => {
4061
- if (idx === 0) {
4062
- acc.push(part);
4063
- return acc;
4064
- }
4065
- acc.unshift(`${acc[0]}.${part}`);
4066
- return acc;
4067
- }, []);
4068
- }
4069
- function compareFqnHierarchically(a, b) {
4070
- const depthA = a.split(".").length;
4071
- const depthB = b.split(".").length;
4072
- switch (true) {
4073
- case depthA > depthB: {
4074
- return 1;
4075
- }
4076
- case depthA < depthB: {
4077
- return -1;
4078
- }
4079
- default: {
4080
- return 0;
4081
- }
4082
- }
4083
- }
4084
- function compareByFqnHierarchically(a, b) {
4085
- return compareFqnHierarchically(a.id, b.id);
4086
- }
4087
- function sortByFqnHierarchically(array) {
4088
- return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
4089
- return a.fqn.length - b.fqn.length;
4090
- }).map(({ item }) => item);
4091
- }
4092
- function sortNaturalByFqn(array) {
4093
- return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
4094
- if (a.fqn.length !== b.fqn.length) {
4095
- return a.fqn.length - b.fqn.length;
4096
- }
4097
- for (let i = 0; i < a.fqn.length; i++) {
4098
- const compare = compareNatural(a.fqn[i], b.fqn[i]);
4099
- if (compare !== 0) {
4100
- return compare;
4101
- }
4102
- }
4103
- return 0;
4104
- }).map(({ item }) => item);
4105
- }
4106
-
4107
4618
  class LikeC4ViewModel {
4108
4619
  constructor(view, model) {
4109
4620
  this.view = view;
@@ -4207,7 +4718,7 @@ class LikeC4ViewModel {
4207
4718
  });
4208
4719
  }
4209
4720
  incomers(element, filter = "all") {
4210
- return this.incoming(element, filter).map((r) => r.source);
4721
+ return [...new Set(this.incoming(element, filter).map((r) => r.source))];
4211
4722
  }
4212
4723
  /**
4213
4724
  * Outgoing relationships from the element and its descendants
@@ -4226,7 +4737,7 @@ class LikeC4ViewModel {
4226
4737
  });
4227
4738
  }
4228
4739
  outgoers(element, filter = "all") {
4229
- return this.outgoing(element, filter).map((r) => r.target);
4740
+ return [...new Set(this.outgoing(element, filter).map((r) => r.target))];
4230
4741
  }
4231
4742
  }
4232
4743
  ((LikeC4ViewModel2) => {
@@ -4328,7 +4839,7 @@ class LikeC4ViewModel {
4328
4839
  })(LikeC4ViewModel || (LikeC4ViewModel = {}));
4329
4840
 
4330
4841
  class LikeC4Model {
4331
- constructor(type, sourcemodel, elements, relations) {
4842
+ constructor(type, sourcemodel, elements, relations, views, ViewModelClass) {
4332
4843
  this.type = type;
4333
4844
  this.sourcemodel = sourcemodel;
4334
4845
  for (const el of elements) {
@@ -4337,6 +4848,9 @@ class LikeC4Model {
4337
4848
  for (const rel of relations) {
4338
4849
  this.addRelation(rel);
4339
4850
  }
4851
+ this._views = new Map(
4852
+ r$1(views).map((view) => [view.id, new ViewModelClass(view, this)])
4853
+ );
4340
4854
  }
4341
4855
  _elements = /* @__PURE__ */ new Map();
4342
4856
  // Parent element for given FQN
@@ -4352,37 +4866,7 @@ class LikeC4Model {
4352
4866
  // Relationships inside the element, among descendants
4353
4867
  _internal = /* @__PURE__ */ new Map();
4354
4868
  _cacheAscendingSiblings = /* @__PURE__ */ new Map();
4355
- _views = /* @__PURE__ */ new Map();
4356
- static create(source) {
4357
- if (source.__ === "layouted") {
4358
- return LikeC4Model.layouted(source);
4359
- }
4360
- return LikeC4Model.computed(source);
4361
- }
4362
- static computed(source) {
4363
- const instance = new LikeC4Model(
4364
- "computed",
4365
- source,
4366
- r$1(source.elements),
4367
- r$1(source.relations)
4368
- );
4369
- for (const view of r$1(source.views)) {
4370
- instance._views.set(view.id, new LikeC4ViewModel(view, instance));
4371
- }
4372
- return instance;
4373
- }
4374
- static layouted(source) {
4375
- const instance = new LikeC4Model(
4376
- "layouted",
4377
- source,
4378
- r$1(source.elements),
4379
- r$1(source.relations)
4380
- );
4381
- for (const view of r$1(source.views)) {
4382
- instance._views.set(view.id, new LikeC4DiagramModel(view, instance));
4383
- }
4384
- return instance;
4385
- }
4869
+ _views;
4386
4870
  /**
4387
4871
  * Returns the root elements of the model.
4388
4872
  */
@@ -4455,7 +4939,7 @@ class LikeC4Model {
4455
4939
  * (from closest to root)
4456
4940
  */
4457
4941
  ancestors(element) {
4458
- let id = t(element) ? element : element.id;
4942
+ let id = t$1(element) ? element : element.id;
4459
4943
  const result = [];
4460
4944
  let parent;
4461
4945
  while (parent = this._parents.get(id)) {
@@ -4493,7 +4977,7 @@ class LikeC4Model {
4493
4977
  * Source elements of incoming relationships
4494
4978
  */
4495
4979
  incomers(element, filter = "all") {
4496
- return this.incoming(element, filter).map((r) => r.source);
4980
+ return [...new Set(this.incoming(element, filter).map((r) => r.source))];
4497
4981
  }
4498
4982
  /**
4499
4983
  * Outgoing relationships from the element and its descendants
@@ -4516,7 +5000,7 @@ class LikeC4Model {
4516
5000
  * Target elements of outgoing relationships
4517
5001
  */
4518
5002
  outgoers(element, filter = "all") {
4519
- return this.outgoing(element, filter).map((r) => r.target);
5003
+ return [...new Set(this.outgoing(element, filter).map((r) => r.target))];
4520
5004
  }
4521
5005
  /**
4522
5006
  * Relationships inside the element, among descendants
@@ -4623,6 +5107,35 @@ class LikeC4Model {
4623
5107
  }
4624
5108
  }
4625
5109
  ((LikeC4Model2) => {
5110
+ function create(source) {
5111
+ if (source.__ === "layouted") {
5112
+ return LikeC4Model2.layouted(source);
5113
+ }
5114
+ return LikeC4Model2.computed(source);
5115
+ }
5116
+ LikeC4Model2.create = create;
5117
+ function computed(source) {
5118
+ return new LikeC4Model2(
5119
+ "computed",
5120
+ source,
5121
+ r$1(source.elements),
5122
+ r$1(source.relations),
5123
+ source.views,
5124
+ LikeC4ViewModel
5125
+ );
5126
+ }
5127
+ LikeC4Model2.computed = computed;
5128
+ function layouted(source) {
5129
+ return new LikeC4Model2(
5130
+ "layouted",
5131
+ source,
5132
+ r$1(source.elements),
5133
+ r$1(source.relations),
5134
+ source.views,
5135
+ LikeC4DiagramModel
5136
+ );
5137
+ }
5138
+ LikeC4Model2.layouted = layouted;
4626
5139
  function isModel(model) {
4627
5140
  return model instanceof LikeC4Model2;
4628
5141
  }
@@ -4664,7 +5177,7 @@ class LikeC4Model {
4664
5177
  return this.relationship.metadata?.[key] ?? defaultValue;
4665
5178
  }
4666
5179
  hasMetadata(key) {
4667
- return n(this.relationship.metadata?.[key]);
5180
+ return n$1(this.relationship.metadata?.[key]);
4668
5181
  }
4669
5182
  }
4670
5183
  LikeC4Model2.Relationship = Relationship;
@@ -4704,7 +5217,7 @@ class LikeC4Model {
4704
5217
  return this.element.metadata?.[key] ?? defaultValue;
4705
5218
  }
4706
5219
  hasMetadata(key) {
4707
- return n(this.element.metadata?.[key]);
5220
+ return n$1(this.element.metadata?.[key]);
4708
5221
  }
4709
5222
  ancestors() {
4710
5223
  return this.model.ancestors(this);
@@ -4718,6 +5231,12 @@ class LikeC4Model {
4718
5231
  children() {
4719
5232
  return this.model.children(this);
4720
5233
  }
5234
+ /**
5235
+ * All views 'view of' current element
5236
+ */
5237
+ viewsOf() {
5238
+ return this.model.views().filter((v) => v.viewOf?.id === this.id);
5239
+ }
4721
5240
  /**
4722
5241
  * Views that contain this element
4723
5242
  */
@@ -4739,6 +5258,13 @@ class LikeC4Model {
4739
5258
  internal() {
4740
5259
  return this.model.internal(this);
4741
5260
  }
5261
+ /**
5262
+ * Resolve siblings of the element and siblings of ancestors
5263
+ * (from closest to root)
5264
+ */
5265
+ ascendingSiblings() {
5266
+ return this.model.ascendingSiblings(this);
5267
+ }
4742
5268
  // public *descendants(): IterableIterator<LikeC4Element> {
4743
5269
  // return
4744
5270
  // }
@@ -4750,7 +5276,7 @@ const DELAY = "LIKEC4_DELAY";
4750
5276
  function delay(...args) {
4751
5277
  let ms = 100;
4752
5278
  if (args.length === 2) {
4753
- ms = o(args[0], args[1]);
5279
+ ms = o$2(args[0], args[1]);
4754
5280
  } else if (args.length === 1) {
4755
5281
  ms = args[0];
4756
5282
  }
@@ -4848,7 +5374,7 @@ exports.compareRelations = compareRelations;
4848
5374
  exports.computeColorValues = computeColorValues;
4849
5375
  exports.defaultTheme = defaultTheme;
4850
5376
  exports.delay = delay;
4851
- exports.hasAtLeast = i;
5377
+ exports.hasAtLeast = i$2;
4852
5378
  exports.isAncestor = isAncestor;
4853
5379
  exports.isDescendantOf = isDescendantOf;
4854
5380
  exports.isNonEmptyArray = isNonEmptyArray;