@istar-ts/core 0.10.1 → 0.12.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 +62 -0
- package/dist/index.cjs +431 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +220 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.js +415 -60
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -268,7 +268,9 @@ function extendMetamodel(base, extension) {
|
|
|
268
268
|
} } : {},
|
|
269
269
|
...parent ? { behavesLike: parent.kind } : {},
|
|
270
270
|
pistarType: type,
|
|
271
|
-
extension: extension.name
|
|
271
|
+
extension: extension.name,
|
|
272
|
+
...declaration.shape ? { shape: declaration.shape } : {},
|
|
273
|
+
...declaration.textBox ? { textBox: declaration.textBox } : {}
|
|
272
274
|
};
|
|
273
275
|
elements.set(kind, definition);
|
|
274
276
|
elementsByType.set(type, kind);
|
|
@@ -301,7 +303,8 @@ function extendMetamodel(base, extension) {
|
|
|
301
303
|
...declaration.rules ? { rules: declaration.rules } : {},
|
|
302
304
|
...declaration.check ? { check: declaration.check } : {},
|
|
303
305
|
pistarType: type,
|
|
304
|
-
extension: extension.name
|
|
306
|
+
extension: extension.name,
|
|
307
|
+
...declaration.line ? { line: declaration.line } : {}
|
|
305
308
|
};
|
|
306
309
|
links.set(kind, definition);
|
|
307
310
|
linksByType.set(type, kind);
|
|
@@ -392,10 +395,27 @@ function withMetamodel(model, metamodel) {
|
|
|
392
395
|
else metamodels.set(model, metamodel);
|
|
393
396
|
return model;
|
|
394
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* For models whose file declares part of their metamodel (see `withFileMetamodel`): the
|
|
400
|
+
* metamodel the host supplied, without the file's kinds.
|
|
401
|
+
*/
|
|
402
|
+
const hostMetamodels = /* @__PURE__ */ new WeakMap();
|
|
403
|
+
/** @internal Records the host part of a model's metamodel (used by serialization). */
|
|
404
|
+
function setHostMetamodel(model, metamodel) {
|
|
405
|
+
if (metamodel) hostMetamodels.set(model, metamodel);
|
|
406
|
+
else hostMetamodels.delete(model);
|
|
407
|
+
}
|
|
408
|
+
/** @internal The host part of a model's metamodel, if the file declares the rest. */
|
|
409
|
+
function hostMetamodelOf(model) {
|
|
410
|
+
return hostMetamodels.get(model);
|
|
411
|
+
}
|
|
395
412
|
/** Gives `to` the metamodel of `from` (used for every model an operation derives). */
|
|
396
413
|
function inheritMetamodel(from, to) {
|
|
414
|
+
if (from === to) return to;
|
|
397
415
|
const metamodel = metamodels.get(from);
|
|
398
|
-
if (metamodel
|
|
416
|
+
if (metamodel) metamodels.set(to, metamodel);
|
|
417
|
+
const host = hostMetamodels.get(from);
|
|
418
|
+
if (host) hostMetamodels.set(to, host);
|
|
399
419
|
return to;
|
|
400
420
|
}
|
|
401
421
|
function createEmptyModel(diagram = DEFAULT_DIAGRAM, options = {}) {
|
|
@@ -467,7 +487,7 @@ function dependencyLinksOf(model, dependumId) {
|
|
|
467
487
|
//#endregion
|
|
468
488
|
//#region src/constraints.ts
|
|
469
489
|
const OK = { ok: true };
|
|
470
|
-
function fail(code, reason) {
|
|
490
|
+
function fail$1(code, reason) {
|
|
471
491
|
return {
|
|
472
492
|
ok: false,
|
|
473
493
|
code,
|
|
@@ -488,10 +508,10 @@ function canLink(model, source, target, kind, options = {}) {
|
|
|
488
508
|
const metamodel = options.metamodel ?? metamodelOf(model);
|
|
489
509
|
const s = resolve(any, source);
|
|
490
510
|
const t = resolve(any, target);
|
|
491
|
-
if (!s) return fail("unknown-element", `unknown source element "${refId(source)}"`);
|
|
492
|
-
if (!t) return fail("unknown-element", `unknown target element "${refId(target)}"`);
|
|
511
|
+
if (!s) return fail$1("unknown-element", `unknown source element "${refId(source)}"`);
|
|
512
|
+
if (!t) return fail$1("unknown-element", `unknown target element "${refId(target)}"`);
|
|
493
513
|
const definition = metamodel.links.get(kind);
|
|
494
|
-
if (!definition) return fail("unknown-link-kind", `unknown link kind "${String(kind)}"`);
|
|
514
|
+
if (!definition) return fail$1("unknown-link-kind", `unknown link kind "${String(kind)}"`);
|
|
495
515
|
return checkWith(new Graph(any, metamodel), definition, s, t);
|
|
496
516
|
}
|
|
497
517
|
/** Runs the rule a link kind resolves to, then every extra predicate along its chain. */
|
|
@@ -503,7 +523,7 @@ function checkWith(graph, definition, source, target) {
|
|
|
503
523
|
let result;
|
|
504
524
|
if (root.rules) result = declarativeCheck(graph, definition, root.rules, root.kind, source, target);
|
|
505
525
|
else if (builtIn) result = builtIn(graph, source, target);
|
|
506
|
-
else result = fail("unknown-link-kind", `link kind "${definition.kind}" has no rules`);
|
|
526
|
+
else result = fail$1("unknown-link-kind", `link kind "${definition.kind}" has no rules`);
|
|
507
527
|
if (!result.ok) return result;
|
|
508
528
|
const context = graph.context(definition.kind, source, target);
|
|
509
529
|
for (const step of chain.toReversed()) {
|
|
@@ -587,18 +607,18 @@ const is = (graph, element, ...shortNames) => {
|
|
|
587
607
|
};
|
|
588
608
|
const isDependum = (element) => element.isDependum === true;
|
|
589
609
|
const isALink = (graph, source, target) => {
|
|
590
|
-
if (!is(graph, source, "Actor", "Role")) return fail("invalid-source", "the source of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).");
|
|
591
|
-
if (source.kind !== target.kind) return fail("actor-types-differ", "the source and target of Is-A links must be of the same type - Actor and Actor, or Role and Role (iStar 2.0 Guide, Page 6).");
|
|
592
|
-
if (!is(graph, target, "Actor", "Role")) return fail("invalid-target", "the target of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).");
|
|
593
|
-
if (source.id === target.id) return fail("self-link", "you cannot make Is-A links from an actor onto itself.");
|
|
594
|
-
if (graph.isThereLinkBetween(source, target)) return fail("duplicate-link", "there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).");
|
|
610
|
+
if (!is(graph, source, "Actor", "Role")) return fail$1("invalid-source", "the source of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).");
|
|
611
|
+
if (source.kind !== target.kind) return fail$1("actor-types-differ", "the source and target of Is-A links must be of the same type - Actor and Actor, or Role and Role (iStar 2.0 Guide, Page 6).");
|
|
612
|
+
if (!is(graph, target, "Actor", "Role")) return fail$1("invalid-target", "the target of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).");
|
|
613
|
+
if (source.id === target.id) return fail$1("self-link", "you cannot make Is-A links from an actor onto itself.");
|
|
614
|
+
if (graph.isThereLinkBetween(source, target)) return fail$1("duplicate-link", "there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).");
|
|
595
615
|
return OK;
|
|
596
616
|
};
|
|
597
617
|
const participatesInLink = (graph, source, target) => {
|
|
598
|
-
if (!graph.isActor(source)) return fail("invalid-source", "the source of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)");
|
|
599
|
-
if (!graph.isActor(target)) return fail("invalid-target", "the target of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)");
|
|
600
|
-
if (source.id === target.id) return fail("self-link", "you cannot make a Participates-In link from an actor onto itself.");
|
|
601
|
-
if (graph.isThereLinkBetween(source, target)) return fail("duplicate-link", "there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).");
|
|
618
|
+
if (!graph.isActor(source)) return fail$1("invalid-source", "the source of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)");
|
|
619
|
+
if (!graph.isActor(target)) return fail$1("invalid-target", "the target of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)");
|
|
620
|
+
if (source.id === target.id) return fail$1("self-link", "you cannot make a Participates-In link from an actor onto itself.");
|
|
621
|
+
if (graph.isThereLinkBetween(source, target)) return fail$1("duplicate-link", "there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).");
|
|
602
622
|
return OK;
|
|
603
623
|
};
|
|
604
624
|
/** The actor an element belongs to: itself for actors, its parent for inner elements. */
|
|
@@ -606,56 +626,56 @@ function owningActorId(graph, element) {
|
|
|
606
626
|
return graph.isActor(element) ? element.id : element.parent;
|
|
607
627
|
}
|
|
608
628
|
const dependencyLink = (graph, source, target) => {
|
|
609
|
-
if (source.id === target.id) return fail("self-link", "a Dependency link cannot link an element onto itself");
|
|
610
|
-
if (isDependum(source)) return fail("dependum-endpoint", "a Dependency link cannot start from a dependum");
|
|
611
|
-
if (isDependum(target)) return fail("dependum-endpoint", "a Dependency link cannot end in a dependum");
|
|
612
|
-
if (owningActorId(graph, source) === owningActorId(graph, target)) return fail("same-actor", "a Dependency link must involve two different actors (iStar 2.0 Guide, Page 14)");
|
|
613
|
-
if (graph.isTargetOfType(source, "istar.OrRefinementLink") || graph.isTargetOfType(source, "istar.AndRefinementLink")) return fail("refined-depender", "a refined element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). Instead, you can try to add the Dependency originating from a child.");
|
|
614
|
-
if (graph.isTargetOfType(source, "istar.ContributionLink")) return fail("contributed-depender", "a contributed element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). Instead, you can try to add the Dependency originating from a child.");
|
|
629
|
+
if (source.id === target.id) return fail$1("self-link", "a Dependency link cannot link an element onto itself");
|
|
630
|
+
if (isDependum(source)) return fail$1("dependum-endpoint", "a Dependency link cannot start from a dependum");
|
|
631
|
+
if (isDependum(target)) return fail$1("dependum-endpoint", "a Dependency link cannot end in a dependum");
|
|
632
|
+
if (owningActorId(graph, source) === owningActorId(graph, target)) return fail$1("same-actor", "a Dependency link must involve two different actors (iStar 2.0 Guide, Page 14)");
|
|
633
|
+
if (graph.isTargetOfType(source, "istar.OrRefinementLink") || graph.isTargetOfType(source, "istar.AndRefinementLink")) return fail$1("refined-depender", "a refined element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). Instead, you can try to add the Dependency originating from a child.");
|
|
634
|
+
if (graph.isTargetOfType(source, "istar.ContributionLink")) return fail$1("contributed-depender", "a contributed element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). Instead, you can try to add the Dependency originating from a child.");
|
|
615
635
|
return OK;
|
|
616
636
|
};
|
|
617
637
|
function refinementLink(label) {
|
|
618
638
|
const other = label === "AND" ? "istar.OrRefinementLink" : "istar.AndRefinementLink";
|
|
619
639
|
return (graph, source, target) => {
|
|
620
|
-
if (!is(graph, source, "Task", "Goal")) return fail("invalid-source", `the source of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`);
|
|
621
|
-
if (!is(graph, target, "Task", "Goal")) return fail("invalid-target", `the target of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`);
|
|
622
|
-
if (source.id === target.id) return fail("self-link", `you cannot make an ${label}-refinement link from an element onto itself`);
|
|
623
|
-
if (isDependum(source) || isDependum(target)) return fail("dependum-endpoint", `you cannot make an ${label}-refinement link with a dependum (iStar 2.0 Guide, Page 14)`);
|
|
624
|
-
if (source.parent !== target.parent) return fail("different-actors", `the source and target of an ${label}-refinement link must pertain to the same actor (iStar 2.0 Guide, Page 14)`);
|
|
625
|
-
if (graph.isThereLinkBetween(source, target)) return fail("duplicate-link", "there can only be one refinement link between the same two elements");
|
|
626
|
-
if (graph.isSourceOfType(target, "istar.DependencyLink")) return fail("depender-target", "you cannot refine a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). Instead, you can try to move the dependency to the sub-element.");
|
|
627
|
-
if (graph.isTargetOfType(target, other)) return fail("mixed-refinement", label === "AND" ? "you cannot mix AND-refinements with OR-refinements targeting the same element (iStar 2.0 Guide, Page 10)." : "you cannot mix OR-refinements with AND-refinements targeting the same element (iStar 2.0 Guide, Page 10).");
|
|
640
|
+
if (!is(graph, source, "Task", "Goal")) return fail$1("invalid-source", `the source of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`);
|
|
641
|
+
if (!is(graph, target, "Task", "Goal")) return fail$1("invalid-target", `the target of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`);
|
|
642
|
+
if (source.id === target.id) return fail$1("self-link", `you cannot make an ${label}-refinement link from an element onto itself`);
|
|
643
|
+
if (isDependum(source) || isDependum(target)) return fail$1("dependum-endpoint", `you cannot make an ${label}-refinement link with a dependum (iStar 2.0 Guide, Page 14)`);
|
|
644
|
+
if (source.parent !== target.parent) return fail$1("different-actors", `the source and target of an ${label}-refinement link must pertain to the same actor (iStar 2.0 Guide, Page 14)`);
|
|
645
|
+
if (graph.isThereLinkBetween(source, target)) return fail$1("duplicate-link", "there can only be one refinement link between the same two elements");
|
|
646
|
+
if (graph.isSourceOfType(target, "istar.DependencyLink")) return fail$1("depender-target", "you cannot refine a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). Instead, you can try to move the dependency to the sub-element.");
|
|
647
|
+
if (graph.isTargetOfType(target, other)) return fail$1("mixed-refinement", label === "AND" ? "you cannot mix AND-refinements with OR-refinements targeting the same element (iStar 2.0 Guide, Page 10)." : "you cannot mix OR-refinements with AND-refinements targeting the same element (iStar 2.0 Guide, Page 10).");
|
|
628
648
|
return OK;
|
|
629
649
|
};
|
|
630
650
|
}
|
|
631
651
|
const neededByLink = (graph, source, target) => {
|
|
632
|
-
if (!is(graph, source, "Resource")) return fail("invalid-source", "the source of a Needed-By link must be a Resource (iStar 2.0 Guide, Table 1)");
|
|
633
|
-
if (!is(graph, target, "Task")) return fail("invalid-target", "the target of a Needed-By link must be a Task (iStar 2.0 Guide, Table 1)");
|
|
634
|
-
if (source.id === target.id) return fail("self-link", "you cannot make a Needed-By link from an element onto itself");
|
|
635
|
-
if (isDependum(source) || isDependum(target)) return fail("dependum-endpoint", "you cannot make a Needed-By link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
636
|
-
if (source.parent !== target.parent) return fail("different-actors", "the source and target of a Needed-By link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
637
|
-
if (graph.isThereLinkBetween(source, target)) return fail("duplicate-link", "there can only be one Needed-By link between the same two elements");
|
|
652
|
+
if (!is(graph, source, "Resource")) return fail$1("invalid-source", "the source of a Needed-By link must be a Resource (iStar 2.0 Guide, Table 1)");
|
|
653
|
+
if (!is(graph, target, "Task")) return fail$1("invalid-target", "the target of a Needed-By link must be a Task (iStar 2.0 Guide, Table 1)");
|
|
654
|
+
if (source.id === target.id) return fail$1("self-link", "you cannot make a Needed-By link from an element onto itself");
|
|
655
|
+
if (isDependum(source) || isDependum(target)) return fail$1("dependum-endpoint", "you cannot make a Needed-By link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
656
|
+
if (source.parent !== target.parent) return fail$1("different-actors", "the source and target of a Needed-By link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
657
|
+
if (graph.isThereLinkBetween(source, target)) return fail$1("duplicate-link", "there can only be one Needed-By link between the same two elements");
|
|
638
658
|
return OK;
|
|
639
659
|
};
|
|
640
660
|
const contributionLink = (graph, source, target) => {
|
|
641
|
-
if (!is(graph, source, "Goal", "Quality", "Task", "Resource")) return fail("invalid-source", "the source of a Contribution link must be a Goal, a Quality, a Task or a Resource (iStar 2.0 Guide, Table 1)");
|
|
642
|
-
if (!is(graph, target, "Quality")) return fail("invalid-target", "the target of a Contribution link must be a Quality (iStar 2.0 Guide, Table 1)");
|
|
643
|
-
if (source.id === target.id) return fail("self-link", "you cannot make a Contribution link from an element onto itself (iStar 2.0 Guide, Page 15)");
|
|
644
|
-
if (isDependum(source) || isDependum(target)) return fail("dependum-endpoint", "you cannot make a Contribution link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
645
|
-
if (source.parent !== target.parent) return fail("different-actors", "the source and target of a Contribution link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
646
|
-
if (graph.isThereLinkBetween(source, target, "istar.ContributionLink")) return fail("duplicate-link", "there can only be one Contribution link between the same two elements");
|
|
647
|
-
if (graph.isThereLinkBetween(source, target, "istar.QualificationLink")) return fail("contribution-and-qualification", "you cannot have Contribution and Qualification links between the same two elements (iStar 2.0 Guide, Page 15)");
|
|
648
|
-
if (graph.isSourceOfType(target, "istar.DependencyLink")) return fail("depender-target", "you cannot contribute to a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). Instead, you can try to move the dependency to the sub-quality.");
|
|
661
|
+
if (!is(graph, source, "Goal", "Quality", "Task", "Resource")) return fail$1("invalid-source", "the source of a Contribution link must be a Goal, a Quality, a Task or a Resource (iStar 2.0 Guide, Table 1)");
|
|
662
|
+
if (!is(graph, target, "Quality")) return fail$1("invalid-target", "the target of a Contribution link must be a Quality (iStar 2.0 Guide, Table 1)");
|
|
663
|
+
if (source.id === target.id) return fail$1("self-link", "you cannot make a Contribution link from an element onto itself (iStar 2.0 Guide, Page 15)");
|
|
664
|
+
if (isDependum(source) || isDependum(target)) return fail$1("dependum-endpoint", "you cannot make a Contribution link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
665
|
+
if (source.parent !== target.parent) return fail$1("different-actors", "the source and target of a Contribution link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
666
|
+
if (graph.isThereLinkBetween(source, target, "istar.ContributionLink")) return fail$1("duplicate-link", "there can only be one Contribution link between the same two elements");
|
|
667
|
+
if (graph.isThereLinkBetween(source, target, "istar.QualificationLink")) return fail$1("contribution-and-qualification", "you cannot have Contribution and Qualification links between the same two elements (iStar 2.0 Guide, Page 15)");
|
|
668
|
+
if (graph.isSourceOfType(target, "istar.DependencyLink")) return fail$1("depender-target", "you cannot contribute to a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). Instead, you can try to move the dependency to the sub-quality.");
|
|
649
669
|
return OK;
|
|
650
670
|
};
|
|
651
671
|
const qualificationLink = (graph, source, target) => {
|
|
652
|
-
if (!is(graph, source, "Quality")) return fail("invalid-source", "the source of a Qualification link must be a Quality (iStar 2.0 Guide, Table 1)");
|
|
653
|
-
if (!is(graph, target, "Goal", "Task", "Resource")) return fail("invalid-target", "the target of a Qualification link must be a Goal, a Task or a Resource (iStar 2.0 Guide, Table 1)");
|
|
654
|
-
if (source.id === target.id) return fail("self-link", "you cannot make a Qualification link from an element onto itself");
|
|
655
|
-
if (isDependum(source) || isDependum(target)) return fail("dependum-endpoint", "you cannot make a Qualification link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
656
|
-
if (source.parent !== target.parent) return fail("different-actors", "the source and target of a Qualification link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
657
|
-
if (graph.isThereLinkBetween(source, target, "istar.QualificationLink")) return fail("duplicate-link", "there can only be one Qualification link between the same two elements");
|
|
658
|
-
if (graph.isThereLinkBetween(source, target, "istar.ContributionLink")) return fail("contribution-and-qualification", "you cannot have Qualification and Contribution links between the same two elements (iStar 2.0 Guide, Page 15)");
|
|
672
|
+
if (!is(graph, source, "Quality")) return fail$1("invalid-source", "the source of a Qualification link must be a Quality (iStar 2.0 Guide, Table 1)");
|
|
673
|
+
if (!is(graph, target, "Goal", "Task", "Resource")) return fail$1("invalid-target", "the target of a Qualification link must be a Goal, a Task or a Resource (iStar 2.0 Guide, Table 1)");
|
|
674
|
+
if (source.id === target.id) return fail$1("self-link", "you cannot make a Qualification link from an element onto itself");
|
|
675
|
+
if (isDependum(source) || isDependum(target)) return fail$1("dependum-endpoint", "you cannot make a Qualification link with a dependum (iStar 2.0 Guide, Page 14)");
|
|
676
|
+
if (source.parent !== target.parent) return fail$1("different-actors", "the source and target of a Qualification link must pertain to the same actor (iStar 2.0 Guide, Page 14)");
|
|
677
|
+
if (graph.isThereLinkBetween(source, target, "istar.QualificationLink")) return fail$1("duplicate-link", "there can only be one Qualification link between the same two elements");
|
|
678
|
+
if (graph.isThereLinkBetween(source, target, "istar.ContributionLink")) return fail$1("contribution-and-qualification", "you cannot have Qualification and Contribution links between the same two elements (iStar 2.0 Guide, Page 15)");
|
|
659
679
|
return OK;
|
|
660
680
|
};
|
|
661
681
|
/** The words used for a list of kind selectors in messages: "a Goal or a Task". */
|
|
@@ -683,15 +703,15 @@ function matchesSelector(graph, element, selector) {
|
|
|
683
703
|
function declarativeCheck(graph, definition, rules, rulesKind, source, target) {
|
|
684
704
|
const name = definition.label;
|
|
685
705
|
const article = /^[aeiou]/i.test(name) ? "an" : "a";
|
|
686
|
-
if (!rules.sources.some((selector) => matchesSelector(graph, source, selector))) return fail("invalid-source", `the source of ${article} ${name} link must be ${describe(graph, rules.sources)}`);
|
|
687
|
-
if (!rules.targets.some((selector) => matchesSelector(graph, target, selector))) return fail("invalid-target", `the target of ${article} ${name} link must be ${describe(graph, rules.targets)}`);
|
|
688
|
-
if (!rules.allowSelf && source.id === target.id) return fail("self-link", `you cannot make ${article} ${name} link from an element onto itself`);
|
|
706
|
+
if (!rules.sources.some((selector) => matchesSelector(graph, source, selector))) return fail$1("invalid-source", `the source of ${article} ${name} link must be ${describe(graph, rules.sources)}`);
|
|
707
|
+
if (!rules.targets.some((selector) => matchesSelector(graph, target, selector))) return fail$1("invalid-target", `the target of ${article} ${name} link must be ${describe(graph, rules.targets)}`);
|
|
708
|
+
if (!rules.allowSelf && source.id === target.id) return fail$1("self-link", `you cannot make ${article} ${name} link from an element onto itself`);
|
|
689
709
|
if (definition.category === "node") {
|
|
690
|
-
if (!rules.allowDependum && (isDependum(source) || isDependum(target))) return fail("dependum-endpoint", `you cannot make ${article} ${name} link with a dependum`);
|
|
691
|
-
if (rules.sameActor !== false && source.parent !== target.parent) return fail("different-actors", `the source and target of ${article} ${name} link must pertain to the same actor (iStar 2.0 Guide, Page 14)`);
|
|
710
|
+
if (!rules.allowDependum && (isDependum(source) || isDependum(target))) return fail$1("dependum-endpoint", `you cannot make ${article} ${name} link with a dependum`);
|
|
711
|
+
if (rules.sameActor !== false && source.parent !== target.parent) return fail$1("different-actors", `the source and target of ${article} ${name} link must pertain to the same actor (iStar 2.0 Guide, Page 14)`);
|
|
692
712
|
}
|
|
693
713
|
const unique = rules.unique ?? "kind";
|
|
694
|
-
if (unique === "any" && graph.isThereLinkBetween(source, target) || unique === "kind" && graph.isThereLinkOfKindBetween(source, target, definition.kind) || unique === "kind" && rulesKind !== definition.kind && graph.isThereLinkOfKindBetween(source, target, rulesKind)) return fail("duplicate-link", `there can only be one ${name} link between the same two elements`);
|
|
714
|
+
if (unique === "any" && graph.isThereLinkBetween(source, target) || unique === "kind" && graph.isThereLinkOfKindBetween(source, target, definition.kind) || unique === "kind" && rulesKind !== definition.kind && graph.isThereLinkOfKindBetween(source, target, rulesKind)) return fail$1("duplicate-link", `there can only be one ${name} link between the same two elements`);
|
|
695
715
|
return OK;
|
|
696
716
|
}
|
|
697
717
|
const CHECKS = {
|
|
@@ -750,6 +770,126 @@ function validateModel(model, options) {
|
|
|
750
770
|
return issues;
|
|
751
771
|
}
|
|
752
772
|
//#endregion
|
|
773
|
+
//#region src/file-metamodel.ts
|
|
774
|
+
/** The top-level key of the block in piStar JSON. */
|
|
775
|
+
const FILE_METAMODEL_KEY = "metamodel";
|
|
776
|
+
function isObject(value) {
|
|
777
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
778
|
+
}
|
|
779
|
+
function fail(path, message) {
|
|
780
|
+
throw new MetamodelError(`${path} ${message}`);
|
|
781
|
+
}
|
|
782
|
+
function optionalString(entry, key, path) {
|
|
783
|
+
if (entry[key] !== void 0 && typeof entry[key] !== "string") fail(`${path}.${key}`, "must be a string");
|
|
784
|
+
}
|
|
785
|
+
function optionalBoolean(entry, key, path) {
|
|
786
|
+
if (entry[key] !== void 0 && typeof entry[key] !== "boolean") fail(`${path}.${key}`, "must be true or false");
|
|
787
|
+
}
|
|
788
|
+
function checkSize(value, path) {
|
|
789
|
+
if (value === void 0) return;
|
|
790
|
+
if (!isObject(value)) fail(path, "must be an object { width, height }");
|
|
791
|
+
for (const key of ["width", "height"]) {
|
|
792
|
+
const n = value[key];
|
|
793
|
+
if (typeof n !== "number" || !Number.isFinite(n) || n <= 0) fail(`${path}.${key}`, "must be a positive number");
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function checkShape(value, path) {
|
|
797
|
+
if (value === void 0) return;
|
|
798
|
+
if (!isObject(value)) fail(path, "must be an object { path, viewBox? }");
|
|
799
|
+
if (typeof value.path !== "string" || value.path.trim() === "") fail(`${path}.path`, "must be SVG path data");
|
|
800
|
+
optionalString(value, "viewBox", path);
|
|
801
|
+
}
|
|
802
|
+
function checkTextBox(value, path) {
|
|
803
|
+
if (value === void 0) return;
|
|
804
|
+
if (!isObject(value)) fail(path, "must be an object { top, right, bottom, left }");
|
|
805
|
+
for (const key of [
|
|
806
|
+
"top",
|
|
807
|
+
"right",
|
|
808
|
+
"bottom",
|
|
809
|
+
"left"
|
|
810
|
+
]) {
|
|
811
|
+
const n = value[key];
|
|
812
|
+
if (typeof n !== "number" || n < 0 || n >= 1) fail(`${path}.${key}`, "must be a fraction from 0 (inclusive) to 1 (exclusive)");
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function checkLine(value, path) {
|
|
816
|
+
if (value === void 0) return;
|
|
817
|
+
if (!isObject(value)) fail(path, "must be an object { dash?, marker?, markerFilled? }");
|
|
818
|
+
optionalString(value, "dash", path);
|
|
819
|
+
if (value.marker !== void 0 && value.marker !== false && typeof value.marker !== "string") fail(`${path}.marker`, "must be SVG path data or false");
|
|
820
|
+
optionalBoolean(value, "markerFilled", path);
|
|
821
|
+
}
|
|
822
|
+
function checkStringList(value, path) {
|
|
823
|
+
if (!Array.isArray(value) || value.length === 0 || value.some((v) => typeof v !== "string")) fail(path, "must be a non-empty list of kind names or categories");
|
|
824
|
+
}
|
|
825
|
+
function checkRules(value, path) {
|
|
826
|
+
if (!isObject(value)) fail(path, "must be an object { sources, targets, … }");
|
|
827
|
+
checkStringList(value.sources, `${path}.sources`);
|
|
828
|
+
checkStringList(value.targets, `${path}.targets`);
|
|
829
|
+
for (const key of [
|
|
830
|
+
"sameActor",
|
|
831
|
+
"allowDependum",
|
|
832
|
+
"allowSelf"
|
|
833
|
+
]) optionalBoolean(value, key, path);
|
|
834
|
+
if (value.unique !== void 0 && ![
|
|
835
|
+
"kind",
|
|
836
|
+
"any",
|
|
837
|
+
false
|
|
838
|
+
].includes(value.unique)) fail(`${path}.unique`, "must be \"kind\", \"any\" or false");
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Checks that `value` is a well-formed `"metamodel"` block and returns it typed. Throws
|
|
842
|
+
* `MetamodelError` naming the offending path (`metamodel.elements[1].kind must be a string`).
|
|
843
|
+
* Whether its kinds fit a given metamodel (namespacing, collisions, `behavesLike` targets) is
|
|
844
|
+
* checked when it is applied, by `extendMetamodel`.
|
|
845
|
+
*/
|
|
846
|
+
function validateFileMetamodel(value, path = FILE_METAMODEL_KEY) {
|
|
847
|
+
if (!isObject(value)) fail(path, "must be an object { name, elements?, links? }");
|
|
848
|
+
if (typeof value.name !== "string" || value.name === "") fail(`${path}.name`, "must be a non-empty string");
|
|
849
|
+
for (const [listKey, kind] of [["elements", "element"], ["links", "link"]]) {
|
|
850
|
+
const list = value[listKey];
|
|
851
|
+
if (list === void 0) continue;
|
|
852
|
+
if (!Array.isArray(list)) fail(`${path}.${listKey}`, "must be a list");
|
|
853
|
+
list.forEach((entry, i) => {
|
|
854
|
+
const at = `${path}.${listKey}[${i}]`;
|
|
855
|
+
if (!isObject(entry)) fail(at, `must be an object describing a ${kind} kind`);
|
|
856
|
+
if (typeof entry.kind !== "string" || entry.kind === "") fail(`${at}.kind`, "must be a string");
|
|
857
|
+
optionalString(entry, "label", at);
|
|
858
|
+
optionalString(entry, "behavesLike", at);
|
|
859
|
+
optionalString(entry, "pistarType", at);
|
|
860
|
+
if (kind === "element") {
|
|
861
|
+
if (entry.category !== void 0 && entry.category !== "node" && entry.category !== "actor") fail(`${at}.category`, "must be \"node\" or \"actor\"");
|
|
862
|
+
checkSize(entry.size, `${at}.size`);
|
|
863
|
+
if (entry.info !== void 0) {
|
|
864
|
+
if (!isObject(entry.info)) fail(`${at}.info`, "must be an object");
|
|
865
|
+
for (const key of [
|
|
866
|
+
"canBeInnerElement",
|
|
867
|
+
"canBeDependum",
|
|
868
|
+
"canBeOnPaper"
|
|
869
|
+
]) optionalBoolean(entry.info, key, `${at}.info`);
|
|
870
|
+
}
|
|
871
|
+
checkShape(entry.shape, `${at}.shape`);
|
|
872
|
+
checkTextBox(entry.textBox, `${at}.textBox`);
|
|
873
|
+
} else {
|
|
874
|
+
if (entry.category !== void 0 && ![
|
|
875
|
+
"node",
|
|
876
|
+
"actor",
|
|
877
|
+
"dependency"
|
|
878
|
+
].includes(entry.category)) fail(`${at}.category`, "must be \"node\", \"actor\" or \"dependency\"");
|
|
879
|
+
if (entry.rules !== void 0) checkRules(entry.rules, `${at}.rules`);
|
|
880
|
+
if ("check" in entry) fail(`${at}.check`, "cannot be stored in a file (it is code)");
|
|
881
|
+
if (entry.info !== void 0 && !isObject(entry.info)) fail(`${at}.info`, "must be an object");
|
|
882
|
+
checkLine(entry.line, `${at}.line`);
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
return value;
|
|
887
|
+
}
|
|
888
|
+
/** The block as an extension `extendMetamodel` applies (it ignores the extra keys). */
|
|
889
|
+
function fileMetamodelExtension(block) {
|
|
890
|
+
return block;
|
|
891
|
+
}
|
|
892
|
+
//#endregion
|
|
753
893
|
//#region src/serialization.ts
|
|
754
894
|
var PistarParseError = class extends Error {
|
|
755
895
|
name = "PistarParseError";
|
|
@@ -827,7 +967,7 @@ function asArray(value, where) {
|
|
|
827
967
|
return value;
|
|
828
968
|
}
|
|
829
969
|
function parsePistar(input, options = {}) {
|
|
830
|
-
|
|
970
|
+
let metamodel = options.metamodel ?? ISTAR_2_0;
|
|
831
971
|
const categoryOf = (kind) => metamodel.elements.get(kind)?.category;
|
|
832
972
|
let json;
|
|
833
973
|
if (typeof input === "string") try {
|
|
@@ -837,6 +977,12 @@ function parsePistar(input, options = {}) {
|
|
|
837
977
|
}
|
|
838
978
|
else json = structuredClone(input);
|
|
839
979
|
if (!isRecord(json)) throw new PistarParseError("a piStar model must be a JSON object");
|
|
980
|
+
let host;
|
|
981
|
+
if (options.fileMetamodel && json["metamodel"] !== void 0) {
|
|
982
|
+
const block = validateFileMetamodel(json[FILE_METAMODEL_KEY]);
|
|
983
|
+
host = metamodel;
|
|
984
|
+
metamodel = extendMetamodel(metamodel, fileMetamodelExtension(block));
|
|
985
|
+
}
|
|
840
986
|
const display = isRecord(json.display) ? json.display : {};
|
|
841
987
|
const usedDisplay = /* @__PURE__ */ new Set();
|
|
842
988
|
const elements = /* @__PURE__ */ new Map();
|
|
@@ -937,6 +1083,7 @@ function parsePistar(input, options = {}) {
|
|
|
937
1083
|
keys: Object.keys(json),
|
|
938
1084
|
display: Object.keys(display)
|
|
939
1085
|
});
|
|
1086
|
+
setHostMetamodel(model, host);
|
|
940
1087
|
return withMetamodel(model, metamodel);
|
|
941
1088
|
}
|
|
942
1089
|
function optional(key, value) {
|
|
@@ -1063,6 +1210,44 @@ function toPistarObject(input, options = {}) {
|
|
|
1063
1210
|
function toPistar(model, options) {
|
|
1064
1211
|
return JSON.stringify(toPistarObject(model, options), null, 2);
|
|
1065
1212
|
}
|
|
1213
|
+
/**
|
|
1214
|
+
* The constructs the model's file declares in its `"metamodel"` block, when they were applied
|
|
1215
|
+
* (read with `fileMetamodel: true`, or set with `withFileMetamodel`); `undefined` otherwise.
|
|
1216
|
+
* Kinds the host supplied are never part of it.
|
|
1217
|
+
*/
|
|
1218
|
+
function fileMetamodelOf(model) {
|
|
1219
|
+
if (!hostMetamodelOf(model)) return void 0;
|
|
1220
|
+
return model.extra?.[FILE_METAMODEL_KEY];
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* A copy of `model` whose file declares `block` (`null` removes the block): its metamodel is the
|
|
1224
|
+
* host's extended by `block`, and `toPistar` writes the block. This is how a tool's "Add new"
|
|
1225
|
+
* construct joins a model. Throws `MetamodelError` if the block is malformed, collides with the
|
|
1226
|
+
* host's kinds, or leaves out a kind the model still uses.
|
|
1227
|
+
*/
|
|
1228
|
+
function withFileMetamodel(model, block) {
|
|
1229
|
+
const any = model;
|
|
1230
|
+
const host = hostMetamodelOf(any) ?? metamodelOf(any);
|
|
1231
|
+
let next = host;
|
|
1232
|
+
if (block) {
|
|
1233
|
+
validateFileMetamodel(block);
|
|
1234
|
+
next = extendMetamodel(host, fileMetamodelExtension(block));
|
|
1235
|
+
}
|
|
1236
|
+
for (const element of any.elements.values()) if (!next.elements.has(element.kind)) throw new MetamodelError(`element "${element.id}" uses kind "${element.kind}", which the new metamodel lacks`);
|
|
1237
|
+
for (const link of any.links.values()) if (!next.links.has(link.kind)) throw new MetamodelError(`link "${link.id}" uses kind "${link.kind}", which the new metamodel lacks`);
|
|
1238
|
+
const { [FILE_METAMODEL_KEY]: _previous, ...others } = any.extra ?? {};
|
|
1239
|
+
const extra = block ? {
|
|
1240
|
+
...any.extra,
|
|
1241
|
+
[FILE_METAMODEL_KEY]: structuredClone(block)
|
|
1242
|
+
} : others;
|
|
1243
|
+
const { extra: _extra, ...rest } = any;
|
|
1244
|
+
const result = inheritSourceLayout(any, {
|
|
1245
|
+
...rest,
|
|
1246
|
+
...Object.keys(extra).length > 0 ? { extra } : {}
|
|
1247
|
+
});
|
|
1248
|
+
setHostMetamodel(result, block ? host : void 0);
|
|
1249
|
+
return withMetamodel(result, next);
|
|
1250
|
+
}
|
|
1066
1251
|
//#endregion
|
|
1067
1252
|
//#region src/operations.ts
|
|
1068
1253
|
var ModelOperationError = class extends Error {
|
|
@@ -1842,13 +2027,185 @@ function validateModelProperties(model, schemas) {
|
|
|
1842
2027
|
return issues;
|
|
1843
2028
|
}
|
|
1844
2029
|
//#endregion
|
|
2030
|
+
//#region src/diagnostics.ts
|
|
2031
|
+
/** Most severe first. */
|
|
2032
|
+
const DIAGNOSTIC_SEVERITIES = [
|
|
2033
|
+
"error",
|
|
2034
|
+
"warning",
|
|
2035
|
+
"info",
|
|
2036
|
+
"hint"
|
|
2037
|
+
];
|
|
2038
|
+
const RANK = {
|
|
2039
|
+
error: 0,
|
|
2040
|
+
warning: 1,
|
|
2041
|
+
info: 2,
|
|
2042
|
+
hint: 3
|
|
2043
|
+
};
|
|
2044
|
+
/** Negative when `a` is more severe than `b`. */
|
|
2045
|
+
function compareSeverity(a, b) {
|
|
2046
|
+
return RANK[a] - RANK[b];
|
|
2047
|
+
}
|
|
2048
|
+
/** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
|
|
2049
|
+
function worstDiagnosticSeverity(diagnostics) {
|
|
2050
|
+
let worst;
|
|
2051
|
+
for (const d of diagnostics ?? []) {
|
|
2052
|
+
if (worst === void 0 || RANK[d.severity] < RANK[worst]) worst = d.severity;
|
|
2053
|
+
if (worst === "error") break;
|
|
2054
|
+
}
|
|
2055
|
+
return worst;
|
|
2056
|
+
}
|
|
2057
|
+
function identity(d) {
|
|
2058
|
+
return `${d.elementId}\u0000${d.key ?? ""}\u0000${d.message}`;
|
|
2059
|
+
}
|
|
2060
|
+
/**
|
|
2061
|
+
* The union of several lists, in order, without duplicates: diagnostics with the same
|
|
2062
|
+
* `(elementId, key, message)` count once, keeping the first one's position and the most severe
|
|
2063
|
+
* severity among them.
|
|
2064
|
+
*/
|
|
2065
|
+
function mergeDiagnostics(lists) {
|
|
2066
|
+
const result = [];
|
|
2067
|
+
const index = /* @__PURE__ */ new Map();
|
|
2068
|
+
for (const list of lists) for (const d of list ?? []) {
|
|
2069
|
+
const id = identity(d);
|
|
2070
|
+
const at = index.get(id);
|
|
2071
|
+
if (at === void 0) {
|
|
2072
|
+
index.set(id, result.length);
|
|
2073
|
+
result.push(d);
|
|
2074
|
+
} else if (RANK[d.severity] < RANK[result[at].severity]) result[at] = {
|
|
2075
|
+
...result[at],
|
|
2076
|
+
severity: d.severity
|
|
2077
|
+
};
|
|
2078
|
+
}
|
|
2079
|
+
return result;
|
|
2080
|
+
}
|
|
2081
|
+
/** Diagnostics by element (or link) id, each list in the input order. */
|
|
2082
|
+
function groupDiagnostics(diagnostics) {
|
|
2083
|
+
const map = /* @__PURE__ */ new Map();
|
|
2084
|
+
for (const d of diagnostics ?? []) {
|
|
2085
|
+
const list = map.get(d.elementId);
|
|
2086
|
+
if (list) list.push(d);
|
|
2087
|
+
else map.set(d.elementId, [d]);
|
|
2088
|
+
}
|
|
2089
|
+
return map;
|
|
2090
|
+
}
|
|
2091
|
+
const NONE = [];
|
|
2092
|
+
function createDiagnosticsStore() {
|
|
2093
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
2094
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2095
|
+
let merged = NONE;
|
|
2096
|
+
const changed = () => {
|
|
2097
|
+
merged = bySource.size === 0 ? NONE : mergeDiagnostics(bySource.values());
|
|
2098
|
+
for (const listener of listeners) listener();
|
|
2099
|
+
};
|
|
2100
|
+
return {
|
|
2101
|
+
publish(source, diagnostics) {
|
|
2102
|
+
if (diagnostics.length === 0) {
|
|
2103
|
+
if (bySource.delete(source)) changed();
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
bySource.set(source, diagnostics.map((d) => d.source === void 0 ? {
|
|
2107
|
+
...d,
|
|
2108
|
+
source
|
|
2109
|
+
} : d));
|
|
2110
|
+
changed();
|
|
2111
|
+
},
|
|
2112
|
+
clear(source) {
|
|
2113
|
+
if (source === void 0) {
|
|
2114
|
+
if (bySource.size === 0) return;
|
|
2115
|
+
bySource.clear();
|
|
2116
|
+
} else if (!bySource.delete(source)) return;
|
|
2117
|
+
changed();
|
|
2118
|
+
},
|
|
2119
|
+
sources: () => [...bySource.keys()],
|
|
2120
|
+
get: (source) => bySource.get(source) ?? NONE,
|
|
2121
|
+
getAll: () => merged,
|
|
2122
|
+
subscribe(listener) {
|
|
2123
|
+
listeners.add(listener);
|
|
2124
|
+
return () => listeners.delete(listener);
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
const LSP_SEVERITIES = [
|
|
2129
|
+
"error",
|
|
2130
|
+
"warning",
|
|
2131
|
+
"info",
|
|
2132
|
+
"hint"
|
|
2133
|
+
];
|
|
2134
|
+
function anchorOf(data) {
|
|
2135
|
+
if (typeof data !== "object" || data === null) return {};
|
|
2136
|
+
const record = data;
|
|
2137
|
+
const elementId = typeof record.elementId === "string" ? record.elementId : typeof record.nodeId === "string" ? record.nodeId : void 0;
|
|
2138
|
+
return {
|
|
2139
|
+
...elementId ? { elementId } : {},
|
|
2140
|
+
...typeof record.key === "string" ? { key: record.key } : {}
|
|
2141
|
+
};
|
|
2142
|
+
}
|
|
2143
|
+
function convertLsp(d, options) {
|
|
2144
|
+
const anchor = anchorOf(d.data);
|
|
2145
|
+
const elementId = anchor.elementId ?? options.elementIdFor?.(d);
|
|
2146
|
+
if (!elementId) return void 0;
|
|
2147
|
+
const base = options.severityNumbering === "vscode" ? 0 : 1;
|
|
2148
|
+
const severity = d.severity === void 0 ? "error" : LSP_SEVERITIES[d.severity - base] ?? "error";
|
|
2149
|
+
const code = typeof d.code === "object" ? d.code.value : d.code;
|
|
2150
|
+
return {
|
|
2151
|
+
elementId,
|
|
2152
|
+
...anchor.key !== void 0 ? { key: anchor.key } : {},
|
|
2153
|
+
severity,
|
|
2154
|
+
message: typeof d.message === "string" ? d.message : d.message.value,
|
|
2155
|
+
...d.source !== void 0 ? { source: d.source } : {},
|
|
2156
|
+
...d.range ? { range: d.range } : {},
|
|
2157
|
+
...code !== void 0 ? { code: String(code) } : {},
|
|
2158
|
+
...d.data !== void 0 ? { data: d.data } : {}
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
|
|
2163
|
+
* names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
|
|
2164
|
+
*/
|
|
2165
|
+
function fromLspDiagnostic(diagnostic) {
|
|
2166
|
+
return convertLsp(diagnostic, {});
|
|
2167
|
+
}
|
|
2168
|
+
/** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
|
|
2169
|
+
function fromLspDiagnostics(diagnostics, options = {}) {
|
|
2170
|
+
const result = [];
|
|
2171
|
+
for (const d of diagnostics) {
|
|
2172
|
+
const converted = convertLsp(d, options);
|
|
2173
|
+
if (converted) result.push(converted);
|
|
2174
|
+
}
|
|
2175
|
+
return result;
|
|
2176
|
+
}
|
|
2177
|
+
/** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
|
|
2178
|
+
function fromNodeIdDiagnostic(diagnostic) {
|
|
2179
|
+
const { nodeId, severity, ...rest } = diagnostic;
|
|
2180
|
+
if (!nodeId) return void 0;
|
|
2181
|
+
return {
|
|
2182
|
+
...rest,
|
|
2183
|
+
elementId: nodeId,
|
|
2184
|
+
severity: Object.hasOwn(RANK, severity) ? severity : "info"
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
/**
|
|
2188
|
+
* `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
|
|
2189
|
+
* without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
|
|
2190
|
+
*/
|
|
2191
|
+
function fromNodeIdDiagnostics(diagnostics) {
|
|
2192
|
+
const result = [];
|
|
2193
|
+
for (const d of diagnostics) {
|
|
2194
|
+
const converted = fromNodeIdDiagnostic(d);
|
|
2195
|
+
if (converted) result.push(converted);
|
|
2196
|
+
}
|
|
2197
|
+
return result;
|
|
2198
|
+
}
|
|
2199
|
+
//#endregion
|
|
1845
2200
|
exports.ACTOR_KINDS = ACTOR_KINDS;
|
|
1846
2201
|
exports.ACTOR_LINK_KINDS = ACTOR_LINK_KINDS;
|
|
1847
2202
|
exports.CONTRIBUTION_LABELS = CONTRIBUTION_LABELS;
|
|
1848
2203
|
exports.DEFAULT_DIAGRAM = DEFAULT_DIAGRAM;
|
|
1849
2204
|
exports.DEFAULT_ELEMENT_SIZE = DEFAULT_ELEMENT_SIZE;
|
|
1850
2205
|
exports.DEPENDENCY_LINK_KINDS = DEPENDENCY_LINK_KINDS;
|
|
2206
|
+
exports.DIAGNOSTIC_SEVERITIES = DIAGNOSTIC_SEVERITIES;
|
|
1851
2207
|
exports.ELEMENT_KINDS = ELEMENT_KINDS;
|
|
2208
|
+
exports.FILE_METAMODEL_KEY = FILE_METAMODEL_KEY;
|
|
1852
2209
|
exports.ISTAR_2_0 = ISTAR_2_0;
|
|
1853
2210
|
exports.ISTAR_PREFIX = ISTAR_PREFIX;
|
|
1854
2211
|
exports.ISTAR_VERSION = ISTAR_VERSION;
|
|
@@ -1868,7 +2225,9 @@ exports.addElement = addElement;
|
|
|
1868
2225
|
exports.boolean = boolean;
|
|
1869
2226
|
exports.canLink = canLink;
|
|
1870
2227
|
exports.childrenOf = childrenOf;
|
|
2228
|
+
exports.compareSeverity = compareSeverity;
|
|
1871
2229
|
exports.connect = connect;
|
|
2230
|
+
exports.createDiagnosticsStore = createDiagnosticsStore;
|
|
1872
2231
|
exports.createEmptyModel = createEmptyModel;
|
|
1873
2232
|
exports.createModelStore = createModelStore;
|
|
1874
2233
|
exports.defaultIdGenerator = defaultIdGenerator;
|
|
@@ -1883,7 +2242,15 @@ exports.elementBehavesLike = elementBehavesLike;
|
|
|
1883
2242
|
exports.elementKindDefinition = elementKindDefinition;
|
|
1884
2243
|
exports.enumOf = enumOf;
|
|
1885
2244
|
exports.extendMetamodel = extendMetamodel;
|
|
2245
|
+
exports.fileMetamodelExtension = fileMetamodelExtension;
|
|
2246
|
+
exports.fileMetamodelOf = fileMetamodelOf;
|
|
2247
|
+
exports.fromLspDiagnostic = fromLspDiagnostic;
|
|
2248
|
+
exports.fromLspDiagnostics = fromLspDiagnostics;
|
|
2249
|
+
exports.fromNodeIdDiagnostic = fromNodeIdDiagnostic;
|
|
2250
|
+
exports.fromNodeIdDiagnostics = fromNodeIdDiagnostics;
|
|
1886
2251
|
exports.getSourceLayout = getSourceLayout;
|
|
2252
|
+
exports.groupDiagnostics = groupDiagnostics;
|
|
2253
|
+
exports.hostMetamodelOf = hostMetamodelOf;
|
|
1887
2254
|
exports.inheritMetamodel = inheritMetamodel;
|
|
1888
2255
|
exports.inheritSourceLayout = inheritSourceLayout;
|
|
1889
2256
|
exports.isActor = isActor;
|
|
@@ -1902,6 +2269,7 @@ exports.isNodeKindIn = isNodeKindIn;
|
|
|
1902
2269
|
exports.isNodeLinkKind = isNodeLinkKind;
|
|
1903
2270
|
exports.linkKindDefinition = linkKindDefinition;
|
|
1904
2271
|
exports.linksOf = linksOf;
|
|
2272
|
+
exports.mergeDiagnostics = mergeDiagnostics;
|
|
1905
2273
|
exports.metamodelOf = metamodelOf;
|
|
1906
2274
|
exports.moveElement = moveElement;
|
|
1907
2275
|
exports.nestElement = nestElement;
|
|
@@ -1910,6 +2278,7 @@ exports.parsePistar = parsePistar;
|
|
|
1910
2278
|
exports.prop = prop;
|
|
1911
2279
|
exports.removeElement = removeElement;
|
|
1912
2280
|
exports.removeElements = removeElements;
|
|
2281
|
+
exports.setHostMetamodel = setHostMetamodel;
|
|
1913
2282
|
exports.shortKindName = shortKindName;
|
|
1914
2283
|
exports.string = string;
|
|
1915
2284
|
exports.toPistar = toPistar;
|
|
@@ -1917,8 +2286,11 @@ exports.toPistarObject = toPistarObject;
|
|
|
1917
2286
|
exports.updateDiagram = updateDiagram;
|
|
1918
2287
|
exports.updateElement = updateElement;
|
|
1919
2288
|
exports.updateLink = updateLink;
|
|
2289
|
+
exports.validateFileMetamodel = validateFileMetamodel;
|
|
1920
2290
|
exports.validateModel = validateModel;
|
|
1921
2291
|
exports.validateModelProperties = validateModelProperties;
|
|
2292
|
+
exports.withFileMetamodel = withFileMetamodel;
|
|
1922
2293
|
exports.withMetamodel = withMetamodel;
|
|
2294
|
+
exports.worstDiagnosticSeverity = worstDiagnosticSeverity;
|
|
1923
2295
|
|
|
1924
2296
|
//# sourceMappingURL=index.cjs.map
|