@uipath/maestro-builder-sdk 6.32.6 → 6.32.8

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.
@@ -269,8 +269,8 @@ function syncEntryPoints(caseplan, outPath) {
269
269
  * succeeds with zero warnings when the sidecar is stale or empty.
270
270
  *
271
271
  * Non-connector resources come from root binding pairs and referenced tasks.
272
- * Connector connection and folder bindings have different resource keys, so
273
- * their relationship comes from the context[] that references both binding ids.
272
+ * A connector's connection and folder relationship comes from the context[]
273
+ * that references both binding ids.
274
274
  * No-op when compiling outside a scaffolded project.
275
275
  */
276
276
  function syncBindingsV2(caseplan, outPath) {
@@ -3,6 +3,7 @@ import { tsLiteral, tsNumber } from '../core/ts-literal.js';
3
3
  import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
4
4
  import { preserveSchemaVersion } from '../schema-version.js';
5
5
  import { ownEntry } from '../core/own-entry.js';
6
+ import { isUnrestorableSlotId } from './preserve.js';
6
7
  const TASK_KIND_METHOD = {
7
8
  process: 'process',
8
9
  agent: 'agent',
@@ -932,6 +933,8 @@ function slaIdentity(sla) {
932
933
  * has that id.
933
934
  * - empty collections — there is nothing to align.
934
935
  * - `nodeOrder` with fewer than two ids — ordering one node is identity.
936
+ * - an `inputs` / `outputs` slot id copied verbatim from its name; the
937
+ * serializer will not restore it, and the minted id replaces it.
935
938
  *
936
939
  * Everything else stays. A designer document orders stages before its trigger,
937
940
  * carries ids no label seeding reproduces, and needs every one of them.
@@ -943,6 +946,11 @@ function prunePreservation(preservation, plan) {
943
946
  delete identities.id;
944
947
  if (identities.triggers?.length === 1 && identities.triggers[0]?.id === 'trigger_1')
945
948
  delete identities.triggers;
949
+ for (const lane of ['inputs', 'outputs']) {
950
+ const rows = identities.variables?.[lane];
951
+ if (Array.isArray(rows))
952
+ identities.variables[lane] = rows.filter((row) => !isUnrestorableSlotId(lane, row));
953
+ }
946
954
  for (const key of ['triggers', 'stages', 'caseExitRules', 'slaRules'])
947
955
  if (Array.isArray(identities[key]) && identities[key].length === 0)
948
956
  delete identities[key];
@@ -1,5 +1,13 @@
1
1
  import type { BuiltCase } from './case-sdk.js';
2
2
  export type PreservedVariableLane = 'inputs' | 'outputs' | 'inputOutputs';
3
+ /**
4
+ * A preserved `inputs[]` / `outputs[]` slot id copied verbatim from its name is
5
+ * the STRICT_FORMAL_ARG_ID defect, not an identity to keep; the minted id stands.
6
+ */
7
+ export declare function isUnrestorableSlotId(lane: string, row: {
8
+ name: string;
9
+ id?: string;
10
+ }): boolean;
3
11
  /** One platform-owned node retained at its original position in `nodes[]`. */
4
12
  export interface PreservedCaseNode {
5
13
  /** Original zero-based position in the top-level `nodes[]` array. */
@@ -1,3 +1,10 @@
1
+ /**
2
+ * A preserved `inputs[]` / `outputs[]` slot id copied verbatim from its name is
3
+ * the STRICT_FORMAL_ARG_ID defect, not an identity to keep; the minted id stands.
4
+ */
5
+ export function isUnrestorableSlotId(lane, row) {
6
+ return lane !== 'inputOutputs' && typeof row.id === 'string' && row.id === row.name;
7
+ }
1
8
  const preserved = new WeakMap();
2
9
  /** Attach decompiler-owned, non-authoring wire data to a built case. */
3
10
  export function preserveCaseJson(built, payload) {
@@ -9,6 +9,7 @@
9
9
  * name) are resolved here to the generated ids.
10
10
  */
11
11
  import { IdGen } from './ids.js';
12
+ import { isUnrestorableSlotId } from './preserve.js';
12
13
  import { buildConnectorInputs, nestConnectorBody, transportHttpMethod } from '../core/connector-inputs.js';
13
14
  import { EQUALS_EXPR_DIALECT } from '../core/connector-checks.js';
14
15
  import { bindingLabelRefusal } from '../core/binding-messages.js';
@@ -184,7 +185,7 @@ export function serialize(built, opts = {}) {
184
185
  context.push(io('connection', 'string', { value: `=bindings.${connection.id}` }));
185
186
  context.push(io('resourceKey', 'string', { value: connection.resourceKey }));
186
187
  }
187
- const folder = bindingRef(resolver, connector.folder, 'Connection', 'folderKey', 'FolderKey', { ...site, attribute: 'folder' });
188
+ const folder = folderBindingRef(resolver, connector.folder, connection, { ...site, attribute: 'folder' });
188
189
  if (folder)
189
190
  context.push(io('folderKey', 'string', { value: `=bindings.${folder.id}` }));
190
191
  }
@@ -502,7 +503,11 @@ function applyPreservedIdentities(result, preservation) {
502
503
  takeSlas(metadata.slaRules, identities.slaRules);
503
504
  const variables = result.variables;
504
505
  for (const [lane, rows] of Object.entries(identities.variables ?? {}))
505
- (rows ?? []).forEach((row) => take(variables[lane]?.find((candidate) => candidate.name === row.name), row.id));
506
+ (rows ?? []).forEach((row) => {
507
+ if (isUnrestorableSlotId(lane, row))
508
+ return;
509
+ take(variables[lane]?.find((candidate) => candidate.name === row.name), row.id);
510
+ });
506
511
  const replace = (value) => {
507
512
  if (replacements.has(value))
508
513
  return replacements.get(value);
@@ -904,7 +909,7 @@ function resolvedSubscriptionBag(kind, spec, resolver, elementId, where) {
904
909
  context.push(io('connection', 'string', { value: `=bindings.${connection.id}` }));
905
910
  context.push(io('resourceKey', 'string', { value: connection.resourceKey }));
906
911
  }
907
- const folder = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
912
+ const folder = folderBindingRef(resolver, spec.folder, connection, { attribute: 'folder', where, target });
908
913
  if (folder)
909
914
  context.push(io('folderKey', 'string', { value: `=bindings.${folder.id}` }));
910
915
  context.push(io('method', 'string', {}), io('path', 'string', {}), io('objectName', 'string', { value: op.objectName ?? spec.event }), io('operation', 'string', { value: op.eventOperation ?? spec.event }), io('metadata', 'json', { body: subscriptionMetadata(rc, op, spec.filters ?? [], elementId) }));
@@ -1100,7 +1105,7 @@ function connectorTaskData(spec, resolver, elementId, where) {
1100
1105
  context.push(io('connection', 'string', { value: `=bindings.${connRef.id}` }));
1101
1106
  context.push(io('resourceKey', 'string', { value: connRef.resourceKey }));
1102
1107
  }
1103
- const folderRef = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
1108
+ const folderRef = folderBindingRef(resolver, spec.folder, connRef, { attribute: 'folder', where, target });
1104
1109
  if (folderRef)
1105
1110
  context.push(io('folderKey', 'string', { value: `=bindings.${folderRef.id}` }));
1106
1111
  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) }));
@@ -1148,7 +1153,7 @@ function externalTaskData(kind, spec, resolver, where) {
1148
1153
  throw new Error(`${kind} task mode must be "sync" or "async".`);
1149
1154
  const target = { key: spec.connector.key, action: spec.connector.action };
1150
1155
  const connection = bindingRef(resolver, spec.connector.connection, 'Connection', 'ConnectionId', `${rc.connectorKey} connection`, { attribute: 'connection', where, target });
1151
- const folder = bindingRef(resolver, spec.connector.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
1156
+ const folder = folderBindingRef(resolver, spec.connector.folder, connection, { attribute: 'folder', where, target });
1152
1157
  if (!connection || !folder)
1153
1158
  throw new Error(`${kind} task requires non-empty connection and folder binding names.`);
1154
1159
  const serviceType = kind === 'external-agent'
@@ -1236,6 +1241,50 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
1236
1241
  }
1237
1242
  return { id, resourceKey };
1238
1243
  }
1244
+ /**
1245
+ * A connector's folder is a property of its connection:
1246
+ * { resourceKey: <connection key>, default: <folder key>, propertyAttribute: 'folderKey' }.
1247
+ * One folder label on two connections gets one row each: `shared`, `shared_2`.
1248
+ * One connection with two different folders is refused: a connection lives in
1249
+ * one folder, and the syncs group rows by `resourceKey`, so one value would win.
1250
+ * Without a connection the folder binds as a plain binding.
1251
+ */
1252
+ function folderBindingRef(resolver, name, connection, site) {
1253
+ if (!connection)
1254
+ return bindingRef(resolver, name, 'Connection', 'folderKey', 'FolderKey', site);
1255
+ if (!name)
1256
+ return undefined;
1257
+ const refused = bindingLabelRefusal(resolver.bindings, name, site.attribute, site.where, site.target);
1258
+ if (refused)
1259
+ throw refused;
1260
+ const entry = resolver.bindings?.entry(name);
1261
+ const baseId = entry?.id ?? name;
1262
+ const folderKey = entry?.default ?? entry?.resourceKey ?? name;
1263
+ const matches = (row) => row?.resourceKey === connection.resourceKey && row?.default === folderKey
1264
+ && row?.propertyAttribute === 'folderKey';
1265
+ for (const row of resolver.bindingSink.values()) {
1266
+ if (row.resourceKey === connection.resourceKey && row.propertyAttribute === 'folderKey'
1267
+ && row.default !== folderKey)
1268
+ throw new Error(`${site.where}: connection "${connection.resourceKey}" is bound to two folders: `
1269
+ + `"${String(row.name)}" (${String(row.default)}) and "${name}" (${folderKey}). `
1270
+ + `A connection lives in one folder; use the same folder binding for every task on it.`);
1271
+ }
1272
+ let id = baseId;
1273
+ for (let n = 2; resolver.bindingSink.has(id) && !matches(resolver.bindingSink.get(id)); n++)
1274
+ id = `${baseId}_${n}`;
1275
+ if (!resolver.bindingSink.has(id)) {
1276
+ resolver.bindingSink.set(id, {
1277
+ id,
1278
+ name: entry?.name ?? 'FolderKey',
1279
+ type: 'string',
1280
+ resource: 'Connection',
1281
+ resourceKey: connection.resourceKey,
1282
+ default: folderKey,
1283
+ propertyAttribute: 'folderKey',
1284
+ });
1285
+ }
1286
+ return { id };
1287
+ }
1239
1288
  /** The connector `metadata` json blob: the FUNCTIONAL essentialConfiguration +
1240
1289
  * activityTypeId. Designer cosmetics (packageId/activityColor/…) are omitted —
1241
1290
  * the caseplan schema-validates without them (see design §C). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.32.6",
3
+ "version": "6.32.8",
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",
@@ -93,5 +93,5 @@
93
93
  "@types/node": "^22.7.0",
94
94
  "esbuild": "^0.28.1"
95
95
  },
96
- "gitref": "0b27856ab8b25ffc834013f559a14946f61cb89a"
96
+ "gitref": "fad79d44a992f72b8a8d0ba0f9c61d8ea5705ed7"
97
97
  }