@istar-ts/core 0.14.1 → 0.15.0-beta.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.d.ts CHANGED
@@ -76,6 +76,7 @@ export type LinkCheck = {
76
76
  ok: false;
77
77
  reason: string;
78
78
  code: ConstraintCode;
79
+ end?: "source" | "target";
79
80
  };
80
81
  /**
81
82
  * True for a link, as opposed to an element: the target of a link kind whose rules target links
@@ -607,6 +608,23 @@ export declare function elementCenter<EK extends string, LK extends string>(mode
607
608
  * Returns its top-left corner for a hub of `size`.
608
609
  */
609
610
  export declare function defaultHubPosition<EK extends string, LK extends string>(model: IstarModel<EK, LK>, source: IstarElement<EK>, target: IstarElement<EK>, size: Size): Point;
611
+ export interface Box extends Point, Size {}
612
+ /** Space kept between inner elements and an actor's boundary (piStar's `updateBoundary` adds 10px). */
613
+ export declare const ACTOR_PADDING = 10;
614
+ /**
615
+ * An actor's boundary: the kind's default-size rectangle at the actor's position, grown to
616
+ * include every inner element (each padded by `ACTOR_PADDING`), like piStar's `updateBoundary`
617
+ * (which floors on the kind's default size, not the actor's last expanded `display` size; an
618
+ * inner element's own `display` size does override, same as its rendered size elsewhere).
619
+ * Shared by `@istar-ts/react`'s node layout and `@istar-ts/glsp`'s GModel, so an actor draws the
620
+ * same box in both: children are looked up by category (`metamodelOf`), not `istar.*` names.
621
+ *
622
+ * `defaultSizeOf` resolves a kind's default size; it defaults to the metamodel's, but a host
623
+ * whose registry overrides a kind's size independently of the metamodel (`@istar-ts/react`'s
624
+ * `IstarRegistry`) must pass one that reads its own sizes, or its boundary would stop matching
625
+ * what it actually draws.
626
+ */
627
+ export declare function actorBounds<EK extends string, LK extends string>(model: IstarModel<EK, LK>, actorId: string, metamodel?: Metamodel<EK, LK>, defaultSizeOf?: (kind: EK) => Size): Box;
610
628
  //#endregion
611
629
  //#region src/file-metamodel.d.ts
612
630
  /** The top-level key of the block in piStar JSON. */
@@ -811,11 +829,149 @@ export declare function fileMetamodelOf<EK extends string, LK extends string>(mo
811
829
  * host's kinds, or leaves out a kind the model still uses.
812
830
  */
813
831
  export declare function withFileMetamodel<EK extends string, LK extends string>(model: IstarModel<EK, LK>, block: FileMetamodel | null): IstarModel<string, string>;
832
+ //#endregion
833
+ //#region src/diagnostics.d.ts
834
+ /**
835
+ * The Goal Model Diagnostics Protocol: findings about a model's elements and links, published by
836
+ * any analyser (a language server, a validator, a simulation…) and anchored by element id rather
837
+ * than by text position. Data only: diagnostics are never part of the model and are never
838
+ * written to disk.
839
+ *
840
+ * See goal-controller issue #24 (option D). Producers publish per source; consumers see the
841
+ * union of every source, deduplicated by `(elementId, key, message)`.
842
+ */
843
+ export type DiagnosticSeverity = "error" | "warning" | "info" | "hint";
844
+ /** Most severe first. */
845
+ export declare const DIAGNOSTIC_SEVERITIES: readonly DiagnosticSeverity[];
846
+ /** A zero-based position in the producer's document (as in LSP). */
847
+ export interface DiagnosticPosition {
848
+ readonly line: number;
849
+ readonly character: number;
850
+ }
851
+ export interface DiagnosticRange {
852
+ readonly start: DiagnosticPosition;
853
+ readonly end: DiagnosticPosition;
854
+ }
855
+ export interface GoalDiagnostic {
856
+ /** Id of the element or link the diagnostic is about. */
857
+ readonly elementId: string;
858
+ /** The custom property it is about; absent for the element as a whole. */
859
+ readonly key?: string;
860
+ readonly severity: DiagnosticSeverity;
861
+ readonly message: string;
862
+ /** Who published it (e.g. `mutrose`, `goal-language`). */
863
+ readonly source?: string;
864
+ /** Where it was found in the producer's document, if it has one. */
865
+ readonly range?: DiagnosticRange;
866
+ readonly code?: string;
867
+ /** Producer data, passed through untouched. */
868
+ readonly data?: unknown;
869
+ }
870
+ /** Negative when `a` is more severe than `b`. */
871
+ export declare function compareSeverity(a: DiagnosticSeverity, b: DiagnosticSeverity): number;
872
+ /** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
873
+ export declare function worstDiagnosticSeverity(diagnostics: readonly {
874
+ readonly severity: DiagnosticSeverity;
875
+ }[] | undefined): DiagnosticSeverity | undefined;
876
+ /**
877
+ * The union of several lists, in order, without duplicates: diagnostics with the same
878
+ * `(elementId, key, message)` count once, keeping the first one's position and the most severe
879
+ * severity among them.
880
+ */
881
+ export declare function mergeDiagnostics(lists: Iterable<readonly GoalDiagnostic[] | undefined>): GoalDiagnostic[];
882
+ /** Diagnostics by element (or link) id, each list in the input order. */
883
+ export declare function groupDiagnostics(diagnostics: readonly GoalDiagnostic[] | undefined): ReadonlyMap<string, readonly GoalDiagnostic[]>;
884
+ /**
885
+ * Holds the diagnostics of several sources. Each `publish` replaces that source's set, so a
886
+ * producer re-publishes everything it currently reports, as an LSP server does.
887
+ */
888
+ export interface DiagnosticsStore {
889
+ /**
890
+ * Replaces `source`'s diagnostics (an empty list clears them). Entries without a `source` get
891
+ * this one.
892
+ */
893
+ publish(source: string, diagnostics: readonly GoalDiagnostic[]): void;
894
+ /** Removes one source's diagnostics, or every source's. */
895
+ clear(source?: string): void;
896
+ /** Sources with diagnostics, in the order they first published. */
897
+ sources(): readonly string[];
898
+ /** One source's diagnostics. */
899
+ get(source: string): readonly GoalDiagnostic[];
900
+ /**
901
+ * Every source's diagnostics, merged (see `mergeDiagnostics`). The same array until the next
902
+ * change, so it can back `useSyncExternalStore`.
903
+ */
904
+ getAll(): readonly GoalDiagnostic[];
905
+ subscribe(listener: () => void): () => void;
906
+ }
907
+ export declare function createDiagnosticsStore(): DiagnosticsStore;
908
+ /**
909
+ * The parts of an LSP `Diagnostic` the adapter reads (structurally typed, so no LSP library is
910
+ * needed). The element is taken from `data.elementId`, or MutRoSe's `data.nodeId`; the property
911
+ * from `data.key`.
912
+ */
913
+ export interface LspDiagnosticLike {
914
+ readonly range?: DiagnosticRange;
915
+ /** LSP numbering: 1 error, 2 warning, 3 information, 4 hint. */
916
+ readonly severity?: number;
917
+ readonly message: string | {
918
+ readonly value: string;
919
+ };
920
+ readonly source?: string;
921
+ readonly code?: string | number | {
922
+ readonly value: string | number;
923
+ };
924
+ readonly data?: unknown;
925
+ }
926
+ export interface FromLspOptions<D extends LspDiagnosticLike = LspDiagnosticLike> {
927
+ /**
928
+ * The element of a diagnostic whose `data` names none, e.g. by looking its range up in the
929
+ * document. Return `undefined` to drop it.
930
+ */
931
+ readonly elementIdFor?: (diagnostic: D) => string | undefined;
932
+ /**
933
+ * `'vscode'` for `vscode.Diagnostic` objects, whose severity counts from 0 (error) to 3
934
+ * (hint). Default `'lsp'`, the protocol's 1 to 4.
935
+ */
936
+ readonly severityNumbering?: "lsp" | "vscode";
937
+ }
938
+ /**
939
+ * One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
940
+ * names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
941
+ */
942
+ export declare function fromLspDiagnostic(diagnostic: LspDiagnosticLike): GoalDiagnostic | undefined;
943
+ /** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
944
+ export declare function fromLspDiagnostics<D extends LspDiagnosticLike>(diagnostics: readonly D[], options?: FromLspOptions<D>): GoalDiagnostic[];
945
+ /**
946
+ * The shape MutRoSe's VS Code extension posts to its webview: `{ nodeId, severity, message }`
947
+ * (plus `range` and `source`). `nodeId` is missing when no node could be found.
948
+ */
949
+ export interface NodeIdDiagnostic {
950
+ readonly nodeId?: string;
951
+ readonly key?: string;
952
+ readonly severity: DiagnosticSeverity | string;
953
+ readonly message: string;
954
+ readonly source?: string;
955
+ readonly range?: DiagnosticRange;
956
+ readonly code?: string;
957
+ }
958
+ /** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
959
+ export declare function fromNodeIdDiagnostic(diagnostic: NodeIdDiagnostic): GoalDiagnostic | undefined;
960
+ /**
961
+ * `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
962
+ * without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
963
+ */
964
+ export declare function fromNodeIdDiagnostics(diagnostics: readonly NodeIdDiagnostic[]): GoalDiagnostic[];
814
965
  declare namespace operations_d_exports {
815
- export { AddDependencyResult, ConnectOptions, ConnectResult, ElementPatch, IdGenerator, LinkPatch, ModelOperationError, NewDependency, NewElement, NewLink, OperationContext, addDependency, addElement, addLeg, connect, defaultIdGenerator, dependencyEnds, disconnect, moveElement, nestElement, removeElement, removeElements, removeLeg, updateDiagram, updateElement, updateLink };
966
+ export { AddDependencyResult, ConnectOptions, ConnectResult, ElementPatch, IdGenerator, LinkPatch, ModelOperationError, NewDependency, NewElement, NewLink, OperationContext, addDependency, addElement, addLeg, connect, connectResultToDiagnostic, defaultIdGenerator, dependencyEnds, disconnect, moveElement, nestElement, removeElement, removeElements, removeLeg, updateDiagram, updateElement, updateLink };
816
967
  }
817
968
  export declare class ModelOperationError extends Error {
818
969
  override name: string;
970
+ /** The element or link the error is about, when the operation named one. */
971
+ readonly elementId?: string;
972
+ constructor(message: string, elementId?: string);
973
+ /** As a `GoalDiagnostic`, anchored on `elementId` (empty string if the error names none). */
974
+ toDiagnostic(): GoalDiagnostic;
819
975
  }
820
976
  /** Generates ids for new elements and links. piStar uses UUID v4. */
821
977
  export type IdGenerator = () => string;
@@ -873,11 +1029,22 @@ export interface NewLink<K extends string = LinkKind> {
873
1029
  readonly source: string;
874
1030
  /** An element id, or a link id for kinds whose rules target links. */
875
1031
  readonly target: string;
1032
+ /**
1033
+ * The new link's id: for an n-ary kind whose target is not yet a hub, the new hub's; for an
1034
+ * n-ary kind whose target already is a hub, the new leg's (same as `legId` there).
1035
+ */
876
1036
  readonly id?: string;
877
1037
  /** Contribution value: make, help, hurt or break. */
878
1038
  readonly label?: string;
879
1039
  readonly name?: string;
880
1040
  readonly customProperties?: CustomProperties;
1041
+ /**
1042
+ * The id of the leg it creates: for a target that is not yet a hub, the new leg from `source`;
1043
+ * for a target that already is a hub, the new leg instead of `id`.
1044
+ */
1045
+ readonly legId?: string;
1046
+ /** For an n-ary kind whose target is not yet a hub: the id of the end it creates. */
1047
+ readonly endId?: string;
881
1048
  }
882
1049
  export interface ConnectOptions extends OperationContext {
883
1050
  /** Skip constraint checking (used when loading or scripting known-good data). */
@@ -899,13 +1066,23 @@ export type ConnectResult<EK extends string = ElementKind, LK extends string = L
899
1066
  } | Extract<LinkCheck, {
900
1067
  ok: false;
901
1068
  }>;
1069
+ /**
1070
+ * Maps a failing `connect` result to a `GoalDiagnostic`, anchored on the end named by the
1071
+ * `LinkCheck`'s `end` field (`target` when a check doesn't single out one end, such as
1072
+ * `self-link` or `actor-types-differ`). `undefined` for a successful result.
1073
+ */
1074
+ export declare function connectResultToDiagnostic<EK extends string = ElementKind, LK extends string = LinkKind>(result: ConnectResult<EK, LK>, endpoints: {
1075
+ readonly source: string;
1076
+ readonly target: string;
1077
+ }): GoalDiagnostic | undefined;
902
1078
  /**
903
1079
  * Adds a link between two elements if the iStar constraints allow it.
904
1080
  *
905
1081
  * With an n-ary kind (`arity: 'n'`), a `target` that is one of the kind's hubs gets a new leg
906
- * from `source` (see `addLeg`). Any other target gets a new hub, centred between source and
907
- * target, with a leg from `source` and an end to `target`. `input.id` and `customProperties`
908
- * then go to the hub, and `label` and `name` to the end.
1082
+ * from `source` (see `addLeg`), taking `input.id` or `input.legId` (default a fresh id) as the
1083
+ * leg's id. Any other target gets a new hub, centred between source and target, with a leg from
1084
+ * `source` and an end to `target`. `input.id` and `customProperties` then go to the hub, `label`
1085
+ * and `name` to the end, and `legId`/`endId` (default fresh ids) to the leg and end.
909
1086
  */
910
1087
  export declare function connect<EK extends string = ElementKind, LK extends string = LinkKind>(model: IstarModel<EK, LK>, input: NewLink<LK>, options?: ConnectOptions): ConnectResult<EK, LK>;
911
1088
  /**
@@ -1170,137 +1347,43 @@ export declare function defineProperties<const S extends PropertyShape, const Ki
1170
1347
  }): PropertySchema<S, Kind>;
1171
1348
  export declare function validateModelProperties<EK extends string, LK extends string>(model: IstarModel<EK, LK>, schemas: readonly PropertySchema<PropertyShape, string>[]): ModelPropertyIssue[];
1172
1349
  //#endregion
1173
- //#region src/diagnostics.d.ts
1174
- /**
1175
- * The Goal Model Diagnostics Protocol: findings about a model's elements and links, published by
1176
- * any analyser (a language server, a validator, a simulation…) and anchored by element id rather
1177
- * than by text position. Data only: diagnostics are never part of the model and are never
1178
- * written to disk.
1179
- *
1180
- * See goal-controller issue #24 (option D). Producers publish per source; consumers see the
1181
- * union of every source, deduplicated by `(elementId, key, message)`.
1182
- */
1183
- export type DiagnosticSeverity = "error" | "warning" | "info" | "hint";
1184
- /** Most severe first. */
1185
- export declare const DIAGNOSTIC_SEVERITIES: readonly DiagnosticSeverity[];
1186
- /** A zero-based position in the producer's document (as in LSP). */
1187
- export interface DiagnosticPosition {
1188
- readonly line: number;
1189
- readonly character: number;
1190
- }
1191
- export interface DiagnosticRange {
1192
- readonly start: DiagnosticPosition;
1193
- readonly end: DiagnosticPosition;
1194
- }
1195
- export interface GoalDiagnostic {
1196
- /** Id of the element or link the diagnostic is about. */
1197
- readonly elementId: string;
1198
- /** The custom property it is about; absent for the element as a whole. */
1199
- readonly key?: string;
1200
- readonly severity: DiagnosticSeverity;
1201
- readonly message: string;
1202
- /** Who published it (e.g. `mutrose`, `goal-language`). */
1203
- readonly source?: string;
1204
- /** Where it was found in the producer's document, if it has one. */
1205
- readonly range?: DiagnosticRange;
1206
- readonly code?: string;
1207
- /** Producer data, passed through untouched. */
1208
- readonly data?: unknown;
1209
- }
1210
- /** Negative when `a` is more severe than `b`. */
1211
- export declare function compareSeverity(a: DiagnosticSeverity, b: DiagnosticSeverity): number;
1212
- /** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
1213
- export declare function worstDiagnosticSeverity(diagnostics: readonly {
1214
- readonly severity: DiagnosticSeverity;
1215
- }[] | undefined): DiagnosticSeverity | undefined;
1216
- /**
1217
- * The union of several lists, in order, without duplicates: diagnostics with the same
1218
- * `(elementId, key, message)` count once, keeping the first one's position and the most severe
1219
- * severity among them.
1220
- */
1221
- export declare function mergeDiagnostics(lists: Iterable<readonly GoalDiagnostic[] | undefined>): GoalDiagnostic[];
1222
- /** Diagnostics by element (or link) id, each list in the input order. */
1223
- export declare function groupDiagnostics(diagnostics: readonly GoalDiagnostic[] | undefined): ReadonlyMap<string, readonly GoalDiagnostic[]>;
1224
- /**
1225
- * Holds the diagnostics of several sources. Each `publish` replaces that source's set, so a
1226
- * producer re-publishes everything it currently reports, as an LSP server does.
1227
- */
1228
- export interface DiagnosticsStore {
1229
- /**
1230
- * Replaces `source`'s diagnostics (an empty list clears them). Entries without a `source` get
1231
- * this one.
1232
- */
1233
- publish(source: string, diagnostics: readonly GoalDiagnostic[]): void;
1234
- /** Removes one source's diagnostics, or every source's. */
1235
- clear(source?: string): void;
1236
- /** Sources with diagnostics, in the order they first published. */
1237
- sources(): readonly string[];
1238
- /** One source's diagnostics. */
1239
- get(source: string): readonly GoalDiagnostic[];
1240
- /**
1241
- * Every source's diagnostics, merged (see `mergeDiagnostics`). The same array until the next
1242
- * change, so it can back `useSyncExternalStore`.
1243
- */
1244
- getAll(): readonly GoalDiagnostic[];
1245
- subscribe(listener: () => void): () => void;
1246
- }
1247
- export declare function createDiagnosticsStore(): DiagnosticsStore;
1248
- /**
1249
- * The parts of an LSP `Diagnostic` the adapter reads (structurally typed, so no LSP library is
1250
- * needed). The element is taken from `data.elementId`, or MutRoSe's `data.nodeId`; the property
1251
- * from `data.key`.
1252
- */
1253
- export interface LspDiagnosticLike {
1254
- readonly range?: DiagnosticRange;
1255
- /** LSP numbering: 1 error, 2 warning, 3 information, 4 hint. */
1256
- readonly severity?: number;
1257
- readonly message: string | {
1258
- readonly value: string;
1259
- };
1260
- readonly source?: string;
1261
- readonly code?: string | number | {
1262
- readonly value: string | number;
1263
- };
1264
- readonly data?: unknown;
1265
- }
1266
- export interface FromLspOptions<D extends LspDiagnosticLike = LspDiagnosticLike> {
1267
- /**
1268
- * The element of a diagnostic whose `data` names none, e.g. by looking its range up in the
1269
- * document. Return `undefined` to drop it.
1270
- */
1271
- readonly elementIdFor?: (diagnostic: D) => string | undefined;
1272
- /**
1273
- * `'vscode'` for `vscode.Diagnostic` objects, whose severity counts from 0 (error) to 3
1274
- * (hint). Default `'lsp'`, the protocol's 1 to 4.
1275
- */
1276
- readonly severityNumbering?: "lsp" | "vscode";
1277
- }
1278
- /**
1279
- * One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
1280
- * names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
1281
- */
1282
- export declare function fromLspDiagnostic(diagnostic: LspDiagnosticLike): GoalDiagnostic | undefined;
1283
- /** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
1284
- export declare function fromLspDiagnostics<D extends LspDiagnosticLike>(diagnostics: readonly D[], options?: FromLspOptions<D>): GoalDiagnostic[];
1285
- /**
1286
- * The shape MutRoSe's VS Code extension posts to its webview: `{ nodeId, severity, message }`
1287
- * (plus `range` and `source`). `nodeId` is missing when no node could be found.
1288
- */
1289
- export interface NodeIdDiagnostic {
1290
- readonly nodeId?: string;
1291
- readonly key?: string;
1292
- readonly severity: DiagnosticSeverity | string;
1293
- readonly message: string;
1294
- readonly source?: string;
1295
- readonly range?: DiagnosticRange;
1296
- readonly code?: string;
1350
+ //#region src/palette.d.ts
1351
+ export interface PaletteEntryDescription {
1352
+ readonly label: string;
1353
+ /** Lower comes first. */
1354
+ readonly order?: number;
1355
+ /** Entries sharing a group collapse into one dropdown button (e.g. Actor / Agent / Role). */
1356
+ readonly group?: string;
1357
+ /** Sections are separated by a divider. Default palette: "actors" and "elements". */
1358
+ readonly section?: string;
1359
+ }
1360
+ export interface ElementToolEntryDescription extends PaletteEntryDescription {
1361
+ /** customProperties preset on the element this entry creates, over `defaultProperties`. */
1362
+ readonly properties?: CustomProperties;
1363
+ }
1364
+ export interface LinkToolEntryDescription<DK extends string = NodeKind> extends PaletteEntryDescription {
1365
+ /** Contribution value to set on the new link. */
1366
+ readonly value?: string;
1367
+ /** For dependencies: the kind of dependum to create. */
1368
+ readonly dependum?: DK;
1369
+ }
1370
+ export interface PaletteGroupDescription {
1371
+ readonly label: string;
1297
1372
  }
1298
- /** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
1299
- export declare function fromNodeIdDiagnostic(diagnostic: NodeIdDiagnostic): GoalDiagnostic | undefined;
1300
1373
  /**
1301
- * `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
1302
- * without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
1374
+ * Per-kind palette data. `elements`/`links` entries are `false` for kinds hidden from the
1375
+ * palette, one entry for most element kinds, or several for a kind with more than one toolbar
1376
+ * button (a link's values, a dependency's dependum kinds).
1303
1377
  */
1304
- export declare function fromNodeIdDiagnostics(diagnostics: readonly NodeIdDiagnostic[]): GoalDiagnostic[];
1378
+ export interface PaletteDescription<EK extends string = ElementKind, LK extends string = LinkKind> {
1379
+ readonly elements: Readonly<Record<EK, PaletteEntryDescription | readonly ElementToolEntryDescription[] | false>>;
1380
+ readonly links: Readonly<Record<LK, readonly LinkToolEntryDescription[] | false>>;
1381
+ /** Labels for palette groups, keyed by `PaletteEntryDescription.group`. */
1382
+ readonly groups: Readonly<Record<string, PaletteGroupDescription>>;
1383
+ }
1384
+ /** A palette description of any dialect, for code that handles every kind generically. */
1385
+ export type AnyPaletteDescription = PaletteDescription<string, string>;
1386
+ /** The palette data of iStar 2.0, as piStar's toolbar presents it. */
1387
+ export declare const DEFAULT_PALETTE: PaletteDescription;
1305
1388
  //#endregion
1306
1389
  //# sourceMappingURL=index.d.ts.map