@timeax/digital-service-engine 0.2.4 → 0.2.6

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.
@@ -730,6 +730,7 @@ function normalise(input, opts = {}) {
730
730
  const excludes_for_buttons = toStringArrayMap(
731
731
  obj.excludes_for_buttons
732
732
  );
733
+ const orderKinds = toStringMap(obj.orderKinds);
733
734
  const notices = toNoticeArray(obj.notices);
734
735
  let filters = rawFilters.map((t) => coerceTag(t, constraints));
735
736
  const fields = rawFields.map((f) => coerceField(f, defRole));
@@ -741,6 +742,7 @@ function normalise(input, opts = {}) {
741
742
  filters,
742
743
  fields,
743
744
  order_for_tags: obj.order_for_tags,
745
+ ...isNonEmpty(orderKinds) && { orderKinds },
744
746
  ...isNonEmpty(includes_for_buttons) && { includes_for_buttons },
745
747
  ...isNonEmpty(excludes_for_buttons) && { excludes_for_buttons },
746
748
  ...fallbacks && (isNonEmpty(fallbacks.nodes) || isNonEmpty(fallbacks.global)) && {
@@ -951,6 +953,15 @@ function normaliseBindId(bind) {
951
953
  }
952
954
  return void 0;
953
955
  }
956
+ function toStringMap(src) {
957
+ if (!src || typeof src !== "object") return void 0;
958
+ const out = {};
959
+ for (const [k, v] of Object.entries(src)) {
960
+ if (!k || typeof v !== "string") continue;
961
+ out[k] = v;
962
+ }
963
+ return Object.keys(out).length ? out : void 0;
964
+ }
954
965
  function toStringArrayMap(src) {
955
966
  if (!src || typeof src !== "object") return void 0;
956
967
  const out = {};
@@ -1769,6 +1780,129 @@ function validateOptionMaps(v) {
1769
1780
  }
1770
1781
  }
1771
1782
 
1783
+ // src/utils/order-kind.ts
1784
+ function normalizeSelectedTriggerKey(key, nodeMap) {
1785
+ if (!key) return void 0;
1786
+ const compositeIdx = key.indexOf("::");
1787
+ if (compositeIdx !== -1) {
1788
+ const fieldId = key.slice(0, compositeIdx).trim();
1789
+ const optionId = key.slice(compositeIdx + 2).trim();
1790
+ if (optionId) {
1791
+ const optionRef = nodeMap.get(optionId);
1792
+ if ((optionRef == null ? void 0 : optionRef.kind) === "option") {
1793
+ return { nodeId: optionRef.id, nodeKind: "option" };
1794
+ }
1795
+ }
1796
+ if (fieldId) {
1797
+ const fieldRef = nodeMap.get(fieldId);
1798
+ if ((fieldRef == null ? void 0 : fieldRef.kind) === "field") {
1799
+ return { nodeId: fieldRef.id, nodeKind: "field" };
1800
+ }
1801
+ }
1802
+ return void 0;
1803
+ }
1804
+ const ref = nodeMap.get(key);
1805
+ if (!ref) return void 0;
1806
+ if (ref.kind !== "field" && ref.kind !== "option") return void 0;
1807
+ return { nodeId: ref.id, nodeKind: ref.kind };
1808
+ }
1809
+ function normalizeSelectedOrderKindTriggers(selectedTriggerKeys, nodeMap) {
1810
+ if (!selectedTriggerKeys) return [];
1811
+ const out = [];
1812
+ const seen = /* @__PURE__ */ new Set();
1813
+ for (const rawKey of selectedTriggerKeys) {
1814
+ const key = String(rawKey != null ? rawKey : "");
1815
+ const normalized = normalizeSelectedTriggerKey(key, nodeMap);
1816
+ if (!normalized) continue;
1817
+ const dedupeKey = `${normalized.nodeKind}:${normalized.nodeId}`;
1818
+ if (seen.has(dedupeKey)) continue;
1819
+ seen.add(dedupeKey);
1820
+ out.push(normalized);
1821
+ }
1822
+ return out;
1823
+ }
1824
+ function resolveOrderKind(params) {
1825
+ var _a, _b;
1826
+ const nodeMap = (_a = params.nodeMap) != null ? _a : buildNodeMap(params.props);
1827
+ const orderKinds = (_b = params.props.orderKinds) != null ? _b : {};
1828
+ const normalizedSelected = normalizeSelectedOrderKindTriggers(
1829
+ params.selectedTriggerKeys,
1830
+ nodeMap
1831
+ );
1832
+ const selectedKindToSource = /* @__PURE__ */ new Map();
1833
+ const selectedNodeIdsForKinds = /* @__PURE__ */ new Map();
1834
+ for (const trigger of normalizedSelected) {
1835
+ const mappedKind = orderKinds[trigger.nodeId];
1836
+ if (typeof mappedKind !== "string") continue;
1837
+ if (!selectedKindToSource.has(mappedKind)) {
1838
+ selectedKindToSource.set(mappedKind, {
1839
+ nodeId: trigger.nodeId,
1840
+ nodeKind: trigger.nodeKind
1841
+ });
1842
+ }
1843
+ if (!selectedNodeIdsForKinds.has(mappedKind)) {
1844
+ selectedNodeIdsForKinds.set(mappedKind, /* @__PURE__ */ new Set());
1845
+ }
1846
+ selectedNodeIdsForKinds.get(mappedKind).add(trigger.nodeId);
1847
+ }
1848
+ const selectedKinds = Array.from(selectedKindToSource.keys());
1849
+ if (selectedKinds.length > 1) {
1850
+ const conflictingNodeIds = Array.from(selectedNodeIdsForKinds.values()).flatMap((ids) => Array.from(ids)).filter((id, idx, arr) => arr.indexOf(id) === idx);
1851
+ return {
1852
+ kind: null,
1853
+ source: null,
1854
+ error: "multiple_order_kinds_selected",
1855
+ conflictingKinds: selectedKinds,
1856
+ conflictingNodeIds
1857
+ };
1858
+ }
1859
+ if (selectedKinds.length === 1) {
1860
+ const selectedKind = selectedKinds[0];
1861
+ return {
1862
+ kind: selectedKind,
1863
+ source: selectedKindToSource.get(selectedKind)
1864
+ };
1865
+ }
1866
+ const activeTagId = params.activeTagId;
1867
+ if (activeTagId) {
1868
+ const tagKind = orderKinds[activeTagId];
1869
+ if (typeof tagKind === "string") {
1870
+ return {
1871
+ kind: tagKind,
1872
+ source: { nodeId: activeTagId, nodeKind: "tag" }
1873
+ };
1874
+ }
1875
+ }
1876
+ return { kind: null, source: null };
1877
+ }
1878
+
1879
+ // src/core/validate/steps/order-kinds.ts
1880
+ function validateOrderKinds(v) {
1881
+ var _a, _b, _c;
1882
+ const selectedTriggerKeys = Array.from((_a = v.selectedKeys) != null ? _a : []);
1883
+ if (!selectedTriggerKeys.length) return;
1884
+ const resolved = resolveOrderKind({
1885
+ props: v.props,
1886
+ selectedTriggerKeys,
1887
+ nodeMap: v.nodeMap
1888
+ });
1889
+ if (resolved.error !== "multiple_order_kinds_selected") return;
1890
+ const conflicts = (_b = resolved.conflictingKinds) != null ? _b : [];
1891
+ const affected = (_c = resolved.conflictingNodeIds) != null ? _c : [];
1892
+ v.errors.push({
1893
+ code: "multiple_order_kinds_selected",
1894
+ severity: "error",
1895
+ message: "Multiple selected triggers resolve to different order kinds. Select triggers that resolve to a single order kind.",
1896
+ details: withAffected(
1897
+ {
1898
+ conflictingKinds: conflicts,
1899
+ conflictingNodeIds: affected
1900
+ },
1901
+ affected
1902
+ )
1903
+ });
1904
+ }
1905
+
1772
1906
  // src/core/validate/steps/service-vs-input.ts
1773
1907
  function validateServiceVsUserInput(v) {
1774
1908
  for (const f of v.fields) {
@@ -3097,6 +3231,7 @@ var BuilderImpl = class {
3097
3231
  const out = {
3098
3232
  filters: this.props.filters.slice(),
3099
3233
  fields,
3234
+ ...this.props.orderKinds ? { orderKinds: this.props.orderKinds } : {},
3100
3235
  ...includes_for_buttons && { includes_for_buttons },
3101
3236
  ...excludes_for_buttons && { excludes_for_buttons },
3102
3237
  schema_version: (_e = this.props.schema_version) != null ? _e : "1.0",
@@ -3429,6 +3564,7 @@ function validate(props, ctx = {}) {
3429
3564
  validateStructure(v);
3430
3565
  validateIdentity(v);
3431
3566
  validateOptionMaps(v);
3567
+ validateOrderKinds(v);
3432
3568
  v.fieldsVisibleUnder = createFieldsVisibleUnder(v);
3433
3569
  const visSim = readVisibilitySimOpts(options);
3434
3570
  validateVisibility(v, visSim);
@@ -3883,7 +4019,7 @@ function createNodeIndex(builder) {
3883
4019
  for (const fieldId of visible) {
3884
4020
  const node = getField(fieldId);
3885
4021
  if (!node) continue;
3886
- const explicit = includes.has(fieldId) || isFieldBoundDirectToTag(fieldId, tagId);
4022
+ const explicit = includes.has(fieldId);
3887
4023
  results.push(explicit ? node : { ...node, isInherited: true });
3888
4024
  }
3889
4025
  return Object.freeze(results);
@@ -4777,6 +4913,13 @@ function buildOrderSnapshot(props, builder, selection, services, settings = {})
4777
4913
  fieldById
4778
4914
  );
4779
4915
  const { min, max } = resolveMinMax(servicesList, services);
4916
+ const maybeNodeMap = typeof builder.getNodeMap === "function" ? builder.getNodeMap() : void 0;
4917
+ const resolvedOrderKind = resolveOrderKind({
4918
+ props,
4919
+ activeTagId: tagId,
4920
+ selectedTriggerKeys: selectedButtonKeys,
4921
+ nodeMap: maybeNodeMap
4922
+ });
4780
4923
  const prunedFallbacks = pruneFallbacksConservative(
4781
4924
  props.fallbacks,
4782
4925
  { tagId, constraints: tagConstraints, serviceMap, servicesList },
@@ -4832,6 +4975,8 @@ function buildOrderSnapshot(props, builder, selection, services, settings = {})
4832
4975
  },
4833
4976
  min,
4834
4977
  max: max != null ? max : min,
4978
+ orderKind: resolvedOrderKind.kind,
4979
+ orderKindSource: resolvedOrderKind.source,
4835
4980
  quantity,
4836
4981
  quantitySource,
4837
4982
  services: servicesList,
@@ -6853,6 +6998,88 @@ function normalizeQuantityRule(input) {
6853
6998
  return out;
6854
6999
  }
6855
7000
 
7001
+ // src/react/canvas/editor/editor-order-kinds.ts
7002
+ function normalizeKind(kind) {
7003
+ const next = String(kind != null ? kind : "").trim();
7004
+ if (!next) {
7005
+ throw new Error("setOrderKind: kind must be a non-empty string");
7006
+ }
7007
+ return next;
7008
+ }
7009
+ function assertCanonicalNodeId(ctx, nodeId) {
7010
+ const id = String(nodeId != null ? nodeId : "").trim();
7011
+ if (!id) throw new Error("setOrderKind: nodeId is required");
7012
+ if (id.includes("::")) {
7013
+ throw new Error(
7014
+ "setOrderKind: composite/internal trigger keys are not allowed; use canonical tag/field/option ids"
7015
+ );
7016
+ }
7017
+ if (!ctx.isTagId(id) && !ctx.isFieldId(id) && !ctx.isOptionId(id)) {
7018
+ throw new Error(
7019
+ `setOrderKind: node id '${id}' is not a known tag, field, or option`
7020
+ );
7021
+ }
7022
+ if (ctx.isFieldId(id)) {
7023
+ const node = ctx.getNode(id);
7024
+ if (node.kind !== "field" || !isActualButtonField(node.data)) {
7025
+ throw new Error(
7026
+ `setOrderKind: field '${id}' must be a button field without options`
7027
+ );
7028
+ }
7029
+ }
7030
+ }
7031
+ function setOrderKind(ctx, nodeId, kind) {
7032
+ const id = String(nodeId != null ? nodeId : "").trim();
7033
+ const nextKind = normalizeKind(kind);
7034
+ assertCanonicalNodeId(ctx, id);
7035
+ ctx.exec({
7036
+ name: "setOrderKind",
7037
+ do: () => ctx.patchProps((p) => {
7038
+ if (!p.orderKinds) p.orderKinds = {};
7039
+ p.orderKinds[id] = nextKind;
7040
+ }),
7041
+ undo: () => ctx.undo()
7042
+ });
7043
+ }
7044
+ function deleteOrderKind(ctx, nodeId) {
7045
+ const id = String(nodeId != null ? nodeId : "").trim();
7046
+ if (!id) return;
7047
+ ctx.exec({
7048
+ name: "deleteOrderKind",
7049
+ do: () => ctx.patchProps((p) => {
7050
+ if (!p.orderKinds || !Object.prototype.hasOwnProperty.call(p.orderKinds, id)) {
7051
+ return;
7052
+ }
7053
+ delete p.orderKinds[id];
7054
+ if (!Object.keys(p.orderKinds).length) {
7055
+ delete p.orderKinds;
7056
+ }
7057
+ }),
7058
+ undo: () => ctx.undo()
7059
+ });
7060
+ }
7061
+ function pruneOrderKind(ctx, kind) {
7062
+ const target = normalizeKind(kind);
7063
+ let removedCount = 0;
7064
+ ctx.exec({
7065
+ name: "pruneOrderKind",
7066
+ do: () => ctx.patchProps((p) => {
7067
+ if (!p.orderKinds) return;
7068
+ removedCount = 0;
7069
+ for (const [nodeId, mapped] of Object.entries(p.orderKinds)) {
7070
+ if (mapped !== target) continue;
7071
+ delete p.orderKinds[nodeId];
7072
+ removedCount++;
7073
+ }
7074
+ if (!Object.keys(p.orderKinds).length) {
7075
+ delete p.orderKinds;
7076
+ }
7077
+ }),
7078
+ undo: () => ctx.undo()
7079
+ });
7080
+ return removedCount;
7081
+ }
7082
+
6856
7083
  // src/react/canvas/editor/editor-relations.ts
6857
7084
  function wouldCreateTagCycle(_ctx, p, parentId, childId) {
6858
7085
  var _a, _b;
@@ -6900,7 +7127,9 @@ function include(ctx, receiverId, idOrIds) {
6900
7127
  const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
6901
7128
  if (receiver.kind === "tag" || receiver.kind === "field" && isActualButtonField(receiver.data) || receiver.kind === "option") {
6902
7129
  if (receiver.kind === "tag") {
6903
- const t = ((_a = p.filters) != null ? _a : []).find((x) => x.id === receiverId);
7130
+ const t = ((_a = p.filters) != null ? _a : []).find(
7131
+ (x) => x.id === receiverId
7132
+ );
6904
7133
  if (t) {
6905
7134
  const accepted = [];
6906
7135
  const next = new Set((_b = t.includes) != null ? _b : []);
@@ -6942,7 +7171,12 @@ function include(ctx, receiverId, idOrIds) {
6942
7171
  const current = (_f = (_e = p.includes_for_buttons) == null ? void 0 : _e[receiverId]) != null ? _f : [];
6943
7172
  const next = new Set(current);
6944
7173
  for (const id of ids) {
6945
- if (wouldCreateIncludeExcludeCycle(ctx, p, receiverId, id)) {
7174
+ if (wouldCreateIncludeExcludeCycle(
7175
+ ctx,
7176
+ p,
7177
+ receiverId,
7178
+ id
7179
+ )) {
6946
7180
  ctx.emit("editor:error", {
6947
7181
  message: `Cycle detected: ${receiverId} including ${id} would create a cycle.`,
6948
7182
  code: "cycle_detected",
@@ -6958,7 +7192,8 @@ function include(ctx, receiverId, idOrIds) {
6958
7192
  accepted.push(id);
6959
7193
  }
6960
7194
  if (accepted.length > 0 || current.length > 0) {
6961
- if (!p.includes_for_buttons) p.includes_for_buttons = {};
7195
+ if (!p.includes_for_buttons)
7196
+ p.includes_for_buttons = {};
6962
7197
  p.includes_for_buttons[receiverId] = Array.from(next);
6963
7198
  }
6964
7199
  if ((_g = p.excludes_for_buttons) == null ? void 0 : _g[receiverId]) {
@@ -6973,7 +7208,9 @@ function include(ctx, receiverId, idOrIds) {
6973
7208
  if (!p.fields) p.fields = [];
6974
7209
  if (!p.filters) p.filters = [];
6975
7210
  } else {
6976
- throw new Error("Receiver must be a tag, button field, or option");
7211
+ throw new Error(
7212
+ "Receiver must be a tag, button field, or option"
7213
+ );
6977
7214
  }
6978
7215
  }),
6979
7216
  undo: () => ctx.undo()
@@ -6988,7 +7225,9 @@ function exclude(ctx, receiverId, idOrIds) {
6988
7225
  const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
6989
7226
  if (receiver.kind === "tag" || receiver.kind === "field" && isActualButtonField(receiver.data) || receiver.kind === "option") {
6990
7227
  if (receiver.kind === "tag") {
6991
- const t = ((_a = p.filters) != null ? _a : []).find((x) => x.id === receiverId);
7228
+ const t = ((_a = p.filters) != null ? _a : []).find(
7229
+ (x) => x.id === receiverId
7230
+ );
6992
7231
  if (t) {
6993
7232
  const accepted = [];
6994
7233
  const next = new Set((_b = t.excludes) != null ? _b : []);
@@ -7030,7 +7269,12 @@ function exclude(ctx, receiverId, idOrIds) {
7030
7269
  const current = (_f = (_e = p.excludes_for_buttons) == null ? void 0 : _e[receiverId]) != null ? _f : [];
7031
7270
  const next = new Set(current);
7032
7271
  for (const id of ids) {
7033
- if (wouldCreateIncludeExcludeCycle(ctx, p, receiverId, id)) {
7272
+ if (wouldCreateIncludeExcludeCycle(
7273
+ ctx,
7274
+ p,
7275
+ receiverId,
7276
+ id
7277
+ )) {
7034
7278
  ctx.emit("editor:error", {
7035
7279
  message: `Cycle detected: ${receiverId} excluding ${id} would create a cycle.`,
7036
7280
  code: "cycle_detected",
@@ -7046,7 +7290,8 @@ function exclude(ctx, receiverId, idOrIds) {
7046
7290
  accepted.push(id);
7047
7291
  }
7048
7292
  if (accepted.length > 0 || current.length > 0) {
7049
- if (!p.excludes_for_buttons) p.excludes_for_buttons = {};
7293
+ if (!p.excludes_for_buttons)
7294
+ p.excludes_for_buttons = {};
7050
7295
  p.excludes_for_buttons[receiverId] = Array.from(next);
7051
7296
  }
7052
7297
  if ((_g = p.includes_for_buttons) == null ? void 0 : _g[receiverId]) {
@@ -7061,7 +7306,9 @@ function exclude(ctx, receiverId, idOrIds) {
7061
7306
  if (!p.fields) p.fields = [];
7062
7307
  if (!p.filters) p.filters = [];
7063
7308
  } else {
7064
- throw new Error("Receiver must be a tag, button field, or option");
7309
+ throw new Error(
7310
+ "Receiver must be a tag, button field, or option"
7311
+ );
7065
7312
  }
7066
7313
  }),
7067
7314
  undo: () => ctx.undo()
@@ -7071,87 +7318,98 @@ function connect(ctx, kind, fromId, toId2) {
7071
7318
  ctx.exec({
7072
7319
  name: `connect:${kind}`,
7073
7320
  do: () => ctx.patchProps((p) => {
7074
- var _a, _b, _c, _d, _e;
7321
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7075
7322
  if (kind === "bind") {
7076
7323
  if (ctx.isTagId(fromId) && ctx.isTagId(toId2)) {
7077
7324
  if (wouldCreateTagCycle(ctx, p, fromId, toId2)) {
7078
- throw new Error(`bind would create a cycle: ${fromId} ? ${toId2}`);
7325
+ throw new Error(
7326
+ `bind would create a cycle: ${fromId} ? ${toId2}`
7327
+ );
7079
7328
  }
7080
- const child = ((_a = p.filters) != null ? _a : []).find((t) => t.id === toId2);
7329
+ const child = ((_a = p.filters) != null ? _a : []).find(
7330
+ (t) => t.id === toId2
7331
+ );
7081
7332
  if (child) child.bind_id = fromId;
7082
7333
  return;
7083
7334
  }
7084
7335
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2) || ctx.isFieldId(fromId) && ctx.isTagId(toId2)) {
7085
7336
  const fieldId = ctx.isFieldId(toId2) ? toId2 : fromId;
7086
7337
  const tagId = ctx.isTagId(fromId) ? fromId : toId2;
7087
- const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === fieldId);
7338
+ const f = ((_b = p.fields) != null ? _b : []).find(
7339
+ (x) => x.id === fieldId
7340
+ );
7088
7341
  if (!f) return;
7089
7342
  if (!f.bind_id) {
7090
7343
  f.bind_id = tagId;
7091
7344
  return;
7092
7345
  }
7093
7346
  if (typeof f.bind_id === "string") {
7094
- if (f.bind_id !== tagId) f.bind_id = [f.bind_id, tagId];
7347
+ if (f.bind_id !== tagId) {
7348
+ f.bind_id = [f.bind_id, tagId];
7349
+ }
7095
7350
  return;
7096
7351
  }
7097
- if (!f.bind_id.includes(tagId)) f.bind_id.push(tagId);
7352
+ if (!f.bind_id.includes(tagId)) {
7353
+ f.bind_id.push(tagId);
7354
+ }
7098
7355
  return;
7099
7356
  }
7100
- throw new Error(`bind: unsupported route ${fromId} ? ${toId2}`);
7357
+ throw new Error(
7358
+ `bind: unsupported route ${fromId} ? ${toId2}`
7359
+ );
7101
7360
  }
7102
7361
  if (kind === "include" || kind === "exclude") {
7103
- const key = kind === "include" ? "includes" : "excludes";
7362
+ const tagKey = kind === "include" ? "includes" : "excludes";
7363
+ const mapKey = kind === "include" ? "includes_for_buttons" : "excludes_for_buttons";
7104
7364
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2)) {
7105
- const t = ((_c = p.filters) != null ? _c : []).find((x) => x.id === fromId);
7365
+ const t = ((_c = p.filters) != null ? _c : []).find(
7366
+ (x) => x.id === fromId
7367
+ );
7106
7368
  if (!t) return;
7107
- const arr = (_d = t[key]) != null ? _d : t[key] = [];
7369
+ const arr = (_d = t[tagKey]) != null ? _d : t[tagKey] = [];
7108
7370
  if (!arr.includes(toId2)) arr.push(toId2);
7109
7371
  return;
7110
7372
  }
7373
+ if (ctx.isFieldId(fromId) && ctx.isFieldId(toId2)) {
7374
+ const source = ((_e = p.fields) != null ? _e : []).find(
7375
+ (x) => x.id === fromId
7376
+ );
7377
+ if (!(source == null ? void 0 : source.button)) {
7378
+ throw new Error(
7379
+ `${kind}: source field must be button=true: ${fromId} ? ${toId2}`
7380
+ );
7381
+ }
7382
+ addMappedField(p, mapKey, fromId, toId2);
7383
+ return;
7384
+ }
7111
7385
  if (ctx.isOptionId(fromId) && ctx.isFieldId(toId2)) {
7112
- const mapKey = kind === "include" ? "includes_for_options" : "excludes_for_options";
7113
- const maps = p[mapKey];
7114
- const next = { ...maps != null ? maps : {} };
7115
- const arr = (_e = next[fromId]) != null ? _e : [];
7116
- if (!arr.includes(toId2)) arr.push(toId2);
7117
- next[fromId] = arr;
7118
- p[mapKey] = next;
7386
+ addMappedField(p, mapKey, fromId, toId2);
7119
7387
  return;
7120
7388
  }
7121
- throw new Error(`${kind}: unsupported route ${fromId} ? ${toId2}`);
7389
+ throw new Error(
7390
+ `${kind}: unsupported route ${fromId} ? ${toId2}`
7391
+ );
7122
7392
  }
7123
7393
  if (kind === "service") {
7124
7394
  ensureServiceExists(ctx.opts, fromId);
7125
7395
  if (toId2.startsWith("t:")) {
7126
- ctx.exec({
7127
- name: "connect:service?tag",
7128
- do: () => ctx.patchProps((next) => {
7129
- var _a2;
7130
- const t = ((_a2 = next.filters) != null ? _a2 : []).find((x) => x.id === toId2);
7131
- if (t) t.service_id = fromId;
7132
- }),
7133
- undo: () => ctx.undo()
7134
- });
7396
+ const t = ((_f = p.filters) != null ? _f : []).find((x) => x.id === toId2);
7397
+ if (t) t.service_id = fromId;
7135
7398
  return;
7136
7399
  }
7137
7400
  if (toId2.startsWith("o:")) {
7138
- ctx.exec({
7139
- name: "connect:service?option",
7140
- do: () => ctx.patchProps((next) => {
7141
- var _a2, _b2;
7142
- for (const f of (_a2 = next.fields) != null ? _a2 : []) {
7143
- const o = (_b2 = f.options) == null ? void 0 : _b2.find((x) => x.id === toId2);
7144
- if (o) {
7145
- o.service_id = fromId;
7146
- return;
7147
- }
7148
- }
7149
- }),
7150
- undo: () => ctx.undo()
7151
- });
7401
+ for (const f of (_g = p.fields) != null ? _g : []) {
7402
+ const o = (_h = f.options) == null ? void 0 : _h.find((x) => x.id === toId2);
7403
+ if (o) {
7404
+ o.service_id = fromId;
7405
+ return;
7406
+ }
7407
+ }
7152
7408
  return;
7153
7409
  }
7154
- throw new Error('service: to must be a tag ("t:*") or option ("o:*")');
7410
+ throw new Error(
7411
+ 'service: to must be a tag ("t:*") or option ("o:*")'
7412
+ );
7155
7413
  }
7156
7414
  throw new Error(`Unknown connect kind: ${kind}`);
7157
7415
  }),
@@ -7162,90 +7420,109 @@ function disconnect(ctx, kind, fromId, toId2) {
7162
7420
  ctx.exec({
7163
7421
  name: `disconnect:${kind}`,
7164
7422
  do: () => ctx.patchProps((p) => {
7165
- var _a, _b, _c, _d, _e, _f, _g, _h;
7423
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
7166
7424
  if (kind === "bind") {
7167
7425
  if (ctx.isTagId(fromId) && ctx.isTagId(toId2)) {
7168
- const child = ((_a = p.filters) != null ? _a : []).find((t) => t.id === toId2);
7169
- if ((child == null ? void 0 : child.bind_id) === fromId) delete child.bind_id;
7426
+ const child = ((_a = p.filters) != null ? _a : []).find(
7427
+ (t) => t.id === toId2
7428
+ );
7429
+ if ((child == null ? void 0 : child.bind_id) === fromId) {
7430
+ delete child.bind_id;
7431
+ }
7170
7432
  return;
7171
7433
  }
7172
7434
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2) || ctx.isFieldId(fromId) && ctx.isTagId(toId2)) {
7173
7435
  const fieldId = ctx.isFieldId(toId2) ? toId2 : fromId;
7174
7436
  const tagId = ctx.isTagId(fromId) ? fromId : toId2;
7175
- const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === fieldId);
7437
+ const f = ((_b = p.fields) != null ? _b : []).find(
7438
+ (x) => x.id === fieldId
7439
+ );
7176
7440
  if (!(f == null ? void 0 : f.bind_id)) return;
7177
7441
  if (typeof f.bind_id === "string") {
7178
- if (f.bind_id === tagId) delete f.bind_id;
7442
+ if (f.bind_id === tagId) {
7443
+ delete f.bind_id;
7444
+ }
7179
7445
  return;
7180
7446
  }
7181
7447
  f.bind_id = f.bind_id.filter((x) => x !== tagId);
7182
- if (((_c = f.bind_id) == null ? void 0 : _c.length) === 0) delete f.bind_id;
7448
+ if (((_c = f.bind_id) == null ? void 0 : _c.length) === 0) {
7449
+ delete f.bind_id;
7450
+ }
7183
7451
  return;
7184
7452
  }
7185
- throw new Error(`unbind: unsupported route ${fromId} ? ${toId2}`);
7453
+ throw new Error(
7454
+ `unbind: unsupported route ${fromId} ? ${toId2}`
7455
+ );
7186
7456
  }
7187
7457
  if (kind === "include" || kind === "exclude") {
7188
- const key = kind === "include" ? "includes" : "excludes";
7458
+ const tagKey = kind === "include" ? "includes" : "excludes";
7459
+ const mapKey = kind === "include" ? "includes_for_buttons" : "excludes_for_buttons";
7189
7460
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2)) {
7190
- const t = ((_d = p.filters) != null ? _d : []).find((x) => x.id === fromId);
7461
+ const t = ((_d = p.filters) != null ? _d : []).find(
7462
+ (x) => x.id === fromId
7463
+ );
7191
7464
  if (!t) return;
7192
- t[key] = ((_e = t[key]) != null ? _e : []).filter((x) => x !== toId2);
7193
- if (!((_f = t[key]) == null ? void 0 : _f.length)) delete t[key];
7465
+ t[tagKey] = ((_e = t[tagKey]) != null ? _e : []).filter((x) => x !== toId2);
7466
+ if (!((_f = t[tagKey]) == null ? void 0 : _f.length)) {
7467
+ delete t[tagKey];
7468
+ }
7194
7469
  return;
7195
7470
  }
7196
- if (ctx.isOptionId(fromId) && ctx.isFieldId(toId2)) {
7197
- const mapKey = kind === "include" ? "includes_for_options" : "excludes_for_options";
7471
+ if ((ctx.isFieldId(fromId) || ctx.isOptionId(fromId)) && ctx.isFieldId(toId2)) {
7198
7472
  const maps = p[mapKey];
7199
- if (!maps) return;
7200
- if (maps[fromId]) {
7201
- maps[fromId] = ((_g = maps[fromId]) != null ? _g : []).filter(
7202
- (fid) => fid !== toId2
7203
- );
7204
- if (!((_h = maps[fromId]) == null ? void 0 : _h.length)) delete maps[fromId];
7473
+ if (!(maps == null ? void 0 : maps[fromId])) return;
7474
+ maps[fromId] = maps[fromId].filter(
7475
+ (fid) => fid !== toId2
7476
+ );
7477
+ if (!((_g = maps[fromId]) == null ? void 0 : _g.length)) {
7478
+ delete maps[fromId];
7479
+ }
7480
+ if (!Object.keys(maps).length) {
7481
+ delete p[mapKey];
7205
7482
  }
7206
- if (!Object.keys(maps).length) delete p[mapKey];
7207
7483
  return;
7208
7484
  }
7209
- throw new Error(`${kind}: unsupported route ${fromId} ? ${toId2}`);
7485
+ throw new Error(
7486
+ `${kind}: unsupported route ${fromId} ? ${toId2}`
7487
+ );
7210
7488
  }
7211
7489
  if (kind === "service") {
7212
7490
  ensureServiceExists(ctx.opts, fromId);
7213
7491
  if (toId2.startsWith("t:")) {
7214
- ctx.exec({
7215
- name: "disconnect:service?tag",
7216
- do: () => ctx.patchProps((next) => {
7217
- var _a2;
7218
- const t = ((_a2 = next.filters) != null ? _a2 : []).find((x) => x.id === toId2);
7219
- if (t) delete t.service_id;
7220
- }),
7221
- undo: () => ctx.undo()
7222
- });
7492
+ const t = ((_h = p.filters) != null ? _h : []).find((x) => x.id === toId2);
7493
+ if (t) {
7494
+ delete t.service_id;
7495
+ }
7223
7496
  return;
7224
7497
  }
7225
7498
  if (toId2.startsWith("o:")) {
7226
- ctx.exec({
7227
- name: "disconnect:service?option",
7228
- do: () => ctx.patchProps((next) => {
7229
- var _a2, _b2;
7230
- for (const f of (_a2 = next.fields) != null ? _a2 : []) {
7231
- const o = (_b2 = f.options) == null ? void 0 : _b2.find((x) => x.id === toId2);
7232
- if (o) {
7233
- delete o.service_id;
7234
- return;
7235
- }
7236
- }
7237
- }),
7238
- undo: () => ctx.undo()
7239
- });
7499
+ for (const f of (_i = p.fields) != null ? _i : []) {
7500
+ const o = (_j = f.options) == null ? void 0 : _j.find((x) => x.id === toId2);
7501
+ if (o) {
7502
+ delete o.service_id;
7503
+ return;
7504
+ }
7505
+ }
7240
7506
  return;
7241
7507
  }
7242
- throw new Error('service: to must be a tag ("t:*") or option ("o:*")');
7508
+ throw new Error(
7509
+ 'service: to must be a tag ("t:*") or option ("o:*")'
7510
+ );
7243
7511
  }
7244
7512
  throw new Error(`Unknown disconnect kind: ${kind}`);
7245
7513
  }),
7246
7514
  undo: () => ctx.undo()
7247
7515
  });
7248
7516
  }
7517
+ function addMappedField(p, mapKey, fromId, toId2) {
7518
+ var _a, _b;
7519
+ const maps = (_a = p[mapKey]) != null ? _a : {};
7520
+ const arr = (_b = maps[fromId]) != null ? _b : [];
7521
+ if (!arr.includes(toId2)) {
7522
+ maps[fromId] = [...arr, toId2];
7523
+ }
7524
+ p[mapKey] = maps;
7525
+ }
7249
7526
 
7250
7527
  // src/react/canvas/editor/editor-service-filter.ts
7251
7528
  function filterServicesForVisibleGroup2(ctx, candidates, input) {
@@ -7833,6 +8110,15 @@ var Editor = class {
7833
8110
  clearFieldValidation(id) {
7834
8111
  return clearFieldValidation(this.moduleCtx(), id);
7835
8112
  }
8113
+ setOrderKind(nodeId, kind) {
8114
+ return setOrderKind(this.moduleCtx(), nodeId, kind);
8115
+ }
8116
+ deleteOrderKind(nodeId) {
8117
+ return deleteOrderKind(this.moduleCtx(), nodeId);
8118
+ }
8119
+ pruneKind(kind) {
8120
+ return pruneOrderKind(this.moduleCtx(), kind);
8121
+ }
7836
8122
  getCatalog() {
7837
8123
  return (0, import_lodash_es4.cloneDeep)(this.catalog);
7838
8124
  }