@uipath/maestro-builder-sdk 6.46.1 → 6.46.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.
- package/dist/api-index.md +25 -25
- package/dist/api-members.md +137 -137
- package/dist/case/case-sdk.d.ts +13 -7
- package/dist/case/case-sdk.js +6 -6
- package/dist/case/check.js +11 -0
- package/dist/case/compile-cli.d.ts +10 -0
- package/dist/case/compile-cli.js +158 -66
- package/dist/case/decompile.js +58 -10
- package/dist/case/resource-identity.d.ts +44 -0
- package/dist/case/resource-identity.js +45 -0
- package/dist/case/serialize.js +234 -23
- package/package.json +2 -2
package/dist/case/serialize.js
CHANGED
|
@@ -18,6 +18,8 @@ import { resolveEventWhere } from '../core/lookups.js';
|
|
|
18
18
|
import { resolveCaseSubscription } from './subscription.js';
|
|
19
19
|
import { externalDescriptorRefusal } from './external.js';
|
|
20
20
|
import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
21
|
+
import { resourceIdentity } from './resource-identity.js';
|
|
22
|
+
import { ownEntry } from '../core/own-entry.js';
|
|
21
23
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
22
24
|
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
23
25
|
import { readEventFilter, eventFilterProblem, eventFilterTreeLeaf } from '../core/event-filters.js';
|
|
@@ -80,7 +82,8 @@ export function serialize(built, opts = {}) {
|
|
|
80
82
|
bindings: opts.bindings,
|
|
81
83
|
bindingSink: new Map(),
|
|
82
84
|
varCompanions: new Map(),
|
|
83
|
-
|
|
85
|
+
outputIds: new Set(),
|
|
86
|
+
ownOutputVars: ownOutputVars(built),
|
|
84
87
|
slaId: new Map(),
|
|
85
88
|
slaIdByName: new Map(),
|
|
86
89
|
escalationId: new Map(),
|
|
@@ -248,7 +251,49 @@ export function serialize(built, opts = {}) {
|
|
|
248
251
|
}
|
|
249
252
|
: {}),
|
|
250
253
|
};
|
|
251
|
-
return applyAuthorLayout(applyPreservation(result, caseJsonPreservation(built)), built.layout);
|
|
254
|
+
return stampConnectorConfigVersion(applyAuthorLayout(applyPreservation(result, caseJsonPreservation(built)), built.layout));
|
|
255
|
+
}
|
|
256
|
+
/** The task types whose `data.context[]` carries an Integration Service activity configuration. */
|
|
257
|
+
const CONNECTOR_CONFIG_TASK_TYPES = new Set([
|
|
258
|
+
'execute-connector-activity',
|
|
259
|
+
'wait-for-connector',
|
|
260
|
+
'external-agent',
|
|
261
|
+
'external-workflow',
|
|
262
|
+
]);
|
|
263
|
+
const V2_CONFIG_ROW = { name: 'activityConfigurationVersion', value: 'v2', type: 'string' };
|
|
264
|
+
/**
|
|
265
|
+
* Flagged-V2 plans: mark each connector task's and event trigger's context
|
|
266
|
+
* `activityConfigurationVersion: v2`, as the Designer and CLI do. Runs
|
|
267
|
+
* post-preservation because the flag is preserved metadata.
|
|
268
|
+
*
|
|
269
|
+
* Only a context bound to a connection is marked. A placeholder bag
|
|
270
|
+
* (`connectorKey` + `operation`, or a trigger's lone `objectName`) has no
|
|
271
|
+
* configuration panel to pick. A context that already carries the row keeps it.
|
|
272
|
+
*/
|
|
273
|
+
function stampConnectorConfigVersion(result) {
|
|
274
|
+
const metadata = result.metadata;
|
|
275
|
+
if (metadata?.intsvcActivityConfig !== 'v2')
|
|
276
|
+
return result;
|
|
277
|
+
const stamp = (context) => {
|
|
278
|
+
if (!Array.isArray(context))
|
|
279
|
+
return;
|
|
280
|
+
if (!context.some((row) => row?.name === 'connection'))
|
|
281
|
+
return;
|
|
282
|
+
if (context.some((row) => row?.name === V2_CONFIG_ROW.name))
|
|
283
|
+
return;
|
|
284
|
+
context.push({ ...V2_CONFIG_ROW });
|
|
285
|
+
};
|
|
286
|
+
for (const node of result.nodes ?? []) {
|
|
287
|
+
if (node?.type === 'case-management:Trigger' || node?.type === 'uipath.case.trigger')
|
|
288
|
+
stamp(node.data?.[CASE_FORMAT_PROFILE.triggerBagField]?.context);
|
|
289
|
+
for (const lane of node?.data?.tasks ?? []) {
|
|
290
|
+
for (const task of Array.isArray(lane) ? lane : []) {
|
|
291
|
+
if (CONNECTOR_CONFIG_TASK_TYPES.has(task?.type))
|
|
292
|
+
stamp(task.data?.context);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return result;
|
|
252
297
|
}
|
|
253
298
|
const CASE_NODE_LAYOUT_FIELDS = ['position', 'style', 'measured', 'width', 'height', 'zIndex'];
|
|
254
299
|
/**
|
|
@@ -480,6 +525,18 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
480
525
|
const triggerNodes = nodes.filter((node) => node.type === 'case-management:Trigger' || node.type === 'uipath.case.trigger');
|
|
481
526
|
(identities.triggers ?? []).forEach((trigger, index) => take(triggerNodes[index], trigger.id));
|
|
482
527
|
const stages = nodes.filter((node) => String(node.type).endsWith('Stage'));
|
|
528
|
+
// Every task-output row id in the plan, kept current as preserved ids are
|
|
529
|
+
// taken. Output ids are unique plan-wide (`claimOutputId`); a preserved id that
|
|
530
|
+
// another row already holds would undo that. Example: an older SDK wrote two
|
|
531
|
+
// action rows both `{ id: 'action', var: 'action' }`; this pass gives the
|
|
532
|
+
// second `action2`, and taking its preserved `action` would make it a duplicate.
|
|
533
|
+
const heldOutputIds = new Set();
|
|
534
|
+
for (const stage of stages)
|
|
535
|
+
for (const lane of stage.data?.tasks ?? [])
|
|
536
|
+
for (const task of lane)
|
|
537
|
+
for (const row of task?.data?.outputs ?? [])
|
|
538
|
+
if (typeof row?.id === 'string')
|
|
539
|
+
heldOutputIds.add(row.id);
|
|
483
540
|
for (const stageIdentity of identities.stages ?? []) {
|
|
484
541
|
const stage = stages.find((candidate) => candidate.data?.label === stageIdentity.label);
|
|
485
542
|
take(stage, stageIdentity.id);
|
|
@@ -504,7 +561,19 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
504
561
|
// A positional match never takes a row a name match owns.
|
|
505
562
|
: named.has(outputRows[index]?.name) ? undefined : outputRows[index];
|
|
506
563
|
const currentId = target?.id;
|
|
564
|
+
// An own-name row's id IS its variable's name (`emitTaskOutput`). A
|
|
565
|
+
// preserved id that differs — an `o<hash>` slot from a plan an older
|
|
566
|
+
// SDK wrote — would rename the variable out from under every
|
|
567
|
+
// `=vars.<name>` reader, so the typed rule wins and the row migrates.
|
|
568
|
+
if (target && OWN_NAME_OUTPUT_ROWS.has(target) && row.id !== target.id)
|
|
569
|
+
return;
|
|
570
|
+
if (target && typeof row.id === 'string' && row.id !== currentId && heldOutputIds.has(row.id))
|
|
571
|
+
return;
|
|
507
572
|
take(target, row.id);
|
|
573
|
+
if (target && typeof row.id === 'string' && typeof currentId === 'string') {
|
|
574
|
+
heldOutputIds.delete(currentId);
|
|
575
|
+
heldOutputIds.add(row.id);
|
|
576
|
+
}
|
|
508
577
|
if (typeof currentId === 'string' && typeof row.id === 'string' && target?.value === currentId) {
|
|
509
578
|
target.value = row.id;
|
|
510
579
|
}
|
|
@@ -841,7 +910,12 @@ function taskData(task, resolver, taskId, stageId, ids) {
|
|
|
841
910
|
// companion so `=vars.<var>` resolves downstream.
|
|
842
911
|
if (!task.ref)
|
|
843
912
|
return {};
|
|
844
|
-
|
|
913
|
+
// The resource is named through a name/folderPath pair of root bindings,
|
|
914
|
+
// never literals: `validate` refuses a literal (CASE_MGMT_RESOURCE_TASK_
|
|
915
|
+
// LITERAL_BINDING), and deploy re-targets a resource only through its
|
|
916
|
+
// binding (#1240).
|
|
917
|
+
const { nameRef, folderRef } = referenceBindings(task.kind, task.ref, resolver, ids);
|
|
918
|
+
const data = { name: nameRef, folderPath: folderRef };
|
|
845
919
|
const elementId = `${stageId}-${taskId}`;
|
|
846
920
|
if (task.inputs?.length)
|
|
847
921
|
data.inputs = task.inputs.map((inp, i) => emitTaskInput(inp, elementId, ids, `${elementId}:in:${i}:${inp.name}`));
|
|
@@ -1061,10 +1135,15 @@ function emitActionField(f, outputElementId, resolver) {
|
|
|
1061
1135
|
if (f.value !== undefined)
|
|
1062
1136
|
row.value = f.value;
|
|
1063
1137
|
if (outputElementId !== undefined && f.value !== undefined) {
|
|
1064
|
-
|
|
1138
|
+
// `id == var` like the Designer; a second form output into the same case
|
|
1139
|
+
// variable takes a suffixed id and becomes a reassigned row (`originalVar`).
|
|
1140
|
+
const id = resolver ? claimOutputId(resolver, f.value) : f.value;
|
|
1141
|
+
row.id = id;
|
|
1065
1142
|
row.var = f.value;
|
|
1143
|
+
if (id !== f.value)
|
|
1144
|
+
row.originalVar = id;
|
|
1066
1145
|
row.source = `=${f.name}`;
|
|
1067
|
-
row.target = `=${
|
|
1146
|
+
row.target = `=${id}`;
|
|
1068
1147
|
row.elementId = outputElementId;
|
|
1069
1148
|
if (resolver && !resolver.varCompanions.has(f.value)) {
|
|
1070
1149
|
resolver.varCompanions.set(f.value, {
|
|
@@ -1087,13 +1166,43 @@ function emitTaskInput(inp, elementId, ids, seed) {
|
|
|
1087
1166
|
const slot = ids.make('v', 8, seed);
|
|
1088
1167
|
return { name: inp.name, type: inp.type, id: slot, var: slot, elementId, value: inp.value };
|
|
1089
1168
|
}
|
|
1090
|
-
/**
|
|
1169
|
+
/** Rows `emitTaskOutput` wrote in the own-name shape (`id == var`); see applyPreservedIdentities. */
|
|
1170
|
+
const OWN_NAME_OUTPUT_ROWS = new WeakSet();
|
|
1171
|
+
/**
|
|
1172
|
+
* One `data.outputs[]` row: `source` field → the `var` case variable. Two shapes,
|
|
1173
|
+
* as the Case Designer writes them:
|
|
1174
|
+
*
|
|
1175
|
+
* - **own name** — the output keeps its field's name (a top-level `source` whose
|
|
1176
|
+
* field is the `var`, or the Designer's camelCase of it, either one optionally
|
|
1177
|
+
* with a numeric suffix: `=APIOutput1` into `APIOutput1`, `aPIOutput1` or
|
|
1178
|
+
* `aPIOutput12`; see `keepsOwnName`). The row's `id` IS the `var`, with no
|
|
1179
|
+
* `originalVar`: `{ id: 'APIOutput1', var: 'APIOutput1', target: '=APIOutput1' }`.
|
|
1180
|
+
* - **reassigned** — the output feeds a differently named variable (`=age` into
|
|
1181
|
+
* `estimatedAge`, or any nested `=Error.Message`). The row keeps its own minted
|
|
1182
|
+
* slot `id`, points `var` at the case variable, and repeats the slot in
|
|
1183
|
+
* `originalVar`, which is how the Designer recognises a reassignment.
|
|
1184
|
+
*
|
|
1185
|
+
* Output ids are unique across the plan (`claimOutputId`). When an own-name id
|
|
1186
|
+
* is already taken — a second task writing the same variable — the row takes
|
|
1187
|
+
* the suffixed id (`APIOutput12`) and falls back to the reassigned shape, so its
|
|
1188
|
+
* `var` still names the shared case variable.
|
|
1189
|
+
*/
|
|
1091
1190
|
function emitTaskOutput(o, elementId, ids, seed, resolver) {
|
|
1092
|
-
const
|
|
1093
|
-
const field =
|
|
1191
|
+
const path = o.source.replace(/^=/, '');
|
|
1192
|
+
const field = path.split('.').pop() || o.source;
|
|
1094
1193
|
// Register the readable companion once (declared vars take precedence in the merge).
|
|
1095
1194
|
if (!resolver.varCompanions.has(o.var))
|
|
1096
1195
|
resolver.varCompanions.set(o.var, { id: o.var, name: o.var, type: o.type, elementId: 'root', custom: true });
|
|
1196
|
+
if (isOwnNameOutput(o)) {
|
|
1197
|
+
const id = claimOutputId(resolver, o.var);
|
|
1198
|
+
if (id === o.var) {
|
|
1199
|
+
const row = { name: field, type: o.type, id, var: o.var, value: o.var, source: o.source, target: `=${id}`, elementId };
|
|
1200
|
+
OWN_NAME_OUTPUT_ROWS.add(row);
|
|
1201
|
+
return row;
|
|
1202
|
+
}
|
|
1203
|
+
return { name: field, type: o.type, id, var: o.var, originalVar: id, value: o.var, source: o.source, target: `=${id}`, elementId };
|
|
1204
|
+
}
|
|
1205
|
+
const slot = claimOutputId(resolver, ids.make('o', 8, seed));
|
|
1097
1206
|
return {
|
|
1098
1207
|
name: field,
|
|
1099
1208
|
type: o.type,
|
|
@@ -1117,32 +1226,70 @@ const BUSINESS_RULE_TASK_VERSION = 'v3';
|
|
|
1117
1226
|
* pattern) is a different namespace, and a binding that uses it is not a
|
|
1118
1227
|
* BusinessRule resource to the bindings_v2 reader. */
|
|
1119
1228
|
const BUSINESS_RULE_RESOURCE = 'BusinessRule';
|
|
1120
|
-
/**
|
|
1121
|
-
|
|
1229
|
+
/**
|
|
1230
|
+
* The root binding `resource` and `resourceSubType` each published-resource
|
|
1231
|
+
* task kind is bound by — the Studio Web / v1-skill table (`bindings/impl-json.md`
|
|
1232
|
+
* § Per Task Type). Every kind but the business rule binds as a `process`; the
|
|
1233
|
+
* subtype tells the platform which kind of process. An RPA process and a Flow
|
|
1234
|
+
* carry no subtype on the binding.
|
|
1235
|
+
*/
|
|
1236
|
+
const REFERENCE_BINDING = {
|
|
1237
|
+
process: { resource: 'process', subType: 'ProcessOrchestration' },
|
|
1238
|
+
agent: { resource: 'process', subType: 'Agent' },
|
|
1239
|
+
rpa: { resource: 'process' },
|
|
1240
|
+
'api-workflow': { resource: 'process', subType: 'Api' },
|
|
1241
|
+
'case-management': { resource: 'process', subType: 'CaseManagement' },
|
|
1242
|
+
'flow-process': { resource: 'process' },
|
|
1243
|
+
};
|
|
1244
|
+
/**
|
|
1245
|
+
* Mint (once per resource + resourceKey + attribute) one root binding row of a
|
|
1246
|
+
* resource task's name/folderPath pair, and return its id. Two tasks on one
|
|
1247
|
+
* resource share the pair: a second pair under the same key is what validate
|
|
1248
|
+
* reads as two resources claiming one binding (CASE_MGMT_BINDING_KEY_SHARED).
|
|
1249
|
+
*/
|
|
1250
|
+
function resourceBinding(resolver, ids, binding, resourceKey, propertyAttribute, value) {
|
|
1122
1251
|
for (const entry of resolver.bindingSink.values()) {
|
|
1123
|
-
if (entry.resource ===
|
|
1252
|
+
if (entry.resource === binding.resource && entry.resourceKey === resourceKey
|
|
1124
1253
|
&& entry.propertyAttribute === propertyAttribute)
|
|
1125
1254
|
return entry.id;
|
|
1126
1255
|
}
|
|
1127
|
-
const id = ids.make('b', 8, `binding:${
|
|
1256
|
+
const id = ids.make('b', 8, `binding:${binding.resource}:${resourceKey}:${propertyAttribute}`);
|
|
1257
|
+
// All seven fields: Studio Web fails to render a case whose binding lacks
|
|
1258
|
+
// `name` or `type`.
|
|
1128
1259
|
resolver.bindingSink.set(id, {
|
|
1129
1260
|
id,
|
|
1130
1261
|
name: propertyAttribute,
|
|
1131
1262
|
type: 'string',
|
|
1132
|
-
resource:
|
|
1263
|
+
resource: binding.resource,
|
|
1264
|
+
...(binding.subType ? { resourceSubType: binding.subType } : {}),
|
|
1133
1265
|
resourceKey,
|
|
1134
1266
|
default: value,
|
|
1135
1267
|
propertyAttribute,
|
|
1136
1268
|
});
|
|
1137
1269
|
return id;
|
|
1138
1270
|
}
|
|
1271
|
+
/** The `=bindings.<id>` name/folderPath references of a published-resource task. */
|
|
1272
|
+
function referenceBindings(kind, ref, resolver, ids) {
|
|
1273
|
+
const binding = kind === 'business-rule'
|
|
1274
|
+
? { resource: BUSINESS_RULE_RESOURCE }
|
|
1275
|
+
: ownEntry(REFERENCE_BINDING, kind);
|
|
1276
|
+
if (!binding)
|
|
1277
|
+
throw new Error(`task kind "${kind}" is not a published-resource task.`);
|
|
1278
|
+
// An in-solution resource (`folder: 'solution_folder'`) keeps the sentinel
|
|
1279
|
+
// in its key and binds an empty folderPath — see resource-identity.ts.
|
|
1280
|
+
const { resourceKey, folderPath } = resourceIdentity(ref.name, ref.folderPath);
|
|
1281
|
+
const nameId = resourceBinding(resolver, ids, binding, resourceKey, 'name', ref.name);
|
|
1282
|
+
const folderId = resourceBinding(resolver, ids, binding, resourceKey, 'folderPath', folderPath);
|
|
1283
|
+
return { nameRef: `=bindings.${nameId}`, folderRef: `=bindings.${folderId}` };
|
|
1284
|
+
}
|
|
1139
1285
|
/**
|
|
1140
1286
|
* The `data` of a `business-rule` task, as Studio Web writes it and as the
|
|
1141
1287
|
* CLI's `tasks describe --type business-rule` + splice produce it:
|
|
1142
1288
|
*
|
|
1143
1289
|
* - `name` / `folderPath` are `=bindings.<id>` references to a `BusinessRule`
|
|
1144
1290
|
* binding pair keyed `<folder>.<name>` (the runtime resolves the rule through
|
|
1145
|
-
* them; `validate --strict` refuses literals)
|
|
1291
|
+
* them; `validate --strict` refuses literals). An in-solution rule is keyed
|
|
1292
|
+
* `solution_folder.<name>` with an empty folderPath default;
|
|
1146
1293
|
* - `version: 'v3'`;
|
|
1147
1294
|
* - `outputs` always starts with `output` (`source: '=result'`, the whole
|
|
1148
1295
|
* decision-keyed result) and `Error` (`source: '=Error'`), followed by the
|
|
@@ -1150,10 +1297,7 @@ function businessRuleBinding(resolver, ids, resourceKey, propertyAttribute, valu
|
|
|
1150
1297
|
* (`=<Decision>.<column>`).
|
|
1151
1298
|
*/
|
|
1152
1299
|
function businessRuleTaskData(task, resolver, elementId, ids) {
|
|
1153
|
-
const
|
|
1154
|
-
const resourceKey = `${ref.folderPath}.${ref.name}`;
|
|
1155
|
-
const nameId = businessRuleBinding(resolver, ids, resourceKey, 'name', ref.name);
|
|
1156
|
-
const folderId = businessRuleBinding(resolver, ids, resourceKey, 'folderPath', ref.folderPath);
|
|
1300
|
+
const { nameRef, folderRef } = referenceBindings(task.kind, task.ref, resolver, ids);
|
|
1157
1301
|
const ownRow = (name, source, seed, extra = {}) => {
|
|
1158
1302
|
const slot = ids.make('v', 8, `${elementId}:${seed}`);
|
|
1159
1303
|
return { name, type: 'jsonSchema', id: slot, var: slot, value: slot, source, target: `=${slot}`, elementId, ...extra };
|
|
@@ -1169,8 +1313,8 @@ function businessRuleTaskData(task, resolver, elementId, ids) {
|
|
|
1169
1313
|
...(task.outputs ?? []).map((o, i) => emitTaskOutput(o, elementId, ids, `${elementId}:out:${i}:${o.var}`, resolver)),
|
|
1170
1314
|
];
|
|
1171
1315
|
return {
|
|
1172
|
-
name:
|
|
1173
|
-
folderPath:
|
|
1316
|
+
name: nameRef,
|
|
1317
|
+
folderPath: folderRef,
|
|
1174
1318
|
version: BUSINESS_RULE_TASK_VERSION,
|
|
1175
1319
|
inputs: (task.inputs ?? []).map((inp, i) => emitTaskInput(inp, elementId, ids, `${elementId}:in:${i}:${inp.name}`)),
|
|
1176
1320
|
outputs,
|
|
@@ -1431,9 +1575,76 @@ function connectorMetadata(rc, op) {
|
|
|
1431
1575
|
/** The `outputs[]`: a `response` json-schema from the op's output schema, plus a
|
|
1432
1576
|
* standard `Error` schema. */
|
|
1433
1577
|
function connectorOutputVar(resolver, base) {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1578
|
+
return claimOutputId(resolver, base);
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Claim a task-output row id from the document-wide pool, the Designer's
|
|
1582
|
+
* uniqueness rule: the first claimant of `base` gets `base`, later ones get
|
|
1583
|
+
* `base2`, `base3`, … (the counter starts at 2 — the Designer-saved plan has
|
|
1584
|
+
* `action` / `action2` and `error` / `error2`). Every output emitter (resource,
|
|
1585
|
+
* action and connector tasks) claims through here, so no two task outputs in a
|
|
1586
|
+
* plan share an id.
|
|
1587
|
+
*/
|
|
1588
|
+
function claimOutputId(resolver, base) {
|
|
1589
|
+
let id = base;
|
|
1590
|
+
// A suffix never lands on a variable another output keeps as its own name
|
|
1591
|
+
// (`ownOutputVars`): with `aPIOutput1`, a second writer of it, and a task that
|
|
1592
|
+
// writes `aPIOutput12` itself, the second writer takes `aPIOutput13` whatever
|
|
1593
|
+
// order the tasks come in.
|
|
1594
|
+
for (let n = 2; resolver.outputIds.has(id) || (id !== base && resolver.ownOutputVars.has(id)); n++)
|
|
1595
|
+
id = `${base}${n}`;
|
|
1596
|
+
resolver.outputIds.add(id);
|
|
1597
|
+
return id;
|
|
1598
|
+
}
|
|
1599
|
+
/** Whether a task output is written in the own-name shape (see `emitTaskOutput`). */
|
|
1600
|
+
function isOwnNameOutput(o) {
|
|
1601
|
+
const path = o.source.replace(/^=/, '');
|
|
1602
|
+
return !path.includes('.') && keepsOwnName(o.var, path);
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Every variable a task in the plan writes under its own name: own-name task
|
|
1606
|
+
* outputs and action form outputs (whose row id is the variable). Collected
|
|
1607
|
+
* before any row is emitted, so `claimOutputId` can keep suffixes off them.
|
|
1608
|
+
*/
|
|
1609
|
+
function ownOutputVars(built) {
|
|
1610
|
+
const vars = new Set();
|
|
1611
|
+
for (const stage of built.stages)
|
|
1612
|
+
for (const lane of stage.lanes)
|
|
1613
|
+
for (const task of lane) {
|
|
1614
|
+
for (const o of task.outputs ?? [])
|
|
1615
|
+
if (isOwnNameOutput(o))
|
|
1616
|
+
vars.add(o.var);
|
|
1617
|
+
for (const f of task.action?.outputs ?? [])
|
|
1618
|
+
if (f.value !== undefined)
|
|
1619
|
+
vars.add(f.value);
|
|
1620
|
+
}
|
|
1621
|
+
return vars;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Whether an output into `name` keeps its field's name: `name` is the field, or
|
|
1625
|
+
* the Designer's camelCase of it, optionally followed by a numeric suffix. The
|
|
1626
|
+
* suffix is how the Designer names the variable a second writer of the same field
|
|
1627
|
+
* gets (`=APIOutput1` → `aPIOutput12`, `=Action` → `action2`): it saves that row
|
|
1628
|
+
* as `{ id: 'aPIOutput12', var: 'aPIOutput12' }` with no `originalVar`, so the
|
|
1629
|
+
* suffixed spelling is an own-name output too, and round-trips as one.
|
|
1630
|
+
*/
|
|
1631
|
+
function keepsOwnName(name, field) {
|
|
1632
|
+
// Only an identifier field: `camelizeName` drops other characters, so `items[0]`
|
|
1633
|
+
// would otherwise match `items0`. The suffix is the Designer's counter, which
|
|
1634
|
+
// starts at 2 and has no leading zero: for the field `APIOutput1`, `APIOutput12`
|
|
1635
|
+
// matches; `APIOutput11` (suffix 1) and `APIOutput102` (suffix 02) do not.
|
|
1636
|
+
if (!/^[A-Za-z_]\w*$/.test(field))
|
|
1637
|
+
return false;
|
|
1638
|
+
return [field, camelizeName(field)].some((base) => name === base || (name.startsWith(base) && /^(?:[2-9]|[1-9]\d+)$/.test(name.slice(base.length))));
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* The Designer's `camelizeDisplayName`: drop non-identifier characters, split on
|
|
1642
|
+
* spaces/underscores, lower the first letter of the first word and upper the
|
|
1643
|
+
* first letter of the rest (`APIOutput1` → `aPIOutput1`).
|
|
1644
|
+
*/
|
|
1645
|
+
function camelizeName(name) {
|
|
1646
|
+
const words = name.replace(/[^a-zA-Z0-9_ ]/g, '').split(/[\s_]+/).filter(Boolean);
|
|
1647
|
+
return words.map((w, i) => (i === 0 ? w.charAt(0).toLowerCase() : w.charAt(0).toUpperCase()) + w.slice(1)).join('');
|
|
1437
1648
|
}
|
|
1438
1649
|
/** The `Error` output's schema: the designer's (and the CLI's) `ERROR_OUTPUT_SCHEMA`. */
|
|
1439
1650
|
const ERROR_OUTPUT_SCHEMA = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.46.
|
|
3
|
+
"version": "6.46.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",
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"@types/node": "^22.7.0",
|
|
94
94
|
"esbuild": "^0.28.1"
|
|
95
95
|
},
|
|
96
|
-
"gitref": "
|
|
96
|
+
"gitref": "b763fc50a8d6430ce9a6e3e3e6b79b7c8645a4b1"
|
|
97
97
|
}
|