@istar-ts/core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1486 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +578 -0
- package/package.json +12 -5
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
//#endregion
|
|
2
|
+
//#region src/metamodel.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The iStar 2.0 metamodel, ported from piStar's `tool/language/metamodel.js`.
|
|
5
|
+
*
|
|
6
|
+
* Kind names carry the `istar.` prefix exactly as they appear in piStar save files.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ISTAR_PREFIX = "istar";
|
|
9
|
+
export declare const METAMODEL_VERSION = "0.2";
|
|
10
|
+
/** Containers: elements that hold inner elements (piStar `metamodel.containers`). */
|
|
11
|
+
export declare const ACTOR_KINDS: readonly ["istar.Actor", "istar.Agent", "istar.Role"];
|
|
12
|
+
export type ActorKind = (typeof ACTOR_KINDS)[number];
|
|
13
|
+
/** Intentional elements (piStar `metamodel.nodes`). */
|
|
14
|
+
export declare const NODE_KINDS: readonly ["istar.Goal", "istar.Quality", "istar.Resource", "istar.Task"];
|
|
15
|
+
export type NodeKind = (typeof NODE_KINDS)[number];
|
|
16
|
+
export type ElementKind = ActorKind | NodeKind;
|
|
17
|
+
export declare const ELEMENT_KINDS: readonly ElementKind[];
|
|
18
|
+
/** Links between two containers (piStar `metamodel.containerLinks`). */
|
|
19
|
+
export declare const ACTOR_LINK_KINDS: readonly ["istar.IsALink", "istar.ParticipatesInLink"];
|
|
20
|
+
export type ActorLinkKind = (typeof ACTOR_LINK_KINDS)[number];
|
|
21
|
+
/** Links that connect two containers through a dependum (piStar `metamodel.dependencyLinks`). */
|
|
22
|
+
export declare const DEPENDENCY_LINK_KINDS: readonly ["istar.DependencyLink"];
|
|
23
|
+
export type DependencyLinkKind = (typeof DEPENDENCY_LINK_KINDS)[number];
|
|
24
|
+
/** Links between two intentional elements (piStar `metamodel.nodeLinks`). */
|
|
25
|
+
export declare const NODE_LINK_KINDS: readonly ["istar.AndRefinementLink", "istar.OrRefinementLink", "istar.NeededByLink", "istar.QualificationLink", "istar.ContributionLink"];
|
|
26
|
+
export type NodeLinkKind = (typeof NODE_LINK_KINDS)[number];
|
|
27
|
+
export type LinkKind = ActorLinkKind | DependencyLinkKind | NodeLinkKind;
|
|
28
|
+
export declare const LINK_KINDS: readonly LinkKind[];
|
|
29
|
+
/** Possible values of a Contribution link's `label`. */
|
|
30
|
+
export declare const CONTRIBUTION_LABELS: readonly ["make", "help", "hurt", "break"];
|
|
31
|
+
export type ContributionLabel = (typeof CONTRIBUTION_LABELS)[number];
|
|
32
|
+
export interface NodeKindInfo {
|
|
33
|
+
/** Can be added inside an actor. */
|
|
34
|
+
readonly canBeInnerElement: boolean;
|
|
35
|
+
/** Can be the dependum of a dependency. */
|
|
36
|
+
readonly canBeDependum: boolean;
|
|
37
|
+
/** Can be placed directly on the diagram, outside any actor. */
|
|
38
|
+
readonly canBeOnPaper: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface LinkKindInfo {
|
|
41
|
+
/** Fixed text drawn on the link (e.g. "is-a"). */
|
|
42
|
+
readonly label?: string;
|
|
43
|
+
/** piStar retries with source and target swapped when the first attempt is invalid. */
|
|
44
|
+
readonly tryReversedWhenAdding?: boolean;
|
|
45
|
+
/** The link carries a user-selectable label, stored as `label` in the save file. */
|
|
46
|
+
readonly changeableLabel?: boolean;
|
|
47
|
+
readonly possibleLabels?: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
export declare const NODE_KIND_INFO: Readonly<Record<NodeKind, NodeKindInfo>>;
|
|
50
|
+
export declare const LINK_KIND_INFO: Readonly<Record<LinkKind, LinkKindInfo>>;
|
|
51
|
+
export interface Size {
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Default sizes of each element kind, from piStar's `shapes.js`. For actors this is the
|
|
57
|
+
* initial boundary size; the collapsed actor symbol is a circle of radius 40.
|
|
58
|
+
*/
|
|
59
|
+
export declare const DEFAULT_ELEMENT_SIZE: Readonly<Record<ElementKind, Size>>;
|
|
60
|
+
export declare function isActorKind(kind: string): kind is ActorKind;
|
|
61
|
+
export declare function isNodeKind(kind: string): kind is NodeKind;
|
|
62
|
+
export declare function isElementKind(kind: string): kind is ElementKind;
|
|
63
|
+
export declare function isLinkKind(kind: string): kind is LinkKind;
|
|
64
|
+
export declare function isActorLinkKind(kind: string): kind is ActorLinkKind;
|
|
65
|
+
export declare function isNodeLinkKind(kind: string): kind is NodeLinkKind;
|
|
66
|
+
export declare function isDependencyLinkKind(kind: string): kind is DependencyLinkKind;
|
|
67
|
+
export declare function isContributionLabel(value: string): value is ContributionLabel;
|
|
68
|
+
/** `'istar.Goal'` → `'Goal'` */
|
|
69
|
+
export declare function shortKindName(kind: ElementKind | LinkKind): string;
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/model.d.ts
|
|
72
|
+
/**
|
|
73
|
+
* piStar stores every custom property value as a string (e.g. `"initialValue": "false"`).
|
|
74
|
+
* Typed access is layered on top with property schemas (see `properties.ts`).
|
|
75
|
+
*/
|
|
76
|
+
export type CustomProperties = Readonly<Record<string, string>>;
|
|
77
|
+
/** Arbitrary JSON keys the library does not interpret; kept so they survive a round trip. */
|
|
78
|
+
export type Extra = Readonly<Record<string, unknown>>;
|
|
79
|
+
export interface Point {
|
|
80
|
+
readonly x: number;
|
|
81
|
+
readonly y: number;
|
|
82
|
+
}
|
|
83
|
+
/** Per-element entry of the save file's `display` section. */
|
|
84
|
+
export interface ElementDisplay {
|
|
85
|
+
readonly backgroundColor?: string;
|
|
86
|
+
readonly width?: number;
|
|
87
|
+
readonly height?: number;
|
|
88
|
+
/** Actors only. */
|
|
89
|
+
readonly collapsed?: boolean;
|
|
90
|
+
readonly [key: string]: unknown;
|
|
91
|
+
}
|
|
92
|
+
/** Per-link entry of the save file's `display` section. */
|
|
93
|
+
export interface LinkDisplay {
|
|
94
|
+
readonly vertices?: readonly Point[];
|
|
95
|
+
readonly [key: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
export interface IstarElement<K extends ElementKind = ElementKind> {
|
|
98
|
+
readonly id: string;
|
|
99
|
+
readonly kind: K;
|
|
100
|
+
/** The element's label; `text` in the save file. */
|
|
101
|
+
readonly name: string;
|
|
102
|
+
/** Absolute diagram coordinates, as in the save file (children are not relative to actors). */
|
|
103
|
+
readonly x: number;
|
|
104
|
+
readonly y: number;
|
|
105
|
+
/** Id of the containing actor, for inner elements. */
|
|
106
|
+
readonly parent?: string;
|
|
107
|
+
/** True when the element is the dependum of a dependency (lives in `dependencies`). */
|
|
108
|
+
readonly isDependum?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Depender/dependee recorded in the save file for a dependum. The dependency links are the
|
|
111
|
+
* source of truth; this is only a fallback used when those links are missing.
|
|
112
|
+
*/
|
|
113
|
+
readonly dependency?: {
|
|
114
|
+
readonly source: string;
|
|
115
|
+
readonly target: string;
|
|
116
|
+
};
|
|
117
|
+
readonly customProperties?: CustomProperties;
|
|
118
|
+
readonly display?: ElementDisplay;
|
|
119
|
+
readonly extra?: Extra;
|
|
120
|
+
}
|
|
121
|
+
export type IstarActor = IstarElement<ActorKind>;
|
|
122
|
+
export type IstarNode = IstarElement<NodeKind>;
|
|
123
|
+
export interface IstarLink<K extends LinkKind = LinkKind> {
|
|
124
|
+
readonly id: string;
|
|
125
|
+
readonly kind: K;
|
|
126
|
+
readonly source: string;
|
|
127
|
+
readonly target: string;
|
|
128
|
+
/** Contribution value (`make`/`help`/`hurt`/`break`), stored as `label` in the save file. */
|
|
129
|
+
readonly label?: string;
|
|
130
|
+
readonly name?: string;
|
|
131
|
+
readonly customProperties?: CustomProperties;
|
|
132
|
+
readonly display?: LinkDisplay;
|
|
133
|
+
readonly extra?: Extra;
|
|
134
|
+
}
|
|
135
|
+
export interface Diagram {
|
|
136
|
+
readonly width?: number;
|
|
137
|
+
readonly height?: number;
|
|
138
|
+
readonly name?: string;
|
|
139
|
+
readonly customProperties?: CustomProperties;
|
|
140
|
+
readonly extra?: Extra;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* An immutable iStar model. Maps preserve insertion order, which is the order elements and
|
|
144
|
+
* links are written back to disk.
|
|
145
|
+
*/
|
|
146
|
+
export interface IstarModel {
|
|
147
|
+
readonly elements: ReadonlyMap<string, IstarElement>;
|
|
148
|
+
readonly links: ReadonlyMap<string, IstarLink>;
|
|
149
|
+
readonly diagram?: Diagram;
|
|
150
|
+
readonly tool?: string;
|
|
151
|
+
readonly istar?: string;
|
|
152
|
+
readonly saveDate?: string;
|
|
153
|
+
/** `display` entries whose id matches no element or link. */
|
|
154
|
+
readonly extraDisplay?: Extra;
|
|
155
|
+
/** Unknown top-level keys (e.g. `metamodelVersion`). */
|
|
156
|
+
readonly extra?: Extra;
|
|
157
|
+
}
|
|
158
|
+
/** Tool identifier written by piStar 2.1.0, whose file format this library emulates. */
|
|
159
|
+
export declare const PISTAR_TOOL = "pistar.2.1.0";
|
|
160
|
+
export declare const ISTAR_VERSION = "2.0";
|
|
161
|
+
export declare const DEFAULT_DIAGRAM: Diagram;
|
|
162
|
+
export declare function createEmptyModel(diagram?: Diagram): IstarModel;
|
|
163
|
+
export declare function isActor(element: IstarElement | undefined): element is IstarActor;
|
|
164
|
+
export declare function isNode(element: IstarElement | undefined): element is IstarNode;
|
|
165
|
+
/** Inner elements of an actor, in model order. */
|
|
166
|
+
export declare function childrenOf(model: IstarModel, actorId: string): IstarElement[];
|
|
167
|
+
/** Links that have the element as source or target. */
|
|
168
|
+
export declare function linksOf(model: IstarModel, elementId: string): IstarLink[];
|
|
169
|
+
/** For a dependum, the two halves of its dependency: depender → dependum → dependee. */
|
|
170
|
+
export declare function dependencyLinksOf(model: IstarModel, dependumId: string): {
|
|
171
|
+
inbound?: IstarLink;
|
|
172
|
+
outbound?: IstarLink;
|
|
173
|
+
};
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/constraints.d.ts
|
|
176
|
+
export type ConstraintCode = "unknown-element" | "unknown-link-kind" | "invalid-source" | "invalid-target" | "actor-types-differ" | "self-link" | "duplicate-link" | "dependum-endpoint" | "same-actor" | "different-actors" | "refined-depender" | "contributed-depender" | "depender-target" | "mixed-refinement" | "contribution-and-qualification";
|
|
177
|
+
export type LinkCheck = {
|
|
178
|
+
ok: true;
|
|
179
|
+
} | {
|
|
180
|
+
ok: false;
|
|
181
|
+
reason: string;
|
|
182
|
+
code: ConstraintCode;
|
|
183
|
+
};
|
|
184
|
+
type ElementRef = string | IstarElement;
|
|
185
|
+
/**
|
|
186
|
+
* Checks whether a link of `kind` may be added from `source` to `target` in `model`.
|
|
187
|
+
*
|
|
188
|
+
* For `istar.DependencyLink`, `source` is the depender and `target` the dependee (an actor or
|
|
189
|
+
* one of its inner elements); the dependum sits between them and is not part of the check.
|
|
190
|
+
*/
|
|
191
|
+
export declare function canLink(model: IstarModel, source: ElementRef, target: ElementRef, kind: LinkKind): LinkCheck;
|
|
192
|
+
export interface ModelIssue {
|
|
193
|
+
readonly linkId: string;
|
|
194
|
+
readonly kind: LinkKind;
|
|
195
|
+
readonly source: string;
|
|
196
|
+
readonly target: string;
|
|
197
|
+
readonly code: ConstraintCode;
|
|
198
|
+
readonly message: string;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Re-validates every link of a model, the way piStar does when loading a file: dependencies
|
|
202
|
+
* first (each checked before its own links are added), then the remaining links in file
|
|
203
|
+
* order, each against the graph built so far. Invalid links are reported, not removed.
|
|
204
|
+
*/
|
|
205
|
+
export declare function validateModel(model: IstarModel): ModelIssue[];
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/serialization.d.ts
|
|
208
|
+
export interface PistarElementJson {
|
|
209
|
+
id: string;
|
|
210
|
+
text: string;
|
|
211
|
+
type: string;
|
|
212
|
+
x: number;
|
|
213
|
+
y: number;
|
|
214
|
+
customProperties?: Record<string, string>;
|
|
215
|
+
[key: string]: unknown;
|
|
216
|
+
}
|
|
217
|
+
export interface PistarActorJson extends PistarElementJson {
|
|
218
|
+
nodes: PistarElementJson[];
|
|
219
|
+
}
|
|
220
|
+
export interface PistarDependencyJson extends PistarElementJson {
|
|
221
|
+
source: string;
|
|
222
|
+
target: string;
|
|
223
|
+
}
|
|
224
|
+
export interface PistarLinkJson {
|
|
225
|
+
id: string;
|
|
226
|
+
type: string;
|
|
227
|
+
source: string;
|
|
228
|
+
target: string;
|
|
229
|
+
name?: string;
|
|
230
|
+
customProperties?: Record<string, string>;
|
|
231
|
+
label?: string;
|
|
232
|
+
[key: string]: unknown;
|
|
233
|
+
}
|
|
234
|
+
export interface PistarDiagramJson {
|
|
235
|
+
width?: number;
|
|
236
|
+
height?: number;
|
|
237
|
+
name?: string;
|
|
238
|
+
customProperties?: Record<string, string>;
|
|
239
|
+
[key: string]: unknown;
|
|
240
|
+
}
|
|
241
|
+
/** A piStar save file. Older piStar versions may omit some sections (e.g. `orphans`). */
|
|
242
|
+
export interface PistarFile {
|
|
243
|
+
actors: PistarActorJson[];
|
|
244
|
+
orphans?: PistarElementJson[];
|
|
245
|
+
dependencies?: PistarDependencyJson[];
|
|
246
|
+
links?: PistarLinkJson[];
|
|
247
|
+
display?: Record<string, Record<string, unknown>>;
|
|
248
|
+
tool?: string;
|
|
249
|
+
istar?: string;
|
|
250
|
+
saveDate?: string;
|
|
251
|
+
diagram?: PistarDiagramJson;
|
|
252
|
+
[key: string]: unknown;
|
|
253
|
+
}
|
|
254
|
+
export declare class PistarParseError extends Error {
|
|
255
|
+
override name: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Parse-time bookkeeping that lets `toPistar` reproduce the original key order. It has no
|
|
259
|
+
* meaning for the model itself and may be dropped.
|
|
260
|
+
*/
|
|
261
|
+
export interface SourceLayout {
|
|
262
|
+
/** Top-level keys in file order. */
|
|
263
|
+
readonly keys: readonly string[];
|
|
264
|
+
/** `display` ids in file order. */
|
|
265
|
+
readonly display: readonly string[];
|
|
266
|
+
}
|
|
267
|
+
/** The key order recorded when `model` was parsed, if it came from `parsePistar`. */
|
|
268
|
+
export declare function getSourceLayout(model: IstarModel): SourceLayout | undefined;
|
|
269
|
+
/**
|
|
270
|
+
* Carries the recorded key order over to a model derived from `from` (the store does this for
|
|
271
|
+
* every edit, so saving an edited file keeps a stable diff).
|
|
272
|
+
*/
|
|
273
|
+
export declare function inheritSourceLayout<M extends IstarModel>(from: IstarModel, to: M): M;
|
|
274
|
+
/**
|
|
275
|
+
* Parses a piStar save file (JSON text or an already-parsed object). The input is not mutated.
|
|
276
|
+
*
|
|
277
|
+
* Unlike the piStar tool, elements with `x` or `y` equal to 0 are kept: upstream's
|
|
278
|
+
* `if (element.x && element.y)` silently drops them, which looks unintended.
|
|
279
|
+
*/
|
|
280
|
+
export declare function parsePistar(input: string | PistarFile | Record<string, unknown>): IstarModel;
|
|
281
|
+
export interface ToPistarOptions {
|
|
282
|
+
/**
|
|
283
|
+
* Value for `saveDate`. Defaults to the model's own `saveDate` (so a load/save round trip is
|
|
284
|
+
* lossless), or the current time for models that never had one. Pass `new Date()` when
|
|
285
|
+
* saving an edited model, as piStar does.
|
|
286
|
+
*/
|
|
287
|
+
saveDate?: string | Date;
|
|
288
|
+
}
|
|
289
|
+
/** Builds the save-file object for a model. `toPistar` is this plus `JSON.stringify`. */
|
|
290
|
+
export declare function toPistarObject(model: IstarModel, options?: ToPistarOptions): PistarFile;
|
|
291
|
+
/** Serializes a model to piStar's JSON text (2-space indentation, no trailing newline). */
|
|
292
|
+
export declare function toPistar(model: IstarModel, options?: ToPistarOptions): string;
|
|
293
|
+
declare namespace operations_d_exports {
|
|
294
|
+
export { AddDependencyResult, ConnectOptions, ConnectResult, ElementPatch, IdGenerator, LinkPatch, ModelOperationError, NewDependency, NewElement, NewLink, OperationContext, addDependency, addElement, connect, defaultIdGenerator, dependencyEnds, disconnect, moveElement, nestElement, removeElement, removeElements, updateDiagram, updateElement, updateLink };
|
|
295
|
+
}
|
|
296
|
+
export declare class ModelOperationError extends Error {
|
|
297
|
+
override name: string;
|
|
298
|
+
}
|
|
299
|
+
/** Generates ids for new elements and links. piStar uses UUID v4. */
|
|
300
|
+
export type IdGenerator = () => string;
|
|
301
|
+
export declare const defaultIdGenerator: IdGenerator;
|
|
302
|
+
export interface OperationContext {
|
|
303
|
+
readonly createId?: IdGenerator;
|
|
304
|
+
}
|
|
305
|
+
export interface NewElement {
|
|
306
|
+
readonly kind: ElementKind;
|
|
307
|
+
readonly x: number;
|
|
308
|
+
readonly y: number;
|
|
309
|
+
readonly id?: string;
|
|
310
|
+
/** Defaults to the kind's short name ("Goal"), like piStar. */
|
|
311
|
+
readonly name?: string;
|
|
312
|
+
/** Actor to place the element in. Required in practice for iStar nodes (see NodeKindInfo). */
|
|
313
|
+
readonly parent?: string;
|
|
314
|
+
readonly customProperties?: CustomProperties;
|
|
315
|
+
readonly display?: ElementDisplay;
|
|
316
|
+
}
|
|
317
|
+
export declare function addElement(model: IstarModel, input: NewElement, ctx?: OperationContext): {
|
|
318
|
+
model: IstarModel;
|
|
319
|
+
element: IstarElement;
|
|
320
|
+
};
|
|
321
|
+
export interface ElementPatch {
|
|
322
|
+
readonly name?: string;
|
|
323
|
+
/** Replaces the whole map. Use `null` to remove it. */
|
|
324
|
+
readonly customProperties?: CustomProperties | null;
|
|
325
|
+
/** Merged into the current display; a key set to `undefined` is removed. `null` clears it. */
|
|
326
|
+
readonly display?: {
|
|
327
|
+
readonly [key: string]: unknown;
|
|
328
|
+
} | null;
|
|
329
|
+
}
|
|
330
|
+
export declare function updateElement(model: IstarModel, id: string, patch: ElementPatch): IstarModel;
|
|
331
|
+
/**
|
|
332
|
+
* Moves an element to an absolute position. Moving an actor shifts its inner elements by the
|
|
333
|
+
* same offset.
|
|
334
|
+
*/
|
|
335
|
+
export declare function moveElement(model: IstarModel, id: string, x: number, y: number): IstarModel;
|
|
336
|
+
/**
|
|
337
|
+
* Moves an inner element into another actor (or out of any actor with `null`). The element
|
|
338
|
+
* becomes the actor's last child. Links that become invalid are kept; `validateModel` reports
|
|
339
|
+
* them.
|
|
340
|
+
*/
|
|
341
|
+
export declare function nestElement(model: IstarModel, id: string, parent: string | null): IstarModel;
|
|
342
|
+
/**
|
|
343
|
+
* Removes elements and everything that depends on them: inner elements of removed actors,
|
|
344
|
+
* links touching removed elements, and the rest of any dependency that loses a part.
|
|
345
|
+
*/
|
|
346
|
+
export declare function removeElements(model: IstarModel, ids: Iterable<string>): IstarModel;
|
|
347
|
+
export declare function removeElement(model: IstarModel, id: string): IstarModel;
|
|
348
|
+
export interface NewLink {
|
|
349
|
+
readonly kind: Exclude<LinkKind, "istar.DependencyLink">;
|
|
350
|
+
readonly source: string;
|
|
351
|
+
readonly target: string;
|
|
352
|
+
readonly id?: string;
|
|
353
|
+
/** Contribution value: make, help, hurt or break. */
|
|
354
|
+
readonly label?: string;
|
|
355
|
+
readonly name?: string;
|
|
356
|
+
readonly customProperties?: CustomProperties;
|
|
357
|
+
}
|
|
358
|
+
export interface ConnectOptions extends OperationContext {
|
|
359
|
+
/** Skip constraint checking (used when loading or scripting known-good data). */
|
|
360
|
+
readonly force?: boolean;
|
|
361
|
+
/**
|
|
362
|
+
* Retry with source and target swapped if the link is invalid as given. Defaults to the
|
|
363
|
+
* metamodel's `tryReversedWhenAdding` (Needed-By and Qualification), as in piStar.
|
|
364
|
+
*/
|
|
365
|
+
readonly tryReversed?: boolean;
|
|
366
|
+
}
|
|
367
|
+
export type ConnectResult = {
|
|
368
|
+
ok: true;
|
|
369
|
+
model: IstarModel;
|
|
370
|
+
link: IstarLink;
|
|
371
|
+
reversed: boolean;
|
|
372
|
+
} | Extract<LinkCheck, {
|
|
373
|
+
ok: false;
|
|
374
|
+
}>;
|
|
375
|
+
/** Adds a link between two elements if the iStar constraints allow it. */
|
|
376
|
+
export declare function connect(model: IstarModel, input: NewLink, options?: ConnectOptions): ConnectResult;
|
|
377
|
+
export interface NewDependency {
|
|
378
|
+
/** The depender: an actor or one of its inner elements. */
|
|
379
|
+
readonly depender: string;
|
|
380
|
+
/** The dependee: an actor or one of its inner elements. */
|
|
381
|
+
readonly dependee: string;
|
|
382
|
+
readonly dependum: {
|
|
383
|
+
readonly kind: NodeKind;
|
|
384
|
+
readonly name?: string;
|
|
385
|
+
readonly id?: string;
|
|
386
|
+
/** Defaults to the midpoint between depender and dependee, as in piStar. */
|
|
387
|
+
readonly x?: number;
|
|
388
|
+
readonly y?: number;
|
|
389
|
+
readonly customProperties?: CustomProperties;
|
|
390
|
+
};
|
|
391
|
+
readonly linkIds?: readonly [string, string];
|
|
392
|
+
}
|
|
393
|
+
export type AddDependencyResult = {
|
|
394
|
+
ok: true;
|
|
395
|
+
model: IstarModel;
|
|
396
|
+
dependum: IstarElement;
|
|
397
|
+
links: readonly [IstarLink, IstarLink];
|
|
398
|
+
} | Extract<LinkCheck, {
|
|
399
|
+
ok: false;
|
|
400
|
+
}>;
|
|
401
|
+
/** Adds depender → dependum → dependee. */
|
|
402
|
+
export declare function addDependency(model: IstarModel, input: NewDependency, options?: Omit<ConnectOptions, "tryReversed">): AddDependencyResult;
|
|
403
|
+
/** Removes a link. Removing either half of a dependency removes the whole dependency. */
|
|
404
|
+
export declare function disconnect(model: IstarModel, id: string): IstarModel;
|
|
405
|
+
export interface LinkPatch {
|
|
406
|
+
/** `null` removes it. */
|
|
407
|
+
readonly label?: string | null;
|
|
408
|
+
readonly name?: string | null;
|
|
409
|
+
readonly customProperties?: CustomProperties | null;
|
|
410
|
+
readonly display?: {
|
|
411
|
+
readonly [key: string]: unknown;
|
|
412
|
+
} | null;
|
|
413
|
+
}
|
|
414
|
+
export declare function updateLink(model: IstarModel, id: string, patch: LinkPatch): IstarModel;
|
|
415
|
+
export declare function updateDiagram(model: IstarModel, patch: Partial<Diagram>): IstarModel;
|
|
416
|
+
/** Where dependency depender/dependee currently point (see `dependencyLinksOf`). */
|
|
417
|
+
export declare function dependencyEnds(model: IstarModel, dependumId: string): {
|
|
418
|
+
depender?: string;
|
|
419
|
+
dependee?: string;
|
|
420
|
+
};
|
|
421
|
+
//#endregion
|
|
422
|
+
//#region src/store.d.ts
|
|
423
|
+
/** What happened, for listeners that want more than the new snapshot. */
|
|
424
|
+
export type ModelChange = {
|
|
425
|
+
type: "addElement";
|
|
426
|
+
id: string;
|
|
427
|
+
} | {
|
|
428
|
+
type: "updateElement";
|
|
429
|
+
id: string;
|
|
430
|
+
patch: ElementPatch;
|
|
431
|
+
} | {
|
|
432
|
+
type: "moveElement";
|
|
433
|
+
id: string;
|
|
434
|
+
x: number;
|
|
435
|
+
y: number;
|
|
436
|
+
} | {
|
|
437
|
+
type: "nestElement";
|
|
438
|
+
id: string;
|
|
439
|
+
parent: string | null;
|
|
440
|
+
} | {
|
|
441
|
+
type: "removeElements";
|
|
442
|
+
ids: readonly string[];
|
|
443
|
+
} | {
|
|
444
|
+
type: "connect";
|
|
445
|
+
id: string;
|
|
446
|
+
} | {
|
|
447
|
+
type: "addDependency";
|
|
448
|
+
dependumId: string;
|
|
449
|
+
linkIds: readonly [string, string];
|
|
450
|
+
} | {
|
|
451
|
+
type: "updateLink";
|
|
452
|
+
id: string;
|
|
453
|
+
patch: LinkPatch;
|
|
454
|
+
} | {
|
|
455
|
+
type: "disconnect";
|
|
456
|
+
id: string;
|
|
457
|
+
} | {
|
|
458
|
+
type: "updateDiagram";
|
|
459
|
+
patch: Partial<Diagram>;
|
|
460
|
+
} | {
|
|
461
|
+
type: "replace";
|
|
462
|
+
};
|
|
463
|
+
export interface ModelChangeEvent {
|
|
464
|
+
readonly model: IstarModel;
|
|
465
|
+
readonly previous: IstarModel;
|
|
466
|
+
/** `undo`/`redo`/`load` carry no changes; a transaction carries all of its changes. */
|
|
467
|
+
readonly changes: readonly ModelChange[];
|
|
468
|
+
readonly source: "edit" | "undo" | "redo" | "load";
|
|
469
|
+
}
|
|
470
|
+
export type ModelListener = (event: ModelChangeEvent) => void;
|
|
471
|
+
export interface ModelStoreOptions {
|
|
472
|
+
readonly createId?: IdGenerator;
|
|
473
|
+
/** Maximum number of undo steps kept. Default 100. */
|
|
474
|
+
readonly historyLimit?: number;
|
|
475
|
+
}
|
|
476
|
+
export interface ModelStore {
|
|
477
|
+
getModel(): IstarModel;
|
|
478
|
+
/** Returns an unsubscribe function. */
|
|
479
|
+
subscribe(listener: ModelListener): () => void;
|
|
480
|
+
canLink(source: string | IstarElement, target: string | IstarElement, kind: LinkKind): LinkCheck;
|
|
481
|
+
addElement(input: NewElement): IstarElement;
|
|
482
|
+
updateElement(id: string, patch: ElementPatch): void;
|
|
483
|
+
moveElement(id: string, x: number, y: number): void;
|
|
484
|
+
nestElement(id: string, parent: string | null): void;
|
|
485
|
+
removeElement(id: string): void;
|
|
486
|
+
removeElements(ids: Iterable<string>): void;
|
|
487
|
+
setCollapsed(actorId: string, collapsed: boolean): void;
|
|
488
|
+
connect(input: NewLink, options?: Omit<ConnectOptions, "createId">): ConnectResult;
|
|
489
|
+
addDependency(input: NewDependency, options?: Omit<ConnectOptions, "createId" | "tryReversed">): AddDependencyResult;
|
|
490
|
+
updateLink(id: string, patch: LinkPatch): void;
|
|
491
|
+
disconnect(id: string): void;
|
|
492
|
+
updateDiagram(patch: Partial<Diagram>): void;
|
|
493
|
+
/** Replaces the model as one undoable edit. */
|
|
494
|
+
replace(model: IstarModel): void;
|
|
495
|
+
/** Replaces the model and clears history (like opening a file in piStar). */
|
|
496
|
+
load(model: IstarModel): void;
|
|
497
|
+
/**
|
|
498
|
+
* Groups several edits into one undo step and one change event. Nested calls join the
|
|
499
|
+
* outermost transaction. If `fn` throws, the model is rolled back.
|
|
500
|
+
*/
|
|
501
|
+
transaction<T>(fn: () => T): T;
|
|
502
|
+
undo(): boolean;
|
|
503
|
+
redo(): boolean;
|
|
504
|
+
canUndo(): boolean;
|
|
505
|
+
canRedo(): boolean;
|
|
506
|
+
clearHistory(): void;
|
|
507
|
+
}
|
|
508
|
+
export declare function createModelStore(initial?: IstarModel, options?: ModelStoreOptions): ModelStore;
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region src/properties.d.ts
|
|
511
|
+
export type PropertyResult<T> = {
|
|
512
|
+
ok: true;
|
|
513
|
+
value: T;
|
|
514
|
+
} | {
|
|
515
|
+
ok: false;
|
|
516
|
+
error: string;
|
|
517
|
+
};
|
|
518
|
+
export interface PropertyOptions<T> {
|
|
519
|
+
default?: T;
|
|
520
|
+
optional?: boolean;
|
|
521
|
+
label?: string;
|
|
522
|
+
description?: string;
|
|
523
|
+
}
|
|
524
|
+
export interface PropertyType<T> {
|
|
525
|
+
readonly type: "string" | "number" | "boolean" | "enum";
|
|
526
|
+
readonly options: PropertyOptions<T>;
|
|
527
|
+
readonly values?: readonly string[];
|
|
528
|
+
readonly integer?: boolean;
|
|
529
|
+
readonly min?: number;
|
|
530
|
+
readonly max?: number;
|
|
531
|
+
parse(raw: string): PropertyResult<T>;
|
|
532
|
+
serialize(value: T): string;
|
|
533
|
+
}
|
|
534
|
+
export declare function string(options?: PropertyOptions<string>): PropertyType<string>;
|
|
535
|
+
export declare function number(options?: PropertyOptions<number> & {
|
|
536
|
+
integer?: boolean;
|
|
537
|
+
min?: number;
|
|
538
|
+
max?: number;
|
|
539
|
+
}): PropertyType<number>;
|
|
540
|
+
export declare function boolean(options?: PropertyOptions<boolean>): PropertyType<boolean>;
|
|
541
|
+
export declare function enumOf<const V extends readonly string[]>(values: V, options?: PropertyOptions<V[number]>): PropertyType<V[number]>;
|
|
542
|
+
export declare const prop: {
|
|
543
|
+
string: typeof string;
|
|
544
|
+
number: typeof number;
|
|
545
|
+
boolean: typeof boolean;
|
|
546
|
+
enum: typeof enumOf;
|
|
547
|
+
};
|
|
548
|
+
export type PropertyShape = Record<string, PropertyType<unknown>>;
|
|
549
|
+
export type InferProperties<S extends PropertyShape> = { [K in keyof S]: S[K] extends PropertyType<infer T> ? T : never; };
|
|
550
|
+
export interface PropertyIssue {
|
|
551
|
+
key: string;
|
|
552
|
+
message: string;
|
|
553
|
+
}
|
|
554
|
+
export interface PropertySchema<S extends PropertyShape = PropertyShape> {
|
|
555
|
+
readonly kind: ElementKind | LinkKind;
|
|
556
|
+
readonly shape: S;
|
|
557
|
+
read(source: CustomProperties | undefined | PropertyOwner): {
|
|
558
|
+
values: Partial<InferProperties<S>>;
|
|
559
|
+
issues: PropertyIssue[];
|
|
560
|
+
};
|
|
561
|
+
validate(source: CustomProperties | undefined | PropertyOwner): PropertyIssue[];
|
|
562
|
+
write(current: CustomProperties | undefined, patch: { [K in keyof S]?: InferProperties<S>[K] | undefined; }): CustomProperties;
|
|
563
|
+
defaults(): CustomProperties;
|
|
564
|
+
}
|
|
565
|
+
/** An element or link, read through its `customProperties`. */
|
|
566
|
+
export interface PropertyOwner {
|
|
567
|
+
readonly kind: string;
|
|
568
|
+
readonly customProperties?: CustomProperties;
|
|
569
|
+
}
|
|
570
|
+
export interface ModelPropertyIssue extends PropertyIssue {
|
|
571
|
+
id: string;
|
|
572
|
+
}
|
|
573
|
+
export declare function defineProperties<const S extends PropertyShape>(kind: ElementKind | LinkKind, shape: S, options?: {
|
|
574
|
+
validate?: (values: Partial<InferProperties<S>>) => PropertyIssue[];
|
|
575
|
+
}): PropertySchema<S>;
|
|
576
|
+
export declare function validateModelProperties(model: IstarModel, schemas: readonly PropertySchema[]): ModelPropertyIssue[];
|
|
577
|
+
//#endregion
|
|
578
|
+
//# sourceMappingURL=index.d.cts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@istar-ts/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Framework-free iStar 2.0 goal-model core: metamodel, constraints, piStar-compatible serialization, undoable store.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,13 +21,20 @@
|
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
23
23
|
"@istar-ts/source": "./src/index.ts",
|
|
24
|
-
"
|
|
25
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/index.d.cts",
|
|
30
|
+
"default": "./dist/index.cjs"
|
|
31
|
+
}
|
|
26
32
|
},
|
|
27
33
|
"./package.json": "./package.json"
|
|
28
34
|
},
|
|
29
|
-
"main": "./dist/index.
|
|
30
|
-
"
|
|
35
|
+
"main": "./dist/index.cjs",
|
|
36
|
+
"module": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.cts",
|
|
31
38
|
"files": [
|
|
32
39
|
"dist",
|
|
33
40
|
"README.md",
|