@likec4/core 1.34.2 → 1.36.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/builder/index.d.mts +15 -4
- package/dist/builder/index.mjs +19 -15
- package/dist/compute-view/index.d.mts +3 -3
- package/dist/compute-view/index.mjs +16 -13
- package/dist/compute-view/relationships-view/index.d.mts +3 -3
- package/dist/compute-view/relationships-view/index.mjs +2 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +14 -9
- package/dist/model/connection/deployment/index.d.mts +5 -5
- package/dist/model/connection/deployment/index.mjs +5 -4
- package/dist/model/connection/index.d.mts +6 -6
- package/dist/model/connection/index.mjs +6 -5
- package/dist/model/connection/model/index.d.mts +5 -5
- package/dist/model/connection/model/index.mjs +3 -3
- package/dist/model/index.d.mts +33 -9
- package/dist/model/index.mjs +12 -10
- package/dist/shared/{core.DAj3LuFH.d.mts → core.BFb3p5d-.d.mts} +4 -2
- package/dist/shared/{core.PqNe5WxQ.mjs → core.BlwZ4tBa.mjs} +98 -92
- package/dist/shared/core.BpJu1RrF.mjs +5 -0
- package/dist/shared/{core.CJSFKrYf.d.mts → core.Bt3kuGUN.d.mts} +3 -3
- package/dist/shared/{core.D5qVzkws.mjs → core.Bus32P0S.mjs} +4 -3
- package/dist/shared/{core.4SpVCM9m.mjs → core.BvIGRozf.mjs} +364 -28
- package/dist/shared/{core.C80Z37Eu.mjs → core.C1GV0WWV.mjs} +1 -1
- package/dist/shared/{core.DXRAwwDB.mjs → core.CaJp8Amg.mjs} +3 -2
- package/dist/shared/{core.D56nCp7e.mjs → core.CaaYNQDM.mjs} +1 -3
- package/dist/shared/core.CnIyafWn.mjs +3 -0
- package/dist/shared/{core.D3xEWj5B.d.mts → core.D8bTI5KC.d.mts} +2 -2
- package/dist/shared/{core.Di7__sMg.d.mts → core.DHYd2-VU.d.mts} +3 -3
- package/dist/shared/{core.C_C-3c1S.mjs → core.DQj9iv_y.mjs} +3 -5
- package/dist/shared/{core.DrS4Bf4y.d.mts → core.DoNP3Yl-.d.mts} +187 -11
- package/dist/shared/{core.IWLie-Ma.d.mts → core.DxDn5nB5.d.mts} +24 -6
- package/dist/shared/{core.CtKXPqN_.mjs → core.HUONfQfd.mjs} +1 -1
- package/dist/shared/{core.BTnf14gD.mjs → core.Y3j3s-oq.mjs} +2 -2
- package/dist/shared/{core.Br7Fab9l.mjs → core._jnYNUQ-.mjs} +8 -70
- package/dist/shared/{core.XptQjhMA.mjs → core.b2BzqGz0.mjs} +2 -2
- package/dist/shared/{core.BMCb0wJI.mjs → core.yaRvRnMW.mjs} +1 -1
- package/dist/theme/index.mjs +34 -3510
- package/dist/types/_aux.d.mts +1 -1
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +6 -4
- package/dist/types/scalar.d.mts +2 -0
- package/dist/types/scalar.mjs +68 -0
- package/dist/utils/index.d.mts +6 -8
- package/dist/utils/index.mjs +5 -5
- package/dist/utils/iterable/index.d.mts +18 -1
- package/dist/utils/iterable/index.mjs +22 -2
- package/package.json +11 -16
- package/src/builder/Builder.ts +17 -6
- package/src/builder/__snapshots__/Builder-style1.spec.ts.snap +9 -0
- package/src/builder/__snapshots__/Builder-style2.compute-model.json5 +3 -0
- package/src/builder/__snapshots__/Builder-style2.spec.ts.snap +3 -0
- package/src/builder/_types.ts +10 -0
- package/src/compute-view/dynamic-view/compute.ts +2 -0
- package/src/compute-view/element-view/__test__/fixture.ts +1 -0
- package/src/compute-view/element-view/predicates/relation-direct.ts +8 -2
- package/src/compute-view/utils/applyCustomRelationProperties.ts +2 -0
- package/src/model/DeploymentModel.ts +1 -1
- package/src/model/LikeC4Model.ts +162 -13
- package/src/model/index.ts +8 -0
- package/src/model/types.ts +1 -8
- package/src/model/utils.ts +66 -0
- package/src/model/view/LikeC4ViewModel.ts +62 -7
- package/src/model/view/LikeC4ViewsFolder.ts +151 -0
- package/src/theme/__test__/theme-index.ts +29 -0
- package/src/theme/element.ts +0 -19
- package/src/theme/index.ts +49 -3
- package/src/types/_aux.ts +6 -0
- package/src/types/index.ts +1 -0
- package/src/types/model-data.ts +2 -0
- package/src/types/model-dump.ts +8 -1
- package/src/types/model-spec.ts +4 -0
- package/src/types/project.ts +9 -0
- package/src/types/view-computed.ts +1 -1
- package/src/types/view-parsed.dynamic.ts +2 -2
- package/src/utils/compare-natural.ts +14 -12
- package/src/utils/index.ts +1 -0
- package/src/utils/iterable/first.ts +48 -0
- package/src/utils/iterable/index.ts +1 -0
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import { u as u$1 } from './core.DbRvwARP.mjs';
|
|
2
|
-
import { p } from './core.
|
|
2
|
+
import { p } from './core.Y3j3s-oq.mjs';
|
|
3
3
|
import { m as m$2 } from './core.ByrmCl9I.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { i as i$2 } from './core.CpwrZi3D.mjs';
|
|
5
|
+
import { g as hierarchyLevel, n as nameFromFqn, i as isAncestor, d as commonAncestor, l as sortNaturalByFqn, m as sortParentsFirst, p as parentFqn, b as ancestorsFqn, C, a as compareNaturalHierarchically, c as compareNatural } from './core.DQj9iv_y.mjs';
|
|
5
6
|
import { g as getOrCreate } from './core.DcS-0zys.mjs';
|
|
6
|
-
import { i, n as n$
|
|
7
|
-
import { D as DefaultMap } from './core.
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { i as i$1, n as n$3, e as DeploymentNodeModel, c as DeployedInstanceModel, N as NestedElementOfDeployedInstanceModel, g as DeploymentRelationModel } from './core.Bus32P0S.mjs';
|
|
8
|
+
import { D as DefaultMap } from './core.yaRvRnMW.mjs';
|
|
9
|
+
import { i as invariant, a as nonNullable } from './core.D4npX2q8.mjs';
|
|
10
|
+
import { F as FqnRef, b as isDeploymentNode, a as _type, _ as _stage, i as isOnStage, w as whereOperatorAsPredicate } from './core._jnYNUQ-.mjs';
|
|
10
11
|
import { m as memoizeProp } from './core.B0oEIXqd.mjs';
|
|
11
12
|
import { i as ifilter } from './core.BH9nN-_I.mjs';
|
|
12
|
-
import {
|
|
13
|
+
import { splitGlobalFqn, extractStep, isStepEdgeId, isGroupElementKind, isGlobalFqn, GlobalFqn } from '../types/scalar.mjs';
|
|
14
|
+
import { n as n$2 } from './core.CnIyafWn.mjs';
|
|
15
|
+
import { a as DefaultElementShape, D as DefaultThemeColor, R as RichText, b as DefaultShapeSize, g as DefaultRelationshipColor, e as DefaultLineStyle } from './core.CaaYNQDM.mjs';
|
|
13
16
|
import { a as ihead, i as ifind } from './core.DsMrjY2q.mjs';
|
|
14
17
|
|
|
15
18
|
function r(...t){return u$1(Object.values,t)}
|
|
16
19
|
|
|
17
20
|
var T={asc:(r,n)=>r>n,desc:(r,n)=>r<n};function s(r,n){let[e,...o]=n;if(!m$1(e)){let t=u(...o);return r(e,t)}let a=u(e,...o);return t=>r(t,a)}function u(r,n,...e){let o=typeof r=="function"?r:r[0],a=typeof r=="function"?"asc":r[1],{[a]:t}=T,i=n===void 0?void 0:u(n,...e);return (y,c)=>{let p=o(y),l=o(c);return t(p,l)?1:t(l,p)?-1:i?.(y,c)??0}}function m$1(r){if(d(r))return true;if(typeof r!="object"||!Array.isArray(r))return false;let[n,e,...o]=r;return d(n)&&typeof e=="string"&&e in T&&o.length===0}var d=r=>typeof r=="function"&&r.length===1;
|
|
18
21
|
|
|
22
|
+
function i(t,e,n){return typeof e=="number"||e===void 0?r=>r.split(t,e):t.split(e,n)}
|
|
23
|
+
|
|
19
24
|
function m(...r){return u$1(o,r)}function o(r,t){let e=[...r];return e.sort(t),e}
|
|
20
25
|
|
|
21
|
-
function a(...r){return s(n,r)}var n=(r,t)=>[...r].sort(t);
|
|
26
|
+
function a$1(...r){return s(n$1,r)}var n$1=(r,t)=>[...r].sort(t);
|
|
27
|
+
|
|
28
|
+
function a(...e){return u$1(n,e)}var n=e=>e.at(-1);
|
|
22
29
|
|
|
23
30
|
function t(...r){return u$1(Object.entries,r)}
|
|
24
31
|
|
|
@@ -68,7 +75,7 @@ class ElementModel {
|
|
|
68
75
|
*/
|
|
69
76
|
get tags() {
|
|
70
77
|
return memoizeProp(this, Symbol.for("tags"), () => {
|
|
71
|
-
return i([
|
|
78
|
+
return i$1([
|
|
72
79
|
...this.$element.tags ?? [],
|
|
73
80
|
...this.$model.specification.elements[this.$element.kind]?.tags ?? []
|
|
74
81
|
]);
|
|
@@ -226,13 +233,13 @@ class ElementModel {
|
|
|
226
233
|
* @returns true if the element is deployed
|
|
227
234
|
*/
|
|
228
235
|
isDeployed() {
|
|
229
|
-
return n$
|
|
236
|
+
return n$2(ihead(this.deployments()));
|
|
230
237
|
}
|
|
231
238
|
deployments() {
|
|
232
239
|
return this.$model.deployment.instancesOf(this);
|
|
233
240
|
}
|
|
234
241
|
hasMetadata() {
|
|
235
|
-
return !!this.$element.metadata && !n$
|
|
242
|
+
return !!this.$element.metadata && !n$3(this.$element.metadata);
|
|
236
243
|
}
|
|
237
244
|
getMetadata(field) {
|
|
238
245
|
if (field) {
|
|
@@ -248,9 +255,37 @@ class ElementModel {
|
|
|
248
255
|
}
|
|
249
256
|
}
|
|
250
257
|
|
|
251
|
-
|
|
258
|
+
const getId = (element) => {
|
|
252
259
|
return typeof element === "string" ? element : element.id;
|
|
253
|
-
}
|
|
260
|
+
};
|
|
261
|
+
const VIEW_FOLDERS_SEPARATOR = "/";
|
|
262
|
+
const splitViewTitle = (title) => {
|
|
263
|
+
invariant(!title.includes("\n"), "View title cannot contain newlines");
|
|
264
|
+
if (title.includes(VIEW_FOLDERS_SEPARATOR)) {
|
|
265
|
+
const segments = title.split(VIEW_FOLDERS_SEPARATOR).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
266
|
+
if (i$2(segments, 1)) {
|
|
267
|
+
return segments;
|
|
268
|
+
}
|
|
269
|
+
return [""];
|
|
270
|
+
}
|
|
271
|
+
return [title.trim()];
|
|
272
|
+
};
|
|
273
|
+
const normalizeViewPath = (title) => {
|
|
274
|
+
return splitViewTitle(title).join(VIEW_FOLDERS_SEPARATOR);
|
|
275
|
+
};
|
|
276
|
+
const getViewFolderPath = (title) => {
|
|
277
|
+
const segments = splitViewTitle(title);
|
|
278
|
+
if (!i$2(segments, 2)) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
return segments.slice(0, -1).join(VIEW_FOLDERS_SEPARATOR);
|
|
282
|
+
};
|
|
283
|
+
const extractViewTitleFromPath = (title) => {
|
|
284
|
+
if (!title.includes(VIEW_FOLDERS_SEPARATOR)) {
|
|
285
|
+
return title.trim();
|
|
286
|
+
}
|
|
287
|
+
return splitViewTitle(title).pop() ?? title;
|
|
288
|
+
};
|
|
254
289
|
|
|
255
290
|
class LikeC4DeploymentModel {
|
|
256
291
|
constructor($model) {
|
|
@@ -579,13 +614,13 @@ class RelationshipModel {
|
|
|
579
614
|
return `${this.source.id} -> ${this.target.id}`;
|
|
580
615
|
}
|
|
581
616
|
get title() {
|
|
582
|
-
if (!n$
|
|
617
|
+
if (!n$2(this.$relationship.title)) {
|
|
583
618
|
return null;
|
|
584
619
|
}
|
|
585
620
|
return this.$relationship.title;
|
|
586
621
|
}
|
|
587
622
|
get technology() {
|
|
588
|
-
if (!n$
|
|
623
|
+
if (!n$2(this.$relationship.technology)) {
|
|
589
624
|
return null;
|
|
590
625
|
}
|
|
591
626
|
return this.$relationship.technology;
|
|
@@ -629,7 +664,7 @@ class RelationshipModel {
|
|
|
629
664
|
return true;
|
|
630
665
|
}
|
|
631
666
|
hasMetadata() {
|
|
632
|
-
return !!this.$relationship.metadata && !n$
|
|
667
|
+
return !!this.$relationship.metadata && !n$3(this.$relationship.metadata);
|
|
633
668
|
}
|
|
634
669
|
getMetadata(field) {
|
|
635
670
|
if (field) {
|
|
@@ -851,13 +886,13 @@ class NodeModel {
|
|
|
851
886
|
* Check if this node references to logical model element.
|
|
852
887
|
*/
|
|
853
888
|
hasElement() {
|
|
854
|
-
return n$
|
|
889
|
+
return n$2(this.#node.modelRef);
|
|
855
890
|
}
|
|
856
891
|
/**
|
|
857
892
|
* Check if this node references to deployment element (Node or Instance).
|
|
858
893
|
*/
|
|
859
894
|
hasDeployment() {
|
|
860
|
-
return n$
|
|
895
|
+
return n$2(this.#node.deploymentRef);
|
|
861
896
|
}
|
|
862
897
|
/**
|
|
863
898
|
* Check if this node references to deployed instance
|
|
@@ -891,9 +926,23 @@ class LikeC4ViewModel {
|
|
|
891
926
|
#allTags = new DefaultMap((_key) => /* @__PURE__ */ new Set());
|
|
892
927
|
$view;
|
|
893
928
|
$model;
|
|
894
|
-
|
|
929
|
+
title;
|
|
930
|
+
/**
|
|
931
|
+
* View folder this view belongs to.
|
|
932
|
+
* If view is top-level, this is the root folder.
|
|
933
|
+
*/
|
|
934
|
+
folder;
|
|
935
|
+
/**
|
|
936
|
+
* Path to this view, processed by {@link normalizeViewPath}
|
|
937
|
+
*
|
|
938
|
+
* @example
|
|
939
|
+
* "Group 1/Group 2/View"
|
|
940
|
+
*/
|
|
941
|
+
viewPath;
|
|
942
|
+
constructor(model, view, folder) {
|
|
895
943
|
this.$model = model;
|
|
896
944
|
this.$view = view;
|
|
945
|
+
this.folder = folder;
|
|
897
946
|
for (const node of view.nodes) {
|
|
898
947
|
const el = new NodeModel(this, Object.freeze(node));
|
|
899
948
|
this.#nodes.set(node.id, el);
|
|
@@ -925,6 +974,8 @@ class LikeC4ViewModel {
|
|
|
925
974
|
}
|
|
926
975
|
this.#edges.set(edge.id, edgeModel);
|
|
927
976
|
}
|
|
977
|
+
this.title = this.$view.title ? extractViewTitleFromPath(this.$view.title) : null;
|
|
978
|
+
this.viewPath = this.$view.title ? normalizeViewPath(this.$view.title) : this.$view.id;
|
|
928
979
|
}
|
|
929
980
|
get _type() {
|
|
930
981
|
return this.$view[_type];
|
|
@@ -932,8 +983,38 @@ class LikeC4ViewModel {
|
|
|
932
983
|
get id() {
|
|
933
984
|
return this.$view.id;
|
|
934
985
|
}
|
|
935
|
-
|
|
936
|
-
|
|
986
|
+
/**
|
|
987
|
+
* Returns title if defined, otherwise returns its {@link id}
|
|
988
|
+
*/
|
|
989
|
+
get titleOrId() {
|
|
990
|
+
return this.title ?? this.id;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Returns title if defined, otherwise returns `Untitled`.
|
|
994
|
+
*/
|
|
995
|
+
get titleOrUntitled() {
|
|
996
|
+
return this.title ?? "Untitled";
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Returns path to this view as an array of groups and this view as the last element
|
|
1000
|
+
* If view is top-level, returns only this view.
|
|
1001
|
+
*
|
|
1002
|
+
* @example
|
|
1003
|
+
* viewPath = "Group 1/Group 2/View"
|
|
1004
|
+
*
|
|
1005
|
+
* breadcrumbs = [
|
|
1006
|
+
* "Group 1", // folder
|
|
1007
|
+
* "Group 1/Group 2", // folder
|
|
1008
|
+
* "Group 1/Group 2/View" // view
|
|
1009
|
+
* ]
|
|
1010
|
+
*/
|
|
1011
|
+
get breadcrumbs() {
|
|
1012
|
+
return memoizeProp(this, "breadcrumbs", () => {
|
|
1013
|
+
if (!this.folder.isRoot) {
|
|
1014
|
+
return [...this.folder.breadcrumbs, this];
|
|
1015
|
+
}
|
|
1016
|
+
return [this];
|
|
1017
|
+
});
|
|
937
1018
|
}
|
|
938
1019
|
get description() {
|
|
939
1020
|
return RichText.memoize(this, this.$view.description);
|
|
@@ -1066,7 +1147,7 @@ class LikeC4ViewModel {
|
|
|
1066
1147
|
return this.$view[_type] === "element";
|
|
1067
1148
|
}
|
|
1068
1149
|
isScopedElementView() {
|
|
1069
|
-
return this.$view[_type] === "element" && n$
|
|
1150
|
+
return this.$view[_type] === "element" && n$2(this.$view.viewOf);
|
|
1070
1151
|
}
|
|
1071
1152
|
isDeploymentView() {
|
|
1072
1153
|
return this.$view[_type] === "deployment";
|
|
@@ -1076,6 +1157,136 @@ class LikeC4ViewModel {
|
|
|
1076
1157
|
}
|
|
1077
1158
|
}
|
|
1078
1159
|
|
|
1160
|
+
class LikeC4ViewsFolder {
|
|
1161
|
+
$model;
|
|
1162
|
+
/**
|
|
1163
|
+
* Path to this view folder, processed by {@link normalizeViewPath}
|
|
1164
|
+
*
|
|
1165
|
+
* @example
|
|
1166
|
+
* "Folder 1/Folder 2/Folder 3"
|
|
1167
|
+
*/
|
|
1168
|
+
path;
|
|
1169
|
+
/**
|
|
1170
|
+
* Title of this view folder.
|
|
1171
|
+
*
|
|
1172
|
+
* @example
|
|
1173
|
+
* // title is the last segment of the path
|
|
1174
|
+
* path = "Folder 1/Folder 2/Folder 3"
|
|
1175
|
+
* title = "Folder 3"
|
|
1176
|
+
*/
|
|
1177
|
+
title;
|
|
1178
|
+
/**
|
|
1179
|
+
* Whether this is the root view folder.
|
|
1180
|
+
*
|
|
1181
|
+
* !NOTE
|
|
1182
|
+
* Root folder is special folder with an empty path and used only for internal purposes. \
|
|
1183
|
+
* It is not visible to the user and should not be used in the code.
|
|
1184
|
+
*/
|
|
1185
|
+
isRoot;
|
|
1186
|
+
parentPath;
|
|
1187
|
+
defaultViewId;
|
|
1188
|
+
constructor($model, path, defaultViewId) {
|
|
1189
|
+
this.$model = $model;
|
|
1190
|
+
this.path = path.join("/");
|
|
1191
|
+
this.isRoot = this.path === "";
|
|
1192
|
+
this.title = a(path);
|
|
1193
|
+
if (this.isRoot) {
|
|
1194
|
+
this.parentPath = void 0;
|
|
1195
|
+
} else {
|
|
1196
|
+
this.parentPath = path.slice(0, -1).join("/");
|
|
1197
|
+
}
|
|
1198
|
+
this.defaultViewId = defaultViewId;
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Default view of this view folder.\
|
|
1202
|
+
* It is for the case when there is a view at the same path as this folder.\
|
|
1203
|
+
* (if there are multiple views at the same path, the first one is chosen)
|
|
1204
|
+
*
|
|
1205
|
+
* @example
|
|
1206
|
+
* ```
|
|
1207
|
+
* // Assume the following views exist:
|
|
1208
|
+
* const views = [
|
|
1209
|
+
* "Folder 1/ Folder 2 / View",
|
|
1210
|
+
* "Folder 1/ Folder 2 / View / Subview",
|
|
1211
|
+
* ]
|
|
1212
|
+
* ```
|
|
1213
|
+
* Group with path `Folder 1/ Folder 2 / View`\
|
|
1214
|
+
* will have default view `Folder 1/ Folder 2 / View`
|
|
1215
|
+
*/
|
|
1216
|
+
get defaultView() {
|
|
1217
|
+
if (!this.defaultViewId) {
|
|
1218
|
+
return null;
|
|
1219
|
+
}
|
|
1220
|
+
return this.$model.view(this.defaultViewId);
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Returns path to this view folder as an array of ancestors (excluding root) and this view folder as the last element
|
|
1224
|
+
*
|
|
1225
|
+
* @throws Error if this is the root folder.
|
|
1226
|
+
*/
|
|
1227
|
+
get breadcrumbs() {
|
|
1228
|
+
invariant(!this.isRoot, "Root view folder has no breadcrumbs");
|
|
1229
|
+
return memoizeProp(this, "breadcrumbs", () => {
|
|
1230
|
+
const parent = this.parent;
|
|
1231
|
+
if (parent) {
|
|
1232
|
+
if (parent.isRoot) {
|
|
1233
|
+
return [parent, this];
|
|
1234
|
+
}
|
|
1235
|
+
return [...parent.breadcrumbs, this];
|
|
1236
|
+
}
|
|
1237
|
+
return [this];
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Returns parent folder
|
|
1242
|
+
*
|
|
1243
|
+
* @throws Error if this is the root folder.
|
|
1244
|
+
*/
|
|
1245
|
+
get parent() {
|
|
1246
|
+
invariant(!this.isRoot, "Root view folder has no parent");
|
|
1247
|
+
if (n$3(this.parentPath)) {
|
|
1248
|
+
return null;
|
|
1249
|
+
}
|
|
1250
|
+
return this.$model.viewFolder(this.parentPath);
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Returns sorted set of children
|
|
1254
|
+
* - First folders
|
|
1255
|
+
* - Then views
|
|
1256
|
+
*/
|
|
1257
|
+
get children() {
|
|
1258
|
+
return this.$model.viewFolderItems(this.path);
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Returns sorted array of children folders
|
|
1262
|
+
*/
|
|
1263
|
+
get folders() {
|
|
1264
|
+
return memoizeProp(this, "folders", () => {
|
|
1265
|
+
const folders = [];
|
|
1266
|
+
for (const child of this.children) {
|
|
1267
|
+
if (child instanceof LikeC4ViewsFolder) {
|
|
1268
|
+
folders.push(child);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return folders;
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Returns all views in this view folder.
|
|
1276
|
+
*/
|
|
1277
|
+
get views() {
|
|
1278
|
+
return memoizeProp(this, "views", () => {
|
|
1279
|
+
const views = [];
|
|
1280
|
+
for (const child of this.children) {
|
|
1281
|
+
if (child instanceof LikeC4ViewModel) {
|
|
1282
|
+
views.push(child);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
return views;
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1079
1290
|
class LikeC4Model {
|
|
1080
1291
|
/**
|
|
1081
1292
|
* Don't use in runtime, only for type inference
|
|
@@ -1095,6 +1306,11 @@ class LikeC4Model {
|
|
|
1095
1306
|
// Relationships inside the element, among descendants
|
|
1096
1307
|
_internal = new DefaultMap(() => /* @__PURE__ */ new Set());
|
|
1097
1308
|
_views = /* @__PURE__ */ new Map();
|
|
1309
|
+
_rootViewFolder;
|
|
1310
|
+
_viewFolders = /* @__PURE__ */ new Map();
|
|
1311
|
+
_viewFolderItems = new DefaultMap(
|
|
1312
|
+
() => /* @__PURE__ */ new Set()
|
|
1313
|
+
);
|
|
1098
1314
|
_allTags = new DefaultMap(
|
|
1099
1315
|
() => /* @__PURE__ */ new Set()
|
|
1100
1316
|
);
|
|
@@ -1116,6 +1332,7 @@ class LikeC4Model {
|
|
|
1116
1332
|
const {
|
|
1117
1333
|
_stage: stage = "layouted",
|
|
1118
1334
|
projectId = "unknown",
|
|
1335
|
+
project,
|
|
1119
1336
|
globals,
|
|
1120
1337
|
imports,
|
|
1121
1338
|
deployments,
|
|
@@ -1127,6 +1344,7 @@ class LikeC4Model {
|
|
|
1127
1344
|
return new LikeC4Model({
|
|
1128
1345
|
[_stage]: stage,
|
|
1129
1346
|
projectId,
|
|
1347
|
+
project,
|
|
1130
1348
|
globals: {
|
|
1131
1349
|
predicates: globals?.predicates ?? {},
|
|
1132
1350
|
dynamicPredicates: globals?.dynamicPredicates ?? {},
|
|
@@ -1169,17 +1387,56 @@ class LikeC4Model {
|
|
|
1169
1387
|
}
|
|
1170
1388
|
this.deployment = new LikeC4DeploymentModel(this);
|
|
1171
1389
|
if (isOnStage($data, "computed") || isOnStage($data, "layouted")) {
|
|
1390
|
+
const compare = compareNaturalHierarchically(VIEW_FOLDERS_SEPARATOR);
|
|
1172
1391
|
const views = C(
|
|
1173
1392
|
r($data.views),
|
|
1174
|
-
m((
|
|
1393
|
+
m$2((view) => ({
|
|
1394
|
+
view,
|
|
1395
|
+
path: normalizeViewPath(view.title ?? view.id),
|
|
1396
|
+
folderPath: view.title && getViewFolderPath(view.title) || ""
|
|
1397
|
+
})),
|
|
1398
|
+
// Sort hierarchically by groups, but keep same order within groups
|
|
1399
|
+
m((a, b) => compare(a.folderPath, b.folderPath))
|
|
1175
1400
|
);
|
|
1176
|
-
|
|
1177
|
-
|
|
1401
|
+
const getOrCreateFolder = (path) => {
|
|
1402
|
+
let folder = this._viewFolders.get(path);
|
|
1403
|
+
if (!folder) {
|
|
1404
|
+
const segments = i(path, VIEW_FOLDERS_SEPARATOR);
|
|
1405
|
+
invariant(i$2(segments, 1), `View group path "${path}" must have at least one element`);
|
|
1406
|
+
let defaultView;
|
|
1407
|
+
if (path === "") {
|
|
1408
|
+
defaultView = views.find((view) => view.view.id === "index");
|
|
1409
|
+
} else {
|
|
1410
|
+
defaultView = views.find((view) => view.path === path);
|
|
1411
|
+
}
|
|
1412
|
+
folder = new LikeC4ViewsFolder(this, segments, defaultView?.view.id);
|
|
1413
|
+
this._viewFolders.set(path, folder);
|
|
1414
|
+
}
|
|
1415
|
+
return folder;
|
|
1416
|
+
};
|
|
1417
|
+
this._rootViewFolder = getOrCreateFolder("");
|
|
1418
|
+
for (const { folderPath } of views) {
|
|
1419
|
+
if (this._viewFolders.has(folderPath)) {
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1422
|
+
i(folderPath, VIEW_FOLDERS_SEPARATOR).reduce((parent, segment) => {
|
|
1423
|
+
const path = [...parent, segment];
|
|
1424
|
+
const folder = getOrCreateFolder(path.join(VIEW_FOLDERS_SEPARATOR));
|
|
1425
|
+
this._viewFolderItems.get(parent.join(VIEW_FOLDERS_SEPARATOR)).add(folder);
|
|
1426
|
+
return path;
|
|
1427
|
+
}, []);
|
|
1428
|
+
}
|
|
1429
|
+
for (const { view, folderPath } of views) {
|
|
1430
|
+
const vm = new LikeC4ViewModel(this, view, getOrCreateFolder(folderPath));
|
|
1431
|
+
this._viewFolderItems.get(folderPath).add(vm);
|
|
1178
1432
|
this._views.set(view.id, vm);
|
|
1179
1433
|
for (const tag of vm.tags) {
|
|
1180
1434
|
this._allTags.get(tag).add(vm);
|
|
1181
1435
|
}
|
|
1182
1436
|
}
|
|
1437
|
+
} else {
|
|
1438
|
+
this._rootViewFolder = new LikeC4ViewsFolder(this, [""], void 0);
|
|
1439
|
+
this._viewFolders.set(this._rootViewFolder.path, this._rootViewFolder);
|
|
1183
1440
|
}
|
|
1184
1441
|
}
|
|
1185
1442
|
/**
|
|
@@ -1234,6 +1491,11 @@ class LikeC4Model {
|
|
|
1234
1491
|
get projectId() {
|
|
1235
1492
|
return this.$data.projectId ?? "unknown";
|
|
1236
1493
|
}
|
|
1494
|
+
get project() {
|
|
1495
|
+
return this.$data.project ?? memoizeProp(this, Symbol.for("project"), () => ({
|
|
1496
|
+
id: this.projectId
|
|
1497
|
+
}));
|
|
1498
|
+
}
|
|
1237
1499
|
get specification() {
|
|
1238
1500
|
return this.$data.specification;
|
|
1239
1501
|
}
|
|
@@ -1250,6 +1512,21 @@ class LikeC4Model {
|
|
|
1250
1512
|
}
|
|
1251
1513
|
}));
|
|
1252
1514
|
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Returns the element with the given FQN.
|
|
1517
|
+
*
|
|
1518
|
+
* @throws Error if element is not found\
|
|
1519
|
+
* Use {@link findElement} if you don't want to throw an error
|
|
1520
|
+
*
|
|
1521
|
+
* @note Method is type-safe for typed model
|
|
1522
|
+
|
|
1523
|
+
* @example
|
|
1524
|
+
* model.element('cloud.frontend')
|
|
1525
|
+
* // or object with id property of scalar.Fqn
|
|
1526
|
+
* model.element({
|
|
1527
|
+
* id: 'dashboard',
|
|
1528
|
+
* })
|
|
1529
|
+
*/
|
|
1253
1530
|
element(el) {
|
|
1254
1531
|
if (el instanceof ElementModel) {
|
|
1255
1532
|
return el;
|
|
@@ -1257,6 +1534,15 @@ class LikeC4Model {
|
|
|
1257
1534
|
const id = getId(el);
|
|
1258
1535
|
return nonNullable(this._elements.get(id), `Element ${id} not found`);
|
|
1259
1536
|
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Returns the element with the given FQN.
|
|
1539
|
+
*
|
|
1540
|
+
* @returns Element if found, null otherwise
|
|
1541
|
+
* @note Method is not type-safe as {@link element}
|
|
1542
|
+
*
|
|
1543
|
+
* @example
|
|
1544
|
+
* model.findElement('cloud.frontend')
|
|
1545
|
+
*/
|
|
1260
1546
|
findElement(el) {
|
|
1261
1547
|
return this._elements.get(getId(el)) ?? null;
|
|
1262
1548
|
}
|
|
@@ -1307,14 +1593,62 @@ class LikeC4Model {
|
|
|
1307
1593
|
}
|
|
1308
1594
|
/**
|
|
1309
1595
|
* Returns a specific view by its ID.
|
|
1596
|
+
* @note Method is type-safe for typed model
|
|
1597
|
+
* @throws Error if view is not found\
|
|
1598
|
+
* Use {@link findView} if you don't want to throw an error
|
|
1599
|
+
*
|
|
1600
|
+
* @example
|
|
1601
|
+
* model.view('index')
|
|
1602
|
+
* // or object with id property of scalar.ViewId
|
|
1603
|
+
* model.view({
|
|
1604
|
+
* id: 'index',
|
|
1605
|
+
* })
|
|
1310
1606
|
*/
|
|
1311
1607
|
view(viewId) {
|
|
1312
1608
|
const id = getId(viewId);
|
|
1313
1609
|
return nonNullable(this._views.get(id), `View ${id} not found`);
|
|
1314
1610
|
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Returns a specific view by its ID.
|
|
1613
|
+
* @note Method is not type-safe as {@link view}
|
|
1614
|
+
*
|
|
1615
|
+
* @example
|
|
1616
|
+
* model.findView('index')
|
|
1617
|
+
*/
|
|
1315
1618
|
findView(viewId) {
|
|
1316
1619
|
return this._views.get(viewId) ?? null;
|
|
1317
1620
|
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Returns a view folder by its path.
|
|
1623
|
+
* Path is extracted from the view title, e.g. "Group 1/Group 2/View" -> "Group 1/Group 2"
|
|
1624
|
+
* @throws Error if view folder is not found.
|
|
1625
|
+
*/
|
|
1626
|
+
viewFolder(path) {
|
|
1627
|
+
return nonNullable(this._viewFolders.get(path), `View folder ${path} not found`);
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Root folder is a special one with an empty path and used only for internal purposes.
|
|
1631
|
+
* It is not visible to the user and should be used only to get top-level folders and views.
|
|
1632
|
+
*/
|
|
1633
|
+
get rootViewFolder() {
|
|
1634
|
+
return this._rootViewFolder;
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Whether the model has any view folders.
|
|
1638
|
+
*/
|
|
1639
|
+
get hasViewFolders() {
|
|
1640
|
+
return this._viewFolders.size > 1;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Returns all children of a view folder.
|
|
1644
|
+
* Path is extracted from the view title, e.g. "Group 1/Group 2/View" -> "Group 1/Group 2"
|
|
1645
|
+
*
|
|
1646
|
+
* @throws Error if view folder is not found.
|
|
1647
|
+
*/
|
|
1648
|
+
viewFolderItems(path) {
|
|
1649
|
+
invariant(this._viewFolders.has(path), `View folder ${path} not found`);
|
|
1650
|
+
return this._viewFolderItems.get(path);
|
|
1651
|
+
}
|
|
1318
1652
|
/**
|
|
1319
1653
|
* Returns the parent element of given element.
|
|
1320
1654
|
* @see ancestors
|
|
@@ -1403,7 +1737,8 @@ class LikeC4Model {
|
|
|
1403
1737
|
return;
|
|
1404
1738
|
}
|
|
1405
1739
|
/**
|
|
1406
|
-
* Returns all tags used in the model, sorted
|
|
1740
|
+
* Returns array of all tags used in the model, sorted naturally.\
|
|
1741
|
+
* Use {@link specification.tags} to get all defined tags
|
|
1407
1742
|
*/
|
|
1408
1743
|
get tags() {
|
|
1409
1744
|
return memoizeProp(this, "tags", () => m([...this._allTags.keys()], compareNatural));
|
|
@@ -1420,7 +1755,7 @@ class LikeC4Model {
|
|
|
1420
1755
|
tagged
|
|
1421
1756
|
})),
|
|
1422
1757
|
m((a, b) => compareNatural(a.tag, b.tag)),
|
|
1423
|
-
a(
|
|
1758
|
+
a$1(
|
|
1424
1759
|
[p("count"), "desc"]
|
|
1425
1760
|
)
|
|
1426
1761
|
));
|
|
@@ -1583,6 +1918,7 @@ class LikeC4Model {
|
|
|
1583
1918
|
LikeC4Model2.EMPTY = LikeC4Model2.create({
|
|
1584
1919
|
_stage: "computed",
|
|
1585
1920
|
projectId: "default",
|
|
1921
|
+
project: { id: "default" },
|
|
1586
1922
|
specification: {
|
|
1587
1923
|
elements: {},
|
|
1588
1924
|
relationships: {},
|
|
@@ -1636,4 +1972,4 @@ function isEdgeModel(edge) {
|
|
|
1636
1972
|
return edge instanceof EdgeModel;
|
|
1637
1973
|
}
|
|
1638
1974
|
|
|
1639
|
-
export { ElementModel as E, LikeC4Model as L, NodeModel as N, RelationshipModel as R, LikeC4DeploymentModel as a, EdgeModel as b, LikeC4ViewModel as c,
|
|
1975
|
+
export { ElementModel as E, LikeC4Model as L, NodeModel as N, RelationshipModel as R, VIEW_FOLDERS_SEPARATOR as V, LikeC4DeploymentModel as a, EdgeModel as b, LikeC4ViewModel as c, LikeC4ViewsFolder as d, extractViewTitleFromPath as e, isDeployedInstanceModel as f, getViewFolderPath as g, isDeploymentElementModel as h, isDeploymentNodeModel as i, isNestedElementOfDeployedInstanceModel as j, isDeploymentRelationModel as k, isRelationModel as l, isElementModel as m, normalizeViewPath as n, isLikeC4ViewModel as o, isNodeModel as p, isEdgeModel as q, r, a$1 as s, t, a as u };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { F as FqnRef
|
|
2
|
-
import { n } from './core.
|
|
1
|
+
import { F as FqnRef } from './core._jnYNUQ-.mjs';
|
|
2
|
+
import { n } from './core.CnIyafWn.mjs';
|
|
3
|
+
import { isStepEdgeId } from '../types/scalar.mjs';
|
|
3
4
|
|
|
4
5
|
function o(r){return Array.isArray(r)}
|
|
5
6
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { m as memoizeProp, b as markdownToText, a as markdownToHtml } from './core.B0oEIXqd.mjs';
|
|
2
2
|
import { n as nonexhaustive } from './core.D4npX2q8.mjs';
|
|
3
3
|
|
|
4
|
-
function n(e){return !!e}
|
|
5
|
-
|
|
6
4
|
const DefaultThemeColor = "primary";
|
|
7
5
|
const DefaultElementShape = "rectangle";
|
|
8
6
|
const DefaultShapeSize = "md";
|
|
@@ -165,4 +163,4 @@ class RichText {
|
|
|
165
163
|
}
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
export { DefaultThemeColor as D, RichText as R, DefaultElementShape as a, DefaultShapeSize as b, DefaultPaddingSize as c, DefaultTextSize as d, DefaultLineStyle as e, DefaultArrowType as f, DefaultRelationshipColor as g
|
|
166
|
+
export { DefaultThemeColor as D, RichText as R, DefaultElementShape as a, DefaultShapeSize as b, DefaultPaddingSize as c, DefaultTextSize as d, DefaultLineStyle as e, DefaultArrowType as f, DefaultRelationshipColor as g };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as ElementModel, e as DeploymentElementModel } from './core.
|
|
2
|
-
import { A as Any } from './core.
|
|
1
|
+
import { E as ElementModel, e as DeploymentElementModel } from './core.DoNP3Yl-.mjs';
|
|
2
|
+
import { A as Any } from './core.BFb3p5d-.mjs';
|
|
3
3
|
import { F as Fqn } from './core.668kXpZq.mjs';
|
|
4
4
|
|
|
5
5
|
interface Connection<Elem = ElementModel<Any> | DeploymentElementModel<Any>, Id = string> {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as Connection, c as customInspectSymbol } from './core.
|
|
2
|
-
import { e as DeploymentElementModel, i as RelationshipsAccum, D as DeploymentNodeModel, R as RelationshipModel, b as DeploymentRelationModel } from './core.
|
|
3
|
-
import { A as Any,
|
|
1
|
+
import { C as Connection, c as customInspectSymbol } from './core.D8bTI5KC.mjs';
|
|
2
|
+
import { e as DeploymentElementModel, i as RelationshipsAccum, D as DeploymentNodeModel, R as RelationshipModel, b as DeploymentRelationModel } from './core.DoNP3Yl-.mjs';
|
|
3
|
+
import { A as Any, C as EdgeId } from './core.BFb3p5d-.mjs';
|
|
4
4
|
import { I as IteratorLike } from './core.DuSLYTG6.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -92,10 +92,8 @@ function compareNaturalHierarchically(separator = ".") {
|
|
|
92
92
|
if (!b) return 1;
|
|
93
93
|
const aParts = a.split(separator);
|
|
94
94
|
const bParts = b.split(separator);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
for (let i = 0; i < aParts.length; i++) {
|
|
95
|
+
const minLength = Math.min(aParts.length, bParts.length);
|
|
96
|
+
for (let i = 0; i < minLength; i++) {
|
|
99
97
|
const aPart = aParts[i];
|
|
100
98
|
const bPart = bParts[i];
|
|
101
99
|
const comparison = compare(aPart, bPart);
|
|
@@ -103,7 +101,7 @@ function compareNaturalHierarchically(separator = ".") {
|
|
|
103
101
|
return comparison;
|
|
104
102
|
}
|
|
105
103
|
}
|
|
106
|
-
return
|
|
104
|
+
return aParts.length - bParts.length;
|
|
107
105
|
};
|
|
108
106
|
}
|
|
109
107
|
|