@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.
@@ -666,6 +666,7 @@ function normalise(input, opts = {}) {
666
666
  const excludes_for_buttons = toStringArrayMap(
667
667
  obj.excludes_for_buttons
668
668
  );
669
+ const orderKinds = toStringMap(obj.orderKinds);
669
670
  const notices = toNoticeArray(obj.notices);
670
671
  let filters = rawFilters.map((t) => coerceTag(t, constraints));
671
672
  const fields = rawFields.map((f) => coerceField(f, defRole));
@@ -677,6 +678,7 @@ function normalise(input, opts = {}) {
677
678
  filters,
678
679
  fields,
679
680
  order_for_tags: obj.order_for_tags,
681
+ ...isNonEmpty(orderKinds) && { orderKinds },
680
682
  ...isNonEmpty(includes_for_buttons) && { includes_for_buttons },
681
683
  ...isNonEmpty(excludes_for_buttons) && { excludes_for_buttons },
682
684
  ...fallbacks && (isNonEmpty(fallbacks.nodes) || isNonEmpty(fallbacks.global)) && {
@@ -887,6 +889,15 @@ function normaliseBindId(bind) {
887
889
  }
888
890
  return void 0;
889
891
  }
892
+ function toStringMap(src) {
893
+ if (!src || typeof src !== "object") return void 0;
894
+ const out = {};
895
+ for (const [k, v] of Object.entries(src)) {
896
+ if (!k || typeof v !== "string") continue;
897
+ out[k] = v;
898
+ }
899
+ return Object.keys(out).length ? out : void 0;
900
+ }
890
901
  function toStringArrayMap(src) {
891
902
  if (!src || typeof src !== "object") return void 0;
892
903
  const out = {};
@@ -1705,6 +1716,129 @@ function validateOptionMaps(v) {
1705
1716
  }
1706
1717
  }
1707
1718
 
1719
+ // src/utils/order-kind.ts
1720
+ function normalizeSelectedTriggerKey(key, nodeMap) {
1721
+ if (!key) return void 0;
1722
+ const compositeIdx = key.indexOf("::");
1723
+ if (compositeIdx !== -1) {
1724
+ const fieldId = key.slice(0, compositeIdx).trim();
1725
+ const optionId = key.slice(compositeIdx + 2).trim();
1726
+ if (optionId) {
1727
+ const optionRef = nodeMap.get(optionId);
1728
+ if ((optionRef == null ? void 0 : optionRef.kind) === "option") {
1729
+ return { nodeId: optionRef.id, nodeKind: "option" };
1730
+ }
1731
+ }
1732
+ if (fieldId) {
1733
+ const fieldRef = nodeMap.get(fieldId);
1734
+ if ((fieldRef == null ? void 0 : fieldRef.kind) === "field") {
1735
+ return { nodeId: fieldRef.id, nodeKind: "field" };
1736
+ }
1737
+ }
1738
+ return void 0;
1739
+ }
1740
+ const ref = nodeMap.get(key);
1741
+ if (!ref) return void 0;
1742
+ if (ref.kind !== "field" && ref.kind !== "option") return void 0;
1743
+ return { nodeId: ref.id, nodeKind: ref.kind };
1744
+ }
1745
+ function normalizeSelectedOrderKindTriggers(selectedTriggerKeys, nodeMap) {
1746
+ if (!selectedTriggerKeys) return [];
1747
+ const out = [];
1748
+ const seen = /* @__PURE__ */ new Set();
1749
+ for (const rawKey of selectedTriggerKeys) {
1750
+ const key = String(rawKey != null ? rawKey : "");
1751
+ const normalized = normalizeSelectedTriggerKey(key, nodeMap);
1752
+ if (!normalized) continue;
1753
+ const dedupeKey = `${normalized.nodeKind}:${normalized.nodeId}`;
1754
+ if (seen.has(dedupeKey)) continue;
1755
+ seen.add(dedupeKey);
1756
+ out.push(normalized);
1757
+ }
1758
+ return out;
1759
+ }
1760
+ function resolveOrderKind(params) {
1761
+ var _a, _b;
1762
+ const nodeMap = (_a = params.nodeMap) != null ? _a : buildNodeMap(params.props);
1763
+ const orderKinds = (_b = params.props.orderKinds) != null ? _b : {};
1764
+ const normalizedSelected = normalizeSelectedOrderKindTriggers(
1765
+ params.selectedTriggerKeys,
1766
+ nodeMap
1767
+ );
1768
+ const selectedKindToSource = /* @__PURE__ */ new Map();
1769
+ const selectedNodeIdsForKinds = /* @__PURE__ */ new Map();
1770
+ for (const trigger of normalizedSelected) {
1771
+ const mappedKind = orderKinds[trigger.nodeId];
1772
+ if (typeof mappedKind !== "string") continue;
1773
+ if (!selectedKindToSource.has(mappedKind)) {
1774
+ selectedKindToSource.set(mappedKind, {
1775
+ nodeId: trigger.nodeId,
1776
+ nodeKind: trigger.nodeKind
1777
+ });
1778
+ }
1779
+ if (!selectedNodeIdsForKinds.has(mappedKind)) {
1780
+ selectedNodeIdsForKinds.set(mappedKind, /* @__PURE__ */ new Set());
1781
+ }
1782
+ selectedNodeIdsForKinds.get(mappedKind).add(trigger.nodeId);
1783
+ }
1784
+ const selectedKinds = Array.from(selectedKindToSource.keys());
1785
+ if (selectedKinds.length > 1) {
1786
+ const conflictingNodeIds = Array.from(selectedNodeIdsForKinds.values()).flatMap((ids) => Array.from(ids)).filter((id, idx, arr) => arr.indexOf(id) === idx);
1787
+ return {
1788
+ kind: null,
1789
+ source: null,
1790
+ error: "multiple_order_kinds_selected",
1791
+ conflictingKinds: selectedKinds,
1792
+ conflictingNodeIds
1793
+ };
1794
+ }
1795
+ if (selectedKinds.length === 1) {
1796
+ const selectedKind = selectedKinds[0];
1797
+ return {
1798
+ kind: selectedKind,
1799
+ source: selectedKindToSource.get(selectedKind)
1800
+ };
1801
+ }
1802
+ const activeTagId = params.activeTagId;
1803
+ if (activeTagId) {
1804
+ const tagKind = orderKinds[activeTagId];
1805
+ if (typeof tagKind === "string") {
1806
+ return {
1807
+ kind: tagKind,
1808
+ source: { nodeId: activeTagId, nodeKind: "tag" }
1809
+ };
1810
+ }
1811
+ }
1812
+ return { kind: null, source: null };
1813
+ }
1814
+
1815
+ // src/core/validate/steps/order-kinds.ts
1816
+ function validateOrderKinds(v) {
1817
+ var _a, _b, _c;
1818
+ const selectedTriggerKeys = Array.from((_a = v.selectedKeys) != null ? _a : []);
1819
+ if (!selectedTriggerKeys.length) return;
1820
+ const resolved = resolveOrderKind({
1821
+ props: v.props,
1822
+ selectedTriggerKeys,
1823
+ nodeMap: v.nodeMap
1824
+ });
1825
+ if (resolved.error !== "multiple_order_kinds_selected") return;
1826
+ const conflicts = (_b = resolved.conflictingKinds) != null ? _b : [];
1827
+ const affected = (_c = resolved.conflictingNodeIds) != null ? _c : [];
1828
+ v.errors.push({
1829
+ code: "multiple_order_kinds_selected",
1830
+ severity: "error",
1831
+ message: "Multiple selected triggers resolve to different order kinds. Select triggers that resolve to a single order kind.",
1832
+ details: withAffected(
1833
+ {
1834
+ conflictingKinds: conflicts,
1835
+ conflictingNodeIds: affected
1836
+ },
1837
+ affected
1838
+ )
1839
+ });
1840
+ }
1841
+
1708
1842
  // src/core/validate/steps/service-vs-input.ts
1709
1843
  function validateServiceVsUserInput(v) {
1710
1844
  for (const f of v.fields) {
@@ -3033,6 +3167,7 @@ var BuilderImpl = class {
3033
3167
  const out = {
3034
3168
  filters: this.props.filters.slice(),
3035
3169
  fields,
3170
+ ...this.props.orderKinds ? { orderKinds: this.props.orderKinds } : {},
3036
3171
  ...includes_for_buttons && { includes_for_buttons },
3037
3172
  ...excludes_for_buttons && { excludes_for_buttons },
3038
3173
  schema_version: (_e = this.props.schema_version) != null ? _e : "1.0",
@@ -3365,6 +3500,7 @@ function validate(props, ctx = {}) {
3365
3500
  validateStructure(v);
3366
3501
  validateIdentity(v);
3367
3502
  validateOptionMaps(v);
3503
+ validateOrderKinds(v);
3368
3504
  v.fieldsVisibleUnder = createFieldsVisibleUnder(v);
3369
3505
  const visSim = readVisibilitySimOpts(options);
3370
3506
  validateVisibility(v, visSim);
@@ -3819,7 +3955,7 @@ function createNodeIndex(builder) {
3819
3955
  for (const fieldId of visible) {
3820
3956
  const node = getField(fieldId);
3821
3957
  if (!node) continue;
3822
- const explicit = includes.has(fieldId) || isFieldBoundDirectToTag(fieldId, tagId);
3958
+ const explicit = includes.has(fieldId);
3823
3959
  results.push(explicit ? node : { ...node, isInherited: true });
3824
3960
  }
3825
3961
  return Object.freeze(results);
@@ -4713,6 +4849,13 @@ function buildOrderSnapshot(props, builder, selection, services, settings = {})
4713
4849
  fieldById
4714
4850
  );
4715
4851
  const { min, max } = resolveMinMax(servicesList, services);
4852
+ const maybeNodeMap = typeof builder.getNodeMap === "function" ? builder.getNodeMap() : void 0;
4853
+ const resolvedOrderKind = resolveOrderKind({
4854
+ props,
4855
+ activeTagId: tagId,
4856
+ selectedTriggerKeys: selectedButtonKeys,
4857
+ nodeMap: maybeNodeMap
4858
+ });
4716
4859
  const prunedFallbacks = pruneFallbacksConservative(
4717
4860
  props.fallbacks,
4718
4861
  { tagId, constraints: tagConstraints, serviceMap, servicesList },
@@ -4768,6 +4911,8 @@ function buildOrderSnapshot(props, builder, selection, services, settings = {})
4768
4911
  },
4769
4912
  min,
4770
4913
  max: max != null ? max : min,
4914
+ orderKind: resolvedOrderKind.kind,
4915
+ orderKindSource: resolvedOrderKind.source,
4771
4916
  quantity,
4772
4917
  quantitySource,
4773
4918
  services: servicesList,
@@ -6789,6 +6934,88 @@ function normalizeQuantityRule(input) {
6789
6934
  return out;
6790
6935
  }
6791
6936
 
6937
+ // src/react/canvas/editor/editor-order-kinds.ts
6938
+ function normalizeKind(kind) {
6939
+ const next = String(kind != null ? kind : "").trim();
6940
+ if (!next) {
6941
+ throw new Error("setOrderKind: kind must be a non-empty string");
6942
+ }
6943
+ return next;
6944
+ }
6945
+ function assertCanonicalNodeId(ctx, nodeId) {
6946
+ const id = String(nodeId != null ? nodeId : "").trim();
6947
+ if (!id) throw new Error("setOrderKind: nodeId is required");
6948
+ if (id.includes("::")) {
6949
+ throw new Error(
6950
+ "setOrderKind: composite/internal trigger keys are not allowed; use canonical tag/field/option ids"
6951
+ );
6952
+ }
6953
+ if (!ctx.isTagId(id) && !ctx.isFieldId(id) && !ctx.isOptionId(id)) {
6954
+ throw new Error(
6955
+ `setOrderKind: node id '${id}' is not a known tag, field, or option`
6956
+ );
6957
+ }
6958
+ if (ctx.isFieldId(id)) {
6959
+ const node = ctx.getNode(id);
6960
+ if (node.kind !== "field" || !isActualButtonField(node.data)) {
6961
+ throw new Error(
6962
+ `setOrderKind: field '${id}' must be a button field without options`
6963
+ );
6964
+ }
6965
+ }
6966
+ }
6967
+ function setOrderKind(ctx, nodeId, kind) {
6968
+ const id = String(nodeId != null ? nodeId : "").trim();
6969
+ const nextKind = normalizeKind(kind);
6970
+ assertCanonicalNodeId(ctx, id);
6971
+ ctx.exec({
6972
+ name: "setOrderKind",
6973
+ do: () => ctx.patchProps((p) => {
6974
+ if (!p.orderKinds) p.orderKinds = {};
6975
+ p.orderKinds[id] = nextKind;
6976
+ }),
6977
+ undo: () => ctx.undo()
6978
+ });
6979
+ }
6980
+ function deleteOrderKind(ctx, nodeId) {
6981
+ const id = String(nodeId != null ? nodeId : "").trim();
6982
+ if (!id) return;
6983
+ ctx.exec({
6984
+ name: "deleteOrderKind",
6985
+ do: () => ctx.patchProps((p) => {
6986
+ if (!p.orderKinds || !Object.prototype.hasOwnProperty.call(p.orderKinds, id)) {
6987
+ return;
6988
+ }
6989
+ delete p.orderKinds[id];
6990
+ if (!Object.keys(p.orderKinds).length) {
6991
+ delete p.orderKinds;
6992
+ }
6993
+ }),
6994
+ undo: () => ctx.undo()
6995
+ });
6996
+ }
6997
+ function pruneOrderKind(ctx, kind) {
6998
+ const target = normalizeKind(kind);
6999
+ let removedCount = 0;
7000
+ ctx.exec({
7001
+ name: "pruneOrderKind",
7002
+ do: () => ctx.patchProps((p) => {
7003
+ if (!p.orderKinds) return;
7004
+ removedCount = 0;
7005
+ for (const [nodeId, mapped] of Object.entries(p.orderKinds)) {
7006
+ if (mapped !== target) continue;
7007
+ delete p.orderKinds[nodeId];
7008
+ removedCount++;
7009
+ }
7010
+ if (!Object.keys(p.orderKinds).length) {
7011
+ delete p.orderKinds;
7012
+ }
7013
+ }),
7014
+ undo: () => ctx.undo()
7015
+ });
7016
+ return removedCount;
7017
+ }
7018
+
6792
7019
  // src/react/canvas/editor/editor-relations.ts
6793
7020
  function wouldCreateTagCycle(_ctx, p, parentId, childId) {
6794
7021
  var _a, _b;
@@ -6836,7 +7063,9 @@ function include(ctx, receiverId, idOrIds) {
6836
7063
  const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
6837
7064
  if (receiver.kind === "tag" || receiver.kind === "field" && isActualButtonField(receiver.data) || receiver.kind === "option") {
6838
7065
  if (receiver.kind === "tag") {
6839
- const t = ((_a = p.filters) != null ? _a : []).find((x) => x.id === receiverId);
7066
+ const t = ((_a = p.filters) != null ? _a : []).find(
7067
+ (x) => x.id === receiverId
7068
+ );
6840
7069
  if (t) {
6841
7070
  const accepted = [];
6842
7071
  const next = new Set((_b = t.includes) != null ? _b : []);
@@ -6878,7 +7107,12 @@ function include(ctx, receiverId, idOrIds) {
6878
7107
  const current = (_f = (_e = p.includes_for_buttons) == null ? void 0 : _e[receiverId]) != null ? _f : [];
6879
7108
  const next = new Set(current);
6880
7109
  for (const id of ids) {
6881
- if (wouldCreateIncludeExcludeCycle(ctx, p, receiverId, id)) {
7110
+ if (wouldCreateIncludeExcludeCycle(
7111
+ ctx,
7112
+ p,
7113
+ receiverId,
7114
+ id
7115
+ )) {
6882
7116
  ctx.emit("editor:error", {
6883
7117
  message: `Cycle detected: ${receiverId} including ${id} would create a cycle.`,
6884
7118
  code: "cycle_detected",
@@ -6894,7 +7128,8 @@ function include(ctx, receiverId, idOrIds) {
6894
7128
  accepted.push(id);
6895
7129
  }
6896
7130
  if (accepted.length > 0 || current.length > 0) {
6897
- if (!p.includes_for_buttons) p.includes_for_buttons = {};
7131
+ if (!p.includes_for_buttons)
7132
+ p.includes_for_buttons = {};
6898
7133
  p.includes_for_buttons[receiverId] = Array.from(next);
6899
7134
  }
6900
7135
  if ((_g = p.excludes_for_buttons) == null ? void 0 : _g[receiverId]) {
@@ -6909,7 +7144,9 @@ function include(ctx, receiverId, idOrIds) {
6909
7144
  if (!p.fields) p.fields = [];
6910
7145
  if (!p.filters) p.filters = [];
6911
7146
  } else {
6912
- throw new Error("Receiver must be a tag, button field, or option");
7147
+ throw new Error(
7148
+ "Receiver must be a tag, button field, or option"
7149
+ );
6913
7150
  }
6914
7151
  }),
6915
7152
  undo: () => ctx.undo()
@@ -6924,7 +7161,9 @@ function exclude(ctx, receiverId, idOrIds) {
6924
7161
  const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
6925
7162
  if (receiver.kind === "tag" || receiver.kind === "field" && isActualButtonField(receiver.data) || receiver.kind === "option") {
6926
7163
  if (receiver.kind === "tag") {
6927
- const t = ((_a = p.filters) != null ? _a : []).find((x) => x.id === receiverId);
7164
+ const t = ((_a = p.filters) != null ? _a : []).find(
7165
+ (x) => x.id === receiverId
7166
+ );
6928
7167
  if (t) {
6929
7168
  const accepted = [];
6930
7169
  const next = new Set((_b = t.excludes) != null ? _b : []);
@@ -6966,7 +7205,12 @@ function exclude(ctx, receiverId, idOrIds) {
6966
7205
  const current = (_f = (_e = p.excludes_for_buttons) == null ? void 0 : _e[receiverId]) != null ? _f : [];
6967
7206
  const next = new Set(current);
6968
7207
  for (const id of ids) {
6969
- if (wouldCreateIncludeExcludeCycle(ctx, p, receiverId, id)) {
7208
+ if (wouldCreateIncludeExcludeCycle(
7209
+ ctx,
7210
+ p,
7211
+ receiverId,
7212
+ id
7213
+ )) {
6970
7214
  ctx.emit("editor:error", {
6971
7215
  message: `Cycle detected: ${receiverId} excluding ${id} would create a cycle.`,
6972
7216
  code: "cycle_detected",
@@ -6982,7 +7226,8 @@ function exclude(ctx, receiverId, idOrIds) {
6982
7226
  accepted.push(id);
6983
7227
  }
6984
7228
  if (accepted.length > 0 || current.length > 0) {
6985
- if (!p.excludes_for_buttons) p.excludes_for_buttons = {};
7229
+ if (!p.excludes_for_buttons)
7230
+ p.excludes_for_buttons = {};
6986
7231
  p.excludes_for_buttons[receiverId] = Array.from(next);
6987
7232
  }
6988
7233
  if ((_g = p.includes_for_buttons) == null ? void 0 : _g[receiverId]) {
@@ -6997,7 +7242,9 @@ function exclude(ctx, receiverId, idOrIds) {
6997
7242
  if (!p.fields) p.fields = [];
6998
7243
  if (!p.filters) p.filters = [];
6999
7244
  } else {
7000
- throw new Error("Receiver must be a tag, button field, or option");
7245
+ throw new Error(
7246
+ "Receiver must be a tag, button field, or option"
7247
+ );
7001
7248
  }
7002
7249
  }),
7003
7250
  undo: () => ctx.undo()
@@ -7007,87 +7254,98 @@ function connect(ctx, kind, fromId, toId2) {
7007
7254
  ctx.exec({
7008
7255
  name: `connect:${kind}`,
7009
7256
  do: () => ctx.patchProps((p) => {
7010
- var _a, _b, _c, _d, _e;
7257
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7011
7258
  if (kind === "bind") {
7012
7259
  if (ctx.isTagId(fromId) && ctx.isTagId(toId2)) {
7013
7260
  if (wouldCreateTagCycle(ctx, p, fromId, toId2)) {
7014
- throw new Error(`bind would create a cycle: ${fromId} ? ${toId2}`);
7261
+ throw new Error(
7262
+ `bind would create a cycle: ${fromId} ? ${toId2}`
7263
+ );
7015
7264
  }
7016
- const child = ((_a = p.filters) != null ? _a : []).find((t) => t.id === toId2);
7265
+ const child = ((_a = p.filters) != null ? _a : []).find(
7266
+ (t) => t.id === toId2
7267
+ );
7017
7268
  if (child) child.bind_id = fromId;
7018
7269
  return;
7019
7270
  }
7020
7271
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2) || ctx.isFieldId(fromId) && ctx.isTagId(toId2)) {
7021
7272
  const fieldId = ctx.isFieldId(toId2) ? toId2 : fromId;
7022
7273
  const tagId = ctx.isTagId(fromId) ? fromId : toId2;
7023
- const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === fieldId);
7274
+ const f = ((_b = p.fields) != null ? _b : []).find(
7275
+ (x) => x.id === fieldId
7276
+ );
7024
7277
  if (!f) return;
7025
7278
  if (!f.bind_id) {
7026
7279
  f.bind_id = tagId;
7027
7280
  return;
7028
7281
  }
7029
7282
  if (typeof f.bind_id === "string") {
7030
- if (f.bind_id !== tagId) f.bind_id = [f.bind_id, tagId];
7283
+ if (f.bind_id !== tagId) {
7284
+ f.bind_id = [f.bind_id, tagId];
7285
+ }
7031
7286
  return;
7032
7287
  }
7033
- if (!f.bind_id.includes(tagId)) f.bind_id.push(tagId);
7288
+ if (!f.bind_id.includes(tagId)) {
7289
+ f.bind_id.push(tagId);
7290
+ }
7034
7291
  return;
7035
7292
  }
7036
- throw new Error(`bind: unsupported route ${fromId} ? ${toId2}`);
7293
+ throw new Error(
7294
+ `bind: unsupported route ${fromId} ? ${toId2}`
7295
+ );
7037
7296
  }
7038
7297
  if (kind === "include" || kind === "exclude") {
7039
- const key = kind === "include" ? "includes" : "excludes";
7298
+ const tagKey = kind === "include" ? "includes" : "excludes";
7299
+ const mapKey = kind === "include" ? "includes_for_buttons" : "excludes_for_buttons";
7040
7300
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2)) {
7041
- const t = ((_c = p.filters) != null ? _c : []).find((x) => x.id === fromId);
7301
+ const t = ((_c = p.filters) != null ? _c : []).find(
7302
+ (x) => x.id === fromId
7303
+ );
7042
7304
  if (!t) return;
7043
- const arr = (_d = t[key]) != null ? _d : t[key] = [];
7305
+ const arr = (_d = t[tagKey]) != null ? _d : t[tagKey] = [];
7044
7306
  if (!arr.includes(toId2)) arr.push(toId2);
7045
7307
  return;
7046
7308
  }
7309
+ if (ctx.isFieldId(fromId) && ctx.isFieldId(toId2)) {
7310
+ const source = ((_e = p.fields) != null ? _e : []).find(
7311
+ (x) => x.id === fromId
7312
+ );
7313
+ if (!(source == null ? void 0 : source.button)) {
7314
+ throw new Error(
7315
+ `${kind}: source field must be button=true: ${fromId} ? ${toId2}`
7316
+ );
7317
+ }
7318
+ addMappedField(p, mapKey, fromId, toId2);
7319
+ return;
7320
+ }
7047
7321
  if (ctx.isOptionId(fromId) && ctx.isFieldId(toId2)) {
7048
- const mapKey = kind === "include" ? "includes_for_options" : "excludes_for_options";
7049
- const maps = p[mapKey];
7050
- const next = { ...maps != null ? maps : {} };
7051
- const arr = (_e = next[fromId]) != null ? _e : [];
7052
- if (!arr.includes(toId2)) arr.push(toId2);
7053
- next[fromId] = arr;
7054
- p[mapKey] = next;
7322
+ addMappedField(p, mapKey, fromId, toId2);
7055
7323
  return;
7056
7324
  }
7057
- throw new Error(`${kind}: unsupported route ${fromId} ? ${toId2}`);
7325
+ throw new Error(
7326
+ `${kind}: unsupported route ${fromId} ? ${toId2}`
7327
+ );
7058
7328
  }
7059
7329
  if (kind === "service") {
7060
7330
  ensureServiceExists(ctx.opts, fromId);
7061
7331
  if (toId2.startsWith("t:")) {
7062
- ctx.exec({
7063
- name: "connect:service?tag",
7064
- do: () => ctx.patchProps((next) => {
7065
- var _a2;
7066
- const t = ((_a2 = next.filters) != null ? _a2 : []).find((x) => x.id === toId2);
7067
- if (t) t.service_id = fromId;
7068
- }),
7069
- undo: () => ctx.undo()
7070
- });
7332
+ const t = ((_f = p.filters) != null ? _f : []).find((x) => x.id === toId2);
7333
+ if (t) t.service_id = fromId;
7071
7334
  return;
7072
7335
  }
7073
7336
  if (toId2.startsWith("o:")) {
7074
- ctx.exec({
7075
- name: "connect:service?option",
7076
- do: () => ctx.patchProps((next) => {
7077
- var _a2, _b2;
7078
- for (const f of (_a2 = next.fields) != null ? _a2 : []) {
7079
- const o = (_b2 = f.options) == null ? void 0 : _b2.find((x) => x.id === toId2);
7080
- if (o) {
7081
- o.service_id = fromId;
7082
- return;
7083
- }
7084
- }
7085
- }),
7086
- undo: () => ctx.undo()
7087
- });
7337
+ for (const f of (_g = p.fields) != null ? _g : []) {
7338
+ const o = (_h = f.options) == null ? void 0 : _h.find((x) => x.id === toId2);
7339
+ if (o) {
7340
+ o.service_id = fromId;
7341
+ return;
7342
+ }
7343
+ }
7088
7344
  return;
7089
7345
  }
7090
- throw new Error('service: to must be a tag ("t:*") or option ("o:*")');
7346
+ throw new Error(
7347
+ 'service: to must be a tag ("t:*") or option ("o:*")'
7348
+ );
7091
7349
  }
7092
7350
  throw new Error(`Unknown connect kind: ${kind}`);
7093
7351
  }),
@@ -7098,90 +7356,109 @@ function disconnect(ctx, kind, fromId, toId2) {
7098
7356
  ctx.exec({
7099
7357
  name: `disconnect:${kind}`,
7100
7358
  do: () => ctx.patchProps((p) => {
7101
- var _a, _b, _c, _d, _e, _f, _g, _h;
7359
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
7102
7360
  if (kind === "bind") {
7103
7361
  if (ctx.isTagId(fromId) && ctx.isTagId(toId2)) {
7104
- const child = ((_a = p.filters) != null ? _a : []).find((t) => t.id === toId2);
7105
- if ((child == null ? void 0 : child.bind_id) === fromId) delete child.bind_id;
7362
+ const child = ((_a = p.filters) != null ? _a : []).find(
7363
+ (t) => t.id === toId2
7364
+ );
7365
+ if ((child == null ? void 0 : child.bind_id) === fromId) {
7366
+ delete child.bind_id;
7367
+ }
7106
7368
  return;
7107
7369
  }
7108
7370
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2) || ctx.isFieldId(fromId) && ctx.isTagId(toId2)) {
7109
7371
  const fieldId = ctx.isFieldId(toId2) ? toId2 : fromId;
7110
7372
  const tagId = ctx.isTagId(fromId) ? fromId : toId2;
7111
- const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === fieldId);
7373
+ const f = ((_b = p.fields) != null ? _b : []).find(
7374
+ (x) => x.id === fieldId
7375
+ );
7112
7376
  if (!(f == null ? void 0 : f.bind_id)) return;
7113
7377
  if (typeof f.bind_id === "string") {
7114
- if (f.bind_id === tagId) delete f.bind_id;
7378
+ if (f.bind_id === tagId) {
7379
+ delete f.bind_id;
7380
+ }
7115
7381
  return;
7116
7382
  }
7117
7383
  f.bind_id = f.bind_id.filter((x) => x !== tagId);
7118
- if (((_c = f.bind_id) == null ? void 0 : _c.length) === 0) delete f.bind_id;
7384
+ if (((_c = f.bind_id) == null ? void 0 : _c.length) === 0) {
7385
+ delete f.bind_id;
7386
+ }
7119
7387
  return;
7120
7388
  }
7121
- throw new Error(`unbind: unsupported route ${fromId} ? ${toId2}`);
7389
+ throw new Error(
7390
+ `unbind: unsupported route ${fromId} ? ${toId2}`
7391
+ );
7122
7392
  }
7123
7393
  if (kind === "include" || kind === "exclude") {
7124
- const key = kind === "include" ? "includes" : "excludes";
7394
+ const tagKey = kind === "include" ? "includes" : "excludes";
7395
+ const mapKey = kind === "include" ? "includes_for_buttons" : "excludes_for_buttons";
7125
7396
  if (ctx.isTagId(fromId) && ctx.isFieldId(toId2)) {
7126
- const t = ((_d = p.filters) != null ? _d : []).find((x) => x.id === fromId);
7397
+ const t = ((_d = p.filters) != null ? _d : []).find(
7398
+ (x) => x.id === fromId
7399
+ );
7127
7400
  if (!t) return;
7128
- t[key] = ((_e = t[key]) != null ? _e : []).filter((x) => x !== toId2);
7129
- if (!((_f = t[key]) == null ? void 0 : _f.length)) delete t[key];
7401
+ t[tagKey] = ((_e = t[tagKey]) != null ? _e : []).filter((x) => x !== toId2);
7402
+ if (!((_f = t[tagKey]) == null ? void 0 : _f.length)) {
7403
+ delete t[tagKey];
7404
+ }
7130
7405
  return;
7131
7406
  }
7132
- if (ctx.isOptionId(fromId) && ctx.isFieldId(toId2)) {
7133
- const mapKey = kind === "include" ? "includes_for_options" : "excludes_for_options";
7407
+ if ((ctx.isFieldId(fromId) || ctx.isOptionId(fromId)) && ctx.isFieldId(toId2)) {
7134
7408
  const maps = p[mapKey];
7135
- if (!maps) return;
7136
- if (maps[fromId]) {
7137
- maps[fromId] = ((_g = maps[fromId]) != null ? _g : []).filter(
7138
- (fid) => fid !== toId2
7139
- );
7140
- if (!((_h = maps[fromId]) == null ? void 0 : _h.length)) delete maps[fromId];
7409
+ if (!(maps == null ? void 0 : maps[fromId])) return;
7410
+ maps[fromId] = maps[fromId].filter(
7411
+ (fid) => fid !== toId2
7412
+ );
7413
+ if (!((_g = maps[fromId]) == null ? void 0 : _g.length)) {
7414
+ delete maps[fromId];
7415
+ }
7416
+ if (!Object.keys(maps).length) {
7417
+ delete p[mapKey];
7141
7418
  }
7142
- if (!Object.keys(maps).length) delete p[mapKey];
7143
7419
  return;
7144
7420
  }
7145
- throw new Error(`${kind}: unsupported route ${fromId} ? ${toId2}`);
7421
+ throw new Error(
7422
+ `${kind}: unsupported route ${fromId} ? ${toId2}`
7423
+ );
7146
7424
  }
7147
7425
  if (kind === "service") {
7148
7426
  ensureServiceExists(ctx.opts, fromId);
7149
7427
  if (toId2.startsWith("t:")) {
7150
- ctx.exec({
7151
- name: "disconnect:service?tag",
7152
- do: () => ctx.patchProps((next) => {
7153
- var _a2;
7154
- const t = ((_a2 = next.filters) != null ? _a2 : []).find((x) => x.id === toId2);
7155
- if (t) delete t.service_id;
7156
- }),
7157
- undo: () => ctx.undo()
7158
- });
7428
+ const t = ((_h = p.filters) != null ? _h : []).find((x) => x.id === toId2);
7429
+ if (t) {
7430
+ delete t.service_id;
7431
+ }
7159
7432
  return;
7160
7433
  }
7161
7434
  if (toId2.startsWith("o:")) {
7162
- ctx.exec({
7163
- name: "disconnect:service?option",
7164
- do: () => ctx.patchProps((next) => {
7165
- var _a2, _b2;
7166
- for (const f of (_a2 = next.fields) != null ? _a2 : []) {
7167
- const o = (_b2 = f.options) == null ? void 0 : _b2.find((x) => x.id === toId2);
7168
- if (o) {
7169
- delete o.service_id;
7170
- return;
7171
- }
7172
- }
7173
- }),
7174
- undo: () => ctx.undo()
7175
- });
7435
+ for (const f of (_i = p.fields) != null ? _i : []) {
7436
+ const o = (_j = f.options) == null ? void 0 : _j.find((x) => x.id === toId2);
7437
+ if (o) {
7438
+ delete o.service_id;
7439
+ return;
7440
+ }
7441
+ }
7176
7442
  return;
7177
7443
  }
7178
- throw new Error('service: to must be a tag ("t:*") or option ("o:*")');
7444
+ throw new Error(
7445
+ 'service: to must be a tag ("t:*") or option ("o:*")'
7446
+ );
7179
7447
  }
7180
7448
  throw new Error(`Unknown disconnect kind: ${kind}`);
7181
7449
  }),
7182
7450
  undo: () => ctx.undo()
7183
7451
  });
7184
7452
  }
7453
+ function addMappedField(p, mapKey, fromId, toId2) {
7454
+ var _a, _b;
7455
+ const maps = (_a = p[mapKey]) != null ? _a : {};
7456
+ const arr = (_b = maps[fromId]) != null ? _b : [];
7457
+ if (!arr.includes(toId2)) {
7458
+ maps[fromId] = [...arr, toId2];
7459
+ }
7460
+ p[mapKey] = maps;
7461
+ }
7185
7462
 
7186
7463
  // src/react/canvas/editor/editor-service-filter.ts
7187
7464
  function filterServicesForVisibleGroup2(ctx, candidates, input) {
@@ -7769,6 +8046,15 @@ var Editor = class {
7769
8046
  clearFieldValidation(id) {
7770
8047
  return clearFieldValidation(this.moduleCtx(), id);
7771
8048
  }
8049
+ setOrderKind(nodeId, kind) {
8050
+ return setOrderKind(this.moduleCtx(), nodeId, kind);
8051
+ }
8052
+ deleteOrderKind(nodeId) {
8053
+ return deleteOrderKind(this.moduleCtx(), nodeId);
8054
+ }
8055
+ pruneKind(kind) {
8056
+ return pruneOrderKind(this.moduleCtx(), kind);
8057
+ }
7772
8058
  getCatalog() {
7773
8059
  return cloneDeep4(this.catalog);
7774
8060
  }