@uipath/maestro-builder-sdk 6.48.0 → 6.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * Diagram interchange (`bpmndi`) is intentionally **not** emitted here: BPMN
19
19
  * validation is layout-independent, so the SDK emits semantic-only XML and a
20
- * separate "tidy" step lays it out. See serialize.ts.
20
+ * `uip maestro bpmn format` lays it out. See serialize.ts.
21
21
  */
22
22
  import type { TypeDesc } from '../core/expr.js';
23
23
  import { type ConnectorOpts, type EventFilter } from '../core/actions.js';
@@ -1157,16 +1157,19 @@ export interface DataServiceOpts extends ActivityOpts {
1157
1157
  export interface HttpOpts extends ActivityOpts {
1158
1158
  /** Display name the designer shows on the task. */
1159
1159
  name?: string;
1160
- /** Request URL. Accepts an `=`-expression, including `=bindings.<id>`. */
1160
+ /**
1161
+ * Request URL. Accepts an `=`-expression, including `=bindings.<id>`. In connector mode
1162
+ * (see {@link HttpOpts.connection}) it is the endpoint on the target connector, relative
1163
+ * to the connection's base URL, e.g. `/emoji.list`.
1164
+ */
1161
1165
  url: string;
1162
1166
  /** HTTP method. Defaults to `'GET'`, matching the registry's own default. */
1163
1167
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
1164
1168
  /** Request headers — serialized to the node's json context field. */
1165
1169
  headers?: Record<string, unknown>;
1166
1170
  /**
1167
- * Query parameters — serialized to the node's json context field. In connector mode
1168
- * (see {@link HttpOpts.connection}) they are appended to the URL, so the URL must be
1169
- * a literal there.
1171
+ * Query parameters — serialized to the node's json context field, or to the request's
1172
+ * `query` in connector mode (see {@link HttpOpts.connection}).
1170
1173
  */
1171
1174
  parameters?: Record<string, unknown>;
1172
1175
  /**
@@ -1186,16 +1189,15 @@ export interface HttpOpts extends ActivityOpts {
1186
1189
  * @remarks
1187
1190
  * Without it the node is `Intsvc.UnifiedHttpRequest` in `mode="manual"`: the
1188
1191
  * process owns the URL, headers and auth, and nothing on the tenant is involved.
1189
- * With it the node is the connector activity the v1 skill calls "connector HTTP" —
1190
- * `Intsvc.ActivityExecution` on the generic HTTP connector (`uipath-uipath-http`,
1191
- * object `http-request`), whose `body` carries the request
1192
- * (`{"authentication":"connector","targetConnector":…,"connection":"=bindings.…","method":"GET","url":…,"path":…,"headers":…,"body":…}`)
1193
- * and whose auth is the connection's. That is the shape for "call an endpoint the
1192
+ * With it the node is the V2 `Intsvc.UnifiedHttpRequest` in connector mode, as
1193
+ * `uip maestro bpmn registry get Intsvc.UnifiedHttpRequest --connection-id` builds it:
1194
+ * context `connectorKey` `uipath-uipath-http`, the connection bound, and a `body` row
1195
+ * carrying the request
1196
+ * (`{"authentication":"connector","method":"GET","targetConnector":…,"connection":…,"path":…,"url":…,"headers":…,"query":…,"body":…}`),
1197
+ * whose auth is the connection's. A value that reads a variable is written `=js:`, as the
1198
+ * CLI writes it (`=vars.x` becomes `=js:vars.x`). That is the shape for "call an endpoint the
1194
1199
  * connector catalog has no activity for, through an existing connection" — the
1195
- * non-catalog HTTP fallback — and it was not expressible before: in flow-v2-run-12
1196
- * both fallback cards (non-catalog-http-fallback, slack-http-fallback) authored a
1197
- * connectionless node because this option did not exist, and the grader found
1198
- * `connectorKey values seen: []`.
1200
+ * non-catalog HTTP fallback.
1199
1201
  *
1200
1202
  * Pair it with {@link HttpOpts.folder}; both resolve as `.dataService()`'s do — an
1201
1203
  * existing binding by id, else `<id>_connection` / `<id>_folder` declared for you
@@ -1205,13 +1207,13 @@ export interface HttpOpts extends ActivityOpts {
1205
1207
  * belongs to one (see {@link HttpOpts.connectorKey}).
1206
1208
  */
1207
1209
  connection?: string;
1208
- /** Symbolic binding name of the connection's folder — connector mode only. */
1210
+ /** Symbolic binding name of the connection's folder — connector mode only, where the CLI requires it. */
1209
1211
  folder?: string;
1210
1212
  /**
1211
1213
  * The connector the connection belongs to, connector mode only. Defaults to
1212
1214
  * `uipath-uipath-http`, the generic HTTP connector. Set it when the connection is a
1213
1215
  * specific connector's (a Slack connection calling a Slack endpoint the catalog does
1214
- * not expose); the body's `targetConnector` follows it.
1216
+ * not expose); it becomes the request's `targetConnector`.
1215
1217
  */
1216
1218
  connectorKey?: string;
1217
1219
  /**
@@ -1226,7 +1228,11 @@ export interface HttpOpts extends ActivityOpts {
1226
1228
  * stays what the platform expects.
1227
1229
  */
1228
1230
  outputs?: Record<string, string>;
1229
- /** Variable the response lands in. Defaults to `<id>_response`. */
1231
+ /**
1232
+ * Variable the response lands in. Defaults to `<id>_response`. In connector mode it is
1233
+ * the response body; the status code and headers land in `<id>_code` and `<id>_headers`,
1234
+ * so it cannot be either.
1235
+ */
1230
1236
  outputVar?: string;
1231
1237
  /** `=`-expression that skips the request when truthy. */
1232
1238
  skipCondition?: string;
@@ -2439,10 +2445,9 @@ declare abstract class ScopeBuilder {
2439
2445
  http(id: string, opts: HttpOpts, body?: ActivityBodyFn): this;
2440
2446
  /**
2441
2447
  * @internal Connector-mode `.http()`: the request through an Integration Service
2442
- * connection, as `Intsvc.ActivityExecution` on the generic HTTP connector's
2443
- * `http-request` object — the shape the v1 arm wrote by hand on flow-v2-run-12
2444
- * (non-catalog-http-fallback) and the live run completed. The connection and folder
2445
- * resolve exactly as `.dataService()`'s do.
2448
+ * connection, as the V2 `Intsvc.UnifiedHttpRequest` element `uip maestro bpmn registry
2449
+ * get Intsvc.UnifiedHttpRequest --connection-id` builds (see `managed-http.ts`). The
2450
+ * connection and folder resolve exactly as `.dataService()`'s do.
2446
2451
  */
2447
2452
  private connectorHttp;
2448
2453
  /**
@@ -5,6 +5,7 @@ import { schemaVersionRefusal } from '../schema-version.js';
5
5
  import { bindingRequiredFields, REGISTRY_GAPS, registryType } from './typed-node.js';
6
6
  import { resolveResourceKeyPattern } from './resource-key-pattern.js';
7
7
  import { DATA_SERVICE_ACTIVITY_TYPE, DATA_SERVICE_CONNECTOR_KEY, dataServiceWire } from './data-service.js';
8
+ import { MANAGED_HTTP_CONNECTION_NAME, MANAGED_HTTP_CONNECTOR_KEY, MANAGED_HTTP_FOLDER_NAME, MANAGED_HTTP_TYPE, managedHttpContext, managedHttpInputs, managedHttpOutputs, } from './managed-http.js';
8
9
  import { ownEntry } from '../core/own-entry.js';
9
10
  export { BpmnBuildError } from './bpmn-expr-check.js';
10
11
  // @internal helpers kept on the published /bpmn subpath; SDK code imports declared-vars.js.
@@ -1032,79 +1033,46 @@ class ScopeBuilder {
1032
1033
  }
1033
1034
  /**
1034
1035
  * @internal Connector-mode `.http()`: the request through an Integration Service
1035
- * connection, as `Intsvc.ActivityExecution` on the generic HTTP connector's
1036
- * `http-request` object — the shape the v1 arm wrote by hand on flow-v2-run-12
1037
- * (non-catalog-http-fallback) and the live run completed. The connection and folder
1038
- * resolve exactly as `.dataService()`'s do.
1036
+ * connection, as the V2 `Intsvc.UnifiedHttpRequest` element `uip maestro bpmn registry
1037
+ * get Intsvc.UnifiedHttpRequest --connection-id` builds (see `managed-http.ts`). The
1038
+ * connection and folder resolve exactly as `.dataService()`'s do.
1039
1039
  */
1040
1040
  connectorHttp(id, opts, body) {
1041
- const connectorKey = opts.connectorKey ?? 'uipath-uipath-http';
1042
- const connection = this.dataServiceBinding(id, 'connection', opts.connection, 'ConnectionId', `${connectorKey} connection`);
1041
+ const codeVar = `${id}_code`;
1042
+ const headersVar = `${id}_headers`;
1043
+ if (opts.outputVar === codeVar || opts.outputVar === headersVar) {
1044
+ throw new Error(`http "${id}": outputVar "${opts.outputVar}" is the variable connector mode writes the status code or headers to. ` +
1045
+ `Pick another name, or drop outputVar for the default "${id}_response".`);
1046
+ }
1047
+ const connection = this.dataServiceBinding(id, 'connection', opts.connection, 'ConnectionId', MANAGED_HTTP_CONNECTION_NAME);
1043
1048
  const folder = opts.folder !== undefined
1044
- ? this.dataServiceBinding(id, 'folder', opts.folder, 'folderKey', `${connectorKey} folder`, connection.key)
1049
+ ? this.dataServiceBinding(id, 'folder', opts.folder, 'folderKey', MANAGED_HTTP_FOLDER_NAME, connection.key)
1045
1050
  : undefined;
1046
- // The request's own URL, with `parameters` folded into its query string — the
1047
- // connector body has no separate parameters slot — and its path for the `path`
1048
- // field, which the v1 artifact carries beside the URL.
1049
- let url = opts.url;
1050
- let path;
1051
- if (!url.startsWith('=')) {
1052
- let parsed;
1053
- try {
1054
- parsed = new URL(url);
1055
- }
1056
- catch {
1057
- throw new Error(`http "${id}": connector mode needs an absolute URL (got ${JSON.stringify(url)}).`);
1058
- }
1059
- for (const [k, v] of Object.entries(opts.parameters ?? {}))
1060
- parsed.searchParams.set(k, String(v));
1061
- url = parsed.toString();
1062
- path = parsed.pathname;
1063
- }
1064
- else if (opts.parameters !== undefined) {
1065
- throw new Error(`http "${id}": connector mode appends \`parameters\` to the URL, so the URL cannot be an expression when they are given — ` +
1066
- `write them into the expression instead.`);
1067
- }
1068
- const responseVar = opts.outputVar ?? `${id}_response`;
1051
+ const request = {
1052
+ connection,
1053
+ folder,
1054
+ targetConnector: opts.connectorKey ?? MANAGED_HTTP_CONNECTOR_KEY,
1055
+ method: opts.method ?? 'GET',
1056
+ url: opts.url,
1057
+ headers: opts.headers,
1058
+ query: opts.parameters,
1059
+ body: opts.body,
1060
+ };
1069
1061
  return this.pushActivity({
1070
1062
  kind: 'typed',
1071
1063
  id,
1072
1064
  name: opts.name,
1073
- type: 'Intsvc.ActivityExecution',
1074
- context: {
1075
- activity: 'Create',
1076
- connectorKey,
1077
- connection: connection.ref,
1078
- ...(folder ? { folderKey: folder.ref } : {}),
1079
- operation: 'Create',
1080
- objectName: 'http-request',
1081
- method: 'POST',
1082
- path: '/http-request',
1083
- activityConfigurationVersion: 'v1',
1084
- metadata: {},
1085
- },
1065
+ type: MANAGED_HTTP_TYPE,
1066
+ context: {},
1067
+ contextRows: managedHttpContext(request),
1086
1068
  inputs: {},
1087
- inputRows: [
1088
- {
1089
- name: 'body',
1090
- type: 'json',
1091
- target: 'body',
1092
- body: {
1093
- authentication: 'connector',
1094
- targetConnector: connectorKey,
1095
- connection: connection.ref,
1096
- method: opts.method ?? 'GET',
1097
- url,
1098
- ...(path !== undefined ? { path } : {}),
1099
- headers: opts.headers ?? {},
1100
- body: opts.body ?? null,
1101
- },
1102
- },
1103
- ],
1104
- outputRows: [
1105
- { name: 'response', type: 'jsonSchema', source: '=response', var: responseVar },
1106
- { name: 'Error', type: 'jsonSchema', source: '=Error', var: `${id}_Error`, schema: errorSchema },
1107
- ],
1069
+ inputRows: managedHttpInputs(request),
1070
+ outputRows: managedHttpOutputs({
1071
+ code: codeVar,
1072
+ headers: headersVar,
1073
+ body: opts.outputVar ?? `${id}_response`,
1074
+ error: `${id}_Error`,
1075
+ }),
1108
1076
  outputs: opts.outputs,
1109
1077
  skipCondition: opts.skipCondition,
1110
1078
  tags: opts.tags,
@@ -5,6 +5,7 @@ import { EQUALS_EXPR_DIALECT, checkConnectorContract, checkConnectorLookups, che
5
5
  import { checkEventResolution, checkEventSubscription, eventParamsFor, } from '../core/event-checks.js';
6
6
  import { bindingRequiredFields, CASE_RUNTIME_INTERNAL_TYPES, missingRequiredContext, missingRequiredInputs, REGISTRY_GAPS, registryType, } from './typed-node.js';
7
7
  import { ownEntry } from '../core/own-entry.js';
8
+ import { isManagedHttpV2, managedHttpAbsoluteUrl, managedHttpMissing } from './managed-http.js';
8
9
  /**
9
10
  * The job-start family — the types whose engine handler switches addressing on the
10
11
  * `uipath:type` version: v2 reads `name`/`folderPath`, v1 reads `releaseKey`/`folderKey`.
@@ -1391,7 +1392,12 @@ inEventSubProcess = false) {
1391
1392
  // emits, so whether this fired depended on a detail of the source document that
1392
1393
  // has nothing to do with whether the field is set.
1393
1394
  const contextNames = contextView;
1394
- for (const field of missingRequiredContext(n.type, contextNames, n.spec)) {
1395
+ const managedHttp = isManagedHttpV2(n.type, contextNames);
1396
+ const httpRequest = n.inputRows?.find((row) => row.name === 'body')?.body ?? n.inputs?.body;
1397
+ const requiredContext = managedHttp
1398
+ ? managedHttpMissing(contextNames, httpRequest)
1399
+ : missingRequiredContext(n.type, contextNames, n.spec);
1400
+ for (const field of requiredContext) {
1395
1401
  diags.push({
1396
1402
  level: 'error',
1397
1403
  code: 'EMPTY_REQUIRED_FIELD',
@@ -1399,6 +1405,17 @@ inEventSubProcess = false) {
1399
1405
  where: n.id,
1400
1406
  });
1401
1407
  }
1408
+ const absoluteUrl = managedHttp ? managedHttpAbsoluteUrl(httpRequest) : undefined;
1409
+ if (absoluteUrl !== undefined) {
1410
+ diags.push({
1411
+ level: 'warning',
1412
+ code: 'MANAGED_HTTP_ABSOLUTE_URL',
1413
+ message: `"${n.id}" (${n.type}) sends the absolute URL "${absoluteUrl.url}" through a ${absoluteUrl.targetConnector} connection. ` +
1414
+ `Integration Service refuses any host but that connector's with 400 "Invalid request URL". ` +
1415
+ `Write url relative to the connection's base URL, e.g. "/emoji.list" for Slack's https://slack.com/api/emoji.list.`,
1416
+ where: n.id,
1417
+ });
1418
+ }
1402
1419
  // The same rule over the PAYLOAD fields — the platform's RequiredFieldsRule
1403
1420
  // draws on both, so an unset required input is the same EMPTY_REQUIRED_FIELD.
1404
1421
  // The payload reaches a node the same two ways — `inputs`, or the verbatim
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * Runs the fast static check first; if it passes, serializes to Maestro `.bpmn`
15
15
  * XML (semantic-only — no diagram). The authoritative deploy gate is
16
- * `uip maestro bpmn validate`; a separate "tidy" step lays the diagram out.
16
+ * `uip maestro bpmn validate`; `uip maestro bpmn format` lays the diagram out.
17
17
  */
18
18
  import { reportDiagnostics, reportResult, thrownDiagnostic } from '../cli-result.js';
19
19
  import { writeFileSync } from 'node:fs';
@@ -22,8 +22,8 @@
22
22
  * repo-relative for in-tree callers, mirroring the Flow and Case arms.
23
23
  *
24
24
  * Diagram layout is not read or emitted — the SDK emits semantic-only XML and
25
- * `tidy` regenerates `bpmndi`. Run `tidy` on the recompiled artifact when a canvas
26
- * needs one.
25
+ * `uip maestro bpmn format` regenerates `bpmndi`. Run it on the recompiled artifact
26
+ * when a canvas needs one.
27
27
  *
28
28
  * `--style nested` lifts the regions the builder's nesting constructs lower to —
29
29
  * see `BpmnDecompileOptions.style`. It is written only after both sources have been
@@ -16,9 +16,9 @@
16
16
  *
17
17
  * What does NOT survive, and why:
18
18
  *
19
- * - **`bpmndi` diagram layout.** The SDK emits none and `tidy` regenerates it, so
20
- * there is nothing to preserve. A decompiled file recompiles to semantic-only
21
- * XML; re-run `tidy` for a canvas.
19
+ * - **`bpmndi` diagram layout.** The SDK emits none and `uip maestro bpmn format`
20
+ * regenerates it, so there is nothing to preserve. A decompiled file recompiles
21
+ * to semantic-only XML; re-run `format` for a canvas.
22
22
  * - **Comments, method order, and formatting.** Regenerated, not preserved.
23
23
  *
24
24
  * Everything else round-trips: events and their definitions, all four gateways,
@@ -2,7 +2,7 @@
2
2
  * Method names the platform expects to be CALLED, not merely named.
3
3
  *
4
4
  * Generated — do not edit by hand. Run `node scripts/gen-bpmn-known-methods.mjs`
5
- * to refresh from the installed `@uipath/maestro-sdk`.
5
+ * to refresh from the installed `@uipath/maestro-validation`.
6
6
  *
7
7
  * The canvas validator's `METHOD_MISSING_PARENTHESES` rule reads this list: an
8
8
  * expression containing `.<name>` not followed by `(` is an ERROR when `<name>` is
@@ -2,7 +2,7 @@
2
2
  * Method names the platform expects to be CALLED, not merely named.
3
3
  *
4
4
  * Generated — do not edit by hand. Run `node scripts/gen-bpmn-known-methods.mjs`
5
- * to refresh from the installed `@uipath/maestro-sdk`.
5
+ * to refresh from the installed `@uipath/maestro-validation`.
6
6
  *
7
7
  * The canvas validator's `METHOD_MISSING_PARENTHESES` rule reads this list: an
8
8
  * expression containing `.<name>` not followed by `(` is an ERROR when `<name>` is
@@ -0,0 +1,56 @@
1
+ /**
2
+ * bpmn/managed-http — the wire shape behind connector-mode `.http()`: a V2
3
+ * `Intsvc.UnifiedHttpRequest` through an Integration Service connection, as
4
+ * `uip maestro bpmn registry get Intsvc.UnifiedHttpRequest --connection-id <id>` builds it
5
+ * (UiPath/cli `buildManagedHttpSpec` rendered by `renderBpmnV2Element`).
6
+ */
7
+ import { MANAGED_HTTP_CONNECTOR_KEY } from '../core/managed-http.js';
8
+ import type { TypedContextRow, TypedInputRow, TypedOutputRow } from './typed-node.js';
9
+ export { MANAGED_HTTP_CONNECTOR_KEY };
10
+ export declare const MANAGED_HTTP_TYPE = "Intsvc.UnifiedHttpRequest";
11
+ /** The connection binding's name, after the node's `connectorKey`, as the CLI names it. */
12
+ export declare const MANAGED_HTTP_CONNECTION_NAME = "uipath-uipath-http connection";
13
+ export declare const MANAGED_HTTP_FOLDER_NAME = "FolderKey";
14
+ /**
15
+ * True for a V2 HTTP request. `registry-types.json` holds the V1 manual node, whose
16
+ * required `url` and `mode` a V2 one does not carry.
17
+ */
18
+ export declare function isManagedHttpV2(type: string, context: Record<string, unknown>): boolean;
19
+ /** The required fields a V2 HTTP request leaves unset, a request field as `body.<key>`; `body` is its request row. */
20
+ export declare function managedHttpMissing(context: Record<string, unknown>, body: unknown): string[];
21
+ /**
22
+ * A connector request's absolute `url`, when the connector it goes through is not the generic
23
+ * HTTP one. Integration Service refuses a host other than the connector's with 400 "Invalid request URL".
24
+ */
25
+ export declare function managedHttpAbsoluteUrl(body: unknown): {
26
+ url: string;
27
+ targetConnector: string;
28
+ } | undefined;
29
+ export interface ManagedHttpRequest {
30
+ /** `ref` is the `=bindings.<id>` reference; `key` the connection id it resolves to. */
31
+ connection: {
32
+ ref: string;
33
+ key: string;
34
+ };
35
+ folder?: {
36
+ ref: string;
37
+ };
38
+ /** The connector the connection belongs to. */
39
+ targetConnector: string;
40
+ method: string;
41
+ /** The endpoint on the target connector, e.g. `/emoji.list`. */
42
+ url: string;
43
+ headers?: Record<string, unknown>;
44
+ query?: Record<string, unknown>;
45
+ body?: unknown;
46
+ }
47
+ export interface ManagedHttpVars {
48
+ code: string;
49
+ headers: string;
50
+ body: string;
51
+ error: string;
52
+ }
53
+ export declare function managedHttpContext(req: ManagedHttpRequest): TypedContextRow[];
54
+ export declare function managedHttpInputs(req: ManagedHttpRequest): TypedInputRow[];
55
+ /** Studio Web's curated HTTP outputs, then `Error`. */
56
+ export declare function managedHttpOutputs(vars: ManagedHttpVars): TypedOutputRow[];
@@ -0,0 +1,159 @@
1
+ /**
2
+ * bpmn/managed-http — the wire shape behind connector-mode `.http()`: a V2
3
+ * `Intsvc.UnifiedHttpRequest` through an Integration Service connection, as
4
+ * `uip maestro bpmn registry get Intsvc.UnifiedHttpRequest --connection-id <id>` builds it
5
+ * (UiPath/cli `buildManagedHttpSpec` rendered by `renderBpmnV2Element`).
6
+ */
7
+ import { MANAGED_HTTP_ACTIVITY_TYPE_ID, MANAGED_HTTP_CONNECTOR_KEY, MANAGED_HTTP_ENDPOINT, MANAGED_HTTP_ENDPOINT_METHOD, MANAGED_HTTP_ESSENTIAL_CONFIGURATION, MANAGED_HTTP_INSTANCE_PARAMETERS, MANAGED_HTTP_OBJECT_NAME, MANAGED_HTTP_TELEMETRY, } from '../core/managed-http.js';
8
+ import { isRecord } from '../core/node-envelope.js';
9
+ export { MANAGED_HTTP_CONNECTOR_KEY };
10
+ export const MANAGED_HTTP_TYPE = 'Intsvc.UnifiedHttpRequest';
11
+ /** The connection binding's name, after the node's `connectorKey`, as the CLI names it. */
12
+ export const MANAGED_HTTP_CONNECTION_NAME = `${MANAGED_HTTP_CONNECTOR_KEY} connection`;
13
+ export const MANAGED_HTTP_FOLDER_NAME = 'FolderKey';
14
+ const CONNECTOR_VERSION = '1.4.50';
15
+ const CONFIGURATION_VERSION = 'v2';
16
+ const CONNECTOR_AUTHENTICATION = 'connector';
17
+ /** Studio Web's guard on a JSON string it stores in node metadata. */
18
+ const JSON_STRING_PREFIX = '=jsonString:';
19
+ /** The CLI's `EXPRESSION_SHAPED`: a value Studio Web's V2 component reads as an expression only as `=js:`. */
20
+ const EXPRESSION_SHAPED = /^=(vars|metadata|response|Error)\b/;
21
+ /**
22
+ * The V2 contract's required context (UiPath/cli `manifest/bpmn-spec.json`), and the fields
23
+ * the CLI requires of a connector request (`managedHttpDetailErrors`).
24
+ */
25
+ const REQUIRED_CONTEXT = ['connectorKey'];
26
+ const CONNECTOR_REQUIRED_CONTEXT = ['folderKey'];
27
+ const CONNECTOR_REQUIRED_BODY = ['targetConnector', 'connection'];
28
+ const ABSOLUTE_URL = /^[a-z][a-z\d+.-]*:\/\//i;
29
+ const ESSENTIAL_CONFIGURATION = {
30
+ essentialConfiguration: {
31
+ connectorVersion: CONNECTOR_VERSION,
32
+ executionType: null,
33
+ customFieldsRequestDetails: null,
34
+ ...MANAGED_HTTP_ESSENTIAL_CONFIGURATION,
35
+ },
36
+ };
37
+ /** The tenant-independent fields of Studio's TypeCache entry, which the CLI fetches live. */
38
+ const CATALOG_ENTRY = {
39
+ displayName: 'HTTP Request',
40
+ description: 'Use HTTP requests to interact with APIs via the selected connector and connection configuration.',
41
+ category: '',
42
+ configuration: JSON.stringify({ ...MANAGED_HTTP_INSTANCE_PARAMETERS, supportsStreaming: false, subType: 'method' }),
43
+ uiPathActivityTypeId: MANAGED_HTTP_ACTIVITY_TYPE_ID,
44
+ isEnabled: true,
45
+ };
46
+ /**
47
+ * True for a V2 HTTP request. `registry-types.json` holds the V1 manual node, whose
48
+ * required `url` and `mode` a V2 one does not carry.
49
+ */
50
+ export function isManagedHttpV2(type, context) {
51
+ return type === MANAGED_HTTP_TYPE && context.activityConfigurationVersion === CONFIGURATION_VERSION;
52
+ }
53
+ /** The required fields a V2 HTTP request leaves unset, a request field as `body.<key>`; `body` is its request row. */
54
+ export function managedHttpMissing(context, body) {
55
+ const unset = (v) => v === undefined || v === null || (typeof v === 'string' && v.trim() === '');
56
+ const missingContext = REQUIRED_CONTEXT.filter((name) => unset(context[name]));
57
+ const request = connectorRequest(body);
58
+ if (request === undefined)
59
+ return missingContext;
60
+ return [
61
+ ...missingContext,
62
+ ...CONNECTOR_REQUIRED_CONTEXT.filter((name) => unset(context[name])),
63
+ ...CONNECTOR_REQUIRED_BODY.filter((name) => typeof request[name] !== 'string' || unset(request[name])).map((name) => `body.${name}`),
64
+ ];
65
+ }
66
+ /**
67
+ * A connector request's absolute `url`, when the connector it goes through is not the generic
68
+ * HTTP one. Integration Service refuses a host other than the connector's with 400 "Invalid request URL".
69
+ */
70
+ export function managedHttpAbsoluteUrl(body) {
71
+ const request = connectorRequest(body);
72
+ if (request === undefined)
73
+ return undefined;
74
+ const { url, targetConnector } = request;
75
+ if (typeof url !== 'string' || typeof targetConnector !== 'string')
76
+ return undefined;
77
+ if (targetConnector === MANAGED_HTTP_CONNECTOR_KEY || !ABSOLUTE_URL.test(url))
78
+ return undefined;
79
+ return { url, targetConnector };
80
+ }
81
+ function connectorRequest(body) {
82
+ const request = typeof body === 'string' ? parseObject(body) : body;
83
+ return isRecord(request) && request.authentication === CONNECTOR_AUTHENTICATION ? request : undefined;
84
+ }
85
+ function parseObject(text) {
86
+ try {
87
+ return JSON.parse(text);
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ }
93
+ /** UiPath/cli `asDesignTimeExpressions`: `=vars.x` → `=js:vars.x`, at any depth; other text stays literal. */
94
+ function designTimeExpressions(value) {
95
+ if (typeof value === 'string')
96
+ return EXPRESSION_SHAPED.test(value) ? `=js:${value.slice(1)}` : value;
97
+ if (Array.isArray(value))
98
+ return value.map(designTimeExpressions);
99
+ if (isRecord(value))
100
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, designTimeExpressions(v)]));
101
+ return value;
102
+ }
103
+ export function managedHttpContext(req) {
104
+ return [
105
+ { name: 'connectorKey', value: MANAGED_HTTP_CONNECTOR_KEY },
106
+ { name: 'connection', value: req.connection.ref },
107
+ { name: 'resourceKey', value: req.connection.key },
108
+ ...(req.folder ? [{ name: 'folderKey', value: req.folder.ref }] : []),
109
+ { name: 'method', value: MANAGED_HTTP_ENDPOINT_METHOD },
110
+ { name: 'path', value: MANAGED_HTTP_ENDPOINT },
111
+ { name: 'objectName', value: MANAGED_HTTP_OBJECT_NAME },
112
+ {
113
+ name: 'metadata',
114
+ type: 'json',
115
+ body: {
116
+ activityPropertyConfiguration: {
117
+ configuration: `${JSON_STRING_PREFIX}${JSON.stringify(ESSENTIAL_CONFIGURATION)}`,
118
+ uiPathActivityTypeId: MANAGED_HTTP_ACTIVITY_TYPE_ID,
119
+ errorState: { issues: [] },
120
+ },
121
+ activityMetadata: { activity: CATALOG_ENTRY },
122
+ inputMetadata: {},
123
+ telemetryData: MANAGED_HTTP_TELEMETRY,
124
+ },
125
+ },
126
+ { name: 'activityConfigurationVersion', value: CONFIGURATION_VERSION },
127
+ ];
128
+ }
129
+ export function managedHttpInputs(req) {
130
+ const url = designTimeExpressions(req.url);
131
+ const body = {
132
+ authentication: CONNECTOR_AUTHENTICATION,
133
+ method: req.method,
134
+ targetConnector: req.targetConnector,
135
+ connection: req.connection.key,
136
+ path: url,
137
+ url,
138
+ };
139
+ if (req.headers !== undefined)
140
+ body.headers = designTimeExpressions(req.headers);
141
+ if (req.query !== undefined)
142
+ body.query = designTimeExpressions(req.query);
143
+ if (req.body !== undefined)
144
+ body.body = designTimeExpressions(req.body);
145
+ return [
146
+ { name: 'pathParameters', type: 'json', target: 'pathParameters', body: {} },
147
+ { name: 'queryParameters', type: 'json', target: 'queryParameters', body: {} },
148
+ { name: 'body', type: 'json', target: 'body', body },
149
+ ];
150
+ }
151
+ /** Studio Web's curated HTTP outputs, then `Error`. */
152
+ export function managedHttpOutputs(vars) {
153
+ return [
154
+ { name: 'code', type: 'number', source: '=response.code', var: vars.code },
155
+ { name: 'headers', type: 'object', source: '=response.headers', var: vars.headers },
156
+ { name: 'body', type: 'object', source: '=response.body', var: vars.body },
157
+ { name: 'Error', type: 'jsonSchema', source: '=Error', var: vars.error },
158
+ ];
159
+ }
@@ -274,7 +274,7 @@ export function mergeBpmn(originalXml, editedXml, options = {}) {
274
274
  originalXml.slice(originalProcess.innerEnd);
275
275
  // The diagram: the original's layout survives, which is strictly better than the
276
276
  // re-layout a bare recompile forces. Shapes and edges for deleted elements go with
277
- // them; anything newly added has no DI yet, which is what `format`/`tidy` is for.
277
+ // them; anything newly added has no DI yet, which is what `format` is for.
278
278
  if (removed.length > 0) {
279
279
  const plane = findByLocal(parseXmlRanges(merged), 'BPMNPlane');
280
280
  if (plane) {
@@ -12,8 +12,7 @@ export declare function serialize(built: BuiltBpmn, opts?: BpmnSerializeOpts): P
12
12
  * an attribute whose value equals the BPMN default, but Studio Web (and the
13
13
  * canvas graders) expect an interrupting boundary event to carry an explicit
14
14
  * `cancelActivity="true"`. Add it wherever a boundary event lacks the attribute
15
- * (its absence already means interrupting). Idempotent; also used by `tidy`,
16
- * which re-serializes through moddle and drops the attribute again.
15
+ * (its absence already means interrupting). Idempotent.
17
16
  *
18
17
  * **This one is a KNOWN divergence from what the product writes, kept on purpose.**
19
18
  * None of the 71 boundary events across the five real Studio Web exports in
@@ -10,8 +10,8 @@
10
10
  * descriptor.
11
11
  *
12
12
  * **Semantic-only, no diagram.** BPMN validation is layout-independent, so no
13
- * `bpmndi:BPMNDiagram` is emitted here; a separate "tidy" step (auto-layout)
14
- * adds geometry when a visual diagram is needed.
13
+ * `bpmndi:BPMNDiagram` is emitted here; `uip maestro bpmn format` adds geometry
14
+ * when a visual diagram is needed.
15
15
  */
16
16
  import BpmnModdle from 'bpmn-moddle';
17
17
  import { createRequire } from 'node:module';
@@ -170,8 +170,7 @@ export async function serialize(built, opts = {}) {
170
170
  * an attribute whose value equals the BPMN default, but Studio Web (and the
171
171
  * canvas graders) expect an interrupting boundary event to carry an explicit
172
172
  * `cancelActivity="true"`. Add it wherever a boundary event lacks the attribute
173
- * (its absence already means interrupting). Idempotent; also used by `tidy`,
174
- * which re-serializes through moddle and drops the attribute again.
173
+ * (its absence already means interrupting). Idempotent.
175
174
  *
176
175
  * **This one is a KNOWN divergence from what the product writes, kept on purpose.**
177
176
  * None of the 71 boundary events across the five real Studio Web exports in
@@ -53,15 +53,6 @@ export function registerBpmnCommands(program) {
53
53
  addValue(argv, '--bindings', options.bindings);
54
54
  await invoke('bpmn check', () => import('../../bpmn/check-cli.js'), argv);
55
55
  });
56
- family.command('tidy')
57
- .description('Add diagram layout to a compiled .bpmn artifact.')
58
- .argument('<input>', 'input .bpmn path')
59
- .option('-o, --output <file>', 'output .bpmn path')
60
- .action(async (input, options) => {
61
- const argv = [input];
62
- addValue(argv, '-o', options.output);
63
- await invoke('bpmn tidy', () => import('../../bpmn/tidy-cli.js'), argv);
64
- });
65
56
  family
66
57
  .command('decompile')
67
58
  .description('Convert a .bpmn artifact to authored TypeScript.')
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The managed HTTP request's fixed identity — Integration Service's generic HTTP
3
+ * connector, `POST /http-request` — shared by Flow's `core.action.http.v2` and BPMN's
4
+ * V2 `Intsvc.UnifiedHttpRequest`.
5
+ */
6
+ export declare const MANAGED_HTTP_CONNECTOR_KEY = "uipath-uipath-http";
7
+ export declare const MANAGED_HTTP_OBJECT_NAME = "http-request";
8
+ export declare const MANAGED_HTTP_ENDPOINT = "/http-request";
9
+ export declare const MANAGED_HTTP_ENDPOINT_METHOD = "POST";
10
+ /** Studio's HTTP Request activity type, the same on every tenant. */
11
+ export declare const MANAGED_HTTP_ACTIVITY_TYPE_ID = "5c4cc855-b42a-37e6-b910-de8588998fce";
12
+ export declare const MANAGED_HTTP_INSTANCE_PARAMETERS: {
13
+ connectorKey: string;
14
+ objectName: string;
15
+ httpMethod: string;
16
+ activityType: string;
17
+ version: string;
18
+ };
19
+ /** The `essentialConfiguration` fields both hosts write, in the order they write them. */
20
+ export declare const MANAGED_HTTP_ESSENTIAL_CONFIGURATION: {
21
+ instanceParameters: {
22
+ connectorKey: string;
23
+ objectName: string;
24
+ httpMethod: string;
25
+ activityType: string;
26
+ version: string;
27
+ };
28
+ objectName: string;
29
+ operation: string;
30
+ packageVersion: string;
31
+ httpMethod: string;
32
+ path: string;
33
+ unifiedTypesCompatible: boolean;
34
+ savedJitInputFieldId: string;
35
+ };
36
+ export declare const MANAGED_HTTP_TELEMETRY: {
37
+ connectorKey: string;
38
+ connectorName: string;
39
+ operationType: string;
40
+ objectName: string;
41
+ objectDisplayName: string;
42
+ primaryKeyName: string;
43
+ };