@uipath/maestro-builder-sdk 6.19.0 → 6.20.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.
Files changed (41) hide show
  1. package/dist/api-index.md +107 -107
  2. package/dist/api-members.md +358 -356
  3. package/dist/check.js +181 -45
  4. package/dist/cli/commands/flow.js +3 -0
  5. package/dist/compile-cli.js +51 -0
  6. package/dist/core/actions.d.ts +13 -5
  7. package/dist/core/actions.js +1 -1
  8. package/dist/core/binding-identity.d.ts +22 -0
  9. package/dist/core/binding-identity.js +28 -0
  10. package/dist/core/context-index.d.ts +34 -0
  11. package/dist/core/context-index.js +38 -0
  12. package/dist/core/definitionless-node-types.d.ts +16 -0
  13. package/dist/core/definitionless-node-types.js +16 -0
  14. package/dist/core/form-field-type.d.ts +33 -0
  15. package/dist/core/form-field-type.js +30 -0
  16. package/dist/core/hitl-routing.d.ts +8 -0
  17. package/dist/core/hitl-routing.js +17 -1
  18. package/dist/core/process-resource-sort-order.d.ts +40 -0
  19. package/dist/core/process-resource-sort-order.js +44 -0
  20. package/dist/core/wire-expr.d.ts +27 -0
  21. package/dist/core/wire-expr.js +34 -0
  22. package/dist/decompile-cli.js +11 -1
  23. package/dist/decompile.d.ts +8 -3
  24. package/dist/decompile.js +680 -104
  25. package/dist/flow-expr-check.js +1 -1
  26. package/dist/flow-sdk.d.ts +33 -1
  27. package/dist/flow-sdk.js +21 -2
  28. package/dist/flow-step-tree.js +2 -1
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.js +1 -0
  31. package/dist/merge-cli.js +25 -8
  32. package/dist/merge-roundtrip.d.ts +81 -0
  33. package/dist/merge-roundtrip.js +404 -0
  34. package/dist/merge.d.ts +35 -6
  35. package/dist/merge.js +124 -24
  36. package/dist/node-placement.d.ts +93 -0
  37. package/dist/node-placement.js +163 -0
  38. package/dist/nodes/transform/flow/node-type.js +2 -1
  39. package/dist/registry/uip/pipeline-front-door.js +5 -3
  40. package/dist/serialize.js +112 -61
  41. package/package.json +2 -2
@@ -75,7 +75,7 @@ function addStepNames(steps, roots) {
75
75
  for (const s of steps) {
76
76
  // `return` carries a synthetic name; the port-edge kinds carry none at all —
77
77
  // they are edges, not nodes, so there is nothing to reference them by.
78
- if (s.kind !== 'return' && s.kind !== 'stepToRef' && s.kind !== 'stepToList' && s.kind !== 'break')
78
+ if (s.kind !== 'return' && s.kind !== 'stepToRef' && s.kind !== 'stepToList' && s.kind !== 'break' && s.kind !== 'continue')
79
79
  roots.add(s.name);
80
80
  switch (s.kind) {
81
81
  case 'stepToList':
@@ -337,6 +337,13 @@ export type CaseValue = string | number | boolean;
337
337
  export interface SwitchArm {
338
338
  value: CaseValue;
339
339
  label?: string;
340
+ /**
341
+ * The case's wire id — `inputs.cases[].id`, and the `case-<id>` port its arm
342
+ * leaves from. Omitted, it is positional (`case_1`, `case_2`, …). Set it only
343
+ * to keep an id a flow already has (decompile does, for a designer-drawn
344
+ * switch whose ids are `default-1`, …).
345
+ */
346
+ id?: string;
340
347
  body: Step[];
341
348
  }
342
349
  /**
@@ -520,6 +527,14 @@ export type Step = {
520
527
  | {
521
528
  kind: 'break';
522
529
  }
530
+ /**
531
+ * Go on to the enclosing loop/do-while's next iteration through its continue
532
+ * handle — the edge a body's last step gets. Terminal on its path. Only valid
533
+ * inside a container body.
534
+ */
535
+ | {
536
+ kind: 'continue';
537
+ }
523
538
  /**
524
539
  * A fan-out and its join. `arms` is one step list per arm — an ARRAY, because
525
540
  * arms are positional and carry no author-supplied keys — and `name` names the
@@ -958,7 +973,8 @@ declare class StepList {
958
973
  * @param name - The switch node's id.
959
974
  * @param on - The value to compare each case against.
960
975
  * @param cases - One entry per arm, evaluated top to bottom; the first strict
961
- * match wins. `label` names the arm's outgoing edge.
976
+ * match wins. `label` names the arm's outgoing edge. `id` keeps a case's wire
977
+ * id (`inputs.cases[].id`, port `case-<id>`); omitted, it is `case_<n>`.
962
978
  * @param defaultFn - Receives a sub-builder for the arm taken when nothing
963
979
  * matches. Omit it and an unmatched value simply continues.
964
980
  * @param options - Node options; `version` selects the exact definition
@@ -969,6 +985,7 @@ declare class StepList {
969
985
  value: CaseValue;
970
986
  body: (b: ArmBuilder) => void;
971
987
  label?: string;
988
+ id?: string;
972
989
  }[], defaultFn?: (b: StepList) => void, options?: NodeOptions): this;
973
990
  /**
974
991
  * Run two or more arms **in parallel** from this point and join them back
@@ -1053,6 +1070,21 @@ declare class StepList {
1053
1070
  * @returns This builder. Nothing after this call on the same path can run.
1054
1071
  */
1055
1072
  break(): this;
1073
+ /**
1074
+ * Go on to the **next iteration** of the enclosing `.loop()` / `.doWhile()`
1075
+ * through its continue handle — the edge the body's last step gets anyway.
1076
+ * Use it where a path would otherwise end the run: an `.onError()` handler or
1077
+ * an HTTP-branch / outcome list inside the body ends on an End node of its own
1078
+ * unless it says where to go, so "log the failure and skip this item" is
1079
+ * `.onError((h) => h.step('log', …).continue())`. Terminal on its path, like
1080
+ * `.break()`. Compilation fails when there is no enclosing container.
1081
+ *
1082
+ * Not `.stepToRef('<loop>')`: that names the loop as a step and enters it from
1083
+ * its outer input — it restarts the loop, it does not go on to the next item.
1084
+ *
1085
+ * @returns This builder. Nothing after this call on the same path can run.
1086
+ */
1087
+ continue(): this;
1056
1088
  /**
1057
1089
  * Stop the **whole run**, here and now — not just this path.
1058
1090
  *
package/dist/flow-sdk.js CHANGED
@@ -617,7 +617,8 @@ class StepList {
617
617
  * @param name - The switch node's id.
618
618
  * @param on - The value to compare each case against.
619
619
  * @param cases - One entry per arm, evaluated top to bottom; the first strict
620
- * match wins. `label` names the arm's outgoing edge.
620
+ * match wins. `label` names the arm's outgoing edge. `id` keeps a case's wire
621
+ * id (`inputs.cases[].id`, port `case-<id>`); omitted, it is `case_<n>`.
621
622
  * @param defaultFn - Receives a sub-builder for the arm taken when nothing
622
623
  * matches. Omit it and an unmatched value simply continues.
623
624
  * @param options - Node options; `version` selects the exact definition
@@ -635,7 +636,7 @@ class StepList {
635
636
  // An arm's own `.label(...)` wins over the case config's `label`; either
636
637
  // overrides the serializer's derived `Case "<value>"`.
637
638
  const label = arm.armLabel ?? c.label;
638
- return { value: c.value, ...(label !== undefined ? { label } : {}), body: arm.steps };
639
+ return { value: c.value, ...(label !== undefined ? { label } : {}), ...(c.id !== undefined ? { id: c.id } : {}), body: arm.steps };
639
640
  });
640
641
  let dflt;
641
642
  if (defaultFn) {
@@ -765,6 +766,24 @@ class StepList {
765
766
  this.steps.push({ kind: 'break' });
766
767
  return this;
767
768
  }
769
+ /**
770
+ * Go on to the **next iteration** of the enclosing `.loop()` / `.doWhile()`
771
+ * through its continue handle — the edge the body's last step gets anyway.
772
+ * Use it where a path would otherwise end the run: an `.onError()` handler or
773
+ * an HTTP-branch / outcome list inside the body ends on an End node of its own
774
+ * unless it says where to go, so "log the failure and skip this item" is
775
+ * `.onError((h) => h.step('log', …).continue())`. Terminal on its path, like
776
+ * `.break()`. Compilation fails when there is no enclosing container.
777
+ *
778
+ * Not `.stepToRef('<loop>')`: that names the loop as a step and enters it from
779
+ * its outer input — it restarts the loop, it does not go on to the next item.
780
+ *
781
+ * @returns This builder. Nothing after this call on the same path can run.
782
+ */
783
+ continue() {
784
+ this.steps.push({ kind: 'continue' });
785
+ return this;
786
+ }
768
787
  /**
769
788
  * Stop the **whole run**, here and now — not just this path.
770
789
  *
@@ -9,7 +9,7 @@ export function stopsAtEnd(steps) {
9
9
  || (st.kind === 'branch' && (has(st.then, kinds) || has(st.otherwise, kinds)))
10
10
  || ((st.kind === 'switch' || st.kind === 'stepSwitch') && st.cases.some((c) => has(c.body, kinds)))
11
11
  || (st.kind === 'switch' && st.default !== undefined && has(st.default, kinds)));
12
- return has(steps, new Set(['return'])) && !has(steps, new Set(['terminate', 'break']));
12
+ return has(steps, new Set(['return'])) && !has(steps, new Set(['terminate', 'break', 'continue']));
13
13
  }
14
14
  /**
15
15
  * The step lists nested DIRECTLY inside `step` — the bodies a walk over this
@@ -37,6 +37,7 @@ export function childStepLists(step) {
37
37
  return step.arms;
38
38
  case 'action':
39
39
  case 'break':
40
+ case 'continue':
40
41
  case 'terminate':
41
42
  case 'stepToRef':
42
43
  case 'return':
package/dist/index.d.ts CHANGED
@@ -14,7 +14,8 @@ export type { EmitFlowOpts } from './emit.js';
14
14
  export { decompile as decompileFlow } from './decompile.js';
15
15
  export type { DecompileOptions as FlowDecompileOptions } from './decompile.js';
16
16
  export { mergeFlow } from './merge.js';
17
- export type { MergeOptions as FlowMergeOptions } from './merge.js';
17
+ export type { MergeOptions as FlowMergeOptions, MergeFinding as FlowMergeFinding } from './merge.js';
18
+ export { MergeRefusedError as FlowMergeRefusedError } from './merge.js';
18
19
  export { Library } from './library.js';
19
20
  export { Bindings } from './bindings.js';
20
21
  export { check } from './check.js';
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ export { serialize } from './serialize.js';
18
18
  export { emitFlow } from './emit.js';
19
19
  export { decompile as decompileFlow } from './decompile.js';
20
20
  export { mergeFlow } from './merge.js';
21
+ export { MergeRefusedError as FlowMergeRefusedError } from './merge.js';
21
22
  export { Library } from './library.js';
22
23
  export { Bindings } from './bindings.js';
23
24
  export { check } from './check.js';
package/dist/merge-cli.js CHANGED
@@ -3,23 +3,25 @@
3
3
  * merge-cli — merge an edited flow back into the original `.flow` (bin `flow-merge`)
4
4
  *
5
5
  * Usage:
6
- * flow-merge <original.flow> <edited.flow> [-o merged.flow] [--baseline <baseline.flow>]
6
+ * flow-merge <original.flow> <edited.flow> [-o merged.flow] [--baseline <baseline.flow>] [--strict]
7
7
  *
8
8
  * `edited.flow` is compile(decompile(original) after your edits). `--baseline`
9
9
  * is compile(decompile(original)) BEFORE any edit — supplying it enables the
10
10
  * delta merge (untouched nodes keep their original content, placeholder-safe);
11
11
  * omit it for a two-way merge (take the edited graph, re-attach original layout).
12
- * See merge.ts.
12
+ * With `--baseline`, every wire-identity difference between the baseline and
13
+ * the original (what the no-edit round trip changed) is printed as a warning;
14
+ * `--strict` refuses instead (exit 1, nothing written). See merge.ts.
13
15
  */
14
16
  import { reportResult } from './cli-result.js';
15
17
  import { writeJsonFile } from './core/json-file.js';
16
18
  import { readFileSync } from 'node:fs';
17
19
  import { basename, resolve } from 'node:path';
18
- import { mergeFlow } from './merge.js';
20
+ import { MergeRefusedError, mergeFlow } from './merge.js';
19
21
  import { flagValue, runWhenInvokedDirectly } from './cli-run.js';
20
22
  export function run(argv) {
21
23
  if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
22
- console.error('usage: flow-merge <original.flow> <edited.flow> [-o merged.flow] [--baseline <baseline.flow>]');
24
+ console.error('usage: flow-merge <original.flow> <edited.flow> [-o merged.flow] [--baseline <baseline.flow>] [--strict]');
23
25
  return 2;
24
26
  }
25
27
  const flags = new Set(['-o', '--baseline']);
@@ -33,10 +35,25 @@ export function run(argv) {
33
35
  const edited = JSON.parse(readFileSync(editedPath, 'utf8'));
34
36
  const baselinePath = flagValue(argv, '--baseline');
35
37
  const baseline = baselinePath ? JSON.parse(readFileSync(baselinePath, 'utf8')) : undefined;
36
- const merged = mergeFlow(original, edited, {
37
- baseline,
38
- warn: (m) => console.error(`flow-merge: warning: ${m}`),
39
- });
38
+ const strict = argv.includes('--strict');
39
+ if (strict && !baseline) {
40
+ console.error('flow-merge: --strict compares the no-edit round trip with the original; pass --baseline <baseline.flow>');
41
+ return 2;
42
+ }
43
+ let merged;
44
+ try {
45
+ merged = mergeFlow(original, edited, {
46
+ baseline,
47
+ strict,
48
+ warn: (m) => console.error(`flow-merge: warning: ${m}`),
49
+ });
50
+ }
51
+ catch (error) {
52
+ if (!(error instanceof MergeRefusedError))
53
+ throw error;
54
+ console.error(`flow-merge: ${error.message}`);
55
+ return 1;
56
+ }
40
57
  const out = flagValue(argv, '-o') ?? 'merged.flow';
41
58
  writeJsonFile(out, merged);
42
59
  console.log(`flow-merge: wrote ${basename(out)} (${(merged.nodes ?? []).length} nodes, ${(merged.edges ?? []).length} edges)`);
@@ -0,0 +1,81 @@
1
+ /** A node as merge sees it: only the fields these checks read. */
2
+ interface RtNode {
3
+ id: string;
4
+ type: string;
5
+ typeVersion?: string;
6
+ inputs?: Record<string, unknown>;
7
+ [k: string]: unknown;
8
+ }
9
+ /** An edge as merge sees it. */
10
+ interface RtEdge {
11
+ id?: string;
12
+ sourceNodeId: string;
13
+ sourcePort: string;
14
+ targetNodeId: string;
15
+ targetPort: string;
16
+ [k: string]: unknown;
17
+ }
18
+ /** A `.flow` file as merge sees it. */
19
+ interface RtFlow {
20
+ nodes?: RtNode[];
21
+ edges?: RtEdge[];
22
+ definitions?: Array<{
23
+ nodeType?: string;
24
+ [k: string]: unknown;
25
+ }>;
26
+ subflows?: Record<string, unknown>;
27
+ bindings?: Array<{
28
+ id?: string;
29
+ [k: string]: unknown;
30
+ }>;
31
+ [k: string]: unknown;
32
+ }
33
+ /** One difference, or one inconsistency in the merged file. */
34
+ export interface MergeFinding {
35
+ /** Which comparison found it. */
36
+ kind: 'node-removed' | 'node-added' | 'node-type' | 'implicit-end' | 'edge-handle-renamed' | 'edge-rewired' | 'edge-removed' | 'edge-added' | 'handle-ids' | 'binding-removed' | 'binding-added' | 'undeclared-handle' | 'duplicate-binding';
37
+ /** The finding, phrased for the author, naming the node, edge or row. */
38
+ message: string;
39
+ /**
40
+ * Whether `strict` refuses the merge over it. False for `implicit-end` and
41
+ * `binding-removed`, which leave the merged file doing what the original does.
42
+ */
43
+ refuses: boolean;
44
+ }
45
+ /**
46
+ * Every wire-identity difference between the original and its no-edit round
47
+ * trip that the merged file still carries, phrased as what the merge writes.
48
+ *
49
+ * A difference the author's edit undid is not reported: an edge the round trip
50
+ * dropped that the merged file has again, an edge or node the round trip added
51
+ * that the merged file lacks, a node whose type or handles the round trip
52
+ * changed that the merged file no longer has (or has with the original's).
53
+ *
54
+ * @param original - The file being merged into.
55
+ * @param baseline - compile(decompile(original)) before any edit.
56
+ * @param merged - The merged file, before it is written.
57
+ * @returns One finding per difference, in a stable order.
58
+ */
59
+ export declare function roundTripFindings(original: RtFlow, baseline: RtFlow, merged: RtFlow): MergeFinding[];
60
+ /**
61
+ * Inconsistencies in the merged file that come from mixing its sources: a root
62
+ * edge leaving a handle its source node does not declare, and two binding rows
63
+ * binding the same resource property.
64
+ *
65
+ * A node with no definition in `merged.definitions` (a sticky note, a type
66
+ * neither input carried) is not judged. Neither is anything the original
67
+ * already had — an edge it carries verbatim, or as many same-identity binding
68
+ * rows as it already holds — because the merge did not cause it.
69
+ *
70
+ * @param merged - The merged file.
71
+ * @param original - The file merged into.
72
+ * @returns One finding per inconsistency.
73
+ */
74
+ export declare function mergedFileFindings(merged: RtFlow, original?: RtFlow): MergeFinding[];
75
+ /** Thrown by `mergeFlow` under `strict` when a finding refuses the merge. */
76
+ export declare class MergeRefusedError extends Error {
77
+ /** Every refusing finding, in report order. */
78
+ readonly findings: readonly MergeFinding[];
79
+ constructor(findings: readonly MergeFinding[]);
80
+ }
81
+ export {};