@uipath/maestro-builder-sdk 6.68.2 → 6.68.3
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/case/check.js +6 -1
- package/dist/case/decompile.d.ts +1 -0
- package/dist/case/decompile.js +23 -0
- package/dist/case/preserve.d.ts +32 -0
- package/dist/case/preserve.js +41 -0
- package/dist/case/serialize.js +6 -4
- package/dist/core/bindings.d.ts +12 -0
- package/dist/core/bindings.js +25 -3
- package/package.json +2 -2
package/dist/case/check.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ruleShapeProblems } from './rule-options.js';
|
|
|
3
3
|
import { types } from '../core/expr.js';
|
|
4
4
|
import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS, authoredCaseVersion, caseVersionMismatch } from './format-profile.js';
|
|
5
5
|
import { schemaVersionRefusal } from '../schema-version.js';
|
|
6
|
-
import { caseJsonPreservation, caseJsonPreservationErrors } from './preserve.js';
|
|
6
|
+
import { caseJsonPreservation, caseJsonPreservationErrors, preservedBindings } from './preserve.js';
|
|
7
7
|
import { EQUALS_EXPR_DIALECT, checkBindingLabels, checkConnectorContract, checkConnectorLookups, checkConnectorSchema, } from '../core/connector-checks.js';
|
|
8
8
|
import { checkEventResolution } from '../core/event-checks.js';
|
|
9
9
|
import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_HYBRID_UNSUPPORTED, externalHybridRefusal, isExternalExecutionMode } from './external.js';
|
|
@@ -25,6 +25,11 @@ const ILLEGAL = [];
|
|
|
25
25
|
*/
|
|
26
26
|
export function check(built, opts = {}) {
|
|
27
27
|
const diags = [];
|
|
28
|
+
// The same registry `serialize` resolves against, so the two agree on which
|
|
29
|
+
// labels a decompiled source's preserved binding rows answer.
|
|
30
|
+
const bindings = preservedBindings(opts.bindings, caseJsonPreservation(built));
|
|
31
|
+
if (bindings !== opts.bindings)
|
|
32
|
+
opts = { ...opts, bindings };
|
|
28
33
|
for (const message of caseJsonPreservationErrors(caseJsonPreservation(built)))
|
|
29
34
|
diags.push({
|
|
30
35
|
level: 'error',
|
package/dist/case/decompile.d.ts
CHANGED
package/dist/case/decompile.js
CHANGED
|
@@ -1315,6 +1315,26 @@ function identityPreservation(plan) {
|
|
|
1315
1315
|
])),
|
|
1316
1316
|
};
|
|
1317
1317
|
}
|
|
1318
|
+
/**
|
|
1319
|
+
* The root connection/folder rows a recompile needs to resolve the labels
|
|
1320
|
+
* decompile names connectors by. `bindingLabel` writes such a label as the
|
|
1321
|
+
* row's `id` (`connection: "bOC1"`), and that id means nothing without the row.
|
|
1322
|
+
* Kept: `resource: "Connection"` rows with a key other than their own id. Not
|
|
1323
|
+
* kept: a row `serialize` minted offline (decompile writes its authored label,
|
|
1324
|
+
* and a recompile mints the same row again) and a row keyed by its own id
|
|
1325
|
+
* (a placeholder, which `Bindings` would ignore anyway).
|
|
1326
|
+
*/
|
|
1327
|
+
function preservedBindingRows(plan) {
|
|
1328
|
+
return (plan.bindings ?? []).filter((row) => {
|
|
1329
|
+
const r = row;
|
|
1330
|
+
if (typeof r.id !== 'string' || r.resource !== 'Connection')
|
|
1331
|
+
return false;
|
|
1332
|
+
if (offlineBindingLabel(r) !== undefined)
|
|
1333
|
+
return false;
|
|
1334
|
+
const key = r.resourceKey ?? r.default;
|
|
1335
|
+
return typeof key === 'string' && key !== '' && key !== r.id;
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1318
1338
|
/**
|
|
1319
1339
|
* Everything the ORIGINAL document owns and the typed builder does not model —
|
|
1320
1340
|
* ids, layout, platform metadata, annotation nodes, node order, designer
|
|
@@ -1436,6 +1456,9 @@ export function collectPreservation(plan) {
|
|
|
1436
1456
|
preservation.omitTaskElementIds = omitTaskElementIds;
|
|
1437
1457
|
if (omitStagePositions.length)
|
|
1438
1458
|
preservation.omitStagePositions = omitStagePositions;
|
|
1459
|
+
const bindingRows = preservedBindingRows(plan);
|
|
1460
|
+
if (bindingRows.length)
|
|
1461
|
+
preservation.bindings = bindingRows;
|
|
1439
1462
|
const variableKnown = new Set(['id', 'name', 'type', 'default', 'body', '_jsonSchema', 'elementId', 'var', 'custom']);
|
|
1440
1463
|
const variableFields = {};
|
|
1441
1464
|
const legacyVariableDefaults = {};
|
package/dist/case/preserve.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { BuiltCase } from './case-sdk.js';
|
|
2
|
+
import { Bindings } from '../core/bindings.js';
|
|
3
|
+
import type { BindingsView } from '../core/binding-messages.js';
|
|
2
4
|
export type PreservedVariableLane = 'inputs' | 'outputs' | 'inputOutputs';
|
|
3
5
|
/**
|
|
4
6
|
* A preserved `inputs[]` / `outputs[]` slot id copied verbatim from its name is
|
|
@@ -143,11 +145,41 @@ export interface CaseJsonPreservation {
|
|
|
143
145
|
omitTaskElementIds?: PreservedTaskRef[];
|
|
144
146
|
/** Opaque wire identities aligned to typed constructs by name and position. */
|
|
145
147
|
identities?: CaseIdentityPreservation;
|
|
148
|
+
/**
|
|
149
|
+
* The original plan's connection and folder rows from root `bindings[]`: the
|
|
150
|
+
* map from the binding id decompile names a connector by
|
|
151
|
+
* (`connection: "bOC1"`) to its resource key. Compile reads them only to
|
|
152
|
+
* resolve such a label when bindings.json does not answer it (see
|
|
153
|
+
* {@link preservedBindings}); it emits a row only when a task references it.
|
|
154
|
+
* Without them, compiling the source anywhere but over the original plan
|
|
155
|
+
* wrote `resourceKey: "bOC1"`, and nothing refused it (builder-sdk#1242).
|
|
156
|
+
*/
|
|
157
|
+
bindings?: Record<string, unknown>[];
|
|
146
158
|
}
|
|
147
159
|
/** Attach decompiler-owned, non-authoring wire data to a built case. */
|
|
148
160
|
export declare function preserveCaseJson(built: BuiltCase, payload: CaseJsonPreservation): BuiltCase;
|
|
149
161
|
/** @internal Read the preservation payload attached by `preserveCaseJson`. */
|
|
150
162
|
export declare function caseJsonPreservation(built: BuiltCase): CaseJsonPreservation | undefined;
|
|
163
|
+
/**
|
|
164
|
+
* The bindings registry `check` and `serialize` resolve a decompiled source's
|
|
165
|
+
* connection and folder labels against: `bindings` plus the rows the source
|
|
166
|
+
* preserved ({@link CaseJsonPreservation.bindings}) as fallback rows. A fallback
|
|
167
|
+
* row answers only a label equal to its id, never counts as declared, and loses
|
|
168
|
+
* to bindings.json and to the plan `-o` writes over (the same rules as
|
|
169
|
+
* `Bindings.withFallback`). A row `serialize` minted offline is a placeholder for
|
|
170
|
+
* its label, not a key, so it answers nothing.
|
|
171
|
+
*
|
|
172
|
+
* A `Bindings` comes back as a new `Bindings`. Any other {@link BindingsView}
|
|
173
|
+
* (an SDK caller's own, or a `Bindings` from a second copy of the package) is
|
|
174
|
+
* wrapped, so the preserved rows answer there too instead of being dropped.
|
|
175
|
+
*
|
|
176
|
+
* @param bindings - The registry the caller loaded, if any.
|
|
177
|
+
* @param payload - The source's preservation payload, if any.
|
|
178
|
+
* @returns A registry with the preserved rows, or `bindings` unchanged when
|
|
179
|
+
* there are none.
|
|
180
|
+
*/
|
|
181
|
+
export declare function preservedBindings(bindings: Bindings | undefined, payload: CaseJsonPreservation | undefined): Bindings | undefined;
|
|
182
|
+
export declare function preservedBindings(bindings: BindingsView | undefined, payload: CaseJsonPreservation | undefined): BindingsView | undefined;
|
|
151
183
|
/** @internal Validate that preservation cannot impersonate typed authoring. */
|
|
152
184
|
export declare function caseJsonPreservationErrors(payload: CaseJsonPreservation | undefined): string[];
|
|
153
185
|
export {};
|
package/dist/case/preserve.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { stableId } from '../core/stable-id.js';
|
|
2
|
+
import { Bindings } from '../core/bindings.js';
|
|
3
|
+
import { offlineBindingLabel } from './ids.js';
|
|
2
4
|
/**
|
|
3
5
|
* A preserved `inputs[]` / `outputs[]` slot id copied verbatim from its name is
|
|
4
6
|
* the STRICT_FORMAL_ARG_ID defect, not an identity to keep; the minted id stands.
|
|
@@ -36,6 +38,30 @@ export function preserveCaseJson(built, payload) {
|
|
|
36
38
|
export function caseJsonPreservation(built) {
|
|
37
39
|
return preserved.get(built);
|
|
38
40
|
}
|
|
41
|
+
export function preservedBindings(bindings, payload) {
|
|
42
|
+
const rows = payload?.bindings;
|
|
43
|
+
if (!Array.isArray(rows) || rows.length === 0)
|
|
44
|
+
return bindings;
|
|
45
|
+
const minted = (row) => offlineBindingLabel(row) !== undefined;
|
|
46
|
+
if (bindings === undefined || bindings instanceof Bindings)
|
|
47
|
+
return (bindings ?? new Bindings()).withFallbackRows(rows, minted);
|
|
48
|
+
return withPreservedRows(bindings, new Bindings().withFallbackRows(rows, minted));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `view` with `extra`'s fallback rows behind it: `view` answers first, and a
|
|
52
|
+
* label only `extra` answers is a fallback label (`fromFallback`), exactly as
|
|
53
|
+
* `Bindings` treats its own fallback rows.
|
|
54
|
+
*/
|
|
55
|
+
function withPreservedRows(view, extra) {
|
|
56
|
+
const primary = (name) => view.resolve(name) !== undefined || view.entry?.(name) !== undefined
|
|
57
|
+
|| (name !== undefined && (view.declared?.() ?? []).includes(name));
|
|
58
|
+
return {
|
|
59
|
+
resolve: (name) => view.resolve(name) ?? (primary(name) ? undefined : extra.resolve(name)),
|
|
60
|
+
...(view.declared ? { declared: () => view.declared() } : {}),
|
|
61
|
+
entry: (name) => view.entry?.(name) ?? (primary(name) ? undefined : extra.entry(name)),
|
|
62
|
+
fromFallback: (name) => view.fromFallback?.(name) === true || (!primary(name) && extra.fromFallback(name)),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
39
65
|
const TOP_LEVEL_KEYS = new Set([
|
|
40
66
|
'id', 'name', 'description', 'version', 'bindings', 'variables', 'metadata', 'nodes', 'edges', 'layout',
|
|
41
67
|
]);
|
|
@@ -123,6 +149,21 @@ export function caseJsonPreservationErrors(payload) {
|
|
|
123
149
|
else if (TASK_KEYS.has(field))
|
|
124
150
|
errors.push(`task "${entry.task}" field "${field}" is owned by the typed Case serializer`);
|
|
125
151
|
}
|
|
152
|
+
if (payload.bindings !== undefined) {
|
|
153
|
+
if (!Array.isArray(payload.bindings))
|
|
154
|
+
errors.push('preserved "bindings" must be an array of root binding rows');
|
|
155
|
+
else
|
|
156
|
+
payload.bindings.forEach((row, index) => {
|
|
157
|
+
const r = row;
|
|
158
|
+
const key = r && typeof r === 'object' ? r.resourceKey ?? r.default : undefined;
|
|
159
|
+
if (!r || typeof r !== 'object' || typeof r.id !== 'string' || r.id === '')
|
|
160
|
+
errors.push(`preserved binding row ${index + 1} has no string id`);
|
|
161
|
+
else if (r.resource !== 'Connection')
|
|
162
|
+
errors.push(`preserved binding row "${r.id}" is not a Connection row (only connection and folder rows are preserved)`);
|
|
163
|
+
else if (typeof key !== 'string' || key === '' || key === r.id)
|
|
164
|
+
errors.push(`preserved binding row "${r.id}" carries no resource key other than its own id`);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
126
167
|
for (const [index, fields] of (payload.triggerDataFields ?? []).entries())
|
|
127
168
|
for (const field of Object.keys(fields))
|
|
128
169
|
if (!PRESERVED_TRIGGER_DATA_KEYS.has(field))
|
package/dist/case/serialize.js
CHANGED
|
@@ -25,7 +25,7 @@ import { isResourceLabelRefusal, resolveResourceRef, resourceIdentity } from './
|
|
|
25
25
|
import { ownEntry } from '../core/own-entry.js';
|
|
26
26
|
import { stableId } from '../core/stable-id.js';
|
|
27
27
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
28
|
-
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
28
|
+
import { caseJsonPreservation, caseJsonPreservationErrors, preservedBindings, } from './preserve.js';
|
|
29
29
|
import { businessEventProblems } from './business-event-shape.js';
|
|
30
30
|
import { readEventFilterLeaf, eventFilterTreeLeaf } from '../core/event-filters.js';
|
|
31
31
|
import { responseJsonSchema } from '../core/connector-response-schema.js';
|
|
@@ -101,7 +101,9 @@ export function serialize(built, opts = {}) {
|
|
|
101
101
|
stageIdByLabel: new Map(),
|
|
102
102
|
taskIdByKey: new Map(),
|
|
103
103
|
library: opts.library,
|
|
104
|
-
|
|
104
|
+
// A decompiled source carries its plan's connection rows: they answer the
|
|
105
|
+
// binding-id labels decompile wrote (`connection: "bOC1"`).
|
|
106
|
+
bindings: preservedBindings(opts.bindings, caseJsonPreservation(built)),
|
|
105
107
|
bindingSink: new Map(),
|
|
106
108
|
ids,
|
|
107
109
|
offlineBindingIds: new Map(),
|
|
@@ -1875,7 +1877,7 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
|
|
|
1875
1877
|
const refused = bindingLabelRefusal(resolver.bindings, name, site.attribute, site.where, site.target);
|
|
1876
1878
|
if (refused)
|
|
1877
1879
|
throw refused;
|
|
1878
|
-
const entry = resolver.bindings?.entry(name);
|
|
1880
|
+
const entry = resolver.bindings?.entry?.(name);
|
|
1879
1881
|
const resourceKey = entry?.resourceKey ?? entry?.default ?? name;
|
|
1880
1882
|
// Only a label with no bindings.json entry gets a minted id: an entry's
|
|
1881
1883
|
// `resourceKey` is the real key, so its id (or its name) cannot clash with it.
|
|
@@ -1912,7 +1914,7 @@ function folderBindingRef(resolver, name, connection, site) {
|
|
|
1912
1914
|
const refused = bindingLabelRefusal(resolver.bindings, name, site.attribute, site.where, site.target);
|
|
1913
1915
|
if (refused)
|
|
1914
1916
|
throw refused;
|
|
1915
|
-
const entry = resolver.bindings?.entry(name);
|
|
1917
|
+
const entry = resolver.bindings?.entry?.(name);
|
|
1916
1918
|
const baseId = entry
|
|
1917
1919
|
? String(entry.id ?? name)
|
|
1918
1920
|
: offlineBindingId(resolver, offlineBindingSeed('Connection', 'folderKey', name, connection.resourceKey));
|
package/dist/core/bindings.d.ts
CHANGED
|
@@ -26,6 +26,18 @@ export declare class Bindings {
|
|
|
26
26
|
* @returns This registry, for chaining.
|
|
27
27
|
*/
|
|
28
28
|
withFallback(file?: string, isPlaceholder?: (row: Record<string, unknown>) => boolean): this;
|
|
29
|
+
/**
|
|
30
|
+
* A NEW registry: this one's entries and fallback rows, plus `rows` as more
|
|
31
|
+
* fallback rows (same rules as {@link withFallback}; a row whose `id` is
|
|
32
|
+
* already a fallback row is skipped, so earlier fallbacks win). This registry
|
|
33
|
+
* is not changed, so a caller's `Bindings` can be shared across compiles.
|
|
34
|
+
*
|
|
35
|
+
* @param rows - Root binding rows, e.g. the ones a decompiled Case source carries.
|
|
36
|
+
* @param isPlaceholder - As for {@link withFallback}.
|
|
37
|
+
* @returns The new registry.
|
|
38
|
+
*/
|
|
39
|
+
withFallbackRows(rows: readonly unknown[], isPlaceholder?: (row: Record<string, unknown>) => boolean): Bindings;
|
|
40
|
+
private addFallbackRows;
|
|
29
41
|
private primary;
|
|
30
42
|
/**
|
|
31
43
|
* The fallback row whose `id` is `name`. A row whose key is its own id
|
package/dist/core/bindings.js
CHANGED
|
@@ -44,11 +44,33 @@ export class Bindings {
|
|
|
44
44
|
catch {
|
|
45
45
|
return this; // a fallback is optional; an unreadable one adds nothing
|
|
46
46
|
}
|
|
47
|
+
this.addFallbackRows(normalizeBindings(parsed), isPlaceholder);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A NEW registry: this one's entries and fallback rows, plus `rows` as more
|
|
52
|
+
* fallback rows (same rules as {@link withFallback}; a row whose `id` is
|
|
53
|
+
* already a fallback row is skipped, so earlier fallbacks win). This registry
|
|
54
|
+
* is not changed, so a caller's `Bindings` can be shared across compiles.
|
|
55
|
+
*
|
|
56
|
+
* @param rows - Root binding rows, e.g. the ones a decompiled Case source carries.
|
|
57
|
+
* @param isPlaceholder - As for {@link withFallback}.
|
|
58
|
+
* @returns The new registry.
|
|
59
|
+
*/
|
|
60
|
+
withFallbackRows(rows, isPlaceholder) {
|
|
61
|
+
const copy = new Bindings();
|
|
62
|
+
copy.list = this.list;
|
|
63
|
+
copy.fallback = [...this.fallback];
|
|
64
|
+
copy.addFallbackRows(rows, isPlaceholder);
|
|
65
|
+
return copy;
|
|
66
|
+
}
|
|
67
|
+
addFallbackRows(rows, isPlaceholder) {
|
|
47
68
|
const ids = new Set(this.fallback.map((x) => x?.id));
|
|
48
|
-
for (const entry of
|
|
49
|
-
if (typeof entry?.id === 'string' && !ids.has(entry.id) && !isPlaceholder?.(entry))
|
|
69
|
+
for (const entry of rows)
|
|
70
|
+
if (typeof entry?.id === 'string' && !ids.has(entry.id) && !isPlaceholder?.(entry)) {
|
|
50
71
|
this.fallback.push(entry);
|
|
51
|
-
|
|
72
|
+
ids.add(entry.id);
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
primary(name) {
|
|
54
76
|
return this.list.find((x) => x.name === name || x.id === name);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.68.
|
|
3
|
+
"version": "6.68.3",
|
|
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": "
|
|
103
|
+
"gitref": "7f50084300a8c68552127c4e1ab51a3cb56a5869"
|
|
104
104
|
}
|