@uipath/maestro-builder-sdk 6.51.2 → 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;
@@ -1414,7 +1414,7 @@ function connectorTaskData(spec, resolver, elementId, where, executionType) {
1414
1414
  const folderRef = folderBindingRef(resolver, spec.folder, connRef, { attribute: 'folder', where, target });
1415
1415
  if (folderRef)
1416
1416
  context.push(io('folderKey', 'string', { value: `=bindings.${folderRef.id}` }));
1417
- 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 }));
1418
1418
  // inputs: the shared validator (`core/connector-inputs.ts`), the one Flow's and
1419
1419
  // BPMN's serializers and every family's `check` run. It refuses a missing
1420
1420
  // required field, an unknown or mistyped input, and swaps a `lookup()` token for
@@ -1435,15 +1435,21 @@ function connectorTaskData(spec, resolver, elementId, where, executionType) {
1435
1435
  const camelKeys = (slot) => Object.fromEntries(Object.entries(slot ?? {}).map(([name, value]) => [toCamel(name), value]));
1436
1436
  const pathParameters = camelKeys(slots.pathParameters);
1437
1437
  const queryParameters = camelKeys(slots.queryParameters);
1438
- // Case has no multipart wire: a filled file part stays in the body, where it
1439
- // has always gone.
1440
- const parts = Object.fromEntries((slots.multipartParameters ?? [])
1441
- .filter((part) => part.value !== undefined).map((part) => [part.name, part.value]));
1442
- 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) }));
1443
1448
  const inputs = [
1444
1449
  ioSlot('pathParameters', pathParameters, `${elementId}`),
1445
1450
  ioSlot('queryParameters', queryParameters, `${elementId}`),
1446
1451
  ioSlot('body', body, `${elementId}`),
1452
+ ...fileParts.map((part) => fileSlot(part, elementId)),
1447
1453
  ];
1448
1454
  const outputs = connectorOutputs(rc, elementId, resolver);
1449
1455
  return { serviceType: CASE_FORMAT_PROFILE.connectorActivityServiceType, context, inputs, outputs, bindings: [] };
@@ -1487,6 +1493,20 @@ function ioSlot(name, bodyObj, elementId) {
1487
1493
  const v = `v${name}`;
1488
1494
  return { name, type: 'json', target: name, body: bodyObj, var: v, id: v, elementId };
1489
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
+ }
1490
1510
  /**
1491
1511
  * The binding id for a label no bindings.json declares. The row's
1492
1512
  * `resourceKey`/`default` stays the label, and the id is minted from it (`b` +
@@ -1582,9 +1602,12 @@ function folderBindingRef(resolver, name, connection, site) {
1582
1602
  return { id };
1583
1603
  }
1584
1604
  /** The connector `metadata` json blob: the FUNCTIONAL essentialConfiguration +
1585
- * activityTypeId. Designer cosmetics (packageId/activityColor/…) are omitted —
1586
- * the caseplan schema-validates without them (see design §C). */
1587
- 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 }));
1588
1611
  const instanceParameters = {
1589
1612
  connectorKey: rc.connectorKey,
1590
1613
  objectName: op.objectName ?? rc.nodeType.split('.').pop(),
@@ -1608,6 +1631,7 @@ function connectorMetadata(rc, op, executionType) {
1608
1631
  };
1609
1632
  return {
1610
1633
  activityPropertyConfiguration: {
1634
+ ...(multipartParameters.length ? { multipartParameters } : {}),
1611
1635
  configuration: `=jsonString:${JSON.stringify(configuration)}`,
1612
1636
  uiPathActivityTypeId: rc.activityTypeId ?? '',
1613
1637
  errorState: { issues: [] },
@@ -1623,6 +1647,9 @@ function connectorMetadata(rc, op, executionType) {
1623
1647
  isEnabled: true,
1624
1648
  },
1625
1649
  },
1650
+ // `{}` unless the operation is multipart, as the Designer saves every
1651
+ // connector activity, external tasks included.
1652
+ inputMetadata: slots.inputMetadata ?? {},
1626
1653
  telemetryData: {
1627
1654
  connectorKey: rc.connectorKey,
1628
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.2",
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": "19785af943dff491f68e984f2440a196f95bc2c6"
95
+ "gitref": "5e87eb230755d35a3c37ebb1921442ab5e196245"
96
96
  }