@likec4/core 0.6.3 → 0.18.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 (42) hide show
  1. package/dist/colors.d.ts +79 -0
  2. package/dist/colors.js +94 -0
  3. package/dist/compute-view/EdgeBuilder.d.ts +1 -0
  4. package/dist/compute-view/EdgeBuilder.js +1 -1
  5. package/dist/compute-view/compute-ctx.d.ts +18 -0
  6. package/dist/compute-view/compute-ctx.js +25 -0
  7. package/dist/compute-view/{compute.element-view.d.ts → compute-element-view.d.ts} +2 -2
  8. package/dist/compute-view/compute-element-view.js +416 -0
  9. package/dist/compute-view/{compute-view.d.ts → compute.d.ts} +2 -2
  10. package/dist/compute-view/{compute-view.js → compute.js} +1 -1
  11. package/dist/compute-view/index.d.ts +2 -1
  12. package/dist/compute-view/index.js +1 -1
  13. package/dist/compute-view/utils/anyPossibleRelations.d.ts +1 -0
  14. package/dist/compute-view/utils/sortNodes.d.ts +1 -0
  15. package/dist/index.d.ts +4 -2
  16. package/dist/index.js +2 -1
  17. package/dist/model-index/{model-index.d.ts → ModelIndex.d.ts} +1 -0
  18. package/dist/model-index/{model-index.js → ModelIndex.js} +3 -3
  19. package/dist/model-index/index.d.ts +2 -1
  20. package/dist/model-index/index.js +1 -1
  21. package/dist/types/computed-view.d.ts +1 -0
  22. package/dist/types/diagram.d.ts +7 -0
  23. package/dist/types/element.d.ts +3 -2
  24. package/dist/types/expression.d.ts +1 -0
  25. package/dist/types/index.d.ts +1 -0
  26. package/dist/types/model.d.ts +1 -0
  27. package/dist/types/opaque.d.ts +1 -0
  28. package/dist/types/relation.d.ts +1 -0
  29. package/dist/types/view.d.ts +1 -0
  30. package/dist/utils/compute-node-levels.d.ts +8 -0
  31. package/dist/utils/compute-node-levels.js +31 -0
  32. package/dist/utils/fqn.d.ts +3 -0
  33. package/dist/utils/fqn.js +22 -1
  34. package/dist/utils/guards.d.ts +1 -0
  35. package/dist/utils/index.d.ts +2 -0
  36. package/dist/utils/index.js +1 -0
  37. package/dist/utils/relations.d.ts +3 -1
  38. package/dist/utils/relations.js +10 -4
  39. package/package.json +31 -21
  40. package/dist/compute-view/compute.element-view.js +0 -168
  41. package/dist/compute-view/utils/evaluate-expression.d.ts +0 -10
  42. package/dist/compute-view/utils/evaluate-expression.js +0 -186
@@ -0,0 +1,79 @@
1
+ export interface ElementColors {
2
+ fill: string;
3
+ stroke: string;
4
+ hiContrast: string;
5
+ loContrast: string;
6
+ }
7
+ export declare const RelationColors: {
8
+ readonly lineColor: "#a3a3a3";
9
+ readonly labelColor: "#d4d4d4";
10
+ };
11
+ export declare const Colors: {
12
+ readonly primary: {
13
+ fill: string;
14
+ stroke: string;
15
+ hiContrast: string;
16
+ loContrast: string;
17
+ };
18
+ readonly blue: {
19
+ fill: string;
20
+ stroke: string;
21
+ hiContrast: string;
22
+ loContrast: string;
23
+ };
24
+ readonly secondary: {
25
+ fill: string;
26
+ stroke: string;
27
+ hiContrast: string;
28
+ loContrast: string;
29
+ };
30
+ readonly sky: {
31
+ fill: string;
32
+ stroke: string;
33
+ hiContrast: string;
34
+ loContrast: string;
35
+ };
36
+ readonly muted: {
37
+ fill: string;
38
+ stroke: string;
39
+ hiContrast: string;
40
+ loContrast: string;
41
+ };
42
+ readonly slate: {
43
+ fill: string;
44
+ stroke: string;
45
+ hiContrast: string;
46
+ loContrast: string;
47
+ };
48
+ readonly gray: {
49
+ readonly fill: "#737373";
50
+ readonly stroke: "#525252";
51
+ readonly hiContrast: "#fafafa";
52
+ readonly loContrast: "#e5e5e5";
53
+ };
54
+ readonly red: {
55
+ readonly fill: "#ef4444";
56
+ readonly stroke: "#dc2626";
57
+ readonly hiContrast: "#fef2f2";
58
+ readonly loContrast: "#fecaca";
59
+ };
60
+ readonly green: {
61
+ readonly fill: "#16a34a";
62
+ readonly stroke: "#15803d";
63
+ readonly hiContrast: "#f0fdf4";
64
+ readonly loContrast: "#bbf7d0";
65
+ };
66
+ readonly amber: {
67
+ readonly fill: "#d97706";
68
+ readonly stroke: "#b45309";
69
+ readonly hiContrast: "#fffbeb";
70
+ readonly loContrast: "#fde68a";
71
+ };
72
+ readonly indigo: {
73
+ readonly fill: "#6366f1";
74
+ readonly stroke: "#4f46e5";
75
+ readonly hiContrast: "#eef2ff";
76
+ readonly loContrast: "#c7d2fe";
77
+ };
78
+ };
79
+ //# sourceMappingURL=colors.d.ts.map
package/dist/colors.js ADDED
@@ -0,0 +1,94 @@
1
+ const blue = {
2
+ // fill: colors.blue[500],
3
+ // stroke: colors.blue[600],
4
+ // hiContrast: colors.blue[50],
5
+ // loContrast: colors.blue[100],
6
+ fill: '#3b82f6',
7
+ stroke: '#2563eb',
8
+ hiContrast: '#eff6ff',
9
+ loContrast: '#dbeafe'
10
+ };
11
+ const sky = {
12
+ // fill: colors.sky[600],
13
+ // stroke: colors.sky[700],
14
+ // hiContrast: colors.sky[50],
15
+ // loContrast: colors.sky[100],
16
+ fill: '#0284c7',
17
+ stroke: '#0369a1',
18
+ hiContrast: '#f0f9ff',
19
+ loContrast: '#e0f2fe'
20
+ };
21
+ const slate = {
22
+ // fill: colors.slate[500],
23
+ // stroke: colors.slate[600],
24
+ // hiContrast: colors.slate[50],
25
+ // loContrast: colors.slate[200],
26
+ fill: '#64748b',
27
+ stroke: '#475569',
28
+ hiContrast: '#f8fafc',
29
+ loContrast: '#e2e8f0'
30
+ };
31
+ export const RelationColors = {
32
+ // lineColor: colors.neutral[400],
33
+ // labelColor: colors.neutral[300],
34
+ lineColor: '#a3a3a3',
35
+ labelColor: '#d4d4d4',
36
+ };
37
+ export const Colors = {
38
+ primary: blue,
39
+ blue,
40
+ secondary: sky,
41
+ sky,
42
+ muted: slate,
43
+ slate,
44
+ gray: {
45
+ // fill: colors.neutral[500],
46
+ // stroke: colors.neutral[600],
47
+ // hiContrast: colors.neutral[50],
48
+ // loContrast: colors.neutral[200],
49
+ fill: '#737373',
50
+ stroke: '#525252',
51
+ hiContrast: '#fafafa',
52
+ loContrast: '#e5e5e5'
53
+ },
54
+ red: {
55
+ // fill: colors.red[500],
56
+ // stroke: colors.red[600],
57
+ // hiContrast: colors.red[50],
58
+ // loContrast: colors.red[200],
59
+ fill: '#ef4444',
60
+ stroke: '#dc2626',
61
+ hiContrast: '#fef2f2',
62
+ loContrast: '#fecaca'
63
+ },
64
+ green: {
65
+ // fill: colors.green[600],
66
+ // stroke: colors.green[700],
67
+ // hiContrast: colors.green[50],
68
+ // loContrast: colors.green[200],
69
+ fill: '#16a34a',
70
+ stroke: '#15803d',
71
+ hiContrast: '#f0fdf4',
72
+ loContrast: '#bbf7d0'
73
+ },
74
+ amber: {
75
+ // fill: colors.amber[600],
76
+ // stroke: colors.amber[700],
77
+ // hiContrast: colors.amber[50],
78
+ // loContrast: colors.amber[200],
79
+ fill: '#d97706',
80
+ stroke: '#b45309',
81
+ hiContrast: '#fffbeb',
82
+ loContrast: '#fde68a'
83
+ },
84
+ indigo: {
85
+ // fill: colors.indigo[500],
86
+ // stroke: colors.indigo[600],
87
+ // hiContrast: colors.indigo[50],
88
+ // loContrast: colors.indigo[200],
89
+ fill: '#6366f1',
90
+ stroke: '#4f46e5',
91
+ hiContrast: '#eef2ff',
92
+ loContrast: '#c7d2fe'
93
+ }
94
+ };
@@ -5,3 +5,4 @@ export declare class EdgeBuilder {
5
5
  add(source: Fqn, target: Fqn, relation: Relation): this;
6
6
  build(): ComputedEdge[];
7
7
  }
8
+ //# sourceMappingURL=EdgeBuilder.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { equals, head, keys, pluck, reject } from 'rambdax';
2
- import { commonAncestor, compareFqnHierarchically } from '../utils/fqn';
2
+ import { commonAncestor } from '../utils/fqn';
3
3
  import { compareRelations } from '../utils/relations';
4
4
  export class EdgeBuilder {
5
5
  _relationsObj = {};
@@ -0,0 +1,18 @@
1
+ import type { ModelIndex } from '../model-index';
2
+ import type { Fqn, Element, Relation } from '../types';
3
+ export type ComputeCtxPatch = {
4
+ elements?: Element[];
5
+ relations?: Relation[];
6
+ implicits?: Element[];
7
+ };
8
+ export declare class ComputeCtx {
9
+ index: ModelIndex;
10
+ root: Fqn | null;
11
+ elements: Set<Element>;
12
+ relations: Set<Relation>;
13
+ implicits: Set<Element>;
14
+ constructor(index: ModelIndex, root: Fqn | null, elements?: Set<Element>, relations?: Set<Relation>, implicits?: Set<Element>);
15
+ include({ elements, relations, implicits }: ComputeCtxPatch): ComputeCtx;
16
+ exclude({ elements, relations, implicits }: ComputeCtxPatch): ComputeCtx;
17
+ }
18
+ //# sourceMappingURL=compute-ctx.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { difference } from 'rambdax';
2
+ export class ComputeCtx {
3
+ index;
4
+ root;
5
+ elements;
6
+ relations;
7
+ implicits;
8
+ constructor(index, root, elements = new Set(), relations = new Set(), implicits = new Set()) {
9
+ this.index = index;
10
+ this.root = root;
11
+ this.elements = elements;
12
+ this.relations = relations;
13
+ this.implicits = implicits;
14
+ }
15
+ include({ elements, relations, implicits }) {
16
+ return new ComputeCtx(this.index, this.root, elements ? new Set([...this.elements, ...elements]) : this.elements, relations ? new Set([...this.relations, ...relations]) : this.relations, implicits ? new Set([...this.implicits, ...implicits]) : this.implicits);
17
+ }
18
+ exclude({ elements, relations, implicits }) {
19
+ let newImplicits = implicits ? new Set(difference([...this.implicits], implicits)) : this.implicits;
20
+ if (elements) {
21
+ newImplicits = new Set(difference([...newImplicits], elements));
22
+ }
23
+ return new ComputeCtx(this.index, this.root, elements ? new Set(difference([...this.elements], elements)) : this.elements, relations ? new Set(difference([...this.relations], relations)) : this.relations, newImplicits);
24
+ }
25
+ }
@@ -1,4 +1,4 @@
1
1
  import type { ModelIndex } from '../model-index';
2
- import { type ElementView } from '../types';
3
- import type { ComputedView } from '../types/computed-view';
2
+ import { type ElementView, type ComputedView } from '../types';
4
3
  export declare function computeElementView(view: ElementView, index: ModelIndex): ComputedView;
4
+ //# sourceMappingURL=compute-element-view.d.ts.map
@@ -0,0 +1,416 @@
1
+ import { anyPass, filter, head, uniq } from 'rambdax';
2
+ import { DefaultThemeColor, DefaultElementShape } from '../types';
3
+ import * as Expression from '../types/expression';
4
+ import { isViewRuleAutoLayout, isViewRuleExpression, isViewRuleStyle } from '../types/view';
5
+ import { compareByFqnHierarchically, failExpectedNever, ignoreNeverInRuntime, isAncestor, isSameHierarchy, parentFqn, Relations } from '../utils';
6
+ import { hasRelation, isAnyInOut, isBetween, isIncoming, isInside, isOutgoing } from '../utils/relations';
7
+ import { EdgeBuilder } from './EdgeBuilder';
8
+ import { sortNodes } from './utils/sortNodes';
9
+ import { ComputeCtx } from './compute-ctx';
10
+ import { anyPossibleRelations } from './utils/anyPossibleRelations';
11
+ import invariant from 'tiny-invariant';
12
+ function transformToNodes(elementsIterator, index, currentViewid) {
13
+ return Array.from(elementsIterator)
14
+ .sort(compareByFqnHierarchically)
15
+ .reduce((map, { id, title, color, shape, description }) => {
16
+ let parent = parentFqn(id);
17
+ while (parent) {
18
+ if (map.has(parent)) {
19
+ break;
20
+ }
21
+ parent = parentFqn(parent);
22
+ }
23
+ const navigateTo = head(index.defaultViewOf(id).filter(v => v !== currentViewid));
24
+ if (parent) {
25
+ const parentNd = map.get(parent);
26
+ invariant(parentNd, `parent node ${parent} not found`);
27
+ parentNd.children.push(id);
28
+ }
29
+ const node = {
30
+ id,
31
+ parent,
32
+ title,
33
+ color: color ?? DefaultThemeColor,
34
+ shape: shape ?? DefaultElementShape,
35
+ children: [],
36
+ ...(description ? { description } : {}),
37
+ ...(navigateTo ? { navigateTo } : {})
38
+ };
39
+ map.set(id, node);
40
+ return map;
41
+ }, new Map());
42
+ }
43
+ function applyViewRuleStyles(rules, nodes) {
44
+ for (const rule of rules) {
45
+ const predicates = [];
46
+ if (!rule.style.color && !rule.style.shape) {
47
+ // skip empty
48
+ continue;
49
+ }
50
+ for (const target of rule.targets) {
51
+ if (Expression.isWildcard(target)) {
52
+ predicates.push(() => true);
53
+ break;
54
+ }
55
+ if (Expression.isElementRef(target)) {
56
+ const { element, isDescedants } = target;
57
+ predicates.push(isDescedants ? n => n.id.startsWith(element + '.') : n => n.id === element);
58
+ continue;
59
+ }
60
+ failExpectedNever(target);
61
+ }
62
+ filter(anyPass(predicates), nodes).forEach(n => {
63
+ n.shape = rule.style.shape ?? n.shape;
64
+ n.color = rule.style.color ?? n.color;
65
+ });
66
+ }
67
+ return nodes;
68
+ }
69
+ const includeElementRef = (ctx, expr) => {
70
+ const elements = expr.isDescedants
71
+ ? ctx.index.children(expr.element)
72
+ : [ctx.index.find(expr.element)];
73
+ const filters = [];
74
+ if (expr.isDescedants) {
75
+ filters.push(Relations.isInside(expr.element));
76
+ }
77
+ const ctxElements = uniq([...ctx.elements, ...ctx.implicits]);
78
+ const excludeImplicits = [];
79
+ for (const el of elements) {
80
+ if (ctx.root && ctx.root !== el.id && !isAncestor(el.id, ctx.root)) {
81
+ excludeImplicits.push(...[...ctx.implicits].filter(impl => isAncestor(el.id, impl.id)));
82
+ }
83
+ for (const ctxEl of ctxElements) {
84
+ if (!isSameHierarchy(el, ctxEl)) {
85
+ filters.push(Relations.isAnyBetween(el.id, ctxEl.id));
86
+ }
87
+ }
88
+ }
89
+ const relations = filters.length ? ctx.index.filterRelations(anyPass(filters)) : [];
90
+ if (excludeImplicits.length == 0) {
91
+ return ctx.include({ elements, relations });
92
+ }
93
+ return ctx.include({ elements, relations }).exclude({ implicits: excludeImplicits });
94
+ };
95
+ const excludeElementRef = (ctx, expr) => {
96
+ const elements = expr.isDescedants
97
+ ? ctx.index.children(expr.element)
98
+ : [ctx.index.find(expr.element)];
99
+ const elementsIds = elements.map(e => e.id);
100
+ const relations = [...ctx.relations].filter(r => elementsIds.includes(r.source) || elementsIds.includes(r.target));
101
+ return ctx.exclude({ elements, relations });
102
+ };
103
+ const includeWildcardRef = (ctx, _expr) => {
104
+ const { root } = ctx;
105
+ if (root) {
106
+ const elements = [ctx.index.find(root), ...ctx.index.children(root)];
107
+ // All neighbors that may have relations with root or its children
108
+ const allImplicits = [
109
+ ...ctx.index.siblings(root),
110
+ ...ctx.index.ancestors(root).flatMap(a => [...ctx.index.siblings(a.id)])
111
+ ];
112
+ const allInOut = ctx.index.filterRelations(isAnyInOut(root));
113
+ // Neighbors that have relations with root or its children
114
+ const implicits = [];
115
+ const relations = [];
116
+ for (const implicit of allImplicits) {
117
+ const relationsWithImplicit = allInOut.filter(isAnyInOut(implicit.id));
118
+ if (relationsWithImplicit.length) {
119
+ implicits.push(implicit);
120
+ relations.push(...relationsWithImplicit);
121
+ }
122
+ }
123
+ return ctx.include({
124
+ elements,
125
+ relations: [
126
+ ...ctx.index.filterRelations(isInside(root)),
127
+ ...relations,
128
+ ],
129
+ implicits: implicits
130
+ });
131
+ }
132
+ else {
133
+ const elements = ctx.index.rootElements();
134
+ if (elements.length <= 1) {
135
+ return new ComputeCtx(ctx.index, ctx.root, new Set(elements));
136
+ }
137
+ const predicates = [];
138
+ for (const [source, target] of anyPossibleRelations(elements)) {
139
+ predicates.push(Relations.isAnyBetween(source.id, target.id));
140
+ }
141
+ const relations = predicates.length ? ctx.index.filterRelations(anyPass(predicates)) : [];
142
+ return new ComputeCtx(ctx.index, ctx.root, new Set(elements), new Set(relations));
143
+ }
144
+ };
145
+ const excludeWildcardRef = (ctx, _expr) => {
146
+ const { root } = ctx;
147
+ if (root) {
148
+ const relations = [...ctx.relations].filter(anyPass([isInside(root), isIncoming(root), isOutgoing(root)]));
149
+ return ctx.exclude({
150
+ elements: [...ctx.elements].filter(e => isAncestor(root, e.id)),
151
+ relations,
152
+ implicits: [...ctx.implicits].filter(anyPass(relations.map(r => hasRelation(r))))
153
+ });
154
+ }
155
+ else {
156
+ return new ComputeCtx(ctx.index, ctx.root);
157
+ }
158
+ };
159
+ const resolveElements = (ctx, expr) => {
160
+ if (Expression.isWildcard(expr)) {
161
+ if (ctx.root) {
162
+ return [ctx.index.find(ctx.root)];
163
+ }
164
+ else {
165
+ return ctx.index.rootElements();
166
+ }
167
+ }
168
+ else {
169
+ if (expr.isDescedants) {
170
+ return ctx.index.children(expr.element);
171
+ }
172
+ else {
173
+ return [ctx.index.find(expr.element)];
174
+ }
175
+ }
176
+ };
177
+ const includeIncomingExpr = (ctx, expr) => {
178
+ if (Expression.isWildcard(expr.incoming) && !ctx.root) {
179
+ return ctx;
180
+ }
181
+ const elements = resolveElements(ctx, expr.incoming);
182
+ if (elements.length === 0) {
183
+ return ctx;
184
+ }
185
+ const implicits = [];
186
+ const relations = [];
187
+ for (const el of elements) {
188
+ const elRelations = ctx.index.filterRelations(isIncoming(el.id));
189
+ if (elRelations.length > 0) {
190
+ relations.push(...elRelations);
191
+ implicits.push(el);
192
+ }
193
+ }
194
+ return ctx.include({
195
+ relations,
196
+ implicits
197
+ });
198
+ };
199
+ const excludeIncomingExpr = (ctx, expr) => {
200
+ if (Expression.isWildcard(expr.incoming) && !ctx.root) {
201
+ return ctx;
202
+ }
203
+ const elements = resolveElements(ctx, expr.incoming);
204
+ if (elements.length === 0) {
205
+ return ctx;
206
+ }
207
+ const isIncomings = anyPass(elements.map(el => isIncoming(el.id)));
208
+ const excluded = [...ctx.relations].filter(isIncomings);
209
+ if (excluded.length > 0) {
210
+ return ctx.exclude({
211
+ relations: excluded
212
+ });
213
+ }
214
+ return ctx;
215
+ };
216
+ const includeOutgoingExpr = (ctx, expr) => {
217
+ if (Expression.isWildcard(expr.outgoing) && !ctx.root) {
218
+ return ctx;
219
+ }
220
+ const elements = resolveElements(ctx, expr.outgoing);
221
+ if (elements.length === 0) {
222
+ return ctx;
223
+ }
224
+ const implicits = [];
225
+ const relations = [];
226
+ for (const el of elements) {
227
+ const elRelations = ctx.index.filterRelations(isOutgoing(el.id));
228
+ if (elRelations.length > 0) {
229
+ relations.push(...elRelations);
230
+ implicits.push(el);
231
+ }
232
+ }
233
+ return ctx.include({
234
+ relations,
235
+ implicits
236
+ });
237
+ };
238
+ const excludeOutgoingExpr = (ctx, expr) => {
239
+ if (Expression.isWildcard(expr.outgoing) && !ctx.root) {
240
+ return ctx;
241
+ }
242
+ const elements = resolveElements(ctx, expr.outgoing);
243
+ if (elements.length === 0) {
244
+ return ctx;
245
+ }
246
+ const isOutgoings = anyPass(elements.map(el => isOutgoing(el.id)));
247
+ const excluded = [...ctx.relations].filter(isOutgoings);
248
+ if (excluded.length > 0) {
249
+ return ctx.exclude({
250
+ relations: excluded
251
+ });
252
+ }
253
+ return ctx;
254
+ };
255
+ const includeInOutExpr = (ctx, expr) => {
256
+ if (Expression.isWildcard(expr.inout) && !ctx.root) {
257
+ return ctx;
258
+ }
259
+ const targets = resolveElements(ctx, expr.inout);
260
+ if (targets.length === 0) {
261
+ return ctx;
262
+ }
263
+ const implicits = [];
264
+ const relations = [];
265
+ for (const target of targets) {
266
+ const foundRelations = ctx.index.filterRelations(isAnyInOut(target.id));
267
+ if (foundRelations.length > 0) {
268
+ relations.push(...foundRelations);
269
+ implicits.push(target);
270
+ }
271
+ }
272
+ return ctx.include({
273
+ relations,
274
+ implicits
275
+ });
276
+ };
277
+ const excludeInOutExpr = (ctx, expr) => {
278
+ if (Expression.isWildcard(expr.inout) && !ctx.root) {
279
+ return ctx;
280
+ }
281
+ const targets = resolveElements(ctx, expr.inout);
282
+ if (targets.length === 0) {
283
+ return ctx;
284
+ }
285
+ const excluded = [...ctx.relations].filter(anyPass(targets.map(t => isAnyInOut(t.id))));
286
+ if (excluded.length > 0) {
287
+ return ctx.exclude({
288
+ relations: excluded
289
+ });
290
+ }
291
+ return ctx;
292
+ };
293
+ const includeRelationExpr = (ctx, expr) => {
294
+ const sources = resolveElements(ctx, expr.source);
295
+ const targets = resolveElements(ctx, expr.target);
296
+ if (sources.length === 0 || targets.length === 0) {
297
+ return ctx;
298
+ }
299
+ const implicits = [];
300
+ const relations = [];
301
+ for (const source of sources) {
302
+ for (const target of targets) {
303
+ if (isSameHierarchy(source, target)) {
304
+ continue;
305
+ }
306
+ const foundRelations = ctx.index.filterRelations(isBetween(source.id, target.id));
307
+ if (foundRelations.length > 0) {
308
+ relations.push(...foundRelations);
309
+ implicits.push(source, target);
310
+ }
311
+ }
312
+ }
313
+ return ctx.include({
314
+ relations,
315
+ implicits
316
+ });
317
+ };
318
+ const excludeRelationExpr = (ctx, expr) => {
319
+ const sources = resolveElements(ctx, expr.source);
320
+ const targets = resolveElements(ctx, expr.target);
321
+ const filters = [];
322
+ for (const source of sources) {
323
+ for (const target of targets) {
324
+ if (isSameHierarchy(source, target)) {
325
+ continue;
326
+ }
327
+ filters.push(isBetween(source.id, target.id));
328
+ }
329
+ }
330
+ if (filters.length == 0) {
331
+ return ctx;
332
+ }
333
+ const excluded = [...ctx.relations].filter(anyPass(filters));
334
+ if (excluded.length == 0) {
335
+ return ctx;
336
+ }
337
+ return ctx.exclude({
338
+ relations: excluded
339
+ });
340
+ };
341
+ export function computeElementView(view, index) {
342
+ const rootElement = view.viewOf ?? null;
343
+ let ctx = new ComputeCtx(index, rootElement);
344
+ const rulesInclude = view.rules.filter(isViewRuleExpression);
345
+ if (rootElement && rulesInclude.length == 0) {
346
+ ctx = ctx.include({
347
+ elements: [index.find(rootElement)]
348
+ });
349
+ }
350
+ for (const { isInclude, exprs } of rulesInclude) {
351
+ for (const expr of exprs) {
352
+ if (Expression.isElementRef(expr)) {
353
+ ctx = isInclude ? includeElementRef(ctx, expr) : excludeElementRef(ctx, expr);
354
+ continue;
355
+ }
356
+ if (Expression.isWildcard(expr)) {
357
+ ctx = isInclude ? includeWildcardRef(ctx, expr) : excludeWildcardRef(ctx, expr);
358
+ continue;
359
+ }
360
+ if (Expression.isIncoming(expr)) {
361
+ ctx = isInclude ? includeIncomingExpr(ctx, expr) : excludeIncomingExpr(ctx, expr);
362
+ continue;
363
+ }
364
+ if (Expression.isOutgoing(expr)) {
365
+ ctx = isInclude ? includeOutgoingExpr(ctx, expr) : excludeOutgoingExpr(ctx, expr);
366
+ continue;
367
+ }
368
+ if (Expression.isInOut(expr)) {
369
+ ctx = isInclude ? includeInOutExpr(ctx, expr) : excludeInOutExpr(ctx, expr);
370
+ continue;
371
+ }
372
+ if (Expression.isRelation(expr)) {
373
+ ctx = isInclude ? includeRelationExpr(ctx, expr) : excludeRelationExpr(ctx, expr);
374
+ continue;
375
+ }
376
+ ignoreNeverInRuntime(expr);
377
+ }
378
+ }
379
+ const elements = new Set([...ctx.elements]);
380
+ const edgeBuilder = new EdgeBuilder();
381
+ const resolvedRelations = [...ctx.relations];
382
+ for (const [source, target] of anyPossibleRelations([...elements, ...ctx.implicits])) {
383
+ if (!elements.has(source) && !elements.has(target)) {
384
+ continue;
385
+ }
386
+ const findPredicate = Relations.isBetween(source.id, target.id);
387
+ let idx = resolvedRelations.findIndex(findPredicate);
388
+ while (idx >= 0) {
389
+ const [rel] = resolvedRelations.splice(idx, 1);
390
+ if (rel) {
391
+ elements.add(source);
392
+ elements.add(target);
393
+ edgeBuilder.add(source.id, target.id, rel);
394
+ }
395
+ idx = resolvedRelations.findIndex(findPredicate);
396
+ }
397
+ }
398
+ const nodesreg = transformToNodes(elements, index, view.id);
399
+ const edges = edgeBuilder.build().map(edge => {
400
+ while (edge.parent) {
401
+ if (nodesreg.has(edge.parent)) {
402
+ break;
403
+ }
404
+ edge.parent = parentFqn(edge.parent);
405
+ }
406
+ return edge;
407
+ });
408
+ const nodes = applyViewRuleStyles(view.rules.filter(isViewRuleStyle), sortNodes(nodesreg, edges));
409
+ const autoLayoutRule = view.rules.find(isViewRuleAutoLayout);
410
+ return {
411
+ ...view,
412
+ autoLayout: autoLayoutRule?.autoLayout ?? 'TB',
413
+ nodes,
414
+ edges
415
+ };
416
+ }
@@ -1,6 +1,5 @@
1
1
  import { ModelIndex } from '../model-index';
2
- import type { Element, ElementView, Fqn, LikeC4Model, Relation, RelationID, ViewID } from '../types';
3
- import type { ComputedView } from '../types/computed-view';
2
+ import type { Element, ElementView, Fqn, LikeC4Model, Relation, ComputedView, RelationID, ViewID } from '../types';
4
3
  export declare function computeView(view: ElementView, index: ModelIndex): ComputedView;
5
4
  type InputModel = {
6
5
  elements: Record<Fqn, Element>;
@@ -9,3 +8,4 @@ type InputModel = {
9
8
  };
10
9
  export declare function computeViews(model: InputModel): LikeC4Model;
11
10
  export {};
11
+ //# sourceMappingURL=compute.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { map } from 'rambdax';
2
2
  import { ModelIndex } from '../model-index';
3
- import { computeElementView } from './compute.element-view';
3
+ import { computeElementView } from './compute-element-view';
4
4
  export function computeView(view, index) {
5
5
  return computeElementView(view, index);
6
6
  }
@@ -1,2 +1,3 @@
1
- export { computeView, computeViews } from './compute-view';
1
+ export { computeView, computeViews } from './compute';
2
2
  export type * from '../types/computed-view';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- export { computeView, computeViews } from './compute-view';
1
+ export { computeView, computeViews } from './compute';
@@ -1,2 +1,3 @@
1
1
  import type { Element } from '../../types';
2
2
  export declare function anyPossibleRelations(elements: Element[]): Generator<[source: Element, target: Element]>;
3
+ //# sourceMappingURL=anyPossibleRelations.d.ts.map