@uipath/maestro-builder-sdk 6.49.1 → 6.49.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/core/connector-inputs.js +57 -2
- package/dist/registry/prepare/inherited-profile.d.ts +14 -0
- package/dist/registry/prepare/inherited-profile.js +28 -0
- package/dist/registry/prepare-cli.js +4 -0
- package/dist/registry/uip/commands.d.ts +1 -0
- package/dist/registry/uip/commands.js +3 -0
- package/package.json +2 -2
|
@@ -106,10 +106,12 @@ export function buildConnectorInputs(rc, inputs, opts) {
|
|
|
106
106
|
// container the runtime composes from `bodyParameters`, so it is listed without
|
|
107
107
|
// a value and is never an author input — see `readFields` in core/library.ts.
|
|
108
108
|
const partValues = new Map();
|
|
109
|
+
const bare = bareArraySpellings(fields, byName);
|
|
109
110
|
for (const f of fields) {
|
|
110
|
-
const
|
|
111
|
+
const flatKey = flatInputKey(inputs, f.name, bare, dialect);
|
|
112
|
+
const flat = flatKey !== undefined;
|
|
111
113
|
let nested = flat
|
|
112
|
-
? { found: true, value: inputs[
|
|
114
|
+
? { found: true, value: inputs[flatKey], projectedArrays: 0 }
|
|
113
115
|
: readConnectorPath(inputs, f.name, dialect);
|
|
114
116
|
if (!nested.found) {
|
|
115
117
|
// A required LOOKUP field is missing far more often because the author does
|
|
@@ -326,6 +328,51 @@ function place(target, parts, index, value) {
|
|
|
326
328
|
target[part.key] = next;
|
|
327
329
|
place(next, parts, index + 1, value);
|
|
328
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* The flat key the product writes for each array LEAF field, by its wire name:
|
|
333
|
+
* `fields.components_arrayRemap_name` for `fields.components_arrayRemap_name[*]`.
|
|
334
|
+
*
|
|
335
|
+
* Product-authored flows key `bodyParameters` either way (86 Slack
|
|
336
|
+
* `create-group-direct-message` nodes in the eval archive, almost all from the v1
|
|
337
|
+
* CLI arm, carry bare `users`; 85 carry `users[*]`; a Studio Web save in
|
|
338
|
+
* #1402 carried a bare Jira key), and the runtime reads both the same for an array
|
|
339
|
+
* value (flow-v1 `convertDotNotationToNested`). The nested reader already strips
|
|
340
|
+
* the marker, so `{ users: [...] }` compiled, but a DOTTED bare key reached only
|
|
341
|
+
* the exact flat lookup and was refused as unknown — so a designer-saved Jira
|
|
342
|
+
* flow decompiled to source that did not compile back (#1402).
|
|
343
|
+
*
|
|
344
|
+
* Only a trailing `[*]` with none before it: `contacts.id` is not `contacts[*].id`
|
|
345
|
+
* (the runtime nests it as an object, not a list). A bare name that is itself a
|
|
346
|
+
* declared field keeps its own meaning.
|
|
347
|
+
*/
|
|
348
|
+
function bareArraySpellings(fields, declared) {
|
|
349
|
+
const bare = new Map();
|
|
350
|
+
for (const f of fields) {
|
|
351
|
+
if (!f.name.endsWith('[*]'))
|
|
352
|
+
continue;
|
|
353
|
+
const key = f.name.slice(0, -3);
|
|
354
|
+
if (key.includes('[*]') || declared.has(key))
|
|
355
|
+
continue;
|
|
356
|
+
bare.set(f.name, key);
|
|
357
|
+
}
|
|
358
|
+
return bare;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* The flat key `inputs` carries field `name` under: its wire name, or its bare
|
|
362
|
+
* spelling when the value there is an array or opaque. A bare SCALAR is left to
|
|
363
|
+
* the nested reader, which refuses it ("expected array"), as before: under
|
|
364
|
+
* `users[*]` the runtime would wrap `"U1,U2"` into `["U1,U2"]`, a different
|
|
365
|
+
* request from the one the bare key sends.
|
|
366
|
+
*/
|
|
367
|
+
function flatInputKey(inputs, name, bare, dialect) {
|
|
368
|
+
if (Object.prototype.hasOwnProperty.call(inputs, name))
|
|
369
|
+
return name;
|
|
370
|
+
const key = bare.get(name);
|
|
371
|
+
if (key === undefined || !Object.prototype.hasOwnProperty.call(inputs, key))
|
|
372
|
+
return undefined;
|
|
373
|
+
const value = inputs[key];
|
|
374
|
+
return Array.isArray(value) || dialect.isOpaque(value) ? key : undefined;
|
|
375
|
+
}
|
|
329
376
|
function connectorPath(name) {
|
|
330
377
|
return name.split('.').map((raw) => ({
|
|
331
378
|
key: raw.endsWith('[*]') ? raw.slice(0, -3) : raw,
|
|
@@ -385,6 +432,7 @@ function buildConnectorInputTrie(fields) {
|
|
|
385
432
|
function validateNestedConnectorKeys(fields, inputs, exact, dialect) {
|
|
386
433
|
const root = buildConnectorInputTrie(fields);
|
|
387
434
|
const errs = [];
|
|
435
|
+
const bare = new Set(bareArraySpellings(fields, exact).values());
|
|
388
436
|
const visit = (value, node, path) => {
|
|
389
437
|
if (dialect.isOpaque(value))
|
|
390
438
|
return;
|
|
@@ -422,6 +470,13 @@ function validateNestedConnectorKeys(fields, inputs, exact, dialect) {
|
|
|
422
470
|
if (exact.has(key))
|
|
423
471
|
continue; // backwards-compatible flat authoring
|
|
424
472
|
const node = root.children.get(key);
|
|
473
|
+
// A dotted bare array key (`fields.labels` for `fields.labels[*]`); a
|
|
474
|
+
// top-level one (`users`) is a trie child and is checked by `visit` below.
|
|
475
|
+
if (!node && bare.has(key)) {
|
|
476
|
+
if (!Array.isArray(value) && !dialect.isOpaque(value))
|
|
477
|
+
errs.push(`input "${key}" expected array, got ${typeof value}`);
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
425
480
|
if (!node) {
|
|
426
481
|
const near = nearestField(key, [...exact.keys()]);
|
|
427
482
|
errs.push(`unknown input "${key}"${near ? ` — did you mean "${near}"?` : ''}`);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UipClient } from "../uip/client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Set by `uip` for the processes it starts: the login profile the run is for.
|
|
4
|
+
* Empty or unset means the default login.
|
|
5
|
+
*/
|
|
6
|
+
export declare const INHERITED_PROFILE_ENV = "UIPATH_CLI_INHERITED_PROFILE";
|
|
7
|
+
/**
|
|
8
|
+
* Refuse unless the `uip` on PATH answers as `profile`.
|
|
9
|
+
*
|
|
10
|
+
* A `uip` older than {@link INHERITED_PROFILE_ENV} ignores it and reads the
|
|
11
|
+
* default login, which can be another customer's tenant, and nothing downstream
|
|
12
|
+
* notices (UiPath/cli#5485).
|
|
13
|
+
*/
|
|
14
|
+
export declare function assertInheritedProfile(client: UipClient, profile: string): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Refusal } from "../errors.js";
|
|
2
|
+
import { loginStatus } from "../uip/commands.js";
|
|
3
|
+
import { failureReason, getCI, parseEnvelope } from "../uip/envelope.js";
|
|
4
|
+
/**
|
|
5
|
+
* Set by `uip` for the processes it starts: the login profile the run is for.
|
|
6
|
+
* Empty or unset means the default login.
|
|
7
|
+
*/
|
|
8
|
+
export const INHERITED_PROFILE_ENV = "UIPATH_CLI_INHERITED_PROFILE";
|
|
9
|
+
/**
|
|
10
|
+
* Refuse unless the `uip` on PATH answers as `profile`.
|
|
11
|
+
*
|
|
12
|
+
* A `uip` older than {@link INHERITED_PROFILE_ENV} ignores it and reads the
|
|
13
|
+
* default login, which can be another customer's tenant, and nothing downstream
|
|
14
|
+
* notices (UiPath/cli#5485).
|
|
15
|
+
*/
|
|
16
|
+
export async function assertInheritedProfile(client, profile) {
|
|
17
|
+
const result = await client.run(loginStatus());
|
|
18
|
+
const data = result.code === 0 ? getCI(parseEnvelope(result.stdout), "Data") : undefined;
|
|
19
|
+
if (data === undefined) {
|
|
20
|
+
throw new Refusal(`could not confirm login profile "${profile}": ${failureReason(result)}`, "PROFILE_UNCONFIRMED");
|
|
21
|
+
}
|
|
22
|
+
const actual = getCI(data, "Profile");
|
|
23
|
+
if (actual === profile)
|
|
24
|
+
return;
|
|
25
|
+
const answeredAs = typeof actual === "string" ? `profile "${actual}"` : "the default login";
|
|
26
|
+
const tenant = `${String(getCI(data, "Organization"))}/${String(getCI(data, "Tenant"))}`;
|
|
27
|
+
throw new Refusal(`this run is for login profile "${profile}", but the uip on PATH answers as ${answeredAs} (${tenant}). Run 'uip update', then retry.`, "PROFILE_MISMATCH");
|
|
28
|
+
}
|
|
@@ -2,6 +2,7 @@ import { resolve } from 'node:path';
|
|
|
2
2
|
import { reportResult } from '../cli-result.js';
|
|
3
3
|
import { PACKAGE_NAME } from "../package-name.js";
|
|
4
4
|
import { exitCodeOf } from "./errors.js";
|
|
5
|
+
import { assertInheritedProfile, INHERITED_PROFILE_ENV } from "./prepare/inherited-profile.js";
|
|
5
6
|
import { exitText } from "./prepare/messages.js";
|
|
6
7
|
import { defaultOverlayOut, prepareConnector as runPipeline } from "./prepare/pipeline.js";
|
|
7
8
|
import { consoleReporter } from "./reporter.js";
|
|
@@ -64,6 +65,9 @@ export async function prepareConnector(options) {
|
|
|
64
65
|
// once, as a warning, and the calls spawn as they did before.
|
|
65
66
|
const client = defaultUipClient({ host: { onFallback: (reason) => consoleReporter.warn(` WARN: ${reason}`) } });
|
|
66
67
|
try {
|
|
68
|
+
const profile = process.env[INHERITED_PROFILE_ENV];
|
|
69
|
+
if (profile)
|
|
70
|
+
await assertInheritedProfile(client, profile);
|
|
67
71
|
return await runPipeline(pipelineOptions(options), {
|
|
68
72
|
client,
|
|
69
73
|
reporter: consoleReporter,
|
|
@@ -15,6 +15,7 @@ export declare const UIP = "uip";
|
|
|
15
15
|
export declare function connectionArgs(connectionId?: string): string[];
|
|
16
16
|
/** `-f name=value` per parent field, in the order given. */
|
|
17
17
|
export declare function fieldArgs(parentFields: ReadonlyMap<string, string> | Readonly<Record<string, string>> | undefined): string[];
|
|
18
|
+
export declare function loginStatus(): string[];
|
|
18
19
|
export declare function registrySearchConnectors(): string[];
|
|
19
20
|
export declare function registrySearch(query: string): string[];
|
|
20
21
|
/**
|
|
@@ -22,6 +22,9 @@ export function fieldArgs(parentFields) {
|
|
|
22
22
|
const entries = parentFields instanceof Map ? [...parentFields.entries()] : Object.entries(parentFields);
|
|
23
23
|
return entries.flatMap(([name, value]) => ["-f", `${name}=${value}`]);
|
|
24
24
|
}
|
|
25
|
+
export function loginStatus() {
|
|
26
|
+
return [UIP, "login", "status", "--output", "json"];
|
|
27
|
+
}
|
|
25
28
|
export function registrySearchConnectors() {
|
|
26
29
|
return [UIP, "maestro", "flow", "registry", "search", "--filter", "tags:in=connector", "--output", "json"];
|
|
27
30
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.49.
|
|
3
|
+
"version": "6.49.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": "0187c4bea37cd0a8fd78aae6125b040583097f96"
|
|
96
96
|
}
|