@uipath/maestro-builder-sdk 6.15.4 → 6.15.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/README.md +3 -1
- package/dist/api-index.md +122 -121
- package/dist/api-members.md +410 -405
- package/dist/bpmn/bpmn-sdk.d.ts +170 -18
- package/dist/bpmn/bpmn-sdk.js +123 -5
- package/dist/bpmn/check-cli.js +4 -3
- package/dist/bpmn/check.js +79 -6
- package/dist/bpmn/connector.js +5 -2
- package/dist/bpmn/data-service.d.ts +10 -2
- package/dist/bpmn/data-service.js +10 -1
- package/dist/bpmn/decompile.js +13 -2
- package/dist/bpmn/intsvc.d.ts +8 -0
- package/dist/bpmn/intsvc.js +43 -2
- package/dist/bpmn/serialize.d.ts +14 -0
- package/dist/bpmn/serialize.js +38 -9
- package/dist/bpmn/typed-node.js +76 -4
- package/dist/check.js +142 -6
- package/dist/cli-result.d.ts +14 -0
- package/dist/cli-result.js +18 -0
- package/dist/core/connector-inputs.d.ts +20 -0
- package/dist/core/connector-inputs.js +51 -0
- package/dist/core/event-checks.d.ts +8 -6
- package/dist/core/event-checks.js +8 -6
- package/dist/core/expr.d.ts +8 -2
- package/dist/core/expr.js +8 -2
- package/dist/core/global-names.d.ts +5 -7
- package/dist/core/global-names.js +5 -14
- package/dist/decompile.js +2 -2
- package/dist/flow-sdk.d.ts +27 -4
- package/dist/flow-sdk.js +24 -7
- package/dist/flow-variables.d.ts +66 -0
- package/dist/flow-variables.js +84 -0
- package/dist/registry/path-cli.js +3 -3
- package/dist/registry/search-cli.js +2 -2
- package/dist/serialize.js +27 -17
- package/package.json +2 -2
package/dist/bpmn/bpmn-sdk.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* separate "tidy" step lays it out. See serialize.ts.
|
|
21
21
|
*/
|
|
22
22
|
import type { TypeDesc } from '../core/expr.js';
|
|
23
|
-
import { type ConnectorOpts } from '../core/actions.js';
|
|
23
|
+
import { type ConnectorOpts, type EventFilter } from '../core/actions.js';
|
|
24
24
|
import type { ConnectorDescriptor } from '../core/connectors.js';
|
|
25
25
|
import type { RegistryTypeSpec, TypedContextRow, TypedInputRow, TypedOutputRow } from './typed-node.js';
|
|
26
26
|
import { type DataServiceOperation } from './data-service.js';
|
|
@@ -230,6 +230,8 @@ export type BpmnNode = {
|
|
|
230
230
|
/** The `where` scope and extra event parameters, when the operation declares any. */
|
|
231
231
|
filter?: Record<string, unknown>;
|
|
232
232
|
parameters?: Record<string, unknown>;
|
|
233
|
+
/** Payload conditions — see {@link ConnectorEventOpts.filters}. */
|
|
234
|
+
filters?: EventFilter[];
|
|
233
235
|
outputVar?: string;
|
|
234
236
|
outputs?: Record<string, string>;
|
|
235
237
|
skipCondition?: string;
|
|
@@ -841,9 +843,20 @@ export interface ScriptTaskOpts extends ActivityOpts {
|
|
|
841
843
|
/** Display name the designer shows on the task. */
|
|
842
844
|
name?: string;
|
|
843
845
|
/**
|
|
844
|
-
* The script body (Jint JavaScript).
|
|
845
|
-
*
|
|
846
|
-
*
|
|
846
|
+
* The script body (Jint JavaScript).
|
|
847
|
+
*
|
|
848
|
+
* @remarks
|
|
849
|
+
* **Read process data as `vars.<id>`, never as a bare identifier.** The runtime
|
|
850
|
+
* injects the product's fixed envelope into the script's scope — `vars` (every
|
|
851
|
+
* variable in scope, by id), `metadata`, and `iterator` inside a loop body — and
|
|
852
|
+
* nothing else. A script written `return amount * 2` with
|
|
853
|
+
* `inputs: { amount: '=vars.amount' }` passes `check`, `compile` and
|
|
854
|
+
* `uip maestro bpmn validate` and then faults on the platform with
|
|
855
|
+
* `amount is not defined`; the same script written `return vars.amount * 2`
|
|
856
|
+
* runs. `check` reports the first shape as `SCRIPT_BARE_INPUT_REF`.
|
|
857
|
+
*
|
|
858
|
+
* The serializer writes the envelope for you (see {@link ScriptTaskOpts.inputs}), so
|
|
859
|
+
* a script task that reads `vars.<id>` needs no `inputs` at all.
|
|
847
860
|
*/
|
|
848
861
|
script: string;
|
|
849
862
|
/** The script language marker. Defaults to `'JavaScript'` (Jint). */
|
|
@@ -862,7 +875,20 @@ export interface ScriptTaskOpts extends ActivityOpts {
|
|
|
862
875
|
* `v3`, spelling an absent element as `'v1'`.
|
|
863
876
|
*/
|
|
864
877
|
scriptVersion?: string;
|
|
865
|
-
/**
|
|
878
|
+
/**
|
|
879
|
+
* Extra keys for the `args` input, after the envelope: key → `=`-expression.
|
|
880
|
+
*
|
|
881
|
+
* @remarks
|
|
882
|
+
* The emitted `<uipath:input name="args" target="bodyField">` is always
|
|
883
|
+
* `{"vars":"=vars","metadata":"=metadata", …inputs}` — the shape every Studio Web
|
|
884
|
+
* export carries and the only one the platform runtime honours. The runtime does
|
|
885
|
+
* NOT make an `inputs` key readable as a bare identifier (see
|
|
886
|
+
* {@link ScriptTaskOpts.script}), so for ordinary authoring leave this off and read
|
|
887
|
+
* `vars.<id>` in the script. It exists for imports — the designer writes
|
|
888
|
+
* `"iterator[0]":"=iterator[0]"` to scope a loop body — and for a key the author
|
|
889
|
+
* knows the runtime reads. `vars` and `metadata` given here override the envelope's
|
|
890
|
+
* values, which is never useful but keeps a round trip byte-faithful.
|
|
891
|
+
*/
|
|
866
892
|
inputs?: Record<string, string>;
|
|
867
893
|
/**
|
|
868
894
|
* `uipath:output` rows: variable id → `=`-expression.
|
|
@@ -891,7 +917,14 @@ export interface ScriptTaskOpts extends ActivityOpts {
|
|
|
891
917
|
outputRows?: TypedOutputRow[];
|
|
892
918
|
/**
|
|
893
919
|
* The `uipath:inputSchema` body inside the mapping's `uipath:context` — a JSON
|
|
894
|
-
* Schema for the `args` the script receives.
|
|
920
|
+
* Schema for the `args` the script receives.
|
|
921
|
+
*
|
|
922
|
+
* @remarks
|
|
923
|
+
* Real script tasks all carry one, so when this is absent the serializer writes the
|
|
924
|
+
* product's: `{"type":"object","properties":{"vars":{"type":"object"},"metadata":{"type":"object"}}}`,
|
|
925
|
+
* plus an untyped property per extra `inputs` key. Set it only on an import whose
|
|
926
|
+
* schema differs (the designer's carries `$schema`); `bpmn-decompile` drops the
|
|
927
|
+
* default and keeps anything else verbatim.
|
|
895
928
|
*/
|
|
896
929
|
inputSchema?: unknown;
|
|
897
930
|
/**
|
|
@@ -1103,10 +1136,57 @@ export interface HttpOpts extends ActivityOpts {
|
|
|
1103
1136
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
1104
1137
|
/** Request headers — serialized to the node's json context field. */
|
|
1105
1138
|
headers?: Record<string, unknown>;
|
|
1106
|
-
/**
|
|
1139
|
+
/**
|
|
1140
|
+
* Query parameters — serialized to the node's json context field. In connector mode
|
|
1141
|
+
* (see {@link HttpOpts.connection}) they are appended to the URL, so the URL must be
|
|
1142
|
+
* a literal there.
|
|
1143
|
+
*/
|
|
1107
1144
|
parameters?: Record<string, unknown>;
|
|
1108
|
-
/**
|
|
1145
|
+
/**
|
|
1146
|
+
* Request body — serialized to the node's json context field.
|
|
1147
|
+
*
|
|
1148
|
+
* @remarks
|
|
1149
|
+
* Leave it off for a request that has none: the row is written as `{}`, which the
|
|
1150
|
+
* runtime accepts. The registry declares the default as the text `null`, and the
|
|
1151
|
+
* runtime refuses that (`IntSvcUnifiedHttpRequestArgs`: `Body cannot be null`,
|
|
1152
|
+
* incident 102018) — every GET this SDK emitted before flow-v2-run-12 faulted on it.
|
|
1153
|
+
*/
|
|
1109
1154
|
body?: unknown;
|
|
1155
|
+
/**
|
|
1156
|
+
* Symbolic binding name of an Integration Service **connection** to send the
|
|
1157
|
+
* request through — which switches the node to CONNECTOR mode.
|
|
1158
|
+
*
|
|
1159
|
+
* @remarks
|
|
1160
|
+
* Without it the node is `Intsvc.UnifiedHttpRequest` in `mode="manual"`: the
|
|
1161
|
+
* process owns the URL, headers and auth, and nothing on the tenant is involved.
|
|
1162
|
+
* With it the node is the connector activity the v1 skill calls "connector HTTP" —
|
|
1163
|
+
* `Intsvc.ActivityExecution` on the generic HTTP connector (`uipath-uipath-http`,
|
|
1164
|
+
* object `http-request`), whose `body` carries the request
|
|
1165
|
+
* (`{"authentication":"connector","targetConnector":…,"connection":"=bindings.…","method":"GET","url":…,"path":…,"headers":…,"body":…}`)
|
|
1166
|
+
* and whose auth is the connection's. That is the shape for "call an endpoint the
|
|
1167
|
+
* connector catalog has no activity for, through an existing connection" — the
|
|
1168
|
+
* non-catalog HTTP fallback — and it was not expressible before: in flow-v2-run-12
|
|
1169
|
+
* both fallback cards (non-catalog-http-fallback, slack-http-fallback) authored a
|
|
1170
|
+
* connectionless node because this option did not exist, and the grader found
|
|
1171
|
+
* `connectorKey values seen: []`.
|
|
1172
|
+
*
|
|
1173
|
+
* Pair it with {@link HttpOpts.folder}; both resolve as `.dataService()`'s do — an
|
|
1174
|
+
* existing binding by id, else `<id>_connection` / `<id>_folder` declared for you
|
|
1175
|
+
* with the symbolic name as the default, which `bindings.json` fills with the real
|
|
1176
|
+
* connection and folder ids.
|
|
1177
|
+
* `connectorKey` names a connection of another connector type when the endpoint
|
|
1178
|
+
* belongs to one (see {@link HttpOpts.connectorKey}).
|
|
1179
|
+
*/
|
|
1180
|
+
connection?: string;
|
|
1181
|
+
/** Symbolic binding name of the connection's folder — connector mode only. */
|
|
1182
|
+
folder?: string;
|
|
1183
|
+
/**
|
|
1184
|
+
* The connector the connection belongs to, connector mode only. Defaults to
|
|
1185
|
+
* `uipath-uipath-http`, the generic HTTP connector. Set it when the connection is a
|
|
1186
|
+
* specific connector's (a Slack connection calling a Slack endpoint the catalog does
|
|
1187
|
+
* not expose); the body's `targetConnector` follows it.
|
|
1188
|
+
*/
|
|
1189
|
+
connectorKey?: string;
|
|
1110
1190
|
/**
|
|
1111
1191
|
* EXTRA output rows: variable id → `=`-expression read against the node's own result,
|
|
1112
1192
|
* e.g. `{ runStatus: '=Status' }`.
|
|
@@ -1136,14 +1216,48 @@ export interface HttpOpts extends ActivityOpts {
|
|
|
1136
1216
|
export interface OrchestratorOpts extends ActivityOpts {
|
|
1137
1217
|
/** Display name the designer shows on the node. */
|
|
1138
1218
|
name?: string;
|
|
1139
|
-
/**
|
|
1219
|
+
/**
|
|
1220
|
+
* The Orchestrator process to start, by name.
|
|
1221
|
+
*
|
|
1222
|
+
* @remarks
|
|
1223
|
+
* **How the runtime finds the process depends on the `uipath:type` version the node
|
|
1224
|
+
* carries, and the SDK picks it from what you pass.** With `process` (+ `folder`) and no
|
|
1225
|
+
* `releaseKey`, the node is emitted at `version="v2"`: the engine's v2 branch
|
|
1226
|
+
* (`OrchestratorRpaActivities`, `ExecuteApiWorkflowArgs`, `HermesJobActivities`) reads
|
|
1227
|
+
* the `name` and `folderPath` context and resolves the release itself. With
|
|
1228
|
+
* `releaseKey`, the node is emitted at `version="v1"`, whose branch reads `releaseKey`
|
|
1229
|
+
* and `folderKey` and ignores the name.
|
|
1230
|
+
*
|
|
1231
|
+
* Measured on flow-v2-run-12: a `v1` node carrying only `name`/`folderPath` — what this
|
|
1232
|
+
* SDK used to emit for every job start — passed `check`, `compile` and `validate` and
|
|
1233
|
+
* faulted on the cloud with `170009 Could not get value for key:ReleaseKey from context
|
|
1234
|
+
* in input`; the local engine resolves by name whatever the version says, so it ran
|
|
1235
|
+
* there. See docs/BPMN_EVAL_RUN12_FINDINGS.md §4 P0-3.
|
|
1236
|
+
*/
|
|
1140
1237
|
process: string;
|
|
1141
1238
|
/** Folder path the process lives in. Omit for the personal/default folder. */
|
|
1142
1239
|
folder?: string;
|
|
1143
1240
|
/** Input arguments — serialized as the node's `JobArguments` body. */
|
|
1144
1241
|
input?: Record<string, unknown>;
|
|
1145
|
-
/**
|
|
1242
|
+
/**
|
|
1243
|
+
* Address the release by KEY instead of by name — the deployed resource's `Key` from
|
|
1244
|
+
* `uip or processes list --folder-path <path> --output json`, or `=bindings.<id>` for a
|
|
1245
|
+
* `process` binding whose `propertyAttribute` is `Key`. Switches the node to
|
|
1246
|
+
* `version="v1"` (see {@link OrchestratorOpts.process}); a literal is turned into such
|
|
1247
|
+
* a binding for you. Pair it with {@link OrchestratorOpts.folderKey} — the v1 branch
|
|
1248
|
+
* does not read `folder`. For imports and for a release the tenant cannot resolve by
|
|
1249
|
+
* name; ordinary authoring passes `process` and `folder` and leaves this off.
|
|
1250
|
+
*/
|
|
1146
1251
|
releaseKey?: string;
|
|
1252
|
+
/**
|
|
1253
|
+
* The folder's `FolderKey` GUID (the same `uip or processes list` row carries it), for
|
|
1254
|
+
* a node addressed by {@link OrchestratorOpts.releaseKey}. The v1 branch reads this and
|
|
1255
|
+
* not `folderPath`: `Orchestrator.ExecuteApiWorkflowAsync` with a key and no
|
|
1256
|
+
* `folderKey` faults with `Could not get value for key:FolderKey from context in
|
|
1257
|
+
* input`, which `check` reports ahead of time as JOB_FOLDER_KEY_MISSING. Ignored when
|
|
1258
|
+
* the node is addressed by name.
|
|
1259
|
+
*/
|
|
1260
|
+
folderKey?: string;
|
|
1147
1261
|
/**
|
|
1148
1262
|
* EXTRA output rows: variable id → `=`-expression read against the node's own result,
|
|
1149
1263
|
* e.g. `{ runStatus: '=Status' }`.
|
|
@@ -1330,12 +1444,37 @@ export interface ConnectorEventOpts extends ActivityOpts {
|
|
|
1330
1444
|
*/
|
|
1331
1445
|
object?: string;
|
|
1332
1446
|
/**
|
|
1333
|
-
* The
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1336
|
-
*
|
|
1447
|
+
* The subscription's SCOPE — the operation's own event parameters, by equality
|
|
1448
|
+
* (`{ parentFolderId: '<mail folder id>' }` for Outlook `email-received`).
|
|
1449
|
+
* `Library.eventParameterFields()` is the authority on which names an operation
|
|
1450
|
+
* accepts — and "declares none" is a real answer for some (HTTP Webhook scopes by
|
|
1451
|
+
* the connection), not a lookup failure.
|
|
1452
|
+
*
|
|
1453
|
+
* @remarks
|
|
1454
|
+
* Emitted into the node's `body` row as both `queryParams` and the leading
|
|
1455
|
+
* `(k == 'v')` clauses of `filters.expression` — the one place the platform reads a
|
|
1456
|
+
* subscription filter (`PO.BpmnEngine` `GetEventFilters`). A payload field that is
|
|
1457
|
+
* not an event parameter (`subject`) does not belong here; it goes in
|
|
1458
|
+
* {@link ConnectorEventOpts.filters}, and `check` reports it here as
|
|
1459
|
+
* `EVENT_UNKNOWN_PARAM`.
|
|
1337
1460
|
*/
|
|
1338
1461
|
filter?: Record<string, unknown>;
|
|
1462
|
+
/**
|
|
1463
|
+
* Conditions on the event PAYLOAD, AND-joined after the scope:
|
|
1464
|
+
* `[{ field: 'subject', contains: 'TestWaitFor' }]`. The same grammar and the same
|
|
1465
|
+
* lowering as the Flow builder's `waitForEvent`/`onEvent` — `contains(f,'v')`,
|
|
1466
|
+
* `f=='v'`, `starts_with(f,'v')`, a date compared through `to_number(...)` — written
|
|
1467
|
+
* into `body.filters.expression` behind the scope's clauses.
|
|
1468
|
+
*
|
|
1469
|
+
* @remarks
|
|
1470
|
+
* On flow-v2-run-12 this surface did not exist, so an author who needed
|
|
1471
|
+
* `contains(subject, 'TestWaitFor')` had nowhere to put it but `filter`, where it was
|
|
1472
|
+
* emitted as an untargeted input no handler reads; the wait validated and matched every
|
|
1473
|
+
* mail in the folder (outlook-waitfor-email 1.00 → 0.43). See {@link EventFilter} for
|
|
1474
|
+
* the operator set; `check` refuses a leaf with no operator or two, and warns on a
|
|
1475
|
+
* field the connector does not expose.
|
|
1476
|
+
*/
|
|
1477
|
+
filters?: EventFilter[];
|
|
1339
1478
|
/** Extra event parameters, for operations that declare them. */
|
|
1340
1479
|
parameters?: Record<string, unknown>;
|
|
1341
1480
|
/** Variable the event payload lands in. Defaults to `<id>_result`. */
|
|
@@ -2258,6 +2397,14 @@ declare abstract class ScopeBuilder {
|
|
|
2258
2397
|
* @returns This builder, so calls chain.
|
|
2259
2398
|
*/
|
|
2260
2399
|
http(id: string, opts: HttpOpts, body?: ActivityBodyFn): this;
|
|
2400
|
+
/**
|
|
2401
|
+
* @internal Connector-mode `.http()`: the request through an Integration Service
|
|
2402
|
+
* connection, as `Intsvc.ActivityExecution` on the generic HTTP connector's
|
|
2403
|
+
* `http-request` object — the shape the v1 arm wrote by hand on flow-v2-run-12
|
|
2404
|
+
* (non-catalog-http-fallback) and the live run completed. The connection and folder
|
|
2405
|
+
* resolve exactly as `.dataService()`'s do.
|
|
2406
|
+
*/
|
|
2407
|
+
private connectorHttp;
|
|
2261
2408
|
/**
|
|
2262
2409
|
* A UiPath **Data Fabric** (Data Service) record or file operation — create,
|
|
2263
2410
|
* update, get, query, delete a record, or download / upload / delete a record's
|
|
@@ -2358,12 +2505,17 @@ declare abstract class ScopeBuilder {
|
|
|
2358
2505
|
*/
|
|
2359
2506
|
startCaseProcess(id: string, opts: OrchestratorAsyncOpts, body?: ActivityBodyFn): this;
|
|
2360
2507
|
/**
|
|
2361
|
-
* Execute an **API workflow
|
|
2362
|
-
* (`Orchestrator.ExecuteApiWorkflowAsync`).
|
|
2508
|
+
* Execute an **API workflow** and wait for it (`Orchestrator.ExecuteApiWorkflowAsync`).
|
|
2363
2509
|
*
|
|
2364
2510
|
* @remarks
|
|
2365
|
-
* The
|
|
2366
|
-
*
|
|
2511
|
+
* The type's name says async and its designer label says `Start and wait for API
|
|
2512
|
+
* workflow`; the label is right. The registry offers only this one type for invoking
|
|
2513
|
+
* a published API workflow, it waits for completion, and the result is available to
|
|
2514
|
+
* later nodes. There is no fire-and-forget variant to model.
|
|
2515
|
+
*
|
|
2516
|
+
* Address it by `process` + `folder` (emitted at `uipath:type version="v2"`), or by
|
|
2517
|
+
* `releaseKey` + `folderKey` (v1) — see {@link OrchestratorOpts.process} for why the
|
|
2518
|
+
* version matters and what a v1 node without a key does on the platform.
|
|
2367
2519
|
*
|
|
2368
2520
|
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
2369
2521
|
* @param opts - Which workflow, folder, and input arguments.
|
package/dist/bpmn/bpmn-sdk.js
CHANGED
|
@@ -980,6 +980,12 @@ class ScopeBuilder {
|
|
|
980
980
|
*/
|
|
981
981
|
http(id, opts, body) {
|
|
982
982
|
const { name, url, method, headers, parameters, body: requestBody, outputs, outputVar, skipCondition, retry, loop, errorMapping } = opts;
|
|
983
|
+
if (opts.connection !== undefined)
|
|
984
|
+
return this.connectorHttp(id, opts, body);
|
|
985
|
+
if (opts.folder !== undefined || opts.connectorKey !== undefined) {
|
|
986
|
+
throw new Error(`http "${id}": \`folder\` and \`connectorKey\` belong to connector mode, which \`connection\` selects — ` +
|
|
987
|
+
`pass the connection's binding name too, or drop them for a connectionless request.`);
|
|
988
|
+
}
|
|
983
989
|
return this.pushActivity({
|
|
984
990
|
kind: 'typed',
|
|
985
991
|
id,
|
|
@@ -1006,6 +1012,89 @@ class ScopeBuilder {
|
|
|
1006
1012
|
errorMapping,
|
|
1007
1013
|
}, body);
|
|
1008
1014
|
}
|
|
1015
|
+
/**
|
|
1016
|
+
* @internal Connector-mode `.http()`: the request through an Integration Service
|
|
1017
|
+
* connection, as `Intsvc.ActivityExecution` on the generic HTTP connector's
|
|
1018
|
+
* `http-request` object — the shape the v1 arm wrote by hand on flow-v2-run-12
|
|
1019
|
+
* (non-catalog-http-fallback) and the live run completed. The connection and folder
|
|
1020
|
+
* resolve exactly as `.dataService()`'s do.
|
|
1021
|
+
*/
|
|
1022
|
+
connectorHttp(id, opts, body) {
|
|
1023
|
+
const connectorKey = opts.connectorKey ?? 'uipath-uipath-http';
|
|
1024
|
+
const connection = this.dataServiceBinding(id, 'connection', opts.connection, 'ConnectionId', `${connectorKey} connection`);
|
|
1025
|
+
const folder = opts.folder !== undefined
|
|
1026
|
+
? this.dataServiceBinding(id, 'folder', opts.folder, 'folderKey', `${connectorKey} folder`, connection.key)
|
|
1027
|
+
: undefined;
|
|
1028
|
+
// The request's own URL, with `parameters` folded into its query string — the
|
|
1029
|
+
// connector body has no separate parameters slot — and its path for the `path`
|
|
1030
|
+
// field, which the v1 artifact carries beside the URL.
|
|
1031
|
+
let url = opts.url;
|
|
1032
|
+
let path;
|
|
1033
|
+
if (!url.startsWith('=')) {
|
|
1034
|
+
let parsed;
|
|
1035
|
+
try {
|
|
1036
|
+
parsed = new URL(url);
|
|
1037
|
+
}
|
|
1038
|
+
catch {
|
|
1039
|
+
throw new Error(`http "${id}": connector mode needs an absolute URL (got ${JSON.stringify(url)}).`);
|
|
1040
|
+
}
|
|
1041
|
+
for (const [k, v] of Object.entries(opts.parameters ?? {}))
|
|
1042
|
+
parsed.searchParams.set(k, String(v));
|
|
1043
|
+
url = parsed.toString();
|
|
1044
|
+
path = parsed.pathname;
|
|
1045
|
+
}
|
|
1046
|
+
else if (opts.parameters !== undefined) {
|
|
1047
|
+
throw new Error(`http "${id}": connector mode appends \`parameters\` to the URL, so the URL cannot be an expression when they are given — ` +
|
|
1048
|
+
`write them into the expression instead.`);
|
|
1049
|
+
}
|
|
1050
|
+
const responseVar = opts.outputVar ?? `${id}_response`;
|
|
1051
|
+
return this.pushActivity({
|
|
1052
|
+
kind: 'typed',
|
|
1053
|
+
id,
|
|
1054
|
+
name: opts.name,
|
|
1055
|
+
type: 'Intsvc.ActivityExecution',
|
|
1056
|
+
context: {
|
|
1057
|
+
activity: 'Create',
|
|
1058
|
+
connectorKey,
|
|
1059
|
+
connection: connection.ref,
|
|
1060
|
+
...(folder ? { folderKey: folder.ref } : {}),
|
|
1061
|
+
operation: 'Create',
|
|
1062
|
+
objectName: 'http-request',
|
|
1063
|
+
method: 'POST',
|
|
1064
|
+
path: '/http-request',
|
|
1065
|
+
activityConfigurationVersion: 'v1',
|
|
1066
|
+
metadata: {},
|
|
1067
|
+
},
|
|
1068
|
+
inputs: {},
|
|
1069
|
+
inputRows: [
|
|
1070
|
+
{
|
|
1071
|
+
name: 'body',
|
|
1072
|
+
type: 'json',
|
|
1073
|
+
target: 'body',
|
|
1074
|
+
body: {
|
|
1075
|
+
authentication: 'connector',
|
|
1076
|
+
targetConnector: connectorKey,
|
|
1077
|
+
connection: connection.ref,
|
|
1078
|
+
method: opts.method ?? 'GET',
|
|
1079
|
+
url,
|
|
1080
|
+
...(path !== undefined ? { path } : {}),
|
|
1081
|
+
headers: opts.headers ?? {},
|
|
1082
|
+
body: opts.body ?? null,
|
|
1083
|
+
},
|
|
1084
|
+
},
|
|
1085
|
+
],
|
|
1086
|
+
outputRows: [
|
|
1087
|
+
{ name: 'response', type: 'jsonSchema', source: '=response', var: responseVar },
|
|
1088
|
+
{ name: 'Error', type: 'jsonSchema', source: '=Error', var: `${id}_Error`, schema: errorSchema },
|
|
1089
|
+
],
|
|
1090
|
+
outputs: opts.outputs,
|
|
1091
|
+
skipCondition: opts.skipCondition,
|
|
1092
|
+
tags: opts.tags,
|
|
1093
|
+
retry: opts.retry,
|
|
1094
|
+
errorMapping: opts.errorMapping,
|
|
1095
|
+
loop: opts.loop,
|
|
1096
|
+
}, body);
|
|
1097
|
+
}
|
|
1009
1098
|
/**
|
|
1010
1099
|
* A UiPath **Data Fabric** (Data Service) record or file operation — create,
|
|
1011
1100
|
* update, get, query, delete a record, or download / upload / delete a record's
|
|
@@ -1137,15 +1226,37 @@ class ScopeBuilder {
|
|
|
1137
1226
|
}
|
|
1138
1227
|
/** @internal Shared body of the Orchestrator process-invocation methods. */
|
|
1139
1228
|
orchestratorNode(id, type, opts, body) {
|
|
1229
|
+
// The `uipath:type` version selects the engine's addressing branch — see
|
|
1230
|
+
// OrchestratorOpts.process. By name → v2 (`name` + `folderPath`); by key → v1
|
|
1231
|
+
// (`releaseKey` + `folderKey`). A literal release key becomes a `process`/`Key`
|
|
1232
|
+
// binding, which is the shape the registry's `bindingInfo` for the field describes
|
|
1233
|
+
// and the one `validate` wants; an `=` expression is the author's own binding.
|
|
1234
|
+
const byKey = opts.releaseKey !== undefined;
|
|
1235
|
+
let releaseKey = opts.releaseKey;
|
|
1236
|
+
if (releaseKey !== undefined && !releaseKey.startsWith('=')) {
|
|
1237
|
+
const bindingId = `${id}_releaseKey`;
|
|
1238
|
+
this._bindingRegistry.declare({
|
|
1239
|
+
id: bindingId,
|
|
1240
|
+
name: opts.process,
|
|
1241
|
+
resource: 'process',
|
|
1242
|
+
propertyAttribute: 'Key',
|
|
1243
|
+
resourceSubType: REGISTRY_GAPS[type]?.resourceSubType,
|
|
1244
|
+
default: releaseKey,
|
|
1245
|
+
resourceKey: releaseKey,
|
|
1246
|
+
});
|
|
1247
|
+
releaseKey = `=bindings.${bindingId}`;
|
|
1248
|
+
}
|
|
1140
1249
|
return this.pushActivity({
|
|
1141
1250
|
kind: 'typed',
|
|
1142
1251
|
id,
|
|
1143
1252
|
name: opts.name,
|
|
1144
1253
|
type,
|
|
1254
|
+
typeVersion: byKey ? 'v1' : 'v2',
|
|
1145
1255
|
context: this.bindRequiredContext(id, type, {
|
|
1146
1256
|
name: opts.process,
|
|
1147
1257
|
...(opts.folder !== undefined ? { folderPath: opts.folder } : {}),
|
|
1148
|
-
...(
|
|
1258
|
+
...(releaseKey !== undefined ? { releaseKey } : {}),
|
|
1259
|
+
...(byKey && opts.folderKey !== undefined ? { folderKey: opts.folderKey } : {}),
|
|
1149
1260
|
}),
|
|
1150
1261
|
inputs: opts.input ?? {},
|
|
1151
1262
|
outputs: opts.outputs,
|
|
@@ -1215,12 +1326,17 @@ class ScopeBuilder {
|
|
|
1215
1326
|
return this.orchestratorNode(id, opts.async ? 'Orchestrator.StartCaseMgmtProcessAsync' : 'Orchestrator.StartCaseMgmtProcess', opts, body);
|
|
1216
1327
|
}
|
|
1217
1328
|
/**
|
|
1218
|
-
* Execute an **API workflow
|
|
1219
|
-
* (`Orchestrator.ExecuteApiWorkflowAsync`).
|
|
1329
|
+
* Execute an **API workflow** and wait for it (`Orchestrator.ExecuteApiWorkflowAsync`).
|
|
1220
1330
|
*
|
|
1221
1331
|
* @remarks
|
|
1222
|
-
* The
|
|
1223
|
-
*
|
|
1332
|
+
* The type's name says async and its designer label says `Start and wait for API
|
|
1333
|
+
* workflow`; the label is right. The registry offers only this one type for invoking
|
|
1334
|
+
* a published API workflow, it waits for completion, and the result is available to
|
|
1335
|
+
* later nodes. There is no fire-and-forget variant to model.
|
|
1336
|
+
*
|
|
1337
|
+
* Address it by `process` + `folder` (emitted at `uipath:type version="v2"`), or by
|
|
1338
|
+
* `releaseKey` + `folderKey` (v1) — see {@link OrchestratorOpts.process} for why the
|
|
1339
|
+
* version matters and what a v1 node without a key does on the platform.
|
|
1224
1340
|
*
|
|
1225
1341
|
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
1226
1342
|
* @param opts - Which workflow, folder, and input arguments.
|
|
@@ -1518,6 +1634,7 @@ class ScopeBuilder {
|
|
|
1518
1634
|
folder: opts.folder,
|
|
1519
1635
|
folderPath: opts.folderPath,
|
|
1520
1636
|
filter: opts.filter,
|
|
1637
|
+
filters: opts.filters,
|
|
1521
1638
|
parameters: opts.parameters,
|
|
1522
1639
|
outputVar: opts.outputVar,
|
|
1523
1640
|
outputs: opts.outputs,
|
|
@@ -1564,6 +1681,7 @@ class ScopeBuilder {
|
|
|
1564
1681
|
folder: opts.folder,
|
|
1565
1682
|
folderPath: opts.folderPath,
|
|
1566
1683
|
filter: opts.filter,
|
|
1684
|
+
filters: opts.filters,
|
|
1567
1685
|
parameters: opts.parameters,
|
|
1568
1686
|
outputVar: opts.outputVar,
|
|
1569
1687
|
outputs: opts.outputs,
|
package/dist/bpmn/check-cli.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* leaving it, implied edges marked — see graph.ts.
|
|
12
12
|
*/
|
|
13
13
|
import { existsSync } from 'node:fs';
|
|
14
|
-
import { reportDiagnostics, reportResult } from '../cli-result.js';
|
|
14
|
+
import { printResult, reportDiagnostics, reportResult } from '../cli-result.js';
|
|
15
15
|
import { resolveBpmnFile, loadBuiltBpmn } from './load.js';
|
|
16
16
|
import { check } from './check.js';
|
|
17
17
|
import { graphModel, renderGraph } from './graph.js';
|
|
@@ -49,8 +49,9 @@ export async function run(argv) {
|
|
|
49
49
|
reportDiagnostics(diags);
|
|
50
50
|
if (graph) {
|
|
51
51
|
// The graph goes to stdout and the diagnostics to stderr, so a reviewer can
|
|
52
|
-
// diff the printed wiring on its own.
|
|
53
|
-
|
|
52
|
+
// diff the printed wiring on its own. Under `--json` the graph is the
|
|
53
|
+
// object's `graph` field instead, not printed a second time (#901).
|
|
54
|
+
printResult(renderGraph(built).trimEnd());
|
|
54
55
|
reportResult({ graph: graphModel(built) });
|
|
55
56
|
}
|
|
56
57
|
for (const d of diags)
|
package/dist/bpmn/check.js
CHANGED
|
@@ -21,6 +21,20 @@ import { KNOWN_METHOD_SET } from './known-methods.js';
|
|
|
21
21
|
import { EQUALS_EXPR_DIALECT, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, checkBindingLabels, } from '../core/connector-checks.js';
|
|
22
22
|
import { checkEventResolution, checkEventSubscription, eventParamsFor, } from '../core/event-checks.js';
|
|
23
23
|
import { bindingRequiredFields, missingRequiredContext, missingRequiredInputs, registryType, REGISTRY_GAPS, unsatisfiableRequiredInputs, } from './typed-node.js';
|
|
24
|
+
/**
|
|
25
|
+
* The job-start family — the types whose engine handler switches addressing on the
|
|
26
|
+
* `uipath:type` version: v2 reads `name`/`folderPath`, v1 reads `releaseKey`/`folderKey`.
|
|
27
|
+
*/
|
|
28
|
+
const JOB_START_TYPES = new Set([
|
|
29
|
+
'Orchestrator.StartJob',
|
|
30
|
+
'Orchestrator.StartAgentJob',
|
|
31
|
+
'Orchestrator.ExecuteApiWorkflowAsync',
|
|
32
|
+
'Orchestrator.StartAgenticProcess',
|
|
33
|
+
'Orchestrator.StartAgenticProcessAsync',
|
|
34
|
+
'Orchestrator.StartCaseMgmtProcess',
|
|
35
|
+
'Orchestrator.StartCaseMgmtProcessAsync',
|
|
36
|
+
'Orchestrator.BusinessRules',
|
|
37
|
+
]);
|
|
24
38
|
/**
|
|
25
39
|
* Service types the platform expects to name a concrete Orchestrator resource.
|
|
26
40
|
*
|
|
@@ -109,12 +123,13 @@ function checkConnectors(built, opts, diags) {
|
|
|
109
123
|
* object, version, connection }` — so the adapter is naming: BPMN calls the
|
|
110
124
|
* connector `key`, the event `eventName`, and the subscription scope `filter`.
|
|
111
125
|
*
|
|
112
|
-
* `filters` is
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* all, whether a generic event named its object, and whether
|
|
116
|
-
* parameters the operation actually declares.
|
|
117
|
-
* in `flow-v2-run-8` failed on that last one
|
|
126
|
+
* `filters` is passed through as of flow-v2-run-12: a BPMN connector event carries
|
|
127
|
+
* payload conditions in `body.filters.expression` exactly as a Flow subscription does,
|
|
128
|
+
* so the `EVENT_FILTER_*` family fires here too. The subscription rules are the rest —
|
|
129
|
+
* whether it resolves at all, whether a generic event named its object, and whether
|
|
130
|
+
* its scope names parameters the operation actually declares.
|
|
131
|
+
* `skill-bpmn-outlook-waitfor-email` in `flow-v2-run-8` failed on that last one, and
|
|
132
|
+
* in run 12 on having no `filters` surface at all.
|
|
118
133
|
*/
|
|
119
134
|
function checkConnectorEvents(built, opts, diags) {
|
|
120
135
|
for (const n of allNodes(built.nodes)) {
|
|
@@ -127,6 +142,7 @@ function checkConnectorEvents(built, opts, diags) {
|
|
|
127
142
|
...(n.version !== undefined ? { version: n.version } : {}),
|
|
128
143
|
...(n.object !== undefined ? { object: n.object } : {}),
|
|
129
144
|
...(n.filter !== undefined ? { where: n.filter } : {}),
|
|
145
|
+
...(n.filters !== undefined ? { filters: n.filters } : {}),
|
|
130
146
|
...(n.connection !== undefined ? { connection: n.connection } : {}),
|
|
131
147
|
};
|
|
132
148
|
const at = (level) => (code, message) => {
|
|
@@ -563,6 +579,21 @@ function isRuntimeDuration(v) {
|
|
|
563
579
|
// "validates, then no runtime can parse it" trap the timer eval card exists for.
|
|
564
580
|
return RUNTIME_DURATION.test(v) && /\d/.test(v);
|
|
565
581
|
}
|
|
582
|
+
/** The `args` keys the platform itself writes and injects — not an author's inputs. */
|
|
583
|
+
const SCRIPT_ENVELOPE_KEYS = new Set(['vars', 'metadata', 'iterator']);
|
|
584
|
+
/**
|
|
585
|
+
* Whether a script body mentions `name` as a bare identifier — not after `.` (a property
|
|
586
|
+
* read such as `vars.amount`), not inside a string or comment. The body is otherwise not
|
|
587
|
+
* parsed: this is the one question about it the platform contract makes answerable.
|
|
588
|
+
*/
|
|
589
|
+
function readsBareIdentifier(script, name) {
|
|
590
|
+
const stripped = script
|
|
591
|
+
.replace(/\/\*[\s\S]*?\*\//g, ' ')
|
|
592
|
+
.replace(/\/\/[^\n]*/g, ' ')
|
|
593
|
+
.replace(/"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`/g, '""');
|
|
594
|
+
const re = new RegExp(`(?<![\\w$.])${name.replace(/\$/g, '\\$')}(?![\\w$])(?!\\s*:)`);
|
|
595
|
+
return re.test(stripped);
|
|
596
|
+
}
|
|
566
597
|
/** Retry and loop options, checked per activity. */
|
|
567
598
|
function checkActivityFields(n, diags) {
|
|
568
599
|
// A script task whose body is missing or blank. The wire form of a script task IS its
|
|
@@ -584,6 +615,29 @@ function checkActivityFields(n, diags) {
|
|
|
584
615
|
`Pass the Jint JavaScript as \`script\` (\`.scriptTask('${n.id}', { script: 'return { … };' })\`).`,
|
|
585
616
|
where: n.id,
|
|
586
617
|
});
|
|
618
|
+
// A script that reads an `inputs` key as a bare identifier. The platform injects only
|
|
619
|
+
// the `args` envelope — `vars`, `metadata`, `iterator` — into the script's scope, so
|
|
620
|
+
// `amount` with `inputs: { amount: '=vars.amount' }` is a ReferenceError at runtime
|
|
621
|
+
// (`amount is not defined`, incident 300501) that `validate` cannot see and the local
|
|
622
|
+
// engine used to hide. Measured on flow-v2-run-12: 3 of 3 cloud-executed script tasks
|
|
623
|
+
// written this way faulted; 0 that read `vars.<id>` did.
|
|
624
|
+
//
|
|
625
|
+
// A warning, not an error, because a brownfield `.bpmn` whose untouched script task
|
|
626
|
+
// carries the shape must still merge — refusing it would be the SDK refusing what
|
|
627
|
+
// `validate` accepts, on a node the edit did not target.
|
|
628
|
+
if (n.kind === 'scriptTask' && n.script) {
|
|
629
|
+
const bare = Object.keys(n.inputs).filter((k) => !SCRIPT_ENVELOPE_KEYS.has(k) && /^[A-Za-z_$][\w$]*$/.test(k) && readsBareIdentifier(n.script, k));
|
|
630
|
+
if (bare.length > 0)
|
|
631
|
+
diags.push({
|
|
632
|
+
level: 'warning',
|
|
633
|
+
code: 'SCRIPT_BARE_INPUT_REF',
|
|
634
|
+
message: `Script task "${n.id}" reads ${bare.map((k) => `\`${k}\``).join(', ')} as a bare identifier, but the platform ` +
|
|
635
|
+
`injects only \`vars\`, \`metadata\` and \`iterator\` into a script's scope — on the cloud this faults with ` +
|
|
636
|
+
`\`${bare[0]} is not defined\` after check, compile and validate have all passed. ` +
|
|
637
|
+
`Read the variable as \`vars.<id>\` (${bare.map((k) => `\`${n.inputs[k].replace(/^=/, '')}\``).join(', ')}) and drop the \`inputs\` entry.`,
|
|
638
|
+
where: n.id,
|
|
639
|
+
});
|
|
640
|
+
}
|
|
587
641
|
if (!('retry' in n) && !('loop' in n))
|
|
588
642
|
return;
|
|
589
643
|
const retry = 'retry' in n ? n.retry : undefined;
|
|
@@ -931,6 +985,25 @@ inEventSubProcess = false) {
|
|
|
931
985
|
const contextView = { ...n.context };
|
|
932
986
|
for (const row of n.contextRows ?? [])
|
|
933
987
|
contextView[row.name] = row.value ?? row.body ?? '';
|
|
988
|
+
// A job start addressed by key (`uipath:type version="v1"`) with no `folderKey`. The
|
|
989
|
+
// engine's v1 branch reads `releaseKey` and `folderKey`, not `folderPath`:
|
|
990
|
+
// `Orchestrator.ExecuteApiWorkflowAsync` so written faults with `Could not get value
|
|
991
|
+
// for key:FolderKey from context in input` (v1 skill, verified live). A node by NAME
|
|
992
|
+
// is emitted at v2 and never reaches that branch — see OrchestratorOpts.process.
|
|
993
|
+
if (JOB_START_TYPES.has(n.type) &&
|
|
994
|
+
(n.typeVersion ?? 'v1') === 'v1' &&
|
|
995
|
+
contextView['releaseKey'] !== undefined &&
|
|
996
|
+
contextView['folderKey'] === undefined)
|
|
997
|
+
diags.push({
|
|
998
|
+
level: 'warning',
|
|
999
|
+
code: 'JOB_FOLDER_KEY_MISSING',
|
|
1000
|
+
message: `"${n.id}" (${n.type}) is addressed by releaseKey (uipath:type version="v1") but carries no folderKey; ` +
|
|
1001
|
+
`the runtime's v1 branch reads folderKey, not folderPath, and faults with ` +
|
|
1002
|
+
`\`Could not get value for key:FolderKey from context in input\`. Pass \`folderKey\` (the folder's FolderKey ` +
|
|
1003
|
+
`GUID from \`uip or processes list --folder-path <path> --output json\`), or drop \`releaseKey\` and address the ` +
|
|
1004
|
+
`process by name, which the SDK emits at version="v2".`,
|
|
1005
|
+
where: n.id,
|
|
1006
|
+
});
|
|
934
1007
|
for (const field of bindingRequiredFields(n.type, n.spec)) {
|
|
935
1008
|
const value = contextView[field.name];
|
|
936
1009
|
if (typeof value === 'string' && value.startsWith('=bindings.'))
|
package/dist/bpmn/connector.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { connectorOutputVars } from './bpmn-sdk.js';
|
|
2
2
|
import { transportHttpMethod } from '../config.js';
|
|
3
3
|
import { EQUALS_EXPR_DIALECT } from '../core/connector-checks.js';
|
|
4
|
-
import { buildConnectorInputs } from '../core/connector-inputs.js';
|
|
4
|
+
import { buildConnectorInputs, nestConnectorBody } from '../core/connector-inputs.js';
|
|
5
5
|
export function createConnectorTask(ctx, n) {
|
|
6
6
|
const { m } = ctx;
|
|
7
7
|
if (!ctx.library)
|
|
@@ -83,7 +83,10 @@ export function createConnectorTask(ctx, n) {
|
|
|
83
83
|
if (part.value !== undefined)
|
|
84
84
|
paramRows.push(paramInput(m, part.name, 'multipart', part.value));
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
// Nested, not the flat dotted map Flow emits: the BPMN runtime sends `body` as written
|
|
87
|
+
// (see `nestConnectorBody`) — a flat `fields.project.key` reached Jira as a literal
|
|
88
|
+
// property and drew a 400 on flow-v2-run-12.
|
|
89
|
+
const body = nestConnectorBody(slots.bodyParameters ?? {});
|
|
87
90
|
// ── outputs — response schema + standard Error ──
|
|
88
91
|
const responseSchema = rc.entry.outputSchema
|
|
89
92
|
? schemaFromFields(rc.entry.outputSchema.fields ?? [])
|
|
@@ -70,9 +70,17 @@ export type DataServiceOperation = {
|
|
|
70
70
|
start?: number;
|
|
71
71
|
/** Page size. Defaults to `100`. */
|
|
72
72
|
limit?: number;
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Field to sort by. Emitted as the body's `_sortFieldName` — the name the curated
|
|
75
|
+
* operation's `RequestFields` declare and the only place the connector reads it; a
|
|
76
|
+
* `sortBy` query parameter is ignored and the records come back in default order.
|
|
77
|
+
*/
|
|
74
78
|
sortBy?: string;
|
|
75
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Sort direction, when `sortBy` is set. Emitted as the `isAscending` query parameter.
|
|
81
|
+
* Set it explicitly: omitted, the query sorts ascending whatever the connector's
|
|
82
|
+
* default says.
|
|
83
|
+
*/
|
|
76
84
|
ascending?: boolean;
|
|
77
85
|
/** How many levels of related records to expand into each result. */
|
|
78
86
|
expansionLevel?: number;
|