@agilewallaby/c4-model 2.6.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 +11 -4
- package/src/core.d.ts +6 -3
- package/src/exportWorkspaceJson.d.ts +4 -0
- package/src/generateDiagrams.d.ts +1 -3
- package/src/index.cjs +355 -46
- package/src/index.d.ts +151 -55
- package/src/index.js +351 -44
- package/src/model.d.ts +14 -4
- package/src/softwareSystem.d.ts +11 -4
- 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
|
|
|
@@ -214,12 +216,16 @@ var Element = class {
|
|
|
214
216
|
get relationships() {
|
|
215
217
|
return this._relationships;
|
|
216
218
|
}
|
|
219
|
+
with(callback) {
|
|
220
|
+
const children = callback(this);
|
|
221
|
+
return Object.assign(this, children);
|
|
222
|
+
}
|
|
217
223
|
getRelationshipsInHierarchy() {
|
|
218
224
|
return this._relationships.concat(this.getChildElements().flatMap((element) => element.getRelationshipsInHierarchy()));
|
|
219
225
|
}
|
|
220
|
-
getChildElementNames(
|
|
226
|
+
getChildElementNames(path4) {
|
|
221
227
|
const result = Array.from(this.getChildElements()).flatMap((reference) => {
|
|
222
|
-
const currentPath = `${
|
|
228
|
+
const currentPath = `${path4 ? path4 : "" + this.name}.${reference.name}`;
|
|
223
229
|
return [currentPath, ...reference.getChildElementNames(currentPath)];
|
|
224
230
|
});
|
|
225
231
|
return result;
|
|
@@ -252,6 +258,13 @@ var Group = class {
|
|
|
252
258
|
constructor(name) {
|
|
253
259
|
this.name = name;
|
|
254
260
|
}
|
|
261
|
+
get canonicalName() {
|
|
262
|
+
return camelCase(this.name);
|
|
263
|
+
}
|
|
264
|
+
with(callback) {
|
|
265
|
+
const children = callback(this);
|
|
266
|
+
return Object.assign(this, children);
|
|
267
|
+
}
|
|
255
268
|
// TODO: Implement this in some useful way?
|
|
256
269
|
// public addToGroup(groupCollection: string, groupMember: T) {}
|
|
257
270
|
};
|
|
@@ -268,21 +281,46 @@ var Component = class extends TechnicalElement {
|
|
|
268
281
|
};
|
|
269
282
|
|
|
270
283
|
// libs/c4-model/src/container.ts
|
|
271
|
-
var ContainerGroup = class extends Group {
|
|
272
|
-
constructor(name, container) {
|
|
284
|
+
var ContainerGroup = class _ContainerGroup extends Group {
|
|
285
|
+
constructor(name, container, pathSegments = []) {
|
|
273
286
|
super(name);
|
|
274
287
|
this.name = name;
|
|
275
288
|
this.container = container;
|
|
289
|
+
this.pathSegments = pathSegments;
|
|
276
290
|
}
|
|
277
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
|
+
}
|
|
278
299
|
component(name, archetypeOrDef, override) {
|
|
279
300
|
const component = this.container.component(name, archetypeOrDef, override);
|
|
280
301
|
this._components.set(name, component);
|
|
281
302
|
return component;
|
|
282
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
|
+
}
|
|
283
315
|
getComponents() {
|
|
284
316
|
return Array.from(this._components.values());
|
|
285
317
|
}
|
|
318
|
+
getAllComponents() {
|
|
319
|
+
return [
|
|
320
|
+
...this._components.values(),
|
|
321
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllComponents())
|
|
322
|
+
];
|
|
323
|
+
}
|
|
286
324
|
};
|
|
287
325
|
var Container = class extends TechnicalElement {
|
|
288
326
|
constructor(name, definition, archetype, overrideDefinition) {
|
|
@@ -307,7 +345,7 @@ var Container = class extends TechnicalElement {
|
|
|
307
345
|
this._components.set(name, component);
|
|
308
346
|
return component;
|
|
309
347
|
}
|
|
310
|
-
|
|
348
|
+
group(groupName) {
|
|
311
349
|
let group = this._groups.get(groupName);
|
|
312
350
|
if (!group) {
|
|
313
351
|
group = new ContainerGroup(groupName, this);
|
|
@@ -319,7 +357,7 @@ var Container = class extends TechnicalElement {
|
|
|
319
357
|
return Array.from(this._groups.values());
|
|
320
358
|
}
|
|
321
359
|
getComponentsNotInGroups() {
|
|
322
|
-
const componentsInGroups = this.getGroups().flatMap((group) => group.
|
|
360
|
+
const componentsInGroups = this.getGroups().flatMap((group) => group.getAllComponents());
|
|
323
361
|
return Array.from(this._components.values()).filter((component) => !componentsInGroups.includes(component));
|
|
324
362
|
}
|
|
325
363
|
getChildElements() {
|
|
@@ -328,21 +366,46 @@ var Container = class extends TechnicalElement {
|
|
|
328
366
|
};
|
|
329
367
|
|
|
330
368
|
// libs/c4-model/src/softwareSystem.ts
|
|
331
|
-
var SoftwareSystemGroup = class extends Group {
|
|
332
|
-
constructor(name, softwareSystem) {
|
|
369
|
+
var SoftwareSystemGroup = class _SoftwareSystemGroup extends Group {
|
|
370
|
+
constructor(name, softwareSystem, pathSegments = []) {
|
|
333
371
|
super(name);
|
|
334
372
|
this.name = name;
|
|
335
373
|
this.softwareSystem = softwareSystem;
|
|
374
|
+
this.pathSegments = pathSegments;
|
|
336
375
|
}
|
|
337
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
|
+
}
|
|
338
384
|
container(name, archetypeOrDef, override) {
|
|
339
385
|
const container = this.softwareSystem.container(name, archetypeOrDef, override);
|
|
340
386
|
this._containers.set(name, container);
|
|
341
387
|
return container;
|
|
342
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
|
+
}
|
|
343
400
|
getContainers() {
|
|
344
401
|
return Array.from(this._containers.values());
|
|
345
402
|
}
|
|
403
|
+
getAllContainers() {
|
|
404
|
+
return [
|
|
405
|
+
...this._containers.values(),
|
|
406
|
+
...Array.from(this._groups.values()).flatMap((g) => g.getAllContainers())
|
|
407
|
+
];
|
|
408
|
+
}
|
|
346
409
|
};
|
|
347
410
|
var SoftwareSystem = class extends Element {
|
|
348
411
|
constructor(name, definition, archetype, overrideDefinition) {
|
|
@@ -367,7 +430,7 @@ var SoftwareSystem = class extends Element {
|
|
|
367
430
|
this._containers.set(name, container);
|
|
368
431
|
return container;
|
|
369
432
|
}
|
|
370
|
-
|
|
433
|
+
group(groupName) {
|
|
371
434
|
let group = this._groups.get(groupName);
|
|
372
435
|
if (!group) {
|
|
373
436
|
group = new SoftwareSystemGroup(groupName, this);
|
|
@@ -382,7 +445,7 @@ var SoftwareSystem = class extends Element {
|
|
|
382
445
|
return Array.from(this._containers.values());
|
|
383
446
|
}
|
|
384
447
|
getContainersNotInGroups() {
|
|
385
|
-
const containersInGroups = Array.from(this._groups.values()).flatMap((group) => group.
|
|
448
|
+
const containersInGroups = Array.from(this._groups.values()).flatMap((group) => group.getAllContainers());
|
|
386
449
|
return Array.from(this._containers.values()).filter((container) => !containersInGroups.includes(container));
|
|
387
450
|
}
|
|
388
451
|
};
|
|
@@ -399,14 +462,22 @@ var Person = class extends Element {
|
|
|
399
462
|
};
|
|
400
463
|
|
|
401
464
|
// libs/c4-model/src/model.ts
|
|
402
|
-
var ModelGroup = class extends Group {
|
|
403
|
-
constructor(name, model) {
|
|
465
|
+
var ModelGroup = class _ModelGroup extends Group {
|
|
466
|
+
constructor(name, model, pathSegments = []) {
|
|
404
467
|
super(name);
|
|
405
468
|
this.name = name;
|
|
406
469
|
this.model = model;
|
|
470
|
+
this.pathSegments = pathSegments;
|
|
407
471
|
}
|
|
408
472
|
softwareSystems = /* @__PURE__ */ new Map();
|
|
409
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
|
+
}
|
|
410
481
|
softwareSystem(name, archetypeOrDef, override) {
|
|
411
482
|
const softwareSystem = this.model.softwareSystem(name, archetypeOrDef, override);
|
|
412
483
|
this.softwareSystems.set(name, softwareSystem);
|
|
@@ -417,12 +488,35 @@ var ModelGroup = class extends Group {
|
|
|
417
488
|
this.people.set(name, person);
|
|
418
489
|
return person;
|
|
419
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
|
+
}
|
|
420
502
|
getSoftwareSystems() {
|
|
421
503
|
return Array.from(this.softwareSystems.values());
|
|
422
504
|
}
|
|
423
505
|
getPeople() {
|
|
424
506
|
return Array.from(this.people.values());
|
|
425
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
|
+
}
|
|
426
520
|
};
|
|
427
521
|
var Model = class {
|
|
428
522
|
constructor(name) {
|
|
@@ -447,8 +541,7 @@ var Model = class {
|
|
|
447
541
|
this.softwareSystems.set(name, system);
|
|
448
542
|
return system;
|
|
449
543
|
}
|
|
450
|
-
|
|
451
|
-
addGroup(groupName) {
|
|
544
|
+
group(groupName) {
|
|
452
545
|
let group = this.groups.get(groupName);
|
|
453
546
|
if (!group) {
|
|
454
547
|
group = new ModelGroup(groupName, this);
|
|
@@ -472,6 +565,7 @@ var Model = class {
|
|
|
472
565
|
this.people.set(name, person);
|
|
473
566
|
return person;
|
|
474
567
|
}
|
|
568
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
475
569
|
validate() {
|
|
476
570
|
}
|
|
477
571
|
getPeople() {
|
|
@@ -481,11 +575,11 @@ var Model = class {
|
|
|
481
575
|
return Array.from(this.softwareSystems.values());
|
|
482
576
|
}
|
|
483
577
|
getPeopleNotInGroups() {
|
|
484
|
-
const peopleInGroups = Array.from(this.groups.values()).flatMap((group) => group.
|
|
578
|
+
const peopleInGroups = Array.from(this.groups.values()).flatMap((group) => group.getAllPeople());
|
|
485
579
|
return Array.from(this.people.values()).filter((person) => !peopleInGroups.includes(person));
|
|
486
580
|
}
|
|
487
581
|
getSoftwareSystemsNotInGroups() {
|
|
488
|
-
const systemsInGroups = Array.from(this.groups.values()).flatMap((group) => group.
|
|
582
|
+
const systemsInGroups = Array.from(this.groups.values()).flatMap((group) => group.getAllSoftwareSystems());
|
|
489
583
|
return Array.from(this.softwareSystems.values()).filter((system) => !systemsInGroups.includes(system));
|
|
490
584
|
}
|
|
491
585
|
getGroups() {
|
|
@@ -505,6 +599,9 @@ var View = class {
|
|
|
505
599
|
description;
|
|
506
600
|
title;
|
|
507
601
|
_scopes = [];
|
|
602
|
+
_autoLayout;
|
|
603
|
+
_isDefault = false;
|
|
604
|
+
_properties = /* @__PURE__ */ new Map();
|
|
508
605
|
includeAll() {
|
|
509
606
|
this._scopes.push("include *");
|
|
510
607
|
}
|
|
@@ -523,15 +620,37 @@ var View = class {
|
|
|
523
620
|
excludeExpression(expression) {
|
|
524
621
|
this._scopes.push(`exclude ${expression}`);
|
|
525
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
|
+
}
|
|
526
632
|
get scopes() {
|
|
527
633
|
return this._scopes;
|
|
528
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
|
+
}
|
|
529
644
|
};
|
|
530
645
|
var Views = class {
|
|
531
646
|
_systemLandscapeViews = /* @__PURE__ */ new Map();
|
|
532
647
|
_systemContextViews = /* @__PURE__ */ new Map();
|
|
533
648
|
_containerViews = /* @__PURE__ */ new Map();
|
|
534
649
|
_componentViews = /* @__PURE__ */ new Map();
|
|
650
|
+
_elementStyles = [];
|
|
651
|
+
_relationshipStyles = [];
|
|
652
|
+
_themes = [];
|
|
653
|
+
_properties = /* @__PURE__ */ new Map();
|
|
535
654
|
addSystemLandscapeView(key, definition) {
|
|
536
655
|
const view = new View(key, { subject: void 0, description: definition.description, title: definition.title });
|
|
537
656
|
this._systemLandscapeViews.set(key, view);
|
|
@@ -552,6 +671,18 @@ var Views = class {
|
|
|
552
671
|
this._componentViews.set(key, view);
|
|
553
672
|
return view;
|
|
554
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
|
+
}
|
|
555
686
|
get systemLandscapeViews() {
|
|
556
687
|
return Array.from(this._systemLandscapeViews.values());
|
|
557
688
|
}
|
|
@@ -564,6 +695,18 @@ var Views = class {
|
|
|
564
695
|
get componentViews() {
|
|
565
696
|
return Array.from(this._componentViews.values());
|
|
566
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
|
+
}
|
|
567
710
|
};
|
|
568
711
|
|
|
569
712
|
// libs/c4-model/src/structurizrDslWriter.ts
|
|
@@ -698,11 +841,17 @@ var StructurizrDSLWriter = class {
|
|
|
698
841
|
}
|
|
699
842
|
writeContainerGroup(group, level) {
|
|
700
843
|
let containerGroupDsl = "";
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
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);
|
|
704
854
|
});
|
|
705
|
-
containerGroupDsl += this.writeLine(`}`, level);
|
|
706
855
|
return containerGroupDsl;
|
|
707
856
|
}
|
|
708
857
|
writeContainer(container, level) {
|
|
@@ -722,11 +871,17 @@ var StructurizrDSLWriter = class {
|
|
|
722
871
|
}
|
|
723
872
|
writeSoftwareSystemGroup(group, level) {
|
|
724
873
|
let softwareSystemGroupDsl = "";
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
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);
|
|
728
884
|
});
|
|
729
|
-
softwareSystemGroupDsl += this.writeLine(`}`, level);
|
|
730
885
|
return softwareSystemGroupDsl;
|
|
731
886
|
}
|
|
732
887
|
writeSoftwareSystem(softwareSystem, level) {
|
|
@@ -778,21 +933,51 @@ var StructurizrDSLWriter = class {
|
|
|
778
933
|
});
|
|
779
934
|
return relationshipsDsl;
|
|
780
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
|
+
}
|
|
781
955
|
writeModelGroup(group, level) {
|
|
782
956
|
let modelGroupDsl = "";
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
modelGroupDsl += this.
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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);
|
|
789
970
|
});
|
|
790
|
-
modelGroupDsl += this.writeLine(`}`, level);
|
|
791
971
|
return modelGroupDsl;
|
|
792
972
|
}
|
|
793
973
|
writeModel(model, level) {
|
|
794
974
|
let modelDsl = "";
|
|
795
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
|
+
}
|
|
796
981
|
modelDsl += this.writeArchetypes(level + 1);
|
|
797
982
|
modelDsl += this.writeLine("// Elements", level + 1);
|
|
798
983
|
model.getPeopleNotInGroups().forEach((person) => {
|
|
@@ -815,12 +1000,66 @@ var StructurizrDSLWriter = class {
|
|
|
815
1000
|
if (view.title) {
|
|
816
1001
|
viewDsl += this.writeLine(`title "${view.title}"`, level + 1);
|
|
817
1002
|
}
|
|
1003
|
+
if (view.isDefault) {
|
|
1004
|
+
viewDsl += this.writeLine("default", level + 1);
|
|
1005
|
+
}
|
|
818
1006
|
view.scopes.forEach((scope) => {
|
|
819
1007
|
viewDsl += this.writeLine(`${scope}`, level + 1);
|
|
820
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
|
+
}
|
|
821
1024
|
viewDsl += this.writeLine(`}`, level);
|
|
822
1025
|
return viewDsl;
|
|
823
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
|
+
}
|
|
824
1063
|
writeViews(views, level) {
|
|
825
1064
|
let viewDsl = "";
|
|
826
1065
|
viewDsl += this.writeLine(`views {`, level);
|
|
@@ -840,6 +1079,19 @@ var StructurizrDSLWriter = class {
|
|
|
840
1079
|
views.componentViews.forEach((view) => {
|
|
841
1080
|
viewDsl += this.writeView(view, "component", level + 1);
|
|
842
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
|
+
}
|
|
843
1095
|
viewDsl += this.writeLine(`}`, level);
|
|
844
1096
|
return viewDsl;
|
|
845
1097
|
}
|
|
@@ -865,8 +1117,8 @@ var import_path = require("path");
|
|
|
865
1117
|
var import_url = require("url");
|
|
866
1118
|
var import_meta = {};
|
|
867
1119
|
var _dirname = typeof __dirname !== "undefined" ? __dirname : (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
|
|
868
|
-
async function
|
|
869
|
-
const { modelName = "model", modules: explicitModules, archetypes = {} } = options;
|
|
1120
|
+
async function buildModel(options = {}) {
|
|
1121
|
+
const { modelName = "model", modules: explicitModules, archetypes = {}, addViews } = options;
|
|
870
1122
|
const model = new Model(modelName);
|
|
871
1123
|
let c4Modules;
|
|
872
1124
|
if (explicitModules) {
|
|
@@ -890,14 +1142,16 @@ async function buildModelWithCatalog(options = {}) {
|
|
|
890
1142
|
rootCatalog[instance.key] = local;
|
|
891
1143
|
registrations.push({ instance, key: instance.key, local });
|
|
892
1144
|
}
|
|
1145
|
+
const dependenciesFor = (key) => Object.fromEntries(Object.entries(rootCatalog).filter(([k]) => k !== key));
|
|
893
1146
|
for (const { instance, key, local } of registrations) {
|
|
894
|
-
|
|
895
|
-
instance.buildRelationships(local, dependencies, archetypes);
|
|
1147
|
+
instance.addRelationships(local, dependenciesFor(key), archetypes);
|
|
896
1148
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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 };
|
|
901
1155
|
}
|
|
902
1156
|
|
|
903
1157
|
// libs/c4-model/src/generateDiagrams.ts
|
|
@@ -906,9 +1160,8 @@ var os = __toESM(require("os"), 1);
|
|
|
906
1160
|
var path = __toESM(require("path"), 1);
|
|
907
1161
|
var import_testcontainers = require("testcontainers");
|
|
908
1162
|
async function generateDiagrams(options) {
|
|
909
|
-
const {
|
|
910
|
-
const { model,
|
|
911
|
-
const views = viewsFactory(catalog);
|
|
1163
|
+
const { outputDir, ...buildOptions } = options;
|
|
1164
|
+
const { model, views } = await buildModel(buildOptions);
|
|
912
1165
|
const dsl = new StructurizrDSLWriter(model, views).write();
|
|
913
1166
|
const tmpDir = await fs.promises.mkdtemp(path.join(fs.realpathSync(os.tmpdir()), "c4-diagrams-"));
|
|
914
1167
|
await fs.promises.writeFile(path.join(tmpDir, "workspace.dsl"), dsl, "utf8");
|
|
@@ -929,6 +1182,60 @@ async function generateDiagrams(options) {
|
|
|
929
1182
|
}
|
|
930
1183
|
return generatedFiles;
|
|
931
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
|
+
}
|
|
932
1239
|
// Annotate the CommonJS export names for ESM import in node:
|
|
933
1240
|
0 && (module.exports = {
|
|
934
1241
|
Component,
|
|
@@ -945,7 +1252,9 @@ async function generateDiagrams(options) {
|
|
|
945
1252
|
View,
|
|
946
1253
|
Views,
|
|
947
1254
|
buildModel,
|
|
948
|
-
|
|
1255
|
+
exportWorkspaceJson,
|
|
1256
|
+
exportWorkspaceJsonFromDsl,
|
|
949
1257
|
generateDiagrams,
|
|
950
|
-
mergeArchetypeWithOverride
|
|
1258
|
+
mergeArchetypeWithOverride,
|
|
1259
|
+
validateModel
|
|
951
1260
|
});
|