@uipath/maestro-builder-sdk 6.11.2 → 6.11.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/check.js CHANGED
@@ -11,8 +11,9 @@ import { isLookupToken, resolvedValue, unresolvedLookupMessage, } from './core/l
11
11
  import { EVENT_FILTER_OPERATORS, readEventFilter, eventFilterProblem } from './event-filters.js';
12
12
  import { extractRefs } from './core/expr-check.js';
13
13
  import { bindingSelfNameMessage, bindingUndeclaredMessage, undeclaredBinding } from './core/binding-messages.js';
14
+ import { isAnswerField } from './core/hitl-answers.js';
14
15
  import { hitlDerivesOutcomeHandles, hitlExitModel, hitlRoutesPerOutcome } from './core/hitl-routing.js';
15
- import { declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
16
+ import { childStepLists, declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
16
17
  import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
17
18
  import { compareSchemaVersions, schemaVersionRefusal } from './schema-version.js';
18
19
  import { prepareCommand, resolveFlagArg } from './core/cli-spelling.js';
@@ -1644,20 +1645,7 @@ function checkLoopListEnvelope(loop, connectors, opts, diags) {
1644
1645
  }
1645
1646
  /** True if any step on THIS flow's own tree is a `.return()`. */
1646
1647
  function hasReturn(steps) {
1647
- for (const s of steps) {
1648
- if (s.kind === 'return')
1649
- return true;
1650
- if (s.kind === 'branch' && (hasReturn(s.then) || hasReturn(s.otherwise)))
1651
- return true;
1652
- if (s.kind === 'switch'
1653
- && (s.cases.some((c) => hasReturn(c.body)) || hasReturn(s.default ?? [])))
1654
- return true;
1655
- if (s.kind === 'parallel' && s.arms.some(hasReturn))
1656
- return true;
1657
- if ((s.kind === 'loop' || s.kind === 'doWhile') && hasReturn(s.body))
1658
- return true;
1659
- }
1660
- return false;
1648
+ return steps.some((s) => s.kind === 'return' || childStepLists(s).some(hasReturn));
1661
1649
  }
1662
1650
  /**
1663
1651
  * Closest of `candidates` to `name`: same word ignoring case, one contained in
@@ -4777,9 +4765,9 @@ function checkHitl(step, inputs, diags) {
4777
4765
  + `gets a text box and the value comes back as a string. Valid: `
4778
4766
  + `${FORM_FIELD_TYPES.join(', ')}.`, nearest !== undefined ? `type: '${nearest}'` : `type: 'text'`);
4779
4767
  }
4768
+ if (isAnswerField(f))
4769
+ answers++; // an `output`, or an `inOut` whose reviewed value comes back
4780
4770
  if (f?.direction === 'input' || f?.direction === 'inOut') {
4781
- if (f.direction === 'inOut')
4782
- answers++; // the reviewed value comes back
4783
4771
  const value = f.value;
4784
4772
  if (value === undefined || value === null) {
4785
4773
  at('HITL_FIELD_NO_VALUE', `Human task "${step}" shows the form field "${id}" to the reviewer but gives it no value, `
@@ -4800,10 +4788,7 @@ function checkHitl(step, inputs, diags) {
4800
4788
  + `Compute it in a script step first and point the field at that step's output.`, `value: out('<scriptStep>')`);
4801
4789
  }
4802
4790
  }
4803
- else if (f?.direction === 'output') {
4804
- answers++;
4805
- }
4806
- else {
4791
+ else if (f?.direction !== 'output') {
4807
4792
  at('HITL_FIELD_DIRECTION', `Human task "${step}" gives the form field "${id}" the direction `
4808
4793
  + `${JSON.stringify(f?.direction)}. A field is shown to the `
4809
4794
  + `reviewer ('input'), filled in by them ('output'), or pre-filled and editable ('inOut'); `
@@ -4926,7 +4911,7 @@ function checkHitlRead(name, field, rest, form, step, diags) {
4926
4911
  if (answer === 'Action')
4927
4912
  return; // which outcome was pressed.
4928
4913
  const answers = (form?.fields ?? [])
4929
- .filter((f) => f?.direction === 'output' && typeof f?.id === 'string')
4914
+ .filter((f) => isAnswerField(f) && typeof f?.id === 'string')
4930
4915
  .map((f) => f.id);
4931
4916
  if (answers.includes(answer))
4932
4917
  return;
@@ -4938,7 +4923,7 @@ function checkHitlRead(name, field, rest, form, step, diags) {
4938
4923
  level: 'error',
4939
4924
  code: 'HITL_READ_UNKNOWN_FIELD',
4940
4925
  message: `Human task "${name}" has no answer "${answer}" (read as "$vars.${name}.output.${answer}" in `
4941
- + `"${step}"). Its result carries only the fields the reviewer FILLS IN`
4926
+ + `"${step}"). Its result carries only the fields the reviewer FILLS IN or EDITS`
4942
4927
  + `${answers.length > 0 ? ` (${answers.join(', ')})` : ' (it declares none)'} plus "Action". `
4943
4928
  + (shown.includes(answer)
4944
4929
  ? `"${answer}" is a field the reviewer only reads, so it is not part of the answer — read the `
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Which form fields of a human task come back in its answer object — the one
3
+ * rule `serialize` (the emitted `outputs.output.properties`) and `check` (the
4
+ * answer count and every `out('<task>', '<field>')` read) all use, so they
5
+ * cannot drift. They did drift (UV-16855): `serialize` emitted `inOut` fields
6
+ * as answers and `check` counted them as answers, but the read check listed
7
+ * `output` fields only, so the documented read of an editable field —
8
+ * `out('review', 'comment')` for `{ id: 'comment', direction: 'inOut', … }` —
9
+ * failed `check` and blocked `compile`.
10
+ *
11
+ * - `output` — the reviewer fills it in; the value comes back.
12
+ * - `inOut` — pre-filled and editable; the (possibly changed) value comes back.
13
+ * - `input` — shown only; NOT an answer. Read the value bound to it instead.
14
+ */
15
+ export type AnswerDirection = 'output' | 'inOut';
16
+ /** True when the field's value comes back in the task's answer object. */
17
+ export declare function isAnswerField(field: {
18
+ direction?: unknown;
19
+ } | null | undefined): boolean;
@@ -0,0 +1,4 @@
1
+ /** True when the field's value comes back in the task's answer object. */
2
+ export function isAnswerField(field) {
3
+ return field?.direction === 'output' || field?.direction === 'inOut';
4
+ }
@@ -42,4 +42,16 @@ export declare function hasExits(r: DeclaredExit[] | NoExits): r is DeclaredExit
42
42
  * `.parallel` join waiting: a terminate ends the run, join included.
43
43
  */
44
44
  export declare function stopsAtEnd(steps: readonly Step[]): boolean;
45
+ /**
46
+ * The step lists nested DIRECTLY inside `step` — the bodies a walk over this
47
+ * flow's own tree must descend into. Exhaustive over `Step['kind']`, so a new
48
+ * container kind fails to compile here instead of being silently skipped by
49
+ * every walker. That is how `check`'s return scan came to miss `.stepSwitch`
50
+ * arms and `.stepToList` / `.onError` bodies, and warned NO_RETURN on flows
51
+ * whose every path ends in `.return()` (UV-16855).
52
+ *
53
+ * A subflow's child flow is deliberately NOT a child here: it is another
54
+ * flow's tree, and its returns say nothing about whether THIS flow ends.
55
+ */
56
+ export declare function childStepLists(step: Step): readonly Step[][];
45
57
  export {};
@@ -107,3 +107,40 @@ export function stopsAtEnd(steps) {
107
107
  || (st.kind === 'switch' && st.default !== undefined && has(st.default, kinds)));
108
108
  return has(steps, new Set(['return'])) && !has(steps, new Set(['terminate', 'break']));
109
109
  }
110
+ /**
111
+ * The step lists nested DIRECTLY inside `step` — the bodies a walk over this
112
+ * flow's own tree must descend into. Exhaustive over `Step['kind']`, so a new
113
+ * container kind fails to compile here instead of being silently skipped by
114
+ * every walker. That is how `check`'s return scan came to miss `.stepSwitch`
115
+ * arms and `.stepToList` / `.onError` bodies, and warned NO_RETURN on flows
116
+ * whose every path ends in `.return()` (UV-16855).
117
+ *
118
+ * A subflow's child flow is deliberately NOT a child here: it is another
119
+ * flow's tree, and its returns say nothing about whether THIS flow ends.
120
+ */
121
+ export function childStepLists(step) {
122
+ switch (step.kind) {
123
+ case 'branch':
124
+ return [step.then, step.otherwise];
125
+ case 'switch':
126
+ return [...step.cases.map((c) => c.body), ...(step.default ? [step.default] : [])];
127
+ case 'stepSwitch':
128
+ return step.cases.map((c) => c.body);
129
+ case 'loop':
130
+ case 'doWhile':
131
+ case 'stepToList':
132
+ return [step.body];
133
+ case 'parallel':
134
+ return step.arms;
135
+ case 'action':
136
+ case 'break':
137
+ case 'terminate':
138
+ case 'stepToRef':
139
+ case 'return':
140
+ return [];
141
+ default: {
142
+ const unhandled = step;
143
+ throw new Error(`childStepLists: unhandled step kind ${JSON.stringify(unhandled.kind)}`);
144
+ }
145
+ }
146
+ }
package/dist/serialize.js CHANGED
@@ -14,6 +14,7 @@ import { Expr, toExpr, SCHEDULE_PRESETS, DELAY_PRESETS, parseIxpProjectType, fla
14
14
  import { FlowAction, FlowTrigger } from './core/node-classes.js';
15
15
  import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
16
16
  import { dataFabricUnknownInputs } from './core/typed-raw-node.js';
17
+ import { isAnswerField } from './core/hitl-answers.js';
17
18
  import { BindingRefusal, GUID_RE, bindingSelfNameMessage, bindingUndeclaredMessage, undeclaredBinding } from './core/binding-messages.js';
18
19
  import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
19
20
  import { declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
@@ -2800,7 +2801,7 @@ function hitlInputs(inputs, nodeId, flowId, label, rename) {
2800
2801
  const properties = {};
2801
2802
  for (const f of inputs?.fields ?? []) {
2802
2803
  // inOut fields land in the answers too — their reviewed value flows back.
2803
- if (f.direction !== 'output' && f.direction !== 'inOut')
2804
+ if (!isAnswerField(f))
2804
2805
  continue;
2805
2806
  properties[f.id] = { ...FORM_FIELD_JSON_TYPE[f.type] };
2806
2807
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.11.2",
3
+ "version": "6.11.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",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "0e144a44d84cd717eaec74c8c43fe864026e7339"
95
+ "gitref": "e1b0e818f78b7911c691e12ea078d03c851daf76"
96
96
  }