@uipath/maestro-builder-sdk 6.47.2 → 6.47.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.
@@ -20,6 +20,8 @@ import { createConnectorEvent, createExternalTask, intsvcOutputVar } from './int
20
20
  import { createExtensionPayload, createTypedNode, rowDeclaration, typedNodeOutputVar, verbatimOutputRows } from './typed-node.js';
21
21
  import { connectorOutputVars, typedNodeDeclaredVars } from './declared-vars.js';
22
22
  import { defaultEntryPointId } from './entry-point-id.js';
23
+ import { parseXmlRanges } from './xml-ranges.js';
24
+ import { ownEntry } from '../core/own-entry.js';
23
25
  const require = createRequire(import.meta.url);
24
26
  const uipathDescriptor = require('./uipath-moddle.v1.json');
25
27
  const NS = {
@@ -181,6 +183,22 @@ export async function serialize(built, opts = {}) {
181
183
  * of the trade. Revisit if the graders learn to treat absence as interrupting.
182
184
  */
183
185
  export function finalizeBpmnXml(xml) {
186
+ return jsonInputBodiesAsCdata(outsideCdata(xml, normalizeMarkup));
187
+ }
188
+ /**
189
+ * Apply `edit` to the markup only — never inside a CDATA section or a comment.
190
+ *
191
+ * The passes below are patterns over the text, and a CDATA payload is author data: a
192
+ * JSON value holding the literal `&#60;` or `<bpmn:boundaryEvent>` must come out of a
193
+ * second `finalizeBpmnXml` (or `tidy`) byte for byte, not rewritten as markup.
194
+ */
195
+ function outsideCdata(xml, edit) {
196
+ return xml
197
+ .split(/(<!\[CDATA\[[\s\S]*?\]\]>|<!--[\s\S]*?-->)/)
198
+ .map((part, i) => (i % 2 === 1 ? part : edit(part)))
199
+ .join('');
200
+ }
201
+ function normalizeMarkup(xml) {
184
202
  return (xml
185
203
  .replace(/<bpmn:boundaryEvent\b(?![^>]*\bcancelActivity=)([^>]*?)(\/?)>/g, '<bpmn:boundaryEvent cancelActivity="true"$1$2>')
186
204
  // Same reason, other schema default: a PARALLEL multi-instance marker is
@@ -206,6 +224,81 @@ export function finalizeBpmnXml(xml) {
206
224
  .replace(/&#(?:34|x22);/g, '&quot;')
207
225
  .replace(/&#(?:39|x27);/g, '&apos;'));
208
226
  }
227
+ /**
228
+ * Rewrite every json `uipath:input` text body as CDATA — the one body shape the cloud
229
+ * engine reads.
230
+ *
231
+ * `PO.BpmnEngine`'s `UiPathExtensionsProvider` (`ExtractContextInputs`,
232
+ * `ExtractActivityInputs`) takes an input's value from an `XCData` child or a `value`
233
+ * attribute and filters out any row with neither. moddle writes a body as entity-escaped
234
+ * TEXT, which is neither, so the engine silently dropped every json input the SDK
235
+ * authored: a script task ran with no `args` (`vars is not defined`), a connector task
236
+ * sent no body. `check`, `compile` and `uip maestro bpmn validate` all read text and
237
+ * CDATA alike, so nothing caught it before the run (#1390). Studio Web writes CDATA.
238
+ *
239
+ * moddle has no CDATA option for a body property, so this rewrites its output — by
240
+ * element range (`xml-ranges.ts`), not a pattern over the document. It runs LAST in
241
+ * `finalizeBpmnXml`, after the markup passes, which skip CDATA (`outsideCdata`), so no
242
+ * pass reaches into a payload this writes. An input whose content is not plain text (already CDATA,
243
+ * as `tidy` may hand it, or empty) is left alone, so this is idempotent.
244
+ */
245
+ function jsonInputBodiesAsCdata(xml) {
246
+ const bodies = [];
247
+ const collect = (nodes) => {
248
+ for (const node of nodes) {
249
+ if (node.name === 'uipath:input' && node.attributes.type === 'json')
250
+ bodies.push(node);
251
+ else
252
+ collect(node.children);
253
+ }
254
+ };
255
+ collect(parseXmlRanges(xml));
256
+ let out = xml;
257
+ // Splice from the end so the earlier offsets stay valid.
258
+ for (const input of bodies.sort((a, b) => b.innerStart - a.innerStart)) {
259
+ const text = xml.slice(input.innerStart, input.innerEnd);
260
+ if (text === '' || text.includes('<'))
261
+ continue;
262
+ out = out.slice(0, input.innerStart) + cdata(input.attributes.name ?? '', decodeXmlText(text)) + out.slice(input.innerEnd);
263
+ }
264
+ return out;
265
+ }
266
+ const NAMED_ENTITY = { lt: '<', gt: '>', amp: '&', quot: '"', apos: "'" };
267
+ /** Decode XML character data in one pass, so `&amp;lt;` stays the text `&lt;`. */
268
+ function decodeXmlText(text) {
269
+ return text.replace(/&(?:#(\d+)|#x([0-9a-fA-F]+)|(lt|gt|amp|quot|apos));/g, (_, dec, hex, named) => dec !== undefined
270
+ ? String.fromCodePoint(Number(dec))
271
+ : hex !== undefined
272
+ ? String.fromCodePoint(parseInt(hex, 16))
273
+ : ownEntry(NAMED_ENTITY, named));
274
+ }
275
+ /**
276
+ * ONE CDATA section holding `text`'s value.
277
+ *
278
+ * A `]]>` cannot sit in a CDATA section, and splitting it across two is no answer: the
279
+ * engine reads the FIRST `XCData` child only (`OfType<XCData>().FirstOrDefault()`), so it
280
+ * would get the JSON cut off at the split. In valid JSON a `]]>` can only sit inside a
281
+ * string (`>` is not JSON outside one), so its `>` is written as the escape `\u003e` —
282
+ * different bytes, the same value. A body that is not JSON has no such escape and could
283
+ * only reach the engine truncated, so it is refused.
284
+ */
285
+ function cdata(name, text) {
286
+ if (!text.includes(']]>'))
287
+ return `<![CDATA[${text}]]>`;
288
+ let value;
289
+ try {
290
+ value = JSON.parse(text);
291
+ }
292
+ catch {
293
+ throw new Error(`json input "${name}" contains "]]>" and is not valid JSON, so it cannot be written as the single CDATA section the engine reads.`);
294
+ }
295
+ const escaped = text.replaceAll(']]>', ']]\\u003e');
296
+ // Holds by the argument above; checked because a wrong payload here would be silent.
297
+ if (JSON.stringify(JSON.parse(escaped)) !== JSON.stringify(value)) {
298
+ throw new Error(`json input "${name}": escaping "]]>" changed its value.`);
299
+ }
300
+ return `<![CDATA[${escaped}]]>`;
301
+ }
209
302
  export function processId(id) {
210
303
  return /^[A-Za-z_][\w.-]*$/.test(id) ? id : 'Process_1';
211
304
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.47.2",
3
+ "version": "6.47.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",
@@ -93,5 +93,5 @@
93
93
  "@types/node": "^22.7.0",
94
94
  "esbuild": "^0.28.1"
95
95
  },
96
- "gitref": "16b96902c3da22af8e0fc3cfc8a53edcc832f04c"
96
+ "gitref": "fc36fa72238f803ed2de5a02dc8a42f6c5d3305d"
97
97
  }