@uipath/maestro-builder-sdk 6.18.4 → 6.18.6
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 +9 -5
- package/dist/case/check.d.ts +16 -3
- package/dist/case/check.js +18 -3
- package/dist/case/cli-library.d.ts +7 -3
- package/dist/case/cli-library.js +20 -5
- package/dist/case/compile-cli.js +3 -3
- package/dist/case/external.d.ts +27 -0
- package/dist/case/external.js +25 -0
- package/dist/case/serialize.js +56 -39
- package/dist/cli/commands/case.js +2 -0
- package/dist/core/binding-messages.d.ts +21 -0
- package/dist/core/binding-messages.js +33 -0
- package/dist/core/connector-checks.js +4 -11
- package/dist/serialize.js +4 -10
- package/package.json +2 -2
package/dist/case/check-cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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>]
|
|
6
|
+
* [--library <library-json dir>] [--connectors-local <overlay dir>] [--bindings <bindings.json>]
|
|
7
7
|
* Exits 0 when clean (warnings allowed), 1 on any error.
|
|
8
8
|
*
|
|
9
9
|
* The library is opened exactly as `compile-cli` opens it (`openCliLibrary`), so
|
|
@@ -14,11 +14,13 @@ import { resolveCaseFile, loadBuiltCase } from './load.js';
|
|
|
14
14
|
import { check } from './check.js';
|
|
15
15
|
import { caseCheckOpts } from './cli-library.js';
|
|
16
16
|
import { openCliLibrary } from '../core/cli-library.js';
|
|
17
|
-
import {
|
|
17
|
+
import { Bindings } from '../core/bindings.js';
|
|
18
|
+
import { defaultBindingsFile } from '../workdir.js';
|
|
19
|
+
import { flagValue, runWhenInvokedDirectly } from '../cli-run.js';
|
|
18
20
|
import { ensureTypeScriptRuntime } from '../node-runtime.js';
|
|
19
21
|
/** Flags that take a value: their argument is never the source positional. */
|
|
20
|
-
const VALUE_FLAGS = new Set(['--library', '--connectors-local']);
|
|
21
|
-
const USAGE = 'usage: check <case.ts | BaseName> [--library <dir>] [--connectors-local <dir>]';
|
|
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
24
|
export async function run(argv) {
|
|
23
25
|
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
24
26
|
console.error(USAGE);
|
|
@@ -32,7 +34,9 @@ export async function run(argv) {
|
|
|
32
34
|
const file = resolveCaseFile(input);
|
|
33
35
|
ensureTypeScriptRuntime();
|
|
34
36
|
const built = await loadBuiltCase(file);
|
|
35
|
-
|
|
37
|
+
// bindings.json as `case compile` reads it, for the binding-label rules (#1034).
|
|
38
|
+
const bindings = new Bindings(flagValue(argv, '--bindings') ?? defaultBindingsFile());
|
|
39
|
+
const diags = check(built, caseCheckOpts(openCliLibrary(argv), bindings));
|
|
36
40
|
reportDiagnostics(diags);
|
|
37
41
|
for (const d of diags)
|
|
38
42
|
console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
|
package/dist/case/check.d.ts
CHANGED
|
@@ -25,19 +25,32 @@ export interface Diagnostic {
|
|
|
25
25
|
* `compile` actually makes. Case `serialize` resolves the connector operation and
|
|
26
26
|
* the event, and validates a connector task's inputs and resolves its lookups
|
|
27
27
|
* through the shared `buildConnectorInputs` (`connectorInputs`, `lookups`,
|
|
28
|
-
* `resolutions`)
|
|
29
|
-
*
|
|
28
|
+
* `resolutions`), and refuses a connection/folder label bindings.json cannot
|
|
29
|
+
* turn into a resource key (`bindings`, `bindingLabelRefusal`). It does not
|
|
30
|
+
* check BYOA, so that hook stays off until Case compile enforces it.
|
|
30
31
|
*
|
|
31
32
|
* Every hook fails open: without a library, `check` stays a pure function of the
|
|
32
33
|
* built model.
|
|
33
34
|
*/
|
|
34
|
-
export type CaseCheckOpts = Pick<ConnectorCheckOpts, 'connectorResolveError' | 'connectorInputs' | 'lookups' | 'resolutions' | 'schemaReadiness'> & {
|
|
35
|
+
export type CaseCheckOpts = Pick<ConnectorCheckOpts, 'connectorResolveError' | 'connectorInputs' | 'lookups' | 'resolutions' | 'schemaReadiness' | 'bindings'> & {
|
|
35
36
|
/**
|
|
36
37
|
* What Case `compile` would refuse an event subscription with, or `undefined`
|
|
37
38
|
* when it resolves: `EVENT_UNKNOWN` (the event is not in the library, or
|
|
38
39
|
* refuses the `object`) or `EVENT_GENERIC_NO_OBJECT` (a GENERIC event with no
|
|
39
40
|
* `object`). Built on `resolveCaseSubscription`, the call compile makes.
|
|
40
41
|
*/
|
|
42
|
+
/**
|
|
43
|
+
* What Case `compile` would refuse an External Agent / External Workflow
|
|
44
|
+
* task's resolved descriptor with (`externalDescriptorRefusal`), or
|
|
45
|
+
* `undefined`: also `undefined` when the descriptor does not resolve, which
|
|
46
|
+
* `connectorResolveError` reports.
|
|
47
|
+
*/
|
|
48
|
+
externalDescriptorError?: (kind: 'external-agent' | 'external-workflow', descriptor: {
|
|
49
|
+
key: string;
|
|
50
|
+
action: string;
|
|
51
|
+
version?: string;
|
|
52
|
+
object?: string;
|
|
53
|
+
}) => string | undefined;
|
|
41
54
|
subscriptionError?: (kind: 'trigger' | 'event', subscription: EventSubscription) => {
|
|
42
55
|
code: string;
|
|
43
56
|
message: string;
|
package/dist/case/check.js
CHANGED
|
@@ -2,8 +2,9 @@ import { types } from '../core/expr.js';
|
|
|
2
2
|
import { authoredCaseVersion, CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
3
3
|
import { schemaVersionRefusal } from '../schema-version.js';
|
|
4
4
|
import { caseJsonPreservation, caseJsonPreservationErrors } from './preserve.js';
|
|
5
|
-
import { EQUALS_EXPR_DIALECT, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, } from '../core/connector-checks.js';
|
|
5
|
+
import { EQUALS_EXPR_DIALECT, checkBindingLabels, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, } from '../core/connector-checks.js';
|
|
6
6
|
import { checkEventResolution } from '../core/event-checks.js';
|
|
7
|
+
import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT } from './external.js';
|
|
7
8
|
const TYPE_NAMES = new Set(Object.values(types));
|
|
8
9
|
// audit-case-coverage: rule-slot table start
|
|
9
10
|
// This runtime table must equal the committed matrix's rejected cells. The audit
|
|
@@ -113,6 +114,11 @@ export function check(built, opts = {}) {
|
|
|
113
114
|
message: `Stage "${stage.label}" selectNextStage.objectName must name a Data Fabric entity.`,
|
|
114
115
|
where: stage.label,
|
|
115
116
|
});
|
|
117
|
+
// Its connector's labels resolve through the same `bindingRef` as a
|
|
118
|
+
// connector task's, so they get the same binding-label rules.
|
|
119
|
+
const connector = exit.selectNextStage.connector;
|
|
120
|
+
if (connector)
|
|
121
|
+
checkBindingLabels('select-next-stage connector', connector, opts, (code, message) => diags.push({ level: 'error', code, message, where: stage.label }), { key: connector.connectorKey });
|
|
116
122
|
}
|
|
117
123
|
for (const lane of stage.lanes)
|
|
118
124
|
for (const t of lane) {
|
|
@@ -270,7 +276,10 @@ export function check(built, opts = {}) {
|
|
|
270
276
|
*
|
|
271
277
|
* - a connector task and an External Agent / External Workflow task resolve
|
|
272
278
|
* their operation (`library.resolve`): CONNECTOR_NOT_IN_LIBRARY,
|
|
273
|
-
* CONNECTOR_OBJECT_REQUIRED, CONNECTOR_OBJECT_NOT_GENERIC;
|
|
279
|
+
* CONNECTOR_OBJECT_REQUIRED, CONNECTOR_OBJECT_NOT_GENERIC; then their inputs
|
|
280
|
+
* (`buildConnectorInputs`): CONNECTOR_INPUT, LOOKUP_UNRESOLVED;
|
|
281
|
+
* - an external task's resolved descriptor (`externalDescriptorRefusal`):
|
|
282
|
+
* EXTERNAL_TASK_DESCRIPTOR_CONTRACT;
|
|
274
283
|
* - an event trigger, a wait-for-connector task and a wait-for-connector rule
|
|
275
284
|
* resolve their subscription (`resolveCaseSubscription`): EVENT_UNKNOWN,
|
|
276
285
|
* EVENT_GENERIC_NO_OBJECT.
|
|
@@ -291,6 +300,7 @@ function checkLibraryConnectors(built, opts, diags) {
|
|
|
291
300
|
diags.push({ level: 'error', code: refused.code, message: `${where}: ${refused.message}`, where: at });
|
|
292
301
|
// A `where` lookup nobody recorded: Flow's LOOKUP_UNRESOLVED warning, from the
|
|
293
302
|
// shared event rules. Only `resolutions` is passed, so nothing else in them fires.
|
|
303
|
+
checkBindingLabels(where, sub, opts, (code, message) => diags.push({ level: 'error', code, message, where: at }), { key: sub.connector, action: sub.event });
|
|
294
304
|
checkEventResolution(sub, where, kind, { resolutions: opts.resolutions ?? {} }, (code, message) => diags.push({ level: 'error', code, message, where: at }), (code, message) => diags.push({ level: 'warning', code, message, where: at }));
|
|
295
305
|
};
|
|
296
306
|
const rules = (conditions, where) => {
|
|
@@ -321,7 +331,12 @@ function checkLibraryConnectors(built, opts, diags) {
|
|
|
321
331
|
if ((t.kind === 'external-agent' || t.kind === 'external-workflow')
|
|
322
332
|
&& t.external?.connector?.key?.trim() && t.external.connector.action?.trim()) {
|
|
323
333
|
const where = `${t.kind === 'external-agent' ? 'External Agent' : 'External Workflow'} task "${t.name}"`;
|
|
324
|
-
|
|
334
|
+
const spec = t.external.connector;
|
|
335
|
+
checkConnectorLookups(where, spec, opts, EQUALS_EXPR_DIALECT, reporter(where, t.name));
|
|
336
|
+
checkConnectorContract(where, spec, opts, reporter(where, t.name));
|
|
337
|
+
const refused = opts.externalDescriptorError?.(t.kind, spec);
|
|
338
|
+
if (refused !== undefined)
|
|
339
|
+
diags.push({ level: 'error', code: EXTERNAL_TASK_DESCRIPTOR_CONTRACT, message: `${where}: ${refused}`, where: t.name });
|
|
325
340
|
}
|
|
326
341
|
if (t.kind === 'wait-for-connector' && isSubscription(t.waitConnector))
|
|
327
342
|
subscription('event', t.waitConnector, `Wait-for-connector task "${t.name}"`, t.name);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Library } from '../core/library.js';
|
|
2
|
+
import type { BindingsView } from '../core/binding-messages.js';
|
|
2
3
|
import type { CaseCheckOpts } from './check.js';
|
|
3
4
|
/**
|
|
4
5
|
* Case's check options from a library the CLI already opened, or `{}` without one.
|
|
@@ -7,10 +8,13 @@ import type { CaseCheckOpts } from './check.js';
|
|
|
7
8
|
* the operation and event resolution (the event through `resolveCaseSubscription`,
|
|
8
9
|
* compile's own call), a connector task's field contract and lookups (the
|
|
9
10
|
* `=`-expression validator Case compile runs), and the schema-readiness warnings.
|
|
10
|
-
*
|
|
11
|
-
* `serialize`
|
|
11
|
+
* With `bindings`, the binding-label rules (BINDING_SELF_NAME, BINDING_UNDECLARED),
|
|
12
|
+
* which Case `serialize` enforces through the same `bindingLabelRefusal`. The
|
|
13
|
+
* BYOA hooks of the shared bag are left out, because Case `serialize` does not
|
|
14
|
+
* enforce them.
|
|
12
15
|
*
|
|
13
16
|
* @param library - The library `openCliLibrary` returned, or `undefined`.
|
|
17
|
+
* @param bindings - The project's bindings.json, as compile reads it.
|
|
14
18
|
* @returns The options for Case `check`.
|
|
15
19
|
*/
|
|
16
|
-
export declare function caseCheckOpts(library: Library | undefined): CaseCheckOpts;
|
|
20
|
+
export declare function caseCheckOpts(library: Library | undefined, bindings?: BindingsView): CaseCheckOpts;
|
package/dist/case/cli-library.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* both `case check` and `case compile`'s check pass call.
|
|
9
9
|
*/
|
|
10
10
|
import { connectorCheckOpts } from '../core/cli-library.js';
|
|
11
|
+
import { externalDescriptorRefusal } from './external.js';
|
|
11
12
|
import { EVENT_GENERIC_NO_OBJECT, GenericEventNoObjectError, resolveCaseSubscription } from './subscription.js';
|
|
12
13
|
/**
|
|
13
14
|
* Case's check options from a library the CLI already opened, or `{}` without one.
|
|
@@ -16,22 +17,36 @@ import { EVENT_GENERIC_NO_OBJECT, GenericEventNoObjectError, resolveCaseSubscrip
|
|
|
16
17
|
* the operation and event resolution (the event through `resolveCaseSubscription`,
|
|
17
18
|
* compile's own call), a connector task's field contract and lookups (the
|
|
18
19
|
* `=`-expression validator Case compile runs), and the schema-readiness warnings.
|
|
19
|
-
*
|
|
20
|
-
* `serialize`
|
|
20
|
+
* With `bindings`, the binding-label rules (BINDING_SELF_NAME, BINDING_UNDECLARED),
|
|
21
|
+
* which Case `serialize` enforces through the same `bindingLabelRefusal`. The
|
|
22
|
+
* BYOA hooks of the shared bag are left out, because Case `serialize` does not
|
|
23
|
+
* enforce them.
|
|
21
24
|
*
|
|
22
25
|
* @param library - The library `openCliLibrary` returned, or `undefined`.
|
|
26
|
+
* @param bindings - The project's bindings.json, as compile reads it.
|
|
23
27
|
* @returns The options for Case `check`.
|
|
24
28
|
*/
|
|
25
|
-
export function caseCheckOpts(library) {
|
|
29
|
+
export function caseCheckOpts(library, bindings) {
|
|
26
30
|
if (!library)
|
|
27
|
-
return {};
|
|
28
|
-
const shared = connectorCheckOpts(library);
|
|
31
|
+
return bindings ? { bindings } : {};
|
|
32
|
+
const shared = connectorCheckOpts(library, bindings);
|
|
29
33
|
return {
|
|
34
|
+
...(bindings ? { bindings } : {}),
|
|
30
35
|
connectorResolveError: shared.connectorResolveError,
|
|
31
36
|
connectorInputs: shared.connectorInputs,
|
|
32
37
|
lookups: shared.lookups,
|
|
33
38
|
resolutions: shared.resolutions,
|
|
34
39
|
schemaReadiness: shared.schemaReadiness,
|
|
40
|
+
externalDescriptorError: (kind, d) => {
|
|
41
|
+
let rc;
|
|
42
|
+
try {
|
|
43
|
+
rc = library.resolve(d.key, d.action, d.version, d.object);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined; // connectorResolveError's to report
|
|
47
|
+
}
|
|
48
|
+
return externalDescriptorRefusal(kind, rc);
|
|
49
|
+
},
|
|
35
50
|
subscriptionError: (kind, sub) => {
|
|
36
51
|
try {
|
|
37
52
|
resolveCaseSubscription(library, kind, sub);
|
package/dist/case/compile-cli.js
CHANGED
|
@@ -49,7 +49,9 @@ export async function run(argv) {
|
|
|
49
49
|
// which is what the three copies of these lines used to each decide for itself.
|
|
50
50
|
// Opened BEFORE the check pass, which reads the same library (#1014).
|
|
51
51
|
const library = openCliLibrary(argv);
|
|
52
|
-
const
|
|
52
|
+
const bindFile = flagValue(argv, '--bindings') ?? defaultBindingsFile();
|
|
53
|
+
const bindings = new Bindings(bindFile);
|
|
54
|
+
const diags = check(built, caseCheckOpts(library, bindings));
|
|
53
55
|
for (const d of diags)
|
|
54
56
|
console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
|
|
55
57
|
// Reported before serialize, so every exit path carries what stderr printed.
|
|
@@ -59,8 +61,6 @@ export async function run(argv) {
|
|
|
59
61
|
console.error(`compile: ${errors.length} error(s); not emitting.`);
|
|
60
62
|
return 1;
|
|
61
63
|
}
|
|
62
|
-
const bindFile = flagValue(argv, '--bindings') ?? defaultBindingsFile();
|
|
63
|
-
const bindings = new Bindings(bindFile);
|
|
64
64
|
let caseplan;
|
|
65
65
|
try {
|
|
66
66
|
caseplan = serialize(built, { library, bindings });
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* case/external — the descriptor contract of an External Agent / External
|
|
3
|
+
* Workflow task, shared by Case `serialize` (which throws it) and Case `check`
|
|
4
|
+
* (which reports it as EXTERNAL_TASK_DESCRIPTOR_CONTRACT), so the two refuse the
|
|
5
|
+
* same descriptors with the same text (#1035).
|
|
6
|
+
*
|
|
7
|
+
* The task's inputs are not here: they go through the shared
|
|
8
|
+
* `buildConnectorInputs`, which `check` already runs as `connectorInputs`.
|
|
9
|
+
*/
|
|
10
|
+
import type { ResolvedConnector } from '../core/library.js';
|
|
11
|
+
/** Check's code for {@link externalDescriptorRefusal}. */
|
|
12
|
+
export declare const EXTERNAL_TASK_DESCRIPTOR_CONTRACT = "EXTERNAL_TASK_DESCRIPTOR_CONTRACT";
|
|
13
|
+
/**
|
|
14
|
+
* Why a resolved descriptor cannot back this external task, or `undefined`.
|
|
15
|
+
*
|
|
16
|
+
* An External Agent task needs an `AgentExecution` operation and an External
|
|
17
|
+
* Workflow task a `ProcessExecution` one: the service type the task emits
|
|
18
|
+
* (`Intsvc.SyncAgentExecution`, …) is chosen by the family, and a descriptor of
|
|
19
|
+
* the other kind (or a plain connector action) would run the wrong contract.
|
|
20
|
+
* Both need the operation's `uiPathActivityTypeId`, which the task emits as its
|
|
21
|
+
* `activity` context.
|
|
22
|
+
*
|
|
23
|
+
* @param kind - The task kind.
|
|
24
|
+
* @param rc - What `library.resolve` returned for the task's descriptor.
|
|
25
|
+
* @returns The refusal, or `undefined`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function externalDescriptorRefusal(kind: 'external-agent' | 'external-workflow', rc: Pick<ResolvedConnector, 'nodeType' | 'version' | 'activityTypeId' | 'entry'>): string | undefined;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Check's code for {@link externalDescriptorRefusal}. */
|
|
2
|
+
export const EXTERNAL_TASK_DESCRIPTOR_CONTRACT = 'EXTERNAL_TASK_DESCRIPTOR_CONTRACT';
|
|
3
|
+
/**
|
|
4
|
+
* Why a resolved descriptor cannot back this external task, or `undefined`.
|
|
5
|
+
*
|
|
6
|
+
* An External Agent task needs an `AgentExecution` operation and an External
|
|
7
|
+
* Workflow task a `ProcessExecution` one: the service type the task emits
|
|
8
|
+
* (`Intsvc.SyncAgentExecution`, …) is chosen by the family, and a descriptor of
|
|
9
|
+
* the other kind (or a plain connector action) would run the wrong contract.
|
|
10
|
+
* Both need the operation's `uiPathActivityTypeId`, which the task emits as its
|
|
11
|
+
* `activity` context.
|
|
12
|
+
*
|
|
13
|
+
* @param kind - The task kind.
|
|
14
|
+
* @param rc - What `library.resolve` returned for the task's descriptor.
|
|
15
|
+
* @returns The refusal, or `undefined`.
|
|
16
|
+
*/
|
|
17
|
+
export function externalDescriptorRefusal(kind, rc) {
|
|
18
|
+
const op = rc.entry?.operation ?? {};
|
|
19
|
+
const expectedSubType = kind === 'external-agent' ? 'AgentExecution' : 'ProcessExecution';
|
|
20
|
+
if (op.subType !== expectedSubType)
|
|
21
|
+
return `${kind} task requires a ${expectedSubType} descriptor; resolved ${String(op.subType ?? 'no subtype')}.`;
|
|
22
|
+
if (!rc.activityTypeId)
|
|
23
|
+
return `${kind} task descriptor ${rc.nodeType}@${rc.version} has no uiPathActivityTypeId.`;
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
package/dist/case/serialize.js
CHANGED
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
import { IdGen } from './ids.js';
|
|
12
12
|
import { buildConnectorInputs, nestConnectorBody, transportHttpMethod } from '../core/connector-inputs.js';
|
|
13
13
|
import { EQUALS_EXPR_DIALECT } from '../core/connector-checks.js';
|
|
14
|
+
import { bindingLabelRefusal } from '../core/binding-messages.js';
|
|
14
15
|
import { resolveEventWhere } from '../core/lookups.js';
|
|
15
16
|
import { resolveCaseSubscription } from './subscription.js';
|
|
17
|
+
import { externalDescriptorRefusal } from './external.js';
|
|
16
18
|
import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
17
19
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
18
20
|
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
@@ -176,12 +178,13 @@ export function serialize(built, opts = {}) {
|
|
|
176
178
|
const context = [];
|
|
177
179
|
if (connector) {
|
|
178
180
|
context.push(io('connectorKey', 'string', { value: connector.connectorKey }));
|
|
179
|
-
const
|
|
181
|
+
const site = { where: 'select-next-stage connector', target: { key: connector.connectorKey } };
|
|
182
|
+
const connection = bindingRef(resolver, connector.connection, 'Connection', 'ConnectionId', `${connector.connectorKey} connection`, { ...site, attribute: 'connection' });
|
|
180
183
|
if (connection) {
|
|
181
184
|
context.push(io('connection', 'string', { value: `=bindings.${connection.id}` }));
|
|
182
185
|
context.push(io('resourceKey', 'string', { value: connection.resourceKey }));
|
|
183
186
|
}
|
|
184
|
-
const folder = bindingRef(resolver, connector.folder, 'Connection', 'folderKey', 'FolderKey');
|
|
187
|
+
const folder = bindingRef(resolver, connector.folder, 'Connection', 'folderKey', 'FolderKey', { ...site, attribute: 'folder' });
|
|
185
188
|
if (folder)
|
|
186
189
|
context.push(io('folderKey', 'string', { value: `=bindings.${folder.id}` }));
|
|
187
190
|
}
|
|
@@ -696,7 +699,7 @@ function emitTriggers(triggers, ids, resolver) {
|
|
|
696
699
|
// placeholder. A subscription resolves through the same library/binding
|
|
697
700
|
// machinery as connector tasks and wait-for-connector bags.
|
|
698
701
|
const bag = t.eventSubscription
|
|
699
|
-
? resolvedSubscriptionBag('trigger', t.eventSubscription, resolver, triggerId)
|
|
702
|
+
? resolvedSubscriptionBag('trigger', t.eventSubscription, resolver, triggerId, `Event trigger "${label}"`)
|
|
700
703
|
: { serviceType: CASE_FORMAT_PROFILE.eventServiceType };
|
|
701
704
|
if (t.eventOutputs?.length) {
|
|
702
705
|
const outputs = t.eventOutputs.map((o) => {
|
|
@@ -835,10 +838,10 @@ function taskData(task, resolver, taskId, stageId, ids) {
|
|
|
835
838
|
return data;
|
|
836
839
|
}
|
|
837
840
|
case 'connector':
|
|
838
|
-
return connectorTaskData(task.connector, resolver, taskId);
|
|
841
|
+
return connectorTaskData(task.connector, resolver, taskId, `Connector task "${task.name}"`);
|
|
839
842
|
case 'external-agent':
|
|
840
843
|
case 'external-workflow':
|
|
841
|
-
return externalTaskData(task.kind, task.external, resolver);
|
|
844
|
+
return externalTaskData(task.kind, task.external, resolver, `${task.kind === 'external-agent' ? 'External Agent' : 'External Workflow'} task "${task.name}"`);
|
|
842
845
|
case 'wait-for-timer': {
|
|
843
846
|
if (task.timer?.duration)
|
|
844
847
|
return { timerType: 'timeDuration', timeDuration: task.timer.duration };
|
|
@@ -851,7 +854,7 @@ function taskData(task, resolver, taskId, stageId, ids) {
|
|
|
851
854
|
case 'wait-for-connector':
|
|
852
855
|
// Floor placeholder (no connector named) = `serviceType` only; naming the
|
|
853
856
|
// connector/operation emits the `context` subscription.
|
|
854
|
-
return waitConnectorBag(task.waitConnector, { alwaysContext: false }, resolver, `${stageId}-${taskId}`);
|
|
857
|
+
return waitConnectorBag(task.waitConnector, { alwaysContext: false }, resolver, `${stageId}-${taskId}`, `Wait-for-connector task "${task.name}"`);
|
|
855
858
|
}
|
|
856
859
|
}
|
|
857
860
|
/**
|
|
@@ -862,9 +865,9 @@ function taskData(task, resolver, taskId, stageId, ids) {
|
|
|
862
865
|
* and empty `inputs`/`outputs`/`bindings`. A *rule* always carries the context —
|
|
863
866
|
* `validate` rejects a bare `uipath` ("connector activity missing").
|
|
864
867
|
*/
|
|
865
|
-
function waitConnectorBag(spec, opts, resolver, elementId) {
|
|
868
|
+
function waitConnectorBag(spec, opts, resolver, elementId, where) {
|
|
866
869
|
if (isResolvedSubscription(spec))
|
|
867
|
-
return resolvedSubscriptionBag('event', spec, resolver, elementId);
|
|
870
|
+
return resolvedSubscriptionBag('event', spec, resolver, elementId, where);
|
|
868
871
|
const bag = { serviceType: CASE_FORMAT_PROFILE.waitConnectorServiceType };
|
|
869
872
|
const named = spec?.connectorKey !== undefined || spec?.operation !== undefined;
|
|
870
873
|
if (opts.alwaysContext || named) {
|
|
@@ -883,19 +886,20 @@ function isResolvedSubscription(spec) {
|
|
|
883
886
|
}
|
|
884
887
|
/** Resolve a Case event/wait subscription into the designer/runtime bag pinned
|
|
885
888
|
* by the archived v1 artifacts. Placeholder bags never enter this path. */
|
|
886
|
-
function resolvedSubscriptionBag(kind, spec, resolver, elementId) {
|
|
889
|
+
function resolvedSubscriptionBag(kind, spec, resolver, elementId, where) {
|
|
887
890
|
if (!resolver.library)
|
|
888
891
|
throw new Error(`${kind === 'trigger' ? 'event trigger' : 'wait-for-connector'} needs the connector library — `
|
|
889
892
|
+ `pass { library } to serialize or use uip maestro case compile --library.`);
|
|
890
893
|
const rc = resolveCaseSubscription(resolver.library, kind, spec);
|
|
891
894
|
const op = rc.entry.operation ?? {};
|
|
892
895
|
const context = [io('connectorKey', 'string', { value: rc.connectorKey })];
|
|
893
|
-
const
|
|
896
|
+
const target = { key: spec.connector, action: spec.event };
|
|
897
|
+
const connection = bindingRef(resolver, spec.connection, 'Connection', 'ConnectionId', `${rc.connectorKey} connection`, { attribute: 'connection', where, target });
|
|
894
898
|
if (connection) {
|
|
895
899
|
context.push(io('connection', 'string', { value: `=bindings.${connection.id}` }));
|
|
896
900
|
context.push(io('resourceKey', 'string', { value: connection.resourceKey }));
|
|
897
901
|
}
|
|
898
|
-
const folder = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey');
|
|
902
|
+
const folder = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
|
|
899
903
|
if (folder)
|
|
900
904
|
context.push(io('folderKey', 'string', { value: `=bindings.${folder.id}` }));
|
|
901
905
|
context.push(io('method', 'string', {}), io('path', 'string', {}), io('objectName', 'string', { value: op.objectName ?? spec.event }), io('operation', 'string', { value: op.eventOperation ?? spec.event }), io('metadata', 'json', { body: subscriptionMetadata(rc, op, spec.filters ?? [], elementId) }));
|
|
@@ -1076,7 +1080,7 @@ function emitTaskOutput(o, elementId, ids, seed, resolver) {
|
|
|
1076
1080
|
* the op's output schema. Connection/folder resolve through `bindings` and are
|
|
1077
1081
|
* referenced as `=bindings.<id>`, with the binding entry collected at case root.
|
|
1078
1082
|
*/
|
|
1079
|
-
function connectorTaskData(spec, resolver, elementId) {
|
|
1083
|
+
function connectorTaskData(spec, resolver, elementId, where) {
|
|
1080
1084
|
if (!resolver.library)
|
|
1081
1085
|
throw new Error(`connector task needs the connector library — pass { library } to serialize or use uip maestro case compile --library.`);
|
|
1082
1086
|
const rc = resolver.library.resolve(spec.key, spec.action, spec.version, spec.object);
|
|
@@ -1085,12 +1089,13 @@ function connectorTaskData(spec, resolver, elementId) {
|
|
|
1085
1089
|
io('connectorKey', 'string', { value: rc.connectorKey }),
|
|
1086
1090
|
];
|
|
1087
1091
|
// connection + folder → root bindings, referenced by id.
|
|
1088
|
-
const
|
|
1092
|
+
const target = { key: spec.key, action: spec.action };
|
|
1093
|
+
const connRef = bindingRef(resolver, spec.connection, 'Connection', 'ConnectionId', `${rc.connectorKey} connection`, { attribute: 'connection', where, target });
|
|
1089
1094
|
if (connRef) {
|
|
1090
1095
|
context.push(io('connection', 'string', { value: `=bindings.${connRef.id}` }));
|
|
1091
1096
|
context.push(io('resourceKey', 'string', { value: connRef.resourceKey }));
|
|
1092
1097
|
}
|
|
1093
|
-
const folderRef = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey');
|
|
1098
|
+
const folderRef = bindingRef(resolver, spec.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
|
|
1094
1099
|
if (folderRef)
|
|
1095
1100
|
context.push(io('folderKey', 'string', { value: `=bindings.${folderRef.id}` }));
|
|
1096
1101
|
context.push(io('objectName', 'string', { value: op.objectName ?? spec.action }), io('method', 'string', { value: transportHttpMethod(rc.httpMethod) }), io('path', 'string', { value: rc.endpoint }), io('metadata', 'json', { body: connectorMetadata(rc, op) }));
|
|
@@ -1127,20 +1132,18 @@ function connectorTaskData(spec, resolver, elementId) {
|
|
|
1127
1132
|
const outputs = connectorOutputs(rc, elementId, resolver);
|
|
1128
1133
|
return { serviceType: CASE_FORMAT_PROFILE.connectorActivityServiceType, context, inputs, outputs, bindings: [] };
|
|
1129
1134
|
}
|
|
1130
|
-
function externalTaskData(kind, spec, resolver) {
|
|
1135
|
+
function externalTaskData(kind, spec, resolver, where) {
|
|
1131
1136
|
if (!resolver.library)
|
|
1132
1137
|
throw new Error(`${kind} task needs the connector library — pass { library } to serialize or use uip maestro case compile --library.`);
|
|
1133
1138
|
const rc = resolver.library.resolve(spec.connector.key, spec.connector.action, spec.connector.version, spec.connector.object);
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
throw new Error(`${kind} task requires a ${expectedSubType} descriptor; resolved ${String(op.subType ?? 'no subtype')}.`);
|
|
1138
|
-
if (!rc.activityTypeId)
|
|
1139
|
-
throw new Error(`${kind} task descriptor ${rc.nodeType}@${rc.version} has no uiPathActivityTypeId.`);
|
|
1139
|
+
const refused = externalDescriptorRefusal(kind, rc);
|
|
1140
|
+
if (refused)
|
|
1141
|
+
throw new Error(refused);
|
|
1140
1142
|
if (spec.mode !== 'sync' && spec.mode !== 'async')
|
|
1141
1143
|
throw new Error(`${kind} task mode must be "sync" or "async".`);
|
|
1142
|
-
const
|
|
1143
|
-
const
|
|
1144
|
+
const target = { key: spec.connector.key, action: spec.connector.action };
|
|
1145
|
+
const connection = bindingRef(resolver, spec.connector.connection, 'Connection', 'ConnectionId', `${rc.connectorKey} connection`, { attribute: 'connection', where, target });
|
|
1146
|
+
const folder = bindingRef(resolver, spec.connector.folder, 'Connection', 'folderKey', 'FolderKey', { attribute: 'folder', where, target });
|
|
1144
1147
|
if (!connection || !folder)
|
|
1145
1148
|
throw new Error(`${kind} task requires non-empty connection and folder binding names.`);
|
|
1146
1149
|
const serviceType = kind === 'external-agent'
|
|
@@ -1150,13 +1153,18 @@ function externalTaskData(kind, spec, resolver) {
|
|
|
1150
1153
|
: (spec.mode === 'sync'
|
|
1151
1154
|
? CASE_FORMAT_PROFILE.externalWorkflowSyncServiceType
|
|
1152
1155
|
: CASE_FORMAT_PROFILE.externalWorkflowAsyncServiceType);
|
|
1156
|
+
// The inputs: the shared validator every connector activity runs (unknown,
|
|
1157
|
+
// missing required or mistyped input; a `lookup()` swapped for its recorded id,
|
|
1158
|
+
// or refused). Case `check` reports the same through `connectorInputs`.
|
|
1153
1159
|
const fields = new Map(rc.fields.map((field) => [field.name, field]));
|
|
1154
|
-
const
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
+
const slots = buildConnectorInputs(rc, spec.connector.inputs, {
|
|
1161
|
+
dialect: EQUALS_EXPR_DIALECT,
|
|
1162
|
+
resolutions: resolver.library.lookupResolutions,
|
|
1163
|
+
lookups: resolver.library.lookupSpecs(spec.connector.key, spec.connector.action, spec.connector.version, spec.connector.object),
|
|
1164
|
+
});
|
|
1165
|
+
const resolved = {
|
|
1166
|
+
...slots.bodyParameters, ...slots.pathParameters, ...slots.queryParameters,
|
|
1167
|
+
};
|
|
1160
1168
|
const responseVar = connectorOutputVar(resolver, 'response');
|
|
1161
1169
|
return {
|
|
1162
1170
|
serviceType,
|
|
@@ -1172,7 +1180,7 @@ function externalTaskData(kind, spec, resolver) {
|
|
|
1172
1180
|
id: name,
|
|
1173
1181
|
name,
|
|
1174
1182
|
type: jsonType(fields.get(name)?.type),
|
|
1175
|
-
value,
|
|
1183
|
+
value: name in resolved ? resolved[name] : value,
|
|
1176
1184
|
target: name,
|
|
1177
1185
|
})),
|
|
1178
1186
|
outputs: [{
|
|
@@ -1196,9 +1204,17 @@ function ioSlot(name, bodyObj, elementId) {
|
|
|
1196
1204
|
}
|
|
1197
1205
|
/** Resolve a symbolic connection/folder to a root binding entry (collected once),
|
|
1198
1206
|
* returning its id + resourceKey for the `=bindings.<id>` reference. */
|
|
1199
|
-
function bindingRef(resolver, name, resource, propertyAttribute, displayName) {
|
|
1207
|
+
function bindingRef(resolver, name, resource, propertyAttribute, displayName, site) {
|
|
1200
1208
|
if (!name)
|
|
1201
1209
|
return undefined;
|
|
1210
|
+
// A label compile cannot turn into a resource key: one bindings.json answers
|
|
1211
|
+
// with the label itself, or a populated one does not declare it. Falling back
|
|
1212
|
+
// to the label emitted it as the binding's resourceKey, and the run faulted
|
|
1213
|
+
// with "'Connection' has an invalid GUID value" (#1034). Same refusal, same
|
|
1214
|
+
// text, as Flow compile and every family's check (`bindingLabelRefusal`).
|
|
1215
|
+
const refused = bindingLabelRefusal(resolver.bindings, name, site.attribute, site.where, site.target);
|
|
1216
|
+
if (refused)
|
|
1217
|
+
throw refused;
|
|
1202
1218
|
const entry = resolver.bindings?.entry(name);
|
|
1203
1219
|
const id = entry?.id ?? name;
|
|
1204
1220
|
const resourceKey = entry?.resourceKey ?? entry?.default ?? name;
|
|
@@ -1321,10 +1337,11 @@ function toCamel(s) {
|
|
|
1321
1337
|
return s.replace(/_([a-z0-9])/gi, (_m, c) => String(c).toUpperCase());
|
|
1322
1338
|
}
|
|
1323
1339
|
// ─── Conditions & rules ───────────────────────────────────────────────────────
|
|
1324
|
-
|
|
1325
|
-
|
|
1340
|
+
/** `site` names the condition as Case `check` does (`stage "S" entry`), for refusals. */
|
|
1341
|
+
function emitRules(rules, seed, ownerId, ids, resolver, site) {
|
|
1342
|
+
return rules.map((group, gi) => group.map((r, ri) => emitRule(r, `${seed}:${gi}:${ri}`, ownerId, ids, resolver, site)));
|
|
1326
1343
|
}
|
|
1327
|
-
function emitRule(r, seed, ownerId, ids, resolver) {
|
|
1344
|
+
function emitRule(r, seed, ownerId, ids, resolver, site) {
|
|
1328
1345
|
const ruleId = ids.ruleId(seed);
|
|
1329
1346
|
const out = { rule: r.rule, id: ruleId };
|
|
1330
1347
|
if (r.rule === 'selected-stage-completed' || r.rule === 'selected-stage-exited') {
|
|
@@ -1344,7 +1361,7 @@ function emitRule(r, seed, ownerId, ids, resolver) {
|
|
|
1344
1361
|
}
|
|
1345
1362
|
if (r.rule === 'wait-for-connector') {
|
|
1346
1363
|
// A rule always carries the subscription under `uipath` (placeholder-safe).
|
|
1347
|
-
out[CASE_FORMAT_PROFILE.waitConnectorRuleBagField] = waitConnectorBag(r.connector, { alwaysContext: true }, resolver, `${ownerId}-${ruleId}`);
|
|
1364
|
+
out[CASE_FORMAT_PROFILE.waitConnectorRuleBagField] = waitConnectorBag(r.connector, { alwaysContext: true }, resolver, `${ownerId}-${ruleId}`, `wait-for-connector rule in ${site}`);
|
|
1348
1365
|
}
|
|
1349
1366
|
if (r.rule === 'sla-status-change') {
|
|
1350
1367
|
// Resolve the SLA (and, for at-risk, the escalation) by displayName → the
|
|
@@ -1368,7 +1385,7 @@ function emitEntry(c, seed, ownerId, label, ids, resolver) {
|
|
|
1368
1385
|
const out = {
|
|
1369
1386
|
id: ids.conditionId(seed),
|
|
1370
1387
|
displayName: resolver.conditionName(c.displayName, `${label} entry`),
|
|
1371
|
-
rules: emitRules(c.rules, seed, ownerId, ids, resolver),
|
|
1388
|
+
rules: emitRules(c.rules, seed, ownerId, ids, resolver, `stage "${label}" entry`),
|
|
1372
1389
|
};
|
|
1373
1390
|
if (c.isInterrupting !== undefined)
|
|
1374
1391
|
out.isInterrupting = c.isInterrupting;
|
|
@@ -1378,7 +1395,7 @@ function emitExit(c, seed, ownerId, label, ids, resolver) {
|
|
|
1378
1395
|
const out = {
|
|
1379
1396
|
id: ids.conditionId(seed),
|
|
1380
1397
|
displayName: resolver.conditionName(c.displayName, `${label} ${c.marksStageComplete ? 'complete' : 'exit'}`),
|
|
1381
|
-
rules: emitRules(c.rules, seed, ownerId, ids, resolver),
|
|
1398
|
+
rules: emitRules(c.rules, seed, ownerId, ids, resolver, `stage "${label}" exit`),
|
|
1382
1399
|
};
|
|
1383
1400
|
if (c.marksStageComplete !== undefined)
|
|
1384
1401
|
out.marksStageComplete = c.marksStageComplete;
|
|
@@ -1396,7 +1413,7 @@ function emitTaskEntry(c, seed, ownerId, label, ids, resolver) {
|
|
|
1396
1413
|
return {
|
|
1397
1414
|
id: ids.conditionId(seed),
|
|
1398
1415
|
displayName: resolver.conditionName(c.displayName, `${label} entry`),
|
|
1399
|
-
rules: emitRules(c.rules, seed, ownerId, ids, resolver),
|
|
1416
|
+
rules: emitRules(c.rules, seed, ownerId, ids, resolver, `task "${label}" entry`),
|
|
1400
1417
|
};
|
|
1401
1418
|
}
|
|
1402
1419
|
function emitCaseExit(c, i, ids, resolver) {
|
|
@@ -1404,7 +1421,7 @@ function emitCaseExit(c, i, ids, resolver) {
|
|
|
1404
1421
|
const out = {
|
|
1405
1422
|
id: ids.conditionId(seed),
|
|
1406
1423
|
displayName: resolver.conditionName(c.displayName, 'Case complete'),
|
|
1407
|
-
rules: emitRules(c.rules, seed, 'root', ids, resolver),
|
|
1424
|
+
rules: emitRules(c.rules, seed, 'root', ids, resolver, 'case exit'),
|
|
1408
1425
|
};
|
|
1409
1426
|
if (c.marksCaseComplete !== undefined)
|
|
1410
1427
|
out.marksCaseComplete = c.marksCaseComplete;
|
|
@@ -26,6 +26,7 @@ export function registerCaseCommands(program) {
|
|
|
26
26
|
// check-cli sees argv.
|
|
27
27
|
.option('--library <dir>', 'connector library directory')
|
|
28
28
|
.option('--connectors-local <dir>', 'connection-resolved connector overlay')
|
|
29
|
+
.option('--bindings <file>', 'bindings.json, for the connection/folder label rules')
|
|
29
30
|
.addOption(retiredCompiledOption())
|
|
30
31
|
.action(async (input, options) => {
|
|
31
32
|
let mode;
|
|
@@ -43,6 +44,7 @@ export function registerCaseCommands(program) {
|
|
|
43
44
|
const argv = [input];
|
|
44
45
|
addValue(argv, '--library', options.library);
|
|
45
46
|
addValue(argv, '--connectors-local', options.connectorsLocal);
|
|
47
|
+
addValue(argv, '--bindings', options.bindings);
|
|
46
48
|
await invoke('case check', () => loadTool(import.meta.url, '../../case/check-cli.js'), argv);
|
|
47
49
|
});
|
|
48
50
|
family.command('decompile')
|
|
@@ -43,6 +43,27 @@ export declare function bindingSelfNameMessage(where: string, name: string, attr
|
|
|
43
43
|
* with nothing real to bind is meant to take.
|
|
44
44
|
*/
|
|
45
45
|
export declare function undeclaredBinding(bindings: BindingsView | undefined, name: string): string[] | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* The refusal for one connection/folder label `compile` cannot turn into a
|
|
48
|
+
* resource key, or `undefined` when the label is acceptable.
|
|
49
|
+
*
|
|
50
|
+
* - `BINDING_SELF_NAME`: bindings.json declares the label and answers with the
|
|
51
|
+
* label itself.
|
|
52
|
+
* - `BINDING_UNDECLARED`: a POPULATED bindings.json does not declare it, and it
|
|
53
|
+
* is not a GUID ({@link undeclaredBinding}).
|
|
54
|
+
*
|
|
55
|
+
* Silent without a bindings.json, or with an empty one: offline authoring. One
|
|
56
|
+
* function for every family's `serialize` (which throws the result) and the
|
|
57
|
+
* shared `check` rule (which reports it), so all print the same sentence.
|
|
58
|
+
*
|
|
59
|
+
* @param bindings - The project's bindings.json, if any.
|
|
60
|
+
* @param name - The authored label.
|
|
61
|
+
* @param attribute - Which half of the pair it is.
|
|
62
|
+
* @param where - The site, prefixed to the message.
|
|
63
|
+
* @param target - The connector and operation, for the `prepare` remedy.
|
|
64
|
+
* @returns The refusal, or `undefined`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function bindingLabelRefusal(bindings: BindingsView | undefined, name: string, attribute: 'connection' | 'folder', where: string, target?: PrepareTarget): BindingRefusal | undefined;
|
|
46
67
|
/**
|
|
47
68
|
* The connector and operation a label belongs to, when the call site knows them:
|
|
48
69
|
* a connector step's `key` + `action`, an event's `connector` + `event`. With it
|
|
@@ -58,6 +58,39 @@ export function undeclaredBinding(bindings, name) {
|
|
|
58
58
|
return undefined;
|
|
59
59
|
return declared;
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* The refusal for one connection/folder label `compile` cannot turn into a
|
|
63
|
+
* resource key, or `undefined` when the label is acceptable.
|
|
64
|
+
*
|
|
65
|
+
* - `BINDING_SELF_NAME`: bindings.json declares the label and answers with the
|
|
66
|
+
* label itself.
|
|
67
|
+
* - `BINDING_UNDECLARED`: a POPULATED bindings.json does not declare it, and it
|
|
68
|
+
* is not a GUID ({@link undeclaredBinding}).
|
|
69
|
+
*
|
|
70
|
+
* Silent without a bindings.json, or with an empty one: offline authoring. One
|
|
71
|
+
* function for every family's `serialize` (which throws the result) and the
|
|
72
|
+
* shared `check` rule (which reports it), so all print the same sentence.
|
|
73
|
+
*
|
|
74
|
+
* @param bindings - The project's bindings.json, if any.
|
|
75
|
+
* @param name - The authored label.
|
|
76
|
+
* @param attribute - Which half of the pair it is.
|
|
77
|
+
* @param where - The site, prefixed to the message.
|
|
78
|
+
* @param target - The connector and operation, for the `prepare` remedy.
|
|
79
|
+
* @returns The refusal, or `undefined`.
|
|
80
|
+
*/
|
|
81
|
+
export function bindingLabelRefusal(bindings, name, attribute, where, target) {
|
|
82
|
+
if (!bindings)
|
|
83
|
+
return undefined;
|
|
84
|
+
const resolved = bindings.resolve(name);
|
|
85
|
+
if (resolved === name)
|
|
86
|
+
return new BindingRefusal('BINDING_SELF_NAME', bindingSelfNameMessage(where, name, attribute, target));
|
|
87
|
+
if (resolved === undefined) {
|
|
88
|
+
const declared = undeclaredBinding(bindings, name);
|
|
89
|
+
if (declared)
|
|
90
|
+
return new BindingRefusal('BINDING_UNDECLARED', bindingUndeclaredMessage(where, name, attribute, declared, target));
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
61
94
|
function prepareFor(target) {
|
|
62
95
|
return prepareCommand(target?.key ?? '<connector-key>', target?.action ?? '<action>');
|
|
63
96
|
}
|
|
@@ -26,7 +26,7 @@ import { isLookupToken, resolvedValue, } from './lookups.js';
|
|
|
26
26
|
import { Expr } from './expr.js';
|
|
27
27
|
import { extractRefs } from './expr-check.js';
|
|
28
28
|
import { prepareCommand, resolveFlagArg } from './cli-spelling.js';
|
|
29
|
-
import {
|
|
29
|
+
import { bindingLabelRefusal, bindingMissingMessage, connectionConnectorConflictMessage, missingBindingLabels, } from './binding-messages.js';
|
|
30
30
|
/**
|
|
31
31
|
* Flow: an input is an {@link Expr} object. A non-literal one is runtime; a
|
|
32
32
|
* literal one (`lit(…)`) carries the constant it was built from.
|
|
@@ -370,16 +370,9 @@ use) {
|
|
|
370
370
|
const name = labels[attribute];
|
|
371
371
|
if (typeof name !== 'string')
|
|
372
372
|
continue;
|
|
373
|
-
const
|
|
374
|
-
if (
|
|
375
|
-
report(
|
|
376
|
-
}
|
|
377
|
-
else if (resolved === undefined) {
|
|
378
|
-
const declared = undeclaredBinding(bindings, name);
|
|
379
|
-
if (declared) {
|
|
380
|
-
report('BINDING_UNDECLARED', bindingUndeclaredMessage(where, name, attribute, declared, target));
|
|
381
|
-
}
|
|
382
|
-
}
|
|
373
|
+
const refused = bindingLabelRefusal(bindings, name, attribute, where, target);
|
|
374
|
+
if (refused)
|
|
375
|
+
report(refused.code, refused.message);
|
|
383
376
|
}
|
|
384
377
|
}
|
|
385
378
|
/**
|
package/dist/serialize.js
CHANGED
|
@@ -18,7 +18,7 @@ import { planContributionBindings } from './core/contribution-bindings.js';
|
|
|
18
18
|
import { definitionHasErrorPort, errorPortRefusal } from './core/error-port.js';
|
|
19
19
|
import { isAnswerField } from './core/hitl-answers.js';
|
|
20
20
|
import { connectionConnectors } from './bindings-v2.js';
|
|
21
|
-
import { BindingRefusal, GUID_RE,
|
|
21
|
+
import { BindingRefusal, GUID_RE, bindingLabelRefusal, bindingMissingMessage, missingBindingLabels } from './core/binding-messages.js';
|
|
22
22
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
23
23
|
import { genericEventObjectRefusal } from './core/event-checks.js';
|
|
24
24
|
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
|
|
@@ -3886,16 +3886,10 @@ function requireBindingPair(where, labels, target) {
|
|
|
3886
3886
|
function resolveBinding(opts, name, attribute, where, target) {
|
|
3887
3887
|
if (name === undefined)
|
|
3888
3888
|
return undefined;
|
|
3889
|
+
const refused = bindingLabelRefusal(opts.bindings, name, attribute, where, target);
|
|
3890
|
+
if (refused)
|
|
3891
|
+
throw refused;
|
|
3889
3892
|
const resolved = opts.bindings?.resolve(name);
|
|
3890
|
-
if (resolved === name) {
|
|
3891
|
-
throw new BindingRefusal('BINDING_SELF_NAME', bindingSelfNameMessage(where, name, attribute, target));
|
|
3892
|
-
}
|
|
3893
|
-
if (resolved === undefined) {
|
|
3894
|
-
const declared = undeclaredBinding(opts.bindings, name);
|
|
3895
|
-
if (declared) {
|
|
3896
|
-
throw new BindingRefusal('BINDING_UNDECLARED', bindingUndeclaredMessage(where, name, attribute, declared, target));
|
|
3897
|
-
}
|
|
3898
|
-
}
|
|
3899
3893
|
const value = resolved ?? name;
|
|
3900
3894
|
const reason = connectionStubReason(value);
|
|
3901
3895
|
if (reason !== undefined && opts.warn) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.18.
|
|
3
|
+
"version": "6.18.6",
|
|
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": "27768f00ecc6986a54deba3c8f327d01ace642f8"
|
|
96
96
|
}
|