@likec4/core 1.2.0 → 1.2.2
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 -0
- package/dist/types/index.js +2 -1
- package/dist/types/model.d.ts +1 -0
- 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 +1 -0
- 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/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
package/dist/types/index.js
CHANGED
package/dist/types/model.d.ts
CHANGED
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
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
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { compareRelations, Relations } from './relations';
|
|
3
|
+
const { isAnyBetween, isAnyInOut, isBetween, isIncoming, isInside, isOutgoing } = Relations;
|
|
4
|
+
const relations = [
|
|
5
|
+
{
|
|
6
|
+
id: 'customer:cloud.frontend.dashboard',
|
|
7
|
+
source: 'customer',
|
|
8
|
+
target: 'cloud.frontend.dashboard',
|
|
9
|
+
title: ''
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: 'support:cloud.frontend.adminPanel',
|
|
13
|
+
source: 'support',
|
|
14
|
+
target: 'cloud.frontend.adminPanel',
|
|
15
|
+
title: ''
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'cloud.backend.storage:amazon.s3',
|
|
19
|
+
source: 'cloud.backend.storage',
|
|
20
|
+
target: 'amazon.s3',
|
|
21
|
+
title: ''
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'amazon.api:cloud.backend.graphql',
|
|
25
|
+
source: 'amazon.api',
|
|
26
|
+
target: 'cloud.backend.graphql',
|
|
27
|
+
title: ''
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'cloud.backend.graphql:cloud.backend.storage',
|
|
31
|
+
source: 'cloud.backend.graphql',
|
|
32
|
+
target: 'cloud.backend.storage',
|
|
33
|
+
title: ''
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'cloud.frontend.dashboard:cloud.backend.graphql',
|
|
37
|
+
source: 'cloud.frontend.dashboard',
|
|
38
|
+
target: 'cloud.backend.graphql',
|
|
39
|
+
title: ''
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'cloud.frontend.adminPanel:cloud.backend.graphql',
|
|
43
|
+
source: 'cloud.frontend.adminPanel',
|
|
44
|
+
target: 'cloud.backend.graphql',
|
|
45
|
+
title: ''
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
describe('relation predicates', () => {
|
|
49
|
+
const expectRelations = (predicate) => expect(relations.filter(predicate).map(r => r.id));
|
|
50
|
+
const customer = 'customer';
|
|
51
|
+
const cloud = 'cloud';
|
|
52
|
+
const frontend = 'cloud.frontend';
|
|
53
|
+
const backend = 'cloud.backend';
|
|
54
|
+
it('isBetween: cloud.frontend -> cloud.backend', () => {
|
|
55
|
+
expectRelations(isBetween(frontend, backend)).toEqual([
|
|
56
|
+
'cloud.frontend.dashboard:cloud.backend.graphql',
|
|
57
|
+
'cloud.frontend.adminPanel:cloud.backend.graphql'
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
it('isBetween: cloud.frontend.dashboard -> cloud.backend', () => {
|
|
61
|
+
expectRelations(isBetween('cloud.frontend.dashboard', backend)).toEqual([
|
|
62
|
+
'cloud.frontend.dashboard:cloud.backend.graphql'
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
it('isBetween: cloud.backend -> cloud.frontend', () => {
|
|
66
|
+
expectRelations(isBetween(backend, frontend)).toEqual([]);
|
|
67
|
+
});
|
|
68
|
+
it('isBetween: cloud.backend -> cloud.backend', () => {
|
|
69
|
+
expectRelations(isBetween(backend, backend)).toEqual([
|
|
70
|
+
'cloud.backend.graphql:cloud.backend.storage'
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
it('isBetween: customer -> cloud', () => {
|
|
74
|
+
expectRelations(isBetween(customer, cloud)).toEqual(['customer:cloud.frontend.dashboard']);
|
|
75
|
+
});
|
|
76
|
+
it('isIncoming: customer', () => {
|
|
77
|
+
expectRelations(isIncoming(customer)).toEqual([]);
|
|
78
|
+
});
|
|
79
|
+
it('isIncoming: cloud', () => {
|
|
80
|
+
expectRelations(isIncoming(cloud)).toEqual([
|
|
81
|
+
'customer:cloud.frontend.dashboard',
|
|
82
|
+
'support:cloud.frontend.adminPanel',
|
|
83
|
+
'amazon.api:cloud.backend.graphql'
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
it('isIncoming: cloud.frontend', () => {
|
|
87
|
+
expectRelations(isIncoming(frontend)).toEqual([
|
|
88
|
+
'customer:cloud.frontend.dashboard',
|
|
89
|
+
'support:cloud.frontend.adminPanel'
|
|
90
|
+
]);
|
|
91
|
+
});
|
|
92
|
+
it('isIncoming: cloud.frontend.dashboard', () => {
|
|
93
|
+
expectRelations(isIncoming('cloud.frontend.dashboard')).toEqual([
|
|
94
|
+
'customer:cloud.frontend.dashboard'
|
|
95
|
+
]);
|
|
96
|
+
});
|
|
97
|
+
it('isOutgoing: cloud', () => {
|
|
98
|
+
expectRelations(isOutgoing(cloud)).toEqual(['cloud.backend.storage:amazon.s3']);
|
|
99
|
+
});
|
|
100
|
+
it('isOutgoing: cloud.frontend', () => {
|
|
101
|
+
expectRelations(isOutgoing(frontend)).toEqual([
|
|
102
|
+
'cloud.frontend.dashboard:cloud.backend.graphql',
|
|
103
|
+
'cloud.frontend.adminPanel:cloud.backend.graphql'
|
|
104
|
+
]);
|
|
105
|
+
});
|
|
106
|
+
it('isOutgoing: cloud.backend.storage', () => {
|
|
107
|
+
expectRelations(isOutgoing('cloud.backend.storage')).toEqual([
|
|
108
|
+
'cloud.backend.storage:amazon.s3'
|
|
109
|
+
]);
|
|
110
|
+
});
|
|
111
|
+
it('isInside: cloud', () => {
|
|
112
|
+
expectRelations(isInside(cloud)).toEqual([
|
|
113
|
+
'cloud.backend.graphql:cloud.backend.storage',
|
|
114
|
+
'cloud.frontend.dashboard:cloud.backend.graphql',
|
|
115
|
+
'cloud.frontend.adminPanel:cloud.backend.graphql'
|
|
116
|
+
]);
|
|
117
|
+
});
|
|
118
|
+
it('isInside: cloud.frontend', () => {
|
|
119
|
+
expectRelations(isInside(frontend)).toEqual([]);
|
|
120
|
+
});
|
|
121
|
+
it('isInside: cloud.backend', () => {
|
|
122
|
+
expectRelations(isInside(backend)).toEqual(['cloud.backend.graphql:cloud.backend.storage']);
|
|
123
|
+
});
|
|
124
|
+
it('isAnyInOut: customer', () => {
|
|
125
|
+
expectRelations(isAnyInOut(customer)).toEqual(['customer:cloud.frontend.dashboard']);
|
|
126
|
+
});
|
|
127
|
+
it('isAnyInOut: cloud', () => {
|
|
128
|
+
expectRelations(isAnyInOut(cloud)).toEqual([
|
|
129
|
+
'customer:cloud.frontend.dashboard',
|
|
130
|
+
'support:cloud.frontend.adminPanel',
|
|
131
|
+
'cloud.backend.storage:amazon.s3',
|
|
132
|
+
'amazon.api:cloud.backend.graphql'
|
|
133
|
+
]);
|
|
134
|
+
});
|
|
135
|
+
it('isAnyBetween: cloud and amazon', () => {
|
|
136
|
+
expectRelations(isAnyBetween(cloud, 'amazon')).toEqual([
|
|
137
|
+
'cloud.backend.storage:amazon.s3',
|
|
138
|
+
'amazon.api:cloud.backend.graphql'
|
|
139
|
+
]);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('compareRelations', () => {
|
|
143
|
+
function rel(source, target) {
|
|
144
|
+
return {
|
|
145
|
+
source,
|
|
146
|
+
target
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function sorted(...relations) {
|
|
150
|
+
return relations.sort(compareRelations).map(r => r.source + ' -> ' + r.target);
|
|
151
|
+
}
|
|
152
|
+
it('should sort by source and target', () => {
|
|
153
|
+
expect(sorted(rel('customer', 'cloud.ui'), rel('customer', 'cloud'))).toEqual([
|
|
154
|
+
'customer -> cloud',
|
|
155
|
+
'customer -> cloud.ui'
|
|
156
|
+
]);
|
|
157
|
+
expect(sorted(rel('1', '2.1'), rel('1', '2'), rel('1.1.1', '2'), rel('1.1.1', '2.1'), rel('1.1', '2'))).toEqual(['1 -> 2', '1 -> 2.1', '1.1 -> 2', '1.1.1 -> 2', '1.1.1 -> 2.1']);
|
|
158
|
+
});
|
|
159
|
+
it('should sort by parent', () => {
|
|
160
|
+
expect(sorted(
|
|
161
|
+
// same parent
|
|
162
|
+
rel('cloud.1.1', 'cloud.2.1'), rel('cloud.1.1', 'cloud.2'), rel('cloud.1', 'cloud.2.1'), rel('cloud.1', 'cloud.2'),
|
|
163
|
+
// no same parent
|
|
164
|
+
rel('cloud.1.1', 'aws.1'), rel('cloud.1', 'aws.1'), rel('cloud', 'aws'))).toEqual([
|
|
165
|
+
'cloud -> aws',
|
|
166
|
+
'cloud.1 -> aws.1',
|
|
167
|
+
'cloud.1.1 -> aws.1',
|
|
168
|
+
'cloud.1 -> cloud.2',
|
|
169
|
+
'cloud.1 -> cloud.2.1',
|
|
170
|
+
'cloud.1.1 -> cloud.2',
|
|
171
|
+
'cloud.1.1 -> cloud.2.1'
|
|
172
|
+
]);
|
|
173
|
+
});
|
|
174
|
+
it('should sort by ancestors', () => {
|
|
175
|
+
expect(sorted(
|
|
176
|
+
// same parent 2nd level
|
|
177
|
+
rel('cloud.api.1', 'cloud.api.2'), rel('cloud.ui.1', 'cloud.ui.2'), rel('cloud.ui.2', 'cloud.ui.1'),
|
|
178
|
+
// same ancestor cloud
|
|
179
|
+
rel('cloud.ui.1', 'cloud.api.1'), rel('cloud.ui.2', 'cloud.api.2'), rel('cloud.ui', 'cloud.api.1'),
|
|
180
|
+
// same parent 1st level
|
|
181
|
+
rel('cloud.ui', 'cloud.api'),
|
|
182
|
+
// no same parent
|
|
183
|
+
rel('cloud.api.1', 'aws.1'), rel('cloud.api', 'aws.1'), rel('cloud.api', 'aws'), rel('cloud.ui.1', 'aws.1'), rel('cloud.ui', 'aws'), rel('cloud', 'aws'))).toEqual([
|
|
184
|
+
'cloud -> aws',
|
|
185
|
+
'cloud.api -> aws',
|
|
186
|
+
'cloud.ui -> aws',
|
|
187
|
+
'cloud.api -> aws.1',
|
|
188
|
+
'cloud.api.1 -> aws.1',
|
|
189
|
+
'cloud.ui.1 -> aws.1',
|
|
190
|
+
'cloud.ui -> cloud.api',
|
|
191
|
+
'cloud.ui -> cloud.api.1',
|
|
192
|
+
'cloud.ui.1 -> cloud.api.1',
|
|
193
|
+
'cloud.ui.2 -> cloud.api.2',
|
|
194
|
+
'cloud.api.1 -> cloud.api.2',
|
|
195
|
+
'cloud.ui.1 -> cloud.ui.2',
|
|
196
|
+
'cloud.ui.2 -> cloud.ui.1'
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
it('should sort relations from example', () => {
|
|
200
|
+
expect(sorted(...relations)).toEqual([
|
|
201
|
+
'customer -> cloud.frontend.dashboard',
|
|
202
|
+
'support -> cloud.frontend.adminPanel',
|
|
203
|
+
'amazon.api -> cloud.backend.graphql',
|
|
204
|
+
'cloud.backend.storage -> amazon.s3',
|
|
205
|
+
'cloud.frontend.dashboard -> cloud.backend.graphql',
|
|
206
|
+
'cloud.frontend.adminPanel -> cloud.backend.graphql',
|
|
207
|
+
'cloud.backend.graphql -> cloud.backend.storage'
|
|
208
|
+
]);
|
|
209
|
+
});
|
|
210
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://likec4.dev",
|
|
6
6
|
"author": "Denis Davydkov <denis@davydkov.com>",
|
|
@@ -11,16 +11,15 @@
|
|
|
11
11
|
},
|
|
12
12
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
13
13
|
"scripts": {
|
|
14
|
-
"typecheck": "tsc
|
|
15
|
-
"
|
|
16
|
-
"prepack": "tsc -p tsconfig.build.json",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"prepack": "tsc",
|
|
17
16
|
"lint": "run -T eslint src/ --fix",
|
|
18
17
|
"test": "run -T vitest run",
|
|
19
18
|
"clean": "run -T rimraf dist"
|
|
20
19
|
},
|
|
21
20
|
"files": [
|
|
22
21
|
"dist",
|
|
23
|
-
"
|
|
22
|
+
"src",
|
|
24
23
|
"!**/*.map"
|
|
25
24
|
],
|
|
26
25
|
"type": "module",
|
|
@@ -71,10 +70,11 @@
|
|
|
71
70
|
"type-fest": "^4.18.2"
|
|
72
71
|
},
|
|
73
72
|
"devDependencies": {
|
|
73
|
+
"@likec4/tsconfig": "1.2.2",
|
|
74
74
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
75
75
|
"execa": "^9.1.0",
|
|
76
76
|
"typescript": "^5.4.5",
|
|
77
|
-
"vitest": "~1.5.
|
|
77
|
+
"vitest": "~1.5.3"
|
|
78
78
|
},
|
|
79
79
|
"packageManager": "yarn@4.3.0"
|
|
80
80
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ElementThemeColors, ElementThemeColorValues } from '../types/theme'
|
|
2
|
+
|
|
3
|
+
const blue = {
|
|
4
|
+
fill: '#3b82f6',
|
|
5
|
+
stroke: '#2563eb',
|
|
6
|
+
hiContrast: '#eff6ff',
|
|
7
|
+
loContrast: '#bfdbfe'
|
|
8
|
+
} satisfies ElementThemeColorValues
|
|
9
|
+
|
|
10
|
+
const sky = {
|
|
11
|
+
fill: '#0284c7',
|
|
12
|
+
stroke: '#0369a1',
|
|
13
|
+
hiContrast: '#f0f9ff',
|
|
14
|
+
loContrast: '#B6ECF7'
|
|
15
|
+
} satisfies ElementThemeColorValues
|
|
16
|
+
|
|
17
|
+
const slate = {
|
|
18
|
+
fill: '#64748b',
|
|
19
|
+
stroke: '#475569',
|
|
20
|
+
hiContrast: '#f8fafc',
|
|
21
|
+
loContrast: '#cbd5e1'
|
|
22
|
+
} satisfies ElementThemeColorValues
|
|
23
|
+
|
|
24
|
+
export const ElementColors = {
|
|
25
|
+
primary: blue,
|
|
26
|
+
blue,
|
|
27
|
+
secondary: sky,
|
|
28
|
+
sky,
|
|
29
|
+
muted: slate,
|
|
30
|
+
slate,
|
|
31
|
+
gray: {
|
|
32
|
+
// fill: colors.neutral[500],
|
|
33
|
+
// stroke: colors.neutral[600],
|
|
34
|
+
// hiContrast: colors.neutral[50],
|
|
35
|
+
// loContrast: colors.neutral[200],
|
|
36
|
+
fill: '#737373',
|
|
37
|
+
stroke: '#525252',
|
|
38
|
+
hiContrast: '#fafafa',
|
|
39
|
+
loContrast: '#d4d4d4'
|
|
40
|
+
},
|
|
41
|
+
red: {
|
|
42
|
+
// fill: colors.red[500],
|
|
43
|
+
// stroke: colors.red[600],
|
|
44
|
+
// hiContrast: colors.red[50],
|
|
45
|
+
// loContrast: colors.red[200],
|
|
46
|
+
fill: '#AC4D39',
|
|
47
|
+
// fill: '#b54548',
|
|
48
|
+
stroke: '#853A2D',
|
|
49
|
+
// hiContrast: '#fef2f2',
|
|
50
|
+
// loContrast: '#fecaca',
|
|
51
|
+
// hiContrast: '#191111', // colors.gray[900],
|
|
52
|
+
// loContrast: '#3b1219' // colors.gray[800],
|
|
53
|
+
hiContrast: '#FBD3CB',
|
|
54
|
+
// hiContrast: '#f8fafc',
|
|
55
|
+
// loContrast: '#fdd8d8' // radix black red 12
|
|
56
|
+
loContrast: '#FF977D'
|
|
57
|
+
},
|
|
58
|
+
green: {
|
|
59
|
+
fill: '#428a4f',
|
|
60
|
+
stroke: '#2d5d39',
|
|
61
|
+
hiContrast: '#f8fafc',
|
|
62
|
+
loContrast: '#c2f0c2'
|
|
63
|
+
},
|
|
64
|
+
amber: {
|
|
65
|
+
fill: '#A35829',
|
|
66
|
+
stroke: '#7E451D',
|
|
67
|
+
hiContrast: '#FFE0C2',
|
|
68
|
+
loContrast: '#FFA057'
|
|
69
|
+
},
|
|
70
|
+
indigo: {
|
|
71
|
+
// fill: colors.indigo[500],
|
|
72
|
+
// stroke: colors.indigo[600],
|
|
73
|
+
// hiContrast: colors.indigo[50],
|
|
74
|
+
// loContrast: colors.indigo[200],
|
|
75
|
+
fill: '#6366f1',
|
|
76
|
+
stroke: '#4f46e5',
|
|
77
|
+
hiContrast: '#eef2ff',
|
|
78
|
+
loContrast: '#c7d2fe'
|
|
79
|
+
}
|
|
80
|
+
} as const satisfies ElementThemeColors
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LikeC4Theme } from '../types/theme'
|
|
2
|
+
import { ElementColors } from './element'
|
|
3
|
+
import { RelationshipColors } from './relationships'
|
|
4
|
+
|
|
5
|
+
export const defaultTheme = {
|
|
6
|
+
elements: ElementColors,
|
|
7
|
+
relationships: RelationshipColors,
|
|
8
|
+
font: 'Helvetica',
|
|
9
|
+
shadow: '#0a0a0a'
|
|
10
|
+
} satisfies LikeC4Theme
|
|
11
|
+
|
|
12
|
+
export { ElementColors, RelationshipColors }
|