@uipath/maestro-builder-sdk 6.66.2 → 6.66.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/decompile.js +31 -18
- package/dist/case/merge.d.ts +3 -3
- package/dist/case/merge.js +12 -8
- package/dist/case/preserve.d.ts +12 -0
- package/dist/case/preserve.js +21 -0
- package/dist/case/serialize.d.ts +16 -0
- package/dist/case/serialize.js +271 -63
- package/package.json +2 -2
package/dist/case/decompile.js
CHANGED
|
@@ -4,7 +4,7 @@ import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
|
4
4
|
import { EXTERNAL_TASK_CONTEXT, externalDescriptorRefusal, externalHybridRefusal, externalServiceType, isExternalExecutionMode } from './external.js';
|
|
5
5
|
import { preserveSchemaVersion } from '../schema-version.js';
|
|
6
6
|
import { ownEntry } from '../core/own-entry.js';
|
|
7
|
-
import { isUnrestorableSlotId } from './preserve.js';
|
|
7
|
+
import { isUnrestorableSlotId, taskFingerprint } from './preserve.js';
|
|
8
8
|
import { isInSolutionKey, SOLUTION_FOLDER } from './resource-identity.js';
|
|
9
9
|
import { offlineBindingLabel } from './ids.js';
|
|
10
10
|
const TASK_KIND_METHOD = {
|
|
@@ -1172,7 +1172,14 @@ function refuseUnsupportedAuthoring(plan) {
|
|
|
1172
1172
|
function conditionIdentity(condition) {
|
|
1173
1173
|
return {
|
|
1174
1174
|
...(condition.id ? { id: condition.id } : {}),
|
|
1175
|
-
rules: (condition.rules ?? []).map((group) => group.map((rule) => ({
|
|
1175
|
+
rules: (condition.rules ?? []).map((group) => group.map((rule) => ({
|
|
1176
|
+
...(rule.id ? { id: rule.id } : {}),
|
|
1177
|
+
// A wait-for-connector rule's rows take their ids from the plan-wide pool,
|
|
1178
|
+
// so deleting an earlier output would renumber them.
|
|
1179
|
+
...(rule.uipath?.outputs?.length
|
|
1180
|
+
? { outputs: rule.uipath.outputs.map((row) => ({ name: row.name ?? '', ...(row.id ? { id: row.id } : {}) })) }
|
|
1181
|
+
: {}),
|
|
1182
|
+
}))),
|
|
1176
1183
|
};
|
|
1177
1184
|
}
|
|
1178
1185
|
function slaIdentity(sla) {
|
|
@@ -1231,20 +1238,25 @@ function identityPreservation(plan) {
|
|
|
1231
1238
|
return {
|
|
1232
1239
|
...(plan.id ? { id: plan.id } : {}),
|
|
1233
1240
|
triggers: (plan.nodes ?? []).filter(isTrigger).map((node) => ({ ...(node.id ? { id: node.id } : {}) })),
|
|
1234
|
-
stages: (plan.nodes ?? []).filter(isStage).map((stage) =>
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
...(
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1241
|
+
stages: (plan.nodes ?? []).filter(isStage).map((stage) => {
|
|
1242
|
+
const shape = (task) => JSON.stringify([task.data?.inputs, task.data?.outputs].map((rows) => (rows ?? []).map((row) => row.name ?? '')));
|
|
1243
|
+
const shapes = (stage.data?.tasks ?? []).flat().map(shape);
|
|
1244
|
+
return {
|
|
1245
|
+
label: stage.data?.label ?? '',
|
|
1246
|
+
...(stage.id ? { id: stage.id } : {}),
|
|
1247
|
+
tasks: (stage.data?.tasks ?? []).map((lane) => lane.map((task) => ({
|
|
1248
|
+
name: task.displayName ?? '',
|
|
1249
|
+
...(task.id ? { id: task.id } : {}),
|
|
1250
|
+
entryConditions: (task.entryConditions ?? []).map(conditionIdentity),
|
|
1251
|
+
inputs: (task.data?.inputs ?? []).map((row) => ({ name: row.name ?? '', ...(row.id ? { id: row.id } : {}) })),
|
|
1252
|
+
outputs: (task.data?.outputs ?? []).map((row) => ({ name: row.name ?? '', ...(row.id ? { id: row.id } : {}) })),
|
|
1253
|
+
...(shapes.filter((other) => other === shape(task)).length > 1 ? { fingerprint: taskFingerprint(task) } : {}),
|
|
1254
|
+
}))),
|
|
1255
|
+
entryConditions: (stage.data?.entryConditions ?? []).map(conditionIdentity),
|
|
1256
|
+
exitConditions: (stage.data?.exitConditions ?? []).map(conditionIdentity),
|
|
1257
|
+
slaRules: (stage.data?.slaRules ?? []).map(slaIdentity),
|
|
1258
|
+
};
|
|
1259
|
+
}),
|
|
1248
1260
|
caseExitRules: (plan.metadata?.caseExitRules ?? []).map(conditionIdentity),
|
|
1249
1261
|
slaRules: (plan.metadata?.slaRules ?? []).map(slaIdentity),
|
|
1250
1262
|
variables: Object.fromEntries(['inputs', 'outputs', 'inputOutputs'].map((lane) => [
|
|
@@ -1374,7 +1386,6 @@ export function collectPreservation(plan) {
|
|
|
1374
1386
|
preservation.omitTaskElementIds = omitTaskElementIds;
|
|
1375
1387
|
if (omitStagePositions.length)
|
|
1376
1388
|
preservation.omitStagePositions = omitStagePositions;
|
|
1377
|
-
const produced = producedVariableNames(plan);
|
|
1378
1389
|
const variableKnown = new Set(['id', 'name', 'type', 'default', 'body', '_jsonSchema', 'elementId', 'var', 'custom']);
|
|
1379
1390
|
const variableFields = {};
|
|
1380
1391
|
const legacyVariableDefaults = {};
|
|
@@ -1390,7 +1401,9 @@ export function collectPreservation(plan) {
|
|
|
1390
1401
|
for (const field of Object.keys(fields))
|
|
1391
1402
|
if (!['subType', 'canonicalId', 'camelizedId', 'variableType', 'internal'].includes(field))
|
|
1392
1403
|
throw new Error(`variable "${row.name}" has unsupported field "${field}", which is not allowed in the collision-refusing preservation channel.`);
|
|
1393
|
-
|
|
1404
|
+
// Carried even while an output writes the variable, so deleting its last
|
|
1405
|
+
// writer keeps the flag; `applyPreservation` reads an equal value as agreement.
|
|
1406
|
+
if (lane === 'inputOutputs' && row.custom)
|
|
1394
1407
|
fields.custom = true;
|
|
1395
1408
|
const formalOutput = (plan.variables?.outputs ?? []).find((candidate) => candidate.name === row.name);
|
|
1396
1409
|
if (lane === 'inputOutputs' && formalOutput && row.default !== undefined && formalOutput.default !== row.default)
|
package/dist/case/merge.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ export type CaseDocument = Record<string, unknown>;
|
|
|
3
3
|
export interface CaseMergeOptions {
|
|
4
4
|
/**
|
|
5
5
|
* Called once per finding. Today the only finding is a construct the original
|
|
6
|
-
* carried an identity for that the edited document no longer has — a
|
|
7
|
-
* a
|
|
8
|
-
*
|
|
6
|
+
* carried an identity for that the edited document no longer has — a delete, or
|
|
7
|
+
* a rename `followRenames` could not pair — which silently drops the original's
|
|
8
|
+
* ids for that construct.
|
|
9
9
|
*/
|
|
10
10
|
warn?: (message: string) => void;
|
|
11
11
|
}
|
package/dist/case/merge.js
CHANGED
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
* merge cannot use.
|
|
23
23
|
*
|
|
24
24
|
* What it uses instead is what the preservation channel already uses: stage
|
|
25
|
-
* LABEL, task displayName, lane and position
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* LABEL, task displayName, lane and position, with `followRenames` first
|
|
26
|
+
* re-pointing a stage or task the edit renamed or moved (see its doc) so it keeps
|
|
27
|
+
* its ids. That is not a second mechanism — it is the same one, read from the
|
|
28
|
+
* original file at merge time rather than from a `preserveCaseJson(...)` payload
|
|
29
|
+
* baked into the source.
|
|
28
30
|
*
|
|
29
31
|
* ## What each side decides
|
|
30
32
|
*
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
* cannot drift from it.
|
|
48
50
|
*/
|
|
49
51
|
import { collectPreservation } from './decompile.js';
|
|
50
|
-
import { applyPreservation } from './serialize.js';
|
|
52
|
+
import { applyPreservation, followRenames } from './serialize.js';
|
|
51
53
|
import { jsonClone } from '../core/json-clone.js';
|
|
52
54
|
/** Stage labels in a document, in order. */
|
|
53
55
|
function stageLabels(document) {
|
|
@@ -79,8 +81,9 @@ function warnOrphanedIdentities(preservation, edited, warn) {
|
|
|
79
81
|
for (const stage of preservation.identities?.stages ?? []) {
|
|
80
82
|
if (!labels.has(stage.label)) {
|
|
81
83
|
warn(`stage "${stage.label}" is in the original but not in the edited case, so its ids are dropped. `
|
|
82
|
-
+ `
|
|
83
|
-
+ `
|
|
84
|
+
+ `A renamed stage keeps its ids while it still holds one of its tasks by name, or when the edit `
|
|
85
|
+
+ `leaves as many new stages as it removed. Neither holds here, so if this was a RENAME, the renamed `
|
|
86
|
+
+ `stage gets a new id and every reference to the old one goes with it: keep a task's name, or keep the label.`);
|
|
84
87
|
continue;
|
|
85
88
|
}
|
|
86
89
|
const present = tasks.get(stage.label) ?? new Set();
|
|
@@ -88,7 +91,8 @@ function warnOrphanedIdentities(preservation, edited, warn) {
|
|
|
88
91
|
for (const task of lane)
|
|
89
92
|
if (!present.has(task.name))
|
|
90
93
|
warn(`task "${task.name}" in stage "${stage.label}" is in the original but not in the edited case, `
|
|
91
|
-
+ `so its ids are dropped. A
|
|
94
|
+
+ `so its ids are dropped. A renamed or moved task keeps its ids only when its input and output `
|
|
95
|
+
+ `rows keep their names; with those changed too, a rename reads the same as a delete.`);
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
/**
|
|
@@ -102,7 +106,7 @@ export function mergeCase(original, edited, options = {}) {
|
|
|
102
106
|
if (!preservation)
|
|
103
107
|
return jsonClone(edited);
|
|
104
108
|
if (options.warn)
|
|
105
|
-
warnOrphanedIdentities(preservation, edited, options.warn);
|
|
109
|
+
warnOrphanedIdentities(followRenames(edited, preservation), edited, options.warn);
|
|
106
110
|
// `applyPreservation` is what `compile` runs with the payload a source
|
|
107
111
|
// carries. Handing it the ORIGINAL's payload and the EDITED graph is the whole
|
|
108
112
|
// merge: same operation, different provenance.
|
package/dist/case/preserve.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ interface ConditionIdentity {
|
|
|
33
33
|
id?: string;
|
|
34
34
|
rules?: Array<Array<{
|
|
35
35
|
id?: string;
|
|
36
|
+
outputs?: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
id?: string;
|
|
39
|
+
}>;
|
|
36
40
|
}>>;
|
|
37
41
|
}
|
|
38
42
|
interface SlaIdentity {
|
|
@@ -56,11 +60,19 @@ interface StageIdentity {
|
|
|
56
60
|
name: string;
|
|
57
61
|
id?: string;
|
|
58
62
|
}>;
|
|
63
|
+
/** `taskFingerprint`, for a task a sibling shares its row names with. */
|
|
64
|
+
fingerprint?: string;
|
|
59
65
|
}>>;
|
|
60
66
|
entryConditions?: ConditionIdentity[];
|
|
61
67
|
exitConditions?: ConditionIdentity[];
|
|
62
68
|
slaRules?: SlaIdentity[];
|
|
63
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* A task less its rows, its ids and every display name (a condition's defaults
|
|
72
|
+
* to its task's): what renaming it leaves alone, so a rename beside a deleted
|
|
73
|
+
* sibling of the same shape can be told from the delete.
|
|
74
|
+
*/
|
|
75
|
+
export declare function taskFingerprint(task: object): string;
|
|
64
76
|
interface CaseIdentityPreservation {
|
|
65
77
|
id?: string;
|
|
66
78
|
triggers?: Array<{
|
package/dist/case/preserve.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stableId } from '../core/stable-id.js';
|
|
1
2
|
/**
|
|
2
3
|
* A preserved `inputs[]` / `outputs[]` slot id copied verbatim from its name is
|
|
3
4
|
* the STRICT_FORMAL_ARG_ID defect, not an identity to keep; the minted id stands.
|
|
@@ -5,6 +6,26 @@
|
|
|
5
6
|
export function isUnrestorableSlotId(lane, row) {
|
|
6
7
|
return lane !== 'inputOutputs' && typeof row.id === 'string' && row.id === row.name;
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A task less its rows, its ids and every display name (a condition's defaults
|
|
11
|
+
* to its task's): what renaming it leaves alone, so a rename beside a deleted
|
|
12
|
+
* sibling of the same shape can be told from the delete.
|
|
13
|
+
*/
|
|
14
|
+
export function taskFingerprint(task) {
|
|
15
|
+
const canonical = (value) => {
|
|
16
|
+
if (Array.isArray(value))
|
|
17
|
+
return value.map(canonical);
|
|
18
|
+
if (!value || typeof value !== 'object')
|
|
19
|
+
return value;
|
|
20
|
+
return Object.fromEntries(Object.entries(value)
|
|
21
|
+
.filter(([key]) => key !== 'id' && key !== 'elementId' && key !== 'displayName')
|
|
22
|
+
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
23
|
+
.map(([key, inner]) => [key, canonical(inner)]));
|
|
24
|
+
};
|
|
25
|
+
const { data, ...rest } = task;
|
|
26
|
+
const { inputs: _inputs, outputs: _outputs, ...fields } = data ?? {};
|
|
27
|
+
return stableId(JSON.stringify(canonical({ ...rest, data: fields })));
|
|
28
|
+
}
|
|
8
29
|
const preserved = new WeakMap();
|
|
9
30
|
/** Attach decompiler-owned, non-authoring wire data to a built case. */
|
|
10
31
|
export function preserveCaseJson(built, payload) {
|
package/dist/case/serialize.d.ts
CHANGED
|
@@ -31,3 +31,19 @@ export interface ApplyPreservationOptions {
|
|
|
31
31
|
* same operation compile performs with the payload the source carries.
|
|
32
32
|
*/
|
|
33
33
|
export declare function applyPreservation(result: Record<string, unknown>, preservation: CaseJsonPreservation | undefined, options?: ApplyPreservationOptions): Record<string, unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* The payload with each stage label and task name an edit renamed rewritten to
|
|
36
|
+
* the one compiled, so a renamed stage or task keeps its ids and wire fields
|
|
37
|
+
* instead of reading as a delete plus an add. Stages left over on both sides
|
|
38
|
+
* pair by the most task names shared, then the fewest not shared, then in order
|
|
39
|
+
* when as many are left on each side; a task left over pairs with one in the
|
|
40
|
+
* same stage whose input and output rows have the same names, and a task gone
|
|
41
|
+
* from its stage that another stage now holds under the same name and rows
|
|
42
|
+
* moved there.
|
|
43
|
+
*
|
|
44
|
+
* `wanted` is the payload's side (identities read from the original plan),
|
|
45
|
+
* `compiled` this compile's. Per stage, `missing` tasks are the payload's that
|
|
46
|
+
* the compiled stage no longer names, `extra` tasks the compiled stage's that
|
|
47
|
+
* the payload does not.
|
|
48
|
+
*/
|
|
49
|
+
export declare function followRenames(result: Record<string, unknown>, preservation: CaseJsonPreservation): CaseJsonPreservation;
|
package/dist/case/serialize.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* name) are resolved here to the generated ids.
|
|
10
10
|
*/
|
|
11
11
|
import { IdGen, offlineBindingSeed } from './ids.js';
|
|
12
|
-
import { isUnrestorableSlotId } from './preserve.js';
|
|
12
|
+
import { isUnrestorableSlotId, taskFingerprint } from './preserve.js';
|
|
13
13
|
import { v31TaskSets } from './task-sets.js';
|
|
14
14
|
import { camelizeName, defaultActionOutputVar } from './action-output-var.js';
|
|
15
15
|
import { buildConnectorInputs, nestConnectorBody, replayInputsOf, transportHttpMethod } from '../core/connector-inputs.js';
|
|
@@ -23,6 +23,7 @@ import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_HYBRID_UNSUPPORTED, ex
|
|
|
23
23
|
import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS } from './format-profile.js';
|
|
24
24
|
import { isResourceLabelRefusal, resolveResourceRef, resourceIdentity } from './resource-identity.js';
|
|
25
25
|
import { ownEntry } from '../core/own-entry.js';
|
|
26
|
+
import { stableId } from '../core/stable-id.js';
|
|
26
27
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
27
28
|
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
28
29
|
import { businessEventProblems } from './business-event-shape.js';
|
|
@@ -30,6 +31,13 @@ import { readEventFilterLeaf, eventFilterTreeLeaf } from '../core/event-filters.
|
|
|
30
31
|
import { responseJsonSchema } from '../core/connector-response-schema.js';
|
|
31
32
|
import { ruleShapeProblems } from './rule-options.js';
|
|
32
33
|
import { CompileRefusal } from '../core/compile-refusal.js';
|
|
34
|
+
/** The ids a serialize pass hashed from element ids, by the document it returned. */
|
|
35
|
+
const ELEMENT_SEEDED_IDS = new WeakMap();
|
|
36
|
+
function elementSeededId(resolver, elementId, suffix) {
|
|
37
|
+
const id = stableId(`${elementId}${suffix}`);
|
|
38
|
+
resolver.elementSeededIds.push({ elementId, suffix, id });
|
|
39
|
+
return id;
|
|
40
|
+
}
|
|
33
41
|
/**
|
|
34
42
|
* Condition `displayName` allocator.
|
|
35
43
|
*
|
|
@@ -102,6 +110,7 @@ export function serialize(built, opts = {}) {
|
|
|
102
110
|
escalationIdByName: new Map(),
|
|
103
111
|
businessEvents: new Set((built.businessEvents ?? []).map((event) => event.name)),
|
|
104
112
|
conditionName: conditionNamer(built),
|
|
113
|
+
elementSeededIds: [],
|
|
105
114
|
};
|
|
106
115
|
// Preallocate SLA + escalation ids (before any rule is emitted) so a
|
|
107
116
|
// `sla-status-change` rule can resolve the `slaId`/`escalationId` it points at.
|
|
@@ -282,6 +291,7 @@ export function serialize(built, opts = {}) {
|
|
|
282
291
|
}
|
|
283
292
|
: {}),
|
|
284
293
|
};
|
|
294
|
+
ELEMENT_SEEDED_IDS.set(result, resolver.elementSeededIds);
|
|
285
295
|
const plan = stampConnectorConfigVersion(applyAuthorLayout(applyPreservation(result, caseJsonPreservation(built)), built.layout));
|
|
286
296
|
// Last, over the finished document: V32 requires case-unique condition names,
|
|
287
297
|
// and an author (or a decompiled pre-V32 plan) can repeat one. Rename the
|
|
@@ -396,6 +406,7 @@ export function applyPreservation(result, preservation, options = {}) {
|
|
|
396
406
|
const errors = caseJsonPreservationErrors(preservation);
|
|
397
407
|
if (errors.length)
|
|
398
408
|
throw new CompileRefusal('PRESERVATION_COLLISION', `invalid Case JSON preservation payload: ${errors.join('; ')}`);
|
|
409
|
+
preservation = followRenames(result, preservation);
|
|
399
410
|
applyPreservedIdentities(result, preservation);
|
|
400
411
|
Object.assign(result, preservation.topLevel ?? {});
|
|
401
412
|
Object.assign(result.metadata, preservation.metadata ?? {});
|
|
@@ -431,9 +442,15 @@ export function applyPreservation(result, preservation, options = {}) {
|
|
|
431
442
|
const row = rows.find((candidate) => candidate.name === name);
|
|
432
443
|
if (!row && options.overwrite)
|
|
433
444
|
continue;
|
|
445
|
+
// `custom` alone has nothing to mark when no row is written: an older SDK's
|
|
446
|
+
// companion for a variable an output writes, which this one migrates away.
|
|
447
|
+
if (!row && Object.keys(fields).every((field) => field === 'custom'))
|
|
448
|
+
continue;
|
|
434
449
|
if (!row)
|
|
435
450
|
throw new CompileRefusal('PRESERVATION_TARGET_MISSING', `preserved variable "${name}" was not regenerated in variables.${lane}.`);
|
|
436
451
|
for (const [field, value] of Object.entries(fields)) {
|
|
452
|
+
if (row[field] === value)
|
|
453
|
+
continue;
|
|
437
454
|
if (!options.overwrite && Object.prototype.hasOwnProperty.call(row, field))
|
|
438
455
|
throw new CompileRefusal('PRESERVATION_FIELD_COLLISION', `preserved variable "${name}" field "${field}" collides with serializer-owned output.`);
|
|
439
456
|
row[field] = value;
|
|
@@ -524,14 +541,171 @@ export function applyPreservation(result, preservation, options = {}) {
|
|
|
524
541
|
nodes.sort((left, right) => (order.get(String(left.id ?? '')) ?? Number.MAX_SAFE_INTEGER)
|
|
525
542
|
- (order.get(String(right.id ?? '')) ?? Number.MAX_SAFE_INTEGER));
|
|
526
543
|
}
|
|
544
|
+
// A stage the payload names that was not regenerated was deleted by the edit:
|
|
545
|
+
// its edges and canvas position go with it.
|
|
546
|
+
const nodeIds = new Set(result.nodes.map((node) => node.id));
|
|
547
|
+
const gone = new Set((preservation.identities?.stages ?? []).flatMap((stage) => (stage.id && !nodeIds.has(stage.id) ? [stage.id] : [])));
|
|
527
548
|
if (preservation.edges !== undefined)
|
|
528
|
-
result.edges = preservation.edges;
|
|
549
|
+
result.edges = preservation.edges.filter((edge) => !gone.has(edge?.source) && !gone.has(edge?.target));
|
|
529
550
|
if (preservation.layout !== undefined)
|
|
530
|
-
result.layout = preservation.layout;
|
|
551
|
+
result.layout = withoutLayoutNodes(preservation.layout, gone);
|
|
531
552
|
else if (preservation.omitLayout)
|
|
532
553
|
delete result.layout;
|
|
533
554
|
return result;
|
|
534
555
|
}
|
|
556
|
+
function withoutLayoutNodes(layout, gone) {
|
|
557
|
+
const nodes = layout?.nodes;
|
|
558
|
+
if (!gone.size || !nodes || typeof nodes !== 'object' || !Object.keys(nodes).some((id) => gone.has(id)))
|
|
559
|
+
return layout;
|
|
560
|
+
return { ...layout, nodes: Object.fromEntries(Object.entries(nodes).filter(([id]) => !gone.has(id))) };
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* The payload with each stage label and task name an edit renamed rewritten to
|
|
564
|
+
* the one compiled, so a renamed stage or task keeps its ids and wire fields
|
|
565
|
+
* instead of reading as a delete plus an add. Stages left over on both sides
|
|
566
|
+
* pair by the most task names shared, then the fewest not shared, then in order
|
|
567
|
+
* when as many are left on each side; a task left over pairs with one in the
|
|
568
|
+
* same stage whose input and output rows have the same names, and a task gone
|
|
569
|
+
* from its stage that another stage now holds under the same name and rows
|
|
570
|
+
* moved there.
|
|
571
|
+
*
|
|
572
|
+
* `wanted` is the payload's side (identities read from the original plan),
|
|
573
|
+
* `compiled` this compile's. Per stage, `missing` tasks are the payload's that
|
|
574
|
+
* the compiled stage no longer names, `extra` tasks the compiled stage's that
|
|
575
|
+
* the payload does not.
|
|
576
|
+
*/
|
|
577
|
+
export function followRenames(result, preservation) {
|
|
578
|
+
const wanted = preservation.identities?.stages ?? [];
|
|
579
|
+
if (!wanted.length)
|
|
580
|
+
return preservation;
|
|
581
|
+
const compiled = (result.nodes ?? []).filter((node) => String(node.type ?? '').endsWith('Stage'));
|
|
582
|
+
const labelOf = (stage) => String(stage.data?.label ?? '');
|
|
583
|
+
const tasksOf = (stage) => (stage.data?.tasks ?? []).flat().filter((task) => task && typeof task === 'object');
|
|
584
|
+
const compiledLabels = new Set(compiled.map(labelOf));
|
|
585
|
+
const wantedLabels = new Set(wanted.map((stage) => stage.label));
|
|
586
|
+
const unmatchedCompiled = compiled.filter((stage) => !wantedLabels.has(labelOf(stage)));
|
|
587
|
+
const stageLabels = new Map();
|
|
588
|
+
const paired = new Set();
|
|
589
|
+
const unmatchedWanted = wanted.filter((stage) => !compiledLabels.has(stage.label));
|
|
590
|
+
// Ranked across every pair, so a deleted stage that shares one task name with
|
|
591
|
+
// a renamed stage cannot take it from the stage that shares more.
|
|
592
|
+
const stagePairs = unmatchedWanted.flatMap((stage, from) => {
|
|
593
|
+
const names = new Set((stage.tasks ?? []).flat().map((task) => task.name));
|
|
594
|
+
return unmatchedCompiled.flatMap((candidate, to) => {
|
|
595
|
+
const tasks = tasksOf(candidate);
|
|
596
|
+
const shared = tasks.filter((task) => names.has(String(task.displayName ?? ''))).length;
|
|
597
|
+
return shared ? [{ from, to, shared, unshared: names.size + tasks.length - 2 * shared }] : [];
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
stagePairs.sort((a, b) => b.shared - a.shared || a.unshared - b.unshared || a.from - b.from || a.to - b.to);
|
|
601
|
+
for (const { from, to } of stagePairs) {
|
|
602
|
+
if (stageLabels.has(unmatchedWanted[from].label) || paired.has(unmatchedCompiled[to]))
|
|
603
|
+
continue;
|
|
604
|
+
paired.add(unmatchedCompiled[to]);
|
|
605
|
+
stageLabels.set(unmatchedWanted[from].label, labelOf(unmatchedCompiled[to]));
|
|
606
|
+
}
|
|
607
|
+
const unpairedWanted = unmatchedWanted.filter((stage) => !stageLabels.has(stage.label));
|
|
608
|
+
const unpairedCompiled = unmatchedCompiled.filter((stage) => !paired.has(stage));
|
|
609
|
+
if (unpairedWanted.length === unpairedCompiled.length)
|
|
610
|
+
unpairedWanted.forEach((stage, index) => stageLabels.set(stage.label, labelOf(unpairedCompiled[index])));
|
|
611
|
+
const rowNames = (inputs, outputs) => JSON.stringify([inputs, outputs].map((rows) => (Array.isArray(rows) ? rows : []).map((row) => String(row?.name ?? ''))));
|
|
612
|
+
const nameOf = (task) => String(task.displayName ?? '');
|
|
613
|
+
const stageSides = wanted.map((stage) => {
|
|
614
|
+
const target = compiled.find((candidate) => labelOf(candidate) === (stageLabels.get(stage.label) ?? stage.label));
|
|
615
|
+
const tasks = (stage.tasks ?? []).flat();
|
|
616
|
+
const current = target ? tasksOf(target) : [];
|
|
617
|
+
const currentNames = new Set(current.map(nameOf));
|
|
618
|
+
const names = new Set(tasks.map((task) => task.name));
|
|
619
|
+
return { stage, target, missing: tasks.filter((task) => !currentNames.has(task.name)), extra: current.filter((task) => !names.has(nameOf(task))) };
|
|
620
|
+
});
|
|
621
|
+
const targeted = new Set(stageSides.map((side) => side.target));
|
|
622
|
+
const extraTasks = [
|
|
623
|
+
...stageSides.flatMap(({ target, extra }) => (target ? extra.map((task) => ({ stage: labelOf(target), task })) : [])),
|
|
624
|
+
...compiled.filter((stage) => !targeted.has(stage)).flatMap((stage) => tasksOf(stage).map((task) => ({ stage: labelOf(stage), task }))),
|
|
625
|
+
];
|
|
626
|
+
const missingTasks = stageSides.flatMap(({ stage, missing }) => missing.map((task) => ({ stage: stage.label, task })));
|
|
627
|
+
const moves = new Map();
|
|
628
|
+
const claimed = new Set();
|
|
629
|
+
for (const { stage, task } of missingTasks) {
|
|
630
|
+
const rows = rowNames(task.inputs, task.outputs);
|
|
631
|
+
const to = extraTasks.filter((extra) => nameOf(extra.task) === task.name && rowNames(extra.task.data?.inputs, extra.task.data?.outputs) === rows);
|
|
632
|
+
if (to.length !== 1 || missingTasks.filter((other) => other.task.name === task.name).length !== 1)
|
|
633
|
+
continue;
|
|
634
|
+
if (!moves.has(stage))
|
|
635
|
+
moves.set(stage, new Map());
|
|
636
|
+
moves.get(stage).set(task.name, to[0].stage);
|
|
637
|
+
claimed.add(to[0].task);
|
|
638
|
+
}
|
|
639
|
+
const movedTo = (label, name) => moves.get(label)?.get(name);
|
|
640
|
+
const taskNames = new Map();
|
|
641
|
+
for (const side of stageSides) {
|
|
642
|
+
if (!side.target)
|
|
643
|
+
continue;
|
|
644
|
+
const missing = side.missing.filter((task) => !movedTo(side.stage.label, task.name));
|
|
645
|
+
const extra = side.extra
|
|
646
|
+
.filter((task) => !claimed.has(task))
|
|
647
|
+
.map((task) => ({ name: nameOf(task), rows: rowNames(task.data?.inputs, task.data?.outputs), task }));
|
|
648
|
+
// A deleted sibling can share a renamed task's rows, so the one whose content
|
|
649
|
+
// the renamed task still has wins, then the old name closest to the new one,
|
|
650
|
+
// then the earlier task.
|
|
651
|
+
const candidates = missing.flatMap((task, from) => extra.flatMap((candidate, to) => candidate.rows === rowNames(task.inputs, task.outputs)
|
|
652
|
+
? [{ from, to, same: Number(task.fingerprint !== undefined && task.fingerprint === taskFingerprint(candidate.task)), score: nameAffinity(task.name, candidate.name) }]
|
|
653
|
+
: []));
|
|
654
|
+
candidates.sort((a, b) => b.same - a.same || b.score - a.score || a.from - b.from || a.to - b.to);
|
|
655
|
+
const renames = new Map();
|
|
656
|
+
const taken = new Set();
|
|
657
|
+
for (const { from, to } of candidates) {
|
|
658
|
+
if (renames.has(missing[from].name) || taken.has(to))
|
|
659
|
+
continue;
|
|
660
|
+
renames.set(missing[from].name, extra[to].name);
|
|
661
|
+
taken.add(to);
|
|
662
|
+
}
|
|
663
|
+
if (renames.size)
|
|
664
|
+
taskNames.set(side.stage.label, renames);
|
|
665
|
+
}
|
|
666
|
+
if (!stageLabels.size && !taskNames.size && !moves.size)
|
|
667
|
+
return preservation;
|
|
668
|
+
const stageName = (label) => stageLabels.get(label) ?? label;
|
|
669
|
+
const taskName = (label, name) => taskNames.get(label)?.get(name) ?? name;
|
|
670
|
+
const ref = (entry) => ({ ...entry, stage: movedTo(entry.stage, entry.task) ?? stageName(entry.stage), task: taskName(entry.stage, entry.task) });
|
|
671
|
+
const stages = wanted.map((stage) => ({
|
|
672
|
+
...stage,
|
|
673
|
+
label: stageName(stage.label),
|
|
674
|
+
...(stage.tasks
|
|
675
|
+
? { tasks: stage.tasks.map((lane) => lane.filter((task) => !movedTo(stage.label, task.name)).map((task) => ({ ...task, name: taskName(stage.label, task.name) }))) }
|
|
676
|
+
: {}),
|
|
677
|
+
}));
|
|
678
|
+
for (const { stage: from, task } of missingTasks) {
|
|
679
|
+
const to = movedTo(from, task.name);
|
|
680
|
+
if (!to)
|
|
681
|
+
continue;
|
|
682
|
+
const target = stages.find((stage) => stage.label === to);
|
|
683
|
+
if (target)
|
|
684
|
+
target.tasks = [...(target.tasks ?? []), [task]];
|
|
685
|
+
else
|
|
686
|
+
stages.push({ label: to, tasks: [[task]] });
|
|
687
|
+
}
|
|
688
|
+
return {
|
|
689
|
+
...preservation,
|
|
690
|
+
identities: {
|
|
691
|
+
...preservation.identities,
|
|
692
|
+
stages,
|
|
693
|
+
},
|
|
694
|
+
...(preservation.taskFields ? { taskFields: preservation.taskFields.map(ref) } : {}),
|
|
695
|
+
...(preservation.omitTaskElementIds ? { omitTaskElementIds: preservation.omitTaskElementIds.map(ref) } : {}),
|
|
696
|
+
...(preservation.omitStagePositions ? { omitStagePositions: preservation.omitStagePositions.map(stageName) } : {}),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
/** How much of a renamed name survives: the longer of the shared prefix and the shared suffix. */
|
|
700
|
+
function nameAffinity(before, after) {
|
|
701
|
+
let prefix = 0;
|
|
702
|
+
while (prefix < before.length && before[prefix] === after[prefix])
|
|
703
|
+
prefix++;
|
|
704
|
+
let suffix = 0;
|
|
705
|
+
while (suffix < before.length && suffix < after.length && before.at(-1 - suffix) === after.at(-1 - suffix))
|
|
706
|
+
suffix++;
|
|
707
|
+
return Math.max(prefix, suffix);
|
|
708
|
+
}
|
|
535
709
|
function applyPreservedIdentities(result, preservation) {
|
|
536
710
|
const identities = preservation.identities;
|
|
537
711
|
if (!identities)
|
|
@@ -543,11 +717,70 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
543
717
|
replacements.set(current.id, wanted);
|
|
544
718
|
current.id = wanted;
|
|
545
719
|
};
|
|
720
|
+
const nodes = result.nodes;
|
|
721
|
+
const stages = nodes.filter((node) => String(node.type).endsWith('Stage'));
|
|
722
|
+
const bagField = CASE_FORMAT_PROFILE.waitConnectorRuleBagField;
|
|
723
|
+
const ruleOutputRows = (conditions) => (conditions ?? []).flatMap((condition) => (condition?.rules ?? []).flat().flatMap((rule) => rule?.[bagField]?.outputs ?? []));
|
|
724
|
+
// Every output row id in the plan, task and rule rows alike, kept current as
|
|
725
|
+
// preserved ids are taken. Output ids are unique plan-wide (`claimOutputId`); a
|
|
726
|
+
// preserved id that another row already holds would undo that. Example: an
|
|
727
|
+
// older SDK wrote two action rows both `{ id: 'action', var: 'action' }`; this
|
|
728
|
+
// pass gives the second `action2`, and taking its preserved `action` would make
|
|
729
|
+
// it a duplicate.
|
|
730
|
+
const heldOutputIds = new Set();
|
|
731
|
+
for (const stage of stages) {
|
|
732
|
+
const rows = [
|
|
733
|
+
...ruleOutputRows(stage.data?.entryConditions),
|
|
734
|
+
...ruleOutputRows(stage.data?.exitConditions),
|
|
735
|
+
...(stage.data?.tasks ?? []).flat().flatMap((task) => [...(task?.data?.outputs ?? []), ...ruleOutputRows(task?.entryConditions)]),
|
|
736
|
+
];
|
|
737
|
+
for (const row of rows)
|
|
738
|
+
if (typeof row?.id === 'string')
|
|
739
|
+
heldOutputIds.add(row.id);
|
|
740
|
+
}
|
|
741
|
+
for (const row of ruleOutputRows(result.metadata?.caseExitRules))
|
|
742
|
+
if (typeof row?.id === 'string')
|
|
743
|
+
heldOutputIds.add(row.id);
|
|
744
|
+
const takeOutputRows = (outputRows, wantedRows) => {
|
|
745
|
+
// Match by name when unique on both sides, else by position.
|
|
746
|
+
const unique = (names, name) => names.filter((n) => n === name).length === 1;
|
|
747
|
+
const currentNames = outputRows.map((r) => r?.name);
|
|
748
|
+
const wantedNames = wantedRows.map((r) => r.name);
|
|
749
|
+
const named = new Set(wantedRows.filter((r) => unique(wantedNames, r.name) && unique(currentNames, r.name)).map((r) => r.name));
|
|
750
|
+
wantedRows.forEach((row, index) => {
|
|
751
|
+
const target = named.has(row.name)
|
|
752
|
+
? outputRows.find((r) => r?.name === row.name)
|
|
753
|
+
// A positional match never takes a row a name match owns.
|
|
754
|
+
: named.has(outputRows[index]?.name) ? undefined : outputRows[index];
|
|
755
|
+
const currentId = target?.id;
|
|
756
|
+
// An own-name row's id IS its variable's name (`emitTaskOutput`). A
|
|
757
|
+
// preserved id that differs — an `o<hash>` slot from a plan an older
|
|
758
|
+
// SDK wrote — would rename the variable out from under every
|
|
759
|
+
// `=vars.<name>` reader, so the typed rule wins and the row migrates.
|
|
760
|
+
if (target && OWN_NAME_OUTPUT_ROWS.has(target) && row.id !== target.id)
|
|
761
|
+
return;
|
|
762
|
+
if (target && typeof row.id === 'string' && row.id !== currentId && heldOutputIds.has(row.id))
|
|
763
|
+
return;
|
|
764
|
+
take(target, row.id);
|
|
765
|
+
if (target && typeof row.id === 'string' && typeof currentId === 'string') {
|
|
766
|
+
heldOutputIds.delete(currentId);
|
|
767
|
+
heldOutputIds.add(row.id);
|
|
768
|
+
}
|
|
769
|
+
if (typeof currentId === 'string' && typeof row.id === 'string' && target?.value === currentId) {
|
|
770
|
+
target.value = row.id;
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
};
|
|
546
774
|
const takeConditions = (current, wanted) => {
|
|
547
775
|
(wanted ?? []).forEach((condition, index) => {
|
|
548
776
|
const target = current?.[index];
|
|
549
777
|
take(target, condition.id);
|
|
550
|
-
(condition.rules ?? []).forEach((group, groupIndex) => group.forEach((rule, ruleIndex) =>
|
|
778
|
+
(condition.rules ?? []).forEach((group, groupIndex) => group.forEach((rule, ruleIndex) => {
|
|
779
|
+
const ruleTarget = target?.rules?.[groupIndex]?.[ruleIndex];
|
|
780
|
+
take(ruleTarget, rule.id);
|
|
781
|
+
if (rule.outputs)
|
|
782
|
+
takeOutputRows(ruleTarget?.[bagField]?.outputs ?? [], rule.outputs);
|
|
783
|
+
}));
|
|
551
784
|
});
|
|
552
785
|
};
|
|
553
786
|
const takeSlas = (current, wanted) => {
|
|
@@ -558,22 +791,8 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
558
791
|
});
|
|
559
792
|
};
|
|
560
793
|
take(result, identities.id);
|
|
561
|
-
const nodes = result.nodes;
|
|
562
794
|
const triggerNodes = nodes.filter((node) => node.type === 'case-management:Trigger' || node.type === 'uipath.case.trigger');
|
|
563
795
|
(identities.triggers ?? []).forEach((trigger, index) => take(triggerNodes[index], trigger.id));
|
|
564
|
-
const stages = nodes.filter((node) => String(node.type).endsWith('Stage'));
|
|
565
|
-
// Every task-output row id in the plan, kept current as preserved ids are
|
|
566
|
-
// taken. Output ids are unique plan-wide (`claimOutputId`); a preserved id that
|
|
567
|
-
// another row already holds would undo that. Example: an older SDK wrote two
|
|
568
|
-
// action rows both `{ id: 'action', var: 'action' }`; this pass gives the
|
|
569
|
-
// second `action2`, and taking its preserved `action` would make it a duplicate.
|
|
570
|
-
const heldOutputIds = new Set();
|
|
571
|
-
for (const stage of stages)
|
|
572
|
-
for (const lane of stage.data?.tasks ?? [])
|
|
573
|
-
for (const task of lane)
|
|
574
|
-
for (const row of task?.data?.outputs ?? [])
|
|
575
|
-
if (typeof row?.id === 'string')
|
|
576
|
-
heldOutputIds.add(row.id);
|
|
577
796
|
for (const stageIdentity of identities.stages ?? []) {
|
|
578
797
|
const stage = stages.find((candidate) => candidate.data?.label === stageIdentity.label);
|
|
579
798
|
take(stage, stageIdentity.id);
|
|
@@ -585,36 +804,7 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
585
804
|
take(task, taskIdentity.id);
|
|
586
805
|
takeConditions(task?.entryConditions, taskIdentity.entryConditions);
|
|
587
806
|
(taskIdentity.inputs ?? []).forEach((row, index) => take(task?.data?.inputs?.[index], row.id));
|
|
588
|
-
|
|
589
|
-
const wantedRows = taskIdentity.outputs ?? [];
|
|
590
|
-
// Match by name when unique on both sides, else by position.
|
|
591
|
-
const unique = (names, name) => names.filter((n) => n === name).length === 1;
|
|
592
|
-
const currentNames = outputRows.map((r) => r?.name);
|
|
593
|
-
const wantedNames = wantedRows.map((r) => r.name);
|
|
594
|
-
const named = new Set(wantedRows.filter((r) => unique(wantedNames, r.name) && unique(currentNames, r.name)).map((r) => r.name));
|
|
595
|
-
wantedRows.forEach((row, index) => {
|
|
596
|
-
const target = named.has(row.name)
|
|
597
|
-
? outputRows.find((r) => r?.name === row.name)
|
|
598
|
-
// A positional match never takes a row a name match owns.
|
|
599
|
-
: named.has(outputRows[index]?.name) ? undefined : outputRows[index];
|
|
600
|
-
const currentId = target?.id;
|
|
601
|
-
// An own-name row's id IS its variable's name (`emitTaskOutput`). A
|
|
602
|
-
// preserved id that differs — an `o<hash>` slot from a plan an older
|
|
603
|
-
// SDK wrote — would rename the variable out from under every
|
|
604
|
-
// `=vars.<name>` reader, so the typed rule wins and the row migrates.
|
|
605
|
-
if (target && OWN_NAME_OUTPUT_ROWS.has(target) && row.id !== target.id)
|
|
606
|
-
return;
|
|
607
|
-
if (target && typeof row.id === 'string' && row.id !== currentId && heldOutputIds.has(row.id))
|
|
608
|
-
return;
|
|
609
|
-
take(target, row.id);
|
|
610
|
-
if (target && typeof row.id === 'string' && typeof currentId === 'string') {
|
|
611
|
-
heldOutputIds.delete(currentId);
|
|
612
|
-
heldOutputIds.add(row.id);
|
|
613
|
-
}
|
|
614
|
-
if (typeof currentId === 'string' && typeof row.id === 'string' && target?.value === currentId) {
|
|
615
|
-
target.value = row.id;
|
|
616
|
-
}
|
|
617
|
-
});
|
|
807
|
+
takeOutputRows(task?.data?.outputs ?? [], taskIdentity.outputs ?? []);
|
|
618
808
|
}));
|
|
619
809
|
}
|
|
620
810
|
const metadata = result.metadata;
|
|
@@ -627,11 +817,12 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
627
817
|
return;
|
|
628
818
|
take(variables[lane]?.find((candidate) => candidate.name === row.name), row.id);
|
|
629
819
|
});
|
|
820
|
+
const longestFirst = [...replacements].sort((a, b) => b[0].length - a[0].length);
|
|
630
821
|
const replace = (value) => {
|
|
631
822
|
if (replacements.has(value))
|
|
632
823
|
return replacements.get(value);
|
|
633
824
|
let replaced = value;
|
|
634
|
-
for (const [current, wanted] of
|
|
825
|
+
for (const [current, wanted] of longestFirst)
|
|
635
826
|
replaced = replaced.replaceAll(current, wanted);
|
|
636
827
|
return replaced;
|
|
637
828
|
};
|
|
@@ -696,6 +887,33 @@ function applyPreservedIdentities(result, preservation) {
|
|
|
696
887
|
rewrite(result);
|
|
697
888
|
for (const { row, source } of preservedOutputSources)
|
|
698
889
|
row.source = source;
|
|
890
|
+
// An id hashed from a generated element id is re-minted from the preserved one,
|
|
891
|
+
// wherever it is spelled, including inside a `=jsonString:` configuration.
|
|
892
|
+
const reseeded = new Map();
|
|
893
|
+
for (const entry of ELEMENT_SEEDED_IDS.get(result) ?? []) {
|
|
894
|
+
const elementId = replace(entry.elementId);
|
|
895
|
+
if (elementId !== entry.elementId)
|
|
896
|
+
reseeded.set(entry.id, stableId(`${elementId}${entry.suffix}`));
|
|
897
|
+
}
|
|
898
|
+
if (reseeded.size)
|
|
899
|
+
reseed(result, reseeded);
|
|
900
|
+
}
|
|
901
|
+
function reseed(value, ids) {
|
|
902
|
+
if (!value || typeof value !== 'object')
|
|
903
|
+
return;
|
|
904
|
+
const entries = Array.isArray(value) ? value.map((entry, index) => [index, entry]) : Object.entries(value);
|
|
905
|
+
for (const [key, entry] of entries) {
|
|
906
|
+
if (typeof entry !== 'string') {
|
|
907
|
+
reseed(entry, ids);
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
let next = entry;
|
|
911
|
+
for (const [from, to] of ids)
|
|
912
|
+
if (next.includes(from))
|
|
913
|
+
next = next.replaceAll(from, to);
|
|
914
|
+
if (next !== entry)
|
|
915
|
+
value[key] = next;
|
|
916
|
+
}
|
|
699
917
|
}
|
|
700
918
|
function emitVariables(vars, ids, triggerNodeByRef) {
|
|
701
919
|
const inputs = [];
|
|
@@ -1091,7 +1309,7 @@ function resolvedSubscriptionBag(kind, spec, resolver, elementId, where) {
|
|
|
1091
1309
|
const folder = folderBindingRef(resolver, spec.folder, connection, { attribute: 'folder', where, target });
|
|
1092
1310
|
if (folder)
|
|
1093
1311
|
context.push(io('folderKey', 'string', { value: `=bindings.${folder.id}` }));
|
|
1094
|
-
context.push(io('method', 'string', {}), io('path', 'string', {}), io('objectName', 'string', { value: op.objectName ?? spec.event }), io('operation', 'string', { value: op.eventOperation ?? spec.event }), io('metadata', 'json', { body: subscriptionMetadata(rc, op, spec.filters ?? [], elementId) }));
|
|
1312
|
+
context.push(io('method', 'string', {}), io('path', 'string', {}), io('objectName', 'string', { value: op.objectName ?? spec.event }), io('operation', 'string', { value: op.eventOperation ?? spec.event }), io('metadata', 'json', { body: subscriptionMetadata(rc, op, spec.filters ?? [], elementId, resolver) }));
|
|
1095
1313
|
return {
|
|
1096
1314
|
serviceType: kind === 'trigger' ? CASE_FORMAT_PROFILE.eventServiceType : CASE_FORMAT_PROFILE.waitConnectorServiceType,
|
|
1097
1315
|
context,
|
|
@@ -1106,7 +1324,7 @@ function eventInput(where, elementId) {
|
|
|
1106
1324
|
? { name: 'body', type: 'json', target: 'body', body: { queryParams: where }, var: 'vbody', id: 'vbody', elementId }
|
|
1107
1325
|
: { name: 'body', type: 'json', target: 'body', value: '', var: 'vbody', id: 'vbody', elementId };
|
|
1108
1326
|
}
|
|
1109
|
-
function subscriptionMetadata(rc, op, filters, elementId) {
|
|
1327
|
+
function subscriptionMetadata(rc, op, filters, elementId, resolver) {
|
|
1110
1328
|
const instanceParameters = {
|
|
1111
1329
|
connectorKey: rc.connectorKey,
|
|
1112
1330
|
objectName: op.objectName ?? rc.nodeType.split('.').pop(),
|
|
@@ -1131,7 +1349,7 @@ function subscriptionMetadata(rc, op, filters, elementId) {
|
|
|
1131
1349
|
const { read } = judged;
|
|
1132
1350
|
return {
|
|
1133
1351
|
...eventFilterTreeLeaf(read),
|
|
1134
|
-
uiId:
|
|
1352
|
+
uiId: elementSeededId(resolver, elementId, `:${read.field}:${String(read.value)}:${index}`),
|
|
1135
1353
|
};
|
|
1136
1354
|
}).map((leaf) => ({
|
|
1137
1355
|
id: leaf.id,
|
|
@@ -1140,7 +1358,7 @@ function subscriptionMetadata(rc, op, filters, elementId) {
|
|
|
1140
1358
|
uiId: leaf.uiId,
|
|
1141
1359
|
})),
|
|
1142
1360
|
groups: [],
|
|
1143
|
-
uuId:
|
|
1361
|
+
uuId: elementSeededId(resolver, elementId, ':filters'),
|
|
1144
1362
|
} : null;
|
|
1145
1363
|
const configuration = {
|
|
1146
1364
|
essentialConfiguration: {
|
|
@@ -1182,16 +1400,6 @@ function subscriptionMetadata(rc, op, filters, elementId) {
|
|
|
1182
1400
|
},
|
|
1183
1401
|
};
|
|
1184
1402
|
}
|
|
1185
|
-
function stableUuid(seed) {
|
|
1186
|
-
let h1 = 0x811c9dc5;
|
|
1187
|
-
let h2 = 0x01000193;
|
|
1188
|
-
for (let index = 0; index < seed.length; index++) {
|
|
1189
|
-
h1 = (h1 ^ seed.charCodeAt(index)) * 0x01000193 >>> 0;
|
|
1190
|
-
h2 = (h2 + seed.charCodeAt(index) * (index + 7)) >>> 0;
|
|
1191
|
-
}
|
|
1192
|
-
const hex = (value, length) => value.toString(16).padStart(8, '0').slice(0, length);
|
|
1193
|
-
return `${hex(h1, 8)}-${hex(h2, 4)}-4${hex(h1 >>> 8, 3)}-8${hex(h2 >>> 8, 3)}-${hex(h1 ^ h2, 8)}${hex(h2, 4)}`;
|
|
1194
|
-
}
|
|
1195
1403
|
// ─── Reference-mode task io-binding (data.inputs[] / data.outputs[]) ───────────
|
|
1196
1404
|
//
|
|
1197
1405
|
// Wire shape verified against a real `uip maestro case` caseplan (the io-binding
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.66.
|
|
3
|
+
"version": "6.66.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": "e7e32040e5596319cf1bccea2a6caa9124d79bbb"
|
|
104
104
|
}
|