@likec4/core 0.7.0 → 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.
@@ -1,168 +0,0 @@
1
- import { anyPass, filter, head } from 'rambdax';
2
- import { DefaultElementShape, DefaultThemeColor } from '../types';
3
- import * as Expression from '../types/expression';
4
- import { isViewRuleAutoLayout, isViewRuleExpression, isViewRuleStyle } from '../types/view';
5
- import { Relations, compareByFqnHierarchically, failExpectedNever, isSameHierarchy, parentFqn } from '../utils';
6
- import { EdgeBuilder } from './EdgeBuilder';
7
- import { anyPossibleRelations } from './utils/anyPossibleRelations';
8
- import { evaluateExpression } from './utils/evaluate-expression';
9
- import { sortNodes } from './utils/sortNodes';
10
- function updateSetWith(set, elements, addToSet = true) {
11
- for (const e of elements) {
12
- addToSet ? set.add(e) : set.delete(e);
13
- }
14
- }
15
- function transformToNodes(elementsIterator, index, currentViewid) {
16
- return Array.from(elementsIterator)
17
- .sort(compareByFqnHierarchically)
18
- .reduce((map, { id, title, color, shape, description }) => {
19
- let parent = parentFqn(id);
20
- while (parent) {
21
- if (map.has(parent)) {
22
- break;
23
- }
24
- parent = parentFqn(parent);
25
- }
26
- const navigateTo = head(index.defaultViewOf(id).filter(v => v !== currentViewid));
27
- map.set(id, Object.assign({
28
- id,
29
- parent,
30
- title,
31
- color: color ?? DefaultThemeColor,
32
- shape: shape ?? DefaultElementShape,
33
- children: []
34
- }, description ? { description } : {}, navigateTo ? { navigateTo } : {}));
35
- if (parent) {
36
- map.get(parent)?.children.push(id);
37
- }
38
- return map;
39
- }, new Map());
40
- }
41
- function applyViewRuleStyles(rules, nodes) {
42
- for (const rule of rules) {
43
- const predicates = [];
44
- if (!rule.style.color && !rule.style.shape) {
45
- // skip empty
46
- continue;
47
- }
48
- for (const target of rule.targets) {
49
- if (Expression.isWildcard(target)) {
50
- predicates.push(() => true);
51
- break;
52
- }
53
- if (Expression.isElementRef(target)) {
54
- const { element, isDescedants } = target;
55
- predicates.push(isDescedants ? n => n.id.startsWith(element + '.') : n => n.id === element);
56
- continue;
57
- }
58
- failExpectedNever(target);
59
- }
60
- filter(anyPass(predicates), nodes).forEach(n => {
61
- n.shape = rule.style.shape ?? n.shape;
62
- n.color = rule.style.color ?? n.color;
63
- });
64
- }
65
- return nodes;
66
- }
67
- export function computeElementView(view, index) {
68
- const relations = new Set();
69
- const elements = new Set();
70
- const neighbours = new Set();
71
- const rootElement = view.viewOf ?? null;
72
- const rulesInclude = view.rules.filter(isViewRuleExpression);
73
- if (rootElement && rulesInclude.length == 0) {
74
- elements.add(index.find(rootElement));
75
- }
76
- for (const { isInclude, exprs } of rulesInclude) {
77
- for (const expr of exprs) {
78
- let { elements: newElements, neighbours: newNeighbours, relations: newRelations } = evaluateExpression(index, expr, rootElement);
79
- if (isInclude) {
80
- const filters = [];
81
- // When include element(s) without newNeighbours, include in-out relations
82
- if (elements.size > 0 &&
83
- newElements.length > 0 &&
84
- newNeighbours.length === 0 &&
85
- Expression.isElement(expr)) {
86
- for (const e of elements) {
87
- for (const newE of newElements) {
88
- if (!isSameHierarchy(e, newE)) {
89
- filters.push(Relations.isAnyBetween(e.id, newE.id));
90
- }
91
- }
92
- }
93
- }
94
- // // When include elements by tag or kind, include in-out relations
95
- // if (elements.size > 0 && newElements.length > 0 && (Expression.isElementKind(expr) || Expression.isElementTag(expr))) {
96
- // for (const e of elements) {
97
- // for (const newE of newElements) {
98
- // if (e.id !== newE.id && !isAncestor(e, newE) && !isAncestor(newE, e)) {
99
- // filters.push(isAnyRelationBetween(e.id, newE.id))
100
- // }
101
- // }
102
- // }
103
- // }
104
- if (filters.length > 0) {
105
- newRelations = newRelations.concat(index.filterRelations(anyPass(filters)));
106
- }
107
- }
108
- else {
109
- if (Expression.isAnyRelation(expr)) {
110
- // Exclude only relations, but not elements and neighbours
111
- newNeighbours = [];
112
- newElements = [];
113
- }
114
- else {
115
- newNeighbours = newNeighbours.concat(newElements);
116
- // Also exclude nested elements from current neighbours
117
- // for (const n of neighbours) {
118
- // if (newNeighbours.some(e => n.id.startsWith(e.id + '.'))) {
119
- // newNeighbours.push(n)
120
- // }
121
- // }
122
- // Do not exclude relations
123
- newRelations = [];
124
- }
125
- }
126
- updateSetWith(elements, newElements, isInclude);
127
- updateSetWith(relations, newRelations, isInclude);
128
- updateSetWith(neighbours, newNeighbours, isInclude);
129
- }
130
- }
131
- const elementsIds = new Set([...elements].map(e => e.id));
132
- const edgeBuilder = new EdgeBuilder();
133
- const resolvedRelations = [...relations];
134
- for (const [source, target] of anyPossibleRelations([...elements, ...neighbours])) {
135
- if (!elementsIds.has(source.id) && !elementsIds.has(target.id)) {
136
- continue;
137
- }
138
- const findPredicate = Relations.isBetween(source.id, target.id);
139
- let idx = resolvedRelations.findIndex(findPredicate);
140
- while (idx >= 0) {
141
- const [rel] = resolvedRelations.splice(idx, 1);
142
- if (rel) {
143
- elements.add(source);
144
- elements.add(target);
145
- edgeBuilder.add(source.id, target.id, rel);
146
- }
147
- idx = resolvedRelations.findIndex(findPredicate);
148
- }
149
- }
150
- const nodesreg = transformToNodes(elements, index, view.id);
151
- const edges = edgeBuilder.build().map(edge => {
152
- while (edge.parent) {
153
- if (nodesreg.has(edge.parent)) {
154
- break;
155
- }
156
- edge.parent = parentFqn(edge.parent);
157
- }
158
- return edge;
159
- });
160
- const nodes = applyViewRuleStyles(view.rules.filter(isViewRuleStyle), sortNodes(nodesreg, edges));
161
- const autoLayoutRule = view.rules.find(isViewRuleAutoLayout);
162
- return {
163
- ...view,
164
- autoLayout: autoLayoutRule?.autoLayout ?? 'TB',
165
- nodes,
166
- edges
167
- };
168
- }
@@ -1,11 +0,0 @@
1
- import type { ModelIndex } from '../../model-index';
2
- import type { Element, Fqn, Relation, Expression } from '../../types';
3
- export declare const keepLeafs: (elements: Element[]) => Element[];
4
- interface EvaluateViewExpressionResult {
5
- elements: Element[];
6
- neighbours: Element[];
7
- relations: Relation[];
8
- }
9
- export declare function evaluateExpression(index: ModelIndex, expr: Expression, rootElement: Fqn | null): EvaluateViewExpressionResult;
10
- export {};
11
- //# sourceMappingURL=evaluate-expression.d.ts.map
@@ -1,186 +0,0 @@
1
- import { anyPass, map, pluck, uniq } from 'rambdax';
2
- import * as Expr from '../../types/expression';
3
- import { failExpectedNever, isAncestor } from '../../utils';
4
- import { isBetween, isIncoming, isInside, isOutgoing } from '../../utils/relations';
5
- import { anyPossibleRelations } from './anyPossibleRelations';
6
- const dropNested = (elements) => {
7
- return elements.reduce((acc, current) => {
8
- if (acc.length === 0)
9
- return [current];
10
- // current is a child of some in acc
11
- if (acc.some(p => p.id === current.id || isAncestor(p, current))) {
12
- return acc;
13
- }
14
- return [
15
- // drop children of current
16
- ...acc.filter(e => !isAncestor(current, e)),
17
- current
18
- ];
19
- }, []);
20
- };
21
- export const keepLeafs = (elements) => {
22
- return elements.reduce((acc, current) => {
23
- if (acc.length === 0)
24
- return [current];
25
- // current is an ancestor of some in acc
26
- if (acc.some(p => p.id === current.id || isAncestor(current, p))) {
27
- return acc;
28
- }
29
- return [
30
- // drop ancestors of current
31
- ...acc.filter(e => !isAncestor(e, current)),
32
- current
33
- ];
34
- }, []);
35
- };
36
- const evaluateElementExpression = (index, expr, rootElement = null) => {
37
- let elements = [];
38
- let neighbours = [];
39
- let relations = [];
40
- // const inOutRelations = (elements: Element[]) => {
41
- // if (elements.length == 0) return []
42
- // const filters = dropNested(elements).map(e => isAnyInOut(e.id))
43
- // return index.filterRelations(anyPass(filters))
44
- // }
45
- const allRelationsBetween = (elements) => {
46
- if (elements.length <= 1)
47
- return [];
48
- const filters = [];
49
- for (const [source, target] of anyPossibleRelations(elements)) {
50
- filters.push(isBetween(source.id, target.id));
51
- }
52
- return filters.length ? index.filterRelations(anyPass(filters)) : [];
53
- };
54
- // WildcardExpression
55
- if (Expr.isWildcard(expr)) {
56
- if (rootElement) {
57
- elements = [index.find(rootElement), ...index.children(rootElement)];
58
- neighbours = [
59
- ...index.siblings(rootElement),
60
- ...index.ancestors(rootElement).flatMap(a => [...index.siblings(a.id)])
61
- ];
62
- relations = index.filterRelations(anyPass([isInside(rootElement), isIncoming(rootElement), isOutgoing(rootElement)]));
63
- }
64
- else {
65
- elements = index.rootElements();
66
- neighbours = elements;
67
- relations = allRelationsBetween(elements);
68
- }
69
- return {
70
- elements,
71
- neighbours,
72
- relations
73
- };
74
- }
75
- // Identifier
76
- if (Expr.isElementRef(expr)) {
77
- elements = expr.isDescedants ? index.children(expr.element) : [index.find(expr.element)];
78
- if (expr.isDescedants) {
79
- relations = index.filterRelations(isInside(expr.element));
80
- // relations = index.filterRelations(anyPass([
81
- // isBetween(expr.element),
82
- // isIncoming(expr.element),
83
- // isOutgoing(expr.element),
84
- // ]))
85
- // } else {
86
- // relations = index.filterRelations(anyPass([
87
- // isIncoming(expr.element),
88
- // isOutgoing(expr.element)
89
- // ]))
90
- }
91
- return {
92
- elements,
93
- neighbours,
94
- relations
95
- };
96
- }
97
- failExpectedNever(expr);
98
- };
99
- export function evaluateExpression(index, expr, rootElement) {
100
- const elements = [];
101
- let neighbours = [];
102
- let relations = [];
103
- if (Expr.isInOut(expr)) {
104
- const targets = evaluateElementExpression(index, expr.inout).elements;
105
- for (const target of targets) {
106
- const incoming = index.filterRelations(isIncoming(target.id));
107
- const outgoing = index.filterRelations(isOutgoing(target.id));
108
- if (incoming.length + outgoing.length > 0) {
109
- elements.push(target);
110
- neighbours = neighbours.concat(map(index.find, [...pluck('source', incoming), ...pluck('target', outgoing)]));
111
- relations = relations.concat([...incoming, ...outgoing]);
112
- }
113
- }
114
- return {
115
- elements: uniq(elements),
116
- neighbours: dropNested(neighbours),
117
- relations: uniq(relations)
118
- };
119
- }
120
- if (Expr.isIncoming(expr)) {
121
- const targets = evaluateElementExpression(index, expr.incoming).elements;
122
- for (const target of targets) {
123
- const incoming = index.filterRelations(isIncoming(target.id));
124
- if (incoming.length > 0) {
125
- elements.push(target);
126
- neighbours = neighbours.concat(map(index.find, pluck('source', incoming)));
127
- relations = relations.concat(incoming);
128
- }
129
- }
130
- return {
131
- elements: uniq(elements),
132
- neighbours: dropNested(neighbours),
133
- relations: uniq(relations)
134
- };
135
- }
136
- if (Expr.isOutgoing(expr)) {
137
- const sources = evaluateElementExpression(index, expr.outgoing).elements;
138
- for (const source of sources) {
139
- const outgoing = index.filterRelations(isOutgoing(source.id));
140
- if (outgoing.length > 0) {
141
- elements.push(source);
142
- neighbours = neighbours.concat(map(index.find, pluck('target', outgoing)));
143
- relations = relations.concat(outgoing);
144
- }
145
- }
146
- return {
147
- elements: uniq(elements),
148
- neighbours: dropNested(neighbours),
149
- relations: uniq(relations)
150
- };
151
- }
152
- if (Expr.isRelation(expr)) {
153
- const isSourceWildcard = Expr.isWildcard(expr.source);
154
- const isTargetWildcard = Expr.isWildcard(expr.target);
155
- if (isSourceWildcard && !isTargetWildcard) {
156
- return evaluateExpression(index, {
157
- incoming: expr.target
158
- }, rootElement);
159
- }
160
- if (!isSourceWildcard && isTargetWildcard) {
161
- return evaluateExpression(index, {
162
- outgoing: expr.source
163
- }, rootElement);
164
- }
165
- const sources = evaluateElementExpression(index, expr.source).elements;
166
- const targets = evaluateElementExpression(index, expr.target).elements;
167
- for (const source of sources) {
168
- for (const target of targets) {
169
- if (isAncestor(source.id, target.id) || isAncestor(target.id, source.id)) {
170
- continue;
171
- }
172
- const foundRelations = index.filterRelations(isBetween(source.id, target.id));
173
- if (foundRelations.length > 0) {
174
- relations = relations.concat(foundRelations);
175
- neighbours.push(source, target);
176
- }
177
- }
178
- }
179
- return {
180
- elements,
181
- neighbours: uniq(neighbours),
182
- relations: uniq(relations)
183
- };
184
- }
185
- return evaluateElementExpression(index, expr, rootElement);
186
- }