@uipath/maestro-builder-sdk 6.36.1 → 6.38.0
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/api-index.md +85 -83
- package/dist/api-members.md +339 -335
- package/dist/bpmn/bpmn-sdk.d.ts +33 -0
- package/dist/bpmn/bpmn-sdk.js +4 -0
- package/dist/bpmn/check.js +79 -0
- package/dist/bpmn/connector-lift-verify.d.ts +32 -0
- package/dist/bpmn/connector-lift-verify.js +220 -0
- package/dist/bpmn/connector.d.ts +12 -0
- package/dist/bpmn/connector.js +19 -1
- package/dist/bpmn/declared-vars.js +10 -3
- package/dist/bpmn/decompile-cli.js +68 -6
- package/dist/bpmn/decompile.d.ts +43 -0
- package/dist/bpmn/decompile.js +274 -9
- package/dist/bpmn/intsvc.d.ts +9 -10
- package/dist/bpmn/intsvc.js +31 -18
- package/dist/bpmn/serialize.js +31 -24
- package/dist/cli-library.js +3 -1
- package/dist/core/cli-library.d.ts +8 -2
- package/dist/core/cli-library.js +6 -4
- package/dist/core/connector-resolve-error.d.ts +7 -1
- package/dist/core/event-checks.js +2 -2
- package/dist/core/lookups.d.ts +22 -0
- package/dist/core/lookups.js +34 -1
- package/dist/core/synthesized-definition.d.ts +15 -0
- package/dist/core/synthesized-definition.js +22 -0
- package/dist/registry/library-build/context.d.ts +16 -0
- package/dist/registry/library-build/context.js +32 -5
- package/dist/registry/prepare/actions.d.ts +15 -0
- package/dist/registry/prepare/actions.js +12 -1
- package/dist/registry/prepare/integration-service.d.ts +105 -0
- package/dist/registry/prepare/integration-service.js +218 -0
- package/dist/registry/prepare/messages.d.ts +41 -1
- package/dist/registry/prepare/messages.js +82 -1
- package/dist/registry/prepare/pipeline.js +73 -15
- package/dist/registry/uip/commands.d.ts +8 -0
- package/dist/registry/uip/commands.js +12 -0
- package/dist/serialize.js +11 -0
- package/lib/library-json.samples/index.json +9 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/update-entity-record@1.0.0.json +132 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/update-entity-record@1.0.0.v1def.json +254 -0
- package/package.json +2 -2
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepare a connector operation the Flow node catalog does not serve, from
|
|
3
|
+
* Integration Service itself.
|
|
4
|
+
*
|
|
5
|
+
* `prepare` names an operation through `uip maestro flow registry get
|
|
6
|
+
* uipath.connector.<key>.<action>`: the registry node is the library entry's
|
|
7
|
+
* source and its `.v1def.json` sidecar. Some connectors have no node there at
|
|
8
|
+
* all, yet Integration Service serves them in full: `uip is activities list
|
|
9
|
+
* <key>` lists the curated activities with their object and HTTP method, and
|
|
10
|
+
* `uip is resources describe <key> <object> --operation <verb>` returns the
|
|
11
|
+
* path, the path/query parameters and the request and response fields. Told
|
|
12
|
+
* "op not in library", an author hand-fills `.activity('Intsvc.ActivityExecution')`
|
|
13
|
+
* tasks and gets the identity rows wrong.
|
|
14
|
+
*
|
|
15
|
+
* A BPMN connector task needs no registry node: the `sendTask` carries its own
|
|
16
|
+
* identity (`objectName`, `method`, `path`, `connectorKey`) and rows, which is
|
|
17
|
+
* exactly what the describe returns. So when the catalog serves NOTHING for the
|
|
18
|
+
* connector — not a misspelt action on a connector it does serve — this builds
|
|
19
|
+
* the library entry and a sidecar from the activity catalog and the describe,
|
|
20
|
+
* and the ordinary overlay write, descriptor regeneration and handoff follow.
|
|
21
|
+
* The sidecar is marked `synthesizedFrom: "integration-service"`: a Flow node
|
|
22
|
+
* embeds the registry's whole definition (form, handles, model), which no
|
|
23
|
+
* describe can supply, so Flow's compile and check refuse the entry with
|
|
24
|
+
* CONNECTOR_NO_FLOW_DEFINITION rather than emit a node the designer cannot open.
|
|
25
|
+
*
|
|
26
|
+
* Every `uip` call goes through the {@link BuildContext}; everything else is
|
|
27
|
+
* pure over the parsed replies.
|
|
28
|
+
*/
|
|
29
|
+
import { SCHEMA_VERSION, normalizeFieldKeys, pick } from "../library-build/canonical.js";
|
|
30
|
+
import { SYNTHESIZED_FROM_INTEGRATION_SERVICE } from "../../core/synthesized-definition.js";
|
|
31
|
+
import { isActivitiesCatalog, isConnectorGet, isDescribeOperation } from "../library-build/context.js";
|
|
32
|
+
import { HTTP_METHOD_TO_OPERATION } from "../library-build/enrich.js";
|
|
33
|
+
import { get, pyOr } from "../library-build/py.js";
|
|
34
|
+
import { isPlainObject } from "./support.js";
|
|
35
|
+
/** The marker a synthesized sidecar carries; Flow refuses a definition that has it. One owner, `core/`, so the writer and the refuser cannot drift. */
|
|
36
|
+
export { SYNTHESIZED_FROM_INTEGRATION_SERVICE };
|
|
37
|
+
/**
|
|
38
|
+
* The action id an activity goes by: its PascalCase name in kebab case —
|
|
39
|
+
* `CreateTestSet` → `create-test-set`, `AssignTestCasesToReq` →
|
|
40
|
+
* `assign-test-cases-to-req`, `CreateV2Attachment` → `create-v2-attachment`.
|
|
41
|
+
* A run of capitals stays one word (`GetPDFReport` → `get-pdf-report`).
|
|
42
|
+
*/
|
|
43
|
+
export function activityActionId(name) {
|
|
44
|
+
return name
|
|
45
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
46
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
|
|
47
|
+
.replace(/[\s_]+/g, "-")
|
|
48
|
+
.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
/** The curated rows of an activities listing, in the catalog's order. */
|
|
51
|
+
export function curatedActivities(rows) {
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const row of rows) {
|
|
54
|
+
if (!isPlainObject(row))
|
|
55
|
+
continue;
|
|
56
|
+
if (String(pyOr(get(row, "IsCurated"), "")).toLowerCase() !== "yes")
|
|
57
|
+
continue;
|
|
58
|
+
const name = String(pyOr(get(row, "Name"), "")).trim();
|
|
59
|
+
const objectName = String(pyOr(get(row, "ObjectName"), "")).trim();
|
|
60
|
+
const method = String(pyOr(get(row, "MethodName"), "")).trim().toUpperCase();
|
|
61
|
+
if (!name || !objectName || objectName === "N/A" || !method || method === "N/A")
|
|
62
|
+
continue;
|
|
63
|
+
out.push({
|
|
64
|
+
name,
|
|
65
|
+
displayName: String(pyOr(get(row, "DisplayName"), name)),
|
|
66
|
+
description: String(pyOr(get(row, "Description"), "")),
|
|
67
|
+
objectName,
|
|
68
|
+
method,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The curated activity an author's action names: by action id first
|
|
75
|
+
* (`create-test-set`), then by the activity's own name or display name,
|
|
76
|
+
* case-insensitively — `CreateTestSet`, `"Create Test Set"` and `create test set`
|
|
77
|
+
* all reach it. The spellings are compared both as given and in kebab case, so a
|
|
78
|
+
* display name with spaces matches whether or not the author kebab-cased it.
|
|
79
|
+
*/
|
|
80
|
+
export function matchActivity(activities, action) {
|
|
81
|
+
const wanted = action.trim().toLowerCase();
|
|
82
|
+
const wantedId = activityActionId(action.trim());
|
|
83
|
+
return (activities.find((a) => activityActionId(a.name) === wanted)
|
|
84
|
+
?? activities.find((a) => a.name.toLowerCase() === wanted)
|
|
85
|
+
?? activities.find((a) => a.displayName.trim().toLowerCase() === wanted)
|
|
86
|
+
?? activities.find((a) => activityActionId(a.displayName) === wantedId));
|
|
87
|
+
}
|
|
88
|
+
/** The `is resources` verb an activity's HTTP method reads under; `undefined` for a verb the catalog has no describe for. */
|
|
89
|
+
export function describeOperationFor(method) {
|
|
90
|
+
return HTTP_METHOD_TO_OPERATION.get(method.toUpperCase());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Prepare one action from Integration Service: the entry and the node the
|
|
94
|
+
* sidecar is built from, or why not.
|
|
95
|
+
*/
|
|
96
|
+
export async function integrationServiceEntry(ctx, input) {
|
|
97
|
+
const { connectorKey, action } = input;
|
|
98
|
+
const catalog = await isActivitiesCatalog(ctx, connectorKey);
|
|
99
|
+
if ("failure" in catalog)
|
|
100
|
+
return { miss: { kind: "no-catalog", reason: catalog.failure } };
|
|
101
|
+
const activities = curatedActivities(catalog.rows);
|
|
102
|
+
if (activities.length === 0)
|
|
103
|
+
return { miss: { kind: "no-catalog" } };
|
|
104
|
+
const activity = matchActivity(activities, action);
|
|
105
|
+
if (!activity)
|
|
106
|
+
return { miss: { kind: "no-such-activity", activities: activities.map((a) => activityActionId(a.name)) } };
|
|
107
|
+
// No guess for a method the table does not list: a describe read under the
|
|
108
|
+
// wrong verb returns another operation's path, and the entry would target it.
|
|
109
|
+
const operation = describeOperationFor(activity.method);
|
|
110
|
+
if (operation === undefined)
|
|
111
|
+
return { miss: { kind: "no-operation", activity } };
|
|
112
|
+
const described = await isDescribeOperation(ctx, connectorKey, activity.objectName, operation);
|
|
113
|
+
if (!isPlainObject(described))
|
|
114
|
+
return { miss: { kind: "no-schema", activity, operation } };
|
|
115
|
+
const connector = await isConnectorGet(ctx, connectorKey);
|
|
116
|
+
const entry = synthesizeEntry({ connectorKey, activity, operation, described, connector });
|
|
117
|
+
return { entry, action: activityActionId(activity.name), node: synthesizeNode(entry, described), activity, operation };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The library entry for one described activity — the shape `extractCanonical`
|
|
121
|
+
* writes from a registry node, filled from the describe instead: the IS
|
|
122
|
+
* object and verb, the path and its parameters, the request fields as the
|
|
123
|
+
* input schema. `httpMethod` keeps the catalog's spelling (`GETBYID` for a
|
|
124
|
+
* get-by-id, as registry entries do); the wire maps it. The entry goes by the
|
|
125
|
+
* activity's own action id, never the author's spelling: a display name would
|
|
126
|
+
* put spaces (or a `/`) in the overlay path and a second entry next to the id.
|
|
127
|
+
*/
|
|
128
|
+
export function synthesizeEntry(input) {
|
|
129
|
+
const { connectorKey, activity, operation, described, connector } = input;
|
|
130
|
+
const op = pyOr(pick(described, "Operation", "operation"), {});
|
|
131
|
+
const path = String(pyOr(pick(op, "Path", "path"), ""));
|
|
132
|
+
const method = String(pyOr(pick(op, "Method", "method"), activity.method)).toUpperCase();
|
|
133
|
+
const label = String(pyOr(pick(op, "Curated", "curated"), activity.displayName));
|
|
134
|
+
const parameters = normalizeFieldKeys(pyOr(pick(described, "Parameters", "parameters"), []));
|
|
135
|
+
const requestFields = normalizeFieldKeys(pyOr(pick(described, "RequestFields", "requestFields"), []));
|
|
136
|
+
const responseFields = normalizeFieldKeys(pyOr(pick(described, "ResponseFields", "responseFields"), []));
|
|
137
|
+
const connectorName = String(pyOr(get(connector, "Name"), connectorKey));
|
|
138
|
+
const icon = String(pyOr(get(connector, "Image"), ""));
|
|
139
|
+
const entry = {
|
|
140
|
+
schemaVersion: SCHEMA_VERSION,
|
|
141
|
+
nodeType: `uipath.connector.${connectorKey}.${activityActionId(activity.name)}`,
|
|
142
|
+
version: "1.0.0",
|
|
143
|
+
category: "connector",
|
|
144
|
+
tags: ["connector", "activity"],
|
|
145
|
+
connector: { key: connectorKey, name: connectorName },
|
|
146
|
+
operation: {
|
|
147
|
+
name: operation,
|
|
148
|
+
objectName: activity.objectName,
|
|
149
|
+
objectDisplayName: String(pyOr(pick(described, "DisplayName", "displayName"), activity.objectName)),
|
|
150
|
+
httpMethod: method,
|
|
151
|
+
path,
|
|
152
|
+
pathTemplate: path,
|
|
153
|
+
subType: "standard",
|
|
154
|
+
supportsStreaming: false,
|
|
155
|
+
activityType: "Curated",
|
|
156
|
+
parameters,
|
|
157
|
+
},
|
|
158
|
+
display: {
|
|
159
|
+
label,
|
|
160
|
+
description: activity.description || `(${connectorName}) ${label}`,
|
|
161
|
+
icon,
|
|
162
|
+
iconBackground: "",
|
|
163
|
+
iconBackgroundDark: "",
|
|
164
|
+
operationLabel: label,
|
|
165
|
+
},
|
|
166
|
+
runtime: {
|
|
167
|
+
bpmnType: "bpmn:SendTask",
|
|
168
|
+
serviceType: "Intsvc.ActivityExecution",
|
|
169
|
+
activityConfigurationVersion: "v1",
|
|
170
|
+
requiresConnection: true,
|
|
171
|
+
requiresFolderKey: true,
|
|
172
|
+
requiresConnectionForSchema: true,
|
|
173
|
+
},
|
|
174
|
+
inputSchema: { fields: requestFields },
|
|
175
|
+
outputSchema: { fields: responseFields },
|
|
176
|
+
provenance: {
|
|
177
|
+
source: SYNTHESIZED_FROM_INTEGRATION_SERVICE,
|
|
178
|
+
activity: activity.name,
|
|
179
|
+
method: activity.method,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
return entry;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The node `planLibrary` turns into the `.v1def.json` sidecar — the little a
|
|
186
|
+
* BPMN compile reads of one (`inputDefinition.fields` for the body, the model's
|
|
187
|
+
* type and service type) and the marker Flow refuses on. `buildV1Definition`
|
|
188
|
+
* keeps every key here.
|
|
189
|
+
*/
|
|
190
|
+
export function synthesizeNode(entry, described) {
|
|
191
|
+
const e = entry;
|
|
192
|
+
const outputFields = normalizeFieldKeys(pyOr(pick(described, "ResponseFields", "responseFields"), []));
|
|
193
|
+
return {
|
|
194
|
+
nodeType: e.nodeType,
|
|
195
|
+
version: e.version,
|
|
196
|
+
category: e.category,
|
|
197
|
+
tags: e.tags,
|
|
198
|
+
display: { label: e.display.label, description: e.display.description, icon: e.display.icon },
|
|
199
|
+
model: {
|
|
200
|
+
type: "bpmn:SendTask",
|
|
201
|
+
serviceType: "Intsvc.ActivityExecution",
|
|
202
|
+
bindings: { resource: "connection", propertyAttribute: "ConnectionId" },
|
|
203
|
+
context: [
|
|
204
|
+
{ name: "connectorKey", value: e.connector.key },
|
|
205
|
+
{ name: "objectName", value: e.operation.objectName },
|
|
206
|
+
{ name: "operation", value: e.operation.name },
|
|
207
|
+
{ name: "method", value: e.operation.httpMethod },
|
|
208
|
+
{ name: "path", value: e.operation.path },
|
|
209
|
+
{ name: "connection", value: "" },
|
|
210
|
+
{ name: "folderKey", value: "" },
|
|
211
|
+
{ name: "activityConfigurationVersion", value: "v1" },
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
inputDefinition: { fields: e.inputSchema.fields },
|
|
215
|
+
outputDefinition: { output: { fields: outputFields }, error: {} },
|
|
216
|
+
synthesizedFrom: SYNTHESIZED_FROM_INTEGRATION_SERVICE,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
* `core/cli-spelling.ts`) without this module reading the environment.
|
|
22
22
|
*/
|
|
23
23
|
import { Refusal } from "../errors.js";
|
|
24
|
-
import { type RegistryCatalog } from "./actions.js";
|
|
24
|
+
import { type RegistryCatalog, type RegistryRefresh } from "./actions.js";
|
|
25
|
+
import type { IntegrationServiceMiss } from "./integration-service.js";
|
|
25
26
|
export declare const PREFIX = "prepare-connector: ";
|
|
26
27
|
/** The spelling the Python hard-coded into every pasteable re-run. */
|
|
27
28
|
export declare const PREPARE_COMMAND = "npx flow-sdk registry prepare";
|
|
@@ -101,6 +102,10 @@ export declare function unresolvedOperationMessage(input: {
|
|
|
101
102
|
name: string;
|
|
102
103
|
probes: readonly ProbeMiss[];
|
|
103
104
|
catalog: RegistryCatalog;
|
|
105
|
+
/** What Integration Service said, when the catalog served nothing for the connector and IS was asked instead. */
|
|
106
|
+
integrationService?: IntegrationServiceMiss;
|
|
107
|
+
/** Whether the catalog was refreshed before that conclusion. */
|
|
108
|
+
registryRefresh?: RegistryRefresh;
|
|
104
109
|
}): string;
|
|
105
110
|
/**
|
|
106
111
|
* A `registry get` probe failed for a reason other than "Node not found" — an
|
|
@@ -133,6 +138,41 @@ export declare function inputFieldNote(count: number | undefined | null): string
|
|
|
133
138
|
export declare function tsNote(jsonOnly: boolean, connectorKey: string): string;
|
|
134
139
|
/** The action path's success line. */
|
|
135
140
|
export declare function preparedSummaryLine(nodeType: string, out: string, ts: string, variants: number, fieldNote: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* "The catalog serves no node for <key>", worded by what was measured: a fact
|
|
143
|
+
* after a forced pull, the local copy's answer when the pull failed or did not
|
|
144
|
+
* run (`registry get` and `registry search` answer from a copy that never
|
|
145
|
+
* refreshes itself).
|
|
146
|
+
*/
|
|
147
|
+
export declare function catalogServesNothingPhrase(key: string, refresh: RegistryRefresh | undefined): string;
|
|
148
|
+
/** The progress line before the one `registry pull --force` the fallback runs. */
|
|
149
|
+
export declare function refreshingCatalogLine(key: string): string;
|
|
150
|
+
/** The warning when that pull failed; the fallback continues against the local copy. */
|
|
151
|
+
export declare function catalogRefreshFailedLine(reason: string): string;
|
|
152
|
+
/** The note when the author's `--action` spelling was not the entry's id. */
|
|
153
|
+
export declare function actionCanonicalizedLine(given: string, actionId: string): string;
|
|
154
|
+
/**
|
|
155
|
+
* What Integration Service serves when the Flow catalog serves nothing for a
|
|
156
|
+
* connector: the curated activities' action ids, so the author re-runs with
|
|
157
|
+
* one of them, or why the one they named could not be read.
|
|
158
|
+
*/
|
|
159
|
+
export declare function integrationServiceLines(key: string, name: string, miss: IntegrationServiceMiss, refresh?: RegistryRefresh): string[];
|
|
160
|
+
/** The action path's source line when Integration Service supplied the entry. */
|
|
161
|
+
export declare function preparedFromIntegrationServiceLine(key: string, activity: {
|
|
162
|
+
name: string;
|
|
163
|
+
objectName: string;
|
|
164
|
+
method: string;
|
|
165
|
+
}, refresh?: RegistryRefresh): string;
|
|
166
|
+
/**
|
|
167
|
+
* The pasteable BPMN call for an operation prepared from Integration Service —
|
|
168
|
+
* the only family that compiles it, so the Flow import handoff is not printed
|
|
169
|
+
* for it. Required inputs are named with their type; the rest are left to the
|
|
170
|
+
* descriptor the overlay carries.
|
|
171
|
+
*/
|
|
172
|
+
export declare function bpmnConnectorUsageLines(connectorKey: string, action: string, required: ReadonlyArray<{
|
|
173
|
+
name: string;
|
|
174
|
+
type: string;
|
|
175
|
+
}>, boundConnection?: string, boundFolder?: string): string[];
|
|
136
176
|
/** Why this run did not overwrite the overlay (`_keep_prepared_schema`). */
|
|
137
177
|
export declare function keptSchemaMessage(action: string, kept: number, discarded: number): string;
|
|
138
178
|
/** The set was SHAPED right but resolved to nothing new: a VALUE is wrong for this connection. */
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import { Refusal, messageOf } from "../errors.js";
|
|
24
24
|
import { commentText } from "../../core/comment-text.js";
|
|
25
25
|
import { plausibleMatches } from "./actions.js";
|
|
26
|
+
import { HTTP_METHOD_TO_OPERATION } from "../library-build/enrich.js";
|
|
26
27
|
import { pyGet, pyOr, pyRepr, pyStrAny, pyTruthy } from "./support.js";
|
|
27
28
|
export const PREFIX = "prepare-connector: ";
|
|
28
29
|
/** The spelling the Python hard-coded into every pasteable re-run. */
|
|
@@ -178,7 +179,7 @@ function sharedTokens(wanted, candidate) {
|
|
|
178
179
|
* offline validators accept and the runtime dispatches to the wrong operation.
|
|
179
180
|
*/
|
|
180
181
|
export function unresolvedOperationMessage(input) {
|
|
181
|
-
const { connectorKey: key, name, probes, catalog } = input;
|
|
182
|
+
const { connectorKey: key, name, probes, catalog, integrationService, registryRefresh } = input;
|
|
182
183
|
const lines = [
|
|
183
184
|
`${PREFIX}\`${key} ${name}\` is neither an action nor an event the registry serves:`,
|
|
184
185
|
...probeLines(probes),
|
|
@@ -221,6 +222,8 @@ export function unresolvedOperationMessage(input) {
|
|
|
221
222
|
else {
|
|
222
223
|
lines.push("", `\`registry search ${key}\` lists no action for ${key} either.`);
|
|
223
224
|
}
|
|
225
|
+
if (integrationService !== undefined)
|
|
226
|
+
lines.push("", ...integrationServiceLines(key, name, integrationService, registryRefresh));
|
|
224
227
|
lines.push("", "`registry get` and `registry search` answer from the CLI's local copy of the catalog.", "If it looks stale, refresh it first: `uip maestro flow registry pull --force`.",
|
|
225
228
|
// Named `flow` on purpose, whatever family you are authoring: this is the
|
|
226
229
|
// catalog `prepare` itself reads, and `uip maestro bpmn registry pull` fills
|
|
@@ -311,6 +314,84 @@ export function tsNote(jsonOnly, connectorKey) {
|
|
|
311
314
|
export function preparedSummaryLine(nodeType, out, ts, variants, fieldNote) {
|
|
312
315
|
return `${PREFIX}${nodeType} → ${out}/ (${ts}, ${variants} variant(s), ${fieldNote})`;
|
|
313
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* "The catalog serves no node for <key>", worded by what was measured: a fact
|
|
319
|
+
* after a forced pull, the local copy's answer when the pull failed or did not
|
|
320
|
+
* run (`registry get` and `registry search` answer from a copy that never
|
|
321
|
+
* refreshes itself).
|
|
322
|
+
*/
|
|
323
|
+
export function catalogServesNothingPhrase(key, refresh) {
|
|
324
|
+
if (refresh?.ok === true)
|
|
325
|
+
return `the Flow node catalog, refreshed with \`uip maestro flow registry pull --force\`, serves no node for ${key}`;
|
|
326
|
+
const why = refresh === undefined ? "it was not refreshed" : `refreshing it failed: ${refresh.reason}`;
|
|
327
|
+
return `the CLI's local copy of the Flow node catalog serves no node for ${key} (${why})`;
|
|
328
|
+
}
|
|
329
|
+
/** The progress line before the one `registry pull --force` the fallback runs. */
|
|
330
|
+
export function refreshingCatalogLine(key) {
|
|
331
|
+
return ` the local catalog copy serves no node for ${key}; refreshing it (uip maestro flow registry pull --force) and looking again.`;
|
|
332
|
+
}
|
|
333
|
+
/** The warning when that pull failed; the fallback continues against the local copy. */
|
|
334
|
+
export function catalogRefreshFailedLine(reason) {
|
|
335
|
+
return `${PREFIX}registry pull --force failed (${reason}); continuing with the local catalog copy, which may be stale.`;
|
|
336
|
+
}
|
|
337
|
+
/** The note when the author's `--action` spelling was not the entry's id. */
|
|
338
|
+
export function actionCanonicalizedLine(given, actionId) {
|
|
339
|
+
return ` action: "${given}" is Integration Service activity ${actionId}; the entry is written under that id.`;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* What Integration Service serves when the Flow catalog serves nothing for a
|
|
343
|
+
* connector: the curated activities' action ids, so the author re-runs with
|
|
344
|
+
* one of them, or why the one they named could not be read.
|
|
345
|
+
*/
|
|
346
|
+
export function integrationServiceLines(key, name, miss, refresh) {
|
|
347
|
+
const phrase = catalogServesNothingPhrase(key, refresh);
|
|
348
|
+
const head = `${phrase[0].toUpperCase()}${phrase.slice(1)}, so Integration Service was asked instead (\`uip is activities list ${key}\`).`;
|
|
349
|
+
if (miss.kind === "no-catalog") {
|
|
350
|
+
return miss.reason === undefined
|
|
351
|
+
? [head, `It lists no curated activity for ${key} either — the connector may need enabling on this tenant, or the key may be misspelt.`]
|
|
352
|
+
: [head, `That call failed: ${miss.reason}`, "Fix that (the connection, the login, the connector's enablement on this tenant), then re-run."];
|
|
353
|
+
}
|
|
354
|
+
if (miss.kind === "no-operation") {
|
|
355
|
+
return [
|
|
356
|
+
head,
|
|
357
|
+
`It lists \`${name}\` (${miss.activity.name}: ${miss.activity.objectName} ${miss.activity.method}), but ${miss.activity.method} maps to no`,
|
|
358
|
+
`\`is resources\` operation (${[...HTTP_METHOD_TO_OPERATION.keys()].join(", ")} do), so there is no describe to prepare it from.`,
|
|
359
|
+
"Author it as an `.activity('Intsvc.ActivityExecution')` task from `uip is activities list` and `uip is resources describe` by hand.",
|
|
360
|
+
];
|
|
361
|
+
}
|
|
362
|
+
if (miss.kind === "no-schema") {
|
|
363
|
+
return [
|
|
364
|
+
head,
|
|
365
|
+
`It lists \`${name}\` (${miss.activity.name}: ${miss.activity.objectName} ${miss.activity.method}), but`,
|
|
366
|
+
`\`uip is resources describe ${key} ${miss.activity.objectName} --operation ${miss.operation} --connection-id <id>\` returned no schema for it,`,
|
|
367
|
+
"so there is nothing to prepare from. Check the connection, then re-run.",
|
|
368
|
+
];
|
|
369
|
+
}
|
|
370
|
+
const close = plausibleMatches(name, miss.activities);
|
|
371
|
+
const lines = [head];
|
|
372
|
+
if (close.length > 0)
|
|
373
|
+
lines.push(`Closest activity to "${name}": ${close.slice(0, 3).join(", ")}`);
|
|
374
|
+
lines.push(`Activities Integration Service serves for ${key} (re-run with one as --action):`, ...miss.activities.map((a) => ` ${a}`));
|
|
375
|
+
return lines;
|
|
376
|
+
}
|
|
377
|
+
/** The action path's source line when Integration Service supplied the entry. */
|
|
378
|
+
export function preparedFromIntegrationServiceLine(key, activity, refresh) {
|
|
379
|
+
return (` source: Integration Service activity ${activity.name} (${activity.objectName} ${activity.method}) — ${catalogServesNothingPhrase(key, refresh)}, `
|
|
380
|
+
+ "so this operation compiles in BPMN only (a Flow step or agent tool needs the registry's node definition).");
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* The pasteable BPMN call for an operation prepared from Integration Service —
|
|
384
|
+
* the only family that compiles it, so the Flow import handoff is not printed
|
|
385
|
+
* for it. Required inputs are named with their type; the rest are left to the
|
|
386
|
+
* descriptor the overlay carries.
|
|
387
|
+
*/
|
|
388
|
+
export function bpmnConnectorUsageLines(connectorKey, action, required, boundConnection = "<binding-name>", boundFolder = "<folder-binding-name>") {
|
|
389
|
+
const inputs = required.map((f) => `${/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(f.name) ? f.name : JSON.stringify(f.name)}: /* ${commentText(f.type)}, required */`).join(", ");
|
|
390
|
+
return [
|
|
391
|
+
`.connector("<id>", "${connectorKey}", "${action}", { ${inputs} }, { connection: "${boundConnection}", folder: "${boundFolder}" })`,
|
|
392
|
+
"this operation was prepared from Integration Service, so it compiles in BPMN only; `bpmn check` and `bpmn compile` read the overlay from ./connectors-local (or --connectors-local <dir>).",
|
|
393
|
+
];
|
|
394
|
+
}
|
|
314
395
|
/** Why this run did not overwrite the overlay (`_keep_prepared_schema`). */
|
|
315
396
|
export function keptSchemaMessage(action, kept, discarded) {
|
|
316
397
|
return (`${PREFIX}kept the prepared schema for ${action} ` +
|
|
@@ -35,12 +35,13 @@ import { enrichEntry } from "../library-build/enrich.js";
|
|
|
35
35
|
import { expandGenericForConnector, genericTemplatesByOp } from "../library-build/generic-expand.js";
|
|
36
36
|
import { planLibrary } from "../library-build/plan.js";
|
|
37
37
|
import { MemoryResponseCache } from "../uip/response-cache.js";
|
|
38
|
-
import { registryCatalog } from "./actions.js";
|
|
38
|
+
import { refreshRegistryCatalog, registryCatalog } from "./actions.js";
|
|
39
39
|
import { chooseConnection, listConnections, lookupConnection, mergeBindings, restoreBindings, snapshotBindings, solutionConnectionIds, } from "./connections.js";
|
|
40
40
|
import { prepareEvent } from "./event.js";
|
|
41
|
+
import { integrationServiceEntry } from "./integration-service.js";
|
|
41
42
|
import { descriptorUsage } from "./handoff.js";
|
|
42
43
|
import { ResolutionsExhausted, allParentsResolved, resolvedParentValues, writeResolutions } from "./ledger.js";
|
|
43
|
-
import { PREPARE_COMMAND, PrepareRefusal, ambiguousLabelsMessage, connectionChoiceLine, bindingsLine, candidateLabel, connectionLine, generatedModulesLine, genericActionNeedsObjectMessage, inputFieldNote, flagDiffersFromSourceLine, keptSchemaMessage, labelTakenMessage, lookupVocabularyLines, missingGenericSchemaMessage, missingParentsNote, nextLine, noCanonicalEntryMessage, objectFlagsOnlyForGenericMessage, objectNoteLine, objectRecordedLine, parentFieldNamesMismatchMessage, parentOnlyMessage, prefixed, preparedSummaryLine, rejectedParentFieldsMessage, rerunAgainstLine, resolvedParentsNote, registryGetFailedMessage, sharedLabelMessage, sourceLabelSuffix, tsNote, partlyUnreadableLabelLine, unreadableLabelLine, unresolvedOperationMessage, } from "./messages.js";
|
|
44
|
+
import { PREPARE_COMMAND, PrepareRefusal, ambiguousLabelsMessage, connectionChoiceLine, bindingsLine, bpmnConnectorUsageLines, candidateLabel, connectionLine, generatedModulesLine, genericActionNeedsObjectMessage, inputFieldNote, flagDiffersFromSourceLine, keptSchemaMessage, labelTakenMessage, lookupVocabularyLines, missingGenericSchemaMessage, missingParentsNote, nextLine, noCanonicalEntryMessage, objectFlagsOnlyForGenericMessage, objectNoteLine, objectRecordedLine, parentFieldNamesMismatchMessage, parentOnlyMessage, prefixed, preparedFromIntegrationServiceLine, actionCanonicalizedLine, catalogRefreshFailedLine, refreshingCatalogLine, preparedSummaryLine, rejectedParentFieldsMessage, rerunAgainstLine, resolvedParentsNote, registryGetFailedMessage, sharedLabelMessage, sourceLabelSuffix, tsNote, partlyUnreadableLabelLine, unreadableLabelLine, unresolvedOperationMessage, } from "./messages.js";
|
|
44
45
|
import { ObjectMatchRefusal, RESOLUTIONS_FILENAME, matchObject, recordObjectResolution } from "./objects.js";
|
|
45
46
|
import { countInputFields, keepPreparedSchema, lookupSpecsFromOverlay, mergeFilesInto, parentFields as overlayParentFields, schemaActionParents, } from "./overlay.js";
|
|
46
47
|
import { declaredParents, objectActionRequest, objectActionSpecs, parseFields } from "./parents.js";
|
|
@@ -326,13 +327,21 @@ export async function prepareConnector(options, ports) {
|
|
|
326
327
|
return prepareConnector({ ...options, ...labels, connectionId: chosenId, refreshLookups: true }, ports);
|
|
327
328
|
}
|
|
328
329
|
}
|
|
329
|
-
/**
|
|
330
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Everything after stage 0, against one settled connection. `registryRefresh`
|
|
332
|
+
* is set on the one re-entry after `registry pull --force` (below), so the
|
|
333
|
+
* pull runs at most once per command.
|
|
334
|
+
*/
|
|
335
|
+
async function prepareOnConnection(options, ports, connected, registryRefresh) {
|
|
331
336
|
const cwd = ports.cwd ?? process.cwd();
|
|
332
337
|
const info = (line) => ports.reporter.info(line);
|
|
333
338
|
const warn = (line) => ports.reporter.warn(line);
|
|
334
339
|
const command = ports.prepareCommand ?? PREPARE_COMMAND;
|
|
335
|
-
const { connectorKey
|
|
340
|
+
const { connectorKey } = options;
|
|
341
|
+
// Rebound to the activity's own action id when Integration Service supplies
|
|
342
|
+
// the entry, so the overlay path, the summary and the handoff all spell the
|
|
343
|
+
// id the entry goes by rather than the author's `--action`.
|
|
344
|
+
let action = options.action;
|
|
336
345
|
const fieldPairs = options.fields ?? [];
|
|
337
346
|
const parentFields = parseFields(fieldPairs);
|
|
338
347
|
const outShown = options.out ?? defaultOverlayOut(cwd);
|
|
@@ -341,7 +350,8 @@ async function prepareOnConnection(options, ports, connected) {
|
|
|
341
350
|
const jsonOnly = options.jsonOnly ?? false;
|
|
342
351
|
const { connectionId, bound, rollback } = connected;
|
|
343
352
|
const ctx = createBuildContext({ client: ports.client, caches: ports.caches ?? memoryCaches(), reporter: ports.reporter, concurrency: 1, timeoutMs: ports.timeoutMs }, { connectionId, parentFields });
|
|
344
|
-
|
|
353
|
+
let nodeType = `uipath.connector.${connectorKey}.${action}`;
|
|
354
|
+
let fromIntegrationService;
|
|
345
355
|
const actionProbe = await registryProbe(ctx, nodeType);
|
|
346
356
|
if ("miss" in actionProbe) {
|
|
347
357
|
// Not an activity. Connector EVENTS live one namespace over, and their
|
|
@@ -375,20 +385,52 @@ async function prepareOnConnection(options, ports, connected) {
|
|
|
375
385
|
throw new PrepareRefusal(registryGetFailedMessage(connectorKey, action, probes), "REGISTRY_GET_FAILED");
|
|
376
386
|
}
|
|
377
387
|
const catalog = await registryCatalog(ports.client, connectorKey, ports.timeoutMs);
|
|
378
|
-
|
|
388
|
+
// A catalog that serves NOTHING for the connector — no action, no event, and
|
|
389
|
+
// the search itself answered — is a connector the Flow registry does not
|
|
390
|
+
// carry, not a misspelt action on one it does. Integration Service still
|
|
391
|
+
// serves it, and a BPMN connector task needs nothing more.
|
|
392
|
+
if (catalog.failure === undefined && catalog.actions.length === 0 && catalog.events.length === 0) {
|
|
393
|
+
// The probes and the search answer from the CLI's local catalog copy,
|
|
394
|
+
// which never refreshes itself. Pull once and look again before
|
|
395
|
+
// concluding anything: a stale copy would send a connector the catalog
|
|
396
|
+
// does serve down the BPMN-only path, and the summary would state it.
|
|
397
|
+
if (registryRefresh === undefined) {
|
|
398
|
+
info(refreshingCatalogLine(connectorKey));
|
|
399
|
+
const refreshed = await refreshRegistryCatalog(ports.client, ports.timeoutMs);
|
|
400
|
+
if (!refreshed.ok)
|
|
401
|
+
warn(catalogRefreshFailedLine(refreshed.reason));
|
|
402
|
+
return prepareOnConnection(options, ports, connected, refreshed);
|
|
403
|
+
}
|
|
404
|
+
const prepared = await integrationServiceEntry(ctx, { connectorKey, action });
|
|
405
|
+
if ("miss" in prepared) {
|
|
406
|
+
throw new PrepareRefusal(unresolvedOperationMessage({ connectorKey, name: action, probes, catalog, integrationService: prepared.miss, registryRefresh }), "OPERATION_UNKNOWN");
|
|
407
|
+
}
|
|
408
|
+
info(preparedFromIntegrationServiceLine(connectorKey, prepared.activity, registryRefresh));
|
|
409
|
+
if (prepared.action !== action)
|
|
410
|
+
info(actionCanonicalizedLine(action, prepared.action));
|
|
411
|
+
action = prepared.action;
|
|
412
|
+
nodeType = prepared.entry.nodeType;
|
|
413
|
+
fromIntegrationService = prepared;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
throw new PrepareRefusal(unresolvedOperationMessage({ connectorKey, name: action, probes, catalog }), "OPERATION_UNKNOWN");
|
|
417
|
+
}
|
|
379
418
|
}
|
|
380
|
-
|
|
419
|
+
// The registry reply this entry came from, or none when Integration Service
|
|
420
|
+
// supplied it — then there is no node to read parents from and the sidecar
|
|
421
|
+
// is built from the synthesized node instead.
|
|
422
|
+
const payload = fromIntegrationService === undefined && "name" in actionProbe ? ctx.caches.registry.read(actionProbe.name) : undefined;
|
|
381
423
|
// The registry's own declaration of parent inputs, read from the same reply.
|
|
382
|
-
const declared = declaredParents(payload);
|
|
383
|
-
let entry = extractCanonical(nodeOf(payload));
|
|
424
|
+
const declared = payload === undefined ? [] : declaredParents(payload);
|
|
425
|
+
let entry = fromIntegrationService?.entry ?? extractCanonical(nodeOf(payload));
|
|
384
426
|
if (entry === undefined)
|
|
385
427
|
throw new PrepareRefusal(noCanonicalEntryMessage(nodeType), "NO_CANONICAL_ENTRY");
|
|
386
428
|
if (options.version)
|
|
387
429
|
entry.version = options.version;
|
|
388
430
|
if (parentFields.size > 0) {
|
|
389
|
-
const request = objectActionRequest(payload, parentFields);
|
|
431
|
+
const request = payload === undefined ? undefined : objectActionRequest(payload, parentFields);
|
|
390
432
|
if (request === undefined) {
|
|
391
|
-
throw new PrepareRefusal(parentFieldNamesMismatchMessage([...parentFields.keys()], objectActionSpecs(payload)), "PARENT_FIELDS_MISMATCH");
|
|
433
|
+
throw new PrepareRefusal(parentFieldNamesMismatchMessage([...parentFields.keys()], payload === undefined ? [] : objectActionSpecs(payload)), "PARENT_FIELDS_MISMATCH");
|
|
392
434
|
}
|
|
393
435
|
entry.operation.customFieldsRequestDetails = request;
|
|
394
436
|
}
|
|
@@ -422,11 +464,14 @@ async function prepareOnConnection(options, ports, connected) {
|
|
|
422
464
|
else {
|
|
423
465
|
if (objectName || options.allObjects)
|
|
424
466
|
throw new PrepareRefusal(objectFlagsOnlyForGenericMessage(), "OBJECT_NOT_GENERIC");
|
|
425
|
-
|
|
467
|
+
// An Integration Service entry IS the describe; there is nothing to enrich it with.
|
|
468
|
+
if (fromIntegrationService === undefined)
|
|
469
|
+
entry = await enrichEntry(ctx, entry); // full schema via --connection-id
|
|
426
470
|
preparedEntries = [entry];
|
|
427
471
|
}
|
|
428
472
|
const entryNodeType = entry.nodeType;
|
|
429
|
-
const
|
|
473
|
+
const sidecarNode = fromIntegrationService?.node ?? nodeOf(payload);
|
|
474
|
+
const plan = planLibrary(preparedEntries, (requestedNodeType) => (requestedNodeType === entryNodeType ? sidecarNode : undefined));
|
|
430
475
|
for (const line of plan.warnings)
|
|
431
476
|
warn(line);
|
|
432
477
|
const kept = keepPreparedSchema(out, entryNodeType, plan.files, parentFields, objectName);
|
|
@@ -501,7 +546,20 @@ async function prepareOnConnection(options, ports, connected) {
|
|
|
501
546
|
warn(missingParentsNote(connectorKey, action, actionParents, missing, parentFields, command));
|
|
502
547
|
}
|
|
503
548
|
}
|
|
504
|
-
if (
|
|
549
|
+
if (fromIntegrationService !== undefined) {
|
|
550
|
+
// BPMN is the family that compiles this entry, so the handoff is its call,
|
|
551
|
+
// whether or not a module was generated; the Flow import is never repointed.
|
|
552
|
+
const required = fromIntegrationService.entry.inputSchema?.fields ?? [];
|
|
553
|
+
const params = fromIntegrationService.entry.operation.parameters ?? [];
|
|
554
|
+
const fields = [
|
|
555
|
+
...params.filter((f) => f.required === true).map((f) => ({ name: String(f.name), type: String(f.dataType ?? "string") })),
|
|
556
|
+
...required.filter((f) => f.required === true).map((f) => ({ name: String(f.name), type: String(f.type ?? f.dataType ?? "string") })),
|
|
557
|
+
];
|
|
558
|
+
for (const line of bpmnConnectorUsageLines(connectorKey, action, fields, pyOr(bound?.connection, "<binding-name>"), pyOr(bound?.folder, "<folder-binding-name>"))) {
|
|
559
|
+
info(nextLine(line));
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else if (!jsonOnly) {
|
|
505
563
|
// Print what was bound, so the last line of output is a call the reader
|
|
506
564
|
// can paste rather than `<binding-name>` placeholders. `or`, not `??`: an
|
|
507
565
|
// empty symbolic name is a placeholder in Python's eyes too.
|
|
@@ -17,7 +17,15 @@ export declare function connectionArgs(connectionId?: string): string[];
|
|
|
17
17
|
export declare function fieldArgs(parentFields: ReadonlyMap<string, string> | Readonly<Record<string, string>> | undefined): string[];
|
|
18
18
|
export declare function registrySearchConnectors(): string[];
|
|
19
19
|
export declare function registrySearch(query: string): string[];
|
|
20
|
+
/**
|
|
21
|
+
* `uip maestro flow registry pull --force`: refresh the CLI's local copy of the
|
|
22
|
+
* Flow node catalog, which `registry get` and `registry search` answer from and
|
|
23
|
+
* which never refreshes itself.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registryPull(): string[];
|
|
20
26
|
export declare function registryGet(nodeType: string, connectionId?: string): string[];
|
|
27
|
+
/** `uip is activities list <key> --output json`: the connector's activity catalog — curated activities with their object and HTTP method, and the generic record verbs. No connection needed. */
|
|
28
|
+
export declare function isActivitiesList(connectorKey: string): string[];
|
|
21
29
|
export declare function isConnectorsMetadata(connectorKey: string): string[];
|
|
22
30
|
export declare function isResourcesDescribeOperation(connectorKey: string, objectName: string, operation: string, connectionId?: string, parentFields?: ReadonlyMap<string, string> | Readonly<Record<string, string>>): string[];
|
|
23
31
|
export declare function isResourcesDescribeObject(connectorKey: string, objectName: string, connectionId?: string): string[];
|
|
@@ -28,9 +28,21 @@ export function registrySearchConnectors() {
|
|
|
28
28
|
export function registrySearch(query) {
|
|
29
29
|
return [UIP, "maestro", "flow", "registry", "search", query, "--output", "json"];
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* `uip maestro flow registry pull --force`: refresh the CLI's local copy of the
|
|
33
|
+
* Flow node catalog, which `registry get` and `registry search` answer from and
|
|
34
|
+
* which never refreshes itself.
|
|
35
|
+
*/
|
|
36
|
+
export function registryPull() {
|
|
37
|
+
return [UIP, "maestro", "flow", "registry", "pull", "--force"];
|
|
38
|
+
}
|
|
31
39
|
export function registryGet(nodeType, connectionId) {
|
|
32
40
|
return [UIP, "maestro", "flow", "registry", "get", nodeType, "--output", "json", ...connectionArgs(connectionId)];
|
|
33
41
|
}
|
|
42
|
+
/** `uip is activities list <key> --output json`: the connector's activity catalog — curated activities with their object and HTTP method, and the generic record verbs. No connection needed. */
|
|
43
|
+
export function isActivitiesList(connectorKey) {
|
|
44
|
+
return [UIP, "is", "activities", "list", connectorKey, "--output", "json"];
|
|
45
|
+
}
|
|
34
46
|
export function isConnectorsMetadata(connectorKey) {
|
|
35
47
|
return [UIP, "is", "connectors", "metadata", connectorKey, "--output", "json"];
|
|
36
48
|
}
|
package/dist/serialize.js
CHANGED
|
@@ -22,6 +22,7 @@ import { resolveVersionCarried } from './core/nodes/versioned.js';
|
|
|
22
22
|
import { indexCarriedDefinitions } from './core/carried-definitions.js';
|
|
23
23
|
import { formFieldJsonSchema, formFieldSettingsWire, wireFormFieldType } from './core/form-field-type.js';
|
|
24
24
|
import { ConnectorResolveError } from './core/connector-resolve-error.js';
|
|
25
|
+
import { synthesizedDefinitionRefusal } from './core/synthesized-definition.js';
|
|
25
26
|
import { connectionConnectors } from './bindings-v2.js';
|
|
26
27
|
import { BindingRefusal, GUID_RE, bindingLabelRefusal, bindingMissingMessage, missingBindingLabels } from './core/binding-messages.js';
|
|
27
28
|
import { ByoaRefusal, byoaUnverified } from './core/byoa.js';
|
|
@@ -5225,6 +5226,10 @@ export function serialize(built, opts = {}) {
|
|
|
5225
5226
|
addEdge(scope, t, id);
|
|
5226
5227
|
return [{ node: id, port: successPort(type) }];
|
|
5227
5228
|
}
|
|
5229
|
+
// An entry `prepare` synthesized from Integration Service compiles in BPMN only.
|
|
5230
|
+
const noDefinition = synthesizedDefinitionRefusal(rc);
|
|
5231
|
+
if (noDefinition)
|
|
5232
|
+
throw noDefinition;
|
|
5228
5233
|
const id = stepUid(scope, step.name);
|
|
5229
5234
|
const node = makeNode(rc.nodeType, id, step.name, { parentId, requestedVersion: step.options?.version, def: rc.v1def });
|
|
5230
5235
|
declareListOutputType(node, rc);
|
|
@@ -5594,6 +5599,12 @@ export function serialize(built, opts = {}) {
|
|
|
5594
5599
|
if (!opts.library)
|
|
5595
5600
|
throw new Error(`inline agent "${step.name}"'s connector tool needs a library (pass --library / set $FLOW_SDK_LIBRARY_JSON).`);
|
|
5596
5601
|
const rc = opts.library.resolve(tr.connector, tr.operation, tr.version, tr.object);
|
|
5602
|
+
// An entry `prepare` synthesized from Integration Service compiles in
|
|
5603
|
+
// BPMN only — for a tool as for a step: `connectorToolDef` reads the
|
|
5604
|
+
// same definition, and a synthesized one has no form or handles.
|
|
5605
|
+
const noDefinition = synthesizedDefinitionRefusal(rc);
|
|
5606
|
+
if (noDefinition)
|
|
5607
|
+
throw noDefinition;
|
|
5597
5608
|
tdef = connectorToolDef(rc);
|
|
5598
5609
|
label = tr.name ?? rc.v1def?.display?.label ?? tr.operation;
|
|
5599
5610
|
// The connection rides the same three places it does for a
|
|
@@ -180,6 +180,15 @@
|
|
|
180
180
|
"activityType": "Curated",
|
|
181
181
|
"objectName": "QueryEntityRecordsCurated",
|
|
182
182
|
"path": "uipath-uipath-dataservice/query-entity-records@1.0.0.json"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"nodeType": "uipath.connector.uipath-uipath-dataservice.update-entity-record",
|
|
186
|
+
"version": "1.0.0",
|
|
187
|
+
"connectorKey": "uipath-uipath-dataservice",
|
|
188
|
+
"label": "Update Entity Record",
|
|
189
|
+
"activityType": "Curated",
|
|
190
|
+
"objectName": "UpdateEntityRecordV2",
|
|
191
|
+
"path": "uipath-uipath-dataservice/update-entity-record@1.0.0.json"
|
|
183
192
|
}
|
|
184
193
|
]
|
|
185
194
|
}
|