@likec4/core 1.4.0 → 1.5.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 +1 -1
- package/dist/types/expression.d.ts +17 -3
- package/dist/types/expression.js +4 -1
- package/dist/types/model.d.ts +2 -2
- package/dist/types/relation.d.ts +1 -1
- package/dist/types/view.d.ts +21 -27
- package/dist/types/view.js +1 -1
- package/dist/utils/fqn.d.ts +5 -0
- package/dist/utils/fqn.js +4 -0
- package/package.json +8 -8
- package/src/types/expression.ts +22 -4
- package/src/types/model.ts +2 -2
- package/src/types/relation.ts +2 -0
- package/src/types/view.ts +23 -35
- package/src/utils/fqn.ts +7 -0
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IconUrl } from './_common';
|
|
2
2
|
import type { BorderStyle, ElementKind, ElementShape, Fqn, Tag } from './element';
|
|
3
|
+
import type { RelationshipArrowType, RelationshipLineType } from './relation';
|
|
3
4
|
import type { ThemeColor } from './theme';
|
|
4
5
|
import type { ViewID } from './view';
|
|
5
6
|
interface BaseExpr {
|
|
@@ -16,6 +17,7 @@ interface BaseExpr {
|
|
|
16
17
|
inout?: never;
|
|
17
18
|
incoming?: never;
|
|
18
19
|
outgoing?: never;
|
|
20
|
+
customRelation?: never;
|
|
19
21
|
}
|
|
20
22
|
export interface ElementRefExpr extends Omit<BaseExpr, 'element' | 'isDescedants'> {
|
|
21
23
|
element: Fqn;
|
|
@@ -57,6 +59,7 @@ export interface ElementTagExpr extends Omit<BaseExpr, 'elementTag' | 'isEqual'>
|
|
|
57
59
|
export declare function isElementTagExpr(expr: Expression): expr is ElementTagExpr;
|
|
58
60
|
export type ElementExpression = ElementRefExpr | WildcardExpr | ElementKindExpr | ElementTagExpr | ExpandedElementExpr;
|
|
59
61
|
export declare function isElement(expr: Expression): expr is ElementExpression;
|
|
62
|
+
export type ElementPredicateExpression = ElementExpression | CustomElementExpr;
|
|
60
63
|
export interface RelationExpr extends Omit<BaseExpr, 'source' | 'target'> {
|
|
61
64
|
source: ElementExpression;
|
|
62
65
|
target: ElementExpression;
|
|
@@ -75,8 +78,19 @@ export interface OutgoingExpr extends Omit<BaseExpr, 'outgoing'> {
|
|
|
75
78
|
outgoing: ElementExpression;
|
|
76
79
|
}
|
|
77
80
|
export declare function isOutgoing(expr: Expression): expr is OutgoingExpr;
|
|
78
|
-
export
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
export interface CustomRelationExpr extends Omit<BaseExpr, 'customRelation'> {
|
|
82
|
+
customRelation: {
|
|
83
|
+
relation: RelationExpr;
|
|
84
|
+
title?: string;
|
|
85
|
+
color?: ThemeColor;
|
|
86
|
+
line?: RelationshipLineType;
|
|
87
|
+
head?: RelationshipArrowType;
|
|
88
|
+
tail?: RelationshipArrowType;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export declare function isCustomRelationExpr(expr: Expression): expr is CustomRelationExpr;
|
|
92
|
+
export type RelationPredicateExpression = RelationExpr | InOutExpr | IncomingExpr | OutgoingExpr | CustomRelationExpr;
|
|
93
|
+
export declare function isAnyRelation(expr: Expression): expr is RelationPredicateExpression;
|
|
94
|
+
export type Expression = ElementPredicateExpression | RelationPredicateExpression;
|
|
81
95
|
export {};
|
|
82
96
|
//# sourceMappingURL=expression.d.ts.map
|
package/dist/types/expression.js
CHANGED
|
@@ -35,8 +35,11 @@ export function isIncoming(expr) {
|
|
|
35
35
|
export function isOutgoing(expr) {
|
|
36
36
|
return 'outgoing' in expr;
|
|
37
37
|
}
|
|
38
|
+
export function isCustomRelationExpr(expr) {
|
|
39
|
+
return 'customRelation' in expr;
|
|
40
|
+
}
|
|
38
41
|
export function isAnyRelation(expr) {
|
|
39
|
-
return isRelation(expr) || isInOut(expr) || isIncoming(expr) || isOutgoing(expr);
|
|
42
|
+
return isRelation(expr) || isInOut(expr) || isIncoming(expr) || isOutgoing(expr) || isCustomRelationExpr(expr);
|
|
40
43
|
}
|
|
41
44
|
// export const Expr = {
|
|
42
45
|
// isElementRef,
|
package/dist/types/model.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Element, Fqn } from './element';
|
|
2
2
|
import type { Relation, RelationID } from './relation';
|
|
3
|
-
import type { ComputedView,
|
|
3
|
+
import type { ComputedView, LikeC4View, ViewID } from './view';
|
|
4
4
|
export interface LikeC4Model {
|
|
5
5
|
elements: Record<Fqn, Element>;
|
|
6
6
|
relations: Record<RelationID, Relation>;
|
|
7
|
-
views: Record<ViewID,
|
|
7
|
+
views: Record<ViewID, LikeC4View>;
|
|
8
8
|
}
|
|
9
9
|
export interface LikeC4ComputedModel {
|
|
10
10
|
elements: Record<Fqn, Element>;
|
package/dist/types/relation.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ThemeColor } from './theme';
|
|
|
5
5
|
export type RelationID = Opaque<string, 'RelationID'>;
|
|
6
6
|
export type RelationshipKind = Opaque<string, 'RelationshipKind'>;
|
|
7
7
|
export type RelationshipLineType = 'dashed' | 'solid' | 'dotted';
|
|
8
|
-
export type RelationshipArrowType = 'none' | 'normal' | 'onormal' | 'diamond' | 'odiamond' | 'crow' | 'open' | 'vee';
|
|
8
|
+
export type RelationshipArrowType = 'none' | 'normal' | 'onormal' | 'dot' | 'odot' | 'diamond' | 'odiamond' | 'crow' | 'open' | 'vee';
|
|
9
9
|
export declare const DefaultLineStyle = "dashed";
|
|
10
10
|
export declare const DefaultArrowType = "normal";
|
|
11
11
|
export declare const DefaultRelationshipColor = "gray";
|
package/dist/types/view.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { IconUrl, NonEmptyArray, Point, XYPosition } from './_common';
|
|
2
2
|
import type { ElementKind, ElementShape, ElementStyle, Fqn, Tag } from './element';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ElementExpression, ElementPredicateExpression, Expression } from './expression';
|
|
4
4
|
import type { Opaque } from './opaque';
|
|
5
5
|
import type { RelationID, RelationshipArrowType, RelationshipLineType } from './relation';
|
|
6
|
-
import type {
|
|
6
|
+
import type { ThemeColor } from './theme';
|
|
7
7
|
export type ViewID = Opaque<string, 'ViewID'>;
|
|
8
8
|
export type ViewRuleExpression = {
|
|
9
9
|
include: Expression[];
|
|
@@ -28,7 +28,7 @@ export interface ViewRuleAutoLayout {
|
|
|
28
28
|
}
|
|
29
29
|
export declare function isViewRuleAutoLayout(rule: ViewRule): rule is ViewRuleAutoLayout;
|
|
30
30
|
export type ViewRule = ViewRuleExpression | ViewRuleStyle | ViewRuleAutoLayout;
|
|
31
|
-
export interface BasicView<ViewType extends 'element' | 'dynamic'
|
|
31
|
+
export interface BasicView<ViewType extends 'element' | 'dynamic'> {
|
|
32
32
|
readonly __?: ViewType;
|
|
33
33
|
readonly id: ViewID;
|
|
34
34
|
readonly title: string | null;
|
|
@@ -59,13 +59,13 @@ export interface BasicElementView extends BasicView<'element'> {
|
|
|
59
59
|
readonly viewOf?: Fqn;
|
|
60
60
|
readonly rules: ViewRule[];
|
|
61
61
|
}
|
|
62
|
-
export interface
|
|
62
|
+
export interface ScopedElementView extends BasicElementView {
|
|
63
63
|
readonly viewOf: Fqn;
|
|
64
64
|
}
|
|
65
65
|
export interface ExtendsElementView extends BasicElementView {
|
|
66
66
|
readonly extends: ViewID;
|
|
67
67
|
}
|
|
68
|
-
export type ElementView =
|
|
68
|
+
export type ElementView = ScopedElementView | ExtendsElementView | BasicElementView;
|
|
69
69
|
export interface DynamicViewStep {
|
|
70
70
|
readonly source: Fqn;
|
|
71
71
|
readonly target: Fqn;
|
|
@@ -73,7 +73,7 @@ export interface DynamicViewStep {
|
|
|
73
73
|
readonly isBackward?: boolean;
|
|
74
74
|
}
|
|
75
75
|
export type DynamicViewIncludeRule = {
|
|
76
|
-
include:
|
|
76
|
+
include: ElementPredicateExpression[];
|
|
77
77
|
};
|
|
78
78
|
export declare function isDynamicViewIncludeRule(rule: DynamicViewRule): rule is DynamicViewIncludeRule;
|
|
79
79
|
export type DynamicViewRule = DynamicViewIncludeRule | ViewRuleStyle | ViewRuleAutoLayout;
|
|
@@ -82,11 +82,11 @@ export interface DynamicView extends BasicView<'dynamic'> {
|
|
|
82
82
|
readonly steps: DynamicViewStep[];
|
|
83
83
|
readonly rules: DynamicViewRule[];
|
|
84
84
|
}
|
|
85
|
-
export type
|
|
86
|
-
export declare function isDynamicView(view:
|
|
87
|
-
export declare function isElementView(view:
|
|
88
|
-
export declare function isExtendsElementView(view:
|
|
89
|
-
export declare function
|
|
85
|
+
export type LikeC4View = ElementView | DynamicView;
|
|
86
|
+
export declare function isDynamicView(view: LikeC4View): view is DynamicView;
|
|
87
|
+
export declare function isElementView(view: LikeC4View): view is ElementView;
|
|
88
|
+
export declare function isExtendsElementView(view: LikeC4View): view is ExtendsElementView;
|
|
89
|
+
export declare function isScopedElementView(view: LikeC4View): view is ScopedElementView;
|
|
90
90
|
export type NodeId = Fqn;
|
|
91
91
|
export type EdgeId = Opaque<string, 'EdgeId'>;
|
|
92
92
|
export type StepEdgeIdLiteral = `step-${number}`;
|
|
@@ -119,6 +119,10 @@ export interface ComputedNode {
|
|
|
119
119
|
navigateTo?: ViewID;
|
|
120
120
|
level: number;
|
|
121
121
|
depth?: number;
|
|
122
|
+
/**
|
|
123
|
+
* If this node was customized in the view
|
|
124
|
+
*/
|
|
125
|
+
isCustomized?: boolean;
|
|
122
126
|
}
|
|
123
127
|
export interface ComputedEdge {
|
|
124
128
|
id: EdgeId;
|
|
@@ -131,6 +135,10 @@ export interface ComputedEdge {
|
|
|
131
135
|
line?: RelationshipLineType;
|
|
132
136
|
head?: RelationshipArrowType;
|
|
133
137
|
tail?: RelationshipArrowType;
|
|
138
|
+
/**
|
|
139
|
+
* If this edge is derived from custom relationship predicate
|
|
140
|
+
*/
|
|
141
|
+
isCustomized?: boolean;
|
|
134
142
|
/**
|
|
135
143
|
* For layouting purposes
|
|
136
144
|
* @default 'forward'
|
|
@@ -157,29 +165,15 @@ export type BBox = {
|
|
|
157
165
|
width: number;
|
|
158
166
|
height: number;
|
|
159
167
|
};
|
|
160
|
-
export interface DiagramLabel {
|
|
161
|
-
align: 'left' | 'right' | 'center';
|
|
162
|
-
fontStyle?: 'bold' | 'normal';
|
|
163
|
-
color?: ColorLiteral;
|
|
164
|
-
fontSize: number;
|
|
165
|
-
pt: Point;
|
|
166
|
-
width: number;
|
|
167
|
-
text: string;
|
|
168
|
-
}
|
|
169
168
|
export interface DiagramNode extends ComputedNode {
|
|
170
169
|
width: number;
|
|
171
170
|
height: number;
|
|
172
171
|
position: Point;
|
|
173
|
-
|
|
172
|
+
labelBBox: BBox;
|
|
174
173
|
}
|
|
175
174
|
export interface DiagramEdge extends ComputedEdge {
|
|
176
175
|
points: NonEmptyArray<Point>;
|
|
177
|
-
|
|
178
|
-
headArrowPoint?: Point;
|
|
179
|
-
tailArrow?: NonEmptyArray<Point>;
|
|
180
|
-
tailArrowPoint?: Point;
|
|
181
|
-
labels?: NonEmptyArray<DiagramLabel>;
|
|
182
|
-
labelBBox?: BBox;
|
|
176
|
+
labelBBox?: BBox | null;
|
|
183
177
|
}
|
|
184
178
|
export interface DiagramView extends Omit<ComputedView, 'nodes' | 'edges'> {
|
|
185
179
|
readonly nodes: DiagramNode[];
|
package/dist/types/view.js
CHANGED
|
@@ -21,7 +21,7 @@ export function isElementView(view) {
|
|
|
21
21
|
export function isExtendsElementView(view) {
|
|
22
22
|
return isElementView(view) && 'extends' in view;
|
|
23
23
|
}
|
|
24
|
-
export function
|
|
24
|
+
export function isScopedElementView(view) {
|
|
25
25
|
return isElementView(view) && 'viewOf' in view;
|
|
26
26
|
}
|
|
27
27
|
export function StepEdgeId(step) {
|
package/dist/utils/fqn.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Element, Fqn } from '../types';
|
|
2
|
+
type Predicate<T> = (x: T) => boolean;
|
|
2
3
|
export declare function nameFromFqn(fqn: Fqn): string;
|
|
3
4
|
export declare function isAncestor<E extends {
|
|
4
5
|
id: Fqn;
|
|
@@ -12,6 +13,9 @@ export declare function isDescendantOf<E extends {
|
|
|
12
13
|
export declare function notDescendantOf(ancestors: Element[]): (e: Element) => boolean;
|
|
13
14
|
export declare function commonAncestor(first: Fqn, second: Fqn): Fqn | null;
|
|
14
15
|
export declare function parentFqn(fqn: Fqn): Fqn | null;
|
|
16
|
+
export declare function parentFqnPredicate<T extends {
|
|
17
|
+
parent: Fqn | null;
|
|
18
|
+
}>(parent: Fqn): Predicate<T>;
|
|
15
19
|
/**
|
|
16
20
|
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
17
21
|
* (from closest to root)
|
|
@@ -31,4 +35,5 @@ export declare function compareFqnHierarchically<T extends string = string>(a: T
|
|
|
31
35
|
export declare function compareByFqnHierarchically<T extends {
|
|
32
36
|
id: string;
|
|
33
37
|
}>(a: T, b: T): number;
|
|
38
|
+
export {};
|
|
34
39
|
//# sourceMappingURL=fqn.d.ts.map
|
package/dist/utils/fqn.js
CHANGED
|
@@ -52,6 +52,10 @@ export function parentFqn(fqn) {
|
|
|
52
52
|
}
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
|
+
export function parentFqnPredicate(parent) {
|
|
56
|
+
const prefix = parent + '.';
|
|
57
|
+
return (e) => !!e.parent && (e.parent === parent || e.parent.startsWith(prefix));
|
|
58
|
+
}
|
|
55
59
|
/**
|
|
56
60
|
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
57
61
|
* (from closest to root)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://likec4.dev",
|
|
6
6
|
"author": "Denis Davydkov <denis@davydkov.com>",
|
|
@@ -66,16 +66,16 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"remeda": "^
|
|
69
|
+
"remeda": "^2.3.0",
|
|
70
70
|
"ts-custom-error": "^3.3.1",
|
|
71
|
-
"type-fest": "^4.
|
|
71
|
+
"type-fest": "^4.21.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@likec4/tsconfig": "1.
|
|
74
|
+
"@likec4/tsconfig": "1.5.0",
|
|
75
75
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
76
|
-
"execa": "^9.
|
|
77
|
-
"typescript": "^5.
|
|
78
|
-
"vitest": "~1.
|
|
76
|
+
"execa": "^9.3.0",
|
|
77
|
+
"typescript": "^5.5.3",
|
|
78
|
+
"vitest": "~1.6.0"
|
|
79
79
|
},
|
|
80
|
-
"packageManager": "yarn@4.3.
|
|
80
|
+
"packageManager": "yarn@4.3.1"
|
|
81
81
|
}
|
package/src/types/expression.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IconUrl } from './_common'
|
|
2
2
|
import type { BorderStyle, ElementKind, ElementShape, Fqn, Tag } from './element'
|
|
3
|
+
import type { RelationshipArrowType, RelationshipLineType } from './relation'
|
|
3
4
|
import type { ThemeColor } from './theme'
|
|
4
5
|
import type { ViewID } from './view'
|
|
5
6
|
|
|
@@ -17,6 +18,7 @@ interface BaseExpr {
|
|
|
17
18
|
inout?: never
|
|
18
19
|
incoming?: never
|
|
19
20
|
outgoing?: never
|
|
21
|
+
customRelation?: never
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface ElementRefExpr extends Omit<BaseExpr, 'element' | 'isDescedants'> {
|
|
@@ -89,6 +91,8 @@ export function isElement(expr: Expression): expr is ElementExpression {
|
|
|
89
91
|
|| isExpandedElementExpr(expr)
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
export type ElementPredicateExpression = ElementExpression | CustomElementExpr
|
|
95
|
+
|
|
92
96
|
export interface RelationExpr extends Omit<BaseExpr, 'source' | 'target'> {
|
|
93
97
|
source: ElementExpression
|
|
94
98
|
target: ElementExpression
|
|
@@ -118,13 +122,27 @@ export function isOutgoing(expr: Expression): expr is OutgoingExpr {
|
|
|
118
122
|
return 'outgoing' in expr
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
export
|
|
125
|
+
export interface CustomRelationExpr extends Omit<BaseExpr, 'customRelation'> {
|
|
126
|
+
customRelation: {
|
|
127
|
+
relation: RelationExpr
|
|
128
|
+
title?: string
|
|
129
|
+
color?: ThemeColor
|
|
130
|
+
line?: RelationshipLineType
|
|
131
|
+
head?: RelationshipArrowType
|
|
132
|
+
tail?: RelationshipArrowType
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export function isCustomRelationExpr(expr: Expression): expr is CustomRelationExpr {
|
|
136
|
+
return 'customRelation' in expr
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type RelationPredicateExpression = RelationExpr | InOutExpr | IncomingExpr | OutgoingExpr | CustomRelationExpr
|
|
122
140
|
|
|
123
|
-
export function isAnyRelation(expr: Expression): expr is
|
|
124
|
-
return isRelation(expr) || isInOut(expr) || isIncoming(expr) || isOutgoing(expr)
|
|
141
|
+
export function isAnyRelation(expr: Expression): expr is RelationPredicateExpression {
|
|
142
|
+
return isRelation(expr) || isInOut(expr) || isIncoming(expr) || isOutgoing(expr) || isCustomRelationExpr(expr)
|
|
125
143
|
}
|
|
126
144
|
|
|
127
|
-
export type Expression =
|
|
145
|
+
export type Expression = ElementPredicateExpression | RelationPredicateExpression
|
|
128
146
|
|
|
129
147
|
// export const Expr = {
|
|
130
148
|
// isElementRef,
|
package/src/types/model.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Element, Fqn } from './element'
|
|
2
2
|
import type { Relation, RelationID } from './relation'
|
|
3
|
-
import type { ComputedView,
|
|
3
|
+
import type { ComputedView, LikeC4View, ViewID } from './view'
|
|
4
4
|
|
|
5
5
|
export interface LikeC4Model {
|
|
6
6
|
elements: Record<Fqn, Element>
|
|
7
7
|
relations: Record<RelationID, Relation>
|
|
8
|
-
views: Record<ViewID,
|
|
8
|
+
views: Record<ViewID, LikeC4View>
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface LikeC4ComputedModel {
|
package/src/types/relation.ts
CHANGED
package/src/types/view.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { isNullish } from 'remeda'
|
|
2
2
|
import type { IconUrl, NonEmptyArray, Point, XYPosition } from './_common'
|
|
3
3
|
import type { ElementKind, ElementShape, ElementStyle, Fqn, Tag } from './element'
|
|
4
|
-
import type {
|
|
4
|
+
import type { ElementExpression, ElementPredicateExpression, Expression } from './expression'
|
|
5
5
|
import type { Opaque } from './opaque'
|
|
6
6
|
import type { RelationID, RelationshipArrowType, RelationshipLineType } from './relation'
|
|
7
|
-
import type {
|
|
7
|
+
import type { ThemeColor } from './theme'
|
|
8
8
|
|
|
9
9
|
// Full-qualified-name
|
|
10
10
|
export type ViewID = Opaque<string, 'ViewID'>
|
|
@@ -47,7 +47,7 @@ export function isViewRuleAutoLayout(rule: ViewRule): rule is ViewRuleAutoLayout
|
|
|
47
47
|
|
|
48
48
|
export type ViewRule = ViewRuleExpression | ViewRuleStyle | ViewRuleAutoLayout
|
|
49
49
|
|
|
50
|
-
export interface BasicView<ViewType extends 'element' | 'dynamic'
|
|
50
|
+
export interface BasicView<ViewType extends 'element' | 'dynamic'> {
|
|
51
51
|
readonly __?: ViewType
|
|
52
52
|
readonly id: ViewID
|
|
53
53
|
readonly title: string | null
|
|
@@ -81,14 +81,14 @@ export interface BasicElementView extends BasicView<'element'> {
|
|
|
81
81
|
readonly viewOf?: Fqn
|
|
82
82
|
readonly rules: ViewRule[]
|
|
83
83
|
}
|
|
84
|
-
export interface
|
|
84
|
+
export interface ScopedElementView extends BasicElementView {
|
|
85
85
|
readonly viewOf: Fqn
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
export interface ExtendsElementView extends BasicElementView {
|
|
89
89
|
readonly extends: ViewID
|
|
90
90
|
}
|
|
91
|
-
export type ElementView =
|
|
91
|
+
export type ElementView = ScopedElementView | ExtendsElementView | BasicElementView
|
|
92
92
|
|
|
93
93
|
export interface DynamicViewStep {
|
|
94
94
|
readonly source: Fqn
|
|
@@ -98,7 +98,7 @@ export interface DynamicViewStep {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export type DynamicViewIncludeRule = {
|
|
101
|
-
include:
|
|
101
|
+
include: ElementPredicateExpression[]
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
export function isDynamicViewIncludeRule(rule: DynamicViewRule): rule is DynamicViewIncludeRule {
|
|
@@ -114,27 +114,26 @@ export interface DynamicView extends BasicView<'dynamic'> {
|
|
|
114
114
|
readonly rules: DynamicViewRule[]
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
export type
|
|
117
|
+
export type LikeC4View = ElementView | DynamicView
|
|
118
118
|
|
|
119
|
-
export function isDynamicView(view:
|
|
119
|
+
export function isDynamicView(view: LikeC4View): view is DynamicView {
|
|
120
120
|
return view.__ === 'dynamic'
|
|
121
121
|
}
|
|
122
|
-
export function isElementView(view:
|
|
122
|
+
export function isElementView(view: LikeC4View): view is ElementView {
|
|
123
123
|
return isNullish(view.__) || view.__ === 'element'
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
export function isExtendsElementView(view:
|
|
126
|
+
export function isExtendsElementView(view: LikeC4View): view is ExtendsElementView {
|
|
127
127
|
return isElementView(view) && 'extends' in view
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
export function
|
|
130
|
+
export function isScopedElementView(view: LikeC4View): view is ScopedElementView {
|
|
131
131
|
return isElementView(view) && 'viewOf' in view
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
export type NodeId = Fqn
|
|
135
135
|
|
|
136
136
|
export type EdgeId = Opaque<string, 'EdgeId'>
|
|
137
|
-
|
|
138
137
|
export type StepEdgeIdLiteral = `step-${number}`
|
|
139
138
|
export type StepEdgeId = Opaque<StepEdgeIdLiteral, 'EdgeId'>
|
|
140
139
|
export function StepEdgeId(step: number): StepEdgeId {
|
|
@@ -177,6 +176,10 @@ export interface ComputedNode {
|
|
|
177
176
|
level: number
|
|
178
177
|
// For compound nodes, the max depth of nested nodes
|
|
179
178
|
depth?: number
|
|
179
|
+
/**
|
|
180
|
+
* If this node was customized in the view
|
|
181
|
+
*/
|
|
182
|
+
isCustomized?: boolean
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
export interface ComputedEdge {
|
|
@@ -190,7 +193,10 @@ export interface ComputedEdge {
|
|
|
190
193
|
line?: RelationshipLineType
|
|
191
194
|
head?: RelationshipArrowType
|
|
192
195
|
tail?: RelationshipArrowType
|
|
193
|
-
|
|
196
|
+
/**
|
|
197
|
+
* If this edge is derived from custom relationship predicate
|
|
198
|
+
*/
|
|
199
|
+
isCustomized?: boolean
|
|
194
200
|
/**
|
|
195
201
|
* For layouting purposes
|
|
196
202
|
* @default 'forward'
|
|
@@ -227,35 +233,17 @@ export type BBox = {
|
|
|
227
233
|
height: number
|
|
228
234
|
}
|
|
229
235
|
|
|
230
|
-
export interface DiagramLabel {
|
|
231
|
-
align: 'left' | 'right' | 'center'
|
|
232
|
-
fontStyle?: 'bold' | 'normal'
|
|
233
|
-
color?: ColorLiteral
|
|
234
|
-
fontSize: number
|
|
235
|
-
pt: Point
|
|
236
|
-
width: number
|
|
237
|
-
text: string
|
|
238
|
-
}
|
|
239
|
-
|
|
240
236
|
export interface DiagramNode extends ComputedNode {
|
|
241
237
|
width: number
|
|
242
238
|
height: number
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
239
|
+
// Absolute position, top left
|
|
240
|
+
position: Point
|
|
241
|
+
labelBBox: BBox
|
|
246
242
|
}
|
|
247
243
|
|
|
248
244
|
export interface DiagramEdge extends ComputedEdge {
|
|
249
245
|
points: NonEmptyArray<Point>
|
|
250
|
-
|
|
251
|
-
headArrow?: NonEmptyArray<Point>
|
|
252
|
-
// Draw arrow from the last point of the edge to this point
|
|
253
|
-
headArrowPoint?: Point
|
|
254
|
-
tailArrow?: NonEmptyArray<Point>
|
|
255
|
-
// Draw arrow from the first point of the edge to this point
|
|
256
|
-
tailArrowPoint?: Point
|
|
257
|
-
labels?: NonEmptyArray<DiagramLabel>
|
|
258
|
-
labelBBox?: BBox
|
|
246
|
+
labelBBox?: BBox | null
|
|
259
247
|
}
|
|
260
248
|
|
|
261
249
|
export interface DiagramView extends Omit<ComputedView, 'nodes' | 'edges'> {
|
package/src/utils/fqn.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Element, Fqn } from '../types'
|
|
2
2
|
import { isString } from './guards'
|
|
3
3
|
|
|
4
|
+
type Predicate<T> = (x: T) => boolean
|
|
5
|
+
|
|
4
6
|
export function nameFromFqn(fqn: Fqn) {
|
|
5
7
|
const lastDot = fqn.lastIndexOf('.')
|
|
6
8
|
if (lastDot > 0) {
|
|
@@ -64,6 +66,11 @@ export function parentFqn(fqn: Fqn): Fqn | null {
|
|
|
64
66
|
return null
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
export function parentFqnPredicate<T extends { parent: Fqn | null }>(parent: Fqn): Predicate<T> {
|
|
70
|
+
const prefix = parent + '.'
|
|
71
|
+
return (e: T) => !!e.parent && (e.parent === parent || e.parent.startsWith(prefix))
|
|
72
|
+
}
|
|
73
|
+
|
|
67
74
|
/**
|
|
68
75
|
* Get all ancestor elements (i.e. parent, parent’s parent, etc.)
|
|
69
76
|
* (from closest to root)
|