@uipath/maestro-builder-sdk 6.25.1 → 6.27.0

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
@@ -19,7 +19,8 @@ import { planContributionBindings } from './core/contribution-bindings.js';
19
19
  import { declaredErrorPortRefusal, definitionHasErrorPort, errorPortRefusal } from './core/error-port.js';
20
20
  import { FLOW_NODE_TYPES } from './flow-node-registry.js';
21
21
  import { stepExits } from './flow-step-exits.js';
22
- import { resolveVersion } from './core/nodes/versioned.js';
22
+ import { resolveVersionCarried } from './core/nodes/versioned.js';
23
+ import { indexCarriedDefinitions } from './core/carried-definitions.js';
23
24
  import { FORM_FIELD_JSON_TYPE } from './core/form-field-type.js';
24
25
  import { connectionConnectors } from './bindings-v2.js';
25
26
  import { BindingRefusal, GUID_RE, bindingLabelRefusal, bindingMissingMessage, missingBindingLabels } from './core/binding-messages.js';
@@ -2271,8 +2272,8 @@ function declaresMemoryHandle(def) {
2271
2272
  * compiles. The corpus also carries 1.1 and 1.3; `shared/sample-flows/
2272
2273
  * inline-agent.flow` says 1.0, which appears in none of the 29.
2273
2274
  */
2274
- function inlineAgentDef(version, withMemory) {
2275
- const bundled = DEFS[`${INLINE_AGENT_TYPE}@${version}`];
2275
+ function inlineAgentDef(version, withMemory, resolve = (t, v) => DEFS[`${t}@${v}`]) {
2276
+ const bundled = resolve(INLINE_AGENT_TYPE, version);
2276
2277
  if (!bundled)
2277
2278
  return undefined;
2278
2279
  const def = jsonClone(bundled);
@@ -4240,6 +4241,17 @@ function stepNamesOf(steps, out = []) {
4240
4241
  return out;
4241
4242
  }
4242
4243
  export function serialize(built, opts = {}) {
4244
+ /**
4245
+ * Definitions the flow carries (`.definitions()`, #1128), by `type@version` —
4246
+ * the third source a pinned `{ version }` resolves from, after the bundle and
4247
+ * the node-type registry. A flow that carries nothing compiles exactly as
4248
+ * before. A subflow body sees its own carried definitions plus its
4249
+ * ancestors' (as `check` does), only while it is emitted.
4250
+ */
4251
+ let carriedDefs = indexCarriedDefinitions(built.definitions ?? [], `flow "${built.id}" .definitions()`);
4252
+ const carriedFor = Object.assign((type, version) => carriedDefs.get(`${type}@${version}`), { versions: (type) => [...carriedDefs.keys()].filter((k) => k.startsWith(`${type}@`)).map((k) => k.slice(type.length + 1)) });
4253
+ /** The exact definition of `type@version`: bundled, else carried, else `undefined`. */
4254
+ const definitionFor = (type, version) => DEFS[`${type}@${version}`] ?? carriedFor(type, version);
4243
4255
  /**
4244
4256
  * The `definitions[]` a flow carries, keyed by `type@version` — NOT by type.
4245
4257
  * One flow can legitimately hold two versions of the same family (a plain
@@ -4451,19 +4463,22 @@ export function serialize(built, opts = {}) {
4451
4463
  function makeNode(type, id, label, o = {}) {
4452
4464
  let def = o.def ?? defByType.get(type);
4453
4465
  if (o.requestedVersion !== undefined && def?.version !== o.requestedVersion) {
4454
- const exact = o.def ? undefined : DEFS[`${type}@${o.requestedVersion}`];
4466
+ const exact = o.def ? undefined : definitionFor(type, o.requestedVersion);
4455
4467
  if (!exact) {
4456
- // Name every version the SDK could have resolved: every bundled
4457
- // version of the type, else (a type built per resource, a connector)
4458
- // the definition in hand. Naming only the default sent the reader
4459
- // looking for a version that was shipped all along (#1128:
4468
+ // Name every version the SDK could have resolved: every bundled or
4469
+ // carried version of the type, else (a type built per resource, a
4470
+ // connector) the definition in hand. Naming only the default sent the
4471
+ // reader looking for a version that was shipped all along (#1128:
4460
4472
  // quick-form bundles 1.0 AND 1.1, and the message said 1.0).
4461
- const bundled = bundledVersions(type);
4462
- const resolvable = bundled.length > 0 ? bundled
4473
+ const prefix = `${type}@`;
4474
+ const carriedVersions = [...carriedDefs.keys()].filter((k) => k.startsWith(prefix)).map((k) => k.slice(prefix.length));
4475
+ const known = o.def ? [] : [...bundledVersions(type), ...carriedVersions];
4476
+ const resolvable = known.length > 0 ? known
4463
4477
  : [def?.version].filter((v) => typeof v === 'string');
4464
4478
  throw new Error(`"${label ?? id}" requests ${type}@${o.requestedVersion}, but this SDK resolves only `
4465
4479
  + `${type}@${resolvable.join(', ') || '<none>'}. Versions are exact — omit { version } to use `
4466
- + `the pinned default, or request a version this SDK ships.`);
4480
+ + `the pinned default, request a version this SDK ships, or carry that version's definition `
4481
+ + `(the .flow file's definitions[] entry) with .definitions([...]).`);
4467
4482
  }
4468
4483
  def = exact;
4469
4484
  }
@@ -4532,6 +4547,16 @@ export function serialize(built, opts = {}) {
4532
4547
  * a null. It is emitted here, always, so it cannot be forgotten.
4533
4548
  */
4534
4549
  function emitSubflowBody(child, nodeId) {
4550
+ const outer = carriedDefs;
4551
+ carriedDefs = indexCarriedDefinitions(child.definitions ?? [], `subflow "${nodeId}" .definitions()`, new Map(outer));
4552
+ try {
4553
+ return emitSubflowBodyIn(child, nodeId);
4554
+ }
4555
+ finally {
4556
+ carriedDefs = outer;
4557
+ }
4558
+ }
4559
+ function emitSubflowBodyIn(child, nodeId) {
4535
4560
  const childGlobals = emittableGlobals(child, `subflow "${nodeId}"`, 'subflow');
4536
4561
  const scope = newScope(childGlobals.outputs, childGlobals.vars, childGlobals.backing, childGlobals.backingReads);
4537
4562
  // Claim this copy's node ids UP FRONT, so the rename map is complete before
@@ -4807,7 +4832,11 @@ export function serialize(built, opts = {}) {
4807
4832
  function emitRegistered(entry, step, tails, scope, parentId) {
4808
4833
  const where = `step "${step.name}"`;
4809
4834
  const spec = step.spec;
4810
- const impl = resolveVersion(entry.type, spec, step.options?.version, where);
4835
+ // A pin the registry has no implementation for, but the flow carries, is
4836
+ // emitted at that version with the carried definition (#1128).
4837
+ const resolved = resolveVersionCarried(entry.type, spec, step.options?.version, where, carriedFor);
4838
+ const impl = resolved.impl;
4839
+ const version = resolved.version;
4811
4840
  const id = stepUid(scope, step.name);
4812
4841
  // As for every typed family: record the failure-envelope boundary before any
4813
4842
  // expression renders, so a handler reading this step resolves correctly.
@@ -4817,14 +4846,19 @@ export function serialize(built, opts = {}) {
4817
4846
  step: step.name,
4818
4847
  nodeId: id,
4819
4848
  flowId: built.id,
4820
- version: impl.version,
4849
+ version,
4821
4850
  pinnedVersion: step.options?.version,
4822
4851
  render: (value) => renderValue(value, scope.rename),
4823
4852
  renameRefs: (js) => renameRefs(js, scope.rename),
4824
4853
  stepNodeId: (name) => scope.stepNodeId.get(name) ?? name,
4825
4854
  mint: (seed) => stableId(`${built.id}:${id}:${seed}`),
4826
4855
  bind: (b) => { bound.push(b); },
4827
- definition: (typeName, version) => bundledDefinition(typeName, version),
4856
+ // At a carried version the node's own definition IS the carried one,
4857
+ // whatever version the implementation asks for (it was written for a
4858
+ // bundled one), so its defaults and outputs come from the file's entry.
4859
+ definition: (typeName, v) => (resolved.carried !== undefined && typeName === impl.typeName
4860
+ ? resolved.carried
4861
+ : bundledDefinition(typeName, v) ?? carriedFor(typeName, v)),
4828
4862
  bindings: resourceBindings,
4829
4863
  resolveBinding: (name, attribute, at) => resolveBinding(opts, name, attribute, at),
4830
4864
  bindConnection: (c) => {
@@ -4843,26 +4877,31 @@ export function serialize(built, opts = {}) {
4843
4877
  // The definition contract, both halves: a per-tenant type supplies its
4844
4878
  // definition, and a bundled type does not (its definition is the bundle's, and
4845
4879
  // makeNode records it, so the error-edge refusal and check ask the same one).
4846
- let def;
4880
+ let def = resolved.carried;
4847
4881
  if (impl.definition === 'bundled' && contribution.definition !== undefined) {
4848
- throw new Error(`internal SDK error: ${where}: bundled node type ${impl.typeName}@${impl.version} returned a definition; `
4882
+ throw new Error(`internal SDK error: ${where}: bundled node type ${impl.typeName}@${version} returned a definition; `
4849
4883
  + 'the bundle owns it — omit `definition`, or declare the type per-tenant.');
4850
4884
  }
4885
+ // A per-tenant type builds its definition from `ctx.definition(type, version)`,
4886
+ // which answers with the carried definition at a carried version, so the
4887
+ // contribution's own definition wins: it is the carried template plus this
4888
+ // instance's edits (a queue step's own resourceKey, for instance). Only a type
4889
+ // that supplies none at a carried version takes the carried definition as is.
4851
4890
  if (contribution.definition !== undefined) {
4852
- def = resolveContributionDefinition(contribution.definition, impl.version, where);
4891
+ def = resolveContributionDefinition(contribution.definition, version, where);
4853
4892
  }
4854
- else if (impl.definition === 'per-tenant') {
4855
- throw new Error(`internal SDK error: ${where}: per-tenant node type ${impl.typeName}@${impl.version} returned no definition.`);
4893
+ else if (impl.definition === 'per-tenant' && resolved.carried === undefined) {
4894
+ throw new Error(`internal SDK error: ${where}: per-tenant node type ${impl.typeName}@${version} returned no definition.`);
4856
4895
  }
4857
4896
  if (impl.definition === 'per-tenant') {
4858
4897
  const port = typeof impl.errorPort === 'function' ? impl.errorPort(spec) : impl.errorPort === true;
4859
4898
  // The declaration answers for check, which has no definition; here the
4860
4899
  // definition is in hand, and the two must agree (#1011).
4861
4900
  if (port && def !== undefined && !definitionHasErrorPort(def)) {
4862
- throw new Error(`internal SDK error: ${where}: node type ${impl.typeName}@${impl.version} declares an error port, `
4901
+ throw new Error(`internal SDK error: ${where}: node type ${impl.typeName}@${version} declares an error port, `
4863
4902
  + 'but the definition it supplied has no error handle and no supportsErrorHandling.');
4864
4903
  }
4865
- declaredErrorPorts.set(id, { port, typeName: impl.typeName, version: impl.version });
4904
+ declaredErrorPorts.set(id, { port, typeName: impl.typeName, version });
4866
4905
  }
4867
4906
  // A forward port is a handle the definition declares, one of the type's
4868
4907
  // author-named exits, or one the product derives (`derivesPort`: a human
@@ -4871,13 +4910,17 @@ export function serialize(built, opts = {}) {
4871
4910
  const exitPorts = new Set(exits && hasExits(exits) ? exits.map((e) => e.port) : []);
4872
4911
  for (const p of [...(contribution.port !== undefined ? [contribution.port] : []), ...(contribution.fanOut ?? []).map((f) => f.port)]) {
4873
4912
  if (exitPorts.has(p) || impl.derivesPort?.(spec, p)
4874
- || declaresForwardPort(def ?? bundledDefinition(impl.typeName, impl.version), p))
4913
+ || declaresForwardPort(def ?? bundledDefinition(impl.typeName, version), p))
4875
4914
  continue;
4876
- throw new Error(`internal SDK error: ${where}: node type ${impl.typeName}@${impl.version} leaves by port "${p}", `
4915
+ throw new Error(`internal SDK error: ${where}: node type ${impl.typeName}@${version} leaves by port "${p}", `
4877
4916
  + 'which its definition declares no source handle for, and the type neither lists as an exit nor derives.');
4878
4917
  }
4918
+ // A carried definition answers the error-edge refusal as a bundled one does
4919
+ // (makeNode records only the definitions it resolved itself).
4920
+ if (resolved.carried !== undefined)
4921
+ bundledNodeDefs.set(id, def ?? resolved.carried);
4879
4922
  return placeStepNode({
4880
- where, stepName: step.name, id, typeName: impl.typeName, requestedVersion: impl.version, def, contribution, bound, tails, scope, parentId,
4923
+ where, stepName: step.name, id, typeName: impl.typeName, requestedVersion: version, def, contribution, bound, tails, scope, parentId,
4881
4924
  trackOutcomes: true,
4882
4925
  });
4883
4926
  }
@@ -5041,11 +5084,12 @@ export function serialize(built, opts = {}) {
5041
5084
  // agent attaches memory keeps the handle for all of them.
5042
5085
  const withMemory = s.memory !== undefined
5043
5086
  || declaresMemoryHandle(emittedDefs.get(`${INLINE_AGENT_TYPE}@${version}`));
5044
- const def = inlineAgentDef(version, withMemory);
5087
+ const def = inlineAgentDef(version, withMemory, definitionFor);
5045
5088
  if (!def) {
5046
5089
  throw new Error(`"${step.name}" requests ${INLINE_AGENT_TYPE}@${version}, but this SDK resolves only `
5047
5090
  + `${INLINE_AGENT_VERSIONS.map((v) => `${INLINE_AGENT_TYPE}@${v}`).join(', ')}. Versions are exact — `
5048
- + `omit { version } to use the default (${INLINE_AGENT_DEFAULT_VERSION}), or request a version this SDK ships.`);
5091
+ + `omit { version } to use the default (${INLINE_AGENT_DEFAULT_VERSION}), request a version this SDK ships, `
5092
+ + `or carry that version's definition with .definitions([...]).`);
5049
5093
  }
5050
5094
  if (s.memory !== undefined && !declaresMemoryHandle(def)) {
5051
5095
  throw new Error(`"${step.name}" attaches \`memory\`, but ${INLINE_AGENT_TYPE}@${version} declares no \`memory\` handle. `
@@ -6127,8 +6171,12 @@ export function serialize(built, opts = {}) {
6127
6171
  // must leave from ITS handles), else positional (#1130).
6128
6172
  const cases = step.cases.map((c, i) => ({
6129
6173
  id: c.id ?? `case_${i + 1}`,
6130
- label: c.label ?? `Case ${caseLiteral(c.value)}`,
6131
- expression: `${renameRefs(step.on.js, scope.rename)} === ${caseLiteral(c.value)}`,
6174
+ // A `when` case writes its own condition — the product's per-case form,
6175
+ // first truthy case wins (#1131). A `value` case compares with `on`.
6176
+ label: c.label ?? (c.when !== undefined ? `Case ${i + 1}` : `Case ${caseLiteral(c.value)}`),
6177
+ expression: c.when !== undefined
6178
+ ? renameRefs(c.when.js, scope.rename)
6179
+ : `${renameRefs(step.on?.js ?? 'undefined', scope.rename)} === ${caseLiteral(c.value)}`,
6132
6180
  }));
6133
6181
  node.inputs = { cases, hasDefault: step.default !== undefined };
6134
6182
  scope.nodes.push(node);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.25.1",
3
+ "version": "6.27.0",
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": "384f76113bc43067b5ec5ea700534e9611e664ff"
95
+ "gitref": "69352e3f5c7c379e0e70b3c7b6fb2fba91255f84"
96
96
  }