@uipath/maestro-builder-sdk 6.70.0 → 6.70.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Connector input fields a decompiled task CARRIES — the plan's own field
3
+ * declarations for the ones the connector library does not list (#1362).
4
+ *
5
+ * The published library is a snapshot, and a connector keeps shipping after it
6
+ * is taken. Studio Web saves a connector activity against the LIVE connector,
7
+ * and writes that connector's field list into the activity's configuration
8
+ * (`optionalConfiguration.fieldsContainer.inputFields`). So a Designer plan can
9
+ * use a field the library has never heard of: Outlook `get-email-list` saved at
10
+ * connector 1.47.0 carries `bodyFormat: "html"`, and the library's entry has no
11
+ * `bodyFormat`. With the library as the only field authority, `check` and
12
+ * `compile` refused that untouched field as `unknown input`, and the easy way
13
+ * past the refusal was to delete it: a silent change to the task.
14
+ *
15
+ * Decompile now copies the saved declaration of each field the library lacks
16
+ * into the task's source (`carriedFields`), and `check` and `compile` read the
17
+ * operation's fields as the library's plus the carried ones. This is the same
18
+ * idea as Flow's carried node definitions (`core/carried-definitions.ts`): the
19
+ * file's own definition is the third source, after the SDK and the library.
20
+ *
21
+ * It only ever ADDS a name. A field the library declares keeps the library's
22
+ * type, location and `required`, whatever the carried copy says, so a carried
23
+ * list cannot relax a check the library makes. And a carried field is accepted,
24
+ * never demanded: the library's own fields are the required contract.
25
+ *
26
+ * For instance, with `carriedFields: [{ name: 'bodyFormat', type: 'string',
27
+ * location: 'query' }]`, the input `{ bodyFormat: 'html' }` compiles to
28
+ * `queryParameters.bodyFormat = "html"`; without it, compile refuses it.
29
+ */
30
+ import type { FieldLocation, ResolvedConnector } from './library.js';
31
+ /** Where a carried field rides on the wire: the request body, the query string or the path. */
32
+ export type CarriedFieldLocation = Extract<FieldLocation, 'body' | 'query' | 'path'>;
33
+ /**
34
+ * One input field a connector task carries from the plan it was decompiled from.
35
+ *
36
+ * Written by decompile, copied from the activity's saved field list. It is not an
37
+ * authoring surface: an input the connector library already declares is checked
38
+ * against the library, whatever is carried.
39
+ */
40
+ export interface CarriedConnectorField {
41
+ /** The field's name, as the saved field list names it, e.g. `bodyFormat`. */
42
+ name: string;
43
+ /** The wire slot the saved field list names (`fieldLocation`). */
44
+ location: CarriedFieldLocation;
45
+ /** `string`, `number`, `boolean`, `array` or `object`, when the saved field declares one. */
46
+ type?: string;
47
+ }
48
+ /**
49
+ * Why `fields` cannot be carried, or `undefined` when it can.
50
+ *
51
+ * For instance `[{ name: 'bodyFormat', location: 'header' }]` is refused: a
52
+ * header is no slot the connector wire has.
53
+ */
54
+ export declare function carriedConnectorFieldsRefusal(fields: unknown, where: string): string | undefined;
55
+ /**
56
+ * `rc` with each carried field the library does not declare appended to its
57
+ * fields, as an optional input. A name the library declares keeps the library's
58
+ * declaration. `fields` must have passed {@link carriedConnectorFieldsRefusal}.
59
+ */
60
+ export declare function withCarriedFields(rc: ResolvedConnector, fields: readonly CarriedConnectorField[] | undefined): ResolvedConnector;
61
+ /**
62
+ * The fields a saved activity configuration declares that `rc` does not, as
63
+ * decompile carries them: from `optionalConfiguration.fieldsContainer.inputFields`,
64
+ * request fields only, in the saved order. Empty when the configuration has no
65
+ * field list (an SDK-compiled plan writes the essential half only), or every
66
+ * saved field is in the library. A saved field on a slot the connector wire has
67
+ * no place for (a `header`) is not carried.
68
+ *
69
+ * @param configuration - The parsed `=jsonString:` configuration blob.
70
+ */
71
+ export declare function savedFieldsMissingFromLibrary(configuration: unknown, rc: ResolvedConnector): CarriedConnectorField[];
@@ -0,0 +1,80 @@
1
+ import { ownEntry } from './own-entry.js';
2
+ const LOCATIONS = { body: 'body', query: 'query', path: 'path' };
3
+ const TYPES = {
4
+ string: 'string', boolean: 'boolean', number: 'number', integer: 'number', array: 'array', object: 'object',
5
+ };
6
+ /**
7
+ * Why `fields` cannot be carried, or `undefined` when it can.
8
+ *
9
+ * For instance `[{ name: 'bodyFormat', location: 'header' }]` is refused: a
10
+ * header is no slot the connector wire has.
11
+ */
12
+ export function carriedConnectorFieldsRefusal(fields, where) {
13
+ if (fields === undefined)
14
+ return undefined;
15
+ if (!Array.isArray(fields))
16
+ return `${where}: carriedFields must be an array of { name, location, type? } fields.`;
17
+ const seen = new Set();
18
+ for (const field of fields) {
19
+ const f = field;
20
+ if (!f || typeof f !== 'object' || typeof f.name !== 'string' || !f.name)
21
+ return `${where}: a carried field must name itself with a non-empty string.`;
22
+ if (typeof f.location !== 'string' || ownEntry(LOCATIONS, f.location) === undefined)
23
+ return `${where}: carried field "${f.name}" has location ${JSON.stringify(f.location)}; expected "body", "query" or "path".`;
24
+ if (f.type !== undefined && (typeof f.type !== 'string' || !Object.values(TYPES).includes(f.type)))
25
+ return `${where}: carried field "${f.name}" has type ${JSON.stringify(f.type)}; expected "string", "number", "boolean", "array" or "object".`;
26
+ const extra = Object.keys(f).find((key) => key !== 'name' && key !== 'location' && key !== 'type');
27
+ if (extra !== undefined)
28
+ return `${where}: carried field "${f.name}" has unsupported key "${extra}".`;
29
+ if (seen.has(f.name))
30
+ return `${where}: carried field "${f.name}" is listed twice.`;
31
+ seen.add(f.name);
32
+ }
33
+ return undefined;
34
+ }
35
+ /**
36
+ * `rc` with each carried field the library does not declare appended to its
37
+ * fields, as an optional input. A name the library declares keeps the library's
38
+ * declaration. `fields` must have passed {@link carriedConnectorFieldsRefusal}.
39
+ */
40
+ export function withCarriedFields(rc, fields) {
41
+ if (!fields?.length)
42
+ return rc;
43
+ const known = new Set(rc.fields.map((f) => f.name));
44
+ const added = fields
45
+ .filter((f) => !known.has(f.name))
46
+ .map((f) => ({ name: f.name, location: f.location, required: false, ...(f.type !== undefined ? { type: f.type } : {}) }));
47
+ return added.length ? { ...rc, fields: [...rc.fields, ...added] } : rc;
48
+ }
49
+ /**
50
+ * The fields a saved activity configuration declares that `rc` does not, as
51
+ * decompile carries them: from `optionalConfiguration.fieldsContainer.inputFields`,
52
+ * request fields only, in the saved order. Empty when the configuration has no
53
+ * field list (an SDK-compiled plan writes the essential half only), or every
54
+ * saved field is in the library. A saved field on a slot the connector wire has
55
+ * no place for (a `header`) is not carried.
56
+ *
57
+ * @param configuration - The parsed `=jsonString:` configuration blob.
58
+ */
59
+ export function savedFieldsMissingFromLibrary(configuration, rc) {
60
+ const inputFields = configuration
61
+ ?.optionalConfiguration?.fieldsContainer?.inputFields;
62
+ if (!Array.isArray(inputFields))
63
+ return [];
64
+ const known = new Set(rc.fields.map((f) => f.name));
65
+ const out = [];
66
+ for (const raw of inputFields) {
67
+ if (!raw || typeof raw !== 'object')
68
+ continue;
69
+ const f = raw;
70
+ if (typeof f.name !== 'string' || !f.name || known.has(f.name) || f.request === false)
71
+ continue;
72
+ const location = typeof f.fieldLocation === 'string' ? ownEntry(LOCATIONS, f.fieldLocation) : undefined;
73
+ if (!location)
74
+ continue;
75
+ known.add(f.name);
76
+ const type = typeof f.type === 'string' ? ownEntry(TYPES, f.type) : undefined;
77
+ out.push({ name: f.name, location, ...(type !== undefined ? { type } : {}) });
78
+ }
79
+ return out;
80
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.70.0",
3
+ "version": "6.70.2",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -100,5 +100,5 @@
100
100
  "@types/node": "^22.7.0",
101
101
  "esbuild": "^0.28.1"
102
102
  },
103
- "gitref": "990446f9254b96a4cb0cbfc1a3ec7f99deaabe5e"
103
+ "gitref": "f3203eee21b892b6b70e41a5bf791aa30fdc0fc2"
104
104
  }