@likec4/core 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -6
- package/dist/cjs/colors/element.d.ts +68 -0
- package/dist/{esm/colors.js → cjs/colors/element.js} +9 -23
- package/dist/cjs/colors/index.d.ts +132 -0
- package/dist/cjs/colors/index.js +27 -0
- package/dist/cjs/colors/relationships.d.ts +57 -0
- package/dist/cjs/colors/relationships.js +76 -0
- package/dist/cjs/index.d.ts +0 -2
- package/dist/cjs/index.js +0 -22
- package/dist/cjs/types/computed-view.d.ts +10 -7
- package/dist/cjs/types/diagram.d.ts +14 -5
- package/dist/cjs/types/expression.d.ts +1 -1
- package/dist/cjs/types/relation.d.ts +12 -0
- package/dist/cjs/types/relation.js +12 -1
- package/dist/cjs/types/theme.d.ts +12 -14
- package/dist/cjs/types/view.d.ts +7 -4
- package/dist/cjs/types/view.js +1 -1
- package/dist/cjs/utils/fqn.d.ts +6 -1
- package/dist/cjs/utils/fqn.js +17 -4
- package/dist/cjs/utils/guards.d.ts +1 -0
- package/dist/cjs/utils/guards.js +7 -0
- package/dist/cjs/utils/index.d.ts +0 -1
- package/dist/cjs/utils/index.js +0 -11
- package/dist/esm/colors/element.d.ts +68 -0
- package/dist/{cjs/colors.js → esm/colors/element.js} +1 -33
- package/dist/esm/colors/index.d.ts +132 -0
- package/dist/esm/colors/index.js +9 -0
- package/dist/esm/colors/relationships.d.ts +57 -0
- package/dist/esm/colors/relationships.js +64 -0
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +1 -3
- package/dist/esm/types/computed-view.d.ts +10 -7
- package/dist/esm/types/diagram.d.ts +14 -5
- package/dist/esm/types/expression.d.ts +1 -1
- package/dist/esm/types/relation.d.ts +12 -0
- package/dist/esm/types/relation.js +3 -0
- package/dist/esm/types/theme.d.ts +12 -14
- package/dist/esm/types/view.d.ts +7 -4
- package/dist/esm/types/view.js +1 -1
- package/dist/esm/utils/fqn.d.ts +6 -1
- package/dist/esm/utils/fqn.js +16 -4
- package/dist/esm/utils/guards.d.ts +1 -0
- package/dist/esm/utils/guards.js +1 -0
- package/dist/esm/utils/index.d.ts +0 -1
- package/dist/esm/utils/index.js +0 -1
- package/dist/types/colors/element.d.ts +69 -0
- package/dist/types/colors/index.d.ts +133 -0
- package/dist/types/colors/relationships.d.ts +58 -0
- package/dist/types/errors/index.d.ts +46 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/types/_common.d.ts +4 -0
- package/dist/types/types/computed-view.d.ts +45 -0
- package/dist/types/types/diagram.d.ts +42 -0
- package/dist/types/types/element.d.ts +30 -0
- package/dist/types/types/expression.d.ts +57 -0
- package/dist/types/types/index.d.ts +12 -0
- package/dist/types/types/model.d.ts +15 -0
- package/dist/types/types/opaque.d.ts +103 -0
- package/dist/types/types/relation.d.ts +23 -0
- package/dist/types/types/theme.d.ts +27 -0
- package/dist/types/types/view.d.ts +62 -0
- package/dist/types/utils/fqn.d.ts +34 -0
- package/dist/types/utils/guards.d.ts +5 -0
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/relations.d.ts +26 -0
- package/package.json +51 -54
- package/dist/cjs/colors.d.ts +0 -148
- package/dist/cjs/compute-view/EdgeBuilder.d.ts +0 -6
- package/dist/cjs/compute-view/EdgeBuilder.js +0 -37
- package/dist/cjs/compute-view/compute-ctx.d.ts +0 -20
- package/dist/cjs/compute-view/compute-ctx.js +0 -91
- package/dist/cjs/compute-view/compute-element-view.d.ts +0 -3
- package/dist/cjs/compute-view/compute-element-view.js +0 -100
- package/dist/cjs/compute-view/compute-predicates.d.ts +0 -16
- package/dist/cjs/compute-view/compute-predicates.js +0 -363
- package/dist/cjs/compute-view/compute.d.ts +0 -14
- package/dist/cjs/compute-view/compute.js +0 -46
- package/dist/cjs/compute-view/index.d.ts +0 -4
- package/dist/cjs/compute-view/index.js +0 -49
- package/dist/cjs/compute-view/resolve-extended-views.d.ts +0 -6
- package/dist/cjs/compute-view/resolve-extended-views.js +0 -53
- package/dist/cjs/compute-view/resolve-relative-paths.d.ts +0 -2
- package/dist/cjs/compute-view/resolve-relative-paths.js +0 -84
- package/dist/cjs/compute-view/utils/anyPossibleRelations.d.ts +0 -2
- package/dist/cjs/compute-view/utils/anyPossibleRelations.js +0 -18
- package/dist/cjs/compute-view/utils/applyViewRuleStyles.d.ts +0 -2
- package/dist/cjs/compute-view/utils/applyViewRuleStyles.js +0 -57
- package/dist/cjs/compute-view/utils/sortNodes.d.ts +0 -19
- package/dist/cjs/compute-view/utils/sortNodes.js +0 -47
- package/dist/cjs/model-index/ModelIndex.d.ts +0 -27
- package/dist/cjs/model-index/ModelIndex.js +0 -139
- package/dist/cjs/model-index/index.d.ts +0 -1
- package/dist/cjs/model-index/index.js +0 -13
- package/dist/cjs/utils/compute-node-levels.d.ts +0 -7
- package/dist/cjs/utils/compute-node-levels.js +0 -48
- package/dist/esm/colors.d.ts +0 -148
- package/dist/esm/compute-view/EdgeBuilder.d.ts +0 -6
- package/dist/esm/compute-view/EdgeBuilder.js +0 -30
- package/dist/esm/compute-view/compute-ctx.d.ts +0 -20
- package/dist/esm/compute-view/compute-ctx.js +0 -100
- package/dist/esm/compute-view/compute-element-view.d.ts +0 -3
- package/dist/esm/compute-view/compute-element-view.js +0 -98
- package/dist/esm/compute-view/compute-predicates.d.ts +0 -16
- package/dist/esm/compute-view/compute-predicates.js +0 -324
- package/dist/esm/compute-view/compute.d.ts +0 -14
- package/dist/esm/compute-view/compute.js +0 -36
- package/dist/esm/compute-view/index.d.ts +0 -4
- package/dist/esm/compute-view/index.js +0 -4
- package/dist/esm/compute-view/resolve-extended-views.d.ts +0 -6
- package/dist/esm/compute-view/resolve-extended-views.js +0 -41
- package/dist/esm/compute-view/resolve-relative-paths.d.ts +0 -2
- package/dist/esm/compute-view/resolve-relative-paths.js +0 -76
- package/dist/esm/compute-view/utils/anyPossibleRelations.d.ts +0 -2
- package/dist/esm/compute-view/utils/anyPossibleRelations.js +0 -12
- package/dist/esm/compute-view/utils/applyViewRuleStyles.d.ts +0 -2
- package/dist/esm/compute-view/utils/applyViewRuleStyles.js +0 -50
- package/dist/esm/compute-view/utils/sortNodes.d.ts +0 -19
- package/dist/esm/compute-view/utils/sortNodes.js +0 -37
- package/dist/esm/model-index/ModelIndex.d.ts +0 -27
- package/dist/esm/model-index/ModelIndex.js +0 -127
- package/dist/esm/model-index/index.d.ts +0 -1
- package/dist/esm/model-index/index.js +0 -1
- package/dist/esm/utils/compute-node-levels.d.ts +0 -7
- package/dist/esm/utils/compute-node-levels.js +0 -31
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import graphlib from "@dagrejs/graphlib";
|
|
2
|
-
import { isExtendsElementView } from "../types/index.js";
|
|
3
|
-
const { Graph, alg } = graphlib;
|
|
4
|
-
export function resolveRulesExtendedViews(unresolvedViews) {
|
|
5
|
-
const g = new Graph({
|
|
6
|
-
directed: true,
|
|
7
|
-
multigraph: false,
|
|
8
|
-
compound: false
|
|
9
|
-
});
|
|
10
|
-
for (const view of Object.values(unresolvedViews)) {
|
|
11
|
-
g.setNode(view.id);
|
|
12
|
-
if (isExtendsElementView(view)) {
|
|
13
|
-
g.setEdge(view.id, view.extends);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
const cycles = alg.findCycles(g);
|
|
17
|
-
if (cycles.length > 0) {
|
|
18
|
-
cycles.flat().forEach((id) => g.removeNode(id));
|
|
19
|
-
}
|
|
20
|
-
const ordered = alg.postorder(g, g.sources());
|
|
21
|
-
return ordered.reduce((acc, id) => {
|
|
22
|
-
const view = unresolvedViews[id];
|
|
23
|
-
if (!view) {
|
|
24
|
-
return acc;
|
|
25
|
-
}
|
|
26
|
-
if (isExtendsElementView(view)) {
|
|
27
|
-
const extendsFrom = acc[view.extends];
|
|
28
|
-
if (!extendsFrom) {
|
|
29
|
-
return acc;
|
|
30
|
-
}
|
|
31
|
-
return Object.assign(acc, {
|
|
32
|
-
[view.id]: {
|
|
33
|
-
...extendsFrom,
|
|
34
|
-
...view,
|
|
35
|
-
rules: [...extendsFrom.rules, ...view.rules]
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
return Object.assign(acc, { [view.id]: view });
|
|
40
|
-
}, {});
|
|
41
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { uniq, zip } from "rambdax";
|
|
2
|
-
import { hasAtLeast } from "remeda";
|
|
3
|
-
import { invariant } from "../errors/index.js";
|
|
4
|
-
function commonAncestorPath(views, sep = "/") {
|
|
5
|
-
if (views.length <= 1)
|
|
6
|
-
return "";
|
|
7
|
-
const uniqURIs = uniq(views.flatMap(({ docUri }) => docUri ? [docUri] : []));
|
|
8
|
-
if (uniqURIs.length === 0)
|
|
9
|
-
return "";
|
|
10
|
-
if (uniqURIs.length === 1) {
|
|
11
|
-
invariant(hasAtLeast(uniqURIs, 1));
|
|
12
|
-
return new URL(uniqURIs[0]).pathname;
|
|
13
|
-
}
|
|
14
|
-
invariant(hasAtLeast(uniqURIs, 2), "Expected at least 2 unique URIs");
|
|
15
|
-
const [baseUri, ...tail] = uniqURIs;
|
|
16
|
-
const parts = new URL(baseUri).pathname.split(sep);
|
|
17
|
-
let endOfPrefix = parts.length;
|
|
18
|
-
for (const uri of tail) {
|
|
19
|
-
if (uri === baseUri) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
const compare = new URL(uri).pathname.split(sep);
|
|
23
|
-
for (let i = 0; i < endOfPrefix; i++) {
|
|
24
|
-
if (compare[i] !== parts[i]) {
|
|
25
|
-
endOfPrefix = i;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (endOfPrefix === 0)
|
|
29
|
-
return "";
|
|
30
|
-
}
|
|
31
|
-
const prefix = parts.slice(0, endOfPrefix).join(sep);
|
|
32
|
-
return prefix.endsWith(sep) ? prefix : prefix + sep;
|
|
33
|
-
}
|
|
34
|
-
export function resolveRelativePaths(views) {
|
|
35
|
-
const commonPrefix = commonAncestorPath(views);
|
|
36
|
-
return views.map((view) => {
|
|
37
|
-
if (!view.docUri) {
|
|
38
|
-
return {
|
|
39
|
-
...view,
|
|
40
|
-
parts: []
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
const path = new URL(view.docUri).pathname;
|
|
44
|
-
const parts = path.replace(commonPrefix, "").split("/");
|
|
45
|
-
parts.pop();
|
|
46
|
-
return {
|
|
47
|
-
...view,
|
|
48
|
-
parts
|
|
49
|
-
};
|
|
50
|
-
}).sort((a, b) => {
|
|
51
|
-
if (a.parts.length === b.parts.length) {
|
|
52
|
-
if (a.parts.length === 0) {
|
|
53
|
-
return 0;
|
|
54
|
-
}
|
|
55
|
-
if (a.parts.length === 1 && hasAtLeast(a.parts, 1) && hasAtLeast(b.parts, 1)) {
|
|
56
|
-
return a.parts[0].localeCompare(b.parts[0]);
|
|
57
|
-
}
|
|
58
|
-
for (const [_a, _b] of zip(a.parts, b.parts)) {
|
|
59
|
-
const compare = _a.localeCompare(_b);
|
|
60
|
-
if (compare !== 0) {
|
|
61
|
-
return compare;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return 0;
|
|
65
|
-
}
|
|
66
|
-
return a.parts.length - b.parts.length;
|
|
67
|
-
}).map(({ parts, ...view }) => {
|
|
68
|
-
if (view.docUri) {
|
|
69
|
-
return {
|
|
70
|
-
...view,
|
|
71
|
-
relativePath: parts.join("/")
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return view;
|
|
75
|
-
});
|
|
76
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { prop, uniqBy } from "rambdax";
|
|
2
|
-
import { compareByFqnHierarchically, isAncestor } from "../../utils/index.js";
|
|
3
|
-
export function* anyPossibleRelations(elements) {
|
|
4
|
-
const uniqElements = uniqBy(prop("id"), elements).sort(compareByFqnHierarchically).reverse();
|
|
5
|
-
for (const source of uniqElements) {
|
|
6
|
-
for (const target of uniqElements) {
|
|
7
|
-
if (source !== target && !isAncestor(source, target) && !isAncestor(target, source)) {
|
|
8
|
-
yield [source, target];
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { anyPass, clone, filter, isNil } from "rambdax";
|
|
2
|
-
import { isDefined } from "remeda";
|
|
3
|
-
import { nonexhaustive } from "../../errors/index.js";
|
|
4
|
-
import { Expr } from "../../types/index.js";
|
|
5
|
-
export function applyViewRuleStyles(rules, _nodes) {
|
|
6
|
-
if (rules.length === 0) {
|
|
7
|
-
return _nodes;
|
|
8
|
-
}
|
|
9
|
-
const nodes = clone(_nodes);
|
|
10
|
-
for (const rule of rules) {
|
|
11
|
-
const predicates = [];
|
|
12
|
-
if (!rule.style.color && !rule.style.shape) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
for (const target of rule.targets) {
|
|
16
|
-
if (Expr.isWildcard(target)) {
|
|
17
|
-
predicates.push(() => true);
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
if (Expr.isElementKindExpr(target)) {
|
|
21
|
-
predicates.push(
|
|
22
|
-
target.isEqual ? (n) => n.kind === target.elementKind : (n) => n.kind !== target.elementKind
|
|
23
|
-
);
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
if (Expr.isElementTagExpr(target)) {
|
|
27
|
-
predicates.push(
|
|
28
|
-
target.isEqual ? ({ tags }) => !!tags && tags.includes(target.elementTag) : ({ tags }) => isNil(tags) || !tags.includes(target.elementTag)
|
|
29
|
-
);
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (Expr.isElementRef(target)) {
|
|
33
|
-
const { element, isDescedants } = target;
|
|
34
|
-
predicates.push(
|
|
35
|
-
isDescedants ? (n) => n.id.startsWith(element + ".") : (n) => n.id === element
|
|
36
|
-
);
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
nonexhaustive(target);
|
|
40
|
-
}
|
|
41
|
-
filter(anyPass(predicates), nodes).forEach((n) => {
|
|
42
|
-
n.shape = rule.style.shape ?? n.shape;
|
|
43
|
-
n.color = rule.style.color ?? n.color;
|
|
44
|
-
if (isDefined.strict(rule.style.icon)) {
|
|
45
|
-
n.icon = rule.style.icon;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
return nodes;
|
|
50
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ComputedEdge, ComputedNode } from '../../types';
|
|
2
|
-
export declare function sortNodes(_nodes: ComputedNode[], edges: ComputedEdge[]): {
|
|
3
|
-
children: import("../../types").Fqn[];
|
|
4
|
-
id: import("../../types").Fqn;
|
|
5
|
-
kind: import("../../types").ElementKind;
|
|
6
|
-
parent: import("../../types").Fqn | null;
|
|
7
|
-
title: string;
|
|
8
|
-
description: string | null;
|
|
9
|
-
technology: string | null;
|
|
10
|
-
tags: import("../../types").NonEmptyArray<import("../../types").Tag> | null;
|
|
11
|
-
links: import("../../types").NonEmptyArray<string> | null;
|
|
12
|
-
inEdges: import("../../types").EdgeId[];
|
|
13
|
-
outEdges: import("../../types").EdgeId[];
|
|
14
|
-
shape: import("../../types").ElementShape;
|
|
15
|
-
color: import("../../types").ThemeColor;
|
|
16
|
-
icon?: import("../../types").IconUrl | undefined;
|
|
17
|
-
navigateTo?: import("../../types").ViewID | undefined;
|
|
18
|
-
level: number;
|
|
19
|
-
}[];
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import pkg from "@dagrejs/graphlib";
|
|
2
|
-
const { Graph, alg } = pkg;
|
|
3
|
-
function fillChildren(nodes) {
|
|
4
|
-
return nodes.map((node) => ({
|
|
5
|
-
...node,
|
|
6
|
-
children: nodes.flatMap((n) => n.parent === node.id ? n.id : [])
|
|
7
|
-
}));
|
|
8
|
-
}
|
|
9
|
-
export function sortNodes(_nodes, edges) {
|
|
10
|
-
if (edges.length === 0) {
|
|
11
|
-
return fillChildren(_nodes);
|
|
12
|
-
}
|
|
13
|
-
const g = new Graph({
|
|
14
|
-
compound: true,
|
|
15
|
-
directed: true,
|
|
16
|
-
multigraph: false
|
|
17
|
-
});
|
|
18
|
-
for (const e of edges) {
|
|
19
|
-
g.setEdge(e.source, e.target);
|
|
20
|
-
}
|
|
21
|
-
for (const n of _nodes) {
|
|
22
|
-
g.setNode(n.id);
|
|
23
|
-
if (n.parent) {
|
|
24
|
-
g.setEdge(n.id, n.parent);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const unprocessed = [..._nodes];
|
|
28
|
-
const sorted = [];
|
|
29
|
-
const ordered = alg.postorder(g, g.sources()).reverse();
|
|
30
|
-
for (const id of ordered) {
|
|
31
|
-
const inx = unprocessed.findIndex((n) => n.id === id);
|
|
32
|
-
if (inx >= 0) {
|
|
33
|
-
sorted.push(...unprocessed.splice(inx, 1));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return fillChildren(sorted.concat(unprocessed));
|
|
37
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { Element, Fqn, Relation, RelationID } from '../types';
|
|
2
|
-
type ModelInput = {
|
|
3
|
-
elements: Record<Fqn, Element>;
|
|
4
|
-
relations: Record<RelationID, Relation>;
|
|
5
|
-
};
|
|
6
|
-
export default class ModelIndex {
|
|
7
|
-
private root;
|
|
8
|
-
private _elements;
|
|
9
|
-
private _relations;
|
|
10
|
-
get relations(): Relation[];
|
|
11
|
-
filterRelations(predicate: (r: Relation) => boolean): Relation[];
|
|
12
|
-
static from({ elements, relations }: ModelInput): ModelIndex;
|
|
13
|
-
addElement(el: Element): void;
|
|
14
|
-
private locateTrie;
|
|
15
|
-
find: (id: Fqn) => Element;
|
|
16
|
-
children: (id: Fqn) => Element[];
|
|
17
|
-
siblings: (id: Fqn) => Element[];
|
|
18
|
-
/**
|
|
19
|
-
* Ancestors from closest parent to root
|
|
20
|
-
*/
|
|
21
|
-
ancestors(id: Fqn): Element[];
|
|
22
|
-
rootElements(): Element[];
|
|
23
|
-
get elements(): Element[];
|
|
24
|
-
hasElement(fqn: Fqn): boolean;
|
|
25
|
-
addRelation(rel: Relation): void;
|
|
26
|
-
}
|
|
27
|
-
export {};
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { values } from "remeda";
|
|
2
|
-
import { InvalidModelError, ensureModel } from "../errors/index.js";
|
|
3
|
-
import { parentFqn } from "../utils/index.js";
|
|
4
|
-
function childrenOf(trie) {
|
|
5
|
-
const children = [];
|
|
6
|
-
for (const { el } of values(trie.children)) {
|
|
7
|
-
if (el) {
|
|
8
|
-
children.push(el);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return children;
|
|
12
|
-
}
|
|
13
|
-
function asPath(id) {
|
|
14
|
-
return id.split(".");
|
|
15
|
-
}
|
|
16
|
-
export default class ModelIndex {
|
|
17
|
-
root = {
|
|
18
|
-
children: {}
|
|
19
|
-
};
|
|
20
|
-
_elements = /* @__PURE__ */ new Map();
|
|
21
|
-
_relations = /* @__PURE__ */ new Map();
|
|
22
|
-
// private _taggedElements = new Map<Tag, Set<Element>>()
|
|
23
|
-
// private _taggedRelations = new Map<Tag, Set<Relation>>()
|
|
24
|
-
get relations() {
|
|
25
|
-
return Array.from(this._relations.values());
|
|
26
|
-
}
|
|
27
|
-
filterRelations(predicate) {
|
|
28
|
-
return this.relations.filter(predicate);
|
|
29
|
-
}
|
|
30
|
-
static from({ elements, relations }) {
|
|
31
|
-
const index = new ModelIndex();
|
|
32
|
-
for (const el of values(elements)) {
|
|
33
|
-
index.addElement(el);
|
|
34
|
-
}
|
|
35
|
-
for (const rel of values(relations)) {
|
|
36
|
-
index.addRelation(rel);
|
|
37
|
-
}
|
|
38
|
-
return index;
|
|
39
|
-
}
|
|
40
|
-
addElement(el) {
|
|
41
|
-
if (this.hasElement(el.id)) {
|
|
42
|
-
throw new InvalidModelError(`Element already exists with id ${el.id}`);
|
|
43
|
-
}
|
|
44
|
-
const path = asPath(el.id);
|
|
45
|
-
let scope = this.root;
|
|
46
|
-
for (const name of path) {
|
|
47
|
-
const next = scope.children[name] ?? {
|
|
48
|
-
children: {}
|
|
49
|
-
};
|
|
50
|
-
scope.children[name] = next;
|
|
51
|
-
scope = next;
|
|
52
|
-
}
|
|
53
|
-
scope.el = el;
|
|
54
|
-
this._elements.set(el.id, el);
|
|
55
|
-
}
|
|
56
|
-
locateTrie = (id) => {
|
|
57
|
-
let scope = this.root;
|
|
58
|
-
for (const name of asPath(id)) {
|
|
59
|
-
const next = scope.children[name];
|
|
60
|
-
ensureModel(next, `Invalid index, Element not found at path ${name} of ${id}`);
|
|
61
|
-
scope = next;
|
|
62
|
-
}
|
|
63
|
-
return scope;
|
|
64
|
-
};
|
|
65
|
-
find = (id) => {
|
|
66
|
-
const el = this._elements.get(id);
|
|
67
|
-
ensureModel(el, `Element not found with id ${id}`);
|
|
68
|
-
return el;
|
|
69
|
-
};
|
|
70
|
-
children = (id) => {
|
|
71
|
-
return childrenOf(this.locateTrie(id));
|
|
72
|
-
};
|
|
73
|
-
siblings = (id) => {
|
|
74
|
-
const parent = parentFqn(id);
|
|
75
|
-
const trie = parent ? this.locateTrie(parent) : this.root;
|
|
76
|
-
return childrenOf(trie).filter((e) => e.id !== id);
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Ancestors from closest parent to root
|
|
80
|
-
*/
|
|
81
|
-
ancestors(id) {
|
|
82
|
-
const path = asPath(id);
|
|
83
|
-
const ancestors = [];
|
|
84
|
-
if (path.length === 1) {
|
|
85
|
-
return ancestors;
|
|
86
|
-
}
|
|
87
|
-
path.pop();
|
|
88
|
-
let name = path.shift();
|
|
89
|
-
let trie = this.root;
|
|
90
|
-
while (name) {
|
|
91
|
-
const next = trie.children[name];
|
|
92
|
-
ensureModel(next, `Invalid index, Element not found at path ${name} of ${id}`);
|
|
93
|
-
trie = next;
|
|
94
|
-
ensureModel(trie.el, `invalid index, no element ${name} found in ${id}`);
|
|
95
|
-
ancestors.unshift(trie.el);
|
|
96
|
-
name = path.shift();
|
|
97
|
-
}
|
|
98
|
-
return ancestors;
|
|
99
|
-
}
|
|
100
|
-
// tagged = (tag?: Tag): TaggedResult => {
|
|
101
|
-
// return tag ? {
|
|
102
|
-
// elements: [...this._taggedElements.get(tag)?.values() ?? []],
|
|
103
|
-
// relations: [...this._taggedRelations.get(tag)?.values() ?? []],
|
|
104
|
-
// } : {
|
|
105
|
-
// elements: uniq([...this._taggedElements.values()].flatMap(s => [...s.values()])),
|
|
106
|
-
// relations: uniq([...this._taggedRelations.values()].flatMap(s => [...s.values()]))
|
|
107
|
-
// }
|
|
108
|
-
// }
|
|
109
|
-
rootElements() {
|
|
110
|
-
return childrenOf(this.root);
|
|
111
|
-
}
|
|
112
|
-
get elements() {
|
|
113
|
-
return Array.from(this._elements.values());
|
|
114
|
-
}
|
|
115
|
-
hasElement(fqn) {
|
|
116
|
-
return this._elements.has(fqn);
|
|
117
|
-
}
|
|
118
|
-
addRelation(rel) {
|
|
119
|
-
if (!this.hasElement(rel.source)) {
|
|
120
|
-
throw new InvalidModelError(`Source of relation not found ${rel.source}`);
|
|
121
|
-
}
|
|
122
|
-
if (!this.hasElement(rel.target)) {
|
|
123
|
-
throw new InvalidModelError(`Target of relation not found ${rel.target}`);
|
|
124
|
-
}
|
|
125
|
-
this._relations.set(rel.id, rel);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as ModelIndex } from './ModelIndex';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as ModelIndex } from "./ModelIndex.js";
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { invariant } from "../errors/index.js";
|
|
2
|
-
export const computeNodeLevels = ({ nodes }) => {
|
|
3
|
-
const nodeLevels = {};
|
|
4
|
-
const compute = (node, level) => {
|
|
5
|
-
let levels = nodeLevels[node.id];
|
|
6
|
-
if (levels) {
|
|
7
|
-
return levels;
|
|
8
|
-
}
|
|
9
|
-
if (node.children.length === 0) {
|
|
10
|
-
levels = { level, depth: 0 };
|
|
11
|
-
nodeLevels[node.id] = levels;
|
|
12
|
-
return levels;
|
|
13
|
-
}
|
|
14
|
-
let depth = 1;
|
|
15
|
-
for (const childId of node.children) {
|
|
16
|
-
const child = nodes.find((n) => n.id === childId);
|
|
17
|
-
invariant(child, `Child ${childId} not found`);
|
|
18
|
-
const { depth: childDepth } = compute(child, level + 1);
|
|
19
|
-
depth = Math.max(childDepth + 1, depth);
|
|
20
|
-
}
|
|
21
|
-
levels = { level, depth };
|
|
22
|
-
nodeLevels[node.id] = levels;
|
|
23
|
-
return levels;
|
|
24
|
-
};
|
|
25
|
-
for (const node of nodes) {
|
|
26
|
-
if (!node.parent) {
|
|
27
|
-
compute(node, 0);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return nodeLevels;
|
|
31
|
-
};
|