@uipath/maestro-builder-sdk 6.11.5 → 6.11.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/check-cli.js +2 -1
- package/dist/check.d.ts +13 -0
- package/dist/check.js +11 -0
- package/dist/cli-library.d.ts +7 -0
- package/dist/cli-library.js +19 -0
- package/dist/compile-cli.js +8 -5
- package/dist/core/byoa.d.ts +69 -0
- package/dist/core/byoa.js +98 -0
- package/dist/core/library.d.ts +23 -0
- package/dist/core/library.js +47 -1
- package/dist/core/lookup-store.d.ts +12 -0
- package/dist/core/lookup-store.js +25 -0
- package/dist/registry/generators/descriptors.d.ts +1 -1
- package/dist/registry/generators/descriptors.js +20 -2
- package/dist/registry/generators/markdown/page.js +3 -1
- package/dist/registry/generators/markdown/sections/event-facts.d.ts +2 -0
- package/dist/registry/generators/markdown/sections/event-facts.js +45 -0
- package/dist/registry/library-build/events.d.ts +32 -3
- package/dist/registry/library-build/events.js +48 -19
- package/dist/registry/prepare/byoa-ledger.d.ts +12 -0
- package/dist/registry/prepare/byoa-ledger.js +26 -0
- package/dist/registry/prepare/event.d.ts +5 -1
- package/dist/registry/prepare/event.js +22 -8
- package/dist/registry/prepare/messages.d.ts +2 -0
- package/dist/registry/prepare/messages.js +4 -0
- package/dist/serialize.js +24 -1
- package/package.json +2 -2
package/dist/check-cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import { reportDiagnostics } from './cli-result.js';
|
|
|
9
9
|
import { existsSync } from 'node:fs';
|
|
10
10
|
import { resolveFlowFile, loadBuiltFlow } from './load.js';
|
|
11
11
|
import { check } from './check.js';
|
|
12
|
-
import { eventResolveErrorFor, openCliLibrary } from './cli-library.js';
|
|
12
|
+
import { byoaCheckOpts, eventResolveErrorFor, openCliLibrary } from './cli-library.js';
|
|
13
13
|
import { Bindings } from './bindings.js';
|
|
14
14
|
import { connectorInputErrors } from './serialize.js';
|
|
15
15
|
import { runWhenInvokedDirectly } from './cli-run.js';
|
|
@@ -41,6 +41,7 @@ function checkOpts(argv) {
|
|
|
41
41
|
return bindings ? { bindings } : {};
|
|
42
42
|
return {
|
|
43
43
|
eventResolveError: eventResolveErrorFor(library),
|
|
44
|
+
...byoaCheckOpts(library),
|
|
44
45
|
eventParams: (connector, event, object) => {
|
|
45
46
|
try {
|
|
46
47
|
return library.eventParameterFields(connector, event, object);
|
package/dist/check.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type LookupResolutions, type LookupSpec } from './core/lookups.js';
|
|
|
2
2
|
import type { SchemaReadiness } from './core/library.js';
|
|
3
3
|
import type { BuiltFlow } from './flow-sdk.js';
|
|
4
4
|
import { type BindingsView } from './core/binding-messages.js';
|
|
5
|
+
import { type ByoaEventFacts, type ByoaLedger } from './core/byoa.js';
|
|
5
6
|
export interface Diagnostic {
|
|
6
7
|
level: 'error' | 'warning';
|
|
7
8
|
code: string;
|
|
@@ -116,6 +117,18 @@ export interface CheckOpts {
|
|
|
116
117
|
lookups?: (connector: string, action: string, version?: string, object?: string) => Readonly<Record<string, LookupSpec>> | undefined;
|
|
117
118
|
/** Everything `registry prepare --resolve` has recorded in the local overlay. */
|
|
118
119
|
resolutions?: LookupResolutions;
|
|
120
|
+
/**
|
|
121
|
+
* A connector event's BYOA and webhook-URL facts, or `undefined` when unknown.
|
|
122
|
+
* Supplied by the CLIs from `library.eventFacts` — the call `serialize` makes
|
|
123
|
+
* for the same refusal — so check and compile cannot disagree; omitted (no
|
|
124
|
+
* library) → EVENT_BYOA_UNVERIFIED is not checked.
|
|
125
|
+
*/
|
|
126
|
+
eventFacts?: (connector: string, event: string, object?: string) => ByoaEventFacts | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* The BYOA checks `registry prepare` recorded — the `byoa` section of the
|
|
129
|
+
* overlay's `resolutions.json`, as `library.byoaVerifications` loads it.
|
|
130
|
+
*/
|
|
131
|
+
byoa?: ByoaLedger;
|
|
119
132
|
/**
|
|
120
133
|
* Whether a connector step's schema is materialized locally — the fact behind
|
|
121
134
|
* the OBJECT_UNPREPARED and CUSTOM_FIELDS_UNPREPARED warnings. Supplied by the
|
package/dist/check.js
CHANGED
|
@@ -18,6 +18,7 @@ import { childStepLists, declaredExits, hasExits, stopsAtEnd } from './core/step
|
|
|
18
18
|
import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
|
|
19
19
|
import { compareSchemaVersions, schemaVersionRefusal } from './schema-version.js';
|
|
20
20
|
import { prepareCommand, resolveFlagArg } from './core/cli-spelling.js';
|
|
21
|
+
import { EVENT_BYOA_UNVERIFIED, byoaUnverified } from './core/byoa.js';
|
|
21
22
|
export function check(built, opts = {}) {
|
|
22
23
|
return checkFlow(built, [], opts);
|
|
23
24
|
}
|
|
@@ -1953,6 +1954,13 @@ function eventParamsFor(subscription, opts) {
|
|
|
1953
1954
|
* the fallback case for a connector the shipped library was not generated
|
|
1954
1955
|
* against. A warning, because compile still succeeds. Prints the one
|
|
1955
1956
|
* command that makes the event checkable.
|
|
1957
|
+
* - `EVENT_BYOA_UNVERIFIED` — an ERROR: the event only fires on a BYOA
|
|
1958
|
+
* (bring-your-own-app) connection, and the bound connection id has no record
|
|
1959
|
+
* of `prepare` having checked it (`core/byoa.ts` has the rule and when it
|
|
1960
|
+
* stays silent). A standard connection deploys and the trigger never fires;
|
|
1961
|
+
* the usual way in is binding the connection by preparing one of the
|
|
1962
|
+
* connector's ACTIONS, which checks nothing about BYOA. `compile` throws the
|
|
1963
|
+
* same text.
|
|
1956
1964
|
* - `EVENT_FILTER_UNKNOWN_FIELD` — a filter leaf naming a field outside the
|
|
1957
1965
|
* prepared vocabulary is an ERROR, not a warning, because the platform's own
|
|
1958
1966
|
* configure DROPS an unmatched leaf and reports Success: the deployed
|
|
@@ -1988,6 +1996,9 @@ function checkEventResolution(subscription, where, kind, opts, error, warn, even
|
|
|
1988
1996
|
return;
|
|
1989
1997
|
}
|
|
1990
1998
|
const object = typeof sub.object === 'string' && sub.object !== '' ? sub.object : undefined;
|
|
1999
|
+
const byoa = opts.eventFacts && byoaUnverified(where, { connector: connectorKey, event: eventName, ...(object ? { object } : {}), connection: sub.connection }, opts.eventFacts(connectorKey, eventName, object), opts.byoa, opts.bindings);
|
|
2000
|
+
if (byoa)
|
|
2001
|
+
error(EVENT_BYOA_UNVERIFIED, byoa);
|
|
1991
2002
|
if (eventParams?.objectUnprepared && object) {
|
|
1992
2003
|
// The generic template answers for every object, so resolution SUCCEEDS
|
|
1993
2004
|
// and nothing downstream notices that the object named here has no
|
package/dist/cli-library.d.ts
CHANGED
|
@@ -19,3 +19,10 @@ export declare function openCliLibrary(argv: readonly string[]): Library | undef
|
|
|
19
19
|
* exactly when compile would throw, with the same text.
|
|
20
20
|
*/
|
|
21
21
|
export declare function eventResolveErrorFor(library: Library): NonNullable<CheckOpts['eventResolveError']>;
|
|
22
|
+
/**
|
|
23
|
+
* `check`'s EVENT_BYOA_UNVERIFIED inputs: the event facts and the recorded BYOA
|
|
24
|
+
* checks, from the same `library.eventFacts` / `library.byoaVerifications` that
|
|
25
|
+
* `serialize` reads for the same refusal. Both CLIs spread this into their
|
|
26
|
+
* check options, so the inner loop and the emit rung refuse the same flows.
|
|
27
|
+
*/
|
|
28
|
+
export declare function byoaCheckOpts(library: Library): Pick<CheckOpts, 'eventFacts' | 'byoa'>;
|
package/dist/cli-library.js
CHANGED
|
@@ -54,3 +54,22 @@ export function eventResolveErrorFor(library) {
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* `check`'s EVENT_BYOA_UNVERIFIED inputs: the event facts and the recorded BYOA
|
|
59
|
+
* checks, from the same `library.eventFacts` / `library.byoaVerifications` that
|
|
60
|
+
* `serialize` reads for the same refusal. Both CLIs spread this into their
|
|
61
|
+
* check options, so the inner loop and the emit rung refuse the same flows.
|
|
62
|
+
*/
|
|
63
|
+
export function byoaCheckOpts(library) {
|
|
64
|
+
return {
|
|
65
|
+
eventFacts: (connector, event, object) => {
|
|
66
|
+
try {
|
|
67
|
+
return library.eventFacts(connector, event, object);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined; // unknown fails open, same as every library callback
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
byoa: library.byoaVerifications,
|
|
74
|
+
};
|
|
75
|
+
}
|
package/dist/compile-cli.js
CHANGED
|
@@ -23,12 +23,13 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
23
23
|
import { resolveFlowFile, loadBuiltFlow } from './load.js';
|
|
24
24
|
import { serializeWithSidecars, connectorInputErrors } from './serialize.js';
|
|
25
25
|
import { check } from './check.js';
|
|
26
|
-
import { eventResolveErrorFor, openCliLibrary } from './cli-library.js';
|
|
26
|
+
import { byoaCheckOpts, eventResolveErrorFor, openCliLibrary } from './cli-library.js';
|
|
27
27
|
import { Bindings } from './bindings.js';
|
|
28
28
|
import { runWhenInvokedDirectly } from './cli-run.js';
|
|
29
29
|
import { connectionResources, mergeBindingsV2, readBindingsV2 } from './bindings-v2.js';
|
|
30
30
|
import { ensureTypeScriptRuntime } from './node-runtime.js';
|
|
31
31
|
import { BindingRefusal } from './core/binding-messages.js';
|
|
32
|
+
import { ByoaRefusal } from './core/byoa.js';
|
|
32
33
|
function opt(argv, name) {
|
|
33
34
|
const i = argv.indexOf(name);
|
|
34
35
|
return i >= 0 ? argv[i + 1] : undefined;
|
|
@@ -96,6 +97,7 @@ export async function run(argv) {
|
|
|
96
97
|
// printed as `✗ [EVENT_UNKNOWN]` before stopping instead of hiding
|
|
97
98
|
// behind "1 error(s); not emitting".
|
|
98
99
|
eventResolveError: eventResolveErrorFor(library),
|
|
100
|
+
...byoaCheckOpts(library),
|
|
99
101
|
eventParams: (connector, event) => {
|
|
100
102
|
try {
|
|
101
103
|
return library.eventParameterFields(connector, event);
|
|
@@ -134,16 +136,17 @@ export async function run(argv) {
|
|
|
134
136
|
// check()'s. Warnings are never fatal: the .flow is still written, exit stays 0.
|
|
135
137
|
// A binding LABEL the serializer refuses (its own name as the resourceKey, or a
|
|
136
138
|
// label a populated bindings.json does not declare) is an error, not a
|
|
137
|
-
// warning
|
|
138
|
-
//
|
|
139
|
-
//
|
|
139
|
+
// warning, and so is a BYOA-only event on a connection `prepare` never checked
|
|
140
|
+
// (EVENT_BYOA_UNVERIFIED): the check pass above reports each first, and this is
|
|
141
|
+
// the same refusal in the same `✗ [CODE]` shape when that pass was skipped
|
|
142
|
+
// (`--no-check`, or an emit-only project). Nothing is written.
|
|
140
143
|
const warnings = [];
|
|
141
144
|
let emitted;
|
|
142
145
|
try {
|
|
143
146
|
emitted = serializeWithSidecars(built, { library, bindings, warn: (w) => warnings.push(w) });
|
|
144
147
|
}
|
|
145
148
|
catch (error) {
|
|
146
|
-
if (!(error instanceof BindingRefusal))
|
|
149
|
+
if (!(error instanceof BindingRefusal || error instanceof ByoaRefusal))
|
|
147
150
|
throw error;
|
|
148
151
|
for (const w of warnings)
|
|
149
152
|
console.error(` ⚠ [${w.code}] ${w.message}`);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** The diagnostic code, in `check` and on the error `serialize` throws. */
|
|
2
|
+
export declare const EVENT_BYOA_UNVERIFIED = "EVENT_BYOA_UNVERIFIED";
|
|
3
|
+
/** One verification `prepare` recorded. Only a PASSING check is ever written. */
|
|
4
|
+
export interface ByoaRecord {
|
|
5
|
+
byoa: true;
|
|
6
|
+
/** The connection's `Name`, so a person reading the file can tell which one it is. */
|
|
7
|
+
connectionName?: string;
|
|
8
|
+
/** `YYYY-MM-DD`: a resolved answer is a snapshot, like every other ledger row. */
|
|
9
|
+
verifiedAt?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The ledger's `byoa` section: `byoa[<event node type>][<connection id>]`.
|
|
13
|
+
*
|
|
14
|
+
* Keyed per EVENT, not per connector — Slack `send-reply` needs no BYOA, the
|
|
15
|
+
* message trigger does — and per CONNECTION, so swapping the connection in
|
|
16
|
+
* bindings.json un-verifies the event until it is prepared again.
|
|
17
|
+
*/
|
|
18
|
+
export type ByoaLedger = Record<string, Record<string, ByoaRecord>>;
|
|
19
|
+
/** The event facts the rule reads, as `Library.eventFacts` answers them. */
|
|
20
|
+
export interface ByoaEventFacts {
|
|
21
|
+
byoaConnection: boolean;
|
|
22
|
+
isWebhookUrlVisible: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The key an event's record is stored under: the WAIT form of the node type,
|
|
26
|
+
* the form `prepare` stores an event's overlay and lookup rows under, whichever
|
|
27
|
+
* role (`onEvent` or `waitForEvent`) the flow uses it in.
|
|
28
|
+
*/
|
|
29
|
+
export declare function byoaLedgerKey(connectorKey: string, event: string): string;
|
|
30
|
+
/** The record for `connectionId` under `nodeType`, matching the id case-insensitively. */
|
|
31
|
+
export declare function byoaRecordFor(ledger: ByoaLedger | undefined, nodeType: string, connectionId: string): ByoaRecord | undefined;
|
|
32
|
+
/** What `compile` throws for the refusal; `code` lets the CLI print it as `✗ [CODE]`. */
|
|
33
|
+
export declare class ByoaRefusal extends Error {
|
|
34
|
+
readonly code = "EVENT_BYOA_UNVERIFIED";
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
/** One subscription, as the rule needs it. */
|
|
38
|
+
export interface ByoaSubscription {
|
|
39
|
+
connector: string;
|
|
40
|
+
event: string;
|
|
41
|
+
object?: string;
|
|
42
|
+
/** The `connection:` label as authored — a bindings.json name, or a connection id. */
|
|
43
|
+
connection?: unknown;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Why a BYOA-only event cannot be trusted to fire on its bound connection, or
|
|
47
|
+
* `undefined` when there is nothing to refuse. The ONE condition behind
|
|
48
|
+
* `check`'s EVENT_BYOA_UNVERIFIED error and `compile`'s refusal, so the two
|
|
49
|
+
* cannot disagree.
|
|
50
|
+
*
|
|
51
|
+
* Refuses when the event's facts say BYOA and the connection resolves to a real
|
|
52
|
+
* connection id with no `byoa` record for this event. Silent when:
|
|
53
|
+
*
|
|
54
|
+
* - the facts are unknown or say no BYOA;
|
|
55
|
+
* - the connection does not resolve to a real id — no bindings.json, a label it
|
|
56
|
+
* does not declare, or a placeholder (`0000…`, `<…>`, the label itself). There
|
|
57
|
+
* is no id to look a record up by, and nothing is lost: such a flow cannot
|
|
58
|
+
* run its trigger on any connection, and BINDING_SELF_NAME /
|
|
59
|
+
* BINDING_UNDECLARED / CONNECTION_STUB already say so.
|
|
60
|
+
*
|
|
61
|
+
* @param where - The call site, as the other event diagnostics name it (`trigger`, `waitForEvent "x"`).
|
|
62
|
+
* @param sub - The subscription.
|
|
63
|
+
* @param facts - The event's facts from the library, or `undefined` when unknown.
|
|
64
|
+
* @param ledger - The overlay ledger's `byoa` section.
|
|
65
|
+
* @param bindings - Resolves the `connection:` label to an id.
|
|
66
|
+
*/
|
|
67
|
+
export declare function byoaUnverified(where: string, sub: ByoaSubscription, facts: ByoaEventFacts | undefined, ledger: ByoaLedger | undefined, bindings: {
|
|
68
|
+
resolve(name?: string): string | undefined;
|
|
69
|
+
} | undefined): string | undefined;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/byoa — connector events that only fire on a BYOA connection (#848).
|
|
3
|
+
*
|
|
4
|
+
* BYOA is "bring your own app": an Integration Service connection created with
|
|
5
|
+
* the customer's own OAuth app. Some event objects need one — Slack
|
|
6
|
+
* `message-received-in-slack` is a webhook the customer's Slack app delivers,
|
|
7
|
+
* so on a standard connection the trigger deploys, validates, and never fires.
|
|
8
|
+
*
|
|
9
|
+
* Only a live call can tell a BYOA connection from a standard one, and `registry
|
|
10
|
+
* prepare` makes it: on an event whose facts say BYOA it lists the tenant's BYOA
|
|
11
|
+
* connections, refuses a connection that is not among them, and records one
|
|
12
|
+
* that is under `byoa[<event node type>][<connection id>]` in
|
|
13
|
+
* `connectors-local/resolutions.json`. This module is the offline half: the
|
|
14
|
+
* record's shape, and the one condition `check` reports and `compile` throws
|
|
15
|
+
* when a BYOA event's bound connection carries no record — typically because
|
|
16
|
+
* the connection was bound by preparing an ACTION of the same connector, which
|
|
17
|
+
* checks nothing about BYOA. `check` stays offline: it checks that the live
|
|
18
|
+
* check happened, never the tenant.
|
|
19
|
+
*
|
|
20
|
+
* No `node:fs` here — `check` and `serialize` import this module, and the file
|
|
21
|
+
* read lives in `lookup-store.ts` beside the ledger's other reader.
|
|
22
|
+
*/
|
|
23
|
+
import { GUID_RE } from './binding-messages.js';
|
|
24
|
+
import { prepareCommand } from './cli-spelling.js';
|
|
25
|
+
/** The diagnostic code, in `check` and on the error `serialize` throws. */
|
|
26
|
+
export const EVENT_BYOA_UNVERIFIED = 'EVENT_BYOA_UNVERIFIED';
|
|
27
|
+
/**
|
|
28
|
+
* The key an event's record is stored under: the WAIT form of the node type,
|
|
29
|
+
* the form `prepare` stores an event's overlay and lookup rows under, whichever
|
|
30
|
+
* role (`onEvent` or `waitForEvent`) the flow uses it in.
|
|
31
|
+
*/
|
|
32
|
+
export function byoaLedgerKey(connectorKey, event) {
|
|
33
|
+
return `uipath.connector.event.${connectorKey}.${event}`;
|
|
34
|
+
}
|
|
35
|
+
/** The record for `connectionId` under `nodeType`, matching the id case-insensitively. */
|
|
36
|
+
export function byoaRecordFor(ledger, nodeType, connectionId) {
|
|
37
|
+
const perEvent = ledger?.[nodeType];
|
|
38
|
+
if (!perEvent || typeof perEvent !== 'object')
|
|
39
|
+
return undefined;
|
|
40
|
+
const wanted = connectionId.toLowerCase();
|
|
41
|
+
for (const [id, record] of Object.entries(perEvent)) {
|
|
42
|
+
if (id.toLowerCase() === wanted && record && typeof record === 'object' && record.byoa === true)
|
|
43
|
+
return record;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/** What `compile` throws for the refusal; `code` lets the CLI print it as `✗ [CODE]`. */
|
|
48
|
+
export class ByoaRefusal extends Error {
|
|
49
|
+
code = EVENT_BYOA_UNVERIFIED;
|
|
50
|
+
constructor(message) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'ByoaRefusal';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** An all-zero GUID: a placeholder no tenant issues (compile's CONNECTION_STUB). */
|
|
56
|
+
const STUB_GUID_RE = /^0{8}-0{4}-0{4}-0{4}-/;
|
|
57
|
+
/**
|
|
58
|
+
* Why a BYOA-only event cannot be trusted to fire on its bound connection, or
|
|
59
|
+
* `undefined` when there is nothing to refuse. The ONE condition behind
|
|
60
|
+
* `check`'s EVENT_BYOA_UNVERIFIED error and `compile`'s refusal, so the two
|
|
61
|
+
* cannot disagree.
|
|
62
|
+
*
|
|
63
|
+
* Refuses when the event's facts say BYOA and the connection resolves to a real
|
|
64
|
+
* connection id with no `byoa` record for this event. Silent when:
|
|
65
|
+
*
|
|
66
|
+
* - the facts are unknown or say no BYOA;
|
|
67
|
+
* - the connection does not resolve to a real id — no bindings.json, a label it
|
|
68
|
+
* does not declare, or a placeholder (`0000…`, `<…>`, the label itself). There
|
|
69
|
+
* is no id to look a record up by, and nothing is lost: such a flow cannot
|
|
70
|
+
* run its trigger on any connection, and BINDING_SELF_NAME /
|
|
71
|
+
* BINDING_UNDECLARED / CONNECTION_STUB already say so.
|
|
72
|
+
*
|
|
73
|
+
* @param where - The call site, as the other event diagnostics name it (`trigger`, `waitForEvent "x"`).
|
|
74
|
+
* @param sub - The subscription.
|
|
75
|
+
* @param facts - The event's facts from the library, or `undefined` when unknown.
|
|
76
|
+
* @param ledger - The overlay ledger's `byoa` section.
|
|
77
|
+
* @param bindings - Resolves the `connection:` label to an id.
|
|
78
|
+
*/
|
|
79
|
+
export function byoaUnverified(where, sub, facts, ledger, bindings) {
|
|
80
|
+
if (!facts?.byoaConnection)
|
|
81
|
+
return undefined;
|
|
82
|
+
if (typeof sub.connection !== 'string' || sub.connection === '')
|
|
83
|
+
return undefined;
|
|
84
|
+
const label = sub.connection;
|
|
85
|
+
const id = bindings?.resolve(label) ?? label;
|
|
86
|
+
if (!GUID_RE.test(id) || STUB_GUID_RE.test(id))
|
|
87
|
+
return undefined;
|
|
88
|
+
if (byoaRecordFor(ledger, byoaLedgerKey(sub.connector, sub.event), id))
|
|
89
|
+
return undefined;
|
|
90
|
+
const named = label === id ? `connection ${id}` : `connection \`${label}\` (${id})`;
|
|
91
|
+
const object = sub.object ? ` --object ${sub.object}` : '';
|
|
92
|
+
return `${where}: \`${sub.connector}\` \`${sub.event}\` requires a BYOA (bring-your-own-app) connection — `
|
|
93
|
+
+ `one created with your own OAuth app — and ${named} was never checked against that requirement. `
|
|
94
|
+
+ `A standard connection deploys and the trigger never fires. Prepare the event on this connection, `
|
|
95
|
+
+ `which refuses a standard connection and records a BYOA one:\n`
|
|
96
|
+
+ ` ${prepareCommand(sub.connector, sub.event)}${object} --connection-id ${id}\n`
|
|
97
|
+
+ `BYOA connections (rows for \`${sub.connector}\`): uip is connections list --byoa --all-folders`;
|
|
98
|
+
}
|
package/dist/core/library.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type LookupResolutions, type LookupSpec } from './lookups.js';
|
|
2
|
+
import type { ByoaEventFacts, ByoaLedger } from './byoa.js';
|
|
2
3
|
export interface ResolvedConnector {
|
|
3
4
|
nodeType: string;
|
|
4
5
|
version: string;
|
|
@@ -229,6 +230,12 @@ export declare class Library {
|
|
|
229
230
|
* id from someone else's connection.
|
|
230
231
|
*/
|
|
231
232
|
readonly lookupResolutions: LookupResolutions;
|
|
233
|
+
/**
|
|
234
|
+
* The BYOA checks `prepare` recorded (`resolutions.json` → `byoa`), from the
|
|
235
|
+
* overlay only, for the same reason as {@link lookupResolutions}: whether a
|
|
236
|
+
* connection is BYOA is a fact about one tenant.
|
|
237
|
+
*/
|
|
238
|
+
readonly byoaVerifications: ByoaLedger;
|
|
232
239
|
/** Collections the ledger declares connector-invariant; overlay unions over baked. */
|
|
233
240
|
private readonly invariantCollections;
|
|
234
241
|
constructor(dir: string, opts?: LibraryOpts);
|
|
@@ -348,6 +355,22 @@ export declare class Library {
|
|
|
348
355
|
* raw library snapshot carries ZERO trigger/event entries).
|
|
349
356
|
*/
|
|
350
357
|
eventParameterFields(key: string, event: string, objectName?: string): EventParameterFields | undefined;
|
|
358
|
+
/**
|
|
359
|
+
* Whether a connector event needs a BYOA (bring-your-own-app) connection, and
|
|
360
|
+
* whether its webhook URL must be registered by hand — or `undefined` when no
|
|
361
|
+
* layer carries the event in either form.
|
|
362
|
+
*
|
|
363
|
+
* Read from the `.v1def.json` sidecar, where the library build stamps the
|
|
364
|
+
* facts from the event's `triggers objects` row and `prepare` stores them on
|
|
365
|
+
* the overlay. A fact is TRUE when ANY layer, in either form (`.event.` or
|
|
366
|
+
* `.trigger.`), says so: the requirement belongs to the event object, not to
|
|
367
|
+
* a tenant, and an overlay written by an older `prepare` — which stored the
|
|
368
|
+
* `describe` answer, `false` for Slack `message-received-in-slack` — must not
|
|
369
|
+
* hide the true fact a newer baked library carries.
|
|
370
|
+
*
|
|
371
|
+
* `check` and `compile` read this through the one rule in `core/byoa.ts`.
|
|
372
|
+
*/
|
|
373
|
+
eventFacts(key: string, event: string, objectName?: string): ByoaEventFacts | undefined;
|
|
351
374
|
/**
|
|
352
375
|
* The filterable-field names a connector event declares — the vocabulary a
|
|
353
376
|
* `filters` leaf may name.
|
package/dist/core/library.js
CHANGED
|
@@ -11,7 +11,7 @@ import { join } from 'node:path';
|
|
|
11
11
|
import { prepareCommand } from './cli-spelling.js';
|
|
12
12
|
import { loadListEnvelopes, lookupListEnvelope } from './list-envelope.js';
|
|
13
13
|
import { lookupSpecOf } from './lookups.js';
|
|
14
|
-
import { loadInvariantCollections, loadLookupResolutions } from './lookup-store.js';
|
|
14
|
+
import { loadByoaLedger, loadInvariantCollections, loadLookupResolutions } from './lookup-store.js';
|
|
15
15
|
export class Library {
|
|
16
16
|
layers = [];
|
|
17
17
|
/** The LIST-ENVELOPE LEDGER, overlay first so a prepared entry can add a row. */
|
|
@@ -24,10 +24,17 @@ export class Library {
|
|
|
24
24
|
* id from someone else's connection.
|
|
25
25
|
*/
|
|
26
26
|
lookupResolutions;
|
|
27
|
+
/**
|
|
28
|
+
* The BYOA checks `prepare` recorded (`resolutions.json` → `byoa`), from the
|
|
29
|
+
* overlay only, for the same reason as {@link lookupResolutions}: whether a
|
|
30
|
+
* connection is BYOA is a fact about one tenant.
|
|
31
|
+
*/
|
|
32
|
+
byoaVerifications;
|
|
27
33
|
/** Collections the ledger declares connector-invariant; overlay unions over baked. */
|
|
28
34
|
invariantCollections;
|
|
29
35
|
constructor(dir, opts = {}) {
|
|
30
36
|
this.lookupResolutions = loadLookupResolutions(opts.overlayDir);
|
|
37
|
+
this.byoaVerifications = loadByoaLedger(opts.overlayDir);
|
|
31
38
|
this.invariantCollections = new Set([
|
|
32
39
|
...loadInvariantCollections(dir),
|
|
33
40
|
...loadInvariantCollections(opts.overlayDir),
|
|
@@ -434,6 +441,45 @@ export class Library {
|
|
|
434
441
|
.some(([name, value]) => name !== 'type' && Boolean(value)),
|
|
435
442
|
};
|
|
436
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Whether a connector event needs a BYOA (bring-your-own-app) connection, and
|
|
446
|
+
* whether its webhook URL must be registered by hand — or `undefined` when no
|
|
447
|
+
* layer carries the event in either form.
|
|
448
|
+
*
|
|
449
|
+
* Read from the `.v1def.json` sidecar, where the library build stamps the
|
|
450
|
+
* facts from the event's `triggers objects` row and `prepare` stores them on
|
|
451
|
+
* the overlay. A fact is TRUE when ANY layer, in either form (`.event.` or
|
|
452
|
+
* `.trigger.`), says so: the requirement belongs to the event object, not to
|
|
453
|
+
* a tenant, and an overlay written by an older `prepare` — which stored the
|
|
454
|
+
* `describe` answer, `false` for Slack `message-received-in-slack` — must not
|
|
455
|
+
* hide the true fact a newer baked library carries.
|
|
456
|
+
*
|
|
457
|
+
* `check` and `compile` read this through the one rule in `core/byoa.ts`.
|
|
458
|
+
*/
|
|
459
|
+
eventFacts(key, event, objectName) {
|
|
460
|
+
let found = false;
|
|
461
|
+
const facts = { byoaConnection: false, isWebhookUrlVisible: false };
|
|
462
|
+
for (const layer of this.layers) {
|
|
463
|
+
for (const kind of ['event', 'trigger']) {
|
|
464
|
+
let rc;
|
|
465
|
+
try {
|
|
466
|
+
rc = this.resolveInLayer(layer, `uipath.connector.${kind}.${key}.${event}`, undefined, objectName);
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
continue; // an ambiguous object is resolveEvent's refusal to report
|
|
470
|
+
}
|
|
471
|
+
if (!rc)
|
|
472
|
+
continue;
|
|
473
|
+
found = true;
|
|
474
|
+
const v1def = (rc.v1def ?? {});
|
|
475
|
+
if (v1def.byoaConnection === true)
|
|
476
|
+
facts.byoaConnection = true;
|
|
477
|
+
if (v1def.isWebhookUrlVisible === true)
|
|
478
|
+
facts.isWebhookUrlVisible = true;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return found ? facts : undefined;
|
|
482
|
+
}
|
|
437
483
|
/**
|
|
438
484
|
* The filterable-field names a connector event declares — the vocabulary a
|
|
439
485
|
* `filters` leaf may name.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ByoaLedger } from './byoa.js';
|
|
1
2
|
import type { LookupResolutions } from './lookups.js';
|
|
2
3
|
/**
|
|
3
4
|
* Load `<overlayDir>/resolutions.json`, or an empty map.
|
|
@@ -8,6 +9,17 @@ import type { LookupResolutions } from './lookups.js';
|
|
|
8
9
|
* behaviour an author wants from a missing resolution anyway.
|
|
9
10
|
*/
|
|
10
11
|
export declare function loadLookupResolutions(overlayDir: string | undefined): LookupResolutions;
|
|
12
|
+
/**
|
|
13
|
+
* Load the `byoa` section of `<overlayDir>/resolutions.json` — the BYOA checks
|
|
14
|
+
* `registry prepare` recorded (see `core/byoa.ts`) — or an empty map.
|
|
15
|
+
*
|
|
16
|
+
* Lenient like {@link loadLookupResolutions}: an absent or malformed file reads
|
|
17
|
+
* as EMPTY, and the consequence of empty is the EVENT_BYOA_UNVERIFIED error
|
|
18
|
+
* naming the `prepare` command that records the check. Read fresh on every
|
|
19
|
+
* call rather than cached: `prepare` rewrites this file, and a stale "never
|
|
20
|
+
* checked" answer would refuse a flow that was just verified.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadByoaLedger(overlayDir: string | undefined): ByoaLedger;
|
|
11
23
|
/**
|
|
12
24
|
* The invariant-collection ledger's `objectName` set, from a library dir.
|
|
13
25
|
*
|
|
@@ -45,6 +45,31 @@ export function loadLookupResolutions(overlayDir) {
|
|
|
45
45
|
RESOLUTION_CACHE.set(overlayDir, rows);
|
|
46
46
|
return rows;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Load the `byoa` section of `<overlayDir>/resolutions.json` — the BYOA checks
|
|
50
|
+
* `registry prepare` recorded (see `core/byoa.ts`) — or an empty map.
|
|
51
|
+
*
|
|
52
|
+
* Lenient like {@link loadLookupResolutions}: an absent or malformed file reads
|
|
53
|
+
* as EMPTY, and the consequence of empty is the EVENT_BYOA_UNVERIFIED error
|
|
54
|
+
* naming the `prepare` command that records the check. Read fresh on every
|
|
55
|
+
* call rather than cached: `prepare` rewrites this file, and a stale "never
|
|
56
|
+
* checked" answer would refuse a flow that was just verified.
|
|
57
|
+
*/
|
|
58
|
+
export function loadByoaLedger(overlayDir) {
|
|
59
|
+
if (!overlayDir)
|
|
60
|
+
return {};
|
|
61
|
+
const file = join(overlayDir, 'resolutions.json');
|
|
62
|
+
if (!existsSync(file))
|
|
63
|
+
return {};
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
66
|
+
const byoa = parsed?.byoa;
|
|
67
|
+
return byoa && typeof byoa === 'object' && !Array.isArray(byoa) ? byoa : {};
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
48
73
|
/**
|
|
49
74
|
* The invariant-collection ledger's `objectName` set, from a library dir.
|
|
50
75
|
*
|
|
@@ -40,7 +40,7 @@ export declare function emitLookupsBlock(specs: ReadonlyMap<string, LookupSpecDa
|
|
|
40
40
|
* parameters (HTTP Webhook) or one nothing has described yet, and an empty
|
|
41
41
|
* interface would refuse every key in both cases.
|
|
42
42
|
*/
|
|
43
|
-
export declare function emitEvent(entry: LibraryEntry, inFields: readonly LibraryField[], inputTree: TypeTree, outputTree: TypeTree, name: string, inputTypes: NamedTypeRegistry, outputTypes: NamedTypeRegistry, invariant?: ReadonlySet<string
|
|
43
|
+
export declare function emitEvent(entry: LibraryEntry, inFields: readonly LibraryField[], inputTree: TypeTree, outputTree: TypeTree, name: string, inputTypes: NamedTypeRegistry, outputTypes: NamedTypeRegistry, invariant?: ReadonlySet<string>, v1def?: V1Definition): string[];
|
|
44
44
|
/** One operation: its `Inputs`/`Outputs` interfaces, doc comment and `descriptor()` const. */
|
|
45
45
|
export declare function emitOp(entry: LibraryEntry, v1def: V1Definition, inputTree: TypeTree, outputTree: TypeTree, name: string, inputTypes: NamedTypeRegistry, outputTypes: NamedTypeRegistry, invariant?: ReadonlySet<string>): string[];
|
|
46
46
|
/**
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* event's per-object variants are skipped because they share their template's
|
|
19
19
|
* node type and so would emit the same const twice.
|
|
20
20
|
*/
|
|
21
|
+
import { prepareCommand } from "../../core/cli-spelling.js";
|
|
21
22
|
import { PACKAGE_NAME } from "../../package-name.js";
|
|
22
23
|
import { pyJsonString, pyJsonStringify } from "../codecs/pyjson.js";
|
|
23
24
|
import { sortedByCodePoint, sortedStrings } from "../compat/compare.js";
|
|
@@ -165,7 +166,7 @@ function versionOf(entry) {
|
|
|
165
166
|
* parameters (HTTP Webhook) or one nothing has described yet, and an empty
|
|
166
167
|
* interface would refuse every key in both cases.
|
|
167
168
|
*/
|
|
168
|
-
export function emitEvent(entry, inFields, inputTree, outputTree, name, inputTypes, outputTypes, invariant = new Set()) {
|
|
169
|
+
export function emitEvent(entry, inFields, inputTree, outputTree, name, inputTypes, outputTypes, invariant = new Set(), v1def = {}) {
|
|
169
170
|
const nodeType = entry.nodeType;
|
|
170
171
|
const eventId = afterLast(nodeType, ".");
|
|
171
172
|
const connectorKey = pyTruthy(entry.connector?.key) ? entry.connector.key : "";
|
|
@@ -196,6 +197,23 @@ export function emitEvent(entry, inFields, inputTree, outputTree, name, inputTyp
|
|
|
196
197
|
lines.push(` * Start a flow on it with \`onEvent(${name}, { where: { … } })\`, or pause for it`);
|
|
197
198
|
lines.push(` * with \`waitForEvent(${name}, { … })\`; \`where\` carries its event parameters.`);
|
|
198
199
|
}
|
|
200
|
+
// The facts the library build stamped from the event's `triggers objects`
|
|
201
|
+
// row. An author holding only the descriptor must learn the requirement here:
|
|
202
|
+
// on a standard connection the trigger deploys and never fires.
|
|
203
|
+
if (v1def.byoaConnection === true) {
|
|
204
|
+
lines.push(" *");
|
|
205
|
+
lines.push(" * Requires a BYOA (bring-your-own-app) connection — on a standard one the");
|
|
206
|
+
lines.push(" * trigger deploys and never fires. Bind it with");
|
|
207
|
+
// Spelled for whoever ran the generator, like every `check` remedy.
|
|
208
|
+
lines.push(` * \`${prepareCommand(pyStr(connectorKey), eventId, "--connection-id", "<id>")}\`,`);
|
|
209
|
+
lines.push(" * which refuses a standard connection and records the check `compile` requires;");
|
|
210
|
+
lines.push(" * `uip is connections list --byoa --all-folders` lists the BYOA connections.");
|
|
211
|
+
}
|
|
212
|
+
if (v1def.isWebhookUrlVisible === true) {
|
|
213
|
+
lines.push(" *");
|
|
214
|
+
lines.push(" * After deploying, register the trigger's webhook URL in the connector app's");
|
|
215
|
+
lines.push(" * event-subscription settings; `registry prepare` prints the instructions.");
|
|
216
|
+
}
|
|
199
217
|
// INSIDE the block: `emitLookupComment` returns bare ` * ` body lines.
|
|
200
218
|
if (specs.size > 0) {
|
|
201
219
|
lines.push(" *");
|
|
@@ -222,7 +240,7 @@ export function emitOp(entry, v1def, inputTree, outputTree, name, inputTypes, ou
|
|
|
222
240
|
const runtime = entry.runtime ?? {};
|
|
223
241
|
const inFields = descriptorInputFields(entry, v1def);
|
|
224
242
|
if (isEventNodeType(nodeType)) {
|
|
225
|
-
return emitEvent(entry, inFields, inputTree, outputTree, name, inputTypes, outputTypes, invariant);
|
|
243
|
+
return emitEvent(entry, inFields, inputTree, outputTree, name, inputTypes, outputTypes, invariant, v1def);
|
|
226
244
|
}
|
|
227
245
|
const lines = [];
|
|
228
246
|
lines.push(...emitInterface(`${name}Inputs`, false, inputTypes, inputTree, true));
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* One library entry rendered to Markdown: header → schema-dynamic notice →
|
|
3
|
-
* choosing the object → resolving the field set → required inputs → optional
|
|
3
|
+
* connection requirements (events) → choosing the object → resolving the field set → required inputs → optional
|
|
4
4
|
* inputs → resolving lookups → example → filtering → outputs. Ported from
|
|
5
5
|
* `render_op`; the page is `"\n".join(lines)` with no trailing newline.
|
|
6
6
|
*/
|
|
7
7
|
import { afterLast, pyStr } from "../../compat/pystr.js";
|
|
8
8
|
import { dictOf, getStr, pyOr, pyTruthy } from "./pyvalue.js";
|
|
9
9
|
import { choosingObjectLines } from "./sections/choosing-object.js";
|
|
10
|
+
import { eventFactsLines } from "./sections/event-facts.js";
|
|
10
11
|
import { exampleLines } from "./sections/example.js";
|
|
11
12
|
import { eventFilterLines } from "./sections/filtering.js";
|
|
12
13
|
import { headerLines } from "./sections/header.js";
|
|
@@ -28,6 +29,7 @@ export function renderOp(j, v1def, symbol, invariant) {
|
|
|
28
29
|
const out = [];
|
|
29
30
|
out.push(...headerLines(j, nodeType));
|
|
30
31
|
out.push(...schemaDynamicLines(j, nodeType));
|
|
32
|
+
out.push(...eventFactsLines(j, v1def));
|
|
31
33
|
const fields = assembleFields(j, v1def);
|
|
32
34
|
const required = fields.filter((f) => pyTruthy(f.required));
|
|
33
35
|
const optional = fields.filter((f) => !pyTruthy(f.required));
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `## Connection requirements`: the event facts an author has to act on before
|
|
3
|
+
* the trigger can fire — a BYOA (bring-your-own-app) connection, and a webhook
|
|
4
|
+
* URL registered by hand. Emitted only when a fact is TRUE, so every other
|
|
5
|
+
* event page is unchanged. The facts are the sidecar's, which the library build
|
|
6
|
+
* stamps from the event's `triggers objects` row (#848).
|
|
7
|
+
*/
|
|
8
|
+
import { prepareCommand } from "../../../../core/cli-spelling.js";
|
|
9
|
+
import { isEventNodeType } from "../../../model/library.js";
|
|
10
|
+
import { dictOf, getStr } from "../pyvalue.js";
|
|
11
|
+
export function eventFactsLines(j, v1def) {
|
|
12
|
+
const nodeType = getStr(j, "nodeType", "");
|
|
13
|
+
if (!isEventNodeType(nodeType))
|
|
14
|
+
return [];
|
|
15
|
+
const facts = dictOf(v1def);
|
|
16
|
+
const byoa = facts.byoaConnection === true;
|
|
17
|
+
const webhook = facts.isWebhookUrlVisible === true;
|
|
18
|
+
if (!byoa && !webhook)
|
|
19
|
+
return [];
|
|
20
|
+
const key = getStr(dictOf(j.connector), "key", "<connector>");
|
|
21
|
+
const event = nodeType.slice(nodeType.lastIndexOf(".") + 1);
|
|
22
|
+
const out = ["## Connection requirements", ""];
|
|
23
|
+
if (byoa) {
|
|
24
|
+
out.push("**Requires a BYOA connection.** This event fires only on a BYOA " +
|
|
25
|
+
"(bring-your-own-app) connection — one created with your own OAuth app. " +
|
|
26
|
+
"On a standard connection the trigger deploys and never fires. Prepare " +
|
|
27
|
+
"the event on the connection you bind: it refuses a standard connection " +
|
|
28
|
+
"and records a BYOA one, and `check` and `compile` refuse this event on a " +
|
|
29
|
+
"connection that was never checked (`EVENT_BYOA_UNVERIFIED`).");
|
|
30
|
+
out.push("");
|
|
31
|
+
out.push("```bash");
|
|
32
|
+
out.push(prepareCommand(key, event, "--connection-id", "<id>"));
|
|
33
|
+
out.push("uip is connections list --byoa --all-folders # the BYOA connections");
|
|
34
|
+
out.push("```");
|
|
35
|
+
out.push("");
|
|
36
|
+
}
|
|
37
|
+
if (webhook) {
|
|
38
|
+
out.push("**Register the webhook URL.** The connector's app delivers these events " +
|
|
39
|
+
"to a URL Integration Service issues. After deploying, copy the trigger's " +
|
|
40
|
+
"webhook URL into the app's event-subscription settings; `registry prepare` " +
|
|
41
|
+
"prints the connector's own instructions.");
|
|
42
|
+
out.push("");
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
@@ -48,15 +48,43 @@ export declare function normalizeBucketFields(parameters: unknown): Dict[];
|
|
|
48
48
|
* survives the merge.
|
|
49
49
|
*/
|
|
50
50
|
export declare function unionEventParameters(declared: unknown, objectParameters: unknown): Dict[];
|
|
51
|
-
/**
|
|
52
|
-
|
|
51
|
+
/** The three event facts: the API's (PascalCase) spelling and the stored (camelCase) one. */
|
|
52
|
+
declare const EVENT_FACTS: ReadonlyArray<readonly [string, "eventMode" | "byoaConnection" | "isWebhookUrlVisible"]>;
|
|
53
|
+
/** The facts one source states, under their stored names; a fact the source does not state is absent. */
|
|
54
|
+
export type StatedEventFacts = Partial<Record<(typeof EVENT_FACTS)[number][1], unknown>>;
|
|
55
|
+
/**
|
|
56
|
+
* THE precedence rule for the three event facts, used by every place that
|
|
57
|
+
* decides one: the `triggers objects` ROW wins, then `fallback`, and a fact
|
|
58
|
+
* neither states stays absent.
|
|
59
|
+
*
|
|
60
|
+
* `fallback` is whichever definition the caller holds — a `triggers describe`
|
|
61
|
+
* answer (PascalCase, generate time) or a registry node (camelCase, prepare
|
|
62
|
+
* time); both spellings are read. The row is the only one of the three sources
|
|
63
|
+
* that tells the truth about BYOA: Slack `message-received-in-slack` answers
|
|
64
|
+
* `ByoaConnection: true` in its objects row and `false` in both `describe` and
|
|
65
|
+
* the registry node. Generate time used to read `describe` alone while
|
|
66
|
+
* `prepare` read the row, so the library baked `false` for a BYOA-only event
|
|
67
|
+
* and nothing downstream could refuse a standard connection on it (#848).
|
|
68
|
+
* One function, so the two sides cannot drift again.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveEventFacts(objectRow: unknown, fallback: unknown): StatedEventFacts;
|
|
71
|
+
/**
|
|
72
|
+
* `merge_describe_into_node`: fold a `triggers describe` answer into a registry
|
|
73
|
+
* trigger definition (a copy). The facts follow {@link resolveEventFacts}, so
|
|
74
|
+
* pass the event's `triggers objects` row when there is one: `prepare` stores
|
|
75
|
+
* this definition as the overlay, and `check` reads BYOA off the overlay.
|
|
76
|
+
*/
|
|
77
|
+
export declare function mergeDescribeIntoNode(node: Dict, describe: Dict, objectParameters?: unknown, objectRow?: unknown): Dict;
|
|
53
78
|
export interface EventFacts {
|
|
54
79
|
eventMode: string;
|
|
55
80
|
byoaConnection: boolean;
|
|
56
81
|
isWebhookUrlVisible: boolean;
|
|
57
82
|
textBlocks: string[];
|
|
58
83
|
}
|
|
59
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* `event_facts`: the three facts that change how a subscription is prepared or
|
|
86
|
+
* tested, by {@link resolveEventFacts} (the object row wins), with defaults.
|
|
87
|
+
*/
|
|
60
88
|
export declare function eventFacts(node: Dict, objectRow: unknown): EventFacts;
|
|
61
89
|
/**
|
|
62
90
|
* `triggers_objects_cached`: cached `uip is triggers objects <key> <OPERATION>`,
|
|
@@ -106,3 +134,4 @@ export declare function expandGenericEvents(ctx: BuildContext, templates: Librar
|
|
|
106
134
|
* input with curated events described in place.
|
|
107
135
|
*/
|
|
108
136
|
export declare function resolveConnectorEvents(ctx: BuildContext, entries: LibraryEntry[]): Promise<[LibraryEntry[], LibraryEntry[]]>;
|
|
137
|
+
export {};
|
|
@@ -261,39 +261,69 @@ export function unionEventParameters(declared, objectParameters) {
|
|
|
261
261
|
}
|
|
262
262
|
return withCascade([...merged.values()]);
|
|
263
263
|
}
|
|
264
|
+
/** The three event facts: the API's (PascalCase) spelling and the stored (camelCase) one. */
|
|
264
265
|
const EVENT_FACTS = [
|
|
265
266
|
["EventMode", "eventMode"],
|
|
266
267
|
["ByoaConnection", "byoaConnection"],
|
|
267
268
|
["IsWebhookUrlVisible", "isWebhookUrlVisible"],
|
|
268
269
|
];
|
|
269
|
-
/**
|
|
270
|
-
|
|
270
|
+
/**
|
|
271
|
+
* THE precedence rule for the three event facts, used by every place that
|
|
272
|
+
* decides one: the `triggers objects` ROW wins, then `fallback`, and a fact
|
|
273
|
+
* neither states stays absent.
|
|
274
|
+
*
|
|
275
|
+
* `fallback` is whichever definition the caller holds — a `triggers describe`
|
|
276
|
+
* answer (PascalCase, generate time) or a registry node (camelCase, prepare
|
|
277
|
+
* time); both spellings are read. The row is the only one of the three sources
|
|
278
|
+
* that tells the truth about BYOA: Slack `message-received-in-slack` answers
|
|
279
|
+
* `ByoaConnection: true` in its objects row and `false` in both `describe` and
|
|
280
|
+
* the registry node. Generate time used to read `describe` alone while
|
|
281
|
+
* `prepare` read the row, so the library baked `false` for a BYOA-only event
|
|
282
|
+
* and nothing downstream could refuse a standard connection on it (#848).
|
|
283
|
+
* One function, so the two sides cannot drift again.
|
|
284
|
+
*/
|
|
285
|
+
export function resolveEventFacts(objectRow, fallback) {
|
|
286
|
+
const row = pyOr(objectRow, {});
|
|
287
|
+
const other = pyOr(fallback, {});
|
|
288
|
+
const out = {};
|
|
289
|
+
for (const [api, stored] of EVENT_FACTS) {
|
|
290
|
+
for (const [source, key] of [[row, api], [other, api], [other, stored]]) {
|
|
291
|
+
if (get(source, key) !== null) {
|
|
292
|
+
out[stored] = source[key];
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* `merge_describe_into_node`: fold a `triggers describe` answer into a registry
|
|
301
|
+
* trigger definition (a copy). The facts follow {@link resolveEventFacts}, so
|
|
302
|
+
* pass the event's `triggers objects` row when there is one: `prepare` stores
|
|
303
|
+
* this definition as the overlay, and `check` reads BYOA off the overlay.
|
|
304
|
+
*/
|
|
305
|
+
export function mergeDescribeIntoNode(node, describe, objectParameters = null, objectRow = null) {
|
|
271
306
|
const out = { ...node };
|
|
272
307
|
out.eventParameters = { fields: unionEventParameters(get(describe, "EventParameters"), objectParameters) };
|
|
273
308
|
out.filterFields = { fields: camelFields(get(describe, "FilterFields")) };
|
|
274
309
|
if (truthy(get(describe, "OutputFields"))) {
|
|
275
310
|
out.outputResponseDefinition = { fields: camelFields(get(describe, "OutputFields")) };
|
|
276
311
|
}
|
|
277
|
-
|
|
278
|
-
if (get(describe, src) !== null)
|
|
279
|
-
out[dst] = describe[src];
|
|
312
|
+
Object.assign(out, resolveEventFacts(objectRow, describe));
|
|
280
313
|
return out;
|
|
281
314
|
}
|
|
282
|
-
/**
|
|
315
|
+
/**
|
|
316
|
+
* `event_facts`: the three facts that change how a subscription is prepared or
|
|
317
|
+
* tested, by {@link resolveEventFacts} (the object row wins), with defaults.
|
|
318
|
+
*/
|
|
283
319
|
export function eventFacts(node, objectRow) {
|
|
284
320
|
const row = pyOr(objectRow, {});
|
|
285
|
-
const
|
|
286
|
-
if (get(row, rowKey) !== null)
|
|
287
|
-
return row[rowKey];
|
|
288
|
-
if (get(node, nodeKey) !== null)
|
|
289
|
-
return node[nodeKey];
|
|
290
|
-
return dflt;
|
|
291
|
-
};
|
|
321
|
+
const stated = resolveEventFacts(row, node);
|
|
292
322
|
const textBlocks = pyOr(get(pyOr(get(row, "Design"), {}), "TextBlocks"), get(pyOr(get(row, "design"), {}), "textBlocks"), []);
|
|
293
323
|
return {
|
|
294
|
-
eventMode: pyStr(pyOr(
|
|
295
|
-
byoaConnection: truthy(
|
|
296
|
-
isWebhookUrlVisible: truthy(
|
|
324
|
+
eventMode: pyStr(pyOr(stated.eventMode ?? null, "polling")),
|
|
325
|
+
byoaConnection: truthy(stated.byoaConnection ?? false),
|
|
326
|
+
isWebhookUrlVisible: truthy(stated.isWebhookUrlVisible ?? false),
|
|
297
327
|
textBlocks: pyIter(textBlocks).map(textBlockText),
|
|
298
328
|
};
|
|
299
329
|
}
|
|
@@ -388,9 +418,8 @@ export function applyEventSchema(entry, describe, obj) {
|
|
|
388
418
|
if (outputFields.length > 0)
|
|
389
419
|
e.outputSchema = { fields: outputFields };
|
|
390
420
|
const eventSchema = { eventParameters: fields, filterFields: camelFields(get(d, "FilterFields")) };
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
eventSchema[dst] = d[src];
|
|
421
|
+
// The objects row is the per-object fact sheet; describe is the fallback.
|
|
422
|
+
Object.assign(eventSchema, resolveEventFacts(o, d));
|
|
394
423
|
e.eventSchema = eventSchema;
|
|
395
424
|
return entry;
|
|
396
425
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ConnectionRow } from "./connections.js";
|
|
2
|
+
/**
|
|
3
|
+
* The ledger with `byoa[nodeType][connectionId]` set to a passing check. Pure:
|
|
4
|
+
* returns a new ledger. A re-run on the same connection rewrites the entry,
|
|
5
|
+
* `verifiedAt` included — the check was made again, so the snapshot is newer.
|
|
6
|
+
*/
|
|
7
|
+
export declare function recordByoa(ledger: Record<string, unknown>, nodeType: string, connectionId: string, row: ConnectionRow | undefined, verifiedAt: string): Record<string, unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* Record a passing BYOA check in `<outDir>/resolutions.json` and return that
|
|
10
|
+
* path: read (refusing a corrupt file before anything is written), record, write.
|
|
11
|
+
*/
|
|
12
|
+
export declare function recordByoaVerification(outDir: string, nodeType: string, connectionId: string, row: ConnectionRow | undefined, verifiedAt?: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ledgerPath, readLedger, writeLedger } from "./objects.js";
|
|
2
|
+
import { isPlainObject, pyGet, pyStrAny } from "./support.js";
|
|
3
|
+
/**
|
|
4
|
+
* The ledger with `byoa[nodeType][connectionId]` set to a passing check. Pure:
|
|
5
|
+
* returns a new ledger. A re-run on the same connection rewrites the entry,
|
|
6
|
+
* `verifiedAt` included — the check was made again, so the snapshot is newer.
|
|
7
|
+
*/
|
|
8
|
+
export function recordByoa(ledger, nodeType, connectionId, row, verifiedAt) {
|
|
9
|
+
const sectionIn = ledger.byoa;
|
|
10
|
+
const section = isPlainObject(sectionIn) ? { ...sectionIn } : {};
|
|
11
|
+
const perEventIn = section[nodeType];
|
|
12
|
+
const perEvent = isPlainObject(perEventIn) ? { ...perEventIn } : {};
|
|
13
|
+
const name = pyStrAny(pyGet(row ?? {}, "Name", "") ?? "");
|
|
14
|
+
perEvent[connectionId] = { byoa: true, ...(name ? { connectionName: name } : {}), verifiedAt };
|
|
15
|
+
section[nodeType] = perEvent;
|
|
16
|
+
return { ...ledger, schemaVersion: "1", byoa: section };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Record a passing BYOA check in `<outDir>/resolutions.json` and return that
|
|
20
|
+
* path: read (refusing a corrupt file before anything is written), record, write.
|
|
21
|
+
*/
|
|
22
|
+
export function recordByoaVerification(outDir, nodeType, connectionId, row, verifiedAt = new Date().toISOString().slice(0, 10)) {
|
|
23
|
+
const path = ledgerPath(outDir);
|
|
24
|
+
writeLedger(path, recordByoa(readLedger(path), nodeType, connectionId, row, verifiedAt));
|
|
25
|
+
return path;
|
|
26
|
+
}
|
|
@@ -3,6 +3,7 @@ import { type EventFacts } from "../library-build/events.js";
|
|
|
3
3
|
import { type Dict } from "../library-build/py.js";
|
|
4
4
|
import type { LibraryEntry } from "../model/library.js";
|
|
5
5
|
import type { UipClient } from "../uip/client.js";
|
|
6
|
+
import { type ConnectionRow } from "./connections.js";
|
|
6
7
|
/**
|
|
7
8
|
* `_event_operation`: the operation key every trigger API takes.
|
|
8
9
|
*
|
|
@@ -50,8 +51,11 @@ export interface BindingsRollback {
|
|
|
50
51
|
* connection into `bindings.json` by the time the event's own metadata says it
|
|
51
52
|
* is the wrong KIND, so the file is restored first. A listing that FAILED is
|
|
52
53
|
* not a tenant with no BYOA connections; the remedies are opposite.
|
|
54
|
+
*
|
|
55
|
+
* Returns the connection's BYOA listing row when it passes, for the record
|
|
56
|
+
* `prepare` then writes (see `byoa-ledger.ts`).
|
|
53
57
|
*/
|
|
54
|
-
export declare function refuseUnlessByoaConnection(client: UipClient, connectorKey: string, connectionId: string, rollback: BindingsRollback | undefined, warn: (line: string) => void): Promise<
|
|
58
|
+
export declare function refuseUnlessByoaConnection(client: UipClient, connectorKey: string, connectionId: string, rollback: BindingsRollback | undefined, warn: (line: string) => void): Promise<ConnectionRow>;
|
|
55
59
|
export interface EventPrepareOptions {
|
|
56
60
|
connectorKey: string;
|
|
57
61
|
action: string;
|
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { extractCanonical, nodeOf } from "../library-build/canonical.js";
|
|
23
23
|
import { registryProbe } from "../library-build/context.js";
|
|
24
|
-
import { EventDiscoveryError, eventFacts, mergeDescribeIntoNode, triggersDescribe, triggersObjects, unionEventParameters, } from "../library-build/events.js";
|
|
24
|
+
import { EventDiscoveryError, eventFacts, mergeDescribeIntoNode, resolveEventFacts, triggersDescribe, triggersObjects, unionEventParameters, } from "../library-build/events.js";
|
|
25
25
|
import { get, isRecord } from "../library-build/py.js";
|
|
26
26
|
import { planLibrary } from "../library-build/plan.js";
|
|
27
|
+
import { recordByoaVerification } from "./byoa-ledger.js";
|
|
27
28
|
import { ConnectionRefusal, byoaConnections, byoaListing, restoreBindings } from "./connections.js";
|
|
28
29
|
import { writeResolutions } from "./ledger.js";
|
|
29
|
-
import { PREPARE_COMMAND, PrepareRefusal, byoaListingFailedMessage, byoaRequiredMessage, describeFallbackWarning, generatedModulesLine, eventAllObjectsMessage, eventNextLine, eventParentFieldsMessage, eventSubscription, eventSummaryLine, filterableFieldsLine, genericEventNeedsObjectMessage, lookupVocabularyLines, objectNoteLine, objectOnCuratedEventMessage, objectRecordedLine, warnLine, webhookNoteLines, } from "./messages.js";
|
|
30
|
+
import { PREPARE_COMMAND, PrepareRefusal, byoaListingFailedMessage, byoaRecordedLine, byoaRequiredMessage, describeFallbackWarning, generatedModulesLine, eventAllObjectsMessage, eventNextLine, eventParentFieldsMessage, eventSubscription, eventSummaryLine, filterableFieldsLine, genericEventNeedsObjectMessage, lookupVocabularyLines, objectNoteLine, objectOnCuratedEventMessage, objectRecordedLine, warnLine, webhookNoteLines, } from "./messages.js";
|
|
30
31
|
import { RESOLUTIONS_FILENAME, matchObject, recordObjectResolution } from "./objects.js";
|
|
31
32
|
import { lookupSpecsFromOverlay, mergeFilesInto } from "./overlay.js";
|
|
32
33
|
import { regenerateDescriptors } from "./regenerate.js";
|
|
@@ -62,12 +63,15 @@ export function assembleEventDefinition(node, entry, describe, objectRow, eventN
|
|
|
62
63
|
const objectParameters = objectRow === undefined ? null : pyGet(objectRow, "Parameters", null);
|
|
63
64
|
let stored;
|
|
64
65
|
if (describe !== undefined) {
|
|
65
|
-
stored = mergeDescribeIntoNode(node, describe, objectParameters);
|
|
66
|
+
stored = mergeDescribeIntoNode(node, describe, objectParameters, objectRow ?? null);
|
|
66
67
|
}
|
|
67
68
|
else {
|
|
68
69
|
stored = { ...node };
|
|
69
70
|
const declared = pyOr(get(stored, "eventParameters"), {});
|
|
70
71
|
stored.eventParameters = { fields: unionEventParameters(get(declared, "fields"), objectParameters) };
|
|
72
|
+
// The row's facts win here too: this definition IS the overlay, and a
|
|
73
|
+
// describe outage on a BYOA event must not store the registry's `false`.
|
|
74
|
+
Object.assign(stored, resolveEventFacts(objectRow ?? null, stored));
|
|
71
75
|
}
|
|
72
76
|
const out = { ...entry };
|
|
73
77
|
const outputDefinition = pyOr(get(stored, "outputResponseDefinition"), {});
|
|
@@ -88,6 +92,9 @@ export function assembleEventDefinition(node, entry, describe, objectRow, eventN
|
|
|
88
92
|
* connection into `bindings.json` by the time the event's own metadata says it
|
|
89
93
|
* is the wrong KIND, so the file is restored first. A listing that FAILED is
|
|
90
94
|
* not a tenant with no BYOA connections; the remedies are opposite.
|
|
95
|
+
*
|
|
96
|
+
* Returns the connection's BYOA listing row when it passes, for the record
|
|
97
|
+
* `prepare` then writes (see `byoa-ledger.ts`).
|
|
91
98
|
*/
|
|
92
99
|
export async function refuseUnlessByoaConnection(client, connectorKey, connectionId, rollback, warn) {
|
|
93
100
|
const restore = () => {
|
|
@@ -104,8 +111,9 @@ export async function refuseUnlessByoaConnection(client, connectorKey, connectio
|
|
|
104
111
|
restore();
|
|
105
112
|
throw new PrepareRefusal(byoaListingFailedMessage(connectionId, error), "BYOA_LISTING_FAILED");
|
|
106
113
|
}
|
|
107
|
-
|
|
108
|
-
|
|
114
|
+
const match = rows.find((row) => pyStrAny(pyGet(row, "Id", null)) === connectionId);
|
|
115
|
+
if (match)
|
|
116
|
+
return match;
|
|
109
117
|
restore();
|
|
110
118
|
throw new PrepareRefusal(byoaRequiredMessage(connectionId, connectorKey, byoaListing(rows, connectorKey)), "BYOA_REQUIRED");
|
|
111
119
|
}
|
|
@@ -212,14 +220,20 @@ export async function prepareEvent(ctx, options) {
|
|
|
212
220
|
}
|
|
213
221
|
}
|
|
214
222
|
const facts = eventFacts(node, objectRow ?? null);
|
|
215
|
-
|
|
216
|
-
await refuseUnlessByoaConnection(ctx.client, connectorKey, connectionId, options.bindings, warn)
|
|
217
|
-
|
|
223
|
+
const byoaRow = facts.byoaConnection
|
|
224
|
+
? await refuseUnlessByoaConnection(ctx.client, connectorKey, connectionId, options.bindings, warn)
|
|
225
|
+
: undefined;
|
|
218
226
|
const definition = assembleEventDefinition(node, entry, describe, objectRow, eventNodeType);
|
|
219
227
|
const plan = planLibrary([definition.entry], () => definition.node);
|
|
220
228
|
for (const line of plan.warnings)
|
|
221
229
|
warn(line);
|
|
222
230
|
mergeFilesInto(plan.files, out);
|
|
231
|
+
if (byoaRow !== undefined) {
|
|
232
|
+
// What `check` and `compile` look for before they accept this event on this
|
|
233
|
+
// connection: the proof that the live check above ran and passed.
|
|
234
|
+
recordByoaVerification(out, eventNodeType, connectionId, byoaRow);
|
|
235
|
+
info(byoaRecordedLine(connectionId, pyPathJoin(outShown, RESOLUTIONS_FILENAME)));
|
|
236
|
+
}
|
|
223
237
|
if (generic) {
|
|
224
238
|
recordObjectResolution(out, eventNodeType, requestedObject, objectRow, operation);
|
|
225
239
|
// Named as the author spelled `--out`, not as the file was resolved.
|
|
@@ -237,6 +237,8 @@ export declare function warnLine(error: unknown): string;
|
|
|
237
237
|
/** The describe could not answer for a curated event; the definition's own sections stand in. */
|
|
238
238
|
export declare function describeFallbackWarning(error: unknown, bakedObject: string): string;
|
|
239
239
|
export declare function byoaListingFailedMessage(connectionId: string, error: unknown): string;
|
|
240
|
+
/** The passing BYOA check, and where it was recorded for `check` / `compile`. */
|
|
241
|
+
export declare function byoaRecordedLine(connectionId: string, ledgerPath: string): string;
|
|
240
242
|
export declare function byoaRequiredMessage(connectionId: string, connectorKey: string, listing: string): string;
|
|
241
243
|
export declare function eventSummaryLine(eventNodeType: string, out: string, operation: string, mode: string, whereParameters: number, filterFields: number): string;
|
|
242
244
|
/** The first eight filterable field names, or nothing when the event has none. */
|
|
@@ -548,6 +548,10 @@ export function byoaListingFailedMessage(connectionId, error) {
|
|
|
548
548
|
"(bring-your-own-app) connection, and the BYOA listing needed to " +
|
|
549
549
|
`check ${connectionId} against it failed: ${messageOf(error)}`);
|
|
550
550
|
}
|
|
551
|
+
/** The passing BYOA check, and where it was recorded for `check` / `compile`. */
|
|
552
|
+
export function byoaRecordedLine(connectionId, ledgerPath) {
|
|
553
|
+
return ` byoa: ${connectionId} is a BYOA connection — recorded in ${ledgerPath}`;
|
|
554
|
+
}
|
|
551
555
|
export function byoaRequiredMessage(connectionId, connectorKey, listing) {
|
|
552
556
|
return (`${PREFIX}this event object requires a BYOA ` +
|
|
553
557
|
`(bring-your-own-app) connection, and ${connectionId} is not ` +
|
package/dist/serialize.js
CHANGED
|
@@ -16,6 +16,7 @@ import { connectorRawNodeRefusal } from './core/connector-raw-node.js';
|
|
|
16
16
|
import { dataFabricUnknownInputs } from './core/typed-raw-node.js';
|
|
17
17
|
import { isAnswerField } from './core/hitl-answers.js';
|
|
18
18
|
import { BindingRefusal, GUID_RE, bindingSelfNameMessage, bindingUndeclaredMessage, undeclaredBinding } from './core/binding-messages.js';
|
|
19
|
+
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
19
20
|
import { OUTCOME_HANDLE_NODE_TYPES, assertHitlExitInvariant, hitlExitModel, hitlExitViolation, outcomeSlug } from './core/hitl-routing.js';
|
|
20
21
|
import { declaredExits, hasExits, stopsAtEnd } from './core/step-ports.js';
|
|
21
22
|
import { buildConfiguration, transportHttpMethod } from './config.js';
|
|
@@ -3212,6 +3213,24 @@ function eventTarget(sub) {
|
|
|
3212
3213
|
? { key: sub.connector, ...(typeof sub.event === 'string' && sub.event !== '' ? { action: sub.event } : {}) }
|
|
3213
3214
|
: undefined;
|
|
3214
3215
|
}
|
|
3216
|
+
/**
|
|
3217
|
+
* Throw `check`'s EVENT_BYOA_UNVERIFIED for a subscription whose event only
|
|
3218
|
+
* fires on a BYOA connection and whose bound connection `prepare` never checked
|
|
3219
|
+
* — the one condition in `core/byoa.ts`, fed from the same library and
|
|
3220
|
+
* bindings, so a flow check refuses never compiles.
|
|
3221
|
+
*
|
|
3222
|
+
* `where` is check's spelling of the site (`trigger` for `onEvent`, entry points
|
|
3223
|
+
* included; `waitForEvent "<step>"`), so the two print the same sentence.
|
|
3224
|
+
*/
|
|
3225
|
+
function refuseUnverifiedByoa(opts, where, sub) {
|
|
3226
|
+
const library = opts.library;
|
|
3227
|
+
if (!library || typeof library.eventFacts !== 'function')
|
|
3228
|
+
return;
|
|
3229
|
+
const object = typeof sub.object === 'string' && sub.object !== '' ? sub.object : undefined;
|
|
3230
|
+
const message = byoaUnverified(where, { connector: sub.connector, event: sub.event, ...(object ? { object } : {}), connection: sub.connection }, library.eventFacts(sub.connector, sub.event, object), library.byoaVerifications, opts.bindings);
|
|
3231
|
+
if (message)
|
|
3232
|
+
throw new ByoaRefusal(message);
|
|
3233
|
+
}
|
|
3215
3234
|
/**
|
|
3216
3235
|
* Resolve a symbolic connection/folder name to the resource key that is inlined
|
|
3217
3236
|
* as `connectionId` / `connectionFolderKey`.
|
|
@@ -4184,7 +4203,9 @@ export function serialize(built, opts = {}) {
|
|
|
4184
4203
|
if (!opts.library)
|
|
4185
4204
|
throw new Error(`onEvent() needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
|
|
4186
4205
|
const sub = built.trigger.subscription;
|
|
4187
|
-
|
|
4206
|
+
const rc = opts.library.resolveEvent('trigger', sub.connector, sub.event, sub.version, sub.object);
|
|
4207
|
+
refuseUnverifiedByoa(opts, 'trigger', sub);
|
|
4208
|
+
return rc;
|
|
4188
4209
|
})()
|
|
4189
4210
|
: undefined;
|
|
4190
4211
|
// The trigger node's id is `start` unless the flow renamed it. `input('x')`
|
|
@@ -5306,6 +5327,7 @@ export function serialize(built, opts = {}) {
|
|
|
5306
5327
|
throw new Error(`waitForEvent "${step.name}" needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
|
|
5307
5328
|
const sub = spec.subscription;
|
|
5308
5329
|
const rc = opts.library.resolveEvent('event', sub.connector, sub.event, sub.version, sub.object);
|
|
5330
|
+
refuseUnverifiedByoa(opts, `waitForEvent "${step.name}"`, sub);
|
|
5309
5331
|
const id = stepUid(scope, step.name);
|
|
5310
5332
|
const node = makeNode(rc.nodeType, id, step.name, { parentId, requestedVersion: step.options?.version, def: rc.v1def });
|
|
5311
5333
|
node.inputs = { detail: eventDetail(rc, sub, id, opts) };
|
|
@@ -6160,6 +6182,7 @@ export function serialize(built, opts = {}) {
|
|
|
6160
6182
|
throw new Error(`onEvent() needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
|
|
6161
6183
|
const sub = epSpec.subscription;
|
|
6162
6184
|
const rc = opts.library.resolveEvent('trigger', sub.connector, sub.event, sub.version, sub.object);
|
|
6185
|
+
refuseUnverifiedByoa(opts, 'trigger', sub);
|
|
6163
6186
|
node = makeNode(rc.nodeType, ep.id, 'Event trigger', { def: rc.v1def, requestedVersion });
|
|
6164
6187
|
node.inputs = {
|
|
6165
6188
|
entryPointId: stableId(`${built.id}:${ep.id}:entryPoint`),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.11.
|
|
3
|
+
"version": "6.11.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": "db117054e312c3c2aa7b7b208d3a92fc68de7fb9"
|
|
96
96
|
}
|