@istar-ts/core 0.6.0 → 0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ops.defaultIdGenerator","ops.addElement","ops.updateElement","ops.moveElement","ops.nestElement","ops.removeElement","ops.removeElements","ops.connect","ops.addDependency","ops.updateLink","ops.disconnect","ops.updateDiagram","ops.ModelOperationError"],"sources":["../src/metamodel.ts","../src/model.ts","../src/constraints.ts","../src/serialization.ts","../src/operations.ts","../src/store.ts","../src/properties.ts"],"sourcesContent":["/**\n * The iStar 2.0 metamodel, ported from piStar's `tool/language/metamodel.js`.\n *\n * Kind names carry the `istar.` prefix exactly as they appear in piStar save files.\n */\n\nexport const ISTAR_PREFIX = 'istar';\nexport const METAMODEL_VERSION = '0.2';\n\n/** Containers: elements that hold inner elements (piStar `metamodel.containers`). */\nexport const ACTOR_KINDS = ['istar.Actor', 'istar.Agent', 'istar.Role'] as const;\nexport type ActorKind = (typeof ACTOR_KINDS)[number];\n\n/** Intentional elements (piStar `metamodel.nodes`). */\nexport const NODE_KINDS = ['istar.Goal', 'istar.Quality', 'istar.Resource', 'istar.Task'] as const;\nexport type NodeKind = (typeof NODE_KINDS)[number];\n\nexport type ElementKind = ActorKind | NodeKind;\nexport const ELEMENT_KINDS: readonly ElementKind[] = [...ACTOR_KINDS, ...NODE_KINDS];\n\n/** Links between two containers (piStar `metamodel.containerLinks`). */\nexport const ACTOR_LINK_KINDS = ['istar.IsALink', 'istar.ParticipatesInLink'] as const;\nexport type ActorLinkKind = (typeof ACTOR_LINK_KINDS)[number];\n\n/** Links that connect two containers through a dependum (piStar `metamodel.dependencyLinks`). */\nexport const DEPENDENCY_LINK_KINDS = ['istar.DependencyLink'] as const;\nexport type DependencyLinkKind = (typeof DEPENDENCY_LINK_KINDS)[number];\n\n/** Links between two intentional elements (piStar `metamodel.nodeLinks`). */\nexport const NODE_LINK_KINDS = [\n 'istar.AndRefinementLink',\n 'istar.OrRefinementLink',\n 'istar.NeededByLink',\n 'istar.QualificationLink',\n 'istar.ContributionLink',\n] as const;\nexport type NodeLinkKind = (typeof NODE_LINK_KINDS)[number];\n\nexport type LinkKind = ActorLinkKind | DependencyLinkKind | NodeLinkKind;\nexport const LINK_KINDS: readonly LinkKind[] = [\n ...ACTOR_LINK_KINDS,\n ...DEPENDENCY_LINK_KINDS,\n ...NODE_LINK_KINDS,\n];\n\n/** Possible values of a Contribution link's `label`. */\nexport const CONTRIBUTION_LABELS = ['make', 'help', 'hurt', 'break'] as const;\nexport type ContributionLabel = (typeof CONTRIBUTION_LABELS)[number];\n\nexport interface NodeKindInfo {\n /** Can be added inside an actor. */\n readonly canBeInnerElement: boolean;\n /** Can be the dependum of a dependency. */\n readonly canBeDependum: boolean;\n /** Can be placed directly on the diagram, outside any actor. */\n readonly canBeOnPaper: boolean;\n}\n\nexport interface LinkKindInfo {\n /** Fixed text drawn on the link (e.g. \"is-a\"). */\n readonly label?: string;\n /** piStar retries with source and target swapped when the first attempt is invalid. */\n readonly tryReversedWhenAdding?: boolean;\n /** The link carries a user-selectable label, stored as `label` in the save file. */\n readonly changeableLabel?: boolean;\n readonly possibleLabels?: readonly string[];\n}\n\nconst innerNode: NodeKindInfo = {\n canBeInnerElement: true,\n canBeDependum: true,\n canBeOnPaper: false,\n};\n\nexport const NODE_KIND_INFO: Readonly<Record<NodeKind, NodeKindInfo>> = {\n 'istar.Goal': innerNode,\n 'istar.Quality': innerNode,\n 'istar.Resource': innerNode,\n 'istar.Task': innerNode,\n};\n\nexport const LINK_KIND_INFO: Readonly<Record<LinkKind, LinkKindInfo>> = {\n 'istar.IsALink': { label: 'is-a' },\n 'istar.ParticipatesInLink': { label: 'participates-in' },\n 'istar.DependencyLink': {},\n 'istar.AndRefinementLink': {},\n 'istar.OrRefinementLink': {},\n 'istar.NeededByLink': { tryReversedWhenAdding: true },\n 'istar.QualificationLink': { tryReversedWhenAdding: true },\n 'istar.ContributionLink': { changeableLabel: true, possibleLabels: CONTRIBUTION_LABELS },\n};\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/**\n * Default sizes of each element kind, from piStar's `shapes.js`. For actors this is the\n * initial boundary size; the collapsed actor symbol is a circle of radius 40.\n */\nexport const DEFAULT_ELEMENT_SIZE: Readonly<Record<ElementKind, Size>> = {\n 'istar.Actor': { width: 200, height: 120 },\n 'istar.Agent': { width: 200, height: 120 },\n 'istar.Role': { width: 200, height: 120 },\n 'istar.Goal': { width: 90, height: 35 },\n 'istar.Quality': { width: 90, height: 55 },\n 'istar.Resource': { width: 90, height: 35 },\n 'istar.Task': { width: 95, height: 36 },\n};\n\nconst actorKinds: ReadonlySet<string> = new Set(ACTOR_KINDS);\nconst nodeKinds: ReadonlySet<string> = new Set(NODE_KINDS);\nconst elementKinds: ReadonlySet<string> = new Set(ELEMENT_KINDS);\nconst linkKinds: ReadonlySet<string> = new Set(LINK_KINDS);\nconst actorLinkKinds: ReadonlySet<string> = new Set(ACTOR_LINK_KINDS);\nconst nodeLinkKinds: ReadonlySet<string> = new Set(NODE_LINK_KINDS);\n\nexport function isActorKind(kind: string): kind is ActorKind {\n return actorKinds.has(kind);\n}\nexport function isNodeKind(kind: string): kind is NodeKind {\n return nodeKinds.has(kind);\n}\nexport function isElementKind(kind: string): kind is ElementKind {\n return elementKinds.has(kind);\n}\nexport function isLinkKind(kind: string): kind is LinkKind {\n return linkKinds.has(kind);\n}\nexport function isActorLinkKind(kind: string): kind is ActorLinkKind {\n return actorLinkKinds.has(kind);\n}\nexport function isNodeLinkKind(kind: string): kind is NodeLinkKind {\n return nodeLinkKinds.has(kind);\n}\nexport function isDependencyLinkKind(kind: string): kind is DependencyLinkKind {\n return kind === 'istar.DependencyLink';\n}\nexport function isContributionLabel(value: string): value is ContributionLabel {\n return (CONTRIBUTION_LABELS as readonly string[]).includes(value);\n}\n\n/** `'istar.Goal'` → `'Goal'` */\nexport function shortKindName(kind: ElementKind | LinkKind): string {\n return kind.slice(ISTAR_PREFIX.length + 1);\n}\n","import type { ActorKind, ElementKind, LinkKind, NodeKind } from './metamodel';\nimport { isActorKind } from './metamodel';\n\n/**\n * piStar stores every custom property value as a string (e.g. `\"initialValue\": \"false\"`).\n * Typed access is layered on top with property schemas (see `properties.ts`).\n */\nexport type CustomProperties = Readonly<Record<string, string>>;\n\n/** Arbitrary JSON keys the library does not interpret; kept so they survive a round trip. */\nexport type Extra = Readonly<Record<string, unknown>>;\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** Per-element entry of the save file's `display` section. */\nexport interface ElementDisplay {\n readonly backgroundColor?: string;\n readonly width?: number;\n readonly height?: number;\n /** Actors only. */\n readonly collapsed?: boolean;\n readonly [key: string]: unknown;\n}\n\n/** Per-link entry of the save file's `display` section. */\nexport interface LinkDisplay {\n readonly vertices?: readonly Point[];\n readonly [key: string]: unknown;\n}\n\nexport interface IstarElement<K extends ElementKind = ElementKind> {\n readonly id: string;\n readonly kind: K;\n /** The element's label; `text` in the save file. */\n readonly name: string;\n /** Absolute diagram coordinates, as in the save file (children are not relative to actors). */\n readonly x: number;\n readonly y: number;\n /** Id of the containing actor, for inner elements. */\n readonly parent?: string;\n /** True when the element is the dependum of a dependency (lives in `dependencies`). */\n readonly isDependum?: boolean;\n /**\n * Depender/dependee recorded in the save file for a dependum. The dependency links are the\n * source of truth; this is only a fallback used when those links are missing.\n */\n readonly dependency?: { readonly source: string; readonly target: string };\n readonly customProperties?: CustomProperties;\n readonly display?: ElementDisplay;\n readonly extra?: Extra;\n}\n\nexport type IstarActor = IstarElement<ActorKind>;\nexport type IstarNode = IstarElement<NodeKind>;\n\nexport interface IstarLink<K extends LinkKind = LinkKind> {\n readonly id: string;\n readonly kind: K;\n readonly source: string;\n readonly target: string;\n /** Contribution value (`make`/`help`/`hurt`/`break`), stored as `label` in the save file. */\n readonly label?: string;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n readonly display?: LinkDisplay;\n readonly extra?: Extra;\n}\n\nexport interface Diagram {\n readonly width?: number;\n readonly height?: number;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n readonly extra?: Extra;\n}\n\n/**\n * An immutable iStar model. Maps preserve insertion order, which is the order elements and\n * links are written back to disk.\n */\nexport interface IstarModel {\n readonly elements: ReadonlyMap<string, IstarElement>;\n readonly links: ReadonlyMap<string, IstarLink>;\n readonly diagram?: Diagram;\n readonly tool?: string;\n readonly istar?: string;\n readonly saveDate?: string;\n /** `display` entries whose id matches no element or link. */\n readonly extraDisplay?: Extra;\n /** Unknown top-level keys (e.g. `metamodelVersion`). */\n readonly extra?: Extra;\n}\n\n/** Tool identifier written by piStar 2.1.0, whose file format this library emulates. */\nexport const PISTAR_TOOL = 'pistar.2.1.0';\nexport const ISTAR_VERSION = '2.0';\n\nexport const DEFAULT_DIAGRAM: Diagram = { width: 2000, height: 1300 };\n\nexport function createEmptyModel(diagram: Diagram = DEFAULT_DIAGRAM): IstarModel {\n return {\n elements: new Map(),\n links: new Map(),\n diagram,\n tool: PISTAR_TOOL,\n istar: ISTAR_VERSION,\n };\n}\n\nexport function isActor(element: IstarElement | undefined): element is IstarActor {\n return element !== undefined && isActorKind(element.kind);\n}\n\nexport function isNode(element: IstarElement | undefined): element is IstarNode {\n return element !== undefined && !isActorKind(element.kind);\n}\n\n/** Inner elements of an actor, in model order. */\nexport function childrenOf(model: IstarModel, actorId: string): IstarElement[] {\n const result: IstarElement[] = [];\n for (const element of model.elements.values()) {\n if (element.parent === actorId) result.push(element);\n }\n return result;\n}\n\n/** Links that have the element as source or target. */\nexport function linksOf(model: IstarModel, elementId: string): IstarLink[] {\n const result: IstarLink[] = [];\n for (const link of model.links.values()) {\n if (link.source === elementId || link.target === elementId) result.push(link);\n }\n return result;\n}\n\n/** For a dependum, the two halves of its dependency: depender → dependum → dependee. */\nexport function dependencyLinksOf(\n model: IstarModel,\n dependumId: string,\n): { inbound?: IstarLink; outbound?: IstarLink } {\n let inbound: IstarLink | undefined;\n let outbound: IstarLink | undefined;\n for (const link of model.links.values()) {\n if (link.kind !== 'istar.DependencyLink') continue;\n if (link.target === dependumId && !inbound) inbound = link;\n if (link.source === dependumId && !outbound) outbound = link;\n }\n return { inbound, outbound };\n}\n","/**\n * iStar 2.0 link constraints, ported from piStar's `tool/language/constraints.js`.\n *\n * Each check runs in the same order as upstream so the reported reason is the one piStar\n * would show. Upstream messages embed HTML and illustrative images; here they are plain text.\n */\nimport type { LinkKind } from './metamodel';\nimport { isActorKind } from './metamodel';\nimport type { IstarElement, IstarLink, IstarModel } from './model';\n\nexport type ConstraintCode =\n | 'unknown-element'\n | 'unknown-link-kind'\n | 'invalid-source'\n | 'invalid-target'\n | 'actor-types-differ'\n | 'self-link'\n | 'duplicate-link'\n | 'dependum-endpoint'\n | 'same-actor'\n | 'different-actors'\n | 'refined-depender'\n | 'contributed-depender'\n | 'depender-target'\n | 'mixed-refinement'\n | 'contribution-and-qualification';\n\nexport type LinkCheck = { ok: true } | { ok: false; reason: string; code: ConstraintCode };\n\nconst OK: LinkCheck = { ok: true };\n\nfunction fail(code: ConstraintCode, reason: string): LinkCheck {\n return { ok: false, code, reason };\n}\n\ntype ElementRef = string | IstarElement;\n\n/**\n * Checks whether a link of `kind` may be added from `source` to `target` in `model`.\n *\n * For `istar.DependencyLink`, `source` is the depender and `target` the dependee (an actor or\n * one of its inner elements); the dependum sits between them and is not part of the check.\n */\nexport function canLink(\n model: IstarModel,\n source: ElementRef,\n target: ElementRef,\n kind: LinkKind,\n): LinkCheck {\n const s = resolve(model, source);\n const t = resolve(model, target);\n if (!s) return fail('unknown-element', `unknown source element \"${refId(source)}\"`);\n if (!t) return fail('unknown-element', `unknown target element \"${refId(target)}\"`);\n const check = CHECKS[kind];\n if (!check) return fail('unknown-link-kind', `unknown link kind \"${String(kind)}\"`);\n return check(new Graph(model), s, t);\n}\n\nfunction refId(ref: ElementRef): string {\n return typeof ref === 'string' ? ref : ref.id;\n}\n\nfunction resolve(model: IstarModel, ref: ElementRef): IstarElement | undefined {\n // Always look the element up so a stale object can't be checked against a newer model.\n return model.elements.get(refId(ref));\n}\n\n/** The graph queries used by upstream constraints (`istar.isThereLinkBetween`, etc.). */\nclass Graph {\n constructor(readonly model: IstarModel) {}\n\n /**\n * True when a link (optionally of `kind`) already connects the two elements, in either\n * direction. Mirrors `istar.isThereLinkBetween`.\n */\n isThereLinkBetween(a: IstarElement, b: IstarElement, kind?: LinkKind): boolean {\n for (const link of this.model.links.values()) {\n if (kind && link.kind !== kind) continue;\n if (\n (link.source === a.id && link.target === b.id) ||\n (link.source === b.id && link.target === a.id)\n ) {\n return true;\n }\n }\n return false;\n }\n\n isSourceOfType(element: IstarElement, kind: LinkKind): boolean {\n for (const link of this.model.links.values()) {\n if (link.kind === kind && link.source === element.id) return true;\n }\n return false;\n }\n\n isTargetOfType(element: IstarElement, kind: LinkKind): boolean {\n for (const link of this.model.links.values()) {\n if (link.kind === kind && link.target === element.id) return true;\n }\n return false;\n }\n}\n\ntype Check = (graph: Graph, source: IstarElement, target: IstarElement) => LinkCheck;\n\nconst is = (element: IstarElement, ...shortNames: string[]): boolean =>\n shortNames.some((name) => element.kind === `istar.${name}`);\n\nconst isKindOfActor = (element: IstarElement): boolean => isActorKind(element.kind);\nconst isDependum = (element: IstarElement): boolean => element.isDependum === true;\n\nconst isALink: Check = (graph, source, target) => {\n // Upstream evaluates the source-kind check after the type-equality check without guarding\n // on the previous result, so its message wins when both fail. Reproduced here.\n if (!is(source, 'Actor', 'Role')) {\n return fail(\n 'invalid-source',\n 'the source of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).',\n );\n }\n if (source.kind !== target.kind) {\n return fail(\n 'actor-types-differ',\n '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).',\n );\n }\n if (!is(target, 'Actor', 'Role')) {\n return fail(\n 'invalid-target',\n 'the target of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make Is-A links from an actor onto itself.');\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).',\n );\n }\n return OK;\n};\n\nconst participatesInLink: Check = (graph, source, target) => {\n if (!isKindOfActor(source)) {\n return fail(\n 'invalid-source',\n 'the source of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)',\n );\n }\n if (!isKindOfActor(target)) {\n return fail(\n 'invalid-target',\n 'the target of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Participates-In link from an actor onto itself.');\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).',\n );\n }\n return OK;\n};\n\n/** The actor an element belongs to: itself for actors, its parent for inner elements. */\nfunction owningActorId(element: IstarElement): string | undefined {\n return isKindOfActor(element) ? element.id : element.parent;\n}\n\nconst dependencyLink: Check = (graph, source, target) => {\n if (source.id === target.id) {\n return fail('self-link', 'a Dependency link cannot link an element onto itself');\n }\n if (isDependum(source)) {\n return fail('dependum-endpoint', 'a Dependency link cannot start from a dependum');\n }\n if (isDependum(target)) {\n return fail('dependum-endpoint', 'a Dependency link cannot end in a dependum');\n }\n if (owningActorId(source) === owningActorId(target)) {\n return fail(\n 'same-actor',\n 'a Dependency link must involve two different actors (iStar 2.0 Guide, Page 14)',\n );\n }\n if (\n graph.isTargetOfType(source, 'istar.OrRefinementLink') ||\n graph.isTargetOfType(source, 'istar.AndRefinementLink')\n ) {\n return fail(\n 'refined-depender',\n 'a refined element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to add the Dependency originating from a child.',\n );\n }\n if (graph.isTargetOfType(source, 'istar.ContributionLink')) {\n return fail(\n 'contributed-depender',\n 'a contributed element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to add the Dependency originating from a child.',\n );\n }\n return OK;\n};\n\nfunction refinementLink(label: 'AND' | 'OR'): Check {\n const other = label === 'AND' ? 'istar.OrRefinementLink' : 'istar.AndRefinementLink';\n return (graph, source, target) => {\n if (!is(source, 'Task', 'Goal')) {\n return fail(\n 'invalid-source',\n `the source of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`,\n );\n }\n if (!is(target, 'Task', 'Goal')) {\n return fail(\n 'invalid-target',\n `the target of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`,\n );\n }\n if (source.id === target.id) {\n return fail(\n 'self-link',\n `you cannot make an ${label}-refinement link from an element onto itself`,\n );\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n `you cannot make an ${label}-refinement link with a dependum (iStar 2.0 Guide, Page 14)`,\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n `the source and target of an ${label}-refinement link must pertain to the same actor (iStar 2.0 Guide, Page 14)`,\n );\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one refinement link between the same two elements',\n );\n }\n if (graph.isSourceOfType(target, 'istar.DependencyLink')) {\n return fail(\n 'depender-target',\n 'you cannot refine a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to move the dependency to the sub-element.',\n );\n }\n if (graph.isTargetOfType(target, other)) {\n const mix =\n label === 'AND'\n ? 'you cannot mix AND-refinements with OR-refinements targeting the same element (iStar 2.0 Guide, Page 10).'\n : 'you cannot mix OR-refinements with AND-refinements targeting the same element (iStar 2.0 Guide, Page 10).';\n return fail('mixed-refinement', mix);\n }\n return OK;\n };\n}\n\nconst neededByLink: Check = (graph, source, target) => {\n if (!is(source, 'Resource')) {\n return fail(\n 'invalid-source',\n 'the source of a Needed-By link must be a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(target, 'Task')) {\n return fail(\n 'invalid-target',\n 'the target of a Needed-By link must be a Task (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Needed-By link from an element onto itself');\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Needed-By link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Needed-By link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Needed-By link between the same two elements',\n );\n }\n return OK;\n};\n\nconst contributionLink: Check = (graph, source, target) => {\n if (!is(source, 'Goal', 'Quality', 'Task', 'Resource')) {\n return fail(\n 'invalid-source',\n 'the source of a Contribution link must be a Goal, a Quality, a Task or a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(target, 'Quality')) {\n return fail(\n 'invalid-target',\n 'the target of a Contribution link must be a Quality (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail(\n 'self-link',\n 'you cannot make a Contribution link from an element onto itself (iStar 2.0 Guide, Page 15)',\n );\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Contribution link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Contribution link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.ContributionLink')) {\n return fail(\n 'duplicate-link',\n 'there can only be one Contribution link between the same two elements',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.QualificationLink')) {\n return fail(\n 'contribution-and-qualification',\n 'you cannot have Contribution and Qualification links between the same two elements (iStar 2.0 Guide, Page 15)',\n );\n }\n if (graph.isSourceOfType(target, 'istar.DependencyLink')) {\n return fail(\n 'depender-target',\n 'you cannot contribute to a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to move the dependency to the sub-quality.',\n );\n }\n return OK;\n};\n\nconst qualificationLink: Check = (graph, source, target) => {\n if (!is(source, 'Quality')) {\n return fail(\n 'invalid-source',\n 'the source of a Qualification link must be a Quality (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(target, 'Goal', 'Task', 'Resource')) {\n return fail(\n 'invalid-target',\n 'the target of a Qualification link must be a Goal, a Task or a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Qualification link from an element onto itself');\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Qualification link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Qualification link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.QualificationLink')) {\n return fail(\n 'duplicate-link',\n 'there can only be one Qualification link between the same two elements',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.ContributionLink')) {\n return fail(\n 'contribution-and-qualification',\n 'you cannot have Qualification and Contribution links between the same two elements (iStar 2.0 Guide, Page 15)',\n );\n }\n return OK;\n};\n\nconst CHECKS: Readonly<Record<LinkKind, Check>> = {\n 'istar.IsALink': isALink,\n 'istar.ParticipatesInLink': participatesInLink,\n 'istar.DependencyLink': dependencyLink,\n 'istar.AndRefinementLink': refinementLink('AND'),\n 'istar.OrRefinementLink': refinementLink('OR'),\n 'istar.NeededByLink': neededByLink,\n 'istar.ContributionLink': contributionLink,\n 'istar.QualificationLink': qualificationLink,\n};\n\nexport interface ModelIssue {\n readonly linkId: string;\n readonly kind: LinkKind;\n readonly source: string;\n readonly target: string;\n readonly code: ConstraintCode;\n readonly message: string;\n}\n\n/**\n * Re-validates every link of a model, the way piStar does when loading a file: dependencies\n * first (each checked before its own links are added), then the remaining links in file\n * order, each against the graph built so far. Invalid links are reported, not removed.\n */\nexport function validateModel(model: IstarModel): ModelIssue[] {\n const issues: ModelIssue[] = [];\n const accepted = new Map<string, IstarLink>();\n const view = (): IstarModel => ({ ...model, links: accepted });\n\n const report = (\n linkId: string,\n kind: LinkKind,\n source: string,\n target: string,\n check: LinkCheck,\n ): void => {\n if (!check.ok) {\n issues.push({ linkId, kind, source, target, code: check.code, message: check.reason });\n }\n };\n\n const dependencyLinks = [...model.links.values()].filter(\n (l) => l.kind === 'istar.DependencyLink',\n );\n for (const dependum of model.elements.values()) {\n if (!dependum.isDependum) continue;\n const inbound = dependencyLinks.find((l) => l.target === dependum.id);\n const outbound = dependencyLinks.find((l) => l.source === dependum.id);\n const depender = inbound?.source ?? dependum.dependency?.source;\n const dependee = outbound?.target ?? dependum.dependency?.target;\n if (depender !== undefined && dependee !== undefined) {\n report(\n inbound?.id ?? dependum.id,\n 'istar.DependencyLink',\n depender,\n dependee,\n canLink(view(), depender, dependee, 'istar.DependencyLink'),\n );\n }\n if (inbound) accepted.set(inbound.id, inbound);\n if (outbound) accepted.set(outbound.id, outbound);\n }\n\n for (const link of model.links.values()) {\n if (link.kind === 'istar.DependencyLink') continue;\n if (model.elements.has(link.source) && model.elements.has(link.target)) {\n report(\n link.id,\n link.kind,\n link.source,\n link.target,\n canLink(view(), link.source, link.target, link.kind),\n );\n } else {\n report(link.id, link.kind, link.source, link.target, {\n ok: false,\n code: 'unknown-element',\n reason: 'the link refers to an element that does not exist',\n });\n }\n accepted.set(link.id, link);\n }\n return issues;\n}\n","/**\n * Reading and writing piStar save files, ported from `tool/app/istarcore/fileManager.js`.\n *\n * Output is produced with the same key order and `JSON.stringify(_, null, 2)` formatting as the\n * piStar web tool, so a file saved by piStar round-trips byte for byte. Keys this library does\n * not interpret are kept and written back.\n */\nimport type { ElementKind, LinkKind } from './metamodel';\nimport { isActorKind, isElementKind, isLinkKind } from './metamodel';\nimport type {\n CustomProperties,\n Diagram,\n ElementDisplay,\n Extra,\n IstarElement,\n IstarLink,\n IstarModel,\n LinkDisplay,\n} from './model';\nimport { dependencyLinksOf } from './model';\n\n// ---------------------------------------------------------------------------------------------\n// File format types\n\nexport interface PistarElementJson {\n id: string;\n text: string;\n type: string;\n x: number;\n y: number;\n customProperties?: Record<string, string>;\n [key: string]: unknown;\n}\n\nexport interface PistarActorJson extends PistarElementJson {\n nodes: PistarElementJson[];\n}\n\nexport interface PistarDependencyJson extends PistarElementJson {\n source: string;\n target: string;\n}\n\nexport interface PistarLinkJson {\n id: string;\n type: string;\n source: string;\n target: string;\n name?: string;\n customProperties?: Record<string, string>;\n label?: string;\n [key: string]: unknown;\n}\n\nexport interface PistarDiagramJson {\n width?: number;\n height?: number;\n name?: string;\n customProperties?: Record<string, string>;\n [key: string]: unknown;\n}\n\n/** A piStar save file. Older piStar versions may omit some sections (e.g. `orphans`). */\nexport interface PistarFile {\n actors: PistarActorJson[];\n orphans?: PistarElementJson[];\n dependencies?: PistarDependencyJson[];\n links?: PistarLinkJson[];\n display?: Record<string, Record<string, unknown>>;\n tool?: string;\n istar?: string;\n saveDate?: string;\n diagram?: PistarDiagramJson;\n [key: string]: unknown;\n}\n\nexport class PistarParseError extends Error {\n override name = 'PistarParseError';\n}\n\n/**\n * Parse-time bookkeeping that lets `toPistar` reproduce the original key order. It has no\n * meaning for the model itself and may be dropped.\n */\nexport interface SourceLayout {\n /** Top-level keys in file order. */\n readonly keys: readonly string[];\n /** `display` ids in file order. */\n readonly display: readonly string[];\n}\n\nconst layouts = new WeakMap<IstarModel, SourceLayout>();\n\n/** The key order recorded when `model` was parsed, if it came from `parsePistar`. */\nexport function getSourceLayout(model: IstarModel): SourceLayout | undefined {\n return layouts.get(model);\n}\n\n/**\n * Carries the recorded key order over to a model derived from `from` (the store does this for\n * every edit, so saving an edited file keeps a stable diff).\n */\nexport function inheritSourceLayout<M extends IstarModel>(from: IstarModel, to: M): M {\n const layout = layouts.get(from);\n if (layout && from !== to) layouts.set(to, layout);\n return to;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Parsing\n\nconst ELEMENT_KEYS = new Set(['id', 'text', 'type', 'x', 'y', 'customProperties']);\nconst ACTOR_KEYS = new Set([...ELEMENT_KEYS, 'nodes']);\nconst DEPENDENCY_KEYS = new Set([...ELEMENT_KEYS, 'source', 'target']);\nconst LINK_KEYS = new Set(['id', 'type', 'source', 'target', 'name', 'customProperties', 'label']);\nconst DIAGRAM_KEYS = new Set(['width', 'height', 'name', 'customProperties']);\nconst TOP_LEVEL_KEYS = [\n 'actors',\n 'orphans',\n 'dependencies',\n 'links',\n 'display',\n 'tool',\n 'istar',\n 'saveDate',\n 'diagram',\n] as const;\nconst TOP_LEVEL_KEY_SET: ReadonlySet<string> = new Set(TOP_LEVEL_KEYS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction extraOf(json: Record<string, unknown>, known: ReadonlySet<string>): Extra | undefined {\n let extra: Record<string, unknown> | undefined;\n for (const key of Object.keys(json)) {\n if (!known.has(key)) (extra ??= {})[key] = json[key];\n }\n return extra;\n}\n\nfunction asArray(value: unknown, where: string): unknown[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) throw new PistarParseError(`\"${where}\" must be an array`);\n return value;\n}\n\n/**\n * Parses a piStar save file (JSON text or an already-parsed object). The input is not mutated.\n *\n * Unlike the piStar tool, elements with `x` or `y` equal to 0 are kept: upstream's\n * `if (element.x && element.y)` silently drops them, which looks unintended.\n */\nexport function parsePistar(input: string | PistarFile | Record<string, unknown>): IstarModel {\n let json: unknown;\n if (typeof input === 'string') {\n try {\n json = JSON.parse(input);\n } catch (error) {\n throw new PistarParseError(`invalid JSON: ${(error as Error).message}`, { cause: error });\n }\n } else {\n json = structuredClone(input);\n }\n if (!isRecord(json)) throw new PistarParseError('a piStar model must be a JSON object');\n\n const display = isRecord(json.display) ? json.display : {};\n const usedDisplay = new Set<string>();\n const elements = new Map<string, IstarElement>();\n const links = new Map<string, IstarLink>();\n\n const displayFor = (id: string): Record<string, unknown> | undefined => {\n const entry = display[id];\n if (!isRecord(entry)) return undefined;\n usedDisplay.add(id);\n return entry;\n };\n\n const readElement = (\n raw: unknown,\n where: string,\n known: ReadonlySet<string>,\n extras: Partial<IstarElement>,\n ): IstarElement => {\n if (!isRecord(raw)) throw new PistarParseError(`${where}: expected an object`);\n const { id, type } = raw;\n if (typeof id !== 'string' || id === '') {\n throw new PistarParseError(`${where}: missing \"id\"`);\n }\n if (typeof type !== 'string' || !isElementKind(type)) {\n throw new PistarParseError(`${where} (${id}): unknown element type ${JSON.stringify(type)}`);\n }\n if (elements.has(id) || links.has(id)) {\n throw new PistarParseError(`${where}: duplicated id \"${id}\"`);\n }\n const element: IstarElement = {\n id,\n kind: type as ElementKind,\n name: typeof raw.text === 'string' ? raw.text : '',\n x: typeof raw.x === 'number' ? raw.x : 0,\n y: typeof raw.y === 'number' ? raw.y : 0,\n ...extras,\n ...(isRecord(raw.customProperties)\n ? { customProperties: raw.customProperties as CustomProperties }\n : {}),\n ...optional('display', displayFor(id) as ElementDisplay | undefined),\n ...optional('extra', extraOf(raw, known)),\n };\n elements.set(id, element);\n return element;\n };\n\n asArray(json.actors, 'actors').forEach((raw, i) => {\n const actor = readElement(raw, `actors[${i}]`, ACTOR_KEYS, {});\n if (!isActorKind(actor.kind)) {\n throw new PistarParseError(`actors[${i}] (${actor.id}): ${actor.kind} is not an actor kind`);\n }\n asArray((raw as Record<string, unknown>).nodes, `actors[${i}].nodes`).forEach((node, j) => {\n const child = readElement(node, `actors[${i}].nodes[${j}]`, ELEMENT_KEYS, {\n parent: actor.id,\n });\n if (isActorKind(child.kind)) {\n throw new PistarParseError(`actors[${i}].nodes[${j}]: actors cannot be nested`);\n }\n });\n });\n\n asArray(json.orphans, 'orphans').forEach((raw, i) => {\n readElement(raw, `orphans[${i}]`, ELEMENT_KEYS, {});\n });\n\n asArray(json.dependencies, 'dependencies').forEach((raw, i) => {\n const r = raw as Record<string, unknown>;\n const dependency =\n typeof r.source === 'string' && typeof r.target === 'string'\n ? { dependency: { source: r.source, target: r.target } }\n : {};\n readElement(raw, `dependencies[${i}]`, DEPENDENCY_KEYS, { isDependum: true, ...dependency });\n });\n\n asArray(json.links, 'links').forEach((raw, i) => {\n if (!isRecord(raw)) throw new PistarParseError(`links[${i}]: expected an object`);\n const { id, type, source, target } = raw;\n if (typeof id !== 'string' || id === '')\n throw new PistarParseError(`links[${i}]: missing \"id\"`);\n if (typeof type !== 'string' || !isLinkKind(type)) {\n throw new PistarParseError(`links[${i}] (${id}): unknown link type ${JSON.stringify(type)}`);\n }\n if (typeof source !== 'string' || typeof target !== 'string') {\n throw new PistarParseError(`links[${i}] (${id}): missing \"source\" or \"target\"`);\n }\n if (elements.has(id) || links.has(id)) {\n throw new PistarParseError(`links[${i}]: duplicated id \"${id}\"`);\n }\n links.set(id, {\n id,\n kind: type as LinkKind,\n source,\n target,\n ...optional('name', typeof raw.name === 'string' ? raw.name : undefined),\n ...(isRecord(raw.customProperties)\n ? { customProperties: raw.customProperties as CustomProperties }\n : {}),\n ...optional('label', typeof raw.label === 'string' ? raw.label : undefined),\n ...optional('display', displayFor(id) as LinkDisplay | undefined),\n ...optional('extra', extraOf(raw, LINK_KEYS)),\n });\n });\n\n let extraDisplay: Record<string, unknown> | undefined;\n for (const [id, value] of Object.entries(display)) {\n if (!usedDisplay.has(id)) (extraDisplay ??= {})[id] = value;\n }\n\n let diagram: Diagram | undefined;\n if (isRecord(json.diagram)) {\n const d = json.diagram;\n diagram = {\n ...optional('width', typeof d.width === 'number' ? d.width : undefined),\n ...optional('height', typeof d.height === 'number' ? d.height : undefined),\n ...optional('name', typeof d.name === 'string' ? d.name : undefined),\n ...(isRecord(d.customProperties)\n ? { customProperties: d.customProperties as CustomProperties }\n : {}),\n ...optional('extra', extraOf(d, DIAGRAM_KEYS)),\n };\n }\n\n const model: IstarModel = {\n elements,\n links,\n ...optional('diagram', diagram),\n ...optional('tool', typeof json.tool === 'string' ? json.tool : undefined),\n ...optional('istar', typeof json.istar === 'string' ? json.istar : undefined),\n ...optional('saveDate', typeof json.saveDate === 'string' ? json.saveDate : undefined),\n ...optional('extraDisplay', extraDisplay),\n ...optional('extra', extraOf(json, TOP_LEVEL_KEY_SET)),\n };\n layouts.set(model, { keys: Object.keys(json), display: Object.keys(display) });\n return model;\n}\n\nfunction optional<K extends string, V>(key: K, value: V | undefined): { [P in K]?: V } {\n return (value === undefined ? {} : { [key]: value }) as { [P in K]?: V };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Serialization\n\nexport interface ToPistarOptions {\n /**\n * Value for `saveDate`. Defaults to the model's own `saveDate` (so a load/save round trip is\n * lossless), or the current time for models that never had one. Pass `new Date()` when\n * saving an edited model, as piStar does.\n */\n saveDate?: string | Date;\n}\n\nfunction formatDate(date: Date): string {\n // piStar uses the deprecated `toGMTString`, an alias of `toUTCString`.\n return date.toUTCString();\n}\n\nfunction elementJson(element: IstarElement): PistarElementJson {\n return {\n id: element.id,\n text: element.name,\n type: element.kind,\n x: element.x,\n y: element.y,\n ...(element.customProperties ? { customProperties: { ...element.customProperties } } : {}),\n };\n}\n\n/** Builds the save-file object for a model. `toPistar` is this plus `JSON.stringify`. */\nexport function toPistarObject(model: IstarModel, options: ToPistarOptions = {}): PistarFile {\n const actors: PistarActorJson[] = [];\n const orphans: PistarElementJson[] = [];\n const dependencies: PistarDependencyJson[] = [];\n const children = new Map<string, PistarElementJson[]>();\n\n for (const element of model.elements.values()) {\n if (element.parent !== undefined && !isActorKind(element.kind)) {\n let list = children.get(element.parent);\n if (!list) children.set(element.parent, (list = []));\n list.push({ ...elementJson(element), ...element.extra });\n }\n }\n\n for (const element of model.elements.values()) {\n if (isActorKind(element.kind)) {\n actors.push({\n ...elementJson(element),\n nodes: children.get(element.id) ?? [],\n ...element.extra,\n });\n } else if (element.isDependum) {\n // Like piStar, derive depender/dependee from the dependency links.\n const { inbound, outbound } = dependencyLinksOf(model, element.id);\n dependencies.push({\n ...elementJson(element),\n source: inbound?.source ?? element.dependency?.source ?? '',\n target: outbound?.target ?? element.dependency?.target ?? '',\n ...element.extra,\n });\n } else if (element.parent === undefined || !model.elements.has(element.parent)) {\n orphans.push({ ...elementJson(element), ...element.extra });\n }\n }\n\n const links: PistarLinkJson[] = [];\n for (const link of model.links.values()) {\n links.push({\n id: link.id,\n type: link.kind,\n source: link.source,\n target: link.target,\n ...(link.name !== undefined ? { name: link.name } : {}),\n ...(link.customProperties ? { customProperties: { ...link.customProperties } } : {}),\n ...(link.label !== undefined ? { label: link.label } : {}),\n ...link.extra,\n });\n }\n\n const layout = layouts.get(model);\n const display: Record<string, Record<string, unknown>> = {};\n const displayOf = (id: string): Record<string, unknown> | undefined => {\n const owner = model.elements.get(id) ?? model.links.get(id);\n if (owner) return owner.display as Record<string, unknown> | undefined;\n return model.extraDisplay?.[id] as Record<string, unknown> | undefined;\n };\n for (const id of layout?.display ?? []) {\n const entry = displayOf(id);\n if (entry !== undefined) display[id] = { ...entry };\n }\n for (const owner of [...model.elements.values(), ...model.links.values()]) {\n if (owner.display && !(owner.id in display)) display[owner.id] = { ...owner.display };\n }\n for (const [id, entry] of Object.entries(model.extraDisplay ?? {})) {\n if (!(id in display)) display[id] = entry as Record<string, unknown>;\n }\n\n let saveDate: string | undefined;\n if (options.saveDate instanceof Date) saveDate = formatDate(options.saveDate);\n else saveDate = options.saveDate ?? model.saveDate ?? formatDate(new Date());\n\n const d = model.diagram;\n const diagram: PistarDiagramJson | undefined = d && {\n ...(d.width !== undefined ? { width: d.width } : {}),\n ...(d.height !== undefined ? { height: d.height } : {}),\n ...(d.name !== undefined ? { name: d.name } : {}),\n ...(d.customProperties ? { customProperties: { ...d.customProperties } } : {}),\n ...d.extra,\n };\n\n const values: Record<string, unknown> = {\n ...model.extra,\n actors,\n orphans,\n dependencies,\n links,\n display,\n tool: model.tool,\n istar: model.istar,\n saveDate,\n diagram,\n };\n\n // Files written by older piStar versions lack some sections (e.g. `orphans`). Keep them\n // absent while they are empty, so such files round-trip unchanged.\n if (layout) {\n for (const key of ['actors', 'orphans', 'dependencies', 'links', 'display'] as const) {\n const value = values[key] as unknown[] | Record<string, unknown>;\n const empty = Array.isArray(value) ? value.length === 0 : Object.keys(value).length === 0;\n if (empty && !layout.keys.includes(key)) values[key] = undefined;\n }\n }\n\n // Emit keys in the order they had in the source file, then any new ones in piStar's order.\n const order = [...(layout?.keys ?? []), ...TOP_LEVEL_KEYS, ...Object.keys(model.extra ?? {})];\n const file: Record<string, unknown> = {};\n for (const key of order) {\n if (!(key in file) && values[key] !== undefined) file[key] = values[key];\n }\n return file as PistarFile;\n}\n\n/** Serializes a model to piStar's JSON text (2-space indentation, no trailing newline). */\nexport function toPistar(model: IstarModel, options?: ToPistarOptions): string {\n return JSON.stringify(toPistarObject(model, options), null, 2);\n}\n","/**\n * Pure model operations. Each takes a model and returns a new one; inputs are never mutated.\n * The store (`store.ts`) wraps these with undo/redo and change events, and the React layer can\n * use them directly for controlled components.\n *\n * Behaviour follows the piStar web tool (`istarFunctions.js` and its UI):\n * - removing an actor removes its inner elements; removing an element removes its links;\n * - a dependency is two `DependencyLink`s around a dependum, and removing any of the three\n * removes the whole dependency (upstream keeps an `otherHalf` reference for this);\n * - moving an actor moves its inner elements with it (they are JointJS-embedded upstream).\n */\nimport type { LinkCheck } from './constraints';\nimport { canLink } from './constraints';\nimport type { ElementKind, LinkKind, NodeKind } from './metamodel';\nimport { LINK_KIND_INFO, isActorKind, isNodeKind, shortKindName } from './metamodel';\nimport type {\n CustomProperties,\n Diagram,\n ElementDisplay,\n IstarElement,\n IstarLink,\n IstarModel,\n LinkDisplay,\n} from './model';\nimport { dependencyLinksOf } from './model';\nimport { inheritSourceLayout } from './serialization';\n\nexport class ModelOperationError extends Error {\n override name = 'ModelOperationError';\n}\n\n/** Generates ids for new elements and links. piStar uses UUID v4. */\nexport type IdGenerator = () => string;\n\nexport const defaultIdGenerator: IdGenerator = () => {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n // Fallback for non-secure browser contexts, where randomUUID is unavailable.\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n const r = (Math.random() * 16) | 0;\n return (ch === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n};\n\nexport interface OperationContext {\n readonly createId?: IdGenerator;\n}\n\nfunction derive(from: IstarModel, changes: Partial<IstarModel>): IstarModel {\n return inheritSourceLayout(from, { ...from, ...changes });\n}\n\nfunction requireElement(model: IstarModel, id: string): IstarElement {\n const element = model.elements.get(id);\n if (!element) throw new ModelOperationError(`unknown element \"${id}\"`);\n return element;\n}\n\nfunction requireLink(model: IstarModel, id: string): IstarLink {\n const link = model.links.get(id);\n if (!link) throw new ModelOperationError(`unknown link \"${id}\"`);\n return link;\n}\n\nfunction withoutUndefined<T extends object>(value: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Elements\n\nexport interface NewElement {\n readonly kind: ElementKind;\n readonly x: number;\n readonly y: number;\n readonly id?: string;\n /** Defaults to the kind's short name (\"Goal\"), like piStar. */\n readonly name?: string;\n /** Actor to place the element in. Required in practice for iStar nodes (see NodeKindInfo). */\n readonly parent?: string;\n readonly customProperties?: CustomProperties;\n readonly display?: ElementDisplay;\n}\n\nexport function addElement(\n model: IstarModel,\n input: NewElement,\n ctx: OperationContext = {},\n): { model: IstarModel; element: IstarElement } {\n const id = input.id ?? (ctx.createId ?? defaultIdGenerator)();\n if (model.elements.has(id) || model.links.has(id)) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n if (input.parent !== undefined) {\n if (isActorKind(input.kind)) throw new ModelOperationError('actors cannot be nested');\n if (!isActorKind(requireElement(model, input.parent).kind)) {\n throw new ModelOperationError(`parent \"${input.parent}\" is not an actor`);\n }\n }\n const element: IstarElement = withoutUndefined({\n id,\n kind: input.kind,\n name: input.name ?? shortKindName(input.kind),\n x: input.x,\n y: input.y,\n parent: input.parent,\n customProperties: input.customProperties,\n display: input.display,\n });\n const elements = new Map(model.elements).set(id, element);\n return { model: derive(model, { elements }), element };\n}\n\nexport interface ElementPatch {\n readonly name?: string;\n /** Replaces the whole map. Use `null` to remove it. */\n readonly customProperties?: CustomProperties | null;\n /** Merged into the current display; a key set to `undefined` is removed. `null` clears it. */\n readonly display?: { readonly [key: string]: unknown } | null;\n}\n\nfunction mergeDisplay<D extends object>(\n current: D | undefined,\n patch: { readonly [key: string]: unknown } | null | undefined,\n): D | undefined {\n if (patch === undefined) return current;\n if (patch === null) return undefined;\n const merged: Record<string, unknown> = { ...current };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) delete merged[key];\n else merged[key] = value;\n }\n return Object.keys(merged).length > 0 ? (merged as D) : undefined;\n}\n\nexport function updateElement(model: IstarModel, id: string, patch: ElementPatch): IstarModel {\n const current = requireElement(model, id);\n const next: IstarElement = withoutUndefined({\n ...current,\n name: patch.name ?? current.name,\n customProperties:\n patch.customProperties === undefined\n ? current.customProperties\n : (patch.customProperties ?? undefined),\n display: mergeDisplay<ElementDisplay>(current.display, patch.display),\n });\n return derive(model, { elements: new Map(model.elements).set(id, next) });\n}\n\n/**\n * Moves an element to an absolute position. Moving an actor shifts its inner elements by the\n * same offset.\n */\nexport function moveElement(model: IstarModel, id: string, x: number, y: number): IstarModel {\n const current = requireElement(model, id);\n const dx = x - current.x;\n const dy = y - current.y;\n if (dx === 0 && dy === 0) return model;\n const elements = new Map(model.elements);\n elements.set(id, { ...current, x, y });\n if (isActorKind(current.kind)) {\n for (const child of model.elements.values()) {\n if (child.parent === id)\n elements.set(child.id, { ...child, x: child.x + dx, y: child.y + dy });\n }\n }\n return derive(model, { elements });\n}\n\n/**\n * Moves an inner element into another actor (or out of any actor with `null`). The element\n * becomes the actor's last child. Links that become invalid are kept; `validateModel` reports\n * them.\n */\nexport function nestElement(model: IstarModel, id: string, parent: string | null): IstarModel {\n const current = requireElement(model, id);\n if (isActorKind(current.kind)) throw new ModelOperationError('actors cannot be nested');\n if (current.isDependum) throw new ModelOperationError('a dependum cannot be nested');\n if ((current.parent ?? null) === parent) return model;\n if (parent !== null && !isActorKind(requireElement(model, parent).kind)) {\n throw new ModelOperationError(`parent \"${parent}\" is not an actor`);\n }\n const elements = new Map(model.elements);\n elements.delete(id);\n const { parent: _old, ...rest } = current;\n elements.set(id, parent === null ? rest : { ...rest, parent });\n return derive(model, { elements });\n}\n\n/**\n * Removes elements and everything that depends on them: inner elements of removed actors,\n * links touching removed elements, and the rest of any dependency that loses a part.\n */\nexport function removeElements(model: IstarModel, ids: Iterable<string>): IstarModel {\n return removeCascade(model, new Set(ids), new Set());\n}\n\nexport function removeElement(model: IstarModel, id: string): IstarModel {\n requireElement(model, id);\n return removeElements(model, [id]);\n}\n\nfunction removeCascade(\n model: IstarModel,\n elementIds: Set<string>,\n linkIds: Set<string>,\n): IstarModel {\n // Iterate to a fixed point: each round may remove more elements or links.\n let changed = true;\n while (changed) {\n changed = false;\n for (const element of model.elements.values()) {\n if (elementIds.has(element.id)) continue;\n if (element.parent !== undefined && elementIds.has(element.parent)) {\n elementIds.add(element.id);\n changed = true;\n }\n }\n for (const link of model.links.values()) {\n if (linkIds.has(link.id)) continue;\n if (elementIds.has(link.source) || elementIds.has(link.target)) {\n linkIds.add(link.id);\n changed = true;\n }\n }\n // A dependency that lost a half, or its dependum, goes entirely.\n for (const link of model.links.values()) {\n if (!linkIds.has(link.id) || link.kind !== 'istar.DependencyLink') continue;\n for (const end of [link.source, link.target]) {\n const element = model.elements.get(end);\n if (element?.isDependum && !elementIds.has(end)) {\n elementIds.add(end);\n changed = true;\n }\n }\n }\n }\n if (elementIds.size === 0 && linkIds.size === 0) return model;\n const elements = new Map(model.elements);\n for (const id of elementIds) elements.delete(id);\n const links = new Map(model.links);\n for (const id of linkIds) links.delete(id);\n return derive(model, { elements, links });\n}\n\n// ---------------------------------------------------------------------------------------------\n// Links\n\nexport interface NewLink {\n readonly kind: Exclude<LinkKind, 'istar.DependencyLink'>;\n readonly source: string;\n readonly target: string;\n readonly id?: string;\n /** Contribution value: make, help, hurt or break. */\n readonly label?: string;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n}\n\nexport interface ConnectOptions extends OperationContext {\n /** Skip constraint checking (used when loading or scripting known-good data). */\n readonly force?: boolean;\n /**\n * Retry with source and target swapped if the link is invalid as given. Defaults to the\n * metamodel's `tryReversedWhenAdding` (Needed-By and Qualification), as in piStar.\n */\n readonly tryReversed?: boolean;\n}\n\nexport type ConnectResult =\n | { ok: true; model: IstarModel; link: IstarLink; reversed: boolean }\n | Extract<LinkCheck, { ok: false }>;\n\n/** Adds a link between two elements if the iStar constraints allow it. */\nexport function connect(\n model: IstarModel,\n input: NewLink,\n options: ConnectOptions = {},\n): ConnectResult {\n if ((input.kind as LinkKind) === 'istar.DependencyLink') {\n throw new ModelOperationError('use addDependency to create dependencies');\n }\n let { source, target } = input;\n let reversed = false;\n if (!options.force) {\n let check = canLink(model, source, target, input.kind);\n const tryReversed = options.tryReversed ?? LINK_KIND_INFO[input.kind].tryReversedWhenAdding;\n if (!check.ok && tryReversed) {\n const swapped = canLink(model, target, source, input.kind);\n if (swapped.ok) {\n [source, target] = [target, source];\n reversed = true;\n check = swapped;\n }\n }\n if (!check.ok) return check;\n } else {\n requireElement(model, source);\n requireElement(model, target);\n }\n const id = input.id ?? (options.createId ?? defaultIdGenerator)();\n if (model.elements.has(id) || model.links.has(id)) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n const link: IstarLink = withoutUndefined({\n id,\n kind: input.kind,\n source,\n target,\n label: input.label,\n name: input.name,\n customProperties: input.customProperties,\n });\n return {\n ok: true,\n model: derive(model, { links: new Map(model.links).set(id, link) }),\n link,\n reversed,\n };\n}\n\nexport interface NewDependency {\n /** The depender: an actor or one of its inner elements. */\n readonly depender: string;\n /** The dependee: an actor or one of its inner elements. */\n readonly dependee: string;\n readonly dependum: {\n readonly kind: NodeKind;\n readonly name?: string;\n readonly id?: string;\n /** Defaults to the midpoint between depender and dependee, as in piStar. */\n readonly x?: number;\n readonly y?: number;\n readonly customProperties?: CustomProperties;\n };\n readonly linkIds?: readonly [string, string];\n}\n\nexport type AddDependencyResult =\n | {\n ok: true;\n model: IstarModel;\n dependum: IstarElement;\n links: readonly [IstarLink, IstarLink];\n }\n | Extract<LinkCheck, { ok: false }>;\n\n/** Adds depender → dependum → dependee. */\nexport function addDependency(\n model: IstarModel,\n input: NewDependency,\n options: Omit<ConnectOptions, 'tryReversed'> = {},\n): AddDependencyResult {\n if (!isNodeKind(input.dependum.kind)) {\n throw new ModelOperationError(`${input.dependum.kind} cannot be a dependum`);\n }\n if (!options.force) {\n const check = canLink(model, input.depender, input.dependee, 'istar.DependencyLink');\n if (!check.ok) return check;\n }\n const depender = requireElement(model, input.depender);\n const dependee = requireElement(model, input.dependee);\n const createId = options.createId ?? defaultIdGenerator;\n const added = addElement(\n model,\n {\n kind: input.dependum.kind,\n id: input.dependum.id,\n name: input.dependum.name,\n x: input.dependum.x ?? (depender.x + dependee.x) / 2,\n y: input.dependum.y ?? (depender.y + dependee.y) / 2,\n customProperties: input.dependum.customProperties,\n },\n { createId },\n );\n const dependum: IstarElement = { ...added.element, isDependum: true };\n const [id1, id2] = input.linkIds ?? [createId(), createId()];\n const first: IstarLink = {\n id: id1,\n kind: 'istar.DependencyLink',\n source: depender.id,\n target: dependum.id,\n };\n const second: IstarLink = {\n id: id2,\n kind: 'istar.DependencyLink',\n source: dependum.id,\n target: dependee.id,\n };\n for (const id of [id1, id2]) {\n if (added.model.elements.has(id) || added.model.links.has(id) || id1 === id2) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n }\n return {\n ok: true,\n model: derive(model, {\n elements: new Map(added.model.elements).set(dependum.id, dependum),\n links: new Map(model.links).set(id1, first).set(id2, second),\n }),\n dependum,\n links: [first, second],\n };\n}\n\n/** Removes a link. Removing either half of a dependency removes the whole dependency. */\nexport function disconnect(model: IstarModel, id: string): IstarModel {\n requireLink(model, id);\n return removeCascade(model, new Set(), new Set([id]));\n}\n\nexport interface LinkPatch {\n /** `null` removes it. */\n readonly label?: string | null;\n readonly name?: string | null;\n readonly customProperties?: CustomProperties | null;\n readonly display?: { readonly [key: string]: unknown } | null;\n}\n\nfunction pick<T>(value: T | null | undefined, fallback: T | undefined): T | undefined {\n return value === undefined ? fallback : (value ?? undefined);\n}\n\nexport function updateLink(model: IstarModel, id: string, patch: LinkPatch): IstarModel {\n const current = requireLink(model, id);\n const next: IstarLink = withoutUndefined({\n ...current,\n label: pick(patch.label, current.label),\n name: pick(patch.name, current.name),\n customProperties: pick(patch.customProperties, current.customProperties),\n display: mergeDisplay<LinkDisplay>(current.display, patch.display),\n });\n return derive(model, { links: new Map(model.links).set(id, next) });\n}\n\n// ---------------------------------------------------------------------------------------------\n// Diagram\n\nexport function updateDiagram(model: IstarModel, patch: Partial<Diagram>): IstarModel {\n return derive(model, { diagram: withoutUndefined({ ...model.diagram, ...patch }) });\n}\n\n/** Where dependency depender/dependee currently point (see `dependencyLinksOf`). */\nexport function dependencyEnds(\n model: IstarModel,\n dependumId: string,\n): { depender?: string; dependee?: string } {\n const { inbound, outbound } = dependencyLinksOf(model, dependumId);\n const fallback = model.elements.get(dependumId)?.dependency;\n return {\n depender: inbound?.source ?? fallback?.source,\n dependee: outbound?.target ?? fallback?.target,\n };\n}\n","/**\n * An event-emitting store around an immutable `IstarModel`, with undo/redo.\n *\n * Every mutation produces a new model snapshot; history is a stack of snapshots, which is cheap\n * because unchanged elements and links are shared between snapshots. This replaces piStar's\n * `undoManager.js`, which stacked hand-written undo closures.\n *\n * `subscribe` + `getModel` match React's `useSyncExternalStore` contract.\n */\nimport type { LinkCheck } from './constraints';\nimport { canLink } from './constraints';\nimport type { LinkKind } from './metamodel';\nimport type { Diagram, IstarElement, IstarModel } from './model';\nimport { createEmptyModel } from './model';\nimport type {\n ConnectOptions,\n ElementPatch,\n IdGenerator,\n LinkPatch,\n NewDependency,\n NewElement,\n NewLink,\n} from './operations';\nimport * as ops from './operations';\n\n/** What happened, for listeners that want more than the new snapshot. */\nexport type ModelChange =\n | { type: 'addElement'; id: string }\n | { type: 'updateElement'; id: string; patch: ElementPatch }\n | { type: 'moveElement'; id: string; x: number; y: number }\n | { type: 'nestElement'; id: string; parent: string | null }\n | { type: 'removeElements'; ids: readonly string[] }\n | { type: 'connect'; id: string }\n | { type: 'addDependency'; dependumId: string; linkIds: readonly [string, string] }\n | { type: 'updateLink'; id: string; patch: LinkPatch }\n | { type: 'disconnect'; id: string }\n | { type: 'updateDiagram'; patch: Partial<Diagram> }\n | { type: 'replace' };\n\nexport interface ModelChangeEvent {\n readonly model: IstarModel;\n readonly previous: IstarModel;\n /** `undo`/`redo`/`load` carry no changes; a transaction carries all of its changes. */\n readonly changes: readonly ModelChange[];\n readonly source: 'edit' | 'undo' | 'redo' | 'load';\n}\n\nexport type ModelListener = (event: ModelChangeEvent) => void;\n\nexport interface ModelStoreOptions {\n readonly createId?: IdGenerator;\n /** Maximum number of undo steps kept. Default 100. */\n readonly historyLimit?: number;\n}\n\nexport interface ModelStore {\n getModel(): IstarModel;\n /** Returns an unsubscribe function. */\n subscribe(listener: ModelListener): () => void;\n\n canLink(source: string | IstarElement, target: string | IstarElement, kind: LinkKind): LinkCheck;\n\n addElement(input: NewElement): IstarElement;\n updateElement(id: string, patch: ElementPatch): void;\n moveElement(id: string, x: number, y: number): void;\n nestElement(id: string, parent: string | null): void;\n removeElement(id: string): void;\n removeElements(ids: Iterable<string>): void;\n setCollapsed(actorId: string, collapsed: boolean): void;\n\n connect(input: NewLink, options?: Omit<ConnectOptions, 'createId'>): ops.ConnectResult;\n addDependency(\n input: NewDependency,\n options?: Omit<ConnectOptions, 'createId' | 'tryReversed'>,\n ): ops.AddDependencyResult;\n updateLink(id: string, patch: LinkPatch): void;\n disconnect(id: string): void;\n updateDiagram(patch: Partial<Diagram>): void;\n\n /** Replaces the model as one undoable edit. */\n replace(model: IstarModel): void;\n /** Replaces the model and clears history (like opening a file in piStar). */\n load(model: IstarModel): void;\n\n /**\n * Groups several edits into one undo step and one change event. Nested calls join the\n * outermost transaction. If `fn` throws, the model is rolled back.\n */\n transaction<T>(fn: () => T): T;\n\n undo(): boolean;\n redo(): boolean;\n canUndo(): boolean;\n canRedo(): boolean;\n clearHistory(): void;\n}\n\nexport function createModelStore(\n initial: IstarModel = createEmptyModel(),\n options: ModelStoreOptions = {},\n): ModelStore {\n const limit = options.historyLimit ?? 100;\n const ctx = { createId: options.createId ?? ops.defaultIdGenerator };\n const listeners = new Set<ModelListener>();\n let model = initial;\n let past: IstarModel[] = [];\n let future: IstarModel[] = [];\n let tx: { start: IstarModel; changes: ModelChange[]; depth: number } | undefined;\n\n const emit = (event: ModelChangeEvent): void => {\n for (const listener of listeners) listener(event);\n };\n\n const commit = (next: IstarModel, change: ModelChange): void => {\n if (next === model) return;\n if (tx) {\n model = next;\n tx.changes.push(change);\n return;\n }\n const previous = model;\n past.push(previous);\n if (past.length > limit) past = past.slice(past.length - limit);\n future = [];\n model = next;\n emit({ model, previous, changes: [change], source: 'edit' });\n };\n\n const store: ModelStore = {\n getModel: () => model,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n\n canLink: (source, target, kind) => canLink(model, source, target, kind),\n\n addElement(input) {\n const result = ops.addElement(model, input, ctx);\n commit(result.model, { type: 'addElement', id: result.element.id });\n return result.element;\n },\n updateElement(id, patch) {\n commit(ops.updateElement(model, id, patch), { type: 'updateElement', id, patch });\n },\n moveElement(id, x, y) {\n commit(ops.moveElement(model, id, x, y), { type: 'moveElement', id, x, y });\n },\n nestElement(id, parent) {\n commit(ops.nestElement(model, id, parent), { type: 'nestElement', id, parent });\n },\n removeElement(id) {\n commit(ops.removeElement(model, id), { type: 'removeElements', ids: [id] });\n },\n removeElements(ids) {\n const list = [...ids];\n commit(ops.removeElements(model, list), { type: 'removeElements', ids: list });\n },\n setCollapsed(actorId, collapsed) {\n const patch = { display: { collapsed: collapsed ? true : undefined } };\n commit(ops.updateElement(model, actorId, patch), {\n type: 'updateElement',\n id: actorId,\n patch,\n });\n },\n\n connect(input, connectOptions) {\n const result = ops.connect(model, input, { ...connectOptions, ...ctx });\n if (result.ok) commit(result.model, { type: 'connect', id: result.link.id });\n return result;\n },\n addDependency(input, dependencyOptions) {\n const result = ops.addDependency(model, input, { ...dependencyOptions, ...ctx });\n if (result.ok) {\n commit(result.model, {\n type: 'addDependency',\n dependumId: result.dependum.id,\n linkIds: [result.links[0].id, result.links[1].id],\n });\n }\n return result;\n },\n updateLink(id, patch) {\n commit(ops.updateLink(model, id, patch), { type: 'updateLink', id, patch });\n },\n disconnect(id) {\n commit(ops.disconnect(model, id), { type: 'disconnect', id });\n },\n updateDiagram(patch) {\n commit(ops.updateDiagram(model, patch), { type: 'updateDiagram', patch });\n },\n\n replace(next) {\n commit(next, { type: 'replace' });\n },\n load(next) {\n if (tx) throw new ops.ModelOperationError('cannot load inside a transaction');\n const previous = model;\n model = next;\n past = [];\n future = [];\n emit({ model, previous, changes: [], source: 'load' });\n },\n\n transaction<T>(fn: () => T): T {\n if (tx) {\n tx.depth++;\n try {\n return fn();\n } finally {\n tx.depth--;\n }\n }\n tx = { start: model, changes: [], depth: 1 };\n let result: T;\n try {\n result = fn();\n } catch (error) {\n model = tx.start;\n tx = undefined;\n throw error;\n }\n const { start, changes } = tx;\n tx = undefined;\n if (model !== start) {\n past.push(start);\n if (past.length > limit) past = past.slice(past.length - limit);\n future = [];\n emit({ model, previous: start, changes, source: 'edit' });\n }\n return result;\n },\n\n undo() {\n const previous = past.pop();\n if (!previous || tx) return false;\n future.push(model);\n const current = model;\n model = previous;\n emit({ model, previous: current, changes: [], source: 'undo' });\n return true;\n },\n redo() {\n const next = future.pop();\n if (!next || tx) return false;\n past.push(model);\n const current = model;\n model = next;\n emit({ model, previous: current, changes: [], source: 'redo' });\n return true;\n },\n canUndo: () => past.length > 0,\n canRedo: () => future.length > 0,\n clearHistory() {\n past = [];\n future = [];\n },\n };\n return store;\n}\n","import type { ElementKind, LinkKind } from './metamodel';\nimport type { CustomProperties, IstarModel } from './model';\n\nexport type PropertyResult<T> = { ok: true; value: T } | { ok: false; error: string };\n\nexport interface PropertyOptions<T> {\n default?: T;\n optional?: boolean;\n label?: string;\n description?: string;\n}\n\nexport interface PropertyType<T> {\n readonly type: 'string' | 'number' | 'boolean' | 'enum';\n readonly options: PropertyOptions<T>;\n readonly values?: readonly string[];\n readonly integer?: boolean;\n readonly min?: number;\n readonly max?: number;\n parse(raw: string): PropertyResult<T>;\n serialize(value: T): string;\n}\n\nexport function string(options?: PropertyOptions<string>): PropertyType<string> {\n const opts: PropertyOptions<string> = options ?? {};\n return {\n type: 'string',\n options: opts,\n parse(raw: string): PropertyResult<string> {\n return { ok: true, value: raw };\n },\n serialize(value: string): string {\n return value;\n },\n };\n}\n\nexport function number(\n options?: PropertyOptions<number> & { integer?: boolean; min?: number; max?: number },\n): PropertyType<number> {\n const opts: PropertyOptions<number> = options ?? {};\n const integer = options?.integer;\n const min = options?.min;\n const max = options?.max;\n return {\n type: 'number',\n options: opts,\n integer,\n min,\n max,\n parse(raw: string): PropertyResult<number> {\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { ok: false, error: 'must be a finite number' };\n }\n if (integer && !Number.isInteger(value)) {\n return { ok: false, error: 'must be an integer' };\n }\n if (min !== undefined && value < min) {\n return { ok: false, error: `must be at least ${min}` };\n }\n if (max !== undefined && value > max) {\n return { ok: false, error: `must be at most ${max}` };\n }\n return { ok: true, value };\n },\n serialize(value: number): string {\n return String(value);\n },\n };\n}\n\nexport function boolean(options?: PropertyOptions<boolean>): PropertyType<boolean> {\n const opts: PropertyOptions<boolean> = options ?? {};\n return {\n type: 'boolean',\n options: opts,\n parse(raw: string): PropertyResult<boolean> {\n if (raw === 'true') return { ok: true, value: true };\n if (raw === 'false') return { ok: true, value: false };\n return { ok: false, error: 'must be true or false' };\n },\n serialize(value: boolean): string {\n return value ? 'true' : 'false';\n },\n };\n}\n\nexport function enumOf<const V extends readonly string[]>(\n values: V,\n options?: PropertyOptions<V[number]>,\n): PropertyType<V[number]> {\n const opts: PropertyOptions<V[number]> = options ?? {};\n return {\n type: 'enum',\n options: opts,\n values,\n parse(raw: string): PropertyResult<V[number]> {\n if ((values as readonly string[]).includes(raw)) {\n return { ok: true, value: raw as V[number] };\n }\n return { ok: false, error: `must be one of: ${values.join(', ')}` };\n },\n serialize(value: V[number]): string {\n return value;\n },\n };\n}\n\nexport const prop: {\n string: typeof string;\n number: typeof number;\n boolean: typeof boolean;\n enum: typeof enumOf;\n} = {\n string,\n number,\n boolean,\n enum: enumOf,\n};\n\nexport type PropertyShape = Record<string, PropertyType<unknown>>;\n\nexport type InferProperties<S extends PropertyShape> = {\n [K in keyof S]: S[K] extends PropertyType<infer T> ? T : never;\n};\n\nexport interface PropertyIssue {\n key: string;\n message: string;\n}\n\nexport interface PropertySchema<S extends PropertyShape = PropertyShape> {\n readonly kind: ElementKind | LinkKind;\n readonly shape: S;\n read(source: CustomProperties | undefined | PropertyOwner): {\n values: Partial<InferProperties<S>>;\n issues: PropertyIssue[];\n };\n validate(source: CustomProperties | undefined | PropertyOwner): PropertyIssue[];\n write(\n current: CustomProperties | undefined,\n patch: { [K in keyof S]?: InferProperties<S>[K] | undefined },\n ): CustomProperties;\n defaults(): CustomProperties;\n}\n\n/** An element or link, read through its `customProperties`. */\nexport interface PropertyOwner {\n readonly kind: string;\n readonly customProperties?: CustomProperties;\n}\n\nexport interface ModelPropertyIssue extends PropertyIssue {\n id: string;\n}\n\ntype PropertySource = CustomProperties | undefined | PropertyOwner;\n\nfunction isCustomPropertiesRecord(source: NonNullable<PropertySource>): source is CustomProperties {\n // Elements and links are passed whole, possibly without `customProperties`; recognize them by\n // their `istar.*` kind and numeric/structural fields a bag of strings can't have.\n if ('customProperties' in source) return false;\n const owner = source as { kind?: unknown; x?: unknown; source?: unknown; target?: unknown };\n const isModelObject =\n typeof owner.kind === 'string' &&\n owner.kind.startsWith('istar.') &&\n (typeof owner.x === 'number' || (owner.source !== undefined && owner.target !== undefined));\n return !isModelObject;\n}\n\nfunction resolveCustomProperties(source: PropertySource): CustomProperties | undefined {\n if (source === undefined) return undefined;\n if (isCustomPropertiesRecord(source)) return source;\n return source.customProperties;\n}\n\nfunction isRequired(options: PropertyOptions<unknown>): boolean {\n return options.optional !== true && options.default === undefined;\n}\n\nfunction emptyMeansAbsent(\n type: PropertyType<unknown>['type'],\n optional: boolean | undefined,\n): boolean {\n return type !== 'string' && optional === true;\n}\n\nfunction readShape<S extends PropertyShape>(\n shape: S,\n source: PropertySource,\n): { values: Partial<InferProperties<S>>; issues: PropertyIssue[] } {\n const custom = resolveCustomProperties(source);\n const values: Partial<InferProperties<S>> = {};\n const issues: PropertyIssue[] = [];\n\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n const field = shape[key];\n if (!field) continue;\n const opts = field.options;\n const hasKey = custom !== undefined && Object.prototype.hasOwnProperty.call(custom, key);\n const raw = hasKey ? custom[key] : undefined;\n\n if (raw === undefined) {\n if (opts.default !== undefined) {\n (values as Record<string, unknown>)[key] = opts.default;\n } else if (isRequired(opts)) {\n issues.push({ key, message: 'is required' });\n }\n continue;\n }\n\n if (raw === '' && field.type !== 'string') {\n if (emptyMeansAbsent(field.type, opts.optional)) {\n if (opts.default !== undefined) {\n (values as Record<string, unknown>)[key] = opts.default;\n }\n continue;\n }\n issues.push({\n key,\n message:\n field.type === 'boolean'\n ? 'must be true or false'\n : field.type === 'enum'\n ? `must be one of: ${field.values?.join(', ') ?? ''}`\n : 'must be a finite number',\n });\n continue;\n }\n\n const parsed = field.parse(raw);\n if (!parsed.ok) {\n issues.push({ key, message: parsed.error });\n continue;\n }\n (values as Record<string, unknown>)[key] = parsed.value;\n }\n\n return { values, issues };\n}\n\nexport function defineProperties<const S extends PropertyShape>(\n kind: ElementKind | LinkKind,\n shape: S,\n options?: { validate?: (values: Partial<InferProperties<S>>) => PropertyIssue[] },\n): PropertySchema<S> {\n const crossValidate = options?.validate;\n\n return {\n kind,\n shape,\n read(source: PropertySource): { values: Partial<InferProperties<S>>; issues: PropertyIssue[] } {\n return readShape(shape, source);\n },\n validate(source: PropertySource): PropertyIssue[] {\n const { values, issues } = readShape(shape, source);\n const cross = crossValidate ? crossValidate(values) : [];\n return [...issues, ...cross];\n },\n write(\n current: CustomProperties | undefined,\n patch: { [K in keyof S]?: InferProperties<S>[K] | undefined },\n ): CustomProperties {\n const result: Record<string, string> = {};\n const seen = new Set<string>();\n\n if (current) {\n for (const [key, value] of Object.entries(current)) {\n if (Object.prototype.hasOwnProperty.call(patch, key)) {\n const patched = patch[key as keyof S];\n if (patched === undefined) {\n continue;\n }\n const field = shape[key];\n if (field) {\n result[key] = field.serialize(patched as never);\n }\n } else {\n result[key] = value;\n }\n seen.add(key);\n }\n }\n\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n if (seen.has(key)) continue;\n if (!Object.prototype.hasOwnProperty.call(patch, key)) continue;\n const patched = patch[key];\n if (patched === undefined) continue;\n const field = shape[key];\n if (field) {\n result[key] = field.serialize(patched as never);\n }\n }\n\n return result;\n },\n defaults(): CustomProperties {\n const result: Record<string, string> = {};\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n const field = shape[key];\n if (!field) continue;\n const def = field.options.default;\n if (def !== undefined) {\n result[key] = field.serialize(def as never);\n }\n }\n return result;\n },\n };\n}\n\nexport function validateModelProperties(\n model: IstarModel,\n schemas: readonly PropertySchema[],\n): ModelPropertyIssue[] {\n const byKind = new Map<ElementKind | LinkKind, PropertySchema[]>();\n for (const schema of schemas) {\n const list = byKind.get(schema.kind) ?? [];\n list.push(schema);\n byKind.set(schema.kind, list);\n }\n\n const issues: ModelPropertyIssue[] = [];\n\n for (const element of model.elements.values()) {\n const kindSchemas = byKind.get(element.kind);\n if (!kindSchemas) continue;\n for (const schema of kindSchemas) {\n for (const issue of schema.validate(element)) {\n issues.push({ ...issue, id: element.id });\n }\n }\n }\n\n for (const link of model.links.values()) {\n const kindSchemas = byKind.get(link.kind);\n if (!kindSchemas) continue;\n for (const schema of kindSchemas) {\n for (const issue of schema.validate(link)) {\n issues.push({ ...issue, id: link.id });\n }\n }\n }\n\n return issues;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ops.defaultIdGenerator","ops.addElement","ops.updateElement","ops.moveElement","ops.nestElement","ops.removeElement","ops.removeElements","ops.connect","ops.addDependency","ops.updateLink","ops.disconnect","ops.updateDiagram","ops.ModelOperationError"],"sources":["../src/metamodel.ts","../src/metamodels.ts","../src/model.ts","../src/constraints.ts","../src/serialization.ts","../src/operations.ts","../src/store.ts","../src/properties.ts"],"sourcesContent":["/**\n * The iStar 2.0 metamodel, ported from piStar's `tool/language/metamodel.js`.\n *\n * Kind names carry the `istar.` prefix exactly as they appear in piStar save files.\n */\n\nexport const ISTAR_PREFIX = 'istar';\nexport const METAMODEL_VERSION = '0.2';\n\n/** Containers: elements that hold inner elements (piStar `metamodel.containers`). */\nexport const ACTOR_KINDS = ['istar.Actor', 'istar.Agent', 'istar.Role'] as const;\nexport type ActorKind = (typeof ACTOR_KINDS)[number];\n\n/** Intentional elements (piStar `metamodel.nodes`). */\nexport const NODE_KINDS = ['istar.Goal', 'istar.Quality', 'istar.Resource', 'istar.Task'] as const;\nexport type NodeKind = (typeof NODE_KINDS)[number];\n\nexport type ElementKind = ActorKind | NodeKind;\nexport const ELEMENT_KINDS: readonly ElementKind[] = [...ACTOR_KINDS, ...NODE_KINDS];\n\n/** Links between two containers (piStar `metamodel.containerLinks`). */\nexport const ACTOR_LINK_KINDS = ['istar.IsALink', 'istar.ParticipatesInLink'] as const;\nexport type ActorLinkKind = (typeof ACTOR_LINK_KINDS)[number];\n\n/** Links that connect two containers through a dependum (piStar `metamodel.dependencyLinks`). */\nexport const DEPENDENCY_LINK_KINDS = ['istar.DependencyLink'] as const;\nexport type DependencyLinkKind = (typeof DEPENDENCY_LINK_KINDS)[number];\n\n/** Links between two intentional elements (piStar `metamodel.nodeLinks`). */\nexport const NODE_LINK_KINDS = [\n 'istar.AndRefinementLink',\n 'istar.OrRefinementLink',\n 'istar.NeededByLink',\n 'istar.QualificationLink',\n 'istar.ContributionLink',\n] as const;\nexport type NodeLinkKind = (typeof NODE_LINK_KINDS)[number];\n\nexport type LinkKind = ActorLinkKind | DependencyLinkKind | NodeLinkKind;\nexport const LINK_KINDS: readonly LinkKind[] = [\n ...ACTOR_LINK_KINDS,\n ...DEPENDENCY_LINK_KINDS,\n ...NODE_LINK_KINDS,\n];\n\n/** Possible values of a Contribution link's `label`. */\nexport const CONTRIBUTION_LABELS = ['make', 'help', 'hurt', 'break'] as const;\nexport type ContributionLabel = (typeof CONTRIBUTION_LABELS)[number];\n\nexport interface NodeKindInfo {\n /** Can be added inside an actor. */\n readonly canBeInnerElement: boolean;\n /** Can be the dependum of a dependency. */\n readonly canBeDependum: boolean;\n /** Can be placed directly on the diagram, outside any actor. */\n readonly canBeOnPaper: boolean;\n}\n\nexport interface LinkKindInfo {\n /** Fixed text drawn on the link (e.g. \"is-a\"). */\n readonly label?: string;\n /** piStar retries with source and target swapped when the first attempt is invalid. */\n readonly tryReversedWhenAdding?: boolean;\n /** The link carries a user-selectable label, stored as `label` in the save file. */\n readonly changeableLabel?: boolean;\n readonly possibleLabels?: readonly string[];\n}\n\nconst innerNode: NodeKindInfo = {\n canBeInnerElement: true,\n canBeDependum: true,\n canBeOnPaper: false,\n};\n\nexport const NODE_KIND_INFO: Readonly<Record<NodeKind, NodeKindInfo>> = {\n 'istar.Goal': innerNode,\n 'istar.Quality': innerNode,\n 'istar.Resource': innerNode,\n 'istar.Task': innerNode,\n};\n\nexport const LINK_KIND_INFO: Readonly<Record<LinkKind, LinkKindInfo>> = {\n 'istar.IsALink': { label: 'is-a' },\n 'istar.ParticipatesInLink': { label: 'participates-in' },\n 'istar.DependencyLink': {},\n 'istar.AndRefinementLink': {},\n 'istar.OrRefinementLink': {},\n 'istar.NeededByLink': { tryReversedWhenAdding: true },\n 'istar.QualificationLink': { tryReversedWhenAdding: true },\n 'istar.ContributionLink': { changeableLabel: true, possibleLabels: CONTRIBUTION_LABELS },\n};\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/**\n * Default sizes of each element kind, from piStar's `shapes.js`. For actors this is the\n * initial boundary size; the collapsed actor symbol is a circle of radius 40.\n */\nexport const DEFAULT_ELEMENT_SIZE: Readonly<Record<ElementKind, Size>> = {\n 'istar.Actor': { width: 200, height: 120 },\n 'istar.Agent': { width: 200, height: 120 },\n 'istar.Role': { width: 200, height: 120 },\n 'istar.Goal': { width: 90, height: 35 },\n 'istar.Quality': { width: 90, height: 55 },\n 'istar.Resource': { width: 90, height: 35 },\n 'istar.Task': { width: 95, height: 36 },\n};\n\nconst actorKinds: ReadonlySet<string> = new Set(ACTOR_KINDS);\nconst nodeKinds: ReadonlySet<string> = new Set(NODE_KINDS);\nconst elementKinds: ReadonlySet<string> = new Set(ELEMENT_KINDS);\nconst linkKinds: ReadonlySet<string> = new Set(LINK_KINDS);\nconst actorLinkKinds: ReadonlySet<string> = new Set(ACTOR_LINK_KINDS);\nconst nodeLinkKinds: ReadonlySet<string> = new Set(NODE_LINK_KINDS);\n\nexport function isActorKind(kind: string): kind is ActorKind {\n return actorKinds.has(kind);\n}\nexport function isNodeKind(kind: string): kind is NodeKind {\n return nodeKinds.has(kind);\n}\nexport function isElementKind(kind: string): kind is ElementKind {\n return elementKinds.has(kind);\n}\nexport function isLinkKind(kind: string): kind is LinkKind {\n return linkKinds.has(kind);\n}\nexport function isActorLinkKind(kind: string): kind is ActorLinkKind {\n return actorLinkKinds.has(kind);\n}\nexport function isNodeLinkKind(kind: string): kind is NodeLinkKind {\n return nodeLinkKinds.has(kind);\n}\nexport function isDependencyLinkKind(kind: string): kind is DependencyLinkKind {\n return kind === 'istar.DependencyLink';\n}\nexport function isContributionLabel(value: string): value is ContributionLabel {\n return (CONTRIBUTION_LABELS as readonly string[]).includes(value);\n}\n\n/** `'istar.Goal'` → `'Goal'` */\nexport function shortKindName(kind: ElementKind | LinkKind): string {\n return kind.slice(ISTAR_PREFIX.length + 1);\n}\n","/**\n * Metamodels as values: iStar 2.0 (`ISTAR_2_0`) plus dialects built with `extendMetamodel`,\n * which add element kinds (e.g. iStar4RationalAgents' Planning and Plan) and link kinds.\n *\n * The constants in `metamodel.ts` (`ELEMENT_KINDS`, `NODE_KIND_INFO`, …) describe iStar 2.0 and\n * stay as they are; this module builds `ISTAR_2_0` from them. Everything that accepts a\n * metamodel defaults to `ISTAR_2_0`, so code that never mentions one behaves exactly as before.\n *\n * Extensions follow piStar-ext (Gonçalves et al., iStar 2020): a new construct has a name, a\n * node-or-link category and, for links, the kinds it may connect. Two additions make them\n * usable as a library: `behavesLike` lets a new kind reuse an existing kind's link rules\n * (Planning behaves like a Task, so it can be refined and be a dependum), and kinds are\n * namespaced (`rationalAgents.Planning`), with `istar.` reserved for iStar 2.0.\n */\nimport type { LinkCheck, LinkRuleContext } from './constraints';\nimport type { ElementKind, LinkKind, LinkKindInfo, NodeKindInfo, Size } from './metamodel';\nimport {\n ACTOR_KINDS,\n ACTOR_LINK_KINDS,\n DEFAULT_ELEMENT_SIZE,\n DEPENDENCY_LINK_KINDS,\n ISTAR_PREFIX,\n LINK_KIND_INFO,\n NODE_KINDS,\n NODE_KIND_INFO,\n NODE_LINK_KINDS,\n} from './metamodel';\n\nexport type ElementCategory = 'actor' | 'node';\nexport type LinkCategory = 'actor' | 'node' | 'dependency';\n\n/** A resolved element kind of a metamodel. */\nexport interface ElementKindDefinition<K extends string = string> {\n readonly kind: K;\n readonly category: ElementCategory;\n /** Human-readable name, e.g. \"Goal\" or \"Planning\". */\n readonly label: string;\n /** Default size; for actors the initial boundary size. */\n readonly size: Size;\n /** Containment rules (nodes only; actors have none). */\n readonly info?: NodeKindInfo;\n /** The kind whose link rules this kind follows (built-in kinds have none). */\n readonly behavesLike?: string;\n /** The `type` written in piStar files. Equal to `kind` unless declared otherwise. */\n readonly pistarType: string;\n /** Name of the extension that declared it; absent for iStar 2.0 kinds. */\n readonly extension?: string;\n}\n\n/**\n * Declarative link rules, as piStar-ext's \"Create a new Construct\" dialog collects them:\n * which kinds may be the source and target. Entries are kind names (`istar.Goal`,\n * `rationalAgents.Plan`) or categories (`node`, `actor`, `*`). A kind name also matches kinds\n * that behave like it, so `istar.Task` accepts a Planning that behaves like a Task.\n */\nexport interface LinkRules {\n readonly sources: readonly string[];\n readonly targets: readonly string[];\n /**\n * Source and target must belong to the same actor (iStar 2.0 Guide, page 14). Default true\n * for node links, ignored for actor links.\n */\n readonly sameActor?: boolean;\n /** Allow a dependum as source or target. Default false. */\n readonly allowDependum?: boolean;\n /** Allow a link from an element onto itself. Default false. */\n readonly allowSelf?: boolean;\n /**\n * At most one link `'kind'` of this kind, or `'any'` link at all, between the same two\n * elements (in either direction); `false` for no limit. Default `'kind'`.\n */\n readonly unique?: 'kind' | 'any' | false;\n}\n\n/** A resolved link kind of a metamodel. */\nexport interface LinkKindDefinition<K extends string = string> {\n readonly kind: K;\n readonly category: LinkCategory;\n readonly label: string;\n readonly info: LinkKindInfo;\n /** The link kind whose rules (and meaning, for other rules) this kind takes on. */\n readonly behavesLike?: string;\n /** Declarative rules, for link kinds that don't behave like another kind. */\n readonly rules?: LinkRules;\n /** An extra predicate, checked after the inherited or declarative rules pass. */\n readonly check?: (context: LinkRuleContext) => LinkCheck;\n readonly pistarType: string;\n readonly extension?: string;\n}\n\n/** A metamodel: the element and link kinds a model may use, and their rules. */\nexport interface Metamodel<EK extends string = ElementKind, LK extends string = LinkKind> {\n /** `istar-2.0`, followed by the names of the extensions applied, e.g. `istar-2.0+rationalAgents`. */\n readonly name: string;\n readonly extensions: readonly string[];\n /** In declaration order: iStar 2.0 kinds first, then each extension's. */\n readonly elements: ReadonlyMap<EK, ElementKindDefinition<EK>>;\n readonly links: ReadonlyMap<LK, LinkKindDefinition<LK>>;\n /** `type` in piStar files → kind. */\n readonly elementsByPistarType: ReadonlyMap<string, EK>;\n readonly linksByPistarType: ReadonlyMap<string, LK>;\n}\n\n/** The kinds of a metamodel, as type-level unions. */\nexport type ElementKindOf<M> = M extends Metamodel<infer EK, string> ? EK : never;\nexport type LinkKindOf<M> = M extends Metamodel<string, infer LK> ? LK : never;\n\n/** A metamodel of any dialect, for code that handles every kind generically. */\nexport type AnyMetamodel = Metamodel<string, string>;\n\n// ---------------------------------------------------------------------------------------------\n// iStar 2.0\n\nfunction shortName(kind: string): string {\n const dot = kind.indexOf('.');\n return dot === -1 ? kind : kind.slice(dot + 1);\n}\n\nfunction buildIstar(): Metamodel {\n const elements = new Map<ElementKind, ElementKindDefinition<ElementKind>>();\n for (const kind of ACTOR_KINDS) {\n elements.set(kind, {\n kind,\n category: 'actor',\n label: shortName(kind),\n size: DEFAULT_ELEMENT_SIZE[kind],\n pistarType: kind,\n });\n }\n for (const kind of NODE_KINDS) {\n elements.set(kind, {\n kind,\n category: 'node',\n label: shortName(kind),\n size: DEFAULT_ELEMENT_SIZE[kind],\n info: NODE_KIND_INFO[kind],\n pistarType: kind,\n });\n }\n const links = new Map<LinkKind, LinkKindDefinition<LinkKind>>();\n const labels: Record<LinkKind, string> = {\n 'istar.IsALink': 'Is-A',\n 'istar.ParticipatesInLink': 'Participates-In',\n 'istar.DependencyLink': 'Dependency',\n 'istar.AndRefinementLink': 'And-Refinement',\n 'istar.OrRefinementLink': 'Or-Refinement',\n 'istar.NeededByLink': 'Needed-By',\n 'istar.QualificationLink': 'Qualification',\n 'istar.ContributionLink': 'Contribution',\n };\n const add = (kinds: readonly LinkKind[], category: LinkCategory): void => {\n for (const kind of kinds) {\n links.set(kind, {\n kind,\n category,\n label: labels[kind],\n info: LINK_KIND_INFO[kind],\n pistarType: kind,\n });\n }\n };\n add(ACTOR_LINK_KINDS, 'actor');\n add(DEPENDENCY_LINK_KINDS, 'dependency');\n add(NODE_LINK_KINDS, 'node');\n return {\n name: 'istar-2.0',\n extensions: [],\n elements,\n links,\n elementsByPistarType: new Map([...elements.keys()].map((k) => [k, k])),\n linksByPistarType: new Map([...links.keys()].map((k) => [k, k])),\n };\n}\n\n/** iStar 2.0, as the piStar tool implements it. The default metamodel everywhere. */\nexport const ISTAR_2_0: Metamodel = buildIstar();\n\n// ---------------------------------------------------------------------------------------------\n// Extensions\n\nexport interface ElementKindDeclaration<K extends string = string> {\n /** Namespaced kind name, e.g. `rationalAgents.Planning`. */\n readonly kind: K;\n /** Default: the part after the namespace (\"Planning\"). */\n readonly label?: string;\n /** Required unless `behavesLike` is given (then it is the same category). */\n readonly category?: ElementCategory;\n /** An existing element kind whose link rules this kind follows, e.g. `istar.Task`. */\n readonly behavesLike?: string;\n /** Containment rules for nodes. Default: those of `behavesLike`, else piStar-ext's (inner, dependum). */\n readonly info?: Partial<NodeKindInfo>;\n /** Default: that of `behavesLike`, else piStar-ext's 90×55 for nodes and 200×120 for actors. */\n readonly size?: Size;\n /**\n * The `type` used in piStar files, when it differs from `kind`. piStar-ext saves its new\n * constructs as `istar.<Name>`, so `pistarType: 'istar.Planning'` reads its files.\n */\n readonly pistarType?: string;\n}\n\nexport interface LinkKindDeclaration<K extends string = string> {\n readonly kind: K;\n readonly label?: string;\n /** Default: that of `behavesLike`, else `node`. */\n readonly category?: LinkCategory;\n /** An existing link kind whose rules this kind takes on, e.g. `istar.OrRefinementLink`. */\n readonly behavesLike?: string;\n /** Declarative rules; give these or `behavesLike`, not both. */\n readonly rules?: LinkRules;\n /** An extra predicate, checked after the other rules pass. */\n readonly check?: (context: LinkRuleContext) => LinkCheck;\n /** Default: that of `behavesLike`, else none (no fixed label, no changeable value). */\n readonly info?: LinkKindInfo;\n readonly pistarType?: string;\n}\n\n/** A named set of new kinds, applied to a metamodel with `extendMetamodel`. */\nexport interface MetamodelExtension<NEK extends string = string, NLK extends string = string> {\n /** Identifies the extension, e.g. `rationalAgents`. */\n readonly name: string;\n readonly elements?: readonly ElementKindDeclaration<NEK>[];\n readonly links?: readonly LinkKindDeclaration<NLK>[];\n}\n\nexport class MetamodelError extends Error {\n override name = 'MetamodelError';\n}\n\n/**\n * Declares an extension, keeping its kind names as literal types (so `extendMetamodel` can\n * type the result). Identity at runtime.\n */\nexport function defineMetamodelExtension<\n const NEK extends string = never,\n const NLK extends string = never,\n>(extension: MetamodelExtension<NEK, NLK>): MetamodelExtension<NEK, NLK> {\n return extension;\n}\n\nconst KIND_NAME = /^[A-Za-z_][\\w-]*\\.[A-Za-z_][\\w-]*$/;\nconst CATEGORY_SELECTORS: ReadonlySet<string> = new Set(['node', 'actor', '*']);\n\n/**\n * Returns a new metamodel with the extension's kinds added. `base` is not modified.\n *\n * Throws `MetamodelError` when a kind name isn't namespaced, uses the reserved `istar.`\n * prefix, collides with an existing kind or piStar type, or refers to an unknown kind.\n */\nexport function extendMetamodel<\n EK extends string,\n LK extends string,\n const NEK extends string = never,\n const NLK extends string = never,\n>(base: Metamodel<EK, LK>, extension: MetamodelExtension<NEK, NLK>): Metamodel<EK | NEK, LK | NLK> {\n const where = `extension \"${extension.name}\"`;\n if (!extension.name || typeof extension.name !== 'string') {\n throw new MetamodelError('an extension needs a name');\n }\n if (base.extensions.includes(extension.name)) {\n throw new MetamodelError(`${where} is already applied`);\n }\n\n const elements = new Map<string, ElementKindDefinition<string>>(base.elements);\n const links = new Map<string, LinkKindDefinition<string>>(base.links);\n const elementsByType = new Map<string, string>(base.elementsByPistarType);\n const linksByType = new Map<string, string>(base.linksByPistarType);\n\n const claimName = (kind: string, what: string): void => {\n if (typeof kind !== 'string' || !KIND_NAME.test(kind)) {\n throw new MetamodelError(\n `${where}: ${what} kind ${JSON.stringify(kind)} must be namespaced, e.g. \"${extension.name}.Name\"`,\n );\n }\n if (kind.startsWith(`${ISTAR_PREFIX}.`)) {\n throw new MetamodelError(\n `${where}: ${what} kind \"${kind}\" uses the reserved \"${ISTAR_PREFIX}.\" prefix; ` +\n `name it \"${extension.name}.${shortName(kind)}\" and set pistarType: \"${kind}\" to read files that use it`,\n );\n }\n if (elements.has(kind) || links.has(kind)) {\n throw new MetamodelError(`${where}: kind \"${kind}\" already exists`);\n }\n };\n const claimType = (type: string, kind: string): void => {\n if (typeof type !== 'string' || type === '') {\n throw new MetamodelError(`${where}: kind \"${kind}\" has an empty pistarType`);\n }\n if (\n elementsByType.has(type) ||\n linksByType.has(type) ||\n elements.has(type) ||\n links.has(type)\n ) {\n throw new MetamodelError(\n `${where}: pistarType \"${type}\" of kind \"${kind}\" is already used by another kind`,\n );\n }\n };\n\n for (const declaration of extension.elements ?? []) {\n const { kind } = declaration;\n claimName(kind, 'element');\n let parent: ElementKindDefinition<string> | undefined;\n if (declaration.behavesLike !== undefined) {\n parent = elements.get(declaration.behavesLike);\n if (!parent) {\n throw new MetamodelError(\n `${where}: \"${kind}\" behaves like unknown element kind \"${declaration.behavesLike}\"`,\n );\n }\n }\n const category = declaration.category ?? parent?.category;\n if (category !== 'actor' && category !== 'node') {\n throw new MetamodelError(\n `${where}: element kind \"${kind}\" needs a category (\"node\" or \"actor\") or behavesLike`,\n );\n }\n if (parent && parent.category !== category) {\n throw new MetamodelError(\n `${where}: \"${kind}\" is a ${category} but behaves like \"${parent.kind}\", a ${parent.category}`,\n );\n }\n const type = declaration.pistarType ?? kind;\n claimType(type, kind);\n const baseInfo: NodeKindInfo = parent?.info ?? {\n // piStar-ext's defaults for new nodes (tool/language/metamodel.js).\n canBeInnerElement: true,\n canBeDependum: true,\n canBeOnPaper: false,\n };\n const definition: ElementKindDefinition<string> = {\n kind,\n category,\n label: declaration.label ?? shortName(kind),\n size:\n declaration.size ??\n parent?.size ??\n (category === 'actor' ? { width: 200, height: 120 } : { width: 90, height: 55 }),\n ...(category === 'node' ? { info: { ...baseInfo, ...declaration.info } } : {}),\n ...(parent ? { behavesLike: parent.kind } : {}),\n pistarType: type,\n extension: extension.name,\n };\n elements.set(kind, definition);\n elementsByType.set(type, kind);\n }\n\n for (const declaration of extension.links ?? []) {\n const { kind } = declaration;\n claimName(kind, 'link');\n if ((declaration.behavesLike === undefined) === (declaration.rules === undefined)) {\n throw new MetamodelError(\n `${where}: link kind \"${kind}\" needs exactly one of behavesLike or rules`,\n );\n }\n let parent: LinkKindDefinition<string> | undefined;\n if (declaration.behavesLike !== undefined) {\n parent = links.get(declaration.behavesLike);\n if (!parent) {\n throw new MetamodelError(\n `${where}: \"${kind}\" behaves like unknown link kind \"${declaration.behavesLike}\"`,\n );\n }\n }\n const category = declaration.category ?? parent?.category ?? 'node';\n if (category !== 'node' && category !== 'actor' && category !== 'dependency') {\n throw new MetamodelError(\n `${where}: link kind \"${kind}\" has an unknown category \"${category}\"`,\n );\n }\n if (parent && parent.category !== category) {\n throw new MetamodelError(\n `${where}: \"${kind}\" is a ${category} link but behaves like \"${parent.kind}\", a ${parent.category} link`,\n );\n }\n if (category === 'dependency' && !parent) {\n throw new MetamodelError(\n `${where}: dependency link kind \"${kind}\" must behave like a dependency link (its dependum makes declarative rules ambiguous)`,\n );\n }\n if (declaration.rules) {\n for (const [side, selectors] of [\n ['sources', declaration.rules.sources],\n ['targets', declaration.rules.targets],\n ] as const) {\n if (!Array.isArray(selectors) || selectors.length === 0) {\n throw new MetamodelError(`${where}: link kind \"${kind}\" needs at least one of ${side}`);\n }\n for (const selector of selectors) {\n if (!CATEGORY_SELECTORS.has(selector) && !elements.has(selector)) {\n throw new MetamodelError(\n `${where}: ${side} of \"${kind}\" names unknown element kind \"${selector}\"`,\n );\n }\n }\n }\n }\n const type = declaration.pistarType ?? kind;\n claimType(type, kind);\n const definition: LinkKindDefinition<string> = {\n kind,\n category,\n label: declaration.label ?? shortName(kind),\n info: declaration.info ?? parent?.info ?? {},\n ...(parent ? { behavesLike: parent.kind } : {}),\n ...(declaration.rules ? { rules: declaration.rules } : {}),\n ...(declaration.check ? { check: declaration.check } : {}),\n pistarType: type,\n extension: extension.name,\n };\n links.set(kind, definition);\n linksByType.set(type, kind);\n }\n\n return {\n name: `${base.name}+${extension.name}`,\n extensions: [...base.extensions, extension.name],\n elements,\n links,\n elementsByPistarType: elementsByType,\n linksByPistarType: linksByType,\n } as unknown as Metamodel<EK | NEK, LK | NLK>;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Queries. They accept any string so code handling models of unknown dialects can ask.\n\nexport function elementKindDefinition(\n metamodel: AnyMetamodel,\n kind: string,\n): ElementKindDefinition | undefined {\n return metamodel.elements.get(kind);\n}\n\nexport function linkKindDefinition(\n metamodel: AnyMetamodel,\n kind: string,\n): LinkKindDefinition | undefined {\n return metamodel.links.get(kind);\n}\n\n/** True for actor-category kinds (Actor, Agent, Role and extensions behaving like them). */\nexport function isActorKindIn(metamodel: AnyMetamodel, kind: string): boolean {\n return metamodel.elements.get(kind)?.category === 'actor';\n}\n\n/** True for node-category kinds (intentional elements, built-in or extended). */\nexport function isNodeKindIn(metamodel: AnyMetamodel, kind: string): boolean {\n return metamodel.elements.get(kind)?.category === 'node';\n}\n\n/**\n * The built-in (or rule-carrying) kind an element kind ultimately behaves like: `istar.Task`\n * for a Planning that behaves like a Task; the kind itself when it behaves like nothing.\n */\nexport function effectiveElementKind(metamodel: AnyMetamodel, kind: string): string {\n let current = metamodel.elements.get(kind);\n const seen = new Set<string>();\n while (current?.behavesLike !== undefined && !seen.has(current.kind)) {\n seen.add(current.kind);\n const next = metamodel.elements.get(current.behavesLike);\n if (!next) break;\n current = next;\n }\n return current?.kind ?? kind;\n}\n\n/** Like `effectiveElementKind`, for link kinds. */\nexport function effectiveLinkKind(metamodel: AnyMetamodel, kind: string): string {\n let current = metamodel.links.get(kind);\n const seen = new Set<string>();\n while (current?.behavesLike !== undefined && !seen.has(current.kind)) {\n seen.add(current.kind);\n const next = metamodel.links.get(current.behavesLike);\n if (!next) break;\n current = next;\n }\n return current?.kind ?? kind;\n}\n\n/** True when `kind` is `ancestor` or (transitively) behaves like it. */\nexport function elementBehavesLike(\n metamodel: AnyMetamodel,\n kind: string,\n ancestor: string,\n): boolean {\n let current: string | undefined = kind;\n const seen = new Set<string>();\n while (current !== undefined && !seen.has(current)) {\n if (current === ancestor) return true;\n seen.add(current);\n current = metamodel.elements.get(current)?.behavesLike;\n }\n return false;\n}\n","import type { ActorKind, ElementKind, LinkKind, NodeKind } from './metamodel';\nimport type { AnyMetamodel, Metamodel } from './metamodels';\nimport { ISTAR_2_0, isActorKindIn } from './metamodels';\n\n/**\n * piStar stores every custom property value as a string (e.g. `\"initialValue\": \"false\"`).\n * Typed access is layered on top with property schemas (see `properties.ts`).\n */\nexport type CustomProperties = Readonly<Record<string, string>>;\n\n/** Arbitrary JSON keys the library does not interpret; kept so they survive a round trip. */\nexport type Extra = Readonly<Record<string, unknown>>;\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** Per-element entry of the save file's `display` section. */\nexport interface ElementDisplay {\n readonly backgroundColor?: string;\n readonly width?: number;\n readonly height?: number;\n /** Actors only. */\n readonly collapsed?: boolean;\n readonly [key: string]: unknown;\n}\n\n/** Per-link entry of the save file's `display` section. */\nexport interface LinkDisplay {\n readonly vertices?: readonly Point[];\n readonly [key: string]: unknown;\n}\n\n/**\n * An element of the model. `K` is the kind union: iStar 2.0's by default, wider for models of an\n * extended metamodel (see `extendMetamodel`).\n */\nexport interface IstarElement<K extends string = ElementKind> {\n readonly id: string;\n readonly kind: K;\n /** The element's label; `text` in the save file. */\n readonly name: string;\n /** Absolute diagram coordinates, as in the save file (children are not relative to actors). */\n readonly x: number;\n readonly y: number;\n /** Id of the containing actor, for inner elements. */\n readonly parent?: string;\n /** True when the element is the dependum of a dependency (lives in `dependencies`). */\n readonly isDependum?: boolean;\n /**\n * Depender/dependee recorded in the save file for a dependum. The dependency links are the\n * source of truth; this is only a fallback used when those links are missing.\n */\n readonly dependency?: { readonly source: string; readonly target: string };\n readonly customProperties?: CustomProperties;\n readonly display?: ElementDisplay;\n readonly extra?: Extra;\n}\n\nexport type IstarActor = IstarElement<ActorKind>;\nexport type IstarNode = IstarElement<NodeKind>;\n\nexport interface IstarLink<K extends string = LinkKind> {\n readonly id: string;\n readonly kind: K;\n readonly source: string;\n readonly target: string;\n /** Contribution value (`make`/`help`/`hurt`/`break`), stored as `label` in the save file. */\n readonly label?: string;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n readonly display?: LinkDisplay;\n readonly extra?: Extra;\n}\n\nexport interface Diagram {\n readonly width?: number;\n readonly height?: number;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n readonly extra?: Extra;\n}\n\n/**\n * An immutable iStar model. Maps preserve insertion order, which is the order elements and\n * links are written back to disk.\n *\n * `EK`/`LK` are the element and link kind unions; they default to iStar 2.0's.\n */\nexport interface IstarModel<EK extends string = ElementKind, LK extends string = LinkKind> {\n readonly elements: ReadonlyMap<string, IstarElement<EK>>;\n readonly links: ReadonlyMap<string, IstarLink<LK>>;\n readonly diagram?: Diagram;\n readonly tool?: string;\n readonly istar?: string;\n readonly saveDate?: string;\n /** `display` entries whose id matches no element or link. */\n readonly extraDisplay?: Extra;\n /** Unknown top-level keys (e.g. `metamodelVersion`). */\n readonly extra?: Extra;\n}\n\n/** Tool identifier written by piStar 2.1.0, whose file format this library emulates. */\nexport const PISTAR_TOOL = 'pistar.2.1.0';\nexport const ISTAR_VERSION = '2.0';\n\nexport const DEFAULT_DIAGRAM: Diagram = { width: 2000, height: 1300 };\n\n/** A model of any dialect, for code that handles every kind generically. */\nexport type AnyIstarModel = IstarModel<string, string>;\n\n/**\n * The metamodel of each model that isn't iStar 2.0. Kept beside the model rather than in it,\n * so a model's shape (and `JSON.stringify`, deep equality, snapshots) is the same as before\n * metamodels existed. Operations and the store carry it to every model they derive.\n */\nconst metamodels = new WeakMap<object, AnyMetamodel>();\n\n/**\n * Associates `metamodel` with `model` and returns the same model, typed for it. Use when a\n * model was built without the library's operations (e.g. with an object spread), which loses\n * the association.\n */\nexport function withMetamodel<EK extends string, LK extends string>(\n model: IstarModel<string, string>,\n metamodel: Metamodel<EK, LK>,\n): IstarModel<EK, LK> {\n if ((metamodel as unknown) === ISTAR_2_0) metamodels.delete(model);\n else metamodels.set(model, metamodel as unknown as AnyMetamodel);\n return model as unknown as IstarModel<EK, LK>;\n}\n\n/** Gives `to` the metamodel of `from` (used for every model an operation derives). */\nexport function inheritMetamodel<M extends IstarModel<string, string>>(\n from: IstarModel<string, string>,\n to: M,\n): M {\n const metamodel = metamodels.get(from);\n if (metamodel && from !== to) metamodels.set(to, metamodel);\n return to;\n}\n\n// The iStar 2.0 overload comes last: TypeScript resolves function references (e.g.\n// `useIstarStore(createEmptyModel)`) against the last one, as before metamodels existed.\nexport function createEmptyModel<EK extends string, LK extends string>(\n diagram: Diagram | undefined,\n options: { metamodel: Metamodel<EK, LK> },\n): IstarModel<EK, LK>;\nexport function createEmptyModel(diagram?: Diagram): IstarModel;\nexport function createEmptyModel(\n diagram: Diagram = DEFAULT_DIAGRAM,\n options: { metamodel?: AnyMetamodel } = {},\n): AnyIstarModel {\n const model: AnyIstarModel = {\n elements: new Map(),\n links: new Map(),\n diagram,\n tool: PISTAR_TOOL,\n istar: ISTAR_VERSION,\n };\n return options.metamodel ? withMetamodel(model, options.metamodel) : model;\n}\n\n/**\n * The metamodel a model was read or created with (see `parsePistar`, `createEmptyModel`), or\n * iStar 2.0. Constraints, operations and serialization use it unless given another one.\n */\nexport function metamodelOf<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n): Metamodel<EK, LK> {\n return (metamodels.get(model) ?? ISTAR_2_0) as unknown as Metamodel<EK, LK>;\n}\n\n/** True for actor-category elements; pass the metamodel for extended actor kinds. */\nexport function isActor(\n element: IstarElement<string> | undefined,\n metamodel: AnyMetamodel = ISTAR_2_0,\n): element is IstarActor {\n return element !== undefined && isActorKindIn(metamodel, element.kind);\n}\n\n/** True for node-category elements; pass the metamodel for extended node kinds. */\nexport function isNode(\n element: IstarElement<string> | undefined,\n metamodel: AnyMetamodel = ISTAR_2_0,\n): element is IstarNode {\n return element !== undefined && !isActorKindIn(metamodel, element.kind);\n}\n\n/** Inner elements of an actor, in model order. */\nexport function childrenOf<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n actorId: string,\n): IstarElement<EK>[] {\n const result: IstarElement<EK>[] = [];\n for (const element of model.elements.values()) {\n if (element.parent === actorId) result.push(element);\n }\n return result;\n}\n\n/** Links that have the element as source or target. */\nexport function linksOf<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n elementId: string,\n): IstarLink<LK>[] {\n const result: IstarLink<LK>[] = [];\n for (const link of model.links.values()) {\n if (link.source === elementId || link.target === elementId) result.push(link);\n }\n return result;\n}\n\n/** For a dependum, the two halves of its dependency: depender → dependum → dependee. */\nexport function dependencyLinksOf<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n dependumId: string,\n): { inbound?: IstarLink<LK>; outbound?: IstarLink<LK> } {\n const metamodel = metamodelOf(model) as AnyMetamodel;\n let inbound: IstarLink<LK> | undefined;\n let outbound: IstarLink<LK> | undefined;\n for (const link of model.links.values()) {\n if (metamodel.links.get(link.kind)?.category !== 'dependency') continue;\n if (link.target === dependumId && !inbound) inbound = link;\n if (link.source === dependumId && !outbound) outbound = link;\n }\n return { inbound, outbound };\n}\n","/**\n * iStar 2.0 link constraints, ported from piStar's `tool/language/constraints.js`.\n *\n * Each check runs in the same order as upstream so the reported reason is the one piStar\n * would show. Upstream messages embed HTML and illustrative images; here they are plain text.\n */\nimport type { ElementKind, LinkKind } from './metamodel';\nimport type { AnyMetamodel, LinkKindDefinition, LinkRules, Metamodel } from './metamodels';\nimport { effectiveElementKind, effectiveLinkKind, elementBehavesLike } from './metamodels';\nimport type { AnyIstarModel, IstarElement, IstarLink, IstarModel } from './model';\nimport { metamodelOf } from './model';\n\nexport type ConstraintCode =\n | 'unknown-element'\n | 'unknown-link-kind'\n | 'invalid-source'\n | 'invalid-target'\n | 'actor-types-differ'\n | 'self-link'\n | 'duplicate-link'\n | 'dependum-endpoint'\n | 'same-actor'\n | 'different-actors'\n | 'refined-depender'\n | 'contributed-depender'\n | 'depender-target'\n | 'mixed-refinement'\n | 'contribution-and-qualification';\n\nexport type LinkCheck = { ok: true } | { ok: false; reason: string; code: ConstraintCode };\n\nconst OK: LinkCheck = { ok: true };\n\nfunction fail(code: ConstraintCode, reason: string): LinkCheck {\n return { ok: false, code, reason };\n}\n\ntype ElementRef = string | IstarElement<string>;\n\nexport interface CanLinkOptions<EK extends string = ElementKind, LK extends string = LinkKind> {\n /** Default: the model's metamodel, or iStar 2.0. */\n readonly metamodel?: Metamodel<EK, LK>;\n}\n\n/**\n * Checks whether a link of `kind` may be added from `source` to `target` in `model`.\n *\n * For dependency links, `source` is the depender and `target` the dependee (an actor or one of\n * its inner elements); the dependum sits between them and is not part of the check.\n *\n * Extended kinds (see `extendMetamodel`) are checked with the rules of the kind they behave\n * like, or with their declarative rules, then with their extra predicate.\n */\nexport function canLink<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n source: string | IstarElement<EK>,\n target: string | IstarElement<EK>,\n kind: LK,\n options: CanLinkOptions<EK, LK> = {},\n): LinkCheck {\n const any = model as unknown as AnyIstarModel;\n const metamodel = (options.metamodel ?? metamodelOf(model)) as unknown as AnyMetamodel;\n const s = resolve(any, source);\n const t = resolve(any, target);\n if (!s) return fail('unknown-element', `unknown source element \"${refId(source)}\"`);\n if (!t) return fail('unknown-element', `unknown target element \"${refId(target)}\"`);\n const definition = metamodel.links.get(kind);\n if (!definition) return fail('unknown-link-kind', `unknown link kind \"${String(kind)}\"`);\n return checkWith(new Graph(any, metamodel), definition, s, t);\n}\n\n/** Runs the rule a link kind resolves to, then every extra predicate along its chain. */\nfunction checkWith(\n graph: Graph,\n definition: LinkKindDefinition,\n source: IstarElement<string>,\n target: IstarElement<string>,\n): LinkCheck {\n const chain: LinkKindDefinition[] = [];\n for (\n let current: LinkKindDefinition | undefined = definition;\n current && !chain.includes(current);\n current = current.behavesLike ? graph.metamodel.links.get(current.behavesLike) : undefined\n ) {\n chain.push(current);\n }\n const root = chain[chain.length - 1]!;\n const builtIn = CHECKS[root.kind as LinkKind];\n let result: LinkCheck;\n if (root.rules)\n result = declarativeCheck(graph, definition, root.rules, root.kind, source, target);\n else if (builtIn) result = builtIn(graph, source, target);\n else result = fail('unknown-link-kind', `link kind \"${definition.kind}\" has no rules`);\n if (!result.ok) return result;\n const context = graph.context(definition.kind, source, target);\n for (const step of chain.toReversed()) {\n if (!step.check) continue;\n const extra = step.check(context);\n if (!extra.ok) return extra;\n }\n return OK;\n}\n\nfunction refId(ref: ElementRef): string {\n return typeof ref === 'string' ? ref : ref.id;\n}\n\nfunction resolve(model: AnyIstarModel, ref: ElementRef): IstarElement<string> | undefined {\n // Always look the element up so a stale object can't be checked against a newer model.\n return model.elements.get(refId(ref));\n}\n\n/**\n * What an extension's `check` predicate receives: the model, the endpoints, and the graph\n * queries the iStar 2.0 rules use.\n */\nexport interface LinkRuleContext {\n readonly model: AnyIstarModel;\n readonly metamodel: AnyMetamodel;\n /** The link kind being added. */\n readonly kind: string;\n readonly source: IstarElement<string>;\n readonly target: IstarElement<string>;\n /** A link (optionally of `kind`, or a kind behaving like it) joins `a` and `b`, either way. */\n isThereLinkBetween(a: IstarElement<string>, b: IstarElement<string>, kind?: string): boolean;\n /** `element` is the source of a link of `kind` (or a kind behaving like it). */\n isSourceOfType(element: IstarElement<string>, kind: string): boolean;\n /** `element` is the target of a link of `kind` (or a kind behaving like it). */\n isTargetOfType(element: IstarElement<string>, kind: string): boolean;\n}\n\n/**\n * The graph queries used by upstream constraints (`istar.isThereLinkBetween`, etc.). Link kinds\n * are compared by what they behave like, so an extension link behaving like an OR-refinement\n * counts as one for the iStar 2.0 rules (no mixing with AND, no refining a depender…).\n */\nclass Graph {\n constructor(\n readonly model: AnyIstarModel,\n readonly metamodel: AnyMetamodel,\n ) {}\n\n private matches(link: IstarLink<string>, kind: string): boolean {\n return link.kind === kind || effectiveLinkKind(this.metamodel, link.kind) === kind;\n }\n\n /**\n * True when a link (optionally of `kind`) already connects the two elements, in either\n * direction. Mirrors `istar.isThereLinkBetween`.\n */\n isThereLinkBetween(a: IstarElement<string>, b: IstarElement<string>, kind?: string): boolean {\n for (const link of this.model.links.values()) {\n if (kind && !this.matches(link, kind)) continue;\n if (\n (link.source === a.id && link.target === b.id) ||\n (link.source === b.id && link.target === a.id)\n ) {\n return true;\n }\n }\n return false;\n }\n\n /** Like `isThereLinkBetween`, counting only links of exactly `kind`. */\n isThereLinkOfKindBetween(\n a: IstarElement<string>,\n b: IstarElement<string>,\n kind: string,\n ): boolean {\n for (const link of this.model.links.values()) {\n if (link.kind !== kind) continue;\n if (\n (link.source === a.id && link.target === b.id) ||\n (link.source === b.id && link.target === a.id)\n ) {\n return true;\n }\n }\n return false;\n }\n\n isSourceOfType(element: IstarElement<string>, kind: string): boolean {\n for (const link of this.model.links.values()) {\n if (link.source === element.id && this.matches(link, kind)) return true;\n }\n return false;\n }\n\n isTargetOfType(element: IstarElement<string>, kind: string): boolean {\n for (const link of this.model.links.values()) {\n if (link.target === element.id && this.matches(link, kind)) return true;\n }\n return false;\n }\n\n /** The kind the iStar 2.0 rules see: built-in kinds as they are, extensions as what they behave like. */\n kindOf(element: IstarElement<string>): string {\n return effectiveElementKind(this.metamodel, element.kind);\n }\n\n isActor(element: IstarElement<string>): boolean {\n return this.metamodel.elements.get(element.kind)?.category === 'actor';\n }\n\n context(\n kind: string,\n source: IstarElement<string>,\n target: IstarElement<string>,\n ): LinkRuleContext {\n return {\n model: this.model,\n metamodel: this.metamodel,\n kind,\n source,\n target,\n isThereLinkBetween: (a, b, k) => this.isThereLinkBetween(a, b, k),\n isSourceOfType: (e, k) => this.isSourceOfType(e, k),\n isTargetOfType: (e, k) => this.isTargetOfType(e, k),\n };\n }\n}\n\ntype Check = (\n graph: Graph,\n source: IstarElement<string>,\n target: IstarElement<string>,\n) => LinkCheck;\n\nconst is = (graph: Graph, element: IstarElement<string>, ...shortNames: string[]): boolean => {\n const kind = graph.kindOf(element);\n return shortNames.some((name) => kind === `istar.${name}`);\n};\n\nconst isDependum = (element: IstarElement<string>): boolean => element.isDependum === true;\n\nconst isALink: Check = (graph, source, target) => {\n // Upstream evaluates the source-kind check after the type-equality check without guarding\n // on the previous result, so its message wins when both fail. Reproduced here.\n if (!is(graph, source, 'Actor', 'Role')) {\n return fail(\n 'invalid-source',\n 'the source of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).',\n );\n }\n if (source.kind !== target.kind) {\n return fail(\n 'actor-types-differ',\n '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).',\n );\n }\n if (!is(graph, target, 'Actor', 'Role')) {\n return fail(\n 'invalid-target',\n 'the target of Is-A links must be a Role or a general Actor (iStar 2.0 Guide, Page 6).',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make Is-A links from an actor onto itself.');\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).',\n );\n }\n return OK;\n};\n\nconst participatesInLink: Check = (graph, source, target) => {\n if (!graph.isActor(source)) {\n return fail(\n 'invalid-source',\n 'the source of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)',\n );\n }\n if (!graph.isActor(target)) {\n return fail(\n 'invalid-target',\n 'the target of a Participates-In link must be some kind of actor (iStar 2.0 Guide, Page 6)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Participates-In link from an actor onto itself.');\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Actor link between the same two actors (iStar 2.0 Guide, Page 14).',\n );\n }\n return OK;\n};\n\n/** The actor an element belongs to: itself for actors, its parent for inner elements. */\nfunction owningActorId(graph: Graph, element: IstarElement<string>): string | undefined {\n return graph.isActor(element) ? element.id : element.parent;\n}\n\nconst dependencyLink: Check = (graph, source, target) => {\n if (source.id === target.id) {\n return fail('self-link', 'a Dependency link cannot link an element onto itself');\n }\n if (isDependum(source)) {\n return fail('dependum-endpoint', 'a Dependency link cannot start from a dependum');\n }\n if (isDependum(target)) {\n return fail('dependum-endpoint', 'a Dependency link cannot end in a dependum');\n }\n if (owningActorId(graph, source) === owningActorId(graph, target)) {\n return fail(\n 'same-actor',\n 'a Dependency link must involve two different actors (iStar 2.0 Guide, Page 14)',\n );\n }\n if (\n graph.isTargetOfType(source, 'istar.OrRefinementLink') ||\n graph.isTargetOfType(source, 'istar.AndRefinementLink')\n ) {\n return fail(\n 'refined-depender',\n 'a refined element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to add the Dependency originating from a child.',\n );\n }\n if (graph.isTargetOfType(source, 'istar.ContributionLink')) {\n return fail(\n 'contributed-depender',\n 'a contributed element cannot be the Depender Element in a Dependency link (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to add the Dependency originating from a child.',\n );\n }\n return OK;\n};\n\nfunction refinementLink(label: 'AND' | 'OR'): Check {\n const other = label === 'AND' ? 'istar.OrRefinementLink' : 'istar.AndRefinementLink';\n return (graph, source, target) => {\n if (!is(graph, source, 'Task', 'Goal')) {\n return fail(\n 'invalid-source',\n `the source of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`,\n );\n }\n if (!is(graph, target, 'Task', 'Goal')) {\n return fail(\n 'invalid-target',\n `the target of an ${label}-refinement link must be a Goal or a Task (iStar 2.0 Guide, Table 1)`,\n );\n }\n if (source.id === target.id) {\n return fail(\n 'self-link',\n `you cannot make an ${label}-refinement link from an element onto itself`,\n );\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n `you cannot make an ${label}-refinement link with a dependum (iStar 2.0 Guide, Page 14)`,\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n `the source and target of an ${label}-refinement link must pertain to the same actor (iStar 2.0 Guide, Page 14)`,\n );\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one refinement link between the same two elements',\n );\n }\n if (graph.isSourceOfType(target, 'istar.DependencyLink')) {\n return fail(\n 'depender-target',\n 'you cannot refine a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to move the dependency to the sub-element.',\n );\n }\n if (graph.isTargetOfType(target, other)) {\n const mix =\n label === 'AND'\n ? 'you cannot mix AND-refinements with OR-refinements targeting the same element (iStar 2.0 Guide, Page 10).'\n : 'you cannot mix OR-refinements with AND-refinements targeting the same element (iStar 2.0 Guide, Page 10).';\n return fail('mixed-refinement', mix);\n }\n return OK;\n };\n}\n\nconst neededByLink: Check = (graph, source, target) => {\n if (!is(graph, source, 'Resource')) {\n return fail(\n 'invalid-source',\n 'the source of a Needed-By link must be a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(graph, target, 'Task')) {\n return fail(\n 'invalid-target',\n 'the target of a Needed-By link must be a Task (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Needed-By link from an element onto itself');\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Needed-By link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Needed-By link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target)) {\n return fail(\n 'duplicate-link',\n 'there can only be one Needed-By link between the same two elements',\n );\n }\n return OK;\n};\n\nconst contributionLink: Check = (graph, source, target) => {\n if (!is(graph, source, 'Goal', 'Quality', 'Task', 'Resource')) {\n return fail(\n 'invalid-source',\n 'the source of a Contribution link must be a Goal, a Quality, a Task or a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(graph, target, 'Quality')) {\n return fail(\n 'invalid-target',\n 'the target of a Contribution link must be a Quality (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail(\n 'self-link',\n 'you cannot make a Contribution link from an element onto itself (iStar 2.0 Guide, Page 15)',\n );\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Contribution link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Contribution link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.ContributionLink')) {\n return fail(\n 'duplicate-link',\n 'there can only be one Contribution link between the same two elements',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.QualificationLink')) {\n return fail(\n 'contribution-and-qualification',\n 'you cannot have Contribution and Qualification links between the same two elements (iStar 2.0 Guide, Page 15)',\n );\n }\n if (graph.isSourceOfType(target, 'istar.DependencyLink')) {\n return fail(\n 'depender-target',\n 'you cannot contribute to a Depender Element; that is, an element that is the source of a Dependency (iStar 2.0 Guide, Page 14). ' +\n 'Instead, you can try to move the dependency to the sub-quality.',\n );\n }\n return OK;\n};\n\nconst qualificationLink: Check = (graph, source, target) => {\n if (!is(graph, source, 'Quality')) {\n return fail(\n 'invalid-source',\n 'the source of a Qualification link must be a Quality (iStar 2.0 Guide, Table 1)',\n );\n }\n if (!is(graph, target, 'Goal', 'Task', 'Resource')) {\n return fail(\n 'invalid-target',\n 'the target of a Qualification link must be a Goal, a Task or a Resource (iStar 2.0 Guide, Table 1)',\n );\n }\n if (source.id === target.id) {\n return fail('self-link', 'you cannot make a Qualification link from an element onto itself');\n }\n if (isDependum(source) || isDependum(target)) {\n return fail(\n 'dependum-endpoint',\n 'you cannot make a Qualification link with a dependum (iStar 2.0 Guide, Page 14)',\n );\n }\n if (source.parent !== target.parent) {\n return fail(\n 'different-actors',\n 'the source and target of a Qualification link must pertain to the same actor (iStar 2.0 Guide, Page 14)',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.QualificationLink')) {\n return fail(\n 'duplicate-link',\n 'there can only be one Qualification link between the same two elements',\n );\n }\n if (graph.isThereLinkBetween(source, target, 'istar.ContributionLink')) {\n return fail(\n 'contribution-and-qualification',\n 'you cannot have Qualification and Contribution links between the same two elements (iStar 2.0 Guide, Page 15)',\n );\n }\n return OK;\n};\n\n/** The words used for a list of kind selectors in messages: \"a Goal or a Task\". */\nfunction describe(graph: Graph, selectors: readonly string[]): string {\n const names = selectors.map((selector) => {\n if (selector === '*') return 'any element';\n if (selector === 'node') return 'an intentional element';\n if (selector === 'actor') return 'an actor';\n const label = graph.metamodel.elements.get(selector)?.label ?? selector;\n return /^[aeiou]/i.test(label) ? `an ${label}` : `a ${label}`;\n });\n return names.length <= 2\n ? names.join(' or ')\n : `${names.slice(0, -1).join(', ')} or ${names[names.length - 1]}`;\n}\n\nfunction matchesSelector(graph: Graph, element: IstarElement<string>, selector: string): boolean {\n if (selector === '*') return true;\n const category = graph.metamodel.elements.get(element.kind)?.category;\n if (selector === 'node' || selector === 'actor') return category === selector;\n return elementBehavesLike(graph.metamodel, element.kind, selector);\n}\n\n/**\n * Declarative rules of an extension link kind, checked in the order of the iStar 2.0 node-link\n * rules (and of piStar-ext's generated `isValid`): source kind, target kind, self link,\n * dependum, same actor, duplicates.\n */\nfunction declarativeCheck(\n graph: Graph,\n definition: LinkKindDefinition,\n rules: LinkRules,\n rulesKind: string,\n source: IstarElement<string>,\n target: IstarElement<string>,\n): LinkCheck {\n const name = definition.label;\n const article = /^[aeiou]/i.test(name) ? 'an' : 'a';\n if (!rules.sources.some((selector) => matchesSelector(graph, source, selector))) {\n return fail(\n 'invalid-source',\n `the source of ${article} ${name} link must be ${describe(graph, rules.sources)}`,\n );\n }\n if (!rules.targets.some((selector) => matchesSelector(graph, target, selector))) {\n return fail(\n 'invalid-target',\n `the target of ${article} ${name} link must be ${describe(graph, rules.targets)}`,\n );\n }\n if (!rules.allowSelf && source.id === target.id) {\n return fail('self-link', `you cannot make ${article} ${name} link from an element onto itself`);\n }\n if (definition.category === 'node') {\n if (!rules.allowDependum && (isDependum(source) || isDependum(target))) {\n return fail('dependum-endpoint', `you cannot make ${article} ${name} link with a dependum`);\n }\n if (rules.sameActor !== false && source.parent !== target.parent) {\n return fail(\n 'different-actors',\n `the source and target of ${article} ${name} link must pertain to the same actor (iStar 2.0 Guide, Page 14)`,\n );\n }\n }\n const unique = rules.unique ?? 'kind';\n if (\n (unique === 'any' && graph.isThereLinkBetween(source, target)) ||\n (unique === 'kind' && graph.isThereLinkOfKindBetween(source, target, definition.kind)) ||\n // A kind inheriting these rules shares the limit with the kind that declares them.\n (unique === 'kind' &&\n rulesKind !== definition.kind &&\n graph.isThereLinkOfKindBetween(source, target, rulesKind))\n ) {\n return fail(\n 'duplicate-link',\n `there can only be one ${name} link between the same two elements`,\n );\n }\n return OK;\n}\n\nconst CHECKS: Partial<Readonly<Record<string, Check>>> = {\n 'istar.IsALink': isALink,\n 'istar.ParticipatesInLink': participatesInLink,\n 'istar.DependencyLink': dependencyLink,\n 'istar.AndRefinementLink': refinementLink('AND'),\n 'istar.OrRefinementLink': refinementLink('OR'),\n 'istar.NeededByLink': neededByLink,\n 'istar.ContributionLink': contributionLink,\n 'istar.QualificationLink': qualificationLink,\n};\n\nexport interface ModelIssue<LK extends string = LinkKind> {\n readonly linkId: string;\n readonly kind: LK;\n readonly source: string;\n readonly target: string;\n readonly code: ConstraintCode;\n readonly message: string;\n}\n\n/**\n * Re-validates every link of a model, the way piStar does when loading a file: dependencies\n * first (each checked before its own links are added), then the remaining links in file\n * order, each against the graph built so far. Invalid links are reported, not removed.\n */\nexport function validateModel<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n options: CanLinkOptions<EK, LK> = {},\n): ModelIssue<LK>[] {\n const metamodel = (options.metamodel ?? metamodelOf(model)) as unknown as AnyMetamodel;\n const any = model as unknown as AnyIstarModel;\n const issues: ModelIssue<LK>[] = [];\n const accepted = new Map<string, IstarLink<string>>();\n const view = (): AnyIstarModel => ({ ...any, links: accepted });\n const check = (source: string, target: string, kind: string): LinkCheck =>\n canLink(view(), source, target, kind, { metamodel });\n const isDependency = (link: IstarLink<string>): boolean =>\n metamodel.links.get(link.kind)?.category === 'dependency';\n\n const report = (\n linkId: string,\n kind: string,\n source: string,\n target: string,\n result: LinkCheck,\n ): void => {\n if (!result.ok) {\n issues.push({\n linkId,\n kind: kind as LK,\n source,\n target,\n code: result.code,\n message: result.reason,\n });\n }\n };\n\n const dependencyLinks = [...any.links.values()].filter(isDependency);\n for (const dependum of any.elements.values()) {\n if (!dependum.isDependum) continue;\n const inbound = dependencyLinks.find((l) => l.target === dependum.id);\n const outbound = dependencyLinks.find((l) => l.source === dependum.id);\n const depender = inbound?.source ?? dependum.dependency?.source;\n const dependee = outbound?.target ?? dependum.dependency?.target;\n const kind = inbound?.kind ?? outbound?.kind ?? 'istar.DependencyLink';\n if (depender !== undefined && dependee !== undefined) {\n report(inbound?.id ?? dependum.id, kind, depender, dependee, check(depender, dependee, kind));\n }\n if (inbound) accepted.set(inbound.id, inbound);\n if (outbound) accepted.set(outbound.id, outbound);\n }\n\n for (const link of any.links.values()) {\n if (isDependency(link)) continue;\n if (any.elements.has(link.source) && any.elements.has(link.target)) {\n report(\n link.id,\n link.kind,\n link.source,\n link.target,\n check(link.source, link.target, link.kind),\n );\n } else {\n report(link.id, link.kind, link.source, link.target, {\n ok: false,\n code: 'unknown-element',\n reason: 'the link refers to an element that does not exist',\n });\n }\n accepted.set(link.id, link);\n }\n return issues;\n}\n","/**\n * Reading and writing piStar save files, ported from `tool/app/istarcore/fileManager.js`.\n *\n * Output is produced with the same key order and `JSON.stringify(_, null, 2)` formatting as the\n * piStar web tool, so a file saved by piStar round-trips byte for byte. Keys this library does\n * not interpret are kept and written back.\n */\nimport type { ElementKind, LinkKind } from './metamodel';\nimport type { AnyMetamodel, Metamodel } from './metamodels';\nimport { ISTAR_2_0 } from './metamodels';\nimport type {\n CustomProperties,\n Diagram,\n ElementDisplay,\n Extra,\n IstarElement,\n IstarLink,\n IstarModel,\n LinkDisplay,\n} from './model';\nimport { dependencyLinksOf, metamodelOf, withMetamodel } from './model';\nimport type { AnyIstarModel } from './model';\n\n// ---------------------------------------------------------------------------------------------\n// File format types\n\nexport interface PistarElementJson {\n id: string;\n text: string;\n type: string;\n x: number;\n y: number;\n customProperties?: Record<string, string>;\n [key: string]: unknown;\n}\n\nexport interface PistarActorJson extends PistarElementJson {\n nodes: PistarElementJson[];\n}\n\nexport interface PistarDependencyJson extends PistarElementJson {\n source: string;\n target: string;\n}\n\nexport interface PistarLinkJson {\n id: string;\n type: string;\n source: string;\n target: string;\n name?: string;\n customProperties?: Record<string, string>;\n label?: string;\n [key: string]: unknown;\n}\n\nexport interface PistarDiagramJson {\n width?: number;\n height?: number;\n name?: string;\n customProperties?: Record<string, string>;\n [key: string]: unknown;\n}\n\n/** A piStar save file. Older piStar versions may omit some sections (e.g. `orphans`). */\nexport interface PistarFile {\n actors: PistarActorJson[];\n orphans?: PistarElementJson[];\n dependencies?: PistarDependencyJson[];\n links?: PistarLinkJson[];\n display?: Record<string, Record<string, unknown>>;\n tool?: string;\n istar?: string;\n saveDate?: string;\n diagram?: PistarDiagramJson;\n [key: string]: unknown;\n}\n\nexport class PistarParseError extends Error {\n override name = 'PistarParseError';\n}\n\n/** Thrown by `toPistar` for a kind its metamodel doesn't know (rather than writing it wrong). */\nexport class PistarWriteError extends Error {\n override name = 'PistarWriteError';\n}\n\n/**\n * Parse-time bookkeeping that lets `toPistar` reproduce the original key order. It has no\n * meaning for the model itself and may be dropped.\n */\nexport interface SourceLayout {\n /** Top-level keys in file order. */\n readonly keys: readonly string[];\n /** `display` ids in file order. */\n readonly display: readonly string[];\n}\n\nconst layouts = new WeakMap<object, SourceLayout>();\n\n/** The key order recorded when `model` was parsed, if it came from `parsePistar`. */\nexport function getSourceLayout<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n): SourceLayout | undefined {\n return layouts.get(model);\n}\n\n/**\n * Carries the recorded key order over to a model derived from `from` (the store does this for\n * every edit, so saving an edited file keeps a stable diff).\n */\nexport function inheritSourceLayout<M extends IstarModel<string, string>>(\n from: IstarModel<string, string>,\n to: M,\n): M {\n const layout = layouts.get(from);\n if (layout && from !== to) layouts.set(to, layout);\n return to;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Parsing\n\nconst ELEMENT_KEYS = new Set(['id', 'text', 'type', 'x', 'y', 'customProperties']);\nconst ACTOR_KEYS = new Set([...ELEMENT_KEYS, 'nodes']);\nconst DEPENDENCY_KEYS = new Set([...ELEMENT_KEYS, 'source', 'target']);\nconst LINK_KEYS = new Set(['id', 'type', 'source', 'target', 'name', 'customProperties', 'label']);\nconst DIAGRAM_KEYS = new Set(['width', 'height', 'name', 'customProperties']);\nconst TOP_LEVEL_KEYS = [\n 'actors',\n 'orphans',\n 'dependencies',\n 'links',\n 'display',\n 'tool',\n 'istar',\n 'saveDate',\n 'diagram',\n] as const;\nconst TOP_LEVEL_KEY_SET: ReadonlySet<string> = new Set(TOP_LEVEL_KEYS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction extraOf(json: Record<string, unknown>, known: ReadonlySet<string>): Extra | undefined {\n let extra: Record<string, unknown> | undefined;\n for (const key of Object.keys(json)) {\n if (!known.has(key)) (extra ??= {})[key] = json[key];\n }\n return extra;\n}\n\nfunction asArray(value: unknown, where: string): unknown[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) throw new PistarParseError(`\"${where}\" must be an array`);\n return value;\n}\n\n/**\n * Parses a piStar save file (JSON text or an already-parsed object). The input is not mutated.\n *\n * Unlike the piStar tool, elements with `x` or `y` equal to 0 are kept: upstream's\n * `if (element.x && element.y)` silently drops them, which looks unintended.\n */\nexport interface ParsePistarOptions<EK extends string = ElementKind, LK extends string = LinkKind> {\n /**\n * The metamodel whose kinds the file may use. Default iStar 2.0: any other `type` throws,\n * as in the piStar tool. The parsed model remembers it (see `metamodelOf`).\n */\n readonly metamodel?: Metamodel<EK, LK>;\n}\n\n// The iStar 2.0 overload comes last, so `parsePistar` passed as a callback types as before.\nexport function parsePistar<EK extends string, LK extends string>(\n input: string | PistarFile | Record<string, unknown>,\n options: ParsePistarOptions<EK, LK> & { readonly metamodel: Metamodel<EK, LK> },\n): IstarModel<EK, LK>;\nexport function parsePistar(\n input: string | PistarFile | Record<string, unknown>,\n options: ParsePistarOptions,\n): IstarModel;\nexport function parsePistar(input: string | PistarFile | Record<string, unknown>): IstarModel;\nexport function parsePistar(\n input: string | PistarFile | Record<string, unknown>,\n options: ParsePistarOptions<string, string> = {},\n): AnyIstarModel {\n const metamodel: AnyMetamodel = options.metamodel ?? ISTAR_2_0;\n const categoryOf = (kind: string): string | undefined => metamodel.elements.get(kind)?.category;\n let json: unknown;\n if (typeof input === 'string') {\n try {\n json = JSON.parse(input);\n } catch (error) {\n throw new PistarParseError(`invalid JSON: ${(error as Error).message}`, { cause: error });\n }\n } else {\n json = structuredClone(input);\n }\n if (!isRecord(json)) throw new PistarParseError('a piStar model must be a JSON object');\n\n const display = isRecord(json.display) ? json.display : {};\n const usedDisplay = new Set<string>();\n const elements = new Map<string, IstarElement<string>>();\n const links = new Map<string, IstarLink<string>>();\n\n const displayFor = (id: string): Record<string, unknown> | undefined => {\n const entry = display[id];\n if (!isRecord(entry)) return undefined;\n usedDisplay.add(id);\n return entry;\n };\n\n const readElement = (\n raw: unknown,\n where: string,\n known: ReadonlySet<string>,\n extras: Partial<IstarElement<string>>,\n ): IstarElement<string> => {\n if (!isRecord(raw)) throw new PistarParseError(`${where}: expected an object`);\n const { id, type } = raw;\n if (typeof id !== 'string' || id === '') {\n throw new PistarParseError(`${where}: missing \"id\"`);\n }\n const kind = typeof type === 'string' ? metamodel.elementsByPistarType.get(type) : undefined;\n if (kind === undefined) {\n throw new PistarParseError(`${where} (${id}): unknown element type ${JSON.stringify(type)}`);\n }\n if (elements.has(id) || links.has(id)) {\n throw new PistarParseError(`${where}: duplicated id \"${id}\"`);\n }\n const element: IstarElement<string> = {\n id,\n kind,\n name: typeof raw.text === 'string' ? raw.text : '',\n x: typeof raw.x === 'number' ? raw.x : 0,\n y: typeof raw.y === 'number' ? raw.y : 0,\n ...extras,\n ...(isRecord(raw.customProperties)\n ? { customProperties: raw.customProperties as CustomProperties }\n : {}),\n ...optional('display', displayFor(id) as ElementDisplay | undefined),\n ...optional('extra', extraOf(raw, known)),\n };\n elements.set(id, element);\n return element;\n };\n\n asArray(json.actors, 'actors').forEach((raw, i) => {\n const actor = readElement(raw, `actors[${i}]`, ACTOR_KEYS, {});\n if (categoryOf(actor.kind) !== 'actor') {\n throw new PistarParseError(`actors[${i}] (${actor.id}): ${actor.kind} is not an actor kind`);\n }\n asArray((raw as Record<string, unknown>).nodes, `actors[${i}].nodes`).forEach((node, j) => {\n const child = readElement(node, `actors[${i}].nodes[${j}]`, ELEMENT_KEYS, {\n parent: actor.id,\n });\n if (categoryOf(child.kind) === 'actor') {\n throw new PistarParseError(`actors[${i}].nodes[${j}]: actors cannot be nested`);\n }\n });\n });\n\n asArray(json.orphans, 'orphans').forEach((raw, i) => {\n readElement(raw, `orphans[${i}]`, ELEMENT_KEYS, {});\n });\n\n asArray(json.dependencies, 'dependencies').forEach((raw, i) => {\n const r = raw as Record<string, unknown>;\n const dependency =\n typeof r.source === 'string' && typeof r.target === 'string'\n ? { dependency: { source: r.source, target: r.target } }\n : {};\n readElement(raw, `dependencies[${i}]`, DEPENDENCY_KEYS, { isDependum: true, ...dependency });\n });\n\n asArray(json.links, 'links').forEach((raw, i) => {\n if (!isRecord(raw)) throw new PistarParseError(`links[${i}]: expected an object`);\n const { id, type, source, target } = raw;\n if (typeof id !== 'string' || id === '')\n throw new PistarParseError(`links[${i}]: missing \"id\"`);\n const kind = typeof type === 'string' ? metamodel.linksByPistarType.get(type) : undefined;\n if (kind === undefined) {\n throw new PistarParseError(`links[${i}] (${id}): unknown link type ${JSON.stringify(type)}`);\n }\n if (typeof source !== 'string' || typeof target !== 'string') {\n throw new PistarParseError(`links[${i}] (${id}): missing \"source\" or \"target\"`);\n }\n if (elements.has(id) || links.has(id)) {\n throw new PistarParseError(`links[${i}]: duplicated id \"${id}\"`);\n }\n links.set(id, {\n id,\n kind,\n source,\n target,\n ...optional('name', typeof raw.name === 'string' ? raw.name : undefined),\n ...(isRecord(raw.customProperties)\n ? { customProperties: raw.customProperties as CustomProperties }\n : {}),\n ...optional('label', typeof raw.label === 'string' ? raw.label : undefined),\n ...optional('display', displayFor(id) as LinkDisplay | undefined),\n ...optional('extra', extraOf(raw, LINK_KEYS)),\n });\n });\n\n let extraDisplay: Record<string, unknown> | undefined;\n for (const [id, value] of Object.entries(display)) {\n if (!usedDisplay.has(id)) (extraDisplay ??= {})[id] = value;\n }\n\n let diagram: Diagram | undefined;\n if (isRecord(json.diagram)) {\n const d = json.diagram;\n diagram = {\n ...optional('width', typeof d.width === 'number' ? d.width : undefined),\n ...optional('height', typeof d.height === 'number' ? d.height : undefined),\n ...optional('name', typeof d.name === 'string' ? d.name : undefined),\n ...(isRecord(d.customProperties)\n ? { customProperties: d.customProperties as CustomProperties }\n : {}),\n ...optional('extra', extraOf(d, DIAGRAM_KEYS)),\n };\n }\n\n const model: AnyIstarModel = {\n elements,\n links,\n ...optional('diagram', diagram),\n ...optional('tool', typeof json.tool === 'string' ? json.tool : undefined),\n ...optional('istar', typeof json.istar === 'string' ? json.istar : undefined),\n ...optional('saveDate', typeof json.saveDate === 'string' ? json.saveDate : undefined),\n ...optional('extraDisplay', extraDisplay),\n ...optional('extra', extraOf(json, TOP_LEVEL_KEY_SET)),\n };\n layouts.set(model, { keys: Object.keys(json), display: Object.keys(display) });\n return withMetamodel(model, metamodel);\n}\n\nfunction optional<K extends string, V>(key: K, value: V | undefined): { [P in K]?: V } {\n return (value === undefined ? {} : { [key]: value }) as { [P in K]?: V };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Serialization\n\nexport interface ToPistarOptions {\n /** Default: the model's metamodel, or iStar 2.0. Decides each kind's `type` and category. */\n metamodel?: AnyMetamodel;\n /**\n * Value for `saveDate`. Defaults to the model's own `saveDate` (so a load/save round trip is\n * lossless), or the current time for models that never had one. Pass `new Date()` when\n * saving an edited model, as piStar does.\n */\n saveDate?: string | Date;\n}\n\nfunction formatDate(date: Date): string {\n // piStar uses the deprecated `toGMTString`, an alias of `toUTCString`.\n return date.toUTCString();\n}\n\nfunction pistarTypeOf(type: string | undefined, kind: string, metamodel: AnyMetamodel): string {\n if (type === undefined) {\n throw new PistarWriteError(\n `kind \"${kind}\" is not part of ${metamodel.name}; pass its metamodel (toPistar(model, { metamodel }) or withMetamodel)`,\n );\n }\n return type;\n}\n\nfunction elementJson(element: IstarElement<string>, metamodel: AnyMetamodel): PistarElementJson {\n return {\n id: element.id,\n text: element.name,\n type: pistarTypeOf(metamodel.elements.get(element.kind)?.pistarType, element.kind, metamodel),\n x: element.x,\n y: element.y,\n ...(element.customProperties ? { customProperties: { ...element.customProperties } } : {}),\n };\n}\n\n/** Builds the save-file object for a model. `toPistar` is this plus `JSON.stringify`. */\nexport function toPistarObject<EK extends string, LK extends string>(\n input: IstarModel<EK, LK>,\n options: ToPistarOptions = {},\n): PistarFile {\n const model = input as unknown as AnyIstarModel;\n const metamodel: AnyMetamodel =\n options.metamodel ?? (metamodelOf(input) as unknown as AnyMetamodel);\n const isActorKind = (kind: string): boolean => metamodel.elements.get(kind)?.category === 'actor';\n const actors: PistarActorJson[] = [];\n const orphans: PistarElementJson[] = [];\n const dependencies: PistarDependencyJson[] = [];\n const children = new Map<string, PistarElementJson[]>();\n\n for (const element of model.elements.values()) {\n if (element.parent !== undefined && !isActorKind(element.kind)) {\n let list = children.get(element.parent);\n if (!list) children.set(element.parent, (list = []));\n list.push({ ...elementJson(element, metamodel), ...element.extra });\n }\n }\n\n for (const element of model.elements.values()) {\n if (isActorKind(element.kind)) {\n actors.push({\n ...elementJson(element, metamodel),\n nodes: children.get(element.id) ?? [],\n ...element.extra,\n });\n } else if (element.isDependum) {\n // Like piStar, derive depender/dependee from the dependency links.\n const { inbound, outbound } = dependencyLinksOf(model, element.id);\n dependencies.push({\n ...elementJson(element, metamodel),\n source: inbound?.source ?? element.dependency?.source ?? '',\n target: outbound?.target ?? element.dependency?.target ?? '',\n ...element.extra,\n });\n } else if (element.parent === undefined || !model.elements.has(element.parent)) {\n orphans.push({ ...elementJson(element, metamodel), ...element.extra });\n }\n }\n\n const links: PistarLinkJson[] = [];\n for (const link of model.links.values()) {\n links.push({\n id: link.id,\n type: pistarTypeOf(metamodel.links.get(link.kind)?.pistarType, link.kind, metamodel),\n source: link.source,\n target: link.target,\n ...(link.name !== undefined ? { name: link.name } : {}),\n ...(link.customProperties ? { customProperties: { ...link.customProperties } } : {}),\n ...(link.label !== undefined ? { label: link.label } : {}),\n ...link.extra,\n });\n }\n\n const layout = layouts.get(model);\n const display: Record<string, Record<string, unknown>> = {};\n const displayOf = (id: string): Record<string, unknown> | undefined => {\n const owner = model.elements.get(id) ?? model.links.get(id);\n if (owner) return owner.display as Record<string, unknown> | undefined;\n return model.extraDisplay?.[id] as Record<string, unknown> | undefined;\n };\n for (const id of layout?.display ?? []) {\n const entry = displayOf(id);\n if (entry !== undefined) display[id] = { ...entry };\n }\n for (const owner of [...model.elements.values(), ...model.links.values()]) {\n if (owner.display && !(owner.id in display)) display[owner.id] = { ...owner.display };\n }\n for (const [id, entry] of Object.entries(model.extraDisplay ?? {})) {\n if (!(id in display)) display[id] = entry as Record<string, unknown>;\n }\n\n let saveDate: string | undefined;\n if (options.saveDate instanceof Date) saveDate = formatDate(options.saveDate);\n else saveDate = options.saveDate ?? model.saveDate ?? formatDate(new Date());\n\n const d = model.diagram;\n const diagram: PistarDiagramJson | undefined = d && {\n ...(d.width !== undefined ? { width: d.width } : {}),\n ...(d.height !== undefined ? { height: d.height } : {}),\n ...(d.name !== undefined ? { name: d.name } : {}),\n ...(d.customProperties ? { customProperties: { ...d.customProperties } } : {}),\n ...d.extra,\n };\n\n const values: Record<string, unknown> = {\n ...model.extra,\n actors,\n orphans,\n dependencies,\n links,\n display,\n tool: model.tool,\n istar: model.istar,\n saveDate,\n diagram,\n };\n\n // Files written by older piStar versions lack some sections (e.g. `orphans`). Keep them\n // absent while they are empty, so such files round-trip unchanged.\n if (layout) {\n for (const key of ['actors', 'orphans', 'dependencies', 'links', 'display'] as const) {\n const value = values[key] as unknown[] | Record<string, unknown>;\n const empty = Array.isArray(value) ? value.length === 0 : Object.keys(value).length === 0;\n if (empty && !layout.keys.includes(key)) values[key] = undefined;\n }\n }\n\n // Emit keys in the order they had in the source file, then any new ones in piStar's order.\n const order = [...(layout?.keys ?? []), ...TOP_LEVEL_KEYS, ...Object.keys(model.extra ?? {})];\n const file: Record<string, unknown> = {};\n for (const key of order) {\n if (!(key in file) && values[key] !== undefined) file[key] = values[key];\n }\n return file as PistarFile;\n}\n\n/** Serializes a model to piStar's JSON text (2-space indentation, no trailing newline). */\nexport function toPistar<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n options?: ToPistarOptions,\n): string {\n return JSON.stringify(toPistarObject(model, options), null, 2);\n}\n","/**\n * Pure model operations. Each takes a model and returns a new one; inputs are never mutated.\n * The store (`store.ts`) wraps these with undo/redo and change events, and the React layer can\n * use them directly for controlled components.\n *\n * Behaviour follows the piStar web tool (`istarFunctions.js` and its UI):\n * - removing an actor removes its inner elements; removing an element removes its links;\n * - a dependency is two `DependencyLink`s around a dependum, and removing any of the three\n * removes the whole dependency (upstream keeps an `otherHalf` reference for this);\n * - moving an actor moves its inner elements with it (they are JointJS-embedded upstream).\n *\n * Kinds are looked up in the model's metamodel (`metamodelOf`, iStar 2.0 by default), so\n * extended actor, node, link and dependency kinds behave like their built-in counterparts.\n */\nimport type { LinkCheck } from './constraints';\nimport { canLink } from './constraints';\nimport type { ActorKind, DependencyLinkKind, ElementKind, LinkKind } from './metamodel';\nimport type { AnyMetamodel } from './metamodels';\nimport type {\n AnyIstarModel,\n CustomProperties,\n Diagram,\n ElementDisplay,\n IstarElement,\n IstarLink,\n IstarModel,\n LinkDisplay,\n} from './model';\nimport { dependencyLinksOf, inheritMetamodel, metamodelOf } from './model';\nimport { inheritSourceLayout } from './serialization';\n\nexport class ModelOperationError extends Error {\n override name = 'ModelOperationError';\n}\n\n/** Generates ids for new elements and links. piStar uses UUID v4. */\nexport type IdGenerator = () => string;\n\nexport const defaultIdGenerator: IdGenerator = () => {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n // Fallback for non-secure browser contexts, where randomUUID is unavailable.\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n const r = (Math.random() * 16) | 0;\n return (ch === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n};\n\nexport interface OperationContext {\n readonly createId?: IdGenerator;\n}\n\ntype AnyElement = IstarElement<string>;\ntype AnyLink = IstarLink<string>;\n\nfunction any<EK extends string, LK extends string>(model: IstarModel<EK, LK>): AnyIstarModel {\n return model as unknown as AnyIstarModel;\n}\n\nfunction typed<EK extends string, LK extends string>(model: AnyIstarModel): IstarModel<EK, LK> {\n return model as unknown as IstarModel<EK, LK>;\n}\n\nfunction metaOf(model: AnyIstarModel): AnyMetamodel {\n return metamodelOf(model) as unknown as AnyMetamodel;\n}\n\nfunction isActorIn(model: AnyIstarModel, kind: string): boolean {\n return metaOf(model).elements.get(kind)?.category === 'actor';\n}\n\nfunction derive(from: AnyIstarModel, changes: Partial<AnyIstarModel>): AnyIstarModel {\n return inheritMetamodel(from, inheritSourceLayout(from, { ...from, ...changes }));\n}\n\nfunction requireElement(model: AnyIstarModel, id: string): AnyElement {\n const element = model.elements.get(id);\n if (!element) throw new ModelOperationError(`unknown element \"${id}\"`);\n return element;\n}\n\nfunction requireLink(model: AnyIstarModel, id: string): AnyLink {\n const link = model.links.get(id);\n if (!link) throw new ModelOperationError(`unknown link \"${id}\"`);\n return link;\n}\n\nfunction withoutUndefined<T extends object>(value: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Elements\n\nexport interface NewElement<K extends string = ElementKind> {\n readonly kind: K;\n readonly x: number;\n readonly y: number;\n readonly id?: string;\n /** Defaults to the kind's label (\"Goal\"), like piStar. */\n readonly name?: string;\n /** Actor to place the element in. Required in practice for iStar nodes (see NodeKindInfo). */\n readonly parent?: string;\n readonly customProperties?: CustomProperties;\n readonly display?: ElementDisplay;\n}\n\nexport function addElement<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n input: NewElement<EK>,\n ctx: OperationContext = {},\n): { model: IstarModel<EK, LK>; element: IstarElement<EK> } {\n const m = any(model);\n const metamodel = metaOf(m);\n const definition = metamodel.elements.get(input.kind);\n if (!definition) {\n throw new ModelOperationError(`unknown element kind \"${input.kind}\" in ${metamodel.name}`);\n }\n const id = input.id ?? (ctx.createId ?? defaultIdGenerator)();\n if (m.elements.has(id) || m.links.has(id)) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n if (input.parent !== undefined) {\n if (definition.category === 'actor') throw new ModelOperationError('actors cannot be nested');\n if (!isActorIn(m, requireElement(m, input.parent).kind)) {\n throw new ModelOperationError(`parent \"${input.parent}\" is not an actor`);\n }\n }\n const element: AnyElement = withoutUndefined({\n id,\n kind: input.kind,\n name: input.name ?? definition.label,\n x: input.x,\n y: input.y,\n parent: input.parent,\n customProperties: input.customProperties,\n display: input.display,\n });\n const elements = new Map(m.elements).set(id, element);\n return { model: typed(derive(m, { elements })), element: element as IstarElement<EK> };\n}\n\nexport interface ElementPatch {\n readonly name?: string;\n /** Replaces the whole map. Use `null` to remove it. */\n readonly customProperties?: CustomProperties | null;\n /** Merged into the current display; a key set to `undefined` is removed. `null` clears it. */\n readonly display?: { readonly [key: string]: unknown } | null;\n}\n\nfunction mergeDisplay<D extends object>(\n current: D | undefined,\n patch: { readonly [key: string]: unknown } | null | undefined,\n): D | undefined {\n if (patch === undefined) return current;\n if (patch === null) return undefined;\n const merged: Record<string, unknown> = { ...current };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) delete merged[key];\n else merged[key] = value;\n }\n return Object.keys(merged).length > 0 ? (merged as D) : undefined;\n}\n\nexport function updateElement<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n patch: ElementPatch,\n): IstarModel<EK, LK> {\n const m = any(model);\n const current = requireElement(m, id);\n const next: AnyElement = withoutUndefined({\n ...current,\n name: patch.name ?? current.name,\n customProperties:\n patch.customProperties === undefined\n ? current.customProperties\n : (patch.customProperties ?? undefined),\n display: mergeDisplay<ElementDisplay>(current.display, patch.display),\n });\n return typed(derive(m, { elements: new Map(m.elements).set(id, next) }));\n}\n\n/**\n * Moves an element to an absolute position. Moving an actor shifts its inner elements by the\n * same offset.\n */\nexport function moveElement<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n x: number,\n y: number,\n): IstarModel<EK, LK> {\n const m = any(model);\n const current = requireElement(m, id);\n const dx = x - current.x;\n const dy = y - current.y;\n if (dx === 0 && dy === 0) return model;\n const elements = new Map(m.elements);\n elements.set(id, { ...current, x, y });\n if (isActorIn(m, current.kind)) {\n for (const child of m.elements.values()) {\n if (child.parent === id)\n elements.set(child.id, { ...child, x: child.x + dx, y: child.y + dy });\n }\n }\n return typed(derive(m, { elements }));\n}\n\n/**\n * Moves an inner element into another actor (or out of any actor with `null`). The element\n * becomes the actor's last child. Links that become invalid are kept; `validateModel` reports\n * them.\n */\nexport function nestElement<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n parent: string | null,\n): IstarModel<EK, LK> {\n const m = any(model);\n const current = requireElement(m, id);\n if (isActorIn(m, current.kind)) throw new ModelOperationError('actors cannot be nested');\n if (current.isDependum) throw new ModelOperationError('a dependum cannot be nested');\n if ((current.parent ?? null) === parent) return model;\n if (parent !== null && !isActorIn(m, requireElement(m, parent).kind)) {\n throw new ModelOperationError(`parent \"${parent}\" is not an actor`);\n }\n const elements = new Map(m.elements);\n elements.delete(id);\n const { parent: _old, ...rest } = current;\n elements.set(id, parent === null ? rest : { ...rest, parent });\n return typed(derive(m, { elements }));\n}\n\n/**\n * Removes elements and everything that depends on them: inner elements of removed actors,\n * links touching removed elements, and the rest of any dependency that loses a part.\n */\nexport function removeElements<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n ids: Iterable<string>,\n): IstarModel<EK, LK> {\n return typed(removeCascade(any(model), new Set(ids), new Set()));\n}\n\nexport function removeElement<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n): IstarModel<EK, LK> {\n requireElement(any(model), id);\n return removeElements(model, [id]);\n}\n\nfunction removeCascade(\n model: AnyIstarModel,\n elementIds: Set<string>,\n linkIds: Set<string>,\n): AnyIstarModel {\n const metamodel = metaOf(model);\n const isDependencyHalf = (link: AnyLink): boolean =>\n metamodel.links.get(link.kind)?.category === 'dependency';\n // Iterate to a fixed point: each round may remove more elements or links.\n let changed = true;\n while (changed) {\n changed = false;\n for (const element of model.elements.values()) {\n if (elementIds.has(element.id)) continue;\n if (element.parent !== undefined && elementIds.has(element.parent)) {\n elementIds.add(element.id);\n changed = true;\n }\n }\n for (const link of model.links.values()) {\n if (linkIds.has(link.id)) continue;\n if (elementIds.has(link.source) || elementIds.has(link.target)) {\n linkIds.add(link.id);\n changed = true;\n }\n }\n // A dependency that lost a half, or its dependum, goes entirely.\n for (const link of model.links.values()) {\n if (!linkIds.has(link.id) || !isDependencyHalf(link)) continue;\n for (const end of [link.source, link.target]) {\n const element = model.elements.get(end);\n if (element?.isDependum && !elementIds.has(end)) {\n elementIds.add(end);\n changed = true;\n }\n }\n }\n }\n if (elementIds.size === 0 && linkIds.size === 0) return model;\n const elements = new Map(model.elements);\n for (const id of elementIds) elements.delete(id);\n const links = new Map(model.links);\n for (const id of linkIds) links.delete(id);\n return derive(model, { elements, links });\n}\n\n// ---------------------------------------------------------------------------------------------\n// Links\n\nexport interface NewLink<K extends string = LinkKind> {\n /** Any link kind except dependency kinds (use `addDependency` for those). */\n readonly kind: Exclude<K, DependencyLinkKind>;\n readonly source: string;\n readonly target: string;\n readonly id?: string;\n /** Contribution value: make, help, hurt or break. */\n readonly label?: string;\n readonly name?: string;\n readonly customProperties?: CustomProperties;\n}\n\nexport interface ConnectOptions extends OperationContext {\n /** Skip constraint checking (used when loading or scripting known-good data). */\n readonly force?: boolean;\n /**\n * Retry with source and target swapped if the link is invalid as given. Defaults to the\n * metamodel's `tryReversedWhenAdding` (Needed-By and Qualification), as in piStar.\n */\n readonly tryReversed?: boolean;\n}\n\nexport type ConnectResult<EK extends string = ElementKind, LK extends string = LinkKind> =\n | { ok: true; model: IstarModel<EK, LK>; link: IstarLink<LK>; reversed: boolean }\n | Extract<LinkCheck, { ok: false }>;\n\n/** Adds a link between two elements if the iStar constraints allow it. */\nexport function connect<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n input: NewLink<LK>,\n options: ConnectOptions = {},\n): ConnectResult<EK, LK> {\n const m = any(model);\n const metamodel = metaOf(m);\n const kind: string = input.kind;\n const definition = metamodel.links.get(kind);\n if (definition?.category === 'dependency') {\n throw new ModelOperationError('use addDependency to create dependencies');\n }\n let { source, target } = input;\n let reversed = false;\n if (!options.force) {\n let check = canLink(m, source, target, kind);\n const tryReversed = options.tryReversed ?? definition?.info.tryReversedWhenAdding;\n if (!check.ok && tryReversed) {\n const swapped = canLink(m, target, source, kind);\n if (swapped.ok) {\n [source, target] = [target, source];\n reversed = true;\n check = swapped;\n }\n }\n if (!check.ok) return check;\n } else {\n if (!definition) {\n throw new ModelOperationError(`unknown link kind \"${kind}\" in ${metamodel.name}`);\n }\n requireElement(m, source);\n requireElement(m, target);\n }\n const id = input.id ?? (options.createId ?? defaultIdGenerator)();\n if (m.elements.has(id) || m.links.has(id)) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n const link: AnyLink = withoutUndefined({\n id,\n kind,\n source,\n target,\n label: input.label,\n name: input.name,\n customProperties: input.customProperties,\n });\n return {\n ok: true,\n model: typed(derive(m, { links: new Map(m.links).set(id, link) })),\n link: link as IstarLink<LK>,\n reversed,\n };\n}\n\nexport interface NewDependency<EK extends string = ElementKind, LK extends string = LinkKind> {\n /** The depender: an actor or one of its inner elements. */\n readonly depender: string;\n /** The dependee: an actor or one of its inner elements. */\n readonly dependee: string;\n readonly dependum: {\n /** A node kind (built-in or extended) that can be a dependum. */\n readonly kind: Exclude<EK, ActorKind>;\n readonly name?: string;\n readonly id?: string;\n /** Defaults to the midpoint between depender and dependee, as in piStar. */\n readonly x?: number;\n readonly y?: number;\n readonly customProperties?: CustomProperties;\n };\n /** A dependency link kind. Default `istar.DependencyLink`. */\n readonly linkKind?: LK;\n readonly linkIds?: readonly [string, string];\n}\n\nexport type AddDependencyResult<EK extends string = ElementKind, LK extends string = LinkKind> =\n | {\n ok: true;\n model: IstarModel<EK, LK>;\n dependum: IstarElement<EK>;\n links: readonly [IstarLink<LK>, IstarLink<LK>];\n }\n | Extract<LinkCheck, { ok: false }>;\n\n/** Adds depender → dependum → dependee. */\nexport function addDependency<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n input: NewDependency<EK, LK>,\n options: Omit<ConnectOptions, 'tryReversed'> = {},\n): AddDependencyResult<EK, LK> {\n const m = any(model);\n const metamodel = metaOf(m);\n const dependumKind: string = input.dependum.kind;\n const dependumDefinition = metamodel.elements.get(dependumKind);\n if (dependumDefinition?.category !== 'node' || dependumDefinition.info?.canBeDependum === false) {\n throw new ModelOperationError(`${dependumKind} cannot be a dependum`);\n }\n const linkKind: string = input.linkKind ?? 'istar.DependencyLink';\n if (metamodel.links.get(linkKind)?.category !== 'dependency') {\n throw new ModelOperationError(`${linkKind} is not a dependency link kind`);\n }\n if (!options.force) {\n const check = canLink(m, input.depender, input.dependee, linkKind);\n if (!check.ok) return check;\n }\n const depender = requireElement(m, input.depender);\n const dependee = requireElement(m, input.dependee);\n const createId = options.createId ?? defaultIdGenerator;\n const added = addElement(\n m,\n {\n kind: dependumKind,\n id: input.dependum.id,\n name: input.dependum.name,\n x: input.dependum.x ?? (depender.x + dependee.x) / 2,\n y: input.dependum.y ?? (depender.y + dependee.y) / 2,\n customProperties: input.dependum.customProperties,\n },\n { createId },\n );\n const dependum: AnyElement = { ...added.element, isDependum: true };\n const [id1, id2] = input.linkIds ?? [createId(), createId()];\n const first: AnyLink = { id: id1, kind: linkKind, source: depender.id, target: dependum.id };\n const second: AnyLink = { id: id2, kind: linkKind, source: dependum.id, target: dependee.id };\n for (const id of [id1, id2]) {\n if (added.model.elements.has(id) || added.model.links.has(id) || id1 === id2) {\n throw new ModelOperationError(`id \"${id}\" is already in use`);\n }\n }\n return {\n ok: true,\n model: typed(\n derive(m, {\n elements: new Map(added.model.elements).set(dependum.id, dependum),\n links: new Map(m.links).set(id1, first).set(id2, second),\n }),\n ),\n dependum: dependum as IstarElement<EK>,\n links: [first as IstarLink<LK>, second as IstarLink<LK>],\n };\n}\n\n/** Removes a link. Removing either half of a dependency removes the whole dependency. */\nexport function disconnect<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n): IstarModel<EK, LK> {\n const m = any(model);\n requireLink(m, id);\n return typed(removeCascade(m, new Set(), new Set([id])));\n}\n\nexport interface LinkPatch {\n /** `null` removes it. */\n readonly label?: string | null;\n readonly name?: string | null;\n readonly customProperties?: CustomProperties | null;\n readonly display?: { readonly [key: string]: unknown } | null;\n}\n\nfunction pick<T>(value: T | null | undefined, fallback: T | undefined): T | undefined {\n return value === undefined ? fallback : (value ?? undefined);\n}\n\nexport function updateLink<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n id: string,\n patch: LinkPatch,\n): IstarModel<EK, LK> {\n const m = any(model);\n const current = requireLink(m, id);\n const next: AnyLink = withoutUndefined({\n ...current,\n label: pick(patch.label, current.label),\n name: pick(patch.name, current.name),\n customProperties: pick(patch.customProperties, current.customProperties),\n display: mergeDisplay<LinkDisplay>(current.display, patch.display),\n });\n return typed(derive(m, { links: new Map(m.links).set(id, next) }));\n}\n\n// ---------------------------------------------------------------------------------------------\n// Diagram\n\nexport function updateDiagram<EK extends string = ElementKind, LK extends string = LinkKind>(\n model: IstarModel<EK, LK>,\n patch: Partial<Diagram>,\n): IstarModel<EK, LK> {\n const m = any(model);\n return typed(derive(m, { diagram: withoutUndefined({ ...m.diagram, ...patch }) }));\n}\n\n/** Where dependency depender/dependee currently point (see `dependencyLinksOf`). */\nexport function dependencyEnds<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n dependumId: string,\n): { depender?: string; dependee?: string } {\n const { inbound, outbound } = dependencyLinksOf(model, dependumId);\n const fallback = model.elements.get(dependumId)?.dependency;\n return {\n depender: inbound?.source ?? fallback?.source,\n dependee: outbound?.target ?? fallback?.target,\n };\n}\n","/**\n * An event-emitting store around an immutable `IstarModel`, with undo/redo.\n *\n * Every mutation produces a new model snapshot; history is a stack of snapshots, which is cheap\n * because unchanged elements and links are shared between snapshots. This replaces piStar's\n * `undoManager.js`, which stacked hand-written undo closures.\n *\n * `subscribe` + `getModel` match React's `useSyncExternalStore` contract.\n */\nimport type { LinkCheck } from './constraints';\nimport { canLink } from './constraints';\nimport type { ElementKind, LinkKind } from './metamodel';\nimport type { Metamodel } from './metamodels';\nimport type { AnyIstarModel, Diagram, IstarElement, IstarModel } from './model';\nimport { createEmptyModel } from './model';\nimport type {\n ConnectOptions,\n ElementPatch,\n IdGenerator,\n LinkPatch,\n NewDependency,\n NewElement,\n NewLink,\n} from './operations';\nimport * as ops from './operations';\n\n/** What happened, for listeners that want more than the new snapshot. */\nexport type ModelChange =\n | { type: 'addElement'; id: string }\n | { type: 'updateElement'; id: string; patch: ElementPatch }\n | { type: 'moveElement'; id: string; x: number; y: number }\n | { type: 'nestElement'; id: string; parent: string | null }\n | { type: 'removeElements'; ids: readonly string[] }\n | { type: 'connect'; id: string }\n | { type: 'addDependency'; dependumId: string; linkIds: readonly [string, string] }\n | { type: 'updateLink'; id: string; patch: LinkPatch }\n | { type: 'disconnect'; id: string }\n | { type: 'updateDiagram'; patch: Partial<Diagram> }\n | { type: 'replace' };\n\nexport interface ModelChangeEvent<EK extends string = ElementKind, LK extends string = LinkKind> {\n readonly model: IstarModel<EK, LK>;\n readonly previous: IstarModel<EK, LK>;\n /** `undo`/`redo`/`load` carry no changes; a transaction carries all of its changes. */\n readonly changes: readonly ModelChange[];\n readonly source: 'edit' | 'undo' | 'redo' | 'load';\n}\n\nexport type ModelListener<EK extends string = ElementKind, LK extends string = LinkKind> = (\n event: ModelChangeEvent<EK, LK>,\n) => void;\n\nexport interface ModelStoreOptions<EK extends string = ElementKind, LK extends string = LinkKind> {\n /**\n * Metamodel for the default empty model, when no initial model is given. A given initial\n * model keeps its own (see `metamodelOf`).\n */\n readonly metamodel?: Metamodel<EK, LK>;\n readonly createId?: IdGenerator;\n /** Maximum number of undo steps kept. Default 100. */\n readonly historyLimit?: number;\n}\n\nexport interface ModelStore<EK extends string = ElementKind, LK extends string = LinkKind> {\n getModel(): IstarModel<EK, LK>;\n /** Returns an unsubscribe function. */\n subscribe(listener: ModelListener<EK, LK>): () => void;\n\n canLink(\n source: string | IstarElement<EK>,\n target: string | IstarElement<EK>,\n kind: LK,\n ): LinkCheck;\n\n addElement(input: NewElement<EK>): IstarElement<EK>;\n updateElement(id: string, patch: ElementPatch): void;\n moveElement(id: string, x: number, y: number): void;\n nestElement(id: string, parent: string | null): void;\n removeElement(id: string): void;\n removeElements(ids: Iterable<string>): void;\n setCollapsed(actorId: string, collapsed: boolean): void;\n\n connect(\n input: NewLink<LK>,\n options?: Omit<ConnectOptions, 'createId'>,\n ): ops.ConnectResult<EK, LK>;\n addDependency(\n input: NewDependency<EK, LK>,\n options?: Omit<ConnectOptions, 'createId' | 'tryReversed'>,\n ): ops.AddDependencyResult<EK, LK>;\n updateLink(id: string, patch: LinkPatch): void;\n disconnect(id: string): void;\n updateDiagram(patch: Partial<Diagram>): void;\n\n /** Replaces the model as one undoable edit. */\n replace(model: IstarModel<EK, LK>): void;\n /** Replaces the model and clears history (like opening a file in piStar). */\n load(model: IstarModel<EK, LK>): void;\n\n /**\n * Groups several edits into one undo step and one change event. Nested calls join the\n * outermost transaction. If `fn` throws, the model is rolled back.\n */\n transaction<T>(fn: () => T): T;\n\n undo(): boolean;\n redo(): boolean;\n canUndo(): boolean;\n canRedo(): boolean;\n clearHistory(): void;\n}\n\n// The iStar 2.0 overload comes last, so function references type as before.\nexport function createModelStore<EK extends string, LK extends string>(\n initial: IstarModel<EK, LK>,\n options?: ModelStoreOptions<EK, LK>,\n): ModelStore<EK, LK>;\nexport function createModelStore<EK extends string, LK extends string>(\n initial: undefined,\n options: ModelStoreOptions<EK, LK> & { readonly metamodel: Metamodel<EK, LK> },\n): ModelStore<EK, LK>;\nexport function createModelStore(initial?: IstarModel, options?: ModelStoreOptions): ModelStore;\nexport function createModelStore(\n initial?: AnyIstarModel,\n options: ModelStoreOptions<string, string> = {},\n): ModelStore<string, string> {\n initial ??= options.metamodel\n ? createEmptyModel(undefined, { metamodel: options.metamodel })\n : (createEmptyModel() as AnyIstarModel);\n const limit = options.historyLimit ?? 100;\n const ctx = { createId: options.createId ?? ops.defaultIdGenerator };\n const listeners = new Set<ModelListener<string, string>>();\n let model = initial;\n let past: AnyIstarModel[] = [];\n let future: AnyIstarModel[] = [];\n let tx: { start: AnyIstarModel; changes: ModelChange[]; depth: number } | undefined;\n\n const emit = (event: ModelChangeEvent<string, string>): void => {\n for (const listener of listeners) listener(event);\n };\n\n const commit = (next: AnyIstarModel, change: ModelChange): void => {\n if (next === model) return;\n if (tx) {\n model = next;\n tx.changes.push(change);\n return;\n }\n const previous = model;\n past.push(previous);\n if (past.length > limit) past = past.slice(past.length - limit);\n future = [];\n model = next;\n emit({ model, previous, changes: [change], source: 'edit' });\n };\n\n const store: ModelStore<string, string> = {\n getModel: () => model,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n\n canLink: (source, target, kind) => canLink(model, source, target, kind),\n\n addElement(input) {\n const result = ops.addElement(model, input, ctx);\n commit(result.model, { type: 'addElement', id: result.element.id });\n return result.element;\n },\n updateElement(id, patch) {\n commit(ops.updateElement(model, id, patch), { type: 'updateElement', id, patch });\n },\n moveElement(id, x, y) {\n commit(ops.moveElement(model, id, x, y), { type: 'moveElement', id, x, y });\n },\n nestElement(id, parent) {\n commit(ops.nestElement(model, id, parent), { type: 'nestElement', id, parent });\n },\n removeElement(id) {\n commit(ops.removeElement(model, id), { type: 'removeElements', ids: [id] });\n },\n removeElements(ids) {\n const list = [...ids];\n commit(ops.removeElements(model, list), { type: 'removeElements', ids: list });\n },\n setCollapsed(actorId, collapsed) {\n const patch = { display: { collapsed: collapsed ? true : undefined } };\n commit(ops.updateElement(model, actorId, patch), {\n type: 'updateElement',\n id: actorId,\n patch,\n });\n },\n\n connect(input, connectOptions) {\n const result = ops.connect(model, input, { ...connectOptions, ...ctx });\n if (result.ok) commit(result.model, { type: 'connect', id: result.link.id });\n return result;\n },\n addDependency(input, dependencyOptions) {\n const result = ops.addDependency(model, input, { ...dependencyOptions, ...ctx });\n if (result.ok) {\n commit(result.model, {\n type: 'addDependency',\n dependumId: result.dependum.id,\n linkIds: [result.links[0].id, result.links[1].id],\n });\n }\n return result;\n },\n updateLink(id, patch) {\n commit(ops.updateLink(model, id, patch), { type: 'updateLink', id, patch });\n },\n disconnect(id) {\n commit(ops.disconnect(model, id), { type: 'disconnect', id });\n },\n updateDiagram(patch) {\n commit(ops.updateDiagram(model, patch), { type: 'updateDiagram', patch });\n },\n\n replace(next) {\n commit(next, { type: 'replace' });\n },\n load(next) {\n if (tx) throw new ops.ModelOperationError('cannot load inside a transaction');\n const previous = model;\n model = next;\n past = [];\n future = [];\n emit({ model, previous, changes: [], source: 'load' });\n },\n\n transaction<T>(fn: () => T): T {\n if (tx) {\n tx.depth++;\n try {\n return fn();\n } finally {\n tx.depth--;\n }\n }\n tx = { start: model, changes: [], depth: 1 };\n let result: T;\n try {\n result = fn();\n } catch (error) {\n model = tx.start;\n tx = undefined;\n throw error;\n }\n const { start, changes } = tx;\n tx = undefined;\n if (model !== start) {\n past.push(start);\n if (past.length > limit) past = past.slice(past.length - limit);\n future = [];\n emit({ model, previous: start, changes, source: 'edit' });\n }\n return result;\n },\n\n undo() {\n const previous = past.pop();\n if (!previous || tx) return false;\n future.push(model);\n const current = model;\n model = previous;\n emit({ model, previous: current, changes: [], source: 'undo' });\n return true;\n },\n redo() {\n const next = future.pop();\n if (!next || tx) return false;\n past.push(model);\n const current = model;\n model = next;\n emit({ model, previous: current, changes: [], source: 'redo' });\n return true;\n },\n canUndo: () => past.length > 0,\n canRedo: () => future.length > 0,\n clearHistory() {\n past = [];\n future = [];\n },\n };\n return store;\n}\n","import type { ElementKind, LinkKind } from './metamodel';\nimport type { CustomProperties, IstarModel } from './model';\n\nexport type PropertyResult<T> = { ok: true; value: T } | { ok: false; error: string };\n\nexport interface PropertyOptions<T> {\n default?: T;\n optional?: boolean;\n label?: string;\n description?: string;\n}\n\nexport interface PropertyType<T> {\n readonly type: 'string' | 'number' | 'boolean' | 'enum';\n readonly options: PropertyOptions<T>;\n readonly values?: readonly string[];\n readonly integer?: boolean;\n readonly min?: number;\n readonly max?: number;\n parse(raw: string): PropertyResult<T>;\n serialize(value: T): string;\n}\n\nexport function string(options?: PropertyOptions<string>): PropertyType<string> {\n const opts: PropertyOptions<string> = options ?? {};\n return {\n type: 'string',\n options: opts,\n parse(raw: string): PropertyResult<string> {\n return { ok: true, value: raw };\n },\n serialize(value: string): string {\n return value;\n },\n };\n}\n\nexport function number(\n options?: PropertyOptions<number> & { integer?: boolean; min?: number; max?: number },\n): PropertyType<number> {\n const opts: PropertyOptions<number> = options ?? {};\n const integer = options?.integer;\n const min = options?.min;\n const max = options?.max;\n return {\n type: 'number',\n options: opts,\n integer,\n min,\n max,\n parse(raw: string): PropertyResult<number> {\n const value = Number(raw);\n if (!Number.isFinite(value)) {\n return { ok: false, error: 'must be a finite number' };\n }\n if (integer && !Number.isInteger(value)) {\n return { ok: false, error: 'must be an integer' };\n }\n if (min !== undefined && value < min) {\n return { ok: false, error: `must be at least ${min}` };\n }\n if (max !== undefined && value > max) {\n return { ok: false, error: `must be at most ${max}` };\n }\n return { ok: true, value };\n },\n serialize(value: number): string {\n return String(value);\n },\n };\n}\n\nexport function boolean(options?: PropertyOptions<boolean>): PropertyType<boolean> {\n const opts: PropertyOptions<boolean> = options ?? {};\n return {\n type: 'boolean',\n options: opts,\n parse(raw: string): PropertyResult<boolean> {\n if (raw === 'true') return { ok: true, value: true };\n if (raw === 'false') return { ok: true, value: false };\n return { ok: false, error: 'must be true or false' };\n },\n serialize(value: boolean): string {\n return value ? 'true' : 'false';\n },\n };\n}\n\nexport function enumOf<const V extends readonly string[]>(\n values: V,\n options?: PropertyOptions<V[number]>,\n): PropertyType<V[number]> {\n const opts: PropertyOptions<V[number]> = options ?? {};\n return {\n type: 'enum',\n options: opts,\n values,\n parse(raw: string): PropertyResult<V[number]> {\n if ((values as readonly string[]).includes(raw)) {\n return { ok: true, value: raw as V[number] };\n }\n return { ok: false, error: `must be one of: ${values.join(', ')}` };\n },\n serialize(value: V[number]): string {\n return value;\n },\n };\n}\n\nexport const prop: {\n string: typeof string;\n number: typeof number;\n boolean: typeof boolean;\n enum: typeof enumOf;\n} = {\n string,\n number,\n boolean,\n enum: enumOf,\n};\n\nexport type PropertyShape = Record<string, PropertyType<unknown>>;\n\nexport type InferProperties<S extends PropertyShape> = {\n [K in keyof S]: S[K] extends PropertyType<infer T> ? T : never;\n};\n\nexport interface PropertyIssue {\n key: string;\n message: string;\n}\n\n/**\n * Typed custom properties of one element or link kind. `K` is the kind: iStar 2.0's kinds by\n * default; any extension kind (see `extendMetamodel`) is accepted too.\n */\nexport interface PropertySchema<\n S extends PropertyShape = PropertyShape,\n K extends string = ElementKind | LinkKind,\n> {\n readonly kind: K;\n readonly shape: S;\n read(source: CustomProperties | undefined | PropertyOwner): {\n values: Partial<InferProperties<S>>;\n issues: PropertyIssue[];\n };\n validate(source: CustomProperties | undefined | PropertyOwner): PropertyIssue[];\n write(\n current: CustomProperties | undefined,\n patch: { [K in keyof S]?: InferProperties<S>[K] | undefined },\n ): CustomProperties;\n defaults(): CustomProperties;\n}\n\n/** An element or link, read through its `customProperties`. */\nexport interface PropertyOwner {\n readonly kind: string;\n readonly customProperties?: CustomProperties;\n}\n\nexport interface ModelPropertyIssue extends PropertyIssue {\n id: string;\n}\n\ntype PropertySource = CustomProperties | undefined | PropertyOwner;\n\nfunction isCustomPropertiesRecord(source: NonNullable<PropertySource>): source is CustomProperties {\n // Elements and links are passed whole, possibly without `customProperties`; recognize them by\n // their `istar.*` kind and numeric/structural fields a bag of strings can't have.\n if ('customProperties' in source) return false;\n const owner = source as { kind?: unknown; x?: unknown; source?: unknown; target?: unknown };\n const isModelObject =\n typeof owner.kind === 'string' &&\n owner.kind.startsWith('istar.') &&\n (typeof owner.x === 'number' || (owner.source !== undefined && owner.target !== undefined));\n return !isModelObject;\n}\n\nfunction resolveCustomProperties(source: PropertySource): CustomProperties | undefined {\n if (source === undefined) return undefined;\n if (isCustomPropertiesRecord(source)) return source;\n return source.customProperties;\n}\n\nfunction isRequired(options: PropertyOptions<unknown>): boolean {\n return options.optional !== true && options.default === undefined;\n}\n\nfunction emptyMeansAbsent(\n type: PropertyType<unknown>['type'],\n optional: boolean | undefined,\n): boolean {\n return type !== 'string' && optional === true;\n}\n\nfunction readShape<S extends PropertyShape>(\n shape: S,\n source: PropertySource,\n): { values: Partial<InferProperties<S>>; issues: PropertyIssue[] } {\n const custom = resolveCustomProperties(source);\n const values: Partial<InferProperties<S>> = {};\n const issues: PropertyIssue[] = [];\n\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n const field = shape[key];\n if (!field) continue;\n const opts = field.options;\n const hasKey = custom !== undefined && Object.prototype.hasOwnProperty.call(custom, key);\n const raw = hasKey ? custom[key] : undefined;\n\n if (raw === undefined) {\n if (opts.default !== undefined) {\n (values as Record<string, unknown>)[key] = opts.default;\n } else if (isRequired(opts)) {\n issues.push({ key, message: 'is required' });\n }\n continue;\n }\n\n if (raw === '' && field.type !== 'string') {\n if (emptyMeansAbsent(field.type, opts.optional)) {\n if (opts.default !== undefined) {\n (values as Record<string, unknown>)[key] = opts.default;\n }\n continue;\n }\n issues.push({\n key,\n message:\n field.type === 'boolean'\n ? 'must be true or false'\n : field.type === 'enum'\n ? `must be one of: ${field.values?.join(', ') ?? ''}`\n : 'must be a finite number',\n });\n continue;\n }\n\n const parsed = field.parse(raw);\n if (!parsed.ok) {\n issues.push({ key, message: parsed.error });\n continue;\n }\n (values as Record<string, unknown>)[key] = parsed.value;\n }\n\n return { values, issues };\n}\n\nexport function defineProperties<\n const S extends PropertyShape,\n const Kind extends string = ElementKind | LinkKind,\n>(\n kind: Kind,\n shape: S,\n options?: { validate?: (values: Partial<InferProperties<S>>) => PropertyIssue[] },\n): PropertySchema<S, Kind> {\n const crossValidate = options?.validate;\n\n return {\n kind,\n shape,\n read(source: PropertySource): { values: Partial<InferProperties<S>>; issues: PropertyIssue[] } {\n return readShape(shape, source);\n },\n validate(source: PropertySource): PropertyIssue[] {\n const { values, issues } = readShape(shape, source);\n const cross = crossValidate ? crossValidate(values) : [];\n return [...issues, ...cross];\n },\n write(\n current: CustomProperties | undefined,\n patch: { [K in keyof S]?: InferProperties<S>[K] | undefined },\n ): CustomProperties {\n const result: Record<string, string> = {};\n const seen = new Set<string>();\n\n if (current) {\n for (const [key, value] of Object.entries(current)) {\n if (Object.prototype.hasOwnProperty.call(patch, key)) {\n const patched = patch[key as keyof S];\n if (patched === undefined) {\n continue;\n }\n const field = shape[key];\n if (field) {\n result[key] = field.serialize(patched as never);\n }\n } else {\n result[key] = value;\n }\n seen.add(key);\n }\n }\n\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n if (seen.has(key)) continue;\n if (!Object.prototype.hasOwnProperty.call(patch, key)) continue;\n const patched = patch[key];\n if (patched === undefined) continue;\n const field = shape[key];\n if (field) {\n result[key] = field.serialize(patched as never);\n }\n }\n\n return result;\n },\n defaults(): CustomProperties {\n const result: Record<string, string> = {};\n for (const key of Object.keys(shape) as (keyof S & string)[]) {\n const field = shape[key];\n if (!field) continue;\n const def = field.options.default;\n if (def !== undefined) {\n result[key] = field.serialize(def as never);\n }\n }\n return result;\n },\n };\n}\n\nexport function validateModelProperties<EK extends string, LK extends string>(\n model: IstarModel<EK, LK>,\n schemas: readonly PropertySchema<PropertyShape, string>[],\n): ModelPropertyIssue[] {\n const byKind = new Map<string, PropertySchema<PropertyShape, string>[]>();\n for (const schema of schemas) {\n const list = byKind.get(schema.kind) ?? [];\n list.push(schema);\n byKind.set(schema.kind, list);\n }\n\n const issues: ModelPropertyIssue[] = [];\n\n for (const element of model.elements.values()) {\n const kindSchemas = byKind.get(element.kind);\n if (!kindSchemas) continue;\n for (const schema of kindSchemas) {\n for (const issue of schema.validate(element)) {\n issues.push({ ...issue, id: element.id });\n }\n }\n }\n\n for (const link of model.links.values()) {\n const kindSchemas = byKind.get(link.kind);\n if (!kindSchemas) continue;\n for (const schema of kindSchemas) {\n for (const issue of schema.validate(link)) {\n issues.push({ ...issue, id: link.id });\n }\n }\n }\n\n return issues;\n}\n"],"mappings":"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"}