@agilewallaby/c4-model 2.7.0 → 2.8.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/package.json +1 -1
- package/src/buildModel.d.ts +7 -4
- package/src/container.d.ts +8 -1
- package/src/exportWorkspaceJson.d.ts +4 -0
- package/src/generateDiagrams.d.ts +1 -3
- package/src/index.cjs +340 -43
- package/src/index.d.ts +138 -45
- package/src/index.js +336 -41
- package/src/model.d.ts +13 -3
- package/src/softwareSystem.d.ts +8 -1
- package/src/structurizrDslWriter.d.ts +5 -0
- package/src/validateModel.d.ts +3 -0
- package/src/views.d.ts +63 -2
package/src/index.cjs
CHANGED
|
@@ -44,9 +44,11 @@ __export(index_exports, {
|
|
|
44
44
|
View: () => View,
|
|
45
45
|
Views: () => Views,
|
|
46
46
|
buildModel: () => buildModel,
|
|
47
|
-
|
|
47
|
+
exportWorkspaceJson: () => exportWorkspaceJson,
|
|
48
|
+
exportWorkspaceJsonFromDsl: () => exportWorkspaceJsonFromDsl,
|
|
48
49
|
generateDiagrams: () => generateDiagrams,
|
|
49
|
-
mergeArchetypeWithOverride: () => mergeArchetypeWithOverride
|
|
50
|
+
mergeArchetypeWithOverride: () => mergeArchetypeWithOverride,
|
|
51
|
+
validateModel: () => validateModel
|
|
50
52
|
});
|
|
51
53
|
module.exports = __toCommonJS(index_exports);
|
|
52
54
|
|
|
@@ -221,9 +223,9 @@ var Element = class {
|
|
|
221
223
|
getRelationshipsInHierarchy() {
|
|
222
224
|
return this._relationships.concat(this.getChildElements().flatMap((element) => element.getRelationshipsInHierarchy()));
|
|
223
225
|
}
|
|
224
|
-
getChildElementNames(
|
|
226
|
+
getChildElementNames(path4) {
|
|
225
227
|
const result = Array.from(this.getChildElements()).flatMap((reference) => {
|
|
226
|
-
const currentPath = `${
|
|
228
|
+
const currentPath = `${path4 ? path4 : "" + this.name}.${reference.name}`;
|
|
227
229
|
return [currentPath, ...reference.getChildElementNames(currentPath)];
|
|
228
230
|
});
|
|
229
231
|
return result;
|
|
@@ -279,21 +281,46 @@ var Component = class extends TechnicalElement {
|
|
|
279
281
|
};
|
|
280
282
|
|
|
281
283
|
// libs/c4-model/src/container.ts
|
|
282
|
-
var ContainerGroup = class extends Group {
|
|
283
|
-
constructor(name, container) {
|
|
284
|
+
var ContainerGroup = class _ContainerGroup extends Group {
|
|
285
|
+
constructor(name, container, pathSegments = []) {
|
|
284
286
|
super(name);
|
|
285
287
|
this.name = name;
|
|
286
288
|
this.container = container;
|
|
289
|
+
this.pathSegments = pathSegments;
|
|
287
290
|
}
|
|
288
291
|
_components = /* @__PURE__ */ new Map();
|
|
292
|
+
_groups = /* @__PURE__ */ new Map();
|
|
293
|
+
get canonicalName() {
|
|
294
|
+
return camelCase([...this.pathSegments, this.name].join(" "));
|
|
295
|
+
}
|
|
296
|
+
get dslName() {
|
|
297
|
+
return [...this.pathSegments, this.name].join("/");
|
|
298
|
+
}
|
|
289
299
|
component(name, archetypeOrDef, override) {
|
|
290
300
|
const component = this.container.component(name, archetypeOrDef, override);
|
|
291
301
|
this._components.set(name, component);
|
|
292
302
|
return component;
|
|
293
303
|
}
|
|
304
|
+
group(groupName) {
|
|
305
|
+
let group = this._groups.get(groupName);
|
|
306
|
+
if (!group) {
|
|
307
|
+
group = new _ContainerGroup(groupName, this.container, [...this.pathSegments, this.name]);
|
|
308
|
+
this._groups.set(groupName, group);
|
|
309
|
+
}
|
|
310
|
+
return group;
|
|
311
|
+
}
|
|
312
|
+
getGroups() {
|
|
313
|
+
return Array.from(this._groups.values());
|
|
314
|
+
}
|
|
294
315
|
getComponents() {
|
|
295
316
|
return Array.from(this._components.values());
|
|
296
317
|
}
|
|
318
|
+
getAllComponents() {
|
|
319
|
+
return [
|
|
320
|
+
...this._components.values(),
|
|
321
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllComponents())
|
|
322
|
+
];
|
|
323
|
+
}
|
|
297
324
|
};
|
|
298
325
|
var Container = class extends TechnicalElement {
|
|
299
326
|
constructor(name, definition, archetype, overrideDefinition) {
|
|
@@ -330,7 +357,7 @@ var Container = class extends TechnicalElement {
|
|
|
330
357
|
return Array.from(this._groups.values());
|
|
331
358
|
}
|
|
332
359
|
getComponentsNotInGroups() {
|
|
333
|
-
const componentsInGroups = this.getGroups().flatMap((group) => group.
|
|
360
|
+
const componentsInGroups = this.getGroups().flatMap((group) => group.getAllComponents());
|
|
334
361
|
return Array.from(this._components.values()).filter((component) => !componentsInGroups.includes(component));
|
|
335
362
|
}
|
|
336
363
|
getChildElements() {
|
|
@@ -339,21 +366,46 @@ var Container = class extends TechnicalElement {
|
|
|
339
366
|
};
|
|
340
367
|
|
|
341
368
|
// libs/c4-model/src/softwareSystem.ts
|
|
342
|
-
var SoftwareSystemGroup = class extends Group {
|
|
343
|
-
constructor(name, softwareSystem) {
|
|
369
|
+
var SoftwareSystemGroup = class _SoftwareSystemGroup extends Group {
|
|
370
|
+
constructor(name, softwareSystem, pathSegments = []) {
|
|
344
371
|
super(name);
|
|
345
372
|
this.name = name;
|
|
346
373
|
this.softwareSystem = softwareSystem;
|
|
374
|
+
this.pathSegments = pathSegments;
|
|
347
375
|
}
|
|
348
376
|
_containers = /* @__PURE__ */ new Map();
|
|
377
|
+
_groups = /* @__PURE__ */ new Map();
|
|
378
|
+
get canonicalName() {
|
|
379
|
+
return camelCase([...this.pathSegments, this.name].join(" "));
|
|
380
|
+
}
|
|
381
|
+
get dslName() {
|
|
382
|
+
return [...this.pathSegments, this.name].join("/");
|
|
383
|
+
}
|
|
349
384
|
container(name, archetypeOrDef, override) {
|
|
350
385
|
const container = this.softwareSystem.container(name, archetypeOrDef, override);
|
|
351
386
|
this._containers.set(name, container);
|
|
352
387
|
return container;
|
|
353
388
|
}
|
|
389
|
+
group(groupName) {
|
|
390
|
+
let group = this._groups.get(groupName);
|
|
391
|
+
if (!group) {
|
|
392
|
+
group = new _SoftwareSystemGroup(groupName, this.softwareSystem, [...this.pathSegments, this.name]);
|
|
393
|
+
this._groups.set(groupName, group);
|
|
394
|
+
}
|
|
395
|
+
return group;
|
|
396
|
+
}
|
|
397
|
+
getGroups() {
|
|
398
|
+
return Array.from(this._groups.values());
|
|
399
|
+
}
|
|
354
400
|
getContainers() {
|
|
355
401
|
return Array.from(this._containers.values());
|
|
356
402
|
}
|
|
403
|
+
getAllContainers() {
|
|
404
|
+
return [
|
|
405
|
+
...this._containers.values(),
|
|
406
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllContainers())
|
|
407
|
+
];
|
|
408
|
+
}
|
|
357
409
|
};
|
|
358
410
|
var SoftwareSystem = class extends Element {
|
|
359
411
|
constructor(name, definition, archetype, overrideDefinition) {
|
|
@@ -393,7 +445,7 @@ var SoftwareSystem = class extends Element {
|
|
|
393
445
|
return Array.from(this._containers.values());
|
|
394
446
|
}
|
|
395
447
|
getContainersNotInGroups() {
|
|
396
|
-
const containersInGroups = Array.from(this._groups.values()).flatMap((group) => group.
|
|
448
|
+
const containersInGroups = Array.from(this._groups.values()).flatMap((group) => group.getAllContainers());
|
|
397
449
|
return Array.from(this._containers.values()).filter((container) => !containersInGroups.includes(container));
|
|
398
450
|
}
|
|
399
451
|
};
|
|
@@ -410,14 +462,22 @@ var Person = class extends Element {
|
|
|
410
462
|
};
|
|
411
463
|
|
|
412
464
|
// libs/c4-model/src/model.ts
|
|
413
|
-
var ModelGroup = class extends Group {
|
|
414
|
-
constructor(name, model) {
|
|
465
|
+
var ModelGroup = class _ModelGroup extends Group {
|
|
466
|
+
constructor(name, model, pathSegments = []) {
|
|
415
467
|
super(name);
|
|
416
468
|
this.name = name;
|
|
417
469
|
this.model = model;
|
|
470
|
+
this.pathSegments = pathSegments;
|
|
418
471
|
}
|
|
419
472
|
softwareSystems = /* @__PURE__ */ new Map();
|
|
420
473
|
people = /* @__PURE__ */ new Map();
|
|
474
|
+
_groups = /* @__PURE__ */ new Map();
|
|
475
|
+
get canonicalName() {
|
|
476
|
+
return camelCase([...this.pathSegments, this.name].join(" "));
|
|
477
|
+
}
|
|
478
|
+
get dslName() {
|
|
479
|
+
return [...this.pathSegments, this.name].join("/");
|
|
480
|
+
}
|
|
421
481
|
softwareSystem(name, archetypeOrDef, override) {
|
|
422
482
|
const softwareSystem = this.model.softwareSystem(name, archetypeOrDef, override);
|
|
423
483
|
this.softwareSystems.set(name, softwareSystem);
|
|
@@ -428,12 +488,35 @@ var ModelGroup = class extends Group {
|
|
|
428
488
|
this.people.set(name, person);
|
|
429
489
|
return person;
|
|
430
490
|
}
|
|
491
|
+
group(groupName) {
|
|
492
|
+
let group = this._groups.get(groupName);
|
|
493
|
+
if (!group) {
|
|
494
|
+
group = new _ModelGroup(groupName, this.model, [...this.pathSegments, this.name]);
|
|
495
|
+
this._groups.set(groupName, group);
|
|
496
|
+
}
|
|
497
|
+
return group;
|
|
498
|
+
}
|
|
499
|
+
getGroups() {
|
|
500
|
+
return Array.from(this._groups.values());
|
|
501
|
+
}
|
|
431
502
|
getSoftwareSystems() {
|
|
432
503
|
return Array.from(this.softwareSystems.values());
|
|
433
504
|
}
|
|
434
505
|
getPeople() {
|
|
435
506
|
return Array.from(this.people.values());
|
|
436
507
|
}
|
|
508
|
+
getAllSoftwareSystems() {
|
|
509
|
+
return [
|
|
510
|
+
...this.softwareSystems.values(),
|
|
511
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllSoftwareSystems())
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
getAllPeople() {
|
|
515
|
+
return [
|
|
516
|
+
...this.people.values(),
|
|
517
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllPeople())
|
|
518
|
+
];
|
|
519
|
+
}
|
|
437
520
|
};
|
|
438
521
|
var Model = class {
|
|
439
522
|
constructor(name) {
|
|
@@ -458,7 +541,6 @@ var Model = class {
|
|
|
458
541
|
this.softwareSystems.set(name, system);
|
|
459
542
|
return system;
|
|
460
543
|
}
|
|
461
|
-
// TODO:Should be a Group<SoftwareSystem | Person> if that is added back in
|
|
462
544
|
group(groupName) {
|
|
463
545
|
let group = this.groups.get(groupName);
|
|
464
546
|
if (!group) {
|
|
@@ -493,11 +575,11 @@ var Model = class {
|
|
|
493
575
|
return Array.from(this.softwareSystems.values());
|
|
494
576
|
}
|
|
495
577
|
getPeopleNotInGroups() {
|
|
496
|
-
const peopleInGroups = Array.from(this.groups.values()).flatMap((group) => group.
|
|
578
|
+
const peopleInGroups = Array.from(this.groups.values()).flatMap((group) => group.getAllPeople());
|
|
497
579
|
return Array.from(this.people.values()).filter((person) => !peopleInGroups.includes(person));
|
|
498
580
|
}
|
|
499
581
|
getSoftwareSystemsNotInGroups() {
|
|
500
|
-
const systemsInGroups = Array.from(this.groups.values()).flatMap((group) => group.
|
|
582
|
+
const systemsInGroups = Array.from(this.groups.values()).flatMap((group) => group.getAllSoftwareSystems());
|
|
501
583
|
return Array.from(this.softwareSystems.values()).filter((system) => !systemsInGroups.includes(system));
|
|
502
584
|
}
|
|
503
585
|
getGroups() {
|
|
@@ -517,6 +599,9 @@ var View = class {
|
|
|
517
599
|
description;
|
|
518
600
|
title;
|
|
519
601
|
_scopes = [];
|
|
602
|
+
_autoLayout;
|
|
603
|
+
_isDefault = false;
|
|
604
|
+
_properties = /* @__PURE__ */ new Map();
|
|
520
605
|
includeAll() {
|
|
521
606
|
this._scopes.push("include *");
|
|
522
607
|
}
|
|
@@ -535,15 +620,37 @@ var View = class {
|
|
|
535
620
|
excludeExpression(expression) {
|
|
536
621
|
this._scopes.push(`exclude ${expression}`);
|
|
537
622
|
}
|
|
623
|
+
autoLayout(direction, rankSeparation, nodeSeparation) {
|
|
624
|
+
this._autoLayout = { direction, rankSeparation, nodeSeparation };
|
|
625
|
+
}
|
|
626
|
+
setDefault() {
|
|
627
|
+
this._isDefault = true;
|
|
628
|
+
}
|
|
629
|
+
addProperty(name, value) {
|
|
630
|
+
this._properties.set(name, value);
|
|
631
|
+
}
|
|
538
632
|
get scopes() {
|
|
539
633
|
return this._scopes;
|
|
540
634
|
}
|
|
635
|
+
get autoLayoutConfig() {
|
|
636
|
+
return this._autoLayout;
|
|
637
|
+
}
|
|
638
|
+
get isDefault() {
|
|
639
|
+
return this._isDefault;
|
|
640
|
+
}
|
|
641
|
+
get properties() {
|
|
642
|
+
return this._properties;
|
|
643
|
+
}
|
|
541
644
|
};
|
|
542
645
|
var Views = class {
|
|
543
646
|
_systemLandscapeViews = /* @__PURE__ */ new Map();
|
|
544
647
|
_systemContextViews = /* @__PURE__ */ new Map();
|
|
545
648
|
_containerViews = /* @__PURE__ */ new Map();
|
|
546
649
|
_componentViews = /* @__PURE__ */ new Map();
|
|
650
|
+
_elementStyles = [];
|
|
651
|
+
_relationshipStyles = [];
|
|
652
|
+
_themes = [];
|
|
653
|
+
_properties = /* @__PURE__ */ new Map();
|
|
547
654
|
addSystemLandscapeView(key, definition) {
|
|
548
655
|
const view = new View(key, { subject: void 0, description: definition.description, title: definition.title });
|
|
549
656
|
this._systemLandscapeViews.set(key, view);
|
|
@@ -564,6 +671,18 @@ var Views = class {
|
|
|
564
671
|
this._componentViews.set(key, view);
|
|
565
672
|
return view;
|
|
566
673
|
}
|
|
674
|
+
addElementStyle(tag, definition) {
|
|
675
|
+
this._elementStyles.push({ tag, definition });
|
|
676
|
+
}
|
|
677
|
+
addRelationshipStyle(tag, definition) {
|
|
678
|
+
this._relationshipStyles.push({ tag, definition });
|
|
679
|
+
}
|
|
680
|
+
addTheme(url) {
|
|
681
|
+
this._themes.push(url);
|
|
682
|
+
}
|
|
683
|
+
addProperty(name, value) {
|
|
684
|
+
this._properties.set(name, value);
|
|
685
|
+
}
|
|
567
686
|
get systemLandscapeViews() {
|
|
568
687
|
return Array.from(this._systemLandscapeViews.values());
|
|
569
688
|
}
|
|
@@ -576,6 +695,18 @@ var Views = class {
|
|
|
576
695
|
get componentViews() {
|
|
577
696
|
return Array.from(this._componentViews.values());
|
|
578
697
|
}
|
|
698
|
+
get elementStyles() {
|
|
699
|
+
return this._elementStyles;
|
|
700
|
+
}
|
|
701
|
+
get relationshipStyles() {
|
|
702
|
+
return this._relationshipStyles;
|
|
703
|
+
}
|
|
704
|
+
get themes() {
|
|
705
|
+
return this._themes;
|
|
706
|
+
}
|
|
707
|
+
get properties() {
|
|
708
|
+
return this._properties;
|
|
709
|
+
}
|
|
579
710
|
};
|
|
580
711
|
|
|
581
712
|
// libs/c4-model/src/structurizrDslWriter.ts
|
|
@@ -710,11 +841,17 @@ var StructurizrDSLWriter = class {
|
|
|
710
841
|
}
|
|
711
842
|
writeContainerGroup(group, level) {
|
|
712
843
|
let containerGroupDsl = "";
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
containerGroupDsl += this.
|
|
844
|
+
const hasDirect = group.getComponents().length > 0;
|
|
845
|
+
if (hasDirect) {
|
|
846
|
+
containerGroupDsl += this.writeLine(`${group.canonicalName} = group "${group.dslName}" {`, level);
|
|
847
|
+
group.getComponents().forEach((component) => {
|
|
848
|
+
containerGroupDsl += this.writeComponent(component, level + 1);
|
|
849
|
+
});
|
|
850
|
+
containerGroupDsl += this.writeLine(`}`, level);
|
|
851
|
+
}
|
|
852
|
+
group.getGroups().forEach((nested) => {
|
|
853
|
+
containerGroupDsl += this.writeContainerGroup(nested, level);
|
|
716
854
|
});
|
|
717
|
-
containerGroupDsl += this.writeLine(`}`, level);
|
|
718
855
|
return containerGroupDsl;
|
|
719
856
|
}
|
|
720
857
|
writeContainer(container, level) {
|
|
@@ -734,11 +871,17 @@ var StructurizrDSLWriter = class {
|
|
|
734
871
|
}
|
|
735
872
|
writeSoftwareSystemGroup(group, level) {
|
|
736
873
|
let softwareSystemGroupDsl = "";
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
softwareSystemGroupDsl += this.
|
|
874
|
+
const hasDirect = group.getContainers().length > 0;
|
|
875
|
+
if (hasDirect) {
|
|
876
|
+
softwareSystemGroupDsl += this.writeLine(`${group.canonicalName} = group "${group.dslName}" {`, level);
|
|
877
|
+
group.getContainers().forEach((container) => {
|
|
878
|
+
softwareSystemGroupDsl += this.writeContainer(container, level + 1);
|
|
879
|
+
});
|
|
880
|
+
softwareSystemGroupDsl += this.writeLine(`}`, level);
|
|
881
|
+
}
|
|
882
|
+
group.getGroups().forEach((nested) => {
|
|
883
|
+
softwareSystemGroupDsl += this.writeSoftwareSystemGroup(nested, level);
|
|
740
884
|
});
|
|
741
|
-
softwareSystemGroupDsl += this.writeLine(`}`, level);
|
|
742
885
|
return softwareSystemGroupDsl;
|
|
743
886
|
}
|
|
744
887
|
writeSoftwareSystem(softwareSystem, level) {
|
|
@@ -790,21 +933,51 @@ var StructurizrDSLWriter = class {
|
|
|
790
933
|
});
|
|
791
934
|
return relationshipsDsl;
|
|
792
935
|
}
|
|
936
|
+
hasNestedModelGroups(groups) {
|
|
937
|
+
return groups.some((g) => g.getGroups().length > 0 || this.hasNestedModelGroups(g.getGroups()));
|
|
938
|
+
}
|
|
939
|
+
hasNestedSoftwareSystemGroups(groups) {
|
|
940
|
+
return groups.some((g) => g.getGroups().length > 0 || this.hasNestedSoftwareSystemGroups(g.getGroups()));
|
|
941
|
+
}
|
|
942
|
+
hasNestedContainerGroups(groups) {
|
|
943
|
+
return groups.some((g) => g.getGroups().length > 0 || this.hasNestedContainerGroups(g.getGroups()));
|
|
944
|
+
}
|
|
945
|
+
hasNestedGroups() {
|
|
946
|
+
if (this.hasNestedModelGroups(this.model.getGroups())) return true;
|
|
947
|
+
for (const ss of this.model.getSoftwareSystems()) {
|
|
948
|
+
if (this.hasNestedSoftwareSystemGroups(ss.getGroups())) return true;
|
|
949
|
+
for (const c of ss.getGroups().flatMap((g) => g.getAllContainers())) {
|
|
950
|
+
if (this.hasNestedContainerGroups(c.getGroups())) return true;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
793
955
|
writeModelGroup(group, level) {
|
|
794
956
|
let modelGroupDsl = "";
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
modelGroupDsl += this.
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
957
|
+
const hasDirect = group.getPeople().length > 0 || group.getSoftwareSystems().length > 0;
|
|
958
|
+
if (hasDirect) {
|
|
959
|
+
modelGroupDsl += this.writeLine(`${group.canonicalName} = group "${group.dslName}" {`, level);
|
|
960
|
+
group.getPeople().forEach((person) => {
|
|
961
|
+
modelGroupDsl += this.writeElement("person", person, level + 1);
|
|
962
|
+
});
|
|
963
|
+
group.getSoftwareSystems().forEach((softwareSystem) => {
|
|
964
|
+
modelGroupDsl += this.writeSoftwareSystem(softwareSystem, level + 1);
|
|
965
|
+
});
|
|
966
|
+
modelGroupDsl += this.writeLine(`}`, level);
|
|
967
|
+
}
|
|
968
|
+
group.getGroups().forEach((nested) => {
|
|
969
|
+
modelGroupDsl += this.writeModelGroup(nested, level);
|
|
801
970
|
});
|
|
802
|
-
modelGroupDsl += this.writeLine(`}`, level);
|
|
803
971
|
return modelGroupDsl;
|
|
804
972
|
}
|
|
805
973
|
writeModel(model, level) {
|
|
806
974
|
let modelDsl = "";
|
|
807
975
|
modelDsl += this.writeLine(`model {`, level);
|
|
976
|
+
if (this.hasNestedGroups()) {
|
|
977
|
+
modelDsl += this.writeLine(`properties {`, level + 1);
|
|
978
|
+
modelDsl += this.writeLine(`"structurizr.groupSeparator" "/"`, level + 2);
|
|
979
|
+
modelDsl += this.writeLine(`}`, level + 1);
|
|
980
|
+
}
|
|
808
981
|
modelDsl += this.writeArchetypes(level + 1);
|
|
809
982
|
modelDsl += this.writeLine("// Elements", level + 1);
|
|
810
983
|
model.getPeopleNotInGroups().forEach((person) => {
|
|
@@ -827,12 +1000,66 @@ var StructurizrDSLWriter = class {
|
|
|
827
1000
|
if (view.title) {
|
|
828
1001
|
viewDsl += this.writeLine(`title "${view.title}"`, level + 1);
|
|
829
1002
|
}
|
|
1003
|
+
if (view.isDefault) {
|
|
1004
|
+
viewDsl += this.writeLine("default", level + 1);
|
|
1005
|
+
}
|
|
830
1006
|
view.scopes.forEach((scope) => {
|
|
831
1007
|
viewDsl += this.writeLine(`${scope}`, level + 1);
|
|
832
1008
|
});
|
|
1009
|
+
if (view.autoLayoutConfig) {
|
|
1010
|
+
const { direction, rankSeparation, nodeSeparation } = view.autoLayoutConfig;
|
|
1011
|
+
let line = "autoLayout";
|
|
1012
|
+
if (direction) line += ` ${direction}`;
|
|
1013
|
+
if (rankSeparation !== void 0) line += ` ${rankSeparation}`;
|
|
1014
|
+
if (nodeSeparation !== void 0) line += ` ${nodeSeparation}`;
|
|
1015
|
+
viewDsl += this.writeLine(line, level + 1);
|
|
1016
|
+
}
|
|
1017
|
+
if (view.properties.size > 0) {
|
|
1018
|
+
viewDsl += this.writeLine("properties {", level + 1);
|
|
1019
|
+
for (const [name, value] of view.properties) {
|
|
1020
|
+
viewDsl += this.writeLine(`"${name}" "${value}"`, level + 2);
|
|
1021
|
+
}
|
|
1022
|
+
viewDsl += this.writeLine("}", level + 1);
|
|
1023
|
+
}
|
|
833
1024
|
viewDsl += this.writeLine(`}`, level);
|
|
834
1025
|
return viewDsl;
|
|
835
1026
|
}
|
|
1027
|
+
writeStyles(views, level) {
|
|
1028
|
+
const { elementStyles, relationshipStyles } = views;
|
|
1029
|
+
if (elementStyles.length === 0 && relationshipStyles.length === 0) return "";
|
|
1030
|
+
let dsl = this.writeLine("styles {", level);
|
|
1031
|
+
for (const { tag, definition: d } of elementStyles) {
|
|
1032
|
+
dsl += this.writeLine(`element "${tag}" {`, level + 1);
|
|
1033
|
+
if (d.shape) dsl += this.writeLine(`shape ${d.shape}`, level + 2);
|
|
1034
|
+
if (d.icon) dsl += this.writeLine(`icon "${d.icon}"`, level + 2);
|
|
1035
|
+
if (d.width) dsl += this.writeLine(`width ${d.width}`, level + 2);
|
|
1036
|
+
if (d.height) dsl += this.writeLine(`height ${d.height}`, level + 2);
|
|
1037
|
+
if (d.background) dsl += this.writeLine(`background "${d.background}"`, level + 2);
|
|
1038
|
+
if (d.color) dsl += this.writeLine(`color "${d.color}"`, level + 2);
|
|
1039
|
+
if (d.stroke) dsl += this.writeLine(`stroke "${d.stroke}"`, level + 2);
|
|
1040
|
+
if (d.strokeWidth) dsl += this.writeLine(`strokeWidth ${d.strokeWidth}`, level + 2);
|
|
1041
|
+
if (d.fontSize) dsl += this.writeLine(`fontSize ${d.fontSize}`, level + 2);
|
|
1042
|
+
if (d.border) dsl += this.writeLine(`border ${d.border}`, level + 2);
|
|
1043
|
+
if (d.opacity !== void 0) dsl += this.writeLine(`opacity ${d.opacity}`, level + 2);
|
|
1044
|
+
if (d.metadata !== void 0) dsl += this.writeLine(`metadata ${d.metadata}`, level + 2);
|
|
1045
|
+
if (d.description !== void 0) dsl += this.writeLine(`description ${d.description}`, level + 2);
|
|
1046
|
+
dsl += this.writeLine("}", level + 1);
|
|
1047
|
+
}
|
|
1048
|
+
for (const { tag, definition: d } of relationshipStyles) {
|
|
1049
|
+
dsl += this.writeLine(`relationship "${tag}" {`, level + 1);
|
|
1050
|
+
if (d.thickness) dsl += this.writeLine(`thickness ${d.thickness}`, level + 2);
|
|
1051
|
+
if (d.color) dsl += this.writeLine(`color "${d.color}"`, level + 2);
|
|
1052
|
+
if (d.style) dsl += this.writeLine(`style ${d.style}`, level + 2);
|
|
1053
|
+
if (d.routing) dsl += this.writeLine(`routing ${d.routing}`, level + 2);
|
|
1054
|
+
if (d.fontSize) dsl += this.writeLine(`fontSize ${d.fontSize}`, level + 2);
|
|
1055
|
+
if (d.width) dsl += this.writeLine(`width ${d.width}`, level + 2);
|
|
1056
|
+
if (d.position !== void 0) dsl += this.writeLine(`position ${d.position}`, level + 2);
|
|
1057
|
+
if (d.opacity !== void 0) dsl += this.writeLine(`opacity ${d.opacity}`, level + 2);
|
|
1058
|
+
dsl += this.writeLine("}", level + 1);
|
|
1059
|
+
}
|
|
1060
|
+
dsl += this.writeLine("}", level);
|
|
1061
|
+
return dsl;
|
|
1062
|
+
}
|
|
836
1063
|
writeViews(views, level) {
|
|
837
1064
|
let viewDsl = "";
|
|
838
1065
|
viewDsl += this.writeLine(`views {`, level);
|
|
@@ -852,6 +1079,19 @@ var StructurizrDSLWriter = class {
|
|
|
852
1079
|
views.componentViews.forEach((view) => {
|
|
853
1080
|
viewDsl += this.writeView(view, "component", level + 1);
|
|
854
1081
|
});
|
|
1082
|
+
viewDsl += this.writeStyles(views, level + 1);
|
|
1083
|
+
if (views.themes.length === 1) {
|
|
1084
|
+
viewDsl += this.writeLine(`theme ${views.themes[0]}`, level + 1);
|
|
1085
|
+
} else if (views.themes.length > 1) {
|
|
1086
|
+
viewDsl += this.writeLine(`themes ${views.themes.join(" ")}`, level + 1);
|
|
1087
|
+
}
|
|
1088
|
+
if (views.properties.size > 0) {
|
|
1089
|
+
viewDsl += this.writeLine("properties {", level + 1);
|
|
1090
|
+
for (const [name, value] of views.properties) {
|
|
1091
|
+
viewDsl += this.writeLine(`"${name}" "${value}"`, level + 2);
|
|
1092
|
+
}
|
|
1093
|
+
viewDsl += this.writeLine("}", level + 1);
|
|
1094
|
+
}
|
|
855
1095
|
viewDsl += this.writeLine(`}`, level);
|
|
856
1096
|
return viewDsl;
|
|
857
1097
|
}
|
|
@@ -877,8 +1117,8 @@ var import_path = require("path");
|
|
|
877
1117
|
var import_url = require("url");
|
|
878
1118
|
var import_meta = {};
|
|
879
1119
|
var _dirname = typeof __dirname !== "undefined" ? __dirname : (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
|
|
880
|
-
async function
|
|
881
|
-
const { modelName = "model", modules: explicitModules, archetypes = {} } = options;
|
|
1120
|
+
async function buildModel(options = {}) {
|
|
1121
|
+
const { modelName = "model", modules: explicitModules, archetypes = {}, addViews } = options;
|
|
882
1122
|
const model = new Model(modelName);
|
|
883
1123
|
let c4Modules;
|
|
884
1124
|
if (explicitModules) {
|
|
@@ -902,14 +1142,16 @@ async function buildModelWithCatalog(options = {}) {
|
|
|
902
1142
|
rootCatalog[instance.key] = local;
|
|
903
1143
|
registrations.push({ instance, key: instance.key, local });
|
|
904
1144
|
}
|
|
1145
|
+
const dependenciesFor = (key) => Object.fromEntries(Object.entries(rootCatalog).filter(([k]) => k !== key));
|
|
905
1146
|
for (const { instance, key, local } of registrations) {
|
|
906
|
-
|
|
907
|
-
instance.buildRelationships(local, dependencies, archetypes);
|
|
1147
|
+
instance.addRelationships(local, dependenciesFor(key), archetypes);
|
|
908
1148
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1149
|
+
const views = new Views();
|
|
1150
|
+
addViews?.(views, rootCatalog);
|
|
1151
|
+
for (const { instance, key, local } of registrations) {
|
|
1152
|
+
instance.addViews?.(views, local, dependenciesFor(key));
|
|
1153
|
+
}
|
|
1154
|
+
return { model, catalog: rootCatalog, views };
|
|
913
1155
|
}
|
|
914
1156
|
|
|
915
1157
|
// libs/c4-model/src/generateDiagrams.ts
|
|
@@ -918,9 +1160,8 @@ var os = __toESM(require("os"), 1);
|
|
|
918
1160
|
var path = __toESM(require("path"), 1);
|
|
919
1161
|
var import_testcontainers = require("testcontainers");
|
|
920
1162
|
async function generateDiagrams(options) {
|
|
921
|
-
const {
|
|
922
|
-
const { model,
|
|
923
|
-
const views = viewsFactory(catalog);
|
|
1163
|
+
const { outputDir, ...buildOptions } = options;
|
|
1164
|
+
const { model, views } = await buildModel(buildOptions);
|
|
924
1165
|
const dsl = new StructurizrDSLWriter(model, views).write();
|
|
925
1166
|
const tmpDir = await fs.promises.mkdtemp(path.join(fs.realpathSync(os.tmpdir()), "c4-diagrams-"));
|
|
926
1167
|
await fs.promises.writeFile(path.join(tmpDir, "workspace.dsl"), dsl, "utf8");
|
|
@@ -941,6 +1182,60 @@ async function generateDiagrams(options) {
|
|
|
941
1182
|
}
|
|
942
1183
|
return generatedFiles;
|
|
943
1184
|
}
|
|
1185
|
+
|
|
1186
|
+
// libs/c4-model/src/validateModel.ts
|
|
1187
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
1188
|
+
var os2 = __toESM(require("os"), 1);
|
|
1189
|
+
var path2 = __toESM(require("path"), 1);
|
|
1190
|
+
var import_testcontainers2 = require("testcontainers");
|
|
1191
|
+
async function validateModel(model, views) {
|
|
1192
|
+
const dsl = new StructurizrDSLWriter(model, views).write();
|
|
1193
|
+
const tmpDir = await fs2.promises.mkdtemp(path2.join(fs2.realpathSync(os2.tmpdir()), "c4-validate-"));
|
|
1194
|
+
try {
|
|
1195
|
+
await fs2.promises.writeFile(path2.join(tmpDir, "workspace.dsl"), dsl, "utf8");
|
|
1196
|
+
const logs = [];
|
|
1197
|
+
try {
|
|
1198
|
+
await new import_testcontainers2.GenericContainer("structurizr/structurizr").withBindMounts([{ source: tmpDir, target: "/workspace", mode: "rw" }]).withCommand(["validate", "-workspace", "/workspace/workspace.dsl"]).withWaitStrategy(import_testcontainers2.Wait.forOneShotStartup()).withLogConsumer((stream) => stream.on("data", (chunk) => logs.push(chunk.toString()))).start();
|
|
1199
|
+
} catch {
|
|
1200
|
+
throw new Error(`Structurizr validation failed:
|
|
1201
|
+
${logs.join("")}`);
|
|
1202
|
+
}
|
|
1203
|
+
} finally {
|
|
1204
|
+
await fs2.promises.rm(tmpDir, { recursive: true, force: true });
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// libs/c4-model/src/exportWorkspaceJson.ts
|
|
1209
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
1210
|
+
var os3 = __toESM(require("os"), 1);
|
|
1211
|
+
var path3 = __toESM(require("path"), 1);
|
|
1212
|
+
var import_testcontainers3 = require("testcontainers");
|
|
1213
|
+
async function exportWorkspaceJsonFromDsl(dsl) {
|
|
1214
|
+
const tmpDir = await fs3.promises.mkdtemp(path3.join(fs3.realpathSync(os3.tmpdir()), "c4-export-"));
|
|
1215
|
+
try {
|
|
1216
|
+
await fs3.promises.writeFile(path3.join(tmpDir, "workspace.dsl"), dsl, "utf8");
|
|
1217
|
+
const logs = [];
|
|
1218
|
+
try {
|
|
1219
|
+
await new import_testcontainers3.GenericContainer("structurizr/structurizr").withBindMounts([{ source: tmpDir, target: "/workspace", mode: "rw" }]).withCommand(["export", "-w", "/workspace/workspace.dsl", "-f", "json", "-o", "/workspace"]).withWaitStrategy(import_testcontainers3.Wait.forOneShotStartup()).withLogConsumer((stream) => stream.on("data", (chunk) => logs.push(chunk.toString()))).start();
|
|
1220
|
+
} catch {
|
|
1221
|
+
throw new Error(`Structurizr JSON export failed:
|
|
1222
|
+
${logs.join("")}`);
|
|
1223
|
+
}
|
|
1224
|
+
const files = await fs3.promises.readdir(tmpDir);
|
|
1225
|
+
const jsonFile = files.find((f) => f.endsWith(".json"));
|
|
1226
|
+
if (!jsonFile) {
|
|
1227
|
+
throw new Error(`Structurizr JSON export produced no .json file. Files: ${files.join(", ")}`);
|
|
1228
|
+
}
|
|
1229
|
+
const jsonContent = await fs3.promises.readFile(path3.join(tmpDir, jsonFile), "utf8");
|
|
1230
|
+
return JSON.parse(jsonContent);
|
|
1231
|
+
} finally {
|
|
1232
|
+
await fs3.promises.rm(tmpDir, { recursive: true, force: true });
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
async function exportWorkspaceJson(model, views) {
|
|
1236
|
+
const dsl = new StructurizrDSLWriter(model, views).write();
|
|
1237
|
+
return exportWorkspaceJsonFromDsl(dsl);
|
|
1238
|
+
}
|
|
944
1239
|
// Annotate the CommonJS export names for ESM import in node:
|
|
945
1240
|
0 && (module.exports = {
|
|
946
1241
|
Component,
|
|
@@ -957,7 +1252,9 @@ async function generateDiagrams(options) {
|
|
|
957
1252
|
View,
|
|
958
1253
|
Views,
|
|
959
1254
|
buildModel,
|
|
960
|
-
|
|
1255
|
+
exportWorkspaceJson,
|
|
1256
|
+
exportWorkspaceJsonFromDsl,
|
|
961
1257
|
generateDiagrams,
|
|
962
|
-
mergeArchetypeWithOverride
|
|
1258
|
+
mergeArchetypeWithOverride,
|
|
1259
|
+
validateModel
|
|
963
1260
|
});
|