@istar-ts/actions 0.15.0-beta.0 → 0.15.0-beta.2

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 CHANGED
@@ -17,7 +17,9 @@ const OPERATION_KIND_LIST = [
17
17
  "istar.updateProperties",
18
18
  "istar.updateDisplay",
19
19
  "istar.setLinkValue",
20
- "istar.updateLinkDisplay"
20
+ "istar.updateLinkDisplay",
21
+ "istar.changeLinkKind",
22
+ "istar.setFileMetamodel"
21
23
  ];
22
24
  const REQUEST_KIND_LIST = [
23
25
  "requestModel",
@@ -184,6 +186,36 @@ function contextActionsFor(palette, metamodel) {
184
186
  groups: palette.groups
185
187
  };
186
188
  }
189
+ /**
190
+ * A minimal palette for a metamodel with none of its own: one toolbar entry per visible kind
191
+ * (declaration order, actors first), labelled from the kind's own `label`. Kinds generated for
192
+ * an n-ary link (a hub, leg or end — `role` set) are hidden, as a hand-written palette would
193
+ * hide them (`KAOS_PALETTE`'s `RefinementLinkHub: false`, for instance). The fallback
194
+ * `createActionDispatcher` and `contributionFor` (`@istar-ts/glsp`) both use when no palette
195
+ * was given.
196
+ */
197
+ function paletteFromMetamodel(metamodel) {
198
+ const elements = {};
199
+ let order = 0;
200
+ for (const definition of metamodel.elements.values()) elements[definition.kind] = definition.role !== void 0 ? false : {
201
+ label: definition.label,
202
+ order: order++,
203
+ section: definition.category === "actor" ? "actors" : "elements",
204
+ ...definition.category === "actor" ? { group: "actors" } : {}
205
+ };
206
+ const links = {};
207
+ order = 0;
208
+ for (const definition of metamodel.links.values()) links[definition.kind] = definition.role !== void 0 ? false : [{
209
+ label: definition.label,
210
+ order: order++,
211
+ section: "elements"
212
+ }];
213
+ return {
214
+ elements,
215
+ links,
216
+ groups: { actors: { label: "Actor" } }
217
+ };
218
+ }
187
219
  //#endregion
188
220
  //#region src/markers.ts
189
221
  /** A `GoalDiagnostic` as a GLSP marker: `kind` is its severity, `label` its message. */
@@ -274,7 +306,12 @@ function linkIssueDiagnostics(model) {
274
306
  function createActionDispatcher(store, options = {}) {
275
307
  const s = store;
276
308
  const guards = options.guards ?? [];
277
- const palette = options.palette ?? _istar_ts_core.DEFAULT_PALETTE;
309
+ const postGuards = options.postGuards ?? [];
310
+ const resolvePalette = (meta) => {
311
+ const option = options.palette;
312
+ if (typeof option === "function") return option();
313
+ return option ?? paletteFromMetamodel(meta);
314
+ };
278
315
  const sourceModelName = options.sourceModelName ?? "";
279
316
  const listeners = /* @__PURE__ */ new Set();
280
317
  let saved = s.getModel();
@@ -319,8 +356,18 @@ function createActionDispatcher(store, options = {}) {
319
356
  for (const guard of guards) for (const d of guard(operation, s.getModel()) ?? []) (d.severity === "error" ? errors : warnings).push(d);
320
357
  if (errors.length > 0) throw new Rejection(errors);
321
358
  };
359
+ const runPostGuards = (operation, before, warnings) => {
360
+ const errors = [];
361
+ for (const guard of postGuards) for (const d of guard(operation, s.getModel(), before) ?? []) (d.severity === "error" ? errors : warnings).push(d);
362
+ if (errors.length > 0) throw new Rejection(errors);
363
+ };
322
364
  const apply = (operation, warnings) => {
323
365
  runGuards(operation, warnings);
366
+ const before = s.getModel();
367
+ doApply(operation, warnings);
368
+ runPostGuards(operation, before, warnings);
369
+ };
370
+ const doApply = (operation, warnings) => {
324
371
  const model = s.getModel();
325
372
  const meta = metaOf(model);
326
373
  switch (operation.kind) {
@@ -487,6 +534,45 @@ function createActionDispatcher(store, options = {}) {
487
534
  s.updateLink(linkId, { label: value });
488
535
  return;
489
536
  }
537
+ case "istar.changeLinkKind": {
538
+ const { linkIds, elementTypeId: kind } = operation;
539
+ if (linkIds.length === 0) return;
540
+ const ids = new Set(linkIds);
541
+ const links = [...ids].map((id) => model.links.get(id) ?? reject(`unknown link "${id}"`, id, "unknown-element"));
542
+ const definition = meta.links.get(kind) ?? reject(`unknown link kind "${kind}" in ${meta.name}`, "", "unknown-kind");
543
+ const toChange = links.filter((link) => link.kind !== kind);
544
+ if (toChange.length === 0) return;
545
+ const remaining = new Map(model.links);
546
+ for (const id of ids) remaining.delete(id);
547
+ const without = withLinks(model, remaining);
548
+ const values = definition.info.possibleLabels;
549
+ for (const link of toChange) {
550
+ const check = (0, _istar_ts_core.canLink)(without, link.source, link.target, kind);
551
+ if (!check.ok) rejectCheck(check, {
552
+ source: link.source,
553
+ target: link.target
554
+ });
555
+ if (link.label != null && values && !values.includes(link.label)) reject(`"${link.label}" is not a value of a ${definition.label} link (${values.join(", ")})`, link.id, "invalid-value");
556
+ }
557
+ const next = new Map(model.links);
558
+ for (const link of toChange) next.set(link.id, {
559
+ ...link,
560
+ kind
561
+ });
562
+ s.replace(withLinks(model, next));
563
+ return;
564
+ }
565
+ case "istar.setFileMetamodel": {
566
+ let next;
567
+ try {
568
+ next = (0, _istar_ts_core.withFileMetamodel)(model, operation.block);
569
+ } catch (error) {
570
+ if (error instanceof _istar_ts_core.MetamodelError) reject(error.message, "", "invalid-metamodel");
571
+ throw error;
572
+ }
573
+ s.replace(next);
574
+ return;
575
+ }
490
576
  default: reject(`unknown operation "${operation.kind}"`, "", "unknown-action");
491
577
  }
492
578
  };
@@ -647,11 +733,14 @@ function createActionDispatcher(store, options = {}) {
647
733
  ...typeHintsFor(metaOf(model))
648
734
  };
649
735
  case "requestCheckEdge": return checkEdge(action);
650
- case "requestContextActions": return {
651
- kind: "setContextActions",
652
- responseId: action.requestId,
653
- ...contextActionsFor(palette, metaOf(model))
654
- };
736
+ case "requestContextActions": {
737
+ const meta = metaOf(model);
738
+ return {
739
+ kind: "setContextActions",
740
+ responseId: action.requestId,
741
+ ...contextActionsFor(resolvePalette(meta), meta)
742
+ };
743
+ }
655
744
  case "requestMarkers": return markers(action);
656
745
  default: return;
657
746
  }
@@ -1112,6 +1201,7 @@ exports.hostToolContext = hostToolContext;
1112
1201
  exports.isOperation = isOperation;
1113
1202
  exports.isRequestAction = isRequestAction;
1114
1203
  exports.markerToDiagnostic = markerToDiagnostic;
1204
+ exports.paletteFromMetamodel = paletteFromMetamodel;
1115
1205
  exports.readOnlyDispatcher = readOnlyDispatcher;
1116
1206
  exports.typeHintsFor = typeHintsFor;
1117
1207