@uipath/maestro-builder-sdk 6.66.3 → 6.66.4

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.
Files changed (2) hide show
  1. package/dist/decompile.js +87 -1
  2. package/package.json +2 -2
package/dist/decompile.js CHANGED
@@ -48,6 +48,7 @@ import { OUTCOME_HANDLE_NODE_TYPES } from './core/hitl-routing.js';
48
48
  import { contributionPort, forwardFanOut } from './core/definition-handles.js';
49
49
  import { STICKY_NOTE_TYPE } from './core/definitionless-node-types.js';
50
50
  import { eventFilterFromTreeLeaf } from './core/event-filters.js';
51
+ import { referencedBindingNames } from './core/contribution-bindings.js';
51
52
  /**
52
53
  * The trigger id of the flow currently being decompiled, so a reference through a
53
54
  * RENAMED trigger is still recognized as `input('x')` rather than falling back to
@@ -89,6 +90,8 @@ let runRawManifests = [];
89
90
  * definition and the node keeps its version even when the author edits it.
90
91
  */
91
92
  let runCarried = new Map();
93
+ /** The file's top-level `bindings[]` rows, by id, for {@link resolveTemplateBindings}. */
94
+ let runBindings = new Map();
92
95
  let runStrict = false;
93
96
  /** `DecompileOptions.warn` for the current run, and the messages already sent to it (one line per finding). */
94
97
  let runWarn;
@@ -1040,6 +1043,81 @@ function emitEventSubscription(node, imp, inputNames) {
1040
1043
  ['folder', folder !== undefined ? tsLiteral(folder) : undefined],
1041
1044
  ]) + unboundMarker(node, { connection: conn, folder }, connector, event);
1042
1045
  }
1046
+ /**
1047
+ * The definition a `rawNode` carries for `node`. A per-tenant template
1048
+ * (`<bindings.NAME>` placeholders, empty `resourceKey`) comes back as a copy
1049
+ * resolved with the node's own key and defaults (#1512); any other `def` comes
1050
+ * back unchanged.
1051
+ *
1052
+ * For instance, a template context row `queueName: "<bindings.name>"`, on a node
1053
+ * whose `queueName` row is `=bindings.bQueueName`, takes `bQueueName`'s
1054
+ * `resourceKey` and `default`. The placeholders stay, for compile to close.
1055
+ *
1056
+ * `reason` says why a template was left unresolved, when the node is bound but
1057
+ * not fully: compile's refusal names only the empty key, not what the node lacks.
1058
+ */
1059
+ function resolveTemplateBindings(def, node) {
1060
+ const model = def?.model;
1061
+ const names = referencedBindingNames(model);
1062
+ const resource = model?.bindings?.resource;
1063
+ if (names.length === 0 || typeof resource !== 'string' || !resource || resource === 'connection')
1064
+ return { def };
1065
+ if (typeof model.bindings.resourceKey === 'string' && model.bindings.resourceKey)
1066
+ return { def };
1067
+ const nodeModel = node.model;
1068
+ const nodeContext = Array.isArray(nodeModel?.context) ? nodeModel.context : [];
1069
+ const nodeValues = Array.isArray(nodeModel?.bindings?.values) ? nodeModel.bindings.values : [];
1070
+ const keys = new Map();
1071
+ const defaults = new Map();
1072
+ const missing = [];
1073
+ for (const name of names) {
1074
+ // Matched by the context row's own `name` (`queueName`): the canvas rewrites its value.
1075
+ const fields = model.context.filter((c) => c?.value === `<bindings.${name}>`).map((c) => c?.name);
1076
+ const ref = nodeContext.find((c) => fields.includes(c?.name) && typeof c?.value === 'string');
1077
+ const id = typeof ref?.value === 'string' ? /^=bindings\.(.+)$/.exec(ref.value)?.[1] : undefined;
1078
+ const row = id !== undefined ? runBindings.get(id) : undefined;
1079
+ let key = row?.resource === resource ? row.resourceKey : undefined;
1080
+ let value = row?.resource === resource ? row.default : undefined;
1081
+ if (typeof key !== 'string' || !key)
1082
+ key = nodeModel?.bindings?.resource === resource ? nodeModel.bindings.resourceKey : undefined;
1083
+ if (typeof value !== 'string')
1084
+ value = nodeValues.find((v) => v?.name === name)?.default;
1085
+ if (typeof key === 'string' && key)
1086
+ keys.set(name, key);
1087
+ else
1088
+ missing.push(`no resourceKey for "${name}"`);
1089
+ if (typeof value === 'string')
1090
+ defaults.set(name, value);
1091
+ else
1092
+ missing.push(`no default for "${name}"`);
1093
+ }
1094
+ const label = `node "${node.id}" (${def?.nodeType}@${def?.version})`;
1095
+ // Nothing bound at all: compile's own refusal already says what to do.
1096
+ if (keys.size === 0 && defaults.size === 0)
1097
+ return { def };
1098
+ if (missing.length > 0) {
1099
+ return { def, reason: `${label} is bound to a ${resource}, but its binding has ${missing.join(', ')}, so its definition stays the template.` };
1100
+ }
1101
+ const distinct = [...new Set(keys.values())];
1102
+ if (distinct.length !== 1) {
1103
+ const each = [...keys].map(([n, k]) => `"${n}" → ${k}`).join(', ');
1104
+ return { def, reason: `${label} names more than one ${resource} (${each}), so its definition stays the template.` };
1105
+ }
1106
+ const values = Array.isArray(model.bindings.values) ? model.bindings.values : [];
1107
+ return {
1108
+ def: {
1109
+ ...def,
1110
+ model: {
1111
+ ...model,
1112
+ bindings: {
1113
+ ...model.bindings,
1114
+ resourceKey: distinct[0],
1115
+ values: values.map((v) => (defaults.has(v?.name) ? { ...v, default: defaults.get(v.name) } : v)),
1116
+ },
1117
+ },
1118
+ },
1119
+ };
1120
+ }
1043
1121
  /** Best-effort placeholder for a node type the reverse-map does not yet cover. */
1044
1122
  function unsupportedSpec(node, imp, o) {
1045
1123
  // The file's own definition for this node — the manifest the platform served.
@@ -1053,7 +1131,10 @@ function unsupportedSpec(node, imp, o) {
1053
1131
  // `mock()` for a flow that genuinely contains one.
1054
1132
  const constName = `${camel(node.id)}Definition`;
1055
1133
  if (!runRawManifests.some(([n]) => n === constName)) {
1056
- runRawManifests.push([constName, JSON.stringify(def, null, 2)]);
1134
+ const resolved = resolveTemplateBindings(def, node);
1135
+ if (resolved.reason !== undefined)
1136
+ warnOnce(resolved.reason);
1137
+ runRawManifests.push([constName, JSON.stringify(resolved.def, null, 2)]);
1057
1138
  }
1058
1139
  const inputs = node.inputs ?? {};
1059
1140
  const inputsSrc = Object.keys(inputs).length > 0 ? JSON.stringify(inputs, null, 2) : undefined;
@@ -2937,6 +3018,11 @@ export function decompile(flow, options = {}) {
2937
3018
  runDefs.set(d.nodeType, d);
2938
3019
  }
2939
3020
  runCarried = carriedPairs(flow);
3021
+ // Best effort: a malformed `bindings` section (not an array) indexes nothing.
3022
+ const rows = flow.bindings;
3023
+ runBindings = new Map((Array.isArray(rows) ? rows : [])
3024
+ .filter((b) => typeof b?.id === 'string')
3025
+ .map((b) => [b.id, b]));
2940
3026
  const imp = new Imports();
2941
3027
  const graph = new Graph(flow.nodes ?? [], flow.edges ?? [], flow.variables);
2942
3028
  const globals = readFlowGlobals(flow.variables, runStrict);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.66.3",
3
+ "version": "6.66.4",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -100,5 +100,5 @@
100
100
  "@types/node": "^22.7.0",
101
101
  "esbuild": "^0.28.1"
102
102
  },
103
- "gitref": "e7e32040e5596319cf1bccea2a6caa9124d79bbb"
103
+ "gitref": "af11f232febf9ed683dec9f44b4ae7fe3c2426fe"
104
104
  }