@uipath/maestro-builder-sdk 6.15.3 → 6.15.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/README.md +3 -1
- package/dist/api-index.md +48 -48
- package/dist/api-members.md +81 -81
- package/dist/bpmn/check-cli.js +4 -3
- package/dist/check.js +181 -18
- package/dist/cli-result.d.ts +14 -0
- package/dist/cli-result.js +18 -0
- package/dist/core/expr.d.ts +8 -2
- package/dist/core/expr.js +8 -2
- package/dist/core/global-names.d.ts +5 -7
- package/dist/core/global-names.js +5 -14
- package/dist/decompile.js +2 -2
- package/dist/flow-sdk.d.ts +27 -4
- package/dist/flow-sdk.js +24 -7
- package/dist/flow-variables.d.ts +66 -0
- package/dist/flow-variables.js +84 -0
- package/dist/registry/path-cli.js +3 -3
- package/dist/registry/search-cli.js +2 -2
- package/dist/serialize.js +27 -17
- package/package.json +2 -2
package/dist/flow-variables.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { globalNameCollisionMessage, globalNameCollisions } from './core/global-names.js';
|
|
1
2
|
const CONTAINER_KEYS = new Set(['globals', 'nodes', 'variableUpdates']);
|
|
2
3
|
const DIRECTIONS = new Set(['in', 'out', 'inout']);
|
|
3
4
|
/** Read both supported Flow variable spellings into one declaration table. */
|
|
@@ -40,3 +41,86 @@ export function readFlowGlobals(variables, strict = false) {
|
|
|
40
41
|
}
|
|
41
42
|
return globals;
|
|
42
43
|
}
|
|
44
|
+
const sameJson = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
45
|
+
/**
|
|
46
|
+
* Turn a flow's `.input()` / `.output()` / `.var()` declarations into the
|
|
47
|
+
* globals the `.flow` file will carry — one per id, because the product's
|
|
48
|
+
* `flow validate` rejects a repeated id (`[variables.globals] Duplicate variable
|
|
49
|
+
* ID`), and the three methods share that one namespace.
|
|
50
|
+
*
|
|
51
|
+
* **An output and a var with the same name are one variable** (flow-builder-sdk#899).
|
|
52
|
+
* The natural loop accumulator is
|
|
53
|
+
* `.output({ product: types.number }).var('product', types.number, 1)`: declare
|
|
54
|
+
* the result, then seed it. Both declarations describe the same value, so they
|
|
55
|
+
* merge into ONE `direction: 'out'` global that carries the var's default.
|
|
56
|
+
*
|
|
57
|
+
* Why `out` and not `inout`, measured against `@uipath/flow-converter` 0.69 and
|
|
58
|
+
* `@uipath/maestro-sdk` (the code that turns a `.flow` into what runs):
|
|
59
|
+
* - only an `out` global is a flow OUTPUT at the root — `buildNodeOutputMappings`
|
|
60
|
+
* drops an End node's mapping for any id that is not `direction: 'out'`;
|
|
61
|
+
* - `inout` is published as an INPUT too — solution discovery puts it on the
|
|
62
|
+
* entry point's input schema — so `inout` would widen the caller's contract;
|
|
63
|
+
* - `{ updates }` on an `out` global is the same output mapping (`var: <id>`) as
|
|
64
|
+
* on an `inout` one, so a loop body can read and rewrite it mid-run;
|
|
65
|
+
* - the `default` on `<uipath:output>` is serialized (`collectVariablesFromNodes`)
|
|
66
|
+
* and a subflow seeds its `out` globals from `defaultValue ?? null`
|
|
67
|
+
* (`buildSeedTask`). The v1 CLI's `variable add --direction out
|
|
68
|
+
* --default-value` writes the same shape.
|
|
69
|
+
*
|
|
70
|
+
* Metadata: the output's `description` / `subType` / `schema` win, falling back
|
|
71
|
+
* to the var's; the default is whichever side declared one. A disagreement the
|
|
72
|
+
* merge would have to resolve by picking a side — a different `type`, two
|
|
73
|
+
* different defaults, two different `subType`s or `schema`s — is
|
|
74
|
+
* `OUTPUT_VAR_MISMATCH` instead, because silently choosing one changes what the
|
|
75
|
+
* flow computes. Every other repeated name (two vars, two outputs, an input
|
|
76
|
+
* reused as an output or var) stays `VARIABLE_NAME_COLLISION`
|
|
77
|
+
* (`core/global-names.ts`, flow-builder-sdk#890).
|
|
78
|
+
*/
|
|
79
|
+
export function planFlowGlobals(decl) {
|
|
80
|
+
const problems = [];
|
|
81
|
+
const varsByName = new Map(decl.vars.map((d) => [d.name, d]));
|
|
82
|
+
const mergeable = new Set();
|
|
83
|
+
for (const collision of globalNameCollisions(decl.inputs, decl.outputs, decl.vars)) {
|
|
84
|
+
const pair = collision.kinds.length === 2 && collision.kinds[0] === 'output' && collision.kinds[1] === 'var';
|
|
85
|
+
if (pair)
|
|
86
|
+
mergeable.add(collision.name);
|
|
87
|
+
else
|
|
88
|
+
problems.push({ code: 'VARIABLE_NAME_COLLISION', name: collision.name, message: globalNameCollisionMessage(collision) });
|
|
89
|
+
}
|
|
90
|
+
const merged = [];
|
|
91
|
+
const outputs = decl.outputs.map((o) => {
|
|
92
|
+
const vd = varsByName.get(o.name);
|
|
93
|
+
if (!vd || !mergeable.has(o.name))
|
|
94
|
+
return o;
|
|
95
|
+
const clash = [];
|
|
96
|
+
if (o.type !== vd.type)
|
|
97
|
+
clash.push(`the output is ${o.type} and the var is ${vd.type}`);
|
|
98
|
+
if (o.default !== undefined && vd.default !== undefined && !sameJson(o.default, vd.default))
|
|
99
|
+
clash.push(`the output's default is ${JSON.stringify(o.default)} and the var's is ${JSON.stringify(vd.default)}`);
|
|
100
|
+
if (o.subType !== undefined && vd.subType !== undefined && o.subType !== vd.subType)
|
|
101
|
+
clash.push(`the output's subType is ${JSON.stringify(o.subType)} and the var's is ${JSON.stringify(vd.subType)}`);
|
|
102
|
+
if (o.schema !== undefined && vd.schema !== undefined && !sameJson(o.schema, vd.schema))
|
|
103
|
+
clash.push(`the output and the var declare different schemas`);
|
|
104
|
+
if (clash.length) {
|
|
105
|
+
problems.push({
|
|
106
|
+
code: 'OUTPUT_VAR_MISMATCH', name: o.name,
|
|
107
|
+
message: `"${o.name}" is declared by both .output() and .var(), which the SDK merges into one output `
|
|
108
|
+
+ `variable, but ${clash.join('; ')}. Make the two declarations agree, or drop the .var().`,
|
|
109
|
+
suggestion: `An output is assignable with { updates } on its own; declare its starting value with `
|
|
110
|
+
+ `.output({ ${o.name}: { type: types.${o.type}, default: … } }).`,
|
|
111
|
+
});
|
|
112
|
+
return o;
|
|
113
|
+
}
|
|
114
|
+
merged.push(o.name);
|
|
115
|
+
return {
|
|
116
|
+
...o,
|
|
117
|
+
...(o.default === undefined && vd.default !== undefined ? { default: vd.default } : {}),
|
|
118
|
+
...(o.description === undefined && vd.description !== undefined ? { description: vd.description } : {}),
|
|
119
|
+
...(o.subType === undefined && vd.subType !== undefined ? { subType: vd.subType } : {}),
|
|
120
|
+
...(o.schema === undefined && vd.schema !== undefined ? { schema: vd.schema } : {}),
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
const mergedSet = new Set(merged);
|
|
124
|
+
const vars = decl.vars.filter((vd) => !mergedSet.has(vd.name));
|
|
125
|
+
return { outputs, vars, merged, problems };
|
|
126
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { reportResult } from '../cli-result.js';
|
|
1
|
+
import { printResult, reportResult } from '../cli-result.js';
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { CURRENT_LINK, PULL_COMMAND, currentEntrySha, libraryCacheRoot, resolveCachedLibrary, resolveCachedMarkdown, } from "./cache.js";
|
|
4
4
|
/**
|
|
@@ -37,7 +37,7 @@ export async function run(argv) {
|
|
|
37
37
|
console.error(`No connector library in the cache yet. Run \`${PULL_COMMAND}\`.`);
|
|
38
38
|
return 1;
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
printResult(value);
|
|
41
41
|
return 0;
|
|
42
42
|
};
|
|
43
43
|
if (argv.includes("--library-json"))
|
|
@@ -56,7 +56,7 @@ export async function run(argv) {
|
|
|
56
56
|
libraryMarkdown: libraryMarkdown ?? null,
|
|
57
57
|
};
|
|
58
58
|
reportResult(all);
|
|
59
|
-
|
|
59
|
+
printResult(JSON.stringify(all, null, 2));
|
|
60
60
|
// Not an error: a caller asking for the whole picture is entitled to be told
|
|
61
61
|
// the cache is empty, rather than getting a non-zero exit for a plain report.
|
|
62
62
|
return 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { reportResult } from '../cli-result.js';
|
|
1
|
+
import { printResult, reportResult } from '../cli-result.js';
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import { PULL_COMMAND, resolveLibraryDir } from "./cache.js";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -155,7 +155,7 @@ export async function run(argv) {
|
|
|
155
155
|
limit,
|
|
156
156
|
});
|
|
157
157
|
reportResult(result);
|
|
158
|
-
|
|
158
|
+
printResult(JSON.stringify(result, null, 2));
|
|
159
159
|
return 0;
|
|
160
160
|
}
|
|
161
161
|
catch (error) {
|
package/dist/serialize.js
CHANGED
|
@@ -16,7 +16,6 @@ import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
|
|
|
16
16
|
import { dataFabricUnknownInputs } from './core/typed-raw-node.js';
|
|
17
17
|
import { isAnswerField } from './core/hitl-answers.js';
|
|
18
18
|
import { connectionConnectors } from './bindings-v2.js';
|
|
19
|
-
import { globalNameCollisionMessage, globalNameCollisions } from './core/global-names.js';
|
|
20
19
|
import { BindingRefusal, GUID_RE, bindingMissingMessage, bindingSelfNameMessage, bindingUndeclaredMessage, missingBindingLabels, undeclaredBinding } from './core/binding-messages.js';
|
|
21
20
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
22
21
|
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
|
|
@@ -46,6 +45,7 @@ import { declaredScriptShape, inferScriptShape } from './core/script-return.js';
|
|
|
46
45
|
import { migrateToSchemaVersion } from './migrate.js';
|
|
47
46
|
import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
|
|
48
47
|
import { resolveSchemaVersion } from './schema-version.js';
|
|
48
|
+
import { planFlowGlobals } from './flow-variables.js';
|
|
49
49
|
import { prepareCommand } from './core/cli-spelling.js';
|
|
50
50
|
import { QUEUE_ITEM_RECORD_SCHEMA } from './core/queue-record.js';
|
|
51
51
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
@@ -3485,12 +3485,6 @@ function refuseUnverifiedByoa(opts, where, sub) {
|
|
|
3485
3485
|
if (message)
|
|
3486
3486
|
throw new ByoaRefusal(message);
|
|
3487
3487
|
}
|
|
3488
|
-
/** Refuse a name declared twice across `.input()` / `.output()` / `.var()` — one `variables.globals[]` id each. */
|
|
3489
|
-
function refuseGlobalNameCollisions(inputs, outputs, vars) {
|
|
3490
|
-
const [first] = globalNameCollisions(inputs, outputs, vars);
|
|
3491
|
-
if (first)
|
|
3492
|
-
throw new Error(globalNameCollisionMessage(first));
|
|
3493
|
-
}
|
|
3494
3488
|
/**
|
|
3495
3489
|
* Refuse a connector-bound node (connector step, event trigger, `.entryPoint`
|
|
3496
3490
|
* onEvent, `waitForEvent`) that names no `connection` or no `folder` label.
|
|
@@ -3957,6 +3951,24 @@ function misplacedLookupMessage(token) {
|
|
|
3957
3951
|
`a lookup() must be the whole value of a connector input, or an element of an array input. ` +
|
|
3958
3952
|
`Emitting it here would send a raw {"__lookup": …} object where the connector expects an id.`);
|
|
3959
3953
|
}
|
|
3954
|
+
/**
|
|
3955
|
+
* The flow's declarations as the globals it will emit: a same-named `.output()`
|
|
3956
|
+
* and `.var()` folded into one `out` global (flow-builder-sdk#899), every other
|
|
3957
|
+
* repeated name refused. `check()` reports the same problems as
|
|
3958
|
+
* VARIABLE_NAME_COLLISION / OUTPUT_VAR_MISMATCH; this throws too, so a path that skips the static pass
|
|
3959
|
+
* (`compile --no-check`, `emitFlow`, a direct `serialize()`) cannot write a
|
|
3960
|
+
* file `flow validate` rejects for a duplicate variable id.
|
|
3961
|
+
*/
|
|
3962
|
+
function emittableGlobals(built, where) {
|
|
3963
|
+
// Entry-point inputs are rows of the same globals[], so they share the
|
|
3964
|
+
// namespace; `check` reports those as ENTRY_POINT_INPUT_COLLISION.
|
|
3965
|
+
const inputs = [...built.inputs, ...(built.entryPoints ?? []).flatMap((ep) => ep.inputs)];
|
|
3966
|
+
const plan = planFlowGlobals({ inputs, outputs: built.outputs, vars: built.vars });
|
|
3967
|
+
if (plan.problems.length) {
|
|
3968
|
+
throw new Error(`${where}: ${plan.problems.map((p) => `[${p.code}] ${p.message}`).join(' ')}`);
|
|
3969
|
+
}
|
|
3970
|
+
return plan;
|
|
3971
|
+
}
|
|
3960
3972
|
function newScope(outputs, vars = []) {
|
|
3961
3973
|
return {
|
|
3962
3974
|
nodes: [],
|
|
@@ -4280,7 +4292,8 @@ export function serialize(built, opts = {}) {
|
|
|
4280
4292
|
*/
|
|
4281
4293
|
const sidecars = opts.sidecars ?? [];
|
|
4282
4294
|
const subflows = {};
|
|
4283
|
-
const
|
|
4295
|
+
const rootGlobals = emittableGlobals(built, `flow "${built.id}"`);
|
|
4296
|
+
const root = newScope(rootGlobals.outputs, rootGlobals.vars);
|
|
4284
4297
|
// `input('x')` lowers eagerly to `$vars.start.output.x` — `start` being the
|
|
4285
4298
|
// trigger node's default id. When the flow renames the trigger, register that
|
|
4286
4299
|
// rename so the SAME pass that rewrites step-name references rewrites these
|
|
@@ -4404,7 +4417,8 @@ export function serialize(built, opts = {}) {
|
|
|
4404
4417
|
* a null. It is emitted here, always, so it cannot be forgotten.
|
|
4405
4418
|
*/
|
|
4406
4419
|
function emitSubflowBody(child, nodeId) {
|
|
4407
|
-
const
|
|
4420
|
+
const childGlobals = emittableGlobals(child, `subflow "${nodeId}"`);
|
|
4421
|
+
const scope = newScope(childGlobals.outputs, childGlobals.vars);
|
|
4408
4422
|
// Claim this copy's node ids UP FRONT, so the rename map is complete before
|
|
4409
4423
|
// the first expression renders. A child's step names are free the first
|
|
4410
4424
|
// time it runs; if any of them is already taken — which is what a second
|
|
@@ -4443,13 +4457,12 @@ export function serialize(built, opts = {}) {
|
|
|
4443
4457
|
for (const t of tails)
|
|
4444
4458
|
addEdge(scope, t, endId);
|
|
4445
4459
|
}
|
|
4446
|
-
refuseGlobalNameCollisions(child.inputs, child.outputs, child.vars);
|
|
4447
4460
|
const globals = [];
|
|
4448
4461
|
for (const inp of child.inputs)
|
|
4449
4462
|
globals.push({ id: inp.name, name: inp.name, direction: 'in', type: inp.type, triggerNodeId: startId, ...varMeta(inp) });
|
|
4450
|
-
for (const o of
|
|
4463
|
+
for (const o of childGlobals.outputs)
|
|
4451
4464
|
globals.push({ id: o.name, name: o.name, direction: 'out', type: o.type, ...varMeta(o) });
|
|
4452
|
-
for (const vd of
|
|
4465
|
+
for (const vd of childGlobals.vars)
|
|
4453
4466
|
globals.push({ id: vd.name, name: vd.name, direction: 'inout', type: vd.type, ...varMeta(vd) });
|
|
4454
4467
|
resolveRejoins(scope);
|
|
4455
4468
|
assertHitlExitInvariant(scope.nodes, scope.edges);
|
|
@@ -6531,16 +6544,13 @@ export function serialize(built, opts = {}) {
|
|
|
6531
6544
|
}
|
|
6532
6545
|
}
|
|
6533
6546
|
}
|
|
6534
|
-
// Entry-point inputs are rows of the same globals[] (pushed below), so they
|
|
6535
|
-
// share the namespace; `check` reports these as ENTRY_POINT_INPUT_COLLISION.
|
|
6536
|
-
refuseGlobalNameCollisions([...built.inputs, ...entryPoints.flatMap((ep) => ep.inputs)], built.outputs, built.vars);
|
|
6537
6547
|
const globals = [];
|
|
6538
6548
|
const triggerNodeId = built.triggerId ?? 'start';
|
|
6539
6549
|
for (const inp of built.inputs)
|
|
6540
6550
|
globals.push({ id: inp.name, name: inp.name, direction: 'in', type: inp.type, triggerNodeId, ...varMeta(inp) });
|
|
6541
|
-
for (const o of
|
|
6551
|
+
for (const o of rootGlobals.outputs)
|
|
6542
6552
|
globals.push({ id: o.name, name: o.name, direction: 'out', type: o.type, ...varMeta(o) });
|
|
6543
|
-
for (const vd of
|
|
6553
|
+
for (const vd of rootGlobals.vars)
|
|
6544
6554
|
globals.push({ id: vd.name, name: vd.name, direction: 'inout', type: vd.type, ...varMeta(vd) });
|
|
6545
6555
|
for (const ep of entryPoints) {
|
|
6546
6556
|
for (const inp of ep.inputs) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.15.
|
|
3
|
+
"version": "6.15.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",
|
|
@@ -92,5 +92,5 @@
|
|
|
92
92
|
"@types/node": "^22.7.0",
|
|
93
93
|
"esbuild": "^0.28.1"
|
|
94
94
|
},
|
|
95
|
-
"gitref": "
|
|
95
|
+
"gitref": "7c0103ce6f6d970156e15bbc3bae0a3f88ca4195"
|
|
96
96
|
}
|