@uipath/maestro-builder-sdk 6.46.6 → 6.47.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/api-index.md +71 -69
- package/dist/api-members.md +216 -210
- package/dist/case/business-event-shape.d.ts +27 -0
- package/dist/case/business-event-shape.js +45 -0
- package/dist/case/case-sdk.d.ts +46 -1
- package/dist/case/case-sdk.js +16 -0
- package/dist/case/check.js +31 -1
- package/dist/case/decompile.d.ts +7 -0
- package/dist/case/decompile.js +52 -3
- package/dist/case/ids.d.ts +26 -0
- package/dist/case/ids.js +49 -0
- package/dist/case/preserve.js +1 -1
- package/dist/case/rule-options.d.ts +15 -0
- package/dist/case/rule-options.js +46 -0
- package/dist/case/serialize.js +86 -4
- package/package.json +2 -2
package/dist/case/serialize.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* `metadata.caseExitRules`. Symbolic references in rules (a stage label, a task
|
|
9
9
|
* name) are resolved here to the generated ids.
|
|
10
10
|
*/
|
|
11
|
-
import { IdGen } from './ids.js';
|
|
11
|
+
import { IdGen, offlineBindingSeed } from './ids.js';
|
|
12
12
|
import { isUnrestorableSlotId } from './preserve.js';
|
|
13
13
|
import { v31TaskSets } from './task-sets.js';
|
|
14
14
|
import { buildConnectorInputs, nestConnectorBody, transportHttpMethod } from '../core/connector-inputs.js';
|
|
@@ -22,7 +22,9 @@ import { isResourceLabelRefusal, resolveResourceRef, resourceIdentity } from './
|
|
|
22
22
|
import { ownEntry } from '../core/own-entry.js';
|
|
23
23
|
import { resolveSchemaVersion } from '../schema-version.js';
|
|
24
24
|
import { caseJsonPreservation, caseJsonPreservationErrors, } from './preserve.js';
|
|
25
|
+
import { businessEventProblems } from './business-event-shape.js';
|
|
25
26
|
import { readEventFilter, eventFilterProblem, eventFilterTreeLeaf } from '../core/event-filters.js';
|
|
27
|
+
import { ruleShapeProblems } from './rule-options.js';
|
|
26
28
|
/**
|
|
27
29
|
* Condition `displayName` allocator.
|
|
28
30
|
*
|
|
@@ -81,6 +83,8 @@ export function serialize(built, opts = {}) {
|
|
|
81
83
|
library: opts.library,
|
|
82
84
|
bindings: opts.bindings,
|
|
83
85
|
bindingSink: new Map(),
|
|
86
|
+
ids,
|
|
87
|
+
offlineBindingIds: new Map(),
|
|
84
88
|
varCompanions: new Map(),
|
|
85
89
|
outputIds: new Set(),
|
|
86
90
|
ownOutputVars: ownOutputVars(built),
|
|
@@ -88,6 +92,7 @@ export function serialize(built, opts = {}) {
|
|
|
88
92
|
slaIdByName: new Map(),
|
|
89
93
|
escalationId: new Map(),
|
|
90
94
|
escalationIdByName: new Map(),
|
|
95
|
+
businessEvents: new Set((built.businessEvents ?? []).map((event) => event.name)),
|
|
91
96
|
conditionName: conditionNamer(built),
|
|
92
97
|
};
|
|
93
98
|
// Preallocate SLA + escalation ids (before any rule is emitted) so a
|
|
@@ -219,6 +224,12 @@ export function serialize(built, opts = {}) {
|
|
|
219
224
|
if (built.slaRules.length) {
|
|
220
225
|
metadata.slaRules = built.slaRules.map((s, i, all) => emitSla(s, i, all.length, ids, resolver));
|
|
221
226
|
}
|
|
227
|
+
if (built.businessEvents?.length) {
|
|
228
|
+
const [problem] = businessEventProblems(built.businessEvents);
|
|
229
|
+
if (problem)
|
|
230
|
+
throw new Error(problem.message);
|
|
231
|
+
metadata.businessEvents = built.businessEvents.map(emitBusinessEvent);
|
|
232
|
+
}
|
|
222
233
|
// Variables: declared vars + the readable companions that task outputs bound
|
|
223
234
|
// (collected during stage emission above). A declared var wins on a name clash.
|
|
224
235
|
const variables = emitVariables(built.vars, ids, triggerNodeByRef);
|
|
@@ -1469,6 +1480,20 @@ function ioSlot(name, bodyObj, elementId) {
|
|
|
1469
1480
|
const v = `v${name}`;
|
|
1470
1481
|
return { name, type: 'json', target: name, body: bodyObj, var: v, id: v, elementId };
|
|
1471
1482
|
}
|
|
1483
|
+
/**
|
|
1484
|
+
* The binding id for a label no bindings.json declares. The row's
|
|
1485
|
+
* `resourceKey`/`default` stays the label, and the id is minted from it (`b` +
|
|
1486
|
+
* 8, as Studio Web mints one), once per label; `offlineBindingLabel` reverses
|
|
1487
|
+
* it for decompile.
|
|
1488
|
+
*/
|
|
1489
|
+
function offlineBindingId(resolver, seed) {
|
|
1490
|
+
let id = resolver.offlineBindingIds.get(seed);
|
|
1491
|
+
if (id === undefined) {
|
|
1492
|
+
id = resolver.ids.make('b', 8, seed);
|
|
1493
|
+
resolver.offlineBindingIds.set(seed, id);
|
|
1494
|
+
}
|
|
1495
|
+
return id;
|
|
1496
|
+
}
|
|
1472
1497
|
/** Resolve a symbolic connection/folder to a root binding entry (collected once),
|
|
1473
1498
|
* returning its id + resourceKey for the `=bindings.<id>` reference. */
|
|
1474
1499
|
function bindingRef(resolver, name, resource, propertyAttribute, displayName, site) {
|
|
@@ -1483,8 +1508,12 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
|
|
|
1483
1508
|
if (refused)
|
|
1484
1509
|
throw refused;
|
|
1485
1510
|
const entry = resolver.bindings?.entry(name);
|
|
1486
|
-
const id = entry?.id ?? name;
|
|
1487
1511
|
const resourceKey = entry?.resourceKey ?? entry?.default ?? name;
|
|
1512
|
+
// Only a label with no bindings.json entry gets a minted id: an entry's
|
|
1513
|
+
// `resourceKey` is the real key, so its id (or its name) cannot clash with it.
|
|
1514
|
+
const id = entry
|
|
1515
|
+
? String(entry.id ?? name)
|
|
1516
|
+
: offlineBindingId(resolver, offlineBindingSeed(resource, propertyAttribute, name));
|
|
1488
1517
|
if (!resolver.bindingSink.has(id)) {
|
|
1489
1518
|
resolver.bindingSink.set(id, {
|
|
1490
1519
|
id,
|
|
@@ -1501,7 +1530,8 @@ function bindingRef(resolver, name, resource, propertyAttribute, displayName, si
|
|
|
1501
1530
|
/**
|
|
1502
1531
|
* A connector's folder is a property of its connection:
|
|
1503
1532
|
* { resourceKey: <connection key>, default: <folder key>, propertyAttribute: 'folderKey' }.
|
|
1504
|
-
* One folder label on two connections gets one row each: `shared`, `shared_2
|
|
1533
|
+
* One folder label on two connections gets one row each: `shared`, `shared_2`
|
|
1534
|
+
* (offline, the minted id is seeded on the connection, so the rows differ anyway).
|
|
1505
1535
|
* One connection with two different folders is refused: a connection lives in
|
|
1506
1536
|
* one folder, and the syncs group rows by `resourceKey`, so one value would win.
|
|
1507
1537
|
* Without a connection the folder binds as a plain binding.
|
|
@@ -1515,7 +1545,9 @@ function folderBindingRef(resolver, name, connection, site) {
|
|
|
1515
1545
|
if (refused)
|
|
1516
1546
|
throw refused;
|
|
1517
1547
|
const entry = resolver.bindings?.entry(name);
|
|
1518
|
-
const baseId = entry
|
|
1548
|
+
const baseId = entry
|
|
1549
|
+
? String(entry.id ?? name)
|
|
1550
|
+
: offlineBindingId(resolver, offlineBindingSeed('Connection', 'folderKey', name, connection.resourceKey));
|
|
1519
1551
|
const folderKey = entry?.default ?? entry?.resourceKey ?? name;
|
|
1520
1552
|
const matches = (row) => row?.resourceKey === connection.resourceKey && row?.default === folderKey
|
|
1521
1553
|
&& row?.propertyAttribute === 'folderKey';
|
|
@@ -1722,6 +1754,9 @@ function emitRules(rules, seed, ownerId, ids, resolver, site) {
|
|
|
1722
1754
|
return rules.map((group, gi) => group.map((r, ri) => emitRule(r, `${seed}:${gi}:${ri}`, ownerId, ids, resolver, site)));
|
|
1723
1755
|
}
|
|
1724
1756
|
function emitRule(r, seed, ownerId, ids, resolver, site) {
|
|
1757
|
+
const [shape] = ruleShapeProblems(r);
|
|
1758
|
+
if (shape)
|
|
1759
|
+
throw new Error(`${shape.message.replace(/^Rule /, 'rule ')} (in ${site})`);
|
|
1725
1760
|
const ruleId = ids.ruleId(seed);
|
|
1726
1761
|
const out = { rule: r.rule, id: ruleId };
|
|
1727
1762
|
if (r.rule === 'selected-stage-completed' || r.rule === 'selected-stage-exited') {
|
|
@@ -1757,10 +1792,57 @@ function emitRule(r, seed, ownerId, ids, resolver, site) {
|
|
|
1757
1792
|
out.escalationId = escId;
|
|
1758
1793
|
}
|
|
1759
1794
|
}
|
|
1795
|
+
if (r.rule === 'api-event') {
|
|
1796
|
+
// The event is matched by its exact name at run time; a rule without one
|
|
1797
|
+
// listens for nothing, so both a missing and an undeclared name refuse.
|
|
1798
|
+
if (!r.businessEvent)
|
|
1799
|
+
throw new Error(`rule "api-event" in ${site} names no business event — write rule('api-event', { businessEvent: '<name>' }) with a name declared by .businessEvent('<name>').`);
|
|
1800
|
+
if (!resolver.businessEvents.has(r.businessEvent))
|
|
1801
|
+
throw new Error(`rule "api-event" in ${site} listens for business event "${r.businessEvent}", which the case does not declare — add .businessEvent(${JSON.stringify(r.businessEvent)}).`);
|
|
1802
|
+
out.businessEventType = r.businessEvent;
|
|
1803
|
+
}
|
|
1760
1804
|
if (r.expression)
|
|
1761
1805
|
out.conditionExpression = r.expression;
|
|
1762
1806
|
return out;
|
|
1763
1807
|
}
|
|
1808
|
+
const JSON_SCHEMA_DRAFT_7 = 'http://json-schema.org/draft-07/schema#';
|
|
1809
|
+
/**
|
|
1810
|
+
* True only for a payload that says nothing at all: `{}`, `{ type: 'object' }`
|
|
1811
|
+
* or `{ type: 'object', properties: {} }`. Any other key (`required`,
|
|
1812
|
+
* `$schema`, a non-object `type`, ...) is content the author wrote, so the
|
|
1813
|
+
* schema is written and survives a decompile/recompile round trip.
|
|
1814
|
+
*/
|
|
1815
|
+
function isEmptyObjectSchema(payload) {
|
|
1816
|
+
return Object.entries(payload).every(([key, value]) => {
|
|
1817
|
+
if (key === 'type')
|
|
1818
|
+
return value === 'object';
|
|
1819
|
+
if (key === 'properties')
|
|
1820
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;
|
|
1821
|
+
return false;
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
/**
|
|
1825
|
+
* One `metadata.businessEvents[]` entry, in the shape the Case Designer saves
|
|
1826
|
+
* (`{ name, description?, schema? }`). `schema` is the payload's JSON Schema
|
|
1827
|
+
* serialized to a string with `$schema` defaulted to draft 7. The payload is an
|
|
1828
|
+
* object or array schema (`businessEventProblems` refuses any other type before
|
|
1829
|
+
* this runs), and every one except the empty object schema
|
|
1830
|
+
* (`isEmptyObjectSchema`) is written. That keeps more than the Designer and `uip maestro case sdd
|
|
1831
|
+
* convert`, which write a schema only for `type: 'array'` or a non-empty
|
|
1832
|
+
* `properties`: `{ type: 'object', required: ['a'] }` is written here and left
|
|
1833
|
+
* out there, so a decompiled payload recompiles unchanged.
|
|
1834
|
+
*/
|
|
1835
|
+
function emitBusinessEvent(event) {
|
|
1836
|
+
const out = { name: event.name };
|
|
1837
|
+
if (event.description !== undefined)
|
|
1838
|
+
out.description = event.description;
|
|
1839
|
+
const payload = event.payload;
|
|
1840
|
+
if (payload !== undefined) {
|
|
1841
|
+
if (!isEmptyObjectSchema(payload))
|
|
1842
|
+
out.schema = JSON.stringify({ ...payload, $schema: payload.$schema ?? JSON_SCHEMA_DRAFT_7 });
|
|
1843
|
+
}
|
|
1844
|
+
return out;
|
|
1845
|
+
}
|
|
1764
1846
|
function emitEntry(c, seed, ownerId, label, ids, resolver) {
|
|
1765
1847
|
const out = {
|
|
1766
1848
|
id: ids.conditionId(seed),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.47.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",
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"@types/node": "^22.7.0",
|
|
94
94
|
"esbuild": "^0.28.1"
|
|
95
95
|
},
|
|
96
|
-
"gitref": "
|
|
96
|
+
"gitref": "e0223e1b46cdf1eb1f4ab072c970824f52b87eeb"
|
|
97
97
|
}
|