@uipath/maestro-builder-sdk 6.11.1 → 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 +8 -23
- package/dist/core/hitl-answers.d.ts +19 -0
- package/dist/core/hitl-answers.js +4 -0
- package/dist/core/step-ports.d.ts +12 -0
- package/dist/core/step-ports.js +37 -0
- package/dist/registry/library-build/events.js +19 -1
- package/dist/serialize.js +2 -1
- package/package.json +2 -2
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
|
-
|
|
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
|
|
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
|
|
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;
|
|
@@ -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 {};
|
package/dist/core/step-ports.js
CHANGED
|
@@ -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
|
+
}
|
|
@@ -294,9 +294,27 @@ export function eventFacts(node, objectRow) {
|
|
|
294
294
|
eventMode: pyStr(pyOr(get(node, "eventMode"), "polling")),
|
|
295
295
|
byoaConnection: truthy(fact("ByoaConnection", "byoaConnection", false)),
|
|
296
296
|
isWebhookUrlVisible: truthy(fact("IsWebhookUrlVisible", "isWebhookUrlVisible", false)),
|
|
297
|
-
textBlocks: pyIter(textBlocks).map(
|
|
297
|
+
textBlocks: pyIter(textBlocks).map(textBlockText),
|
|
298
298
|
};
|
|
299
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* One `Design.TextBlocks` entry as display text. The tenant answers with
|
|
302
|
+
* records — `{ Name, Text, Position }` (every Slack event object carries
|
|
303
|
+
* `{ Name: 'defaultMessage', Text: 'Add this webhook URL to your Slack app. …',
|
|
304
|
+
* Position: 'top' }`) — so the text is the record's `Text`. A bare string is
|
|
305
|
+
* kept as is. Anything else still goes through `pyStr`, which refuses it
|
|
306
|
+
* loudly: the Python's `str(t)` printed a dict repr into the webhook note, and
|
|
307
|
+
* an unknown shape should fail the same way this one did rather than print
|
|
308
|
+
* something plausible.
|
|
309
|
+
*/
|
|
310
|
+
function textBlockText(block) {
|
|
311
|
+
if (isRecord(block)) {
|
|
312
|
+
const text = pyOr(get(block, "Text"), get(block, "text"));
|
|
313
|
+
if (typeof text === "string")
|
|
314
|
+
return text;
|
|
315
|
+
}
|
|
316
|
+
return pyStr(block);
|
|
317
|
+
}
|
|
300
318
|
// ---------------------------------------------------------------------------
|
|
301
319
|
// The generator's cached event calls and its event passes
|
|
302
320
|
// ---------------------------------------------------------------------------
|
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
|
|
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.
|
|
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": "
|
|
95
|
+
"gitref": "e1b0e818f78b7911c691e12ea078d03c851daf76"
|
|
96
96
|
}
|