@uipath/maestro-builder-sdk 6.20.5 → 6.20.6

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/serialize.js CHANGED
@@ -55,6 +55,8 @@ import { migrateToSchemaVersion } from './migrate.js';
55
55
  import { FLOW_SCHEMA_VERSIONS } from './format-profile.js';
56
56
  import { resolveSchemaVersion } from './schema-version.js';
57
57
  import { planFlowGlobals, planSharedInputs, sharedInputRoots } from './flow-variables.js';
58
+ import { outputBackingGlobal, planOutputBacking } from './flow-output-backing.js';
59
+ import { mapJsCode } from './core/js-code-spans.js';
58
60
  import { prepareCommand } from './core/cli-spelling.js';
59
61
  import { QUEUE_ITEM_RECORD_SCHEMA } from './core/queue-record.js';
60
62
  import { AGENTIC_PROCESS_FORMS } from './core/agentic-process-forms.js';
@@ -3589,10 +3591,11 @@ function applyAuthorLayout(layout, scope, where) {
3589
3591
  * identically into ExpressionValue envelopes.
3590
3592
  */
3591
3593
  function renderUpdates(updates, rename) {
3592
- return Object.entries(updates).map(([variableId, val]) => {
3594
+ return Object.entries(updates).map(([name, val]) => {
3593
3595
  const expr = toExpr(val);
3594
3596
  const expression = expr.literal ? '=js:' + JSON.stringify(expr.value) : '=js:' + renameRefs(expr.js, rename);
3595
- return { variableId, expression };
3597
+ // An output is never an update target: its backing Variable is (#1092).
3598
+ return { variableId: rename.updates?.get(name) ?? name, expression };
3596
3599
  });
3597
3600
  }
3598
3601
  /**
@@ -4263,7 +4266,14 @@ function emittableGlobals(built, where, kind = 'root') {
4263
4266
  if (plan.problems.length) {
4264
4267
  throw new Error(`${where}: ${plan.problems.map((p) => `[${p.code}] ${p.message}`).join(' ')}`);
4265
4268
  }
4266
- return plan;
4269
+ // An output the flow sets from inside gets an `inout` Variable to hold the
4270
+ // value; the End copies it into the Output (#1092, `flow-output-backing.ts`).
4271
+ const sharedOutputs = new Set(shared.targets.filter((t) => t.declaredAs === 'output').map((t) => t.name));
4272
+ const backing = planOutputBacking(built, plan.outputs, plan.vars, sharedOutputs);
4273
+ if (backing.problems.length) {
4274
+ throw new Error(`${where}: ${backing.problems.map((p) => `[${p.code}] ${p.message}`).join(' ')}`);
4275
+ }
4276
+ return { ...plan, backing: backing.backing, backingReads: backing.reads };
4267
4277
  }
4268
4278
  /**
4269
4279
  * The flow's `{ shared }` input plan (#924), refused here as `check` refuses it
@@ -4284,17 +4294,20 @@ function sharedInputsOf(built, where, kind) {
4284
4294
  throw new Error(`${where}: ${errors.map((p) => `[${p.code}] ${p.message}`).join(' ')}`);
4285
4295
  return plan;
4286
4296
  }
4287
- function newScope(outputs, vars = []) {
4297
+ function newScope(outputs, vars = [], backing = new Map(), backingReads = backing) {
4298
+ const typeOf = new Map(outputs.map((o) => [o.name, o.type]));
4288
4299
  return {
4289
4300
  nodes: [],
4290
4301
  edges: [],
4291
4302
  variableUpdates: {},
4292
- outputType: new Map(outputs.map((o) => [o.name, o.type])),
4303
+ outputType: typeOf,
4293
4304
  endVarType: new Map([
4294
4305
  ...outputs.map((o) => [o.name, o.type]),
4306
+ ...[...backing].map(([o, b]) => [b, typeOf.get(o)]),
4295
4307
  ...vars.map((vd) => [vd.name, vd.type]),
4296
4308
  ]),
4297
- rename: { nodeIds: new Map(), errorEnvelopes: new Map() },
4309
+ backing,
4310
+ rename: { nodeIds: new Map(), errorEnvelopes: new Map(), vars: new Map(backingReads), updates: new Map(backing) },
4298
4311
  pending: new Map(),
4299
4312
  agentSchemas: [],
4300
4313
  stepNodeId: new Map(),
@@ -4535,11 +4548,11 @@ function isTypeDesc(type) {
4535
4548
  * An End node's `outputs` map: every variable this scope exposes as a flow
4536
4549
  * output, in declaration order.
4537
4550
  *
4538
- * `explicit` holds the sources a `.return({…})` named. Everything else maps to
4539
- * ITSELF (`$vars.<name>`) — "this output is whatever the variable holds when the
4540
- * flow leaves here", which is what Studio Web wires when you add a variable to
4541
- * an End node, and the only sensible reading for a `.var(…)` counter or an
4542
- * output another branch returns.
4551
+ * `explicit` holds the sources a `.return({…})` named. Everything else gets
4552
+ * `fillInSource`: a Variable maps to ITSELF (`$vars.<name>`), "whatever it holds
4553
+ * when the flow leaves here"; an output maps from its backing Variable when a
4554
+ * step sets it, else to `null` (#1092). An End never reads `$vars.<output>`:
4555
+ * Studio Web does not declare Outputs on `$vars`.
4543
4556
  *
4544
4557
  * Emitting the full set is not cosmetic. The product's output-mapping rule warns
4545
4558
  * `MISSING_OUTPUT_MAPPING` once per (End node × unmapped output variable), and
@@ -4552,8 +4565,7 @@ function isTypeDesc(type) {
4552
4565
  function endOutputs(scope, explicit = {}) {
4553
4566
  const outs = {};
4554
4567
  for (const [name, type] of scope.endVarType) {
4555
- const source = explicit[name] ?? `=js:$vars.${name}`;
4556
- outs[name] = { type, description: '', source, var: name };
4568
+ outs[name] = { type, description: '', source: explicit[name] ?? fillInSource(scope, name), var: name };
4557
4569
  }
4558
4570
  // A `.return(…)` naming something the flow never declared is a check() error
4559
4571
  // (RETURN_UNDECLARED), but serialize must not silently swallow the mapping if
@@ -4564,6 +4576,23 @@ function endOutputs(scope, explicit = {}) {
4564
4576
  }
4565
4577
  return outs;
4566
4578
  }
4579
+ /**
4580
+ * What an End maps a variable to when no `.return()` named it here.
4581
+ *
4582
+ * - A Variable (`inout`, a backing one included) maps to itself: "whatever it
4583
+ * holds when the flow leaves here".
4584
+ * - An Output with a backing Variable maps from that Variable (#1092).
4585
+ * - Any other Output was never set on the way (only `.return()` values set
4586
+ * it, and this End returns none), so it maps to `null`. That is the value the
4587
+ * old `$vars.<output>` read gave on this path, without reading an Output,
4588
+ * which Studio Web does not allow.
4589
+ */
4590
+ function fillInSource(scope, name) {
4591
+ if (!scope.outputType.has(name))
4592
+ return `=js:$vars.${name}`;
4593
+ const backing = scope.backing.get(name);
4594
+ return backing ? `=js:$vars.${backing}` : '=js:null';
4595
+ }
4567
4596
  /**
4568
4597
  * A Terminate event has no action result, but it is still a terminal event. The
4569
4598
  * product's output-mapping validator therefore requires every flow output on it,
@@ -4586,19 +4615,23 @@ function terminateOutputs(scope) {
4586
4615
  * same name (an error in its own right — DUP_STEP).
4587
4616
  */
4588
4617
  function renameRefs(text, rename) {
4589
- if (rename.nodeIds.size === 0 && rename.errorEnvelopes.size === 0)
4618
+ if (rename.nodeIds.size === 0 && rename.errorEnvelopes.size === 0 && !rename.vars?.size)
4590
4619
  return text;
4591
4620
  // `.error` matches only with a FIELD behind it: a bare `$vars.<step>.error` is
4592
4621
  // the boolean "did this fail" (`err('<step>')`), which is truthy on every
4593
4622
  // family — the envelope object included — and must be left alone.
4594
- return text.replace(/\$vars\.([A-Za-z0-9_]+)(\.error(?=\.[A-Za-z0-9_]))?/g, (m, name, tail) => {
4623
+ // Only code is rewritten: `"$vars.summary"` in a script is text (#1092).
4624
+ return mapJsCode(text, (code) => code.replace(/\$vars\.([A-Za-z0-9_]+)(\.error(?=\.[A-Za-z0-9_]))?/g, (m, name, tail) => {
4625
+ const backing = rename.vars?.get(name);
4626
+ if (backing)
4627
+ return `$vars.${backing}${tail ?? ''}`;
4595
4628
  const to = rename.nodeIds.get(name);
4596
4629
  const nodeId = to && to.length > 0 ? to[0] : name;
4597
4630
  if (!tail)
4598
4631
  return nodeId === name ? m : `$vars.${nodeId}`;
4599
4632
  const envelope = rename.errorEnvelopes.get(name) ?? 'error';
4600
4633
  return `$vars.${nodeId}.${envelope}`;
4601
- });
4634
+ }));
4602
4635
  }
4603
4636
  /** Every step name a flow declares in its own scope (not its children's). */
4604
4637
  function stepNamesOf(steps, out = []) {
@@ -4743,7 +4776,7 @@ export function serialize(built, opts = {}) {
4743
4776
  const sidecars = opts.sidecars ?? [];
4744
4777
  const subflows = {};
4745
4778
  const rootGlobals = emittableGlobals(built, `flow "${built.id}"`);
4746
- const root = newScope(rootGlobals.outputs, rootGlobals.vars);
4779
+ const root = newScope(rootGlobals.outputs, rootGlobals.vars, rootGlobals.backing, rootGlobals.backingReads);
4747
4780
  // `input('x')` lowers eagerly to `$vars.start.output.x` — `start` being the
4748
4781
  // trigger node's default id. When the flow renames the trigger, register that
4749
4782
  // rename so the SAME pass that rewrites step-name references rewrites these
@@ -4920,7 +4953,7 @@ export function serialize(built, opts = {}) {
4920
4953
  */
4921
4954
  function emitSubflowBody(child, nodeId) {
4922
4955
  const childGlobals = emittableGlobals(child, `subflow "${nodeId}"`, 'subflow');
4923
- const scope = newScope(childGlobals.outputs, childGlobals.vars);
4956
+ const scope = newScope(childGlobals.outputs, childGlobals.vars, childGlobals.backing, childGlobals.backingReads);
4924
4957
  // Claim this copy's node ids UP FRONT, so the rename map is complete before
4925
4958
  // the first expression renders. A child's step names are free the first
4926
4959
  // time it runs; if any of them is already taken — which is what a second
@@ -4958,6 +4991,11 @@ export function serialize(built, opts = {}) {
4958
4991
  globals.push({ id: inp.name, name: inp.name, direction: 'in', type: inp.type, triggerNodeId: startId, ...varMeta(inp) });
4959
4992
  for (const o of childGlobals.outputs)
4960
4993
  globals.push({ id: o.name, name: o.name, direction: 'out', type: o.type, ...varMeta(o) });
4994
+ for (const o of childGlobals.outputs) {
4995
+ const b = childGlobals.backing.get(o.name);
4996
+ if (b)
4997
+ globals.push(outputBackingGlobal(o, b));
4998
+ }
4961
4999
  for (const vd of childGlobals.vars)
4962
5000
  globals.push({ id: vd.name, name: vd.name, direction: 'inout', type: vd.type, ...varMeta(vd) });
4963
5001
  resolveRejoins(scope, addEdge);
@@ -6919,10 +6957,14 @@ export function serialize(built, opts = {}) {
6919
6957
  for (const [name, expr] of Object.entries(step.values)) {
6920
6958
  const src = expr.literal ? '=js:' + JSON.stringify(expr.value) : '=js:' + renameRefs(expr.js, scope.rename);
6921
6959
  explicit[name] = src;
6922
- // Only the values the author actually RETURNED are written back to the
6923
- // variable. The identity mappings `endOutputs` fills in read a
6924
- // variable; a variableUpdate for one would be a no-op assignment.
6925
- updates.push({ variableId: name, expression: src });
6960
+ // The End's output mapping is what sets an Output; Studio Web writes
6961
+ // no variable update for it (`end-node-sets-output.flow`), and an
6962
+ // Output is not an update target (#1092). A returned `.var()` is a
6963
+ // Variable, so it is still written back. The identity mappings
6964
+ // `endOutputs` fills in read a variable; an update for one would be
6965
+ // a no-op assignment.
6966
+ if (!scope.outputType.has(name))
6967
+ updates.push({ variableId: name, expression: src });
6926
6968
  }
6927
6969
  emitEnd(scope, id, tails, { label: step.options?.label, parentId, requestedVersion: step.options?.version, explicit });
6928
6970
  const extra = step.options?.updates ?? {};
@@ -7073,6 +7115,11 @@ export function serialize(built, opts = {}) {
7073
7115
  globals.push({ id: inp.name, name: inp.name, direction: 'in', type: inp.type, triggerNodeId, ...varMeta(inp) });
7074
7116
  for (const o of rootGlobals.outputs)
7075
7117
  globals.push({ id: o.name, name: o.name, direction: 'out', type: o.type, ...varMeta(o) });
7118
+ for (const o of rootGlobals.outputs) {
7119
+ const b = rootGlobals.backing.get(o.name);
7120
+ if (b)
7121
+ globals.push(outputBackingGlobal(o, b));
7122
+ }
7076
7123
  for (const vd of rootGlobals.vars)
7077
7124
  globals.push({ id: vd.name, name: vd.name, direction: 'inout', type: vd.type, ...varMeta(vd) });
7078
7125
  for (const ep of entryPoints) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.20.5",
3
+ "version": "6.20.6",
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",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "2ed3ce64cea5047f9da44c287cacc18f0f66f37d"
95
+ "gitref": "124c0cac0f49d9974da5619817458d4d8760a91f"
96
96
  }