@uipath/maestro-builder-sdk 6.51.1 → 6.51.3

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.
@@ -542,8 +542,18 @@ function connectorInputs(slots, resolved, owner) {
542
542
  for (const parameter of resolved.entry.operation?.parameters ?? [])
543
543
  parameterByWireName.set(toCamel(String(parameter.name)), String(parameter.name));
544
544
  const inputs = {};
545
+ const fileParts = new Set(resolved.multipartParts
546
+ ?.filter((part) => part.dataType.toLowerCase() === 'file').map((part) => part.name));
545
547
  for (const slot of slots) {
546
548
  const name = String(slot?.name ?? '');
549
+ // A multipart file part's input (`target: "file"`), named after the part.
550
+ // Its value is the authored input; a valueless one is only the declaration
551
+ // that serialize writes for every file part.
552
+ if (slot?.type === 'file' && slot.target === 'file' && fileParts.has(name)) {
553
+ if (slot.value !== undefined)
554
+ inputs[name] = slot.value;
555
+ continue;
556
+ }
547
557
  if (owner && !CONNECTOR_INPUT_CONTAINERS.has(name))
548
558
  throw new Error(`${owner} has unsupported input row "${name}".`);
549
559
  const body = slot?.body;
@@ -989,11 +989,15 @@ function taskData(task, resolver, taskId, stageId, ids) {
989
989
  }
990
990
  return data;
991
991
  }
992
+ // The io rows carry the task's own `elementId` ("<stageId>-<taskId>"), as
993
+ // every other kind's do. They once got the bare task id, so the converter's
994
+ // `task.elementId === output.elementId` filter matched none of them and the
995
+ // task's `response` / `Error` never reached a later task (#1419).
992
996
  case 'connector':
993
- return connectorTaskData(task.connector, resolver, taskId, `Connector task "${task.name}"`);
997
+ return connectorTaskData(task.connector, resolver, `${stageId}-${taskId}`, `Connector task "${task.name}"`);
994
998
  case 'external-agent':
995
999
  case 'external-workflow':
996
- return externalTaskData(task.kind, task.external, resolver, taskId, `${task.kind === 'external-agent' ? 'External Agent' : 'External Workflow'} task "${task.name}"`);
1000
+ return externalTaskData(task.kind, task.external, resolver, `${stageId}-${taskId}`, `${task.kind === 'external-agent' ? 'External Agent' : 'External Workflow'} task "${task.name}"`);
997
1001
  case 'wait-for-timer': {
998
1002
  if (task.timer?.duration)
999
1003
  return { timerType: 'timeDuration', timeDuration: task.timer.duration };
@@ -1410,7 +1414,7 @@ function connectorTaskData(spec, resolver, elementId, where, executionType) {
1410
1414
  const folderRef = folderBindingRef(resolver, spec.folder, connRef, { attribute: 'folder', where, target });
1411
1415
  if (folderRef)
1412
1416
  context.push(io('folderKey', 'string', { value: `=bindings.${folderRef.id}` }));
1413
- context.push(io('objectName', 'string', { value: op.objectName ?? spec.action }), io('method', 'string', { value: transportHttpMethod(rc.httpMethod) }), io('path', 'string', { value: rc.endpoint }), io('metadata', 'json', { body: connectorMetadata(rc, op, executionType) }));
1417
+ context.push(io('objectName', 'string', { value: op.objectName ?? spec.action }), io('method', 'string', { value: transportHttpMethod(rc.httpMethod) }), io('path', 'string', { value: rc.endpoint }));
1414
1418
  // inputs: the shared validator (`core/connector-inputs.ts`), the one Flow's and
1415
1419
  // BPMN's serializers and every family's `check` run. It refuses a missing
1416
1420
  // required field, an unknown or mistyped input, and swaps a `lookup()` token for
@@ -1431,15 +1435,21 @@ function connectorTaskData(spec, resolver, elementId, where, executionType) {
1431
1435
  const camelKeys = (slot) => Object.fromEntries(Object.entries(slot ?? {}).map(([name, value]) => [toCamel(name), value]));
1432
1436
  const pathParameters = camelKeys(slots.pathParameters);
1433
1437
  const queryParameters = camelKeys(slots.queryParameters);
1434
- // Case has no multipart wire: a filled file part stays in the body, where it
1435
- // has always gone.
1436
- const parts = Object.fromEntries((slots.multipartParameters ?? [])
1437
- .filter((part) => part.value !== undefined).map((part) => [part.name, part.value]));
1438
- const body = nestConnectorBody({ ...(slots.bodyParameters ?? {}), ...parts });
1438
+ const body = nestConnectorBody(slots.bodyParameters ?? {});
1439
+ // A multipart operation travels on the multipart wire, as the Case Designer
1440
+ // and `uip maestro case` save it: the parts declared in the metadata's
1441
+ // `multipartParameters`, `inputMetadata` naming the container part, and one
1442
+ // `file` input per FILE part, carrying the author's value when there is one.
1443
+ // The container part (`body`) gets no input of its own: the runtime builds it
1444
+ // from the `body` slot. This used to drop the whole wire and push a filled
1445
+ // file part into the body, where the runtime does not look for it (#1420).
1446
+ const fileParts = (slots.multipartParameters ?? []).filter((part) => part.dataType.toLowerCase() === 'file');
1447
+ context.push(io('metadata', 'json', { body: connectorMetadata(rc, op, slots, executionType) }));
1439
1448
  const inputs = [
1440
1449
  ioSlot('pathParameters', pathParameters, `${elementId}`),
1441
1450
  ioSlot('queryParameters', queryParameters, `${elementId}`),
1442
1451
  ioSlot('body', body, `${elementId}`),
1452
+ ...fileParts.map((part) => fileSlot(part, elementId)),
1443
1453
  ];
1444
1454
  const outputs = connectorOutputs(rc, elementId, resolver);
1445
1455
  return { serviceType: CASE_FORMAT_PROFILE.connectorActivityServiceType, context, inputs, outputs, bindings: [] };
@@ -1483,6 +1493,20 @@ function ioSlot(name, bodyObj, elementId) {
1483
1493
  const v = `v${name}`;
1484
1494
  return { name, type: 'json', target: name, body: bodyObj, var: v, id: v, elementId };
1485
1495
  }
1496
+ /**
1497
+ * An `inputs[]` row for a multipart FILE part. It is named after the part and
1498
+ * targets `file`, the one input whose `name` and `target` differ (the CLI's
1499
+ * `case validate` reads the file channel by that `target`). A part the author
1500
+ * left empty is still declared, valueless, as the Designer saves it.
1501
+ */
1502
+ function fileSlot(part, elementId) {
1503
+ const v = `v${part.name}`;
1504
+ return {
1505
+ name: part.name, type: 'file', target: 'file',
1506
+ ...(part.value !== undefined ? { value: part.value } : {}),
1507
+ var: v, id: v, elementId,
1508
+ };
1509
+ }
1486
1510
  /**
1487
1511
  * The binding id for a label no bindings.json declares. The row's
1488
1512
  * `resourceKey`/`default` stays the label, and the id is minted from it (`b` +
@@ -1578,9 +1602,12 @@ function folderBindingRef(resolver, name, connection, site) {
1578
1602
  return { id };
1579
1603
  }
1580
1604
  /** The connector `metadata` json blob: the FUNCTIONAL essentialConfiguration +
1581
- * activityTypeId. Designer cosmetics (packageId/activityColor/…) are omitted —
1582
- * the caseplan schema-validates without them (see design §C). */
1583
- function connectorMetadata(rc, op, executionType) {
1605
+ * activityTypeId, and the multipart wire of a multipart operation. Designer
1606
+ * cosmetics (packageId/activityColor/…) are omitted — the caseplan
1607
+ * schema-validates without them (see design §C). */
1608
+ function connectorMetadata(rc, op, slots, executionType) {
1609
+ // The part DECLARATIONS only: a file part's value rides on its `file` input.
1610
+ const multipartParameters = (slots.multipartParameters ?? []).map(({ name, dataType }) => ({ name, dataType }));
1584
1611
  const instanceParameters = {
1585
1612
  connectorKey: rc.connectorKey,
1586
1613
  objectName: op.objectName ?? rc.nodeType.split('.').pop(),
@@ -1604,6 +1631,7 @@ function connectorMetadata(rc, op, executionType) {
1604
1631
  };
1605
1632
  return {
1606
1633
  activityPropertyConfiguration: {
1634
+ ...(multipartParameters.length ? { multipartParameters } : {}),
1607
1635
  configuration: `=jsonString:${JSON.stringify(configuration)}`,
1608
1636
  uiPathActivityTypeId: rc.activityTypeId ?? '',
1609
1637
  errorState: { issues: [] },
@@ -1619,6 +1647,9 @@ function connectorMetadata(rc, op, executionType) {
1619
1647
  isEnabled: true,
1620
1648
  },
1621
1649
  },
1650
+ // `{}` unless the operation is multipart, as the Designer saves every
1651
+ // connector activity, external tasks included.
1652
+ inputMetadata: slots.inputMetadata ?? {},
1622
1653
  telemetryData: {
1623
1654
  connectorKey: rc.connectorKey,
1624
1655
  connectorName: rc.connectorName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.51.1",
3
+ "version": "6.51.3",
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",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "c337d613dbdd47c336bac7e128bca86a54032c95"
95
+ "gitref": "5e87eb230755d35a3c37ebb1921442ab5e196245"
96
96
  }