@uipath/maestro-builder-sdk 6.31.4 → 6.31.5
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/merge.d.ts +3 -1
- package/dist/merge.js +69 -29
- package/package.json +2 -2
package/dist/merge.d.ts
CHANGED
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
* preserved from the original; `subflows` and edges (with their ids) come from
|
|
29
29
|
* `edited`; `definitions` and `bindings` are unioned
|
|
30
30
|
* (original wins on conflict, since the original's are the tenant-resolved
|
|
31
|
-
* authority). A binding row's identity is what it binds, not its row id
|
|
31
|
+
* authority). A binding row's identity is what it binds, not its row id, and a
|
|
32
|
+
* row the no-edit recompile minted only for nodes merge kept from the original
|
|
33
|
+
* is not carried (see withoutRowsMintedForKeptNodes). Node ids are stable by construction (decompile names every step by
|
|
32
34
|
* its node id), which is what lets every re-attach key on id.
|
|
33
35
|
*
|
|
34
36
|
* ## Definitions are keyed by `nodeType@version`, not by `nodeType`
|
package/dist/merge.js
CHANGED
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
* preserved from the original; `subflows` and edges (with their ids) come from
|
|
29
29
|
* `edited`; `definitions` and `bindings` are unioned
|
|
30
30
|
* (original wins on conflict, since the original's are the tenant-resolved
|
|
31
|
-
* authority). A binding row's identity is what it binds, not its row id
|
|
31
|
+
* authority). A binding row's identity is what it binds, not its row id, and a
|
|
32
|
+
* row the no-edit recompile minted only for nodes merge kept from the original
|
|
33
|
+
* is not carried (see withoutRowsMintedForKeptNodes). Node ids are stable by construction (decompile names every step by
|
|
32
34
|
* its node id), which is what lets every re-attach key on id.
|
|
33
35
|
*
|
|
34
36
|
* ## Definitions are keyed by `nodeType@version`, not by `nodeType`
|
|
@@ -212,12 +214,17 @@ function mergeFlowFindings(original, edited, options) {
|
|
|
212
214
|
// ── Nodes: the edited graph decides which nodes exist and in what order; the
|
|
213
215
|
// original decides their look (and, for untouched nodes, their content). ──
|
|
214
216
|
const finalNodes = [];
|
|
217
|
+
// The edited nodes the merge replaced with the original's: their bindings
|
|
218
|
+
// references are the original's now, not the recompile's
|
|
219
|
+
// (see withoutRowsMintedForKeptNodes).
|
|
220
|
+
const keptFromOriginal = new Set();
|
|
215
221
|
for (const e of edited.nodes ?? []) {
|
|
216
222
|
const orig = origNodes.get(e.id);
|
|
217
223
|
if (isKept(e, origNodes, baseNodes, options.baseline) && orig) {
|
|
218
224
|
// Untouched by the user (equal to the faithful baseline) → keep the
|
|
219
225
|
// original node exactly, placeholder-safe.
|
|
220
226
|
finalNodes.push(jsonClone(orig));
|
|
227
|
+
keptFromOriginal.add(e.id);
|
|
221
228
|
}
|
|
222
229
|
else {
|
|
223
230
|
// Added or edited → take the edited node, re-attaching original layout.
|
|
@@ -266,9 +273,11 @@ function mergeFlowFindings(original, edited, options) {
|
|
|
266
273
|
];
|
|
267
274
|
result.definitions = mergeDefinitions(original.definitions, edited.definitions, allNodes, originalNodes, options.warn);
|
|
268
275
|
// ── Bindings: union by what each row binds (original wins), so resources for
|
|
269
|
-
// newly-added nodes come from `edited` while the original's stay intact.
|
|
276
|
+
// newly-added nodes come from `edited` while the original's stay intact.
|
|
277
|
+
// A row the no-edit recompile minted only for nodes the merge kept from the
|
|
278
|
+
// original is not carried (#1133). ──
|
|
270
279
|
result.bindings = mergeBindings(original.bindings, edited.bindings);
|
|
271
|
-
result.bindings =
|
|
280
|
+
result.bindings = withoutRowsMintedForKeptNodes(result.bindings, original, edited, options.baseline, keptFromOriginal);
|
|
272
281
|
// metadata / solutionId / projectId / layout / runtime were carried by the
|
|
273
282
|
// initial clone of `original` and are intentionally left untouched.
|
|
274
283
|
//
|
|
@@ -379,12 +388,14 @@ function mergeDefinitions(orig, edited, nodes, originalNodes, warn) {
|
|
|
379
388
|
* holds it, in which case it gets a fresh one — ids are unreferenced labels, but
|
|
380
389
|
* two rows with one id are not a valid file.
|
|
381
390
|
*
|
|
382
|
-
* Rows
|
|
391
|
+
* Rows of the ORIGINAL are never pruned. The canvas file has no uniform
|
|
383
392
|
* node-to-row reference to decide "unused" by: an in-solution Flow is named by
|
|
384
393
|
* the node TYPE's suffix, a connection by an id in the node's inputs, a published
|
|
385
394
|
* process by a folder-qualified key that no node field spells. A wrong prune
|
|
386
395
|
* drops a row a kept node needs, and the run fails to resolve its resource; an
|
|
387
|
-
* orphan row is accepted by `validate` and ignored at run time.
|
|
396
|
+
* orphan row is accepted by `validate` and ignored at run time. Added rows the
|
|
397
|
+
* round trip minted only for kept nodes are dropped afterwards, by
|
|
398
|
+
* {@link withoutRowsMintedForKeptNodes}.
|
|
388
399
|
*/
|
|
389
400
|
function mergeBindings(orig, edited) {
|
|
390
401
|
const out = (orig ?? []).map((b) => jsonClone(b));
|
|
@@ -409,41 +420,70 @@ function mergeBindings(orig, edited) {
|
|
|
409
420
|
return out;
|
|
410
421
|
}
|
|
411
422
|
/**
|
|
412
|
-
* Drop each added row that the no-edit recompile minted for
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
423
|
+
* Drop each added row that the no-edit recompile minted only for nodes the merge
|
|
424
|
+
* kept from the original (#1133). A row qualifies when the original lacks it, the
|
|
425
|
+
* baseline has it, and at least one edited node references it, every one of
|
|
426
|
+
* which is in `keptFromOriginal`: the kept node is the original's, which reaches
|
|
427
|
+
* its resource without that row.
|
|
417
428
|
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
429
|
+
* Examples:
|
|
430
|
+
* - A classic-CLI IxP extract carries its model inline and has no rows. It
|
|
431
|
+
* decompiles to `ixpExtract(...)`, whose compile mints `ixpDeployment` rows
|
|
432
|
+
* keyed by the model id.
|
|
433
|
+
* - A classic-CLI `core.action.http.v2` with no connection decompiles to
|
|
434
|
+
* `http({ managed: true })`, whose compile mints `""`-keyed rows for
|
|
435
|
+
* `<bindings.uipath-uipath-http connection>` and `<bindings.FolderKey>`.
|
|
422
436
|
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
437
|
+
* "References" is read off the EDITED file, which the SDK wrote. A node
|
|
438
|
+
* references a row when it spells the row's `resourceKey`, or when it spells the
|
|
439
|
+
* row's `<bindings.NAME>` placeholder (in the node, or in its type's definition)
|
|
440
|
+
* and points at that row's resource. Names are not unique: a Slack step on
|
|
441
|
+
* connection X and a connection-less http step both use `<bindings.FolderKey>`,
|
|
442
|
+
* each with its own `FolderKey` row. So a placeholder counts for a keyed row
|
|
443
|
+
* only when no other row has that name, and for a `""`-keyed row only when the
|
|
444
|
+
* node spells none of the other same-named rows' keys.
|
|
445
|
+
*
|
|
446
|
+
* Kept: a row no edited node references (one a sidecar file uses, say), a row
|
|
447
|
+
* a subflow node or an edited node references, and every row without a baseline.
|
|
425
448
|
*/
|
|
426
|
-
function
|
|
427
|
-
if (!baseline || !rows)
|
|
449
|
+
function withoutRowsMintedForKeptNodes(rows, original, edited, baseline, keptFromOriginal) {
|
|
450
|
+
if (!baseline || !rows || keptFromOriginal.size === 0)
|
|
428
451
|
return rows;
|
|
429
|
-
const
|
|
430
|
-
const
|
|
452
|
+
const contextByType = new Map();
|
|
453
|
+
for (const d of (edited.definitions ?? [])) {
|
|
454
|
+
if (typeof d?.nodeType !== 'string' || d.model?.context === undefined)
|
|
455
|
+
continue;
|
|
456
|
+
contextByType.set(d.nodeType, (contextByType.get(d.nodeType) ?? '') + JSON.stringify(d.model.context));
|
|
457
|
+
}
|
|
458
|
+
const describe = (n, kept) => ({ kept, text: JSON.stringify(n) + (contextByType.get(n.type) ?? '') });
|
|
431
459
|
const nodes = [
|
|
432
|
-
...(edited.nodes ?? []).map((n) => (
|
|
433
|
-
...Object.values(edited.subflows ?? {}).flatMap((sf) => (sf?.nodes ?? []).map((n) => (
|
|
460
|
+
...(edited.nodes ?? []).map((n) => describe(n, keptFromOriginal.has(n.id))),
|
|
461
|
+
...Object.values(edited.subflows ?? {}).flatMap((sf) => (sf?.nodes ?? []).map((n) => describe(n, false))),
|
|
434
462
|
];
|
|
435
|
-
|
|
436
|
-
|
|
463
|
+
const spelled = (s) => JSON.stringify(s).slice(1, -1);
|
|
464
|
+
const keyOf = (b) => (typeof b.resourceKey === 'string' ? b.resourceKey : '');
|
|
465
|
+
const all = (edited.bindings ?? []);
|
|
437
466
|
const fromOriginal = new Set((original.bindings ?? []).map(bindingIdentity));
|
|
438
467
|
const inBaseline = new Set((baseline.bindings ?? []).map(bindingIdentity));
|
|
439
468
|
return rows.filter((b) => {
|
|
440
469
|
const identity = bindingIdentity(b);
|
|
441
470
|
if (fromOriginal.has(identity) || !inBaseline.has(identity))
|
|
442
471
|
return true;
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
472
|
+
const key = keyOf(b);
|
|
473
|
+
const others = typeof b.name === 'string'
|
|
474
|
+
? all.filter((o) => o.name === b.name && keyOf(o) !== key)
|
|
475
|
+
: [];
|
|
476
|
+
const placeholder = typeof b.name === 'string' ? spelled(`<bindings.${b.name}>`) : undefined;
|
|
477
|
+
const references = (text) => {
|
|
478
|
+
if (key !== '' && text.includes(spelled(key)))
|
|
479
|
+
return true;
|
|
480
|
+
if (placeholder === undefined || !text.includes(placeholder))
|
|
481
|
+
return false;
|
|
482
|
+
return key === ''
|
|
483
|
+
? !others.some((o) => text.includes(spelled(keyOf(o))))
|
|
484
|
+
: others.length === 0;
|
|
485
|
+
};
|
|
486
|
+
const referencers = nodes.filter((n) => references(n.text));
|
|
487
|
+
return !(referencers.length > 0 && referencers.every((n) => n.kept));
|
|
448
488
|
});
|
|
449
489
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.31.
|
|
3
|
+
"version": "6.31.5",
|
|
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": "19700f105da9eae840ec05cd3796c28a96f1a4ed"
|
|
97
97
|
}
|