@uipath/maestro-builder-sdk 6.18.0 → 6.18.2
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 +18 -4
- package/dist/case/check.d.ts +37 -1
- package/dist/case/check.js +76 -2
- package/dist/case/cli-library.d.ts +15 -0
- package/dist/case/cli-library.js +44 -0
- package/dist/case/compile-cli.js +11 -9
- package/dist/case/decompile.js +2 -0
- package/dist/case/serialize.js +2 -1
- package/dist/case/subscription.d.ts +30 -0
- package/dist/case/subscription.js +29 -0
- package/dist/cli/commands/case.js +10 -1
- package/dist/core/event-checks.d.ts +31 -0
- package/dist/core/event-checks.js +38 -0
- package/dist/serialize.js +7 -18
- package/package.json +2 -2
package/dist/case/check-cli.js
CHANGED
|
@@ -2,23 +2,37 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* check-cli — fast static validation of <Name>.case.ts (no output file).
|
|
4
4
|
*
|
|
5
|
-
* Usage: node --experimental-strip-types check-cli.js <case.ts | BaseName>
|
|
5
|
+
* Usage: node --experimental-strip-types check-cli.js <case.ts | BaseName> \
|
|
6
|
+
* [--library <library-json dir>] [--connectors-local <overlay dir>]
|
|
6
7
|
* Exits 0 when clean (warnings allowed), 1 on any error.
|
|
8
|
+
*
|
|
9
|
+
* The library is opened exactly as `compile-cli` opens it (`openCliLibrary`), so
|
|
10
|
+
* a connector task `compile` cannot resolve fails here first (#1014).
|
|
7
11
|
*/
|
|
8
12
|
import { reportDiagnostics } from '../cli-result.js';
|
|
9
13
|
import { resolveCaseFile, loadBuiltCase } from './load.js';
|
|
10
14
|
import { check } from './check.js';
|
|
15
|
+
import { caseCheckOpts } from './cli-library.js';
|
|
16
|
+
import { openCliLibrary } from '../core/cli-library.js';
|
|
11
17
|
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
12
18
|
import { ensureTypeScriptRuntime } from '../node-runtime.js';
|
|
19
|
+
/** 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>]';
|
|
13
22
|
export async function run(argv) {
|
|
14
23
|
if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
|
|
15
|
-
console.error(
|
|
24
|
+
console.error(USAGE);
|
|
25
|
+
return 2;
|
|
26
|
+
}
|
|
27
|
+
const input = argv.find((a, i) => !a.startsWith('--') && !VALUE_FLAGS.has(argv[i - 1]));
|
|
28
|
+
if (input === undefined) {
|
|
29
|
+
console.error(USAGE);
|
|
16
30
|
return 2;
|
|
17
31
|
}
|
|
18
|
-
const file = resolveCaseFile(
|
|
32
|
+
const file = resolveCaseFile(input);
|
|
19
33
|
ensureTypeScriptRuntime();
|
|
20
34
|
const built = await loadBuiltCase(file);
|
|
21
|
-
const diags = check(built);
|
|
35
|
+
const diags = check(built, caseCheckOpts(openCliLibrary(argv)));
|
|
22
36
|
reportDiagnostics(diags);
|
|
23
37
|
for (const d of diags)
|
|
24
38
|
console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
|
package/dist/case/check.d.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* `uip maestro case validate` / `@uipath/case-schema` on the emitted file.
|
|
9
9
|
*/
|
|
10
10
|
import type { BuiltCase } from './case-sdk.js';
|
|
11
|
+
import { type ConnectorCheckOpts } from '../core/connector-checks.js';
|
|
12
|
+
import type { EventSubscription } from '../core/actions.js';
|
|
11
13
|
export interface Diagnostic {
|
|
12
14
|
level: 'error' | 'warning';
|
|
13
15
|
code: string;
|
|
@@ -15,4 +17,38 @@ export interface Diagnostic {
|
|
|
15
17
|
where?: string;
|
|
16
18
|
suggestion?: string;
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
/**
|
|
21
|
+
* The connector-library facts Case `check` reads, from the same `Library`
|
|
22
|
+
* instance `compile` serializes against (`caseCheckOpts` in `./cli-library.ts`).
|
|
23
|
+
*
|
|
24
|
+
* Deliberately NARROWER than Flow's and BPMN's bag. An error here must be a
|
|
25
|
+
* refusal Case `compile` actually makes, and Case `serialize` resolves the
|
|
26
|
+
* connector operation and the event (`library.resolve` / `resolveEvent`) but does
|
|
27
|
+
* not validate connector inputs, binding labels or BYOA. Those rules stay off
|
|
28
|
+
* until Case compile enforces them; passing them here would refuse sources that
|
|
29
|
+
* compile accepts.
|
|
30
|
+
*
|
|
31
|
+
* Every hook fails open: without a library, `check` stays a pure function of the
|
|
32
|
+
* built model.
|
|
33
|
+
*/
|
|
34
|
+
export type CaseCheckOpts = Pick<ConnectorCheckOpts, 'connectorResolveError' | 'schemaReadiness'> & {
|
|
35
|
+
/**
|
|
36
|
+
* What Case `compile` would refuse an event subscription with, or `undefined`
|
|
37
|
+
* when it resolves: `EVENT_UNKNOWN` (the event is not in the library, or
|
|
38
|
+
* refuses the `object`) or `EVENT_GENERIC_NO_OBJECT` (a GENERIC event with no
|
|
39
|
+
* `object`). Built on `resolveCaseSubscription`, the call compile makes.
|
|
40
|
+
*/
|
|
41
|
+
subscriptionError?: (kind: 'trigger' | 'event', subscription: EventSubscription) => {
|
|
42
|
+
code: string;
|
|
43
|
+
message: string;
|
|
44
|
+
} | undefined;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Validate a built case.
|
|
48
|
+
*
|
|
49
|
+
* @param built - The case `casePlan(...).build()` returned.
|
|
50
|
+
* @param opts - Connector-library facts (see {@link CaseCheckOpts}); omit them to
|
|
51
|
+
* check only the model itself.
|
|
52
|
+
* @returns Every diagnostic found; any `error` means `compile` refuses the case.
|
|
53
|
+
*/
|
|
54
|
+
export declare function check(built: BuiltCase, opts?: CaseCheckOpts): Diagnostic[];
|
package/dist/case/check.js
CHANGED
|
@@ -2,13 +2,21 @@ 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, checkConnectorSchema, } from '../core/connector-checks.js';
|
|
5
6
|
const TYPE_NAMES = new Set(Object.values(types));
|
|
6
7
|
// audit-case-coverage: rule-slot table start
|
|
7
8
|
// This runtime table must equal the committed matrix's rejected cells. The audit
|
|
8
9
|
// parses these object literals; the product-pin matrix currently rejects none.
|
|
9
10
|
const ILLEGAL = [];
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Validate a built case.
|
|
13
|
+
*
|
|
14
|
+
* @param built - The case `casePlan(...).build()` returned.
|
|
15
|
+
* @param opts - Connector-library facts (see {@link CaseCheckOpts}); omit them to
|
|
16
|
+
* check only the model itself.
|
|
17
|
+
* @returns Every diagnostic found; any `error` means `compile` refuses the case.
|
|
18
|
+
*/
|
|
19
|
+
export function check(built, opts = {}) {
|
|
12
20
|
const diags = [];
|
|
13
21
|
for (const message of caseJsonPreservationErrors(caseJsonPreservation(built)))
|
|
14
22
|
diags.push({
|
|
@@ -252,8 +260,74 @@ export function check(built) {
|
|
|
252
260
|
refStage(r, 'case-exit');
|
|
253
261
|
refPlacement(r, 'case-exit', 'case-exit');
|
|
254
262
|
}
|
|
263
|
+
checkLibraryConnectors(built, opts, diags);
|
|
255
264
|
return diags;
|
|
256
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* The connector-library rules (#1014): every place Case `serialize` resolves a
|
|
268
|
+
* connector against the library, checked with the same call and the same text.
|
|
269
|
+
*
|
|
270
|
+
* - a connector task and an External Agent / External Workflow task resolve
|
|
271
|
+
* their operation (`library.resolve`): CONNECTOR_NOT_IN_LIBRARY,
|
|
272
|
+
* CONNECTOR_OBJECT_REQUIRED, CONNECTOR_OBJECT_NOT_GENERIC;
|
|
273
|
+
* - an event trigger, a wait-for-connector task and a wait-for-connector rule
|
|
274
|
+
* resolve their subscription (`resolveCaseSubscription`): EVENT_UNKNOWN,
|
|
275
|
+
* EVENT_GENERIC_NO_OBJECT.
|
|
276
|
+
*
|
|
277
|
+
* A connector task also gets the schema-readiness warnings, because the
|
|
278
|
+
* `connectors-local` overlay `registry prepare` writes is what Case compile
|
|
279
|
+
* resolves against too.
|
|
280
|
+
*/
|
|
281
|
+
function checkLibraryConnectors(built, opts, diags) {
|
|
282
|
+
const reporter = (_where, at) => (d) => {
|
|
283
|
+
diags.push({ level: d.level, code: d.code, message: d.message, where: at, ...(d.suggestion ? { suggestion: d.suggestion } : {}) });
|
|
284
|
+
};
|
|
285
|
+
const subscription = (kind, sub, where, at) => {
|
|
286
|
+
// The call `resolvedSubscriptionBag` makes (`resolveCaseSubscription`), so
|
|
287
|
+
// check refuses exactly what compile refuses, with the same text.
|
|
288
|
+
const refused = opts.subscriptionError?.(kind, sub);
|
|
289
|
+
if (refused !== undefined)
|
|
290
|
+
diags.push({ level: 'error', code: refused.code, message: `${where}: ${refused.message}`, where: at });
|
|
291
|
+
};
|
|
292
|
+
const rules = (conditions, where) => {
|
|
293
|
+
for (const c of conditions)
|
|
294
|
+
for (const g of c.rules)
|
|
295
|
+
for (const r of g)
|
|
296
|
+
if (r.rule === 'wait-for-connector' && isSubscription(r.connector))
|
|
297
|
+
subscription('event', r.connector, `wait-for-connector rule in ${where}`, where);
|
|
298
|
+
};
|
|
299
|
+
built.triggers.forEach((t, i) => {
|
|
300
|
+
if (t.kind !== 'event' || !t.eventSubscription)
|
|
301
|
+
return;
|
|
302
|
+
const name = t.name ?? `Trigger ${i + 1}`;
|
|
303
|
+
subscription('trigger', t.eventSubscription, `Event trigger "${name}"`, name);
|
|
304
|
+
});
|
|
305
|
+
for (const stage of built.stages) {
|
|
306
|
+
rules(stage.entry, `stage "${stage.label}" entry`);
|
|
307
|
+
rules(stage.exit, `stage "${stage.label}" exit`);
|
|
308
|
+
for (const t of stage.lanes.flat()) {
|
|
309
|
+
rules(t.entry, `task "${t.name}" entry`);
|
|
310
|
+
if (t.kind === 'connector' && t.connector) {
|
|
311
|
+
const where = `Connector task "${t.name}"`;
|
|
312
|
+
const spec = t.connector;
|
|
313
|
+
checkConnectorSchema(where, spec, opts, EQUALS_EXPR_DIALECT, reporter(where, t.name));
|
|
314
|
+
checkConnectorContract(where, spec, opts, reporter(where, t.name));
|
|
315
|
+
}
|
|
316
|
+
if ((t.kind === 'external-agent' || t.kind === 'external-workflow')
|
|
317
|
+
&& t.external?.connector?.key?.trim() && t.external.connector.action?.trim()) {
|
|
318
|
+
const where = `${t.kind === 'external-agent' ? 'External Agent' : 'External Workflow'} task "${t.name}"`;
|
|
319
|
+
checkConnectorContract(where, t.external.connector, opts, reporter(where, t.name));
|
|
320
|
+
}
|
|
321
|
+
if (t.kind === 'wait-for-connector' && isSubscription(t.waitConnector))
|
|
322
|
+
subscription('event', t.waitConnector, `Wait-for-connector task "${t.name}"`, t.name);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
rules(built.caseExit, 'case exit');
|
|
326
|
+
}
|
|
327
|
+
/** A resolved subscription, not a placeholder; the test `serialize`'s `isResolvedSubscription` makes. */
|
|
328
|
+
function isSubscription(spec) {
|
|
329
|
+
return !!spec && typeof spec === 'object' && 'connector' in spec && 'event' in spec;
|
|
330
|
+
}
|
|
257
331
|
/**
|
|
258
332
|
* SLA guardrails surfaced early: zero at-risk percentages that the engine
|
|
259
333
|
* coerces to 100, empty recipient lists, and deadlines with no escalations.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Library } from '../core/library.js';
|
|
2
|
+
import type { CaseCheckOpts } from './check.js';
|
|
3
|
+
/**
|
|
4
|
+
* Case's check options from a library the CLI already opened, or `{}` without one.
|
|
5
|
+
*
|
|
6
|
+
* Only the hooks for refusals Case `compile` makes (see {@link CaseCheckOpts}):
|
|
7
|
+
* the operation and event resolution (the event through `resolveCaseSubscription`,
|
|
8
|
+
* compile's own call), and the schema-readiness warnings. The
|
|
9
|
+
* field-contract, binding-label and BYOA hooks of the shared bag are left out,
|
|
10
|
+
* because Case `serialize` does not enforce them.
|
|
11
|
+
*
|
|
12
|
+
* @param library - The library `openCliLibrary` returned, or `undefined`.
|
|
13
|
+
* @returns The options for Case `check`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function caseCheckOpts(library: Library | undefined): CaseCheckOpts;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* case/cli-library — Case's check options, built from the shared connector hooks.
|
|
3
|
+
*
|
|
4
|
+
* `case check` took no options at all, so a connector task naming an operation
|
|
5
|
+
* the library does not carry passed `check` and failed at `compile` (#1014).
|
|
6
|
+
* Flow and BPMN read their connector facts from `connectorCheckOpts`
|
|
7
|
+
* (`core/cli-library.ts`); Case now does too, through this one builder, which
|
|
8
|
+
* both `case check` and `case compile`'s check pass call.
|
|
9
|
+
*/
|
|
10
|
+
import { connectorCheckOpts } from '../core/cli-library.js';
|
|
11
|
+
import { EVENT_GENERIC_NO_OBJECT, GenericEventNoObjectError, resolveCaseSubscription } from './subscription.js';
|
|
12
|
+
/**
|
|
13
|
+
* Case's check options from a library the CLI already opened, or `{}` without one.
|
|
14
|
+
*
|
|
15
|
+
* Only the hooks for refusals Case `compile` makes (see {@link CaseCheckOpts}):
|
|
16
|
+
* the operation and event resolution (the event through `resolveCaseSubscription`,
|
|
17
|
+
* compile's own call), and the schema-readiness warnings. The
|
|
18
|
+
* field-contract, binding-label and BYOA hooks of the shared bag are left out,
|
|
19
|
+
* because Case `serialize` does not enforce them.
|
|
20
|
+
*
|
|
21
|
+
* @param library - The library `openCliLibrary` returned, or `undefined`.
|
|
22
|
+
* @returns The options for Case `check`.
|
|
23
|
+
*/
|
|
24
|
+
export function caseCheckOpts(library) {
|
|
25
|
+
if (!library)
|
|
26
|
+
return {};
|
|
27
|
+
const shared = connectorCheckOpts(library);
|
|
28
|
+
return {
|
|
29
|
+
connectorResolveError: shared.connectorResolveError,
|
|
30
|
+
schemaReadiness: shared.schemaReadiness,
|
|
31
|
+
subscriptionError: (kind, sub) => {
|
|
32
|
+
try {
|
|
33
|
+
resolveCaseSubscription(library, kind, sub);
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
code: error instanceof GenericEventNoObjectError ? EVENT_GENERIC_NO_OBJECT : 'EVENT_UNKNOWN',
|
|
39
|
+
message: error instanceof Error ? error.message : String(error),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
package/dist/case/compile-cli.js
CHANGED
|
@@ -16,6 +16,7 @@ import { join, dirname, basename, resolve } from 'node:path';
|
|
|
16
16
|
import { resolveCaseFile, loadBuiltCase } from './load.js';
|
|
17
17
|
import { serialize } from './serialize.js';
|
|
18
18
|
import { check } from './check.js';
|
|
19
|
+
import { caseCheckOpts } from './cli-library.js';
|
|
19
20
|
import { entryPointIO } from './entry-points.js';
|
|
20
21
|
import { Bindings } from '../core/bindings.js';
|
|
21
22
|
import { openCliLibrary } from '../core/cli-library.js';
|
|
@@ -39,7 +40,16 @@ export async function run(argv) {
|
|
|
39
40
|
const file = resolveCaseFile(pos);
|
|
40
41
|
ensureTypeScriptRuntime();
|
|
41
42
|
const built = await loadBuiltCase(file);
|
|
42
|
-
|
|
43
|
+
// Connector tasks resolve against the library; load it only when present, and
|
|
44
|
+
// bindings.json from alongside the case when present. Resolved through the same
|
|
45
|
+
// helper Flow and BPMN use, so `registry pull` serves all three families —
|
|
46
|
+
// reading the env directly skipped the shared cache, and a Case that compiled
|
|
47
|
+
// fine right after a pull on Flow failed here for no visible reason. The helper
|
|
48
|
+
// also auto-detects the `connectors-local/` overlay `registry prepare` writes,
|
|
49
|
+
// which is what the three copies of these lines used to each decide for itself.
|
|
50
|
+
// Opened BEFORE the check pass, which reads the same library (#1014).
|
|
51
|
+
const library = openCliLibrary(argv);
|
|
52
|
+
const diags = check(built, caseCheckOpts(library));
|
|
43
53
|
for (const d of diags)
|
|
44
54
|
console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
|
|
45
55
|
// Reported before serialize, so every exit path carries what stderr printed.
|
|
@@ -49,14 +59,6 @@ export async function run(argv) {
|
|
|
49
59
|
console.error(`compile: ${errors.length} error(s); not emitting.`);
|
|
50
60
|
return 1;
|
|
51
61
|
}
|
|
52
|
-
// Connector tasks resolve against the library; load it only when present, and
|
|
53
|
-
// bindings.json from alongside the case when present. Resolved through the same
|
|
54
|
-
// helper Flow and BPMN use, so `registry pull` serves all three families —
|
|
55
|
-
// reading the env directly skipped the shared cache, and a Case that compiled
|
|
56
|
-
// fine right after a pull on Flow failed here for no visible reason. The helper
|
|
57
|
-
// also auto-detects the `connectors-local/` overlay `registry prepare` writes,
|
|
58
|
-
// which is what the three copies of these lines used to each decide for itself.
|
|
59
|
-
const library = openCliLibrary(argv);
|
|
60
62
|
const bindFile = flagValue(argv, '--bindings') ?? defaultBindingsFile();
|
|
61
63
|
const bindings = new Bindings(bindFile);
|
|
62
64
|
let caseplan;
|
package/dist/case/decompile.js
CHANGED
|
@@ -190,6 +190,8 @@ function resolvedSubscriptionSource(bag, owner, kind, refs) {
|
|
|
190
190
|
return opts([
|
|
191
191
|
['connector', tsLiteral(identity.key)],
|
|
192
192
|
['event', tsLiteral(identity.event)],
|
|
193
|
+
// A GENERIC event's object is the author's choice, so it comes back as `object`.
|
|
194
|
+
['object', identity.object !== undefined ? tsLiteral(identity.object) : undefined],
|
|
193
195
|
['where', where !== undefined ? tsLiteral(where) : undefined],
|
|
194
196
|
['filters', filters !== undefined ? tsLiteral(filters) : undefined],
|
|
195
197
|
['connection', connection !== undefined ? tsLiteral(connection) : undefined],
|
package/dist/case/serialize.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { IdGen } from './ids.js';
|
|
12
12
|
import { transportHttpMethod } from '../core/connector-inputs.js';
|
|
13
13
|
import { refuseLookupToken } from '../core/lookups.js';
|
|
14
|
+
import { resolveCaseSubscription } from './subscription.js';
|
|
14
15
|
import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
15
16
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
16
17
|
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
@@ -885,7 +886,7 @@ function resolvedSubscriptionBag(kind, spec, resolver, elementId) {
|
|
|
885
886
|
if (!resolver.library)
|
|
886
887
|
throw new Error(`${kind === 'trigger' ? 'event trigger' : 'wait-for-connector'} needs the connector library — `
|
|
887
888
|
+ `pass { library } to serialize or use uip maestro case compile --library.`);
|
|
888
|
-
const rc = resolver.library
|
|
889
|
+
const rc = resolveCaseSubscription(resolver.library, kind, spec);
|
|
889
890
|
const op = rc.entry.operation ?? {};
|
|
890
891
|
const context = [io('connectorKey', 'string', { value: rc.connectorKey })];
|
|
891
892
|
const connection = bindingRef(resolver, spec.connection, 'Connection', 'ConnectionId', `${rc.connectorKey} connection`);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* case/subscription — how Case resolves a connector event subscription against
|
|
3
|
+
* the library, shared by `serialize` (which throws) and `check` (which reports).
|
|
4
|
+
*
|
|
5
|
+
* One function, so the two cannot drift: the event trigger, the
|
|
6
|
+
* wait-for-connector task and the wait-for-connector rule all resolve here, with
|
|
7
|
+
* the author's `object` (#1033), and a GENERIC event that names no object is
|
|
8
|
+
* refused here with the text Flow's compile uses too
|
|
9
|
+
* (`genericEventObjectRefusal`).
|
|
10
|
+
*/
|
|
11
|
+
import type { EventSubscription } from '../core/actions.js';
|
|
12
|
+
import type { Library, ResolvedConnector } from '../core/library.js';
|
|
13
|
+
/** Check's code for {@link GenericEventNoObjectError}; Flow and BPMN `check` use the same one. */
|
|
14
|
+
export declare const EVENT_GENERIC_NO_OBJECT = "EVENT_GENERIC_NO_OBJECT";
|
|
15
|
+
/** A GENERIC event subscription that names no object. */
|
|
16
|
+
export declare class GenericEventNoObjectError extends Error {
|
|
17
|
+
readonly code = "EVENT_GENERIC_NO_OBJECT";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a Case event subscription: `library.resolveEvent` with the
|
|
21
|
+
* subscription's own `version` and `object`, then refuse a GENERIC event the
|
|
22
|
+
* author named no object for.
|
|
23
|
+
*
|
|
24
|
+
* @param library - The connector library.
|
|
25
|
+
* @param kind - `trigger` for an event trigger, `event` for a wait-for-connector task or rule.
|
|
26
|
+
* @param sub - The authored subscription.
|
|
27
|
+
* @returns The resolved event.
|
|
28
|
+
* @throws What `resolveEvent` throws, or {@link GenericEventNoObjectError}.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveCaseSubscription(library: Library, kind: 'trigger' | 'event', sub: EventSubscription): ResolvedConnector;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { genericEventObjectRefusal } from '../core/event-checks.js';
|
|
2
|
+
/** Check's code for {@link GenericEventNoObjectError}; Flow and BPMN `check` use the same one. */
|
|
3
|
+
export const EVENT_GENERIC_NO_OBJECT = 'EVENT_GENERIC_NO_OBJECT';
|
|
4
|
+
/** A GENERIC event subscription that names no object. */
|
|
5
|
+
export class GenericEventNoObjectError extends Error {
|
|
6
|
+
code = EVENT_GENERIC_NO_OBJECT;
|
|
7
|
+
}
|
|
8
|
+
/** How a Case subscription spells the `object` of a GENERIC event, for the refusal text. */
|
|
9
|
+
function caseObjectOption(object) {
|
|
10
|
+
return `{ connector, event, object: '${object}', … } in the subscription`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a Case event subscription: `library.resolveEvent` with the
|
|
14
|
+
* subscription's own `version` and `object`, then refuse a GENERIC event the
|
|
15
|
+
* author named no object for.
|
|
16
|
+
*
|
|
17
|
+
* @param library - The connector library.
|
|
18
|
+
* @param kind - `trigger` for an event trigger, `event` for a wait-for-connector task or rule.
|
|
19
|
+
* @param sub - The authored subscription.
|
|
20
|
+
* @returns The resolved event.
|
|
21
|
+
* @throws What `resolveEvent` throws, or {@link GenericEventNoObjectError}.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveCaseSubscription(library, kind, sub) {
|
|
24
|
+
const rc = library.resolveEvent(kind, sub.connector, sub.event, sub.version, sub.object);
|
|
25
|
+
const noObject = genericEventObjectRefusal(rc, sub, caseObjectOption);
|
|
26
|
+
if (noObject)
|
|
27
|
+
throw new GenericEventNoObjectError(noObject);
|
|
28
|
+
return rc;
|
|
29
|
+
}
|
|
@@ -20,6 +20,12 @@ export function registerCaseCommands(program) {
|
|
|
20
20
|
.description('Check authored TypeScript. Check a caseplan.json with `uip maestro case validate`.')
|
|
21
21
|
.argument('<input>', 'a .case.ts path or bare name')
|
|
22
22
|
.option('--source', 'check authored TypeScript')
|
|
23
|
+
// The library and its overlay, as `case compile` takes them: check resolves
|
|
24
|
+
// connector tasks and event subscriptions against the same library (#1014),
|
|
25
|
+
// and an option this parser does not declare is `unknown option` before
|
|
26
|
+
// check-cli sees argv.
|
|
27
|
+
.option('--library <dir>', 'connector library directory')
|
|
28
|
+
.option('--connectors-local <dir>', 'connection-resolved connector overlay')
|
|
23
29
|
.addOption(retiredCompiledOption())
|
|
24
30
|
.action(async (input, options) => {
|
|
25
31
|
let mode;
|
|
@@ -34,7 +40,10 @@ export function registerCaseCommands(program) {
|
|
|
34
40
|
refuse('flow-sdk case check --compiled: use `uip maestro case validate caseplan.json`');
|
|
35
41
|
return;
|
|
36
42
|
}
|
|
37
|
-
|
|
43
|
+
const argv = [input];
|
|
44
|
+
addValue(argv, '--library', options.library);
|
|
45
|
+
addValue(argv, '--connectors-local', options.connectorsLocal);
|
|
46
|
+
await invoke('case check', () => loadTool(import.meta.url, '../../case/check-cli.js'), argv);
|
|
38
47
|
});
|
|
39
48
|
family.command('decompile')
|
|
40
49
|
.description('Convert a caseplan.json to authored TypeScript.')
|
|
@@ -136,4 +136,35 @@ export declare function eventParamsFor(subscription: unknown, opts: EventCheckOp
|
|
|
136
136
|
* under the event-form node type — the form `prepare` stores.
|
|
137
137
|
*/
|
|
138
138
|
export declare function checkEventResolution(subscription: unknown, where: string, kind: 'trigger' | 'event', opts: EventCheckOpts, error: (code: string, message: string, suggestion?: string) => void, warn: (code: string, message: string, suggestion?: string) => void, eventParams?: EventParamFields): void;
|
|
139
|
+
/**
|
|
140
|
+
* The compile-time refusal of a GENERIC event subscription that names no object,
|
|
141
|
+
* or `undefined` when the resolved event is fine.
|
|
142
|
+
*
|
|
143
|
+
* A GENERIC event (`activityType: GenericTrigger` — Data Fabric, Salesforce,
|
|
144
|
+
* ServiceNow, Jira, … `record-created`/`record-updated`) fires for ONE object of
|
|
145
|
+
* the connection, and its library entry names none: the author's `object` is the
|
|
146
|
+
* only source. `Library.resolveEvent` stamps that object into the resolved
|
|
147
|
+
* operation's `objectName`; without it the operation's `objectName` stays `''`,
|
|
148
|
+
* and a node built from it validates and is refused by the platform's dispatcher
|
|
149
|
+
* ("missing objectName"), or watches nothing.
|
|
150
|
+
*
|
|
151
|
+
* Every family's serializer that emits a connector event calls this on the
|
|
152
|
+
* connector `resolveEvent` returned, so the refusal has one text. Case `check`
|
|
153
|
+
* calls it on the same resolution, so it reports exactly what Case `compile`
|
|
154
|
+
* throws.
|
|
155
|
+
*
|
|
156
|
+
* @param rc - What `library.resolveEvent(kind, connector, event, version, object)` returned.
|
|
157
|
+
* @param sub - The authored subscription (only `where` is read, for the hint).
|
|
158
|
+
* @param objectOption - How this family spells the `object` option, given the object.
|
|
159
|
+
* @returns The refusal message (no site prefix), or `undefined`.
|
|
160
|
+
*/
|
|
161
|
+
export declare function genericEventObjectRefusal(rc: {
|
|
162
|
+
nodeType: string;
|
|
163
|
+
connectorKey: string;
|
|
164
|
+
entry?: {
|
|
165
|
+
operation?: Record<string, unknown>;
|
|
166
|
+
};
|
|
167
|
+
}, sub: {
|
|
168
|
+
where?: unknown;
|
|
169
|
+
}, objectOption: (object: string) => string): string | undefined;
|
|
139
170
|
export declare function checkEventSubscription(subscription: unknown, where: string, at: (code: string, message: string, suggestion?: string) => void, warn?: (code: string, message: string, suggestion?: string) => void, eventParams?: EventParamFields): void;
|
|
@@ -204,6 +204,44 @@ export function checkEventResolution(subscription, where, kind, opts, error, war
|
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* The compile-time refusal of a GENERIC event subscription that names no object,
|
|
209
|
+
* or `undefined` when the resolved event is fine.
|
|
210
|
+
*
|
|
211
|
+
* A GENERIC event (`activityType: GenericTrigger` — Data Fabric, Salesforce,
|
|
212
|
+
* ServiceNow, Jira, … `record-created`/`record-updated`) fires for ONE object of
|
|
213
|
+
* the connection, and its library entry names none: the author's `object` is the
|
|
214
|
+
* only source. `Library.resolveEvent` stamps that object into the resolved
|
|
215
|
+
* operation's `objectName`; without it the operation's `objectName` stays `''`,
|
|
216
|
+
* and a node built from it validates and is refused by the platform's dispatcher
|
|
217
|
+
* ("missing objectName"), or watches nothing.
|
|
218
|
+
*
|
|
219
|
+
* Every family's serializer that emits a connector event calls this on the
|
|
220
|
+
* connector `resolveEvent` returned, so the refusal has one text. Case `check`
|
|
221
|
+
* calls it on the same resolution, so it reports exactly what Case `compile`
|
|
222
|
+
* throws.
|
|
223
|
+
*
|
|
224
|
+
* @param rc - What `library.resolveEvent(kind, connector, event, version, object)` returned.
|
|
225
|
+
* @param sub - The authored subscription (only `where` is read, for the hint).
|
|
226
|
+
* @param objectOption - How this family spells the `object` option, given the object.
|
|
227
|
+
* @returns The refusal message (no site prefix), or `undefined`.
|
|
228
|
+
*/
|
|
229
|
+
export function genericEventObjectRefusal(rc, sub, objectOption) {
|
|
230
|
+
const op = (rc.entry?.operation ?? {});
|
|
231
|
+
if (op.activityType !== 'GenericTrigger' || String(op.objectName ?? '') !== '')
|
|
232
|
+
return undefined;
|
|
233
|
+
const scopeObject = sub.where && typeof sub.where === 'object'
|
|
234
|
+
? Object.entries(sub.where)
|
|
235
|
+
.find(([k]) => /^(objectName|entityName|object)$/i.test(k))?.[1]
|
|
236
|
+
: undefined;
|
|
237
|
+
return `${rc.nodeType} is a GENERIC event — it watches ONE object of the connection `
|
|
238
|
+
+ `(an entity, a table, a custom object) and its library entry carries no default. Name it with the `
|
|
239
|
+
+ `\`object\` option: ${objectOption(scopeObject !== undefined ? String(scopeObject) : '<Object>')}. `
|
|
240
|
+
+ (scopeObject !== undefined
|
|
241
|
+
? `\`where: { objectName }\` is not it — \`where\` holds event PARAMETERS, and this operation has none. `
|
|
242
|
+
: '')
|
|
243
|
+
+ `\`uip is triggers objects ${rc.connectorKey} ${String(op.eventOperation ?? '<EVENT>')} --connection-id <id>\` lists the objects.`;
|
|
244
|
+
}
|
|
207
245
|
export function checkEventSubscription(subscription, where, at, warn, eventParams) {
|
|
208
246
|
const sub = subscription;
|
|
209
247
|
if (!sub || typeof sub !== 'object') {
|
package/dist/serialize.js
CHANGED
|
@@ -20,6 +20,7 @@ import { isAnswerField } from './core/hitl-answers.js';
|
|
|
20
20
|
import { connectionConnectors } from './bindings-v2.js';
|
|
21
21
|
import { BindingRefusal, GUID_RE, bindingMissingMessage, bindingSelfNameMessage, bindingUndeclaredMessage, missingBindingLabels, undeclaredBinding } from './core/binding-messages.js';
|
|
22
22
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
23
|
+
import { genericEventObjectRefusal } from './core/event-checks.js';
|
|
23
24
|
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
|
|
24
25
|
import { declaredExits, hasExits } from './core/step-ports.js';
|
|
25
26
|
import { stopsAtEnd } from './flow-step-tree.js';
|
|
@@ -4115,25 +4116,13 @@ function eventDetail(rc, sub, nodeId, opts, site) {
|
|
|
4115
4116
|
const folder = resolveBinding(opts, sub.folder, 'folder', `event node "${nodeId}"`, eventTarget(sub));
|
|
4116
4117
|
const op = (rc.entry?.operation ?? {});
|
|
4117
4118
|
const filters = sub.filters ?? [];
|
|
4118
|
-
// A GENERIC event
|
|
4119
|
-
//
|
|
4120
|
-
//
|
|
4121
|
-
// the only source. Without it the node would carry `objectName: ""` — it
|
|
4122
|
-
// validates, and the platform's dispatcher refuses it ("missing objectName") or
|
|
4123
|
-
// the designer shows a trigger bound to nothing. Refused here, at the layer
|
|
4124
|
-
// that would otherwise emit it.
|
|
4119
|
+
// A GENERIC event with no `object` would carry `objectName: ""`: it validates
|
|
4120
|
+
// and the platform's dispatcher refuses it. Refused here, at the layer that
|
|
4121
|
+
// would otherwise emit it, with the text every family's compile shares.
|
|
4125
4122
|
const objectName = String(op.objectName ?? '');
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
throw new Error(`event node "${nodeId}": ${rc.nodeType} is a GENERIC event — it watches ONE object of the connection `
|
|
4130
|
-
+ `(an entity, a table, a custom object) and its library entry carries no default. Name it with the `
|
|
4131
|
-
+ `\`object\` option: onEvent(…, { object: '${scopeObject ?? '<Object>'}' }). `
|
|
4132
|
-
+ (scopeObject !== undefined
|
|
4133
|
-
? `\`where: { objectName }\` is not it — \`where\` holds event PARAMETERS, and this operation has none. `
|
|
4134
|
-
: '')
|
|
4135
|
-
+ `\`uip is triggers objects ${rc.connectorKey} ${String(op.eventOperation ?? '<EVENT>')} --connection-id <id>\` lists the objects.`);
|
|
4136
|
-
}
|
|
4123
|
+
const noObject = genericEventObjectRefusal(rc, sub, (o) => `onEvent(…, { object: '${o}' })`);
|
|
4124
|
+
if (noObject)
|
|
4125
|
+
throw new Error(`event node "${nodeId}": ${noObject}`);
|
|
4137
4126
|
// An unresolved `where` lookup is swapped for its recorded id — the id
|
|
4138
4127
|
// `prepare --resolve` stored under the EVENT-form node type — or refused.
|
|
4139
4128
|
// Same rule as connector inputs: emitting a placeholder for a value nobody
|
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.2",
|
|
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": "a1a9df938c60a4e31cc9025ec9664d34f41aa799"
|
|
96
96
|
}
|