@likec4/core 1.1.1 → 1.2.1
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/dist/colors/element.d.ts +1 -0
- package/dist/colors/index.d.ts +1 -0
- package/dist/colors/relationships.d.ts +1 -0
- package/dist/errors/errors.spec.d.ts +2 -0
- package/dist/errors/errors.spec.js +69 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +7 -1
- package/dist/index.d.ts +1 -0
- package/dist/types/_common.d.ts +1 -0
- package/dist/types/element.d.ts +1 -0
- package/dist/types/expression.d.ts +1 -0
- package/dist/types/index.d.ts +1 -2
- package/dist/types/index.js +2 -3
- package/dist/types/model.d.ts +3 -3
- package/dist/types/opaque.d.ts +1 -0
- package/dist/types/relation.d.ts +1 -0
- package/dist/types/theme.d.ts +1 -0
- package/dist/types/view.d.ts +133 -8
- package/dist/types/view.js +31 -3
- package/dist/utils/fqn.d.ts +1 -0
- package/dist/utils/fqn.spec.d.ts +2 -0
- package/dist/utils/fqn.spec.js +82 -0
- package/dist/utils/guards.d.ts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/promises.d.ts +1 -0
- package/dist/utils/relations.d.ts +1 -0
- package/dist/utils/relations.spec.d.ts +2 -0
- package/dist/utils/relations.spec.js +210 -0
- package/package.json +6 -6
- package/src/colors/element.ts +80 -0
- package/src/colors/index.ts +12 -0
- package/src/colors/relationships.ts +54 -0
- package/src/errors/errors.spec.ts +88 -0
- package/src/errors/index.ts +120 -0
- package/src/index.ts +9 -0
- package/src/reset.d.ts +2 -0
- package/src/types/_common.ts +5 -0
- package/src/types/element.ts +56 -0
- package/src/types/expression.ts +140 -0
- package/src/types/index.ts +10 -0
- package/src/types/model.ts +15 -0
- package/src/types/opaque.ts +108 -0
- package/src/types/relation.ts +38 -0
- package/src/types/theme.ts +46 -0
- package/src/types/view.ts +263 -0
- package/src/utils/fqn.spec.ts +105 -0
- package/src/utils/fqn.ts +112 -0
- package/src/utils/guards.ts +10 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/promises.ts +9 -0
- package/src/utils/relations.spec.ts +268 -0
- package/src/utils/relations.ts +104 -0
- package/dist/types/computed-view.d.ts +0 -52
- package/dist/types/computed-view.js +0 -1
- package/dist/types/diagram.d.ts +0 -40
- package/dist/types/diagram.js +0 -1
package/dist/colors/element.d.ts
CHANGED
package/dist/colors/index.d.ts
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { BaseError, InvalidArgError, InvalidModelError, invariant, InvariantError, NonExhaustiveError, normalizeError, NullableError, RelationRefError, UnknownError } from './index';
|
|
3
|
+
describe('errors', () => {
|
|
4
|
+
describe('normalizeError', () => {
|
|
5
|
+
it.each([
|
|
6
|
+
{ error: new BaseError('BaseError') },
|
|
7
|
+
{ error: new RelationRefError('RelationRefError') },
|
|
8
|
+
{ error: new UnknownError('UnknownError') },
|
|
9
|
+
{ error: new InvariantError('InvariantError') },
|
|
10
|
+
{ error: new NonExhaustiveError('NonExhaustiveError') },
|
|
11
|
+
{ error: new InvalidModelError('InvalidModelError') },
|
|
12
|
+
{ error: new NullableError('NullableError') },
|
|
13
|
+
{ error: new InvalidArgError('InvalidArgError') }
|
|
14
|
+
])('should return $error.name as-is', ({ error }) => {
|
|
15
|
+
expect(normalizeError(error)).toBe(error);
|
|
16
|
+
});
|
|
17
|
+
it.skip('should wrap an error', () => {
|
|
18
|
+
const cause = new Error('original test');
|
|
19
|
+
const error = normalizeError(cause);
|
|
20
|
+
expect(error).toBeInstanceOf(UnknownError);
|
|
21
|
+
expect(error).to.include({
|
|
22
|
+
name: 'UnknownError',
|
|
23
|
+
message: 'original test'
|
|
24
|
+
});
|
|
25
|
+
expect(error).to.have.property('cause').that.eq(cause);
|
|
26
|
+
expect(error)
|
|
27
|
+
.to.have.property('stack')
|
|
28
|
+
.that.is.a('string')
|
|
29
|
+
.and.includes('UnknownError: original test');
|
|
30
|
+
});
|
|
31
|
+
it('should wrap a string', () => {
|
|
32
|
+
const cause = 'error string';
|
|
33
|
+
const error = normalizeError(cause);
|
|
34
|
+
expect(error).toBeInstanceOf(UnknownError);
|
|
35
|
+
expect(error).to.include({
|
|
36
|
+
name: 'UnknownError',
|
|
37
|
+
message: cause
|
|
38
|
+
});
|
|
39
|
+
expect(error).not.to.have.property('cause');
|
|
40
|
+
expect(error).to.have.property('stack').that.is.a('string');
|
|
41
|
+
});
|
|
42
|
+
// Fails on serializiation of AST
|
|
43
|
+
it.skip('should wrap an object', () => {
|
|
44
|
+
const cause = { foo: 'bar' };
|
|
45
|
+
const error = normalizeError(cause);
|
|
46
|
+
expect(error).toBeInstanceOf(UnknownError);
|
|
47
|
+
expect(error).to.include({
|
|
48
|
+
name: 'UnknownError',
|
|
49
|
+
message: '{"foo":"bar"}'
|
|
50
|
+
});
|
|
51
|
+
expect(error).not.to.have.property('cause');
|
|
52
|
+
expect(error).to.have.property('stack').that.is.a('string');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('invariant', () => {
|
|
57
|
+
it('should throw an error if the condition fails', () => {
|
|
58
|
+
expect(() => invariant(false)).toThrow('Invariant failed');
|
|
59
|
+
});
|
|
60
|
+
it('should throw an error if the condition is null', () => {
|
|
61
|
+
expect(() => invariant(null)).toThrow(InvariantError);
|
|
62
|
+
});
|
|
63
|
+
it('should not throw an error if the condition passes', () => {
|
|
64
|
+
expect(() => invariant(true)).not.toThrow();
|
|
65
|
+
});
|
|
66
|
+
it('should throw an error with the provided message if the condition fails', () => {
|
|
67
|
+
expect(() => invariant(false, 'test')).toThrow('test');
|
|
68
|
+
});
|
|
69
|
+
});
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -63,7 +63,13 @@ export function normalizeError(e) {
|
|
|
63
63
|
}
|
|
64
64
|
const message = isString(e) ? e : String(e);
|
|
65
65
|
const error = new UnknownError(message);
|
|
66
|
-
|
|
66
|
+
try {
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
Error.captureStackTrace(error, normalizeError);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Ignore
|
|
72
|
+
}
|
|
67
73
|
return error;
|
|
68
74
|
}
|
|
69
75
|
// Throw an error if the condition fails
|
package/dist/index.d.ts
CHANGED
package/dist/types/_common.d.ts
CHANGED
package/dist/types/element.d.ts
CHANGED
|
@@ -79,3 +79,4 @@ export type AnyRelationExpression = RelationExpr | InOutExpr | IncomingExpr | Ou
|
|
|
79
79
|
export declare function isAnyRelation(expr: Expression): expr is AnyRelationExpression;
|
|
80
80
|
export type Expression = ElementExpression | CustomElementExpr | AnyRelationExpression;
|
|
81
81
|
export {};
|
|
82
|
+
//# sourceMappingURL=expression.d.ts.map
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export * from './_common';
|
|
2
|
-
export * from './computed-view';
|
|
3
|
-
export * from './diagram';
|
|
4
2
|
export * from './element';
|
|
5
3
|
export * from './expression';
|
|
6
4
|
export * from './model';
|
|
@@ -9,3 +7,4 @@ export * from './relation';
|
|
|
9
7
|
export * from './theme';
|
|
10
8
|
export * from './view';
|
|
11
9
|
export * as Expr from './expression';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/types/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export * from './_common';
|
|
2
|
-
export * from './computed-view';
|
|
3
|
-
export * from './diagram';
|
|
4
2
|
export * from './element';
|
|
5
3
|
export * from './expression';
|
|
6
4
|
export * from './model';
|
|
@@ -8,4 +6,5 @@ export * from './opaque';
|
|
|
8
6
|
export * from './relation';
|
|
9
7
|
export * from './theme';
|
|
10
8
|
export * from './view';
|
|
11
|
-
|
|
9
|
+
import * as Expr_1 from './expression';
|
|
10
|
+
export { Expr_1 as Expr };
|
package/dist/types/model.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { ComputedView } from './computed-view';
|
|
2
1
|
import type { Element, Fqn } from './element';
|
|
3
2
|
import type { Relation, RelationID } from './relation';
|
|
4
|
-
import type {
|
|
3
|
+
import type { ComputedView, View, ViewID } from './view';
|
|
5
4
|
export interface LikeC4Model {
|
|
6
5
|
elements: Record<Fqn, Element>;
|
|
7
6
|
relations: Record<RelationID, Relation>;
|
|
8
|
-
views: Record<ViewID,
|
|
7
|
+
views: Record<ViewID, View>;
|
|
9
8
|
}
|
|
10
9
|
export interface LikeC4ComputedModel {
|
|
11
10
|
elements: Record<Fqn, Element>;
|
|
12
11
|
relations: Record<RelationID, Relation>;
|
|
13
12
|
views: Record<ViewID, ComputedView>;
|
|
14
13
|
}
|
|
14
|
+
//# sourceMappingURL=model.d.ts.map
|
package/dist/types/opaque.d.ts
CHANGED
package/dist/types/relation.d.ts
CHANGED
package/dist/types/theme.d.ts
CHANGED
package/dist/types/view.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { IconUrl, NonEmptyArray } from './_common';
|
|
2
|
-
import type { ElementShape, ElementStyle, Fqn, Tag } from './element';
|
|
3
|
-
import type { ElementExpression, Expression } from './expression';
|
|
2
|
+
import type { ElementKind, ElementShape, ElementStyle, Fqn, Tag } from './element';
|
|
3
|
+
import type { CustomElementExpr, ElementExpression, Expression } from './expression';
|
|
4
4
|
import type { Opaque } from './opaque';
|
|
5
|
-
import type {
|
|
5
|
+
import type { RelationID, RelationshipArrowType, RelationshipLineType } from './relation';
|
|
6
|
+
import type { ColorLiteral, ThemeColor } from './theme';
|
|
6
7
|
export type ViewID = Opaque<string, 'ViewID'>;
|
|
7
8
|
export type ViewRuleExpression = {
|
|
8
9
|
include: Expression[];
|
|
@@ -27,14 +28,13 @@ export interface ViewRuleAutoLayout {
|
|
|
27
28
|
}
|
|
28
29
|
export declare function isViewRuleAutoLayout(rule: ViewRule): rule is ViewRuleAutoLayout;
|
|
29
30
|
export type ViewRule = ViewRuleExpression | ViewRuleStyle | ViewRuleAutoLayout;
|
|
30
|
-
export interface
|
|
31
|
+
export interface BasicView<ViewType extends 'element' | 'dynamic' = 'element' | 'dynamic'> {
|
|
32
|
+
readonly __?: ViewType;
|
|
31
33
|
readonly id: ViewID;
|
|
32
|
-
readonly viewOf?: Fqn;
|
|
33
34
|
readonly title: string | null;
|
|
34
35
|
readonly description: string | null;
|
|
35
36
|
readonly tags: NonEmptyArray<Tag> | null;
|
|
36
37
|
readonly links: NonEmptyArray<string> | null;
|
|
37
|
-
readonly rules: ViewRule[];
|
|
38
38
|
/**
|
|
39
39
|
* URI to the source file of this view.
|
|
40
40
|
* Undefined if the view is auto-generated.
|
|
@@ -51,12 +51,137 @@ export interface BasicElementView {
|
|
|
51
51
|
*/
|
|
52
52
|
readonly relativePath?: string;
|
|
53
53
|
}
|
|
54
|
+
export interface BasicElementView extends BasicView<'element'> {
|
|
55
|
+
readonly viewOf?: Fqn;
|
|
56
|
+
readonly rules: ViewRule[];
|
|
57
|
+
}
|
|
54
58
|
export interface StrictElementView extends BasicElementView {
|
|
55
59
|
readonly viewOf: Fqn;
|
|
56
60
|
}
|
|
57
|
-
export declare function isStrictElementView(view: ElementView): view is StrictElementView;
|
|
58
61
|
export interface ExtendsElementView extends BasicElementView {
|
|
59
62
|
readonly extends: ViewID;
|
|
60
63
|
}
|
|
61
|
-
export declare function isExtendsElementView(view: ElementView): view is ExtendsElementView;
|
|
62
64
|
export type ElementView = StrictElementView | ExtendsElementView | BasicElementView;
|
|
65
|
+
export interface DynamicViewStep {
|
|
66
|
+
readonly source: Fqn;
|
|
67
|
+
readonly target: Fqn;
|
|
68
|
+
readonly title: string | null;
|
|
69
|
+
readonly isBackward?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export type DynamicViewIncludeRule = {
|
|
72
|
+
include: (ElementExpression | CustomElementExpr)[];
|
|
73
|
+
};
|
|
74
|
+
export declare function isDynamicViewIncludeRule(rule: DynamicViewRule): rule is DynamicViewIncludeRule;
|
|
75
|
+
export type DynamicViewRule = DynamicViewIncludeRule | ViewRuleStyle | ViewRuleAutoLayout;
|
|
76
|
+
export interface DynamicView extends BasicView<'dynamic'> {
|
|
77
|
+
readonly __: 'dynamic';
|
|
78
|
+
readonly steps: DynamicViewStep[];
|
|
79
|
+
readonly rules: DynamicViewRule[];
|
|
80
|
+
}
|
|
81
|
+
export type View = ElementView | DynamicView;
|
|
82
|
+
export declare function isDynamicView(view: View): view is DynamicView;
|
|
83
|
+
export declare function isElementView(view: View): view is ElementView;
|
|
84
|
+
export declare function isExtendsElementView(view: View): view is ExtendsElementView;
|
|
85
|
+
export declare function isStrictElementView(view: View): view is StrictElementView;
|
|
86
|
+
export type NodeId = Fqn;
|
|
87
|
+
export type EdgeId = Opaque<string, 'EdgeId'>;
|
|
88
|
+
export type StepEdgeIdLiteral = `step-${number}`;
|
|
89
|
+
export type StepEdgeId = Opaque<StepEdgeIdLiteral, 'EdgeId'>;
|
|
90
|
+
export declare function StepEdgeId(step: number): StepEdgeId;
|
|
91
|
+
export declare function isStepEdgeId(id: string): id is StepEdgeId;
|
|
92
|
+
export declare function extractStep(id: EdgeId): number;
|
|
93
|
+
export interface ComputedNode {
|
|
94
|
+
id: NodeId;
|
|
95
|
+
kind: ElementKind;
|
|
96
|
+
parent: NodeId | null;
|
|
97
|
+
title: string;
|
|
98
|
+
description: string | null;
|
|
99
|
+
technology: string | null;
|
|
100
|
+
tags: NonEmptyArray<Tag> | null;
|
|
101
|
+
links: NonEmptyArray<string> | null;
|
|
102
|
+
children: NodeId[];
|
|
103
|
+
inEdges: EdgeId[];
|
|
104
|
+
outEdges: EdgeId[];
|
|
105
|
+
shape: ElementShape;
|
|
106
|
+
/**
|
|
107
|
+
* @deprecated Use `style` instead
|
|
108
|
+
*/
|
|
109
|
+
color: ThemeColor;
|
|
110
|
+
/**
|
|
111
|
+
* @deprecated Use `style` instead
|
|
112
|
+
*/
|
|
113
|
+
icon?: IconUrl;
|
|
114
|
+
style: ElementStyle;
|
|
115
|
+
navigateTo?: ViewID;
|
|
116
|
+
level: number;
|
|
117
|
+
depth?: number;
|
|
118
|
+
}
|
|
119
|
+
export interface ComputedEdge {
|
|
120
|
+
id: EdgeId;
|
|
121
|
+
parent: NodeId | null;
|
|
122
|
+
source: NodeId;
|
|
123
|
+
target: NodeId;
|
|
124
|
+
label: string | null;
|
|
125
|
+
relations: RelationID[];
|
|
126
|
+
color?: ThemeColor;
|
|
127
|
+
line?: RelationshipLineType;
|
|
128
|
+
head?: RelationshipArrowType;
|
|
129
|
+
tail?: RelationshipArrowType;
|
|
130
|
+
/**
|
|
131
|
+
* For layouting purposes
|
|
132
|
+
* @default 'forward'
|
|
133
|
+
*/
|
|
134
|
+
dir?: 'forward' | 'back';
|
|
135
|
+
}
|
|
136
|
+
export interface ComputedElementView extends Omit<ElementView, 'rules'> {
|
|
137
|
+
readonly extends?: ViewID;
|
|
138
|
+
readonly autoLayout: ViewRuleAutoLayout['autoLayout'];
|
|
139
|
+
readonly nodes: ComputedNode[];
|
|
140
|
+
readonly edges: ComputedEdge[];
|
|
141
|
+
}
|
|
142
|
+
export interface ComputedDynamicView extends Omit<DynamicView, 'rules' | 'steps'> {
|
|
143
|
+
readonly autoLayout: ViewRuleAutoLayout['autoLayout'];
|
|
144
|
+
readonly nodes: ComputedNode[];
|
|
145
|
+
readonly edges: ComputedEdge[];
|
|
146
|
+
}
|
|
147
|
+
export declare function isComputedDynamicView(view: ComputedView): view is ComputedDynamicView;
|
|
148
|
+
export type ComputedView = ComputedElementView | ComputedDynamicView;
|
|
149
|
+
export declare function isComputedElementView(view: ComputedView): view is ComputedElementView;
|
|
150
|
+
export type Point = readonly [x: number, y: number];
|
|
151
|
+
export type BBox = {
|
|
152
|
+
x: number;
|
|
153
|
+
y: number;
|
|
154
|
+
width: number;
|
|
155
|
+
height: number;
|
|
156
|
+
};
|
|
157
|
+
export interface DiagramLabel {
|
|
158
|
+
align: 'left' | 'right' | 'center';
|
|
159
|
+
fontStyle?: 'bold' | 'normal';
|
|
160
|
+
color?: ColorLiteral;
|
|
161
|
+
fontSize: number;
|
|
162
|
+
pt: Point;
|
|
163
|
+
width: number;
|
|
164
|
+
text: string;
|
|
165
|
+
}
|
|
166
|
+
export interface DiagramNode extends ComputedNode {
|
|
167
|
+
width: number;
|
|
168
|
+
height: number;
|
|
169
|
+
position: Point;
|
|
170
|
+
labels: DiagramLabel[];
|
|
171
|
+
}
|
|
172
|
+
export interface DiagramEdge extends ComputedEdge {
|
|
173
|
+
points: NonEmptyArray<Point>;
|
|
174
|
+
headArrow?: NonEmptyArray<Point>;
|
|
175
|
+
headArrowPoint?: Point;
|
|
176
|
+
tailArrow?: NonEmptyArray<Point>;
|
|
177
|
+
tailArrowPoint?: Point;
|
|
178
|
+
labels?: NonEmptyArray<DiagramLabel>;
|
|
179
|
+
labelBBox?: BBox;
|
|
180
|
+
}
|
|
181
|
+
export interface DiagramView extends Omit<ComputedView, 'nodes' | 'edges'> {
|
|
182
|
+
readonly nodes: DiagramNode[];
|
|
183
|
+
readonly edges: DiagramEdge[];
|
|
184
|
+
readonly width: number;
|
|
185
|
+
readonly height: number;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=view.d.ts.map
|
package/dist/types/view.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNullish } from 'remeda';
|
|
1
2
|
export function isViewRuleExpression(rule) {
|
|
2
3
|
return (('include' in rule && Array.isArray(rule.include))
|
|
3
4
|
|| ('exclude' in rule && Array.isArray(rule.exclude)));
|
|
@@ -8,9 +9,36 @@ export function isViewRuleStyle(rule) {
|
|
|
8
9
|
export function isViewRuleAutoLayout(rule) {
|
|
9
10
|
return 'autoLayout' in rule;
|
|
10
11
|
}
|
|
11
|
-
export function
|
|
12
|
-
return '
|
|
12
|
+
export function isDynamicViewIncludeRule(rule) {
|
|
13
|
+
return 'include' in rule && Array.isArray(rule.include);
|
|
14
|
+
}
|
|
15
|
+
export function isDynamicView(view) {
|
|
16
|
+
return view.__ === 'dynamic';
|
|
17
|
+
}
|
|
18
|
+
export function isElementView(view) {
|
|
19
|
+
return isNullish(view.__) || view.__ === 'element';
|
|
13
20
|
}
|
|
14
21
|
export function isExtendsElementView(view) {
|
|
15
|
-
return 'extends' in view;
|
|
22
|
+
return isElementView(view) && 'extends' in view;
|
|
23
|
+
}
|
|
24
|
+
export function isStrictElementView(view) {
|
|
25
|
+
return isElementView(view) && 'viewOf' in view;
|
|
26
|
+
}
|
|
27
|
+
export function StepEdgeId(step) {
|
|
28
|
+
return `step-${String(step).padStart(3, '0')}`;
|
|
29
|
+
}
|
|
30
|
+
export function isStepEdgeId(id) {
|
|
31
|
+
return id.startsWith('step-');
|
|
32
|
+
}
|
|
33
|
+
export function extractStep(id) {
|
|
34
|
+
if (!isStepEdgeId(id)) {
|
|
35
|
+
throw new Error(`Invalid step edge id: ${id}`);
|
|
36
|
+
}
|
|
37
|
+
return Number(id.slice('step-'.length));
|
|
38
|
+
}
|
|
39
|
+
export function isComputedDynamicView(view) {
|
|
40
|
+
return view.__ === 'dynamic';
|
|
41
|
+
}
|
|
42
|
+
export function isComputedElementView(view) {
|
|
43
|
+
return isNullish(view.__) || view.__ === 'element';
|
|
16
44
|
}
|
package/dist/utils/fqn.d.ts
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { ancestorsFqn, commonAncestor, compareFqnHierarchically, isAncestor, isDescendantOf, notDescendantOf, parentFqn } from './fqn';
|
|
3
|
+
const el = (id) => ({ id });
|
|
4
|
+
describe('parentFqn', () => {
|
|
5
|
+
it('should return null if no parent', () => {
|
|
6
|
+
expect(parentFqn('a')).toBeNull();
|
|
7
|
+
});
|
|
8
|
+
it('should return parent', () => {
|
|
9
|
+
expect(parentFqn('a.b')).toBe('a');
|
|
10
|
+
expect(parentFqn('a.b.c')).toBe('a.b');
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
describe('ancestorsFqn', () => {
|
|
14
|
+
it('should return empty array if no parent', () => {
|
|
15
|
+
expect(ancestorsFqn('a')).toEqual([]);
|
|
16
|
+
});
|
|
17
|
+
it('should return ancestors', () => {
|
|
18
|
+
expect(ancestorsFqn('a.b.c.d.e')).toEqual(['a.b.c.d', 'a.b.c', 'a.b', 'a']);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe('commonAncestor', () => {
|
|
22
|
+
it('should return null if no common ancestor', () => {
|
|
23
|
+
expect(commonAncestor('a', 'b')).toBeNull();
|
|
24
|
+
expect(commonAncestor('a.b', 'c.d')).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
it('should return common ancestor', () => {
|
|
27
|
+
expect(commonAncestor('a.b', 'a.c')).toBe('a');
|
|
28
|
+
expect(commonAncestor('a.b.c', 'a.b.e')).toBe('a.b');
|
|
29
|
+
expect(commonAncestor('a.b.c.d.e', 'a.b.c.d')).toBe('a.b.c');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('isAncestor', () => {
|
|
33
|
+
it('should return true if ancestor', () => {
|
|
34
|
+
expect(isAncestor('a', 'a.b')).toBe(true);
|
|
35
|
+
expect(isAncestor('a.b', 'a.b.c')).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
it('should return false if not ancestor', () => {
|
|
38
|
+
expect(isAncestor('a', 'b')).toBe(false);
|
|
39
|
+
expect(isAncestor('a.b', 'a')).toBe(false);
|
|
40
|
+
expect(isAncestor('a.b', 'b.a')).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('isDescendantOf', () => {
|
|
44
|
+
const predicate = isDescendantOf(['a', 'b', 'a.b', 'a.b.c'].map(el));
|
|
45
|
+
it('should return true if isDescendantOf', () => {
|
|
46
|
+
expect(predicate(el('a'))).toBe(true);
|
|
47
|
+
expect(predicate(el('b.c'))).toBe(true);
|
|
48
|
+
expect(predicate(el('a.b.c.d.e'))).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it('should return false if not descendantOf', () => {
|
|
51
|
+
expect(predicate(el('c'))).toBe(false);
|
|
52
|
+
expect(predicate(el('ac'))).toBe(false);
|
|
53
|
+
expect(predicate(el('d.a.c'))).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('notDescendantOf', () => {
|
|
57
|
+
const predicate = notDescendantOf(['a', 'b', 'a.b', 'a.b.c'].map(el));
|
|
58
|
+
it('should return true if notDescendantOf', () => {
|
|
59
|
+
expect(predicate(el('c'))).toBe(true);
|
|
60
|
+
expect(predicate(el('ac'))).toBe(true);
|
|
61
|
+
expect(predicate(el('d.a.c'))).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('should return false if descendantOf', () => {
|
|
64
|
+
expect(predicate(el('a'))).toBe(false);
|
|
65
|
+
expect(predicate(el('b.c'))).toBe(false);
|
|
66
|
+
expect(predicate(el('a.b.c.d.e'))).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('compareFqnHierarchically', () => {
|
|
70
|
+
it('should compare hierarchically', () => {
|
|
71
|
+
expect(['a', 'b', 'a.b', 'a.b.c', 'a.c.c'].sort(compareFqnHierarchically)).toEqual([
|
|
72
|
+
'a',
|
|
73
|
+
'b',
|
|
74
|
+
'a.b',
|
|
75
|
+
'a.b.c',
|
|
76
|
+
'a.c.c'
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
it('should preserve initial order', () => {
|
|
80
|
+
expect(['aaa', 'aa', 'a', 'aaa.c', 'aa.b', 'a.c', 'a.b'].sort(compareFqnHierarchically)).toEqual(['aaa', 'aa', 'a', 'aaa.c', 'aa.b', 'a.c', 'a.b']);
|
|
81
|
+
});
|
|
82
|
+
});
|
package/dist/utils/guards.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ import type { NonEmptyArray } from '../types';
|
|
|
2
2
|
export { hasAtLeast } from 'remeda';
|
|
3
3
|
export declare function isString(value: unknown): value is string;
|
|
4
4
|
export declare function isNonEmptyArray<A>(arr: ArrayLike<A> | undefined): arr is NonEmptyArray<A>;
|
|
5
|
+
//# sourceMappingURL=guards.d.ts.map
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/promises.d.ts
CHANGED