@uipath/maestro-builder-sdk 6.14.0 → 6.14.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.
package/dist/check.js CHANGED
@@ -92,9 +92,9 @@ function checkFlow(built, ancestors, opts = {}) {
92
92
  * checkable at all — see ERROR_ENVELOPE_VIA_OUTPUT.
93
93
  */
94
94
  const exprs = [];
95
- // Loop step names, so `$vars.<loop>.<field>` can be checked against the loop
96
- // node's actual output fields (see LOOP_FIELDS below).
97
- const loopNames = new Set();
95
+ // Loop step names, each with the output fields its node version exposes, so
96
+ // `$vars.<loop>.<field>` can be checked against them (see LOOP_FIELDS below).
97
+ const loopNames = new Map();
98
98
  // Switch step names. A switch is pure routing — its definition carries
99
99
  // `outputDefinition: null`, so it publishes NOTHING; reading `$vars.<switch>`
100
100
  // is always undefined at run time (see SWITCH_HAS_NO_OUTPUT below).
@@ -649,7 +649,7 @@ function checkFlow(built, ancestors, opts = {}) {
649
649
  checkLoopListEnvelope(s, connectorSteps, opts, diags);
650
650
  if (s.options?.completionCondition)
651
651
  addExpr(s.options.completionCondition.js, s.name);
652
- loopNames.add(s.name);
652
+ loopNames.set(s.name, s.options?.version === '1.0.0' ? LOOP_FIELDS_1_0_0 : LOOP_FIELDS);
653
653
  if (s.body.length === 0)
654
654
  diags.push({ level: 'warning', code: 'EMPTY_LOOP', message: `Loop "${s.name}" has an empty body.`, step: s.name });
655
655
  walk(s.body, true);
@@ -660,7 +660,7 @@ function checkFlow(built, ancestors, opts = {}) {
660
660
  // but no error handle.
661
661
  prevPortSource = s;
662
662
  addExpr(s.condition.js, s.name);
663
- loopNames.add(s.name);
663
+ loopNames.set(s.name, LOOP_FIELDS_1_0_0);
664
664
  // The platform's dowhile-limit rule: 1..10000 when set; blank = 10,000.
665
665
  const limit = s.options?.limit;
666
666
  if (limit !== undefined && (!Number.isFinite(limit) || limit < 1 || limit > 10000)) {
@@ -1178,14 +1178,24 @@ function checkFlow(built, ancestors, opts = {}) {
1178
1178
  // A loop step exposes a fixed set of fields, and only those resolve at run
1179
1179
  // time — `$vars.<loop>.item` reads undefined rather than the iteration
1180
1180
  // item. Catch the wrong spelling here, in the fast loop.
1181
- if (loopNames.has(name) && field && !LOOP_FIELDS.has(field)) {
1181
+ const loopFields = loopNames.get(name);
1182
+ if (loopFields && field && !loopFields.has(field)) {
1183
+ // `currentIndex` (0-based) is the 1.0.0 name; loop 2.x renamed it to
1184
+ // `currentIteration` (1-based). The platform's converter rewrites only
1185
+ // `currentItem` / `currentIteration` / `collection`, so the old name on a
1186
+ // 2.4 loop reads undefined at run time — no error, just a wrong value.
1187
+ const renamed = field === 'currentIndex' && loopFields.has('currentIteration');
1182
1188
  diags.push({
1183
1189
  level: 'error',
1184
1190
  code: 'UNKNOWN_LOOP_FIELD',
1185
1191
  message: `Loop "${name}" has no output "${field}" (read as "$vars.${name}.${field}" in "${step}"). `
1186
- + `A loop exposes: ${[...LOOP_FIELDS].join(', ')}.`,
1192
+ + `A loop exposes: ${[...loopFields].join(', ')}.`
1193
+ + (renamed
1194
+ ? ' `currentIndex` (0-based) is the legacy loop 1.0.0 output; loop 2.4 — the default — names it '
1195
+ + '`currentIteration` and counts from 1, so a 0-based index is `currentIteration - 1`.'
1196
+ : ''),
1187
1197
  step,
1188
- suggestion: `$vars.${name}.currentItem`,
1198
+ suggestion: renamed ? `$vars.${name}.currentIteration - 1` : `$vars.${name}.currentItem`,
1189
1199
  });
1190
1200
  }
1191
1201
  }
@@ -5330,11 +5340,18 @@ function checkCaseValueTypes(s, typeOf, diags, triggerId) {
5330
5340
  }
5331
5341
  }
5332
5342
  /**
5333
- * The outputs a `core.logic.loop` node exposes. `currentItem`/`currentIndex` are
5334
- * the per-iteration values a body reads; `collection` is what it iterates;
5335
- * `output` is the aggregate (after the loop) and `error` the failure detail.
5343
+ * The outputs a `core.logic.loop@2.4` node — the `.loop()` default — exposes.
5344
+ * `currentItem`/`currentIteration` (1-based) are the per-iteration values a body
5345
+ * reads; `collection` is what it iterates; `output` is the aggregate (after the
5346
+ * loop) and `error` the failure detail.
5336
5347
  */
5337
- const LOOP_FIELDS = new Set(['currentItem', 'currentIndex', 'collection', 'output', 'error']);
5348
+ const LOOP_FIELDS = new Set(['currentItem', 'currentIteration', 'collection', 'output', 'error']);
5349
+ /**
5350
+ * The same for a loop pinned to `{ version: '1.0.0' }`, whose per-iteration
5351
+ * counter is the 0-based `currentIndex`. `.doWhile()` keeps this set as it had
5352
+ * before the 2.4 default (#868); its own fields are not audited here.
5353
+ */
5354
+ const LOOP_FIELDS_1_0_0 = new Set(['currentItem', 'currentIndex', 'collection', 'output', 'error']);
5338
5355
  /**
5339
5356
  * Columns Data Fabric assigns and never accepts a write for.
5340
5357
  *
@@ -5865,12 +5882,12 @@ function checkStepRefs(built, diags) {
5865
5882
  const targetScope = scopeOf.get(target) ?? '';
5866
5883
  if (targetScope !== scope) {
5867
5884
  // INTO a loop body is provably wrong, and not merely for containment: the
5868
- // body reads `currentItem` / `currentIndex`, which only an ITERATION gives a
5885
+ // body reads `currentItem` / `currentIteration`, which only an ITERATION gives a
5869
5886
  // value. An edge that arrives from outside is not an iteration, so those
5870
5887
  // reads have nothing to resolve to.
5871
5888
  if (targetScope !== '') {
5872
5889
  say('error', 'REF_INTO_LOOP', `.stepToRef('${target}') ${where} points INTO the body of loop "${targetScope}". A loop body runs per `
5873
- + `ITERATION and reads currentItem / currentIndex from it; an edge arriving from outside carries no `
5890
+ + `ITERATION and reads currentItem / currentIteration from it; an edge arriving from outside carries no `
5874
5891
  + `iteration, so those have no value. Point at a step after the loop, or do this work inside the body.`);
5875
5892
  continue;
5876
5893
  }
@@ -384,12 +384,11 @@ export interface ReturnOptions extends NodeOptions {
384
384
  name?: string;
385
385
  }
386
386
  /**
387
- * Loop-specific options. Any of these — or a `b.break()` in the
388
- * body — selects the loop's v2.4 definition (the current Workbench contract,
389
- * with inner `start`/`continue`/`break` handles); a plain `.loop()` keeps the
390
- * SDK's long-pinned 1.0.0 emission unchanged. An explicit `{ version: '1.0.0' }`
391
- * combined with any of these fails compilation: that definition cannot express
392
- * them.
387
+ * Loop-specific options. Every `.loop()` emits the loop's v2.4 definition (the
388
+ * version the registry serves: inner `start`/`continue`/`break` handles, and a
389
+ * 1-based `currentIteration` output). The legacy 1.0.0 shape is emitted only for
390
+ * an explicit `{ version: '1.0.0' }`, and that combined with any of these options
391
+ * fails compilation: that definition cannot express them.
393
392
  */
394
393
  export interface LoopOptions extends NodeOptions {
395
394
  /** Run iterations in parallel instead of sequentially. */
package/dist/serialize.js CHANGED
@@ -32,9 +32,10 @@ import { QUEUE_ITEM_RECORD_SCHEMA } from './core/queue-record.js';
32
32
  const HERE = dirname(fileURLToPath(import.meta.url));
33
33
  // core-definitions.json is an object keyed by "<nodeType>@<version>".
34
34
  const DEFS = JSON.parse(readFileSync(join(HERE, 'core-definitions.json'), 'utf8'));
35
- // FIRST occurrence wins: with multiple bundled versions of one family (loop
36
- // 1.0.0 + 2.4), the unversioned lookup must stay the pinned default, not
37
- // whichever entry happens to be last in the JSON.
35
+ // FIRST occurrence wins: with multiple bundled versions of one family (HITL
36
+ // 1.0 / 1.1 / 1.2), the unversioned lookup must stay the pinned default, not
37
+ // whichever entry happens to be last in the JSON. (`.loop()` always passes its
38
+ // version — 2.4 unless `{ version: '1.0.0' }` is pinned — so it never reads this.)
38
39
  const defByType = new Map();
39
40
  for (const d of Object.values(DEFS))
40
41
  if (!defByType.has(d.nodeType))
@@ -5981,13 +5982,14 @@ export function serialize(built, opts = {}) {
5981
5982
  else if (step.kind === 'loop') {
5982
5983
  const o = step.options ?? {};
5983
5984
  const usesBreak = bodyUsesBreak(step.body);
5984
- // Rich loop semantics live in the v2.4 contract (inner start/continue/
5985
- // break handles). A plain .loop() keeps the long-pinned 1.0.0 emission
5986
- // byte-for-byte; any rich option — or a break in the body — selects 2.4
5987
- // as its deterministic pinned default. An explicit 1.0.0 plus a rich
5988
- // option is a contradiction the author must resolve, not a silent drop.
5985
+ // Every .loop() defaults to 2.4 — the version the registry serves and the
5986
+ // designer authors (inner start/continue/break handles, `currentIteration`
5987
+ // output). 1.0.0 is the legacy shape the canvas shows in its old form; it
5988
+ // is emitted only when { version: '1.0.0' } is pinned explicitly (#868).
5989
+ // An explicit 1.0.0 plus a rich option is a contradiction the author must
5990
+ // resolve, not a silent drop.
5989
5991
  const rich = o.parallel !== undefined || o.completionCondition !== undefined || o.breakEnabled !== undefined || usesBreak;
5990
- const version = o.version ?? (rich ? '2.4' : '1.0.0');
5992
+ const version = o.version ?? '2.4';
5991
5993
  if (rich && version === '1.0.0') {
5992
5994
  throw new Error(`loop "${step.name}": parallel/completionCondition/breakEnabled/break() need the loop's 2.4 `
5993
5995
  + `definition, but { version: '1.0.0' } was requested. Drop the version or request 2.4.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.14.0",
3
+ "version": "6.14.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",
@@ -92,5 +92,5 @@
92
92
  "@types/node": "^22.7.0",
93
93
  "esbuild": "^0.28.1"
94
94
  },
95
- "gitref": "84bd49a28ffaae311bcb7b3207a311dfeaf1c08f"
95
+ "gitref": "cb7a821ea17b6f3022c7b90e2567e91a5495576a"
96
96
  }