@uipath/maestro-builder-sdk 6.50.0 → 6.50.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.
- package/dist/case/check-cli.js +10 -9
- package/dist/case/compile-cli.d.ts +21 -0
- package/dist/case/compile-cli.js +26 -3
- package/dist/core/binding-messages.d.ts +2 -0
- package/dist/core/binding-messages.js +5 -0
- package/dist/core/bindings.d.ts +42 -3
- package/dist/core/bindings.js +67 -5
- package/package.json +2 -2
package/dist/case/check-cli.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* check-cli — fast static validation of <Name>.case.ts (no output file).
|
|
4
4
|
*
|
|
5
5
|
* Usage: node --experimental-strip-types check-cli.js <case.ts | BaseName> \
|
|
6
|
-
* [--library <library-json dir>] [--connectors-local <overlay dir>] [--bindings <bindings.json>]
|
|
6
|
+
* [--library <library-json dir>] [--connectors-local <overlay dir>] [--bindings <bindings.json>] \
|
|
7
|
+
* [-o <the plan compile writes>]
|
|
7
8
|
* Exits 0 when clean (warnings allowed), 1 on any error.
|
|
8
9
|
*
|
|
9
10
|
* The library is opened exactly as `compile-cli` opens it (`openCliLibrary`), so
|
|
@@ -14,19 +15,18 @@ import { resolveCaseFile, loadBuiltCase } from './load.js';
|
|
|
14
15
|
import { check } from './check.js';
|
|
15
16
|
import { caseCheckOpts } from './cli-library.js';
|
|
16
17
|
import { openCliLibrary } from '../core/cli-library.js';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { flagValue, runWhenInvokedDirectly } from '../cli-run.js';
|
|
18
|
+
import { caseCompileTarget } from './compile-cli.js';
|
|
19
|
+
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
20
20
|
import { ensureTypeScriptRuntime } from '../node-runtime.js';
|
|
21
21
|
/** Flags that take a value: their argument is never the source positional. */
|
|
22
|
-
const VALUE_FLAGS = new Set(['--library', '--connectors-local', '--bindings']);
|
|
23
|
-
const USAGE = 'usage: check <case.ts | BaseName> [--library <dir>] [--connectors-local <dir>] [--bindings <file>]';
|
|
22
|
+
const VALUE_FLAGS = new Set(['--library', '--connectors-local', '--bindings', '-o']);
|
|
23
|
+
const USAGE = 'usage: check <case.ts | BaseName> [--library <dir>] [--connectors-local <dir>] [--bindings <file>] [-o <plan>]';
|
|
24
24
|
export async function run(argv) {
|
|
25
25
|
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
26
26
|
console.error(USAGE);
|
|
27
27
|
return 2;
|
|
28
28
|
}
|
|
29
|
-
const input = argv.find((a, i) => !a.startsWith('
|
|
29
|
+
const input = argv.find((a, i) => !a.startsWith('-') && !VALUE_FLAGS.has(argv[i - 1]));
|
|
30
30
|
if (input === undefined) {
|
|
31
31
|
console.error(USAGE);
|
|
32
32
|
return 2;
|
|
@@ -34,8 +34,9 @@ export async function run(argv) {
|
|
|
34
34
|
const file = resolveCaseFile(input);
|
|
35
35
|
ensureTypeScriptRuntime();
|
|
36
36
|
const built = await loadBuiltCase(file);
|
|
37
|
-
// bindings
|
|
38
|
-
|
|
37
|
+
// The bindings `case compile` reads, plan fallback included, for the
|
|
38
|
+
// binding-label rules (#1034): `-o` names the plan as it does for compile.
|
|
39
|
+
const { bindings } = caseCompileTarget(argv);
|
|
39
40
|
const diags = check(built, caseCheckOpts(openCliLibrary(argv), bindings));
|
|
40
41
|
reportDiagnostics(diags);
|
|
41
42
|
for (const d of diags)
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { Bindings } from '../core/bindings.js';
|
|
2
3
|
import { type CliExitCode } from '../cli-run.js';
|
|
3
4
|
export declare function run(argv: string[]): Promise<CliExitCode>;
|
|
5
|
+
/**
|
|
6
|
+
* The plan file `case compile` writes, and the bindings it resolves connection
|
|
7
|
+
* and folder labels against. `case check` reads the same pair, so the two agree
|
|
8
|
+
* on which labels are declared.
|
|
9
|
+
*
|
|
10
|
+
* The plan is `-o`, else the plan file the project in the working directory
|
|
11
|
+
* ships, else `caseplan.json`. The bindings are `--bindings` (default: the
|
|
12
|
+
* project's bindings.json), with that plan's own root bindings as a fallback
|
|
13
|
+
* when it exists. Recompiling into an existing plan (the brownfield loop:
|
|
14
|
+
* decompile, edit, compile back over the same file) then resolves the binding
|
|
15
|
+
* ids decompile names a connector's connection and folder by
|
|
16
|
+
* (`connection: "bOC1"`).
|
|
17
|
+
*
|
|
18
|
+
* @param argv - The command's arguments.
|
|
19
|
+
* @returns The output path and the bindings registry.
|
|
20
|
+
*/
|
|
21
|
+
export declare function caseCompileTarget(argv: string[]): {
|
|
22
|
+
out: string;
|
|
23
|
+
bindings: Bindings;
|
|
24
|
+
};
|
|
4
25
|
/**
|
|
5
26
|
* Write the entry point's id onto its trigger, as `data.inputs.entryPointId`.
|
|
6
27
|
*
|
package/dist/case/compile-cli.js
CHANGED
|
@@ -23,6 +23,7 @@ import { check } from './check.js';
|
|
|
23
23
|
import { caseCheckOpts } from './cli-library.js';
|
|
24
24
|
import { entryPointIO } from './entry-points.js';
|
|
25
25
|
import { Bindings } from '../core/bindings.js';
|
|
26
|
+
import { offlineBindingLabel } from './ids.js';
|
|
26
27
|
import { openCliLibrary } from '../core/cli-library.js';
|
|
27
28
|
import { defaultBindingsFile } from '../workdir.js';
|
|
28
29
|
import { flagValue, runWhenInvokedDirectly } from '../cli-run.js';
|
|
@@ -54,8 +55,7 @@ export async function run(argv) {
|
|
|
54
55
|
// which is what the three copies of these lines used to each decide for itself.
|
|
55
56
|
// Opened BEFORE the check pass, which reads the same library (#1014).
|
|
56
57
|
const library = openCliLibrary(argv);
|
|
57
|
-
const
|
|
58
|
-
const bindings = new Bindings(bindFile);
|
|
58
|
+
const { out, bindings } = caseCompileTarget(argv);
|
|
59
59
|
const diags = check(built, caseCheckOpts(library, bindings));
|
|
60
60
|
for (const d of diags)
|
|
61
61
|
console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
|
|
@@ -66,7 +66,6 @@ export async function run(argv) {
|
|
|
66
66
|
console.error(`compile: ${errors.length} error(s); not emitting.`);
|
|
67
67
|
return 1;
|
|
68
68
|
}
|
|
69
|
-
const out = flagValue(argv, '-o') ?? shippedCasePlanName('.') ?? 'caseplan.json';
|
|
70
69
|
const shadow = shadowedOutputDiagnostic(out);
|
|
71
70
|
if (shadow) {
|
|
72
71
|
console.error(` ✗ [${shadow.code}] ${shadow.message} Fix: ${shadow.suggestion}.`);
|
|
@@ -94,6 +93,30 @@ export async function run(argv) {
|
|
|
94
93
|
reportResult({ path: resolve(out), stages, ...(triggers >= 0 ? { triggers } : {}), ...(resources >= 0 ? { resources } : {}) });
|
|
95
94
|
return 0;
|
|
96
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* The plan file `case compile` writes, and the bindings it resolves connection
|
|
98
|
+
* and folder labels against. `case check` reads the same pair, so the two agree
|
|
99
|
+
* on which labels are declared.
|
|
100
|
+
*
|
|
101
|
+
* The plan is `-o`, else the plan file the project in the working directory
|
|
102
|
+
* ships, else `caseplan.json`. The bindings are `--bindings` (default: the
|
|
103
|
+
* project's bindings.json), with that plan's own root bindings as a fallback
|
|
104
|
+
* when it exists. Recompiling into an existing plan (the brownfield loop:
|
|
105
|
+
* decompile, edit, compile back over the same file) then resolves the binding
|
|
106
|
+
* ids decompile names a connector's connection and folder by
|
|
107
|
+
* (`connection: "bOC1"`).
|
|
108
|
+
*
|
|
109
|
+
* @param argv - The command's arguments.
|
|
110
|
+
* @returns The output path and the bindings registry.
|
|
111
|
+
*/
|
|
112
|
+
export function caseCompileTarget(argv) {
|
|
113
|
+
const out = flagValue(argv, '-o') ?? shippedCasePlanName('.') ?? 'caseplan.json';
|
|
114
|
+
const bindFile = flagValue(argv, '--bindings') ?? defaultBindingsFile();
|
|
115
|
+
// A row serialize minted offline (`{ id: 'b…', resourceKey: 'drive' }`) is a
|
|
116
|
+
// placeholder for the label `drive`, not a binding: it must not answer.
|
|
117
|
+
const minted = (row) => offlineBindingLabel(row) !== undefined;
|
|
118
|
+
return { out, bindings: new Bindings(bindFile).withFallback(existsSync(out) ? out : undefined, minted) };
|
|
119
|
+
}
|
|
97
120
|
/**
|
|
98
121
|
* The file names a Case project's plan can have, in the order the packager
|
|
99
122
|
* (`@uipath/packager-tool-case` `CasePlanFileNames`) picks the first one present.
|
|
@@ -27,6 +27,8 @@ export interface BindingsView {
|
|
|
27
27
|
resolve(name?: string): string | undefined;
|
|
28
28
|
declared?(): string[];
|
|
29
29
|
entry?(name?: string): unknown;
|
|
30
|
+
/** True when only a recompile fallback row (the plan's own bindings) answers `name`. */
|
|
31
|
+
fromFallback?(name?: string): boolean;
|
|
30
32
|
}
|
|
31
33
|
export declare function bindingSelfNameMessage(where: string, name: string, attribute: 'connection' | 'folder', target?: PrepareTarget): string;
|
|
32
34
|
/**
|
|
@@ -81,6 +81,11 @@ export function undeclaredBinding(bindings, name) {
|
|
|
81
81
|
export function bindingLabelRefusal(bindings, name, attribute, where, target) {
|
|
82
82
|
if (!bindings)
|
|
83
83
|
return undefined;
|
|
84
|
+
// A label that is exactly a row id of the plan being recompiled (what
|
|
85
|
+
// decompile emits) reuses that row. Those rows are not an author's
|
|
86
|
+
// bindings.json, so neither rule applies to them.
|
|
87
|
+
if (bindings.fromFallback?.(name))
|
|
88
|
+
return undefined;
|
|
84
89
|
const resolved = bindings.resolve(name);
|
|
85
90
|
if (resolved === name)
|
|
86
91
|
return new BindingRefusal('BINDING_SELF_NAME', bindingSelfNameMessage(where, name, attribute, target));
|
package/dist/core/bindings.d.ts
CHANGED
|
@@ -1,11 +1,50 @@
|
|
|
1
1
|
export declare class Bindings {
|
|
2
2
|
private list;
|
|
3
|
+
/**
|
|
4
|
+
* Rows from {@link withFallback}: the root `bindings[]` of the plan being
|
|
5
|
+
* recompiled. Kept apart from `list` on purpose. They are not an author's
|
|
6
|
+
* bindings.json, so they never count as declared names and never feed the
|
|
7
|
+
* self-name / undeclared label rules. An offline plan's own rows are
|
|
8
|
+
* `{ id: 'slack', resourceKey: 'slack' }`; counted as declared they made the
|
|
9
|
+
* second offline compile refuse the connector's own label (BINDING_SELF_NAME).
|
|
10
|
+
*/
|
|
11
|
+
private fallback;
|
|
3
12
|
constructor(file?: string);
|
|
4
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Add the root bindings of another document (the plan being recompiled) as a
|
|
15
|
+
* fallback. A fallback row answers only a label that is exactly its `id`
|
|
16
|
+
* (what decompile emits), whose key is not that same id (a placeholder; see
|
|
17
|
+
* `fallbackRow`), and that the primary registry does not answer. It
|
|
18
|
+
* is never part of {@link declared}, and {@link fromFallback} lets the label
|
|
19
|
+
* rules skip it.
|
|
20
|
+
*
|
|
21
|
+
* @param file - A bindings.json, or any document with a root `bindings[]`
|
|
22
|
+
* (a caseplan); a missing or unreadable file adds nothing.
|
|
23
|
+
* @param isPlaceholder - Recognises a row the document's own compiler minted
|
|
24
|
+
* offline (a label with no real key behind it, under a minted id). Such a
|
|
25
|
+
* row answers nothing, like a row whose key is its own id.
|
|
26
|
+
* @returns This registry, for chaining.
|
|
27
|
+
*/
|
|
28
|
+
withFallback(file?: string, isPlaceholder?: (row: Record<string, unknown>) => boolean): this;
|
|
29
|
+
private primary;
|
|
30
|
+
/**
|
|
31
|
+
* The fallback row whose `id` is `name`. A row whose key is its own id
|
|
32
|
+
* (`{ id: 'drive', resourceKey: 'drive' }`, what an offline compile writes) is
|
|
33
|
+
* a placeholder, not an answer, so it is skipped: the label rules then judge
|
|
34
|
+
* `drive` against the author's bindings.json as they would without a fallback.
|
|
35
|
+
*/
|
|
36
|
+
private fallbackRow;
|
|
37
|
+
/**
|
|
38
|
+
* True when only a fallback row answers `name`: the primary registry does not,
|
|
39
|
+
* and a fallback row's `id` is exactly `name`. The label rules
|
|
40
|
+
* (`bindingLabelRefusal`) accept such a label as is.
|
|
41
|
+
*/
|
|
42
|
+
fromFallback(name?: string): boolean;
|
|
43
|
+
/** Resolve by binding `name` or `id` (fallback rows: `id` only); returns its resourceKey (or default). */
|
|
5
44
|
resolve(name?: string): string | undefined;
|
|
6
|
-
/** Every symbolic name the
|
|
45
|
+
/** Every symbolic name the bindings.json declares — what an author CAN write in `connection:` / `folder:`. Fallback rows are not included. */
|
|
7
46
|
declared(): string[];
|
|
8
|
-
/** The full binding entry by `name` or `id` — for consumers that emit a binding
|
|
47
|
+
/** The full binding entry by `name` or `id` (fallback rows: `id` only) — for consumers that emit a binding
|
|
9
48
|
* registry + `=bindings.<id>` refs (the Case caseplan) rather than inlining the
|
|
10
49
|
* resourceKey (the Flow node). */
|
|
11
50
|
entry(name?: string): Record<string, unknown> | undefined;
|
package/dist/core/bindings.js
CHANGED
|
@@ -5,21 +5,83 @@
|
|
|
5
5
|
import { readFileSync, existsSync } from 'node:fs';
|
|
6
6
|
export class Bindings {
|
|
7
7
|
list = [];
|
|
8
|
+
/**
|
|
9
|
+
* Rows from {@link withFallback}: the root `bindings[]` of the plan being
|
|
10
|
+
* recompiled. Kept apart from `list` on purpose. They are not an author's
|
|
11
|
+
* bindings.json, so they never count as declared names and never feed the
|
|
12
|
+
* self-name / undeclared label rules. An offline plan's own rows are
|
|
13
|
+
* `{ id: 'slack', resourceKey: 'slack' }`; counted as declared they made the
|
|
14
|
+
* second offline compile refuse the connector's own label (BINDING_SELF_NAME).
|
|
15
|
+
*/
|
|
16
|
+
fallback = [];
|
|
8
17
|
constructor(file) {
|
|
9
18
|
if (file && existsSync(file)) {
|
|
10
19
|
this.list = normalizeBindings(JSON.parse(readFileSync(file, 'utf8')));
|
|
11
20
|
}
|
|
12
21
|
}
|
|
13
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Add the root bindings of another document (the plan being recompiled) as a
|
|
24
|
+
* fallback. A fallback row answers only a label that is exactly its `id`
|
|
25
|
+
* (what decompile emits), whose key is not that same id (a placeholder; see
|
|
26
|
+
* `fallbackRow`), and that the primary registry does not answer. It
|
|
27
|
+
* is never part of {@link declared}, and {@link fromFallback} lets the label
|
|
28
|
+
* rules skip it.
|
|
29
|
+
*
|
|
30
|
+
* @param file - A bindings.json, or any document with a root `bindings[]`
|
|
31
|
+
* (a caseplan); a missing or unreadable file adds nothing.
|
|
32
|
+
* @param isPlaceholder - Recognises a row the document's own compiler minted
|
|
33
|
+
* offline (a label with no real key behind it, under a minted id). Such a
|
|
34
|
+
* row answers nothing, like a row whose key is its own id.
|
|
35
|
+
* @returns This registry, for chaining.
|
|
36
|
+
*/
|
|
37
|
+
withFallback(file, isPlaceholder) {
|
|
38
|
+
if (!file || !existsSync(file))
|
|
39
|
+
return this;
|
|
40
|
+
let parsed;
|
|
41
|
+
try {
|
|
42
|
+
parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return this; // a fallback is optional; an unreadable one adds nothing
|
|
46
|
+
}
|
|
47
|
+
const ids = new Set(this.fallback.map((x) => x?.id));
|
|
48
|
+
for (const entry of normalizeBindings(parsed))
|
|
49
|
+
if (typeof entry?.id === 'string' && !ids.has(entry.id) && !isPlaceholder?.(entry))
|
|
50
|
+
this.fallback.push(entry);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
primary(name) {
|
|
54
|
+
return this.list.find((x) => x.name === name || x.id === name);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The fallback row whose `id` is `name`. A row whose key is its own id
|
|
58
|
+
* (`{ id: 'drive', resourceKey: 'drive' }`, what an offline compile writes) is
|
|
59
|
+
* a placeholder, not an answer, so it is skipped: the label rules then judge
|
|
60
|
+
* `drive` against the author's bindings.json as they would without a fallback.
|
|
61
|
+
*/
|
|
62
|
+
fallbackRow(name) {
|
|
63
|
+
return this.fallback.find((x) => x.id === name && (x.resourceKey ?? x.default) !== name);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* True when only a fallback row answers `name`: the primary registry does not,
|
|
67
|
+
* and a fallback row's `id` is exactly `name`. The label rules
|
|
68
|
+
* (`bindingLabelRefusal`) accept such a label as is.
|
|
69
|
+
*/
|
|
70
|
+
fromFallback(name) {
|
|
71
|
+
if (!name)
|
|
72
|
+
return false;
|
|
73
|
+
return this.primary(name) === undefined && this.fallbackRow(name) !== undefined;
|
|
74
|
+
}
|
|
75
|
+
/** Resolve by binding `name` or `id` (fallback rows: `id` only); returns its resourceKey (or default). */
|
|
14
76
|
resolve(name) {
|
|
15
77
|
if (!name)
|
|
16
78
|
return undefined;
|
|
17
|
-
const b = this.
|
|
79
|
+
const b = this.primary(name) ?? this.fallbackRow(name);
|
|
18
80
|
if (!b)
|
|
19
81
|
return undefined;
|
|
20
82
|
return (b.resourceKey ?? b.default);
|
|
21
83
|
}
|
|
22
|
-
/** Every symbolic name the
|
|
84
|
+
/** Every symbolic name the bindings.json declares — what an author CAN write in `connection:` / `folder:`. Fallback rows are not included. */
|
|
23
85
|
declared() {
|
|
24
86
|
const names = [];
|
|
25
87
|
for (const b of this.list) {
|
|
@@ -29,13 +91,13 @@ export class Bindings {
|
|
|
29
91
|
}
|
|
30
92
|
return names;
|
|
31
93
|
}
|
|
32
|
-
/** The full binding entry by `name` or `id` — for consumers that emit a binding
|
|
94
|
+
/** The full binding entry by `name` or `id` (fallback rows: `id` only) — for consumers that emit a binding
|
|
33
95
|
* registry + `=bindings.<id>` refs (the Case caseplan) rather than inlining the
|
|
34
96
|
* resourceKey (the Flow node). */
|
|
35
97
|
entry(name) {
|
|
36
98
|
if (!name)
|
|
37
99
|
return undefined;
|
|
38
|
-
return this.
|
|
100
|
+
return (this.primary(name) ?? this.fallbackRow(name));
|
|
39
101
|
}
|
|
40
102
|
}
|
|
41
103
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.50.
|
|
3
|
+
"version": "6.50.1",
|
|
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": "3b0f8b3f6e84465828936a6242656c563947c74d"
|
|
96
96
|
}
|