@uipath/maestro-builder-sdk 6.45.0 → 6.45.1
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 +3 -3
- package/dist/api-members.md +5 -5
- package/dist/check.js +22 -19
- package/dist/decompile.js +42 -9
- package/dist/flow-node-type.d.ts +3 -2
- package/dist/flow-sdk.d.ts +7 -6
- package/dist/flow-sdk.js +7 -6
- package/dist/merge.js +88 -13
- package/dist/serialize.js +13 -5
- package/package.json +2 -2
package/dist/api-index.md
CHANGED
|
@@ -133,11 +133,11 @@ could hand you spans for a version you do not have.
|
|
|
133
133
|
| `FilterCondition` | type | `dist/nodes/transform/flow/spec.d.ts:10-11` | Supporting types | Comparison a filter rule applies to a field. |
|
|
134
134
|
| `FilterMatch` | type | `dist/nodes/transform/flow/spec.d.ts:8-9` | Supporting types | How a filter combines its rules: every rule must match, or any one. |
|
|
135
135
|
| `FilterRule` | interface | `dist/nodes/transform/flow/spec.d.ts:12-24` | Supporting types | 3 field(s) |
|
|
136
|
-
| `flow` | function | `dist/flow-sdk.d.ts:
|
|
136
|
+
| `flow` | function | `dist/flow-sdk.d.ts:1763-1778` | Flow construction | Start building a flow with the given id. |
|
|
137
137
|
| `FlowAction` | class | `dist/core/node-classes.d.ts:162-168` | Supporting types | A node placed as a step — pass an instance to `.step(name, …)`. |
|
|
138
138
|
| `FlowActionSpec` | type | `dist/flow-sdk.d.ts:55-56` | Supporting types | What `.step()` accepts here: the shared actions plus this SDK's subflow. |
|
|
139
139
|
| `FlowActionSpecs` | interface | `dist/core/actions.d.ts:905-942` | Supporting types | Every action kind, keyed by kind, to the body of its spec — the arm's fields other than `kind`. |
|
|
140
|
-
| `FlowBuilder` | class | `dist/flow-sdk.d.ts:1382-
|
|
140
|
+
| `FlowBuilder` | class | `dist/flow-sdk.d.ts:1382-1762` | Builders | 15 member(s) |
|
|
141
141
|
| `FlowLayout` | interface | `dist/flow-sdk.d.ts:807-820` | Supporting types | Designer layout for a flow, keyed by AUTHOR-level ids: node entries by step name (plus the trigger id and `end`), edge… |
|
|
142
142
|
| `FlowNode` | class | `dist/core/node-classes.d.ts:126-161` | Supporting types | The abstract root of every definition-backed node the builder can place. |
|
|
143
143
|
| `FlowResource` | class | `dist/core/node-classes.d.ts:176-183` | Supporting types | A node attached to another semantic node — an inline agent's tool, context, memory, or escalation. |
|
|
@@ -241,7 +241,7 @@ could hand you spans for a version you do not have.
|
|
|
241
241
|
| `STICKY_NOTE_COLORS` | const | `dist/flow-sdk.d.ts:760-765` | Flow construction | The designer's sticky-note palette. |
|
|
242
242
|
| `StickyNote` | interface | `dist/flow-sdk.d.ts:772-806` | Supporting types | A canvas sticky note — free text pinned to the diagram, for the humans reading it. |
|
|
243
243
|
| `StickyNoteColor` | type | `dist/flow-sdk.d.ts:766-771` | Supporting types | A sticky note's swatch. |
|
|
244
|
-
| `subflow` | function | `dist/flow-sdk.d.ts:
|
|
244
|
+
| `subflow` | function | `dist/flow-sdk.d.ts:1779-1818` | Flow construction | Run another flow as one step, and read back what it returns. |
|
|
245
245
|
| `SubflowSpec` | interface | `dist/flow-sdk.d.ts:47-54` | Supporting types | A step that runs a child flow. |
|
|
246
246
|
| `summarize` | function | `dist/nodes/ai-patterns/flow/factories.d.ts:8-48` | Actions | Summarize a document with citations — the platform's **Summarize** node. |
|
|
247
247
|
| `SummarizeInputs` | interface | `dist/nodes/ai-patterns/flow/spec.d.ts:8-40` | Option shapes | 3 field(s) |
|
package/dist/api-members.md
CHANGED
|
@@ -105,7 +105,7 @@ not find it either.
|
|
|
105
105
|
| `breakEnabled` | property | `LoopOptions` | `dist/flow-sdk.d.ts:541-545` |
|
|
106
106
|
| `build` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3581-3586` |
|
|
107
107
|
| `build` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1344-1349` |
|
|
108
|
-
| `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
108
|
+
| `build` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1755-1761` |
|
|
109
109
|
| `businessRule` | property | `BuiltTask` | `dist/case/case-sdk.d.ts:542-543` |
|
|
110
110
|
| `businessRule` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2577-2641` |
|
|
111
111
|
| `businessRule` | method | `TaskBuilder` | `dist/case/case-sdk.d.ts:833-861` |
|
|
@@ -481,7 +481,7 @@ not find it either.
|
|
|
481
481
|
| `inclusiveGateway` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2305-2312` |
|
|
482
482
|
| `inlineAgent` | property | `FlowActionSpecs` | `dist/nodes/agent/flow/spec.d.ts:443-446` |
|
|
483
483
|
| `input` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1235-1260` |
|
|
484
|
-
| `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
484
|
+
| `input` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1696-1708` |
|
|
485
485
|
| `input` | property | `HumanTaskOpts` | `dist/bpmn/bpmn-sdk.d.ts:1381-1382` |
|
|
486
486
|
| `input` | property | `OrchestratorOpts` | `dist/bpmn/bpmn-sdk.d.ts:1267-1268` |
|
|
487
487
|
| `input` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3137-3145` |
|
|
@@ -746,7 +746,7 @@ not find it either.
|
|
|
746
746
|
| `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3382-3390` |
|
|
747
747
|
| `onTimer` | method | `ActivityBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3391-3399` |
|
|
748
748
|
| `openTails` | property | `BuiltFlow` | `dist/flow-sdk.d.ts:875-880` |
|
|
749
|
-
| `openTails` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1656-
|
|
749
|
+
| `openTails` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1656-1695` |
|
|
750
750
|
| `operation` | property | `Aggregation` | `dist/nodes/transform/flow/spec.d.ts:37` |
|
|
751
751
|
| `operation` | property | `ConnectorToolRef` | `dist/core/actions.d.ts:686-687` |
|
|
752
752
|
| `operation` | property | `WaitConnectorPlaceholderSpec` | `dist/case/case-sdk.d.ts:386-387` |
|
|
@@ -762,7 +762,7 @@ not find it either.
|
|
|
762
762
|
| `outcomes` | property | `EscalationRef` | `dist/core/actions.d.ts:851-856` |
|
|
763
763
|
| `outcomes` | property | `HitlInputs` | `dist/nodes/hitl/flow/spec.d.ts:211-225` |
|
|
764
764
|
| `output` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1261-1273` |
|
|
765
|
-
| `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
765
|
+
| `output` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1709-1744` |
|
|
766
766
|
| `output` | property | `RegistryTypeSpec` | `dist/bpmn/typed-node.d.ts:97` |
|
|
767
767
|
| `output` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3146-3154` |
|
|
768
768
|
| `outputColumns` | property | `BatchTransformInputs` | `dist/nodes/ai-patterns/flow/spec.d.ts:56-60` |
|
|
@@ -1151,7 +1151,7 @@ not find it either.
|
|
|
1151
1151
|
| `value` | property | `TypedInputRow` | `dist/bpmn/typed-node.d.ts:250-251` |
|
|
1152
1152
|
| `values` | property | `DataFabricCreateInputs` | `dist/nodes/data-fabric/flow/spec.d.ts:132-137` |
|
|
1153
1153
|
| `var` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1274-1298` |
|
|
1154
|
-
| `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:
|
|
1154
|
+
| `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1745-1754` |
|
|
1155
1155
|
| `var` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:3128-3136` |
|
|
1156
1156
|
| `var` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:531-532` |
|
|
1157
1157
|
| `var` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:296-297` |
|
package/dist/check.js
CHANGED
|
@@ -3267,8 +3267,8 @@ function checkArmScopedReads(built, diags) {
|
|
|
3267
3267
|
*/
|
|
3268
3268
|
function checkStepRefs(built, diags, reservedIds = []) {
|
|
3269
3269
|
const order = new Map();
|
|
3270
|
-
/**
|
|
3271
|
-
const
|
|
3270
|
+
/** Step name → the `.stepToList` whose port path it lives in — a path only that port reaches. */
|
|
3271
|
+
const portListOf = new Map();
|
|
3272
3272
|
/** Step name → the id of the scope it lives in (a loop body is its own). */
|
|
3273
3273
|
const scopeOf = new Map();
|
|
3274
3274
|
/** Step name → the parallel arm it lives in, as `<parallel>#<index>`. */
|
|
@@ -3321,7 +3321,7 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3321
3321
|
if (!order.has(name))
|
|
3322
3322
|
order.set(name, seq);
|
|
3323
3323
|
if (portList)
|
|
3324
|
-
|
|
3324
|
+
portListOf.set(name, portList);
|
|
3325
3325
|
scopeOf.set(name, scope);
|
|
3326
3326
|
if (arm)
|
|
3327
3327
|
armOf.set(name, arm);
|
|
@@ -3329,7 +3329,7 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3329
3329
|
}
|
|
3330
3330
|
seq++;
|
|
3331
3331
|
if (s.kind === 'stepToList')
|
|
3332
|
-
index(s.body,
|
|
3332
|
+
index(s.body, s, scope, arm);
|
|
3333
3333
|
// A `.stepSwitch` routes EVERY declared exit, as `.switch` routes every
|
|
3334
3334
|
// case, so its arms are not side paths: they inherit `portList`, as a
|
|
3335
3335
|
// `.switch` case does. So a ref into a step of an arm is legal from another
|
|
@@ -3356,7 +3356,7 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3356
3356
|
if (!order.has(fork.name))
|
|
3357
3357
|
order.set(fork.name, seq);
|
|
3358
3358
|
if (portList)
|
|
3359
|
-
|
|
3359
|
+
portListOf.set(fork.name, portList);
|
|
3360
3360
|
scopeOf.set(fork.name, scope);
|
|
3361
3361
|
if (arm)
|
|
3362
3362
|
armOf.set(fork.name, arm);
|
|
@@ -3368,11 +3368,11 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3368
3368
|
index(s.body, portList, s.name, arm);
|
|
3369
3369
|
}
|
|
3370
3370
|
};
|
|
3371
|
-
index(built.steps,
|
|
3371
|
+
index(built.steps, undefined, '', undefined);
|
|
3372
3372
|
// An entry-point prefix is a path of its own that may end at the shared body's
|
|
3373
3373
|
// End, so its Ends count toward the duplicate-name rule below (#1231).
|
|
3374
3374
|
for (const ep of built.entryPoints ?? [])
|
|
3375
|
-
index(ep.steps,
|
|
3375
|
+
index(ep.steps, undefined, '', undefined);
|
|
3376
3376
|
// Two `.return`s asking for the same End name with different content are two
|
|
3377
3377
|
// End nodes, which compile refuses rather than renaming the second `<name>2`
|
|
3378
3378
|
// (#1231). One End shared by several paths is spelled once, with every other
|
|
@@ -3425,14 +3425,14 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3425
3425
|
}
|
|
3426
3426
|
/** Every ref, with where it sits. */
|
|
3427
3427
|
const found = [];
|
|
3428
|
-
const collect = (steps, from, scope, arm, enclosing = []) => {
|
|
3428
|
+
const collect = (steps, from, scope, arm, enclosing = [], paths = []) => {
|
|
3429
3429
|
let source = from;
|
|
3430
3430
|
for (const [i, s] of steps.entries()) {
|
|
3431
3431
|
if (s.kind === 'action' || s.kind === 'stepSwitch')
|
|
3432
3432
|
source = s.name;
|
|
3433
3433
|
if (s.kind === 'stepToRef') {
|
|
3434
3434
|
found.push({
|
|
3435
|
-
target: s.target, port: s.port, from: source, scope, arm, enclosing,
|
|
3435
|
+
target: s.target, port: s.port, from: source, scope, arm, enclosing, paths,
|
|
3436
3436
|
// Only a default-port ref hands the path off, so only it can strand
|
|
3437
3437
|
// what follows; a side exit leaves the chain running.
|
|
3438
3438
|
after: s.port === 'output' ? steps.length - i - 1 : 0,
|
|
@@ -3440,16 +3440,16 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3440
3440
|
continue;
|
|
3441
3441
|
}
|
|
3442
3442
|
if (s.kind === 'stepToList')
|
|
3443
|
-
collect(s.body, source, scope, arm, enclosing);
|
|
3443
|
+
collect(s.body, source, scope, arm, enclosing, [...paths, s]);
|
|
3444
3444
|
else if (s.kind === 'stepSwitch')
|
|
3445
|
-
s.cases.forEach((c) => collect(c.body, s.name, scope, arm, enclosing));
|
|
3445
|
+
s.cases.forEach((c) => collect(c.body, s.name, scope, arm, enclosing, paths));
|
|
3446
3446
|
else if (s.kind === 'branch') {
|
|
3447
|
-
collect(s.then, source, scope, arm, enclosing);
|
|
3448
|
-
collect(s.otherwise, source, scope, arm, enclosing);
|
|
3447
|
+
collect(s.then, source, scope, arm, enclosing, paths);
|
|
3448
|
+
collect(s.otherwise, source, scope, arm, enclosing, paths);
|
|
3449
3449
|
}
|
|
3450
3450
|
else if (s.kind === 'switch') {
|
|
3451
|
-
s.cases.forEach((c) => collect(c.body, source, scope, arm, enclosing));
|
|
3452
|
-
collect(s.default ?? [], source, scope, arm, enclosing);
|
|
3451
|
+
s.cases.forEach((c) => collect(c.body, source, scope, arm, enclosing, paths));
|
|
3452
|
+
collect(s.default ?? [], source, scope, arm, enclosing, paths);
|
|
3453
3453
|
}
|
|
3454
3454
|
else if (s.kind === 'parallel') {
|
|
3455
3455
|
// Arms that all end in `.stepToRef(<one step>)` (or stop) have no Merge:
|
|
@@ -3461,11 +3461,11 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3461
3461
|
const key = `${s.name}#${i}`;
|
|
3462
3462
|
if (refJoinTarget !== undefined)
|
|
3463
3463
|
refJoin.set(key, refJoinTarget);
|
|
3464
|
-
collect(a, source, scope, key, enclosing);
|
|
3464
|
+
collect(a, source, scope, key, enclosing, paths);
|
|
3465
3465
|
});
|
|
3466
3466
|
}
|
|
3467
3467
|
else if (s.kind === 'loop' || s.kind === 'doWhile')
|
|
3468
|
-
collect(s.body, source, s.name, arm, [...enclosing, s.name]);
|
|
3468
|
+
collect(s.body, source, s.name, arm, [...enclosing, s.name], paths);
|
|
3469
3469
|
}
|
|
3470
3470
|
};
|
|
3471
3471
|
/** The step every arm of a parallel refs instead of a Merge, by `<parallel>#<arm>`. */
|
|
@@ -3475,7 +3475,7 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3475
3475
|
collect(built.steps, undefined, '', undefined);
|
|
3476
3476
|
for (const ep of built.entryPoints ?? [])
|
|
3477
3477
|
collect(ep.steps, ep.id, '', undefined);
|
|
3478
|
-
for (const { target, from, after, scope, arm, enclosing } of found) {
|
|
3478
|
+
for (const { target, from, after, scope, arm, enclosing, paths } of found) {
|
|
3479
3479
|
const where = from ? `after "${from}"` : 'at the start of the flow';
|
|
3480
3480
|
const say = (level, code, message, suggestion) => {
|
|
3481
3481
|
diags.push({ level, code, message, step: from ?? 'stepToRef', ...(suggestion ? { suggestion } : {}) });
|
|
@@ -3517,7 +3517,10 @@ function checkStepRefs(built, diags, reservedIds = []) {
|
|
|
3517
3517
|
+ `next iteration, or .break() to leave the loop.`, '.continue()');
|
|
3518
3518
|
continue;
|
|
3519
3519
|
}
|
|
3520
|
-
|
|
3520
|
+
// A ref inside the port path its target is on (a step's own `.onError`
|
|
3521
|
+
// rejoining the error path it sits on) runs only when that port fired too.
|
|
3522
|
+
const targetPath = portListOf.get(target);
|
|
3523
|
+
if (targetPath && !paths.includes(targetPath) && !terminal) {
|
|
3521
3524
|
say('error', 'REF_INTO_PORT_LIST', `.stepToRef('${target}') ${where} targets a step inside another port's path. That path runs only when ITS `
|
|
3522
3525
|
+ `port fired — it is not somewhere another edge can jump into. Point at a step on the main path, or end `
|
|
3523
3526
|
+ `this one with .return() / .terminate(). (A named End or a Terminate is the exception: any path may end `
|
package/dist/decompile.js
CHANGED
|
@@ -602,6 +602,36 @@ class Graph {
|
|
|
602
602
|
&& (!e.sourcePort.startsWith('outcome-') || e.sourcePort === primary)
|
|
603
603
|
&& !side?.has(e.sourcePort))));
|
|
604
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* `true` when a decision or switch has an arm with no edge at all: a
|
|
607
|
+
* decision's `true` or `false`, a switch's `case-<id>`, or its `default` when
|
|
608
|
+
* the switch has one. Such an arm is a dead end — the flow stops there — so in
|
|
609
|
+
* the post-dominator walk it is a path to the scope's EXIT, exactly like a
|
|
610
|
+
* step with no successor (#1228). Without that, the arms "reconverged" at the
|
|
611
|
+
* wired arm's first step: `dec@true -> a`, `dec@false` unwired decompiled to
|
|
612
|
+
* `.branch("dec", …, (t) => t, (e) => e).step("a", …)`, and compiling it wired
|
|
613
|
+
* `dec@false -> a`, an edge the file never had.
|
|
614
|
+
*
|
|
615
|
+
* Only the two structured forks need this. Every other exit that may be
|
|
616
|
+
* unwired (`branch-*`, a non-primary `outcome-*`, a raw node's side exit) is
|
|
617
|
+
* a side path, not a successor, so it never takes part in a join; and a node
|
|
618
|
+
* whose declared exits are all wired (`fullyWiredExits`) has none unwired.
|
|
619
|
+
*/
|
|
620
|
+
hasUnwiredArm(id) {
|
|
621
|
+
const node = this.byId.get(id);
|
|
622
|
+
if (!node)
|
|
623
|
+
return false;
|
|
624
|
+
const wired = new Set(this.outEdges(id).map((e) => e.sourcePort));
|
|
625
|
+
if (node.type === T.decision)
|
|
626
|
+
return !wired.has('true') || !wired.has('false');
|
|
627
|
+
if (node.type !== T.switch)
|
|
628
|
+
return false;
|
|
629
|
+
const inputs = (node.inputs ?? {});
|
|
630
|
+
const arms = (inputs.cases ?? []).map((c) => `case-${String(c?.id ?? '')}`);
|
|
631
|
+
if (inputs.hasDefault === true)
|
|
632
|
+
arms.push('default');
|
|
633
|
+
return arms.some((p) => !wired.has(p));
|
|
634
|
+
}
|
|
605
635
|
/**
|
|
606
636
|
* A multi-exit `rawNode`'s SIDE exits when not every exit is wired: each
|
|
607
637
|
* declared exit except the one its main path leaves on (`contributionPort`,
|
|
@@ -1307,7 +1337,10 @@ function postDominators(entry, scope, graph, container) {
|
|
|
1307
1337
|
// first step.
|
|
1308
1338
|
const leaves = container !== undefined
|
|
1309
1339
|
&& graph.successorEdges(n).some((e) => e.targetNodeId === container);
|
|
1310
|
-
|
|
1340
|
+
// A decision or switch arm with no edge is a dead end: a path to EXIT too,
|
|
1341
|
+
// or the fork "reconverges" at the wired arm's first step and compiling
|
|
1342
|
+
// wires the empty arm there (#1228).
|
|
1343
|
+
const ss = s.length === 0 ? [EXIT] : leaves || graph.hasUnwiredArm(n) ? [...s, EXIT] : s;
|
|
1311
1344
|
succ.set(n, ss);
|
|
1312
1345
|
for (const t of ss) {
|
|
1313
1346
|
addP(n, t);
|
|
@@ -1848,15 +1881,15 @@ function region(cursor, stop, scope, ipdom, ctx, refInto) {
|
|
|
1848
1881
|
cursor = fork.next.cursor;
|
|
1849
1882
|
continue;
|
|
1850
1883
|
}
|
|
1851
|
-
// A merge node with one edge in and one out is a pass-through
|
|
1852
|
-
// designer left in place (a join whose arms were
|
|
1853
|
-
// layout names it, so it is kept: it falls through
|
|
1854
|
-
// path below and comes back as the raw node of its
|
|
1855
|
-
// (#1310). Skipping it dropped the node, and compile then
|
|
1856
|
-
// `.layout()` key. A bare merge with several edges in (a
|
|
1857
|
-
// was not detected) is still skipped — best effort.
|
|
1884
|
+
// A merge node with one edge in and at most one out is a pass-through
|
|
1885
|
+
// (or a dead end) the designer left in place (a join whose arms were
|
|
1886
|
+
// later removed). The layout names it, so it is kept: it falls through
|
|
1887
|
+
// to the regular step path below and comes back as the raw node of its
|
|
1888
|
+
// own definition (#1310). Skipping it dropped the node, and compile then
|
|
1889
|
+
// refused the `.layout()` key. A bare merge with several edges in (a
|
|
1890
|
+
// join whose fork was not detected) is still skipped — best effort.
|
|
1858
1891
|
const ins = ctx.graph.inEdges(node.id).filter((e) => scope.has(e.sourceNodeId));
|
|
1859
|
-
if (outs.length
|
|
1892
|
+
if (outs.length > 1 || ins.length !== 1) {
|
|
1860
1893
|
const next = continueOn(node, 'output', ctx, refInto);
|
|
1861
1894
|
if (next.brk || next.cont) {
|
|
1862
1895
|
segs.push(next.brk ? '.break()' : '.continue()');
|
package/dist/flow-node-type.d.ts
CHANGED
|
@@ -428,8 +428,9 @@ export interface FlowNodeType<Spec> extends NodeType<Spec, FlowNodeContribution,
|
|
|
428
428
|
readonly errorEnvelope?: string;
|
|
429
429
|
/**
|
|
430
430
|
* `true`: a path that ends on this node is capped with an End even under
|
|
431
|
-
* `.openTails()
|
|
432
|
-
*
|
|
431
|
+
* `.openTails()`, unless the node already has a `completed` or `outcome-*`
|
|
432
|
+
* edge. A human task sets it: the product's `hitl-completed` rule wants an
|
|
433
|
+
* edge after the task.
|
|
433
434
|
*/
|
|
434
435
|
readonly capsOpenTail?: boolean;
|
|
435
436
|
/**
|
package/dist/flow-sdk.d.ts
CHANGED
|
@@ -1671,12 +1671,13 @@ declare class FlowBuilder extends StepList {
|
|
|
1671
1671
|
*
|
|
1672
1672
|
* It changes only paths that fall off. `.return(...)`, `.terminate(...)`, a
|
|
1673
1673
|
* `.stepSwitch` exit with no arm and a human-task outcome with
|
|
1674
|
-
* `action: 'End'` still emit their End. A human task that ends a path
|
|
1675
|
-
* still capped with an End (the product's
|
|
1676
|
-
* after it), so a file whose human task
|
|
1677
|
-
*
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
1674
|
+
* `action: 'End'` still emit their End. A human task that ends a path with
|
|
1675
|
+
* no outcome wired is still capped with an End (the product's
|
|
1676
|
+
* `hitl-completed` rule wants an edge after it), so a file whose human task
|
|
1677
|
+
* has no outgoing edge gains one on a round trip; one whose other outcome is
|
|
1678
|
+
* wired keeps the open one open. A path left open maps no outputs, so a flow
|
|
1679
|
+
* that declares `.output(...)` answers nothing on that path. Use
|
|
1680
|
+
* `.return(...)` on the paths that must answer.
|
|
1680
1681
|
*
|
|
1681
1682
|
* A subflow's child flow has its own setting; it does not inherit the
|
|
1682
1683
|
* caller's.
|
package/dist/flow-sdk.js
CHANGED
|
@@ -1325,12 +1325,13 @@ class FlowBuilder extends StepList {
|
|
|
1325
1325
|
*
|
|
1326
1326
|
* It changes only paths that fall off. `.return(...)`, `.terminate(...)`, a
|
|
1327
1327
|
* `.stepSwitch` exit with no arm and a human-task outcome with
|
|
1328
|
-
* `action: 'End'` still emit their End. A human task that ends a path
|
|
1329
|
-
* still capped with an End (the product's
|
|
1330
|
-
* after it), so a file whose human task
|
|
1331
|
-
*
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1328
|
+
* `action: 'End'` still emit their End. A human task that ends a path with
|
|
1329
|
+
* no outcome wired is still capped with an End (the product's
|
|
1330
|
+
* `hitl-completed` rule wants an edge after it), so a file whose human task
|
|
1331
|
+
* has no outgoing edge gains one on a round trip; one whose other outcome is
|
|
1332
|
+
* wired keeps the open one open. A path left open maps no outputs, so a flow
|
|
1333
|
+
* that declares `.output(...)` answers nothing on that path. Use
|
|
1334
|
+
* `.return(...)` on the paths that must answer.
|
|
1334
1335
|
*
|
|
1335
1336
|
* A subflow's child flow has its own setting; it does not inherit the
|
|
1336
1337
|
* caller's.
|
package/dist/merge.js
CHANGED
|
@@ -262,23 +262,83 @@ function withDisplayEdits(node, orig, e, base) {
|
|
|
262
262
|
* The original with the author's edits applied, by the delta rule of
|
|
263
263
|
* merge-variables.ts: where `e` equals the baseline `b` the original's value
|
|
264
264
|
* stays (absent stays absent), and inside objects all three have, the rule
|
|
265
|
-
* recurses key by key.
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
265
|
+
* recurses key by key. A list whose entries have ids goes entry by entry
|
|
266
|
+
* ({@link withListEdits}), so relabelling one form field does not rewrite the
|
|
267
|
+
* others in compile's spelling, and an edited condition keeps the original's
|
|
268
|
+
* spelling ({@link inOriginalSpelling}). Any other list is taken whole, and so is a
|
|
269
|
+
* changed expression value, whose `type` says how to read its `expression`:
|
|
270
|
+
* decompile turns a legacy `{ type: 'literal', expression: '{{ $vars.x }}' }`
|
|
271
|
+
* agent input into a `jsExpression`, so an edited reference merged key by key
|
|
272
|
+
* would keep `literal` and hand the agent the text. Applied to an edited node, a
|
|
270
273
|
* one-input edit to a connector keeps the rest of its `detail` as written, and
|
|
271
274
|
* compile's `model`, derived `outputs` and other spellings stay out of it.
|
|
272
275
|
*/
|
|
273
276
|
function withEdits(o, b, e) {
|
|
274
277
|
if (stableJson(e) === stableJson(b))
|
|
275
278
|
return o === undefined ? o : jsonClone(o);
|
|
279
|
+
const respelled = inOriginalSpelling(o, b, e);
|
|
280
|
+
if (respelled !== undefined)
|
|
281
|
+
return respelled;
|
|
282
|
+
if (Array.isArray(o) && Array.isArray(b) && Array.isArray(e))
|
|
283
|
+
return withListEdits(o, b, e) ?? jsonClone(e);
|
|
276
284
|
if (!isRecord(o) || !isRecord(b) || !isRecord(e) || isExpressionValue(o) || isExpressionValue(e)) {
|
|
277
285
|
return e === undefined ? e : jsonClone(e);
|
|
278
286
|
}
|
|
279
287
|
return mergeObject(o, b, e, withEdits);
|
|
280
288
|
}
|
|
281
289
|
const isExpressionValue = (v) => typeof v.type === 'string' && Object.hasOwn(v, 'expression');
|
|
290
|
+
/**
|
|
291
|
+
* An edited condition `e` in the original's spelling, where compile writes it
|
|
292
|
+
* bare: Studio Web writes a decision or switch condition as `=js: <x>` or a
|
|
293
|
+
* `{ type: 'jsExpression', expression: <x> }` envelope, compile as `<x>` (#1308).
|
|
294
|
+
* `undefined` when `o` is not one of those spellings of `b`.
|
|
295
|
+
*/
|
|
296
|
+
function inOriginalSpelling(o, b, e) {
|
|
297
|
+
if (typeof b !== 'string' || typeof e !== 'string' || e.startsWith('='))
|
|
298
|
+
return undefined;
|
|
299
|
+
if (typeof o === 'string') {
|
|
300
|
+
const prefix = /^=js:\s*/.exec(o)?.[0];
|
|
301
|
+
return prefix && o.slice(prefix.length) === b ? prefix + e : undefined;
|
|
302
|
+
}
|
|
303
|
+
return isRecord(o) && o.type === 'jsExpression' && o.expression === b ? { ...jsonClone(o), expression: e } : undefined;
|
|
304
|
+
}
|
|
305
|
+
/** What `after` changed from `before`, key by key; `undefined` when nothing. */
|
|
306
|
+
function changedFrom(before, after) {
|
|
307
|
+
if (stableJson(after) === stableJson(before))
|
|
308
|
+
return undefined;
|
|
309
|
+
if (!isRecord(before) || !isRecord(after) || isExpressionValue(before) || isExpressionValue(after))
|
|
310
|
+
return after;
|
|
311
|
+
const out = {};
|
|
312
|
+
for (const k of Object.keys(after)) {
|
|
313
|
+
const d = changedFrom(before[k], after[k]);
|
|
314
|
+
if (d !== undefined)
|
|
315
|
+
out[k] = d;
|
|
316
|
+
}
|
|
317
|
+
return out;
|
|
318
|
+
}
|
|
319
|
+
/** The `id` of every entry, when every entry is an object with its own string `id`. */
|
|
320
|
+
function entryIds(list) {
|
|
321
|
+
const ids = list.map((x) => (isRecord(x) && typeof x.id === 'string' ? x.id : undefined));
|
|
322
|
+
return ids.every((id) => id !== undefined) && new Set(ids).size === ids.length ? ids : undefined;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* {@link withEdits} over a list whose entries all have their own `id` (a human
|
|
326
|
+
* task's form fields, a switch's cases), entry by entry: an entry the author
|
|
327
|
+
* did not change stays as the original wrote it. `undefined` when the lists
|
|
328
|
+
* cannot be lined up that way (no ids, or the round trip changed which entries
|
|
329
|
+
* there are), and the caller takes the edited list whole.
|
|
330
|
+
*/
|
|
331
|
+
function withListEdits(o, b, e) {
|
|
332
|
+
const [oi, bi, ei] = [entryIds(o), entryIds(b), entryIds(e)];
|
|
333
|
+
if (!oi || !bi || !ei || oi.length !== bi.length || !oi.every((id) => bi.includes(id)))
|
|
334
|
+
return undefined;
|
|
335
|
+
const at = (list, ids, id) => list[ids.indexOf(id)];
|
|
336
|
+
// The author kept the entries and their order: keep the original's order too.
|
|
337
|
+
const order = ei.join('\0') === bi.join('\0') ? oi : ei;
|
|
338
|
+
return order.map((id) => (bi.includes(id)
|
|
339
|
+
? withEdits(at(o, oi, id), at(b, bi, id), at(e, ei, id))
|
|
340
|
+
: jsonClone(at(e, ei, id))));
|
|
341
|
+
}
|
|
282
342
|
/**
|
|
283
343
|
* Whether an edited node can merge field by field onto its original: all three
|
|
284
344
|
* have one type and one `typeVersion`. A node whose version the edit or the
|
|
@@ -369,6 +429,9 @@ function mergeFlowFindings(original, edited, options) {
|
|
|
369
429
|
// references are the original's now, not the recompile's
|
|
370
430
|
// (see withoutRowsMintedForKeptNodes).
|
|
371
431
|
const keptFromOriginal = new Set();
|
|
432
|
+
// The edited nodes merged field by field, with what the merge took from the
|
|
433
|
+
// edit: their other fields are the original's, and so are the bindings those need.
|
|
434
|
+
const fieldwise = new Map();
|
|
372
435
|
/** Root node ids taken from `edited` that the original also has (the author edited them). */
|
|
373
436
|
const editedIds = new Set();
|
|
374
437
|
for (const e of edited.nodes ?? []) {
|
|
@@ -385,9 +448,14 @@ function mergeFlowFindings(original, edited, options) {
|
|
|
385
448
|
// field (withEdits), else the edited node; then re-attach original layout.
|
|
386
449
|
// An EMBEDDED agent stays embedded: the original plus the author's change
|
|
387
450
|
// to the node, never the edited shell whole (#1220, merge-embedded-agent.ts).
|
|
451
|
+
const byField = !keepsEmbeddedAgent(orig, e) && !!orig && !!base && mergesByField(orig, base, e);
|
|
388
452
|
const taken = keepsEmbeddedAgent(orig, e) ? mergeEmbeddedAgentNode(orig, e, base)
|
|
389
|
-
:
|
|
453
|
+
: byField ? withEdits(orig, base, e)
|
|
390
454
|
: jsonClone(e);
|
|
455
|
+
// Against the merged node, not the edit: a key the original lacks comes
|
|
456
|
+
// from the edit whole, unchanged children and their bindings included.
|
|
457
|
+
if (byField)
|
|
458
|
+
fieldwise.set(e.id, changedFrom(orig, taken));
|
|
391
459
|
const node = orig && base ? withDisplayEdits(taken, orig, e, base) : taken;
|
|
392
460
|
const placed = withOriginalSource(withOriginalLayout(node, orig, layoutNodesOf(original)), orig, base);
|
|
393
461
|
finalNodes.push(placed);
|
|
@@ -493,9 +561,10 @@ function mergeFlowFindings(original, edited, options) {
|
|
|
493
561
|
// ── Bindings: union by what each row binds (original wins), so resources for
|
|
494
562
|
// newly-added nodes come from `edited` while the original's stay intact.
|
|
495
563
|
// A row the no-edit recompile minted only for nodes the merge kept from the
|
|
496
|
-
// original
|
|
564
|
+
// original, or for fields of an edited node the edit did not change, is
|
|
565
|
+
// not carried (#1133). ──
|
|
497
566
|
result.bindings = mergeBindings(original.bindings, edited.bindings);
|
|
498
|
-
result.bindings = withoutRowsMintedForKeptNodes(result.bindings, original, edited, options.baseline, keptFromOriginal);
|
|
567
|
+
result.bindings = withoutRowsMintedForKeptNodes(result.bindings, original, edited, options.baseline, keptFromOriginal, fieldwise);
|
|
499
568
|
// metadata / solutionId / projectId / layout / runtime were carried by the
|
|
500
569
|
// initial clone of `original` and are intentionally left untouched, apart
|
|
501
570
|
// from the `layout.nodes` entries of removed nodes (dropped above) and added
|
|
@@ -733,11 +802,16 @@ function mergeBindings(orig, edited) {
|
|
|
733
802
|
* only when no other row has that name, and for a `""`-keyed row only when the
|
|
734
803
|
* node spells none of the other same-named rows' keys.
|
|
735
804
|
*
|
|
805
|
+
* An edited node merged field by field (`fieldwise`, with what the merge took
|
|
806
|
+
* from the edit) is the original's in every other field, so it needs such a row
|
|
807
|
+
* only when what it took references it. A classic-CLI IxP extract
|
|
808
|
+
* whose `fileRef` the author edits still carries its model inline.
|
|
809
|
+
*
|
|
736
810
|
* Kept: a row no edited node references (one a sidecar file uses, say), a row
|
|
737
811
|
* a subflow node or an edited node references, and every row without a baseline.
|
|
738
812
|
*/
|
|
739
|
-
function withoutRowsMintedForKeptNodes(rows, original, edited, baseline, keptFromOriginal) {
|
|
740
|
-
if (!baseline || !rows || keptFromOriginal.size === 0)
|
|
813
|
+
function withoutRowsMintedForKeptNodes(rows, original, edited, baseline, keptFromOriginal, fieldwise) {
|
|
814
|
+
if (!baseline || !rows || (keptFromOriginal.size === 0 && fieldwise.size === 0))
|
|
741
815
|
return rows;
|
|
742
816
|
const contextByType = new Map();
|
|
743
817
|
for (const d of (edited.definitions ?? [])) {
|
|
@@ -745,9 +819,9 @@ function withoutRowsMintedForKeptNodes(rows, original, edited, baseline, keptFro
|
|
|
745
819
|
continue;
|
|
746
820
|
contextByType.set(d.nodeType, (contextByType.get(d.nodeType) ?? '') + JSON.stringify(d.model.context));
|
|
747
821
|
}
|
|
748
|
-
const describe = (n, kept) => ({ kept, text: JSON.stringify(n) + (contextByType.get(n.type) ?? '') });
|
|
822
|
+
const describe = (n, kept, changed) => ({ kept, changed, text: JSON.stringify(n) + (contextByType.get(n.type) ?? '') });
|
|
749
823
|
const nodes = [
|
|
750
|
-
...(edited.nodes ?? []).map((n) => describe(n, keptFromOriginal.has(n.id))),
|
|
824
|
+
...(edited.nodes ?? []).map((n) => describe(n, keptFromOriginal.has(n.id), fieldwise.has(n.id) ? JSON.stringify(fieldwise.get(n.id) ?? {}) : undefined)),
|
|
751
825
|
...Object.values(edited.subflows ?? {}).flatMap((sf) => (sf?.nodes ?? []).map((n) => describe(n, false))),
|
|
752
826
|
];
|
|
753
827
|
const spelled = (s) => JSON.stringify(s).slice(1, -1);
|
|
@@ -774,6 +848,7 @@ function withoutRowsMintedForKeptNodes(rows, original, edited, baseline, keptFro
|
|
|
774
848
|
: others.length === 0;
|
|
775
849
|
};
|
|
776
850
|
const referencers = nodes.filter((n) => references(n.text));
|
|
777
|
-
|
|
851
|
+
const needs = (n) => !n.kept && (n.changed === undefined || references(n.changed));
|
|
852
|
+
return !(referencers.length > 0 && !referencers.some(needs));
|
|
778
853
|
});
|
|
779
854
|
}
|
package/dist/serialize.js
CHANGED
|
@@ -2217,13 +2217,19 @@ export function serialize(built, opts = {}) {
|
|
|
2217
2217
|
*
|
|
2218
2218
|
* All of them by default. Under `.openTails()` (#1142) only the tails
|
|
2219
2219
|
* of a node whose type sets `capsOpenTail` (a human task: the product's
|
|
2220
|
-
* `hitl-completed` rule wants an edge after it)
|
|
2221
|
-
*
|
|
2220
|
+
* `hitl-completed` rule wants an edge after it) and that has no outcome
|
|
2221
|
+
* edge yet: the rule is met by any `completed` or `outcome-*` edge, so a
|
|
2222
|
+
* task whose Reject is wired keeps its Approve open. Every other tail is
|
|
2223
|
+
* left open, which is the shape the classic CLI and the canvas write.
|
|
2222
2224
|
*/
|
|
2223
2225
|
function tailsToCap(scope, tails) {
|
|
2224
2226
|
if (!scope.openTails)
|
|
2225
2227
|
return [...tails];
|
|
2226
|
-
|
|
2228
|
+
const isOutcome = (port) => port === 'completed' || String(port).startsWith('outcome-');
|
|
2229
|
+
// A `.stepToRef` edge is still pending here: resolveRejoins runs after.
|
|
2230
|
+
const hasOutcomeEdge = (node) => scope.edges.some((e) => e.sourceNodeId === node && isOutcome(e.sourcePort))
|
|
2231
|
+
|| scope.pendingEdges.some((p) => p.from.node === node && isOutcome(p.from.port));
|
|
2232
|
+
return tails.filter((t) => capsOpenTail.has(t.node) && !hasOutcomeEdge(t.node));
|
|
2227
2233
|
}
|
|
2228
2234
|
/**
|
|
2229
2235
|
* Emit a child flow into its own scope and register it under the calling
|
|
@@ -3178,7 +3184,7 @@ export function serialize(built, opts = {}) {
|
|
|
3178
3184
|
// DYNAMIC, one per case, so they are synthesized here instead of copied
|
|
3179
3185
|
// from the definition. The emitted shape mirrors the platform's
|
|
3180
3186
|
// `walkSwitchStatement` (the canonical emitter) exactly:
|
|
3181
|
-
// inputs.cases[] = { id, label, expression }, inputs.hasDefault,
|
|
3187
|
+
// inputs.cases[] = { id, label, expression }, inputs.hasDefault (1.0.0),
|
|
3182
3188
|
// source ports `case-<id>` per case + `default` for the default arm.
|
|
3183
3189
|
// Each case `expression` is a full boolean condition (the node evaluates
|
|
3184
3190
|
// them in order and takes the first truthy one), auto-evaluated as JS by
|
|
@@ -3197,7 +3203,9 @@ export function serialize(built, opts = {}) {
|
|
|
3197
3203
|
? renameRefs(c.when.js, scope.rename)
|
|
3198
3204
|
: `${renameRefs(step.on?.js ?? 'undefined', scope.rename)} === ${caseLiteral(c.value)}`,
|
|
3199
3205
|
}));
|
|
3200
|
-
|
|
3206
|
+
// Switch 1.1 dropped `hasDefault`: its `default` handle is always there.
|
|
3207
|
+
const declared = bundledNodeDefs.get(id)?.inputDefinition?.properties;
|
|
3208
|
+
node.inputs = { cases, ...(!declared || Object.hasOwn(declared, 'hasDefault') ? { hasDefault: step.default !== undefined } : {}) };
|
|
3201
3209
|
scope.nodes.push(node);
|
|
3202
3210
|
for (const t of tails)
|
|
3203
3211
|
addEdge(scope, t, id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.45.
|
|
3
|
+
"version": "6.45.1",
|
|
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": "f8fe049e27996a1862ea9ce5c48507b15b6178d0"
|
|
97
97
|
}
|