@uipath/maestro-builder-sdk 6.6.1 → 6.7.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 +51 -44
- package/dist/api-members.md +55 -38
- package/dist/check.js +195 -8
- package/dist/core/actions.d.ts +258 -49
- package/dist/core/actions.js +81 -34
- package/dist/core-definitions.json +1774 -1073
- package/dist/decompile.js +77 -13
- package/dist/serialize.js +157 -24
- package/package.json +2 -2
package/dist/check.js
CHANGED
|
@@ -116,7 +116,17 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
116
116
|
// decision waits until the expressions are collected (see
|
|
117
117
|
// HITL_OUTCOMES_UNREACHABLE below).
|
|
118
118
|
const hitlChoiceNoPorts = new Map();
|
|
119
|
-
|
|
119
|
+
// Data Fabric writes that target a record `{ fromRead: '<step>' }` — update and
|
|
120
|
+
// delete share the selector, so they share the check.
|
|
121
|
+
const dataFabricRefs = [];
|
|
122
|
+
// Delete step names. `core.datafabric.delete` is the one verb of the family
|
|
123
|
+
// whose definition declares NO outputDefinition, so `$vars.<delete>.output` is
|
|
124
|
+
// undefined at run time (see DATAFABRIC_DELETE_HAS_NO_OUTPUT below).
|
|
125
|
+
const dataFabricDeletes = new Set();
|
|
126
|
+
// Reads that return a LIST. A multi-record read is refused as a write target
|
|
127
|
+
// (see DATAFABRIC_FROMREAD_MULTIPLE below) — the serializer emits a plain
|
|
128
|
+
// no-op task for the write, and nothing at any rung reports it.
|
|
129
|
+
const dataFabricMultiReads = new Set();
|
|
120
130
|
// Placeholder (`mock()`) step names. The platform's `core.logic.mock` declares
|
|
121
131
|
// one output whose `source` is the literal `"null"` — it publishes nothing —
|
|
122
132
|
// so `$vars.<mock>.output` is null at run time, always (see
|
|
@@ -435,24 +445,52 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
435
445
|
});
|
|
436
446
|
}
|
|
437
447
|
}
|
|
438
|
-
if (s.spec.kind === 'dataFabricRead' || s.spec.kind === '
|
|
448
|
+
if (s.spec.kind === 'dataFabricRead' || s.spec.kind === 'dataFabricCreate'
|
|
449
|
+
|| s.spec.kind === 'dataFabricUpdate' || s.spec.kind === 'dataFabricDelete') {
|
|
439
450
|
if (!String(s.spec.inputs.entity ?? '').trim()) {
|
|
440
451
|
diags.push({
|
|
441
452
|
level: 'error', code: 'DATAFABRIC_NO_ENTITY', step: s.name,
|
|
442
453
|
message: `"${s.name}" names no Data Fabric entity. Set { entity: '<entity name>' }.`,
|
|
443
454
|
});
|
|
444
455
|
}
|
|
456
|
+
if (s.spec.kind === 'dataFabricRead') {
|
|
457
|
+
dataFabricReads.add(s.name);
|
|
458
|
+
if (s.spec.inputs.resultMode === 'multiple')
|
|
459
|
+
dataFabricMultiReads.add(s.name);
|
|
460
|
+
checkDataFabricQuery(s.name, s.spec.inputs, diags);
|
|
461
|
+
}
|
|
462
|
+
if (s.spec.kind === 'dataFabricCreate') {
|
|
463
|
+
// Not the same failure as an empty update: a BLANK value is omitted
|
|
464
|
+
// from the insert so the column default applies, so an all-blank
|
|
465
|
+
// `fieldValues` serializes to an empty body and runs green having
|
|
466
|
+
// inserted nothing. The node's schema rejects that — and the fix is
|
|
467
|
+
// a real value, never a placeholder to satisfy the rule.
|
|
468
|
+
const written = Object.values(s.spec.inputs.values ?? {})
|
|
469
|
+
.filter((v) => (v instanceof Expr ? true : String(v ?? '').trim() !== ''));
|
|
470
|
+
if (written.length === 0) {
|
|
471
|
+
diags.push({
|
|
472
|
+
level: 'error', code: 'DATAFABRIC_EMPTY_VALUES', step: s.name,
|
|
473
|
+
message: `"${s.name}" sets no column to a non-blank value, so it would insert nothing and run green. `
|
|
474
|
+
+ 'The node\'s schema rejects that — give a real column a real value rather than a placeholder.',
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
checkDataFabricColumns(s.name, Object.keys(s.spec.inputs.values ?? {}), 'values', diags);
|
|
478
|
+
}
|
|
445
479
|
if (s.spec.kind === 'dataFabricUpdate') {
|
|
446
|
-
dataFabricUpdates.push({ step: s.name, inputs: s.spec.inputs });
|
|
447
480
|
if (Object.keys(s.spec.inputs.set ?? {}).length === 0) {
|
|
448
481
|
diags.push({
|
|
449
482
|
level: 'error', code: 'DATAFABRIC_EMPTY_SET', step: s.name,
|
|
450
483
|
message: `"${s.name}" writes no columns — { set } is empty, so the update would no-op green.`,
|
|
451
484
|
});
|
|
452
485
|
}
|
|
486
|
+
checkDataFabricColumns(s.name, Object.keys(s.spec.inputs.set ?? {}), 'set', diags);
|
|
453
487
|
}
|
|
454
|
-
|
|
455
|
-
|
|
488
|
+
checkDataFabricScope(s.name, s.spec.inputs, diags);
|
|
489
|
+
if (s.spec.kind === 'dataFabricUpdate' || s.spec.kind === 'dataFabricDelete') {
|
|
490
|
+
const factory = s.spec.kind === 'dataFabricUpdate' ? 'dataFabricUpdate' : 'dataFabricDelete';
|
|
491
|
+
dataFabricRefs.push({ step: s.name, factory, record: s.spec.inputs.record });
|
|
492
|
+
if (s.spec.kind === 'dataFabricDelete')
|
|
493
|
+
dataFabricDeletes.add(s.name);
|
|
456
494
|
}
|
|
457
495
|
}
|
|
458
496
|
if (s.spec.kind === 'ixpExtract')
|
|
@@ -729,12 +767,27 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
729
767
|
}
|
|
730
768
|
}
|
|
731
769
|
reportUnreachableHitlOutcomes(hitlChoiceNoPorts, exprs, diags);
|
|
732
|
-
for (const { step,
|
|
733
|
-
const fromRead =
|
|
734
|
-
if (typeof fromRead
|
|
770
|
+
for (const { step, factory, record } of dataFabricRefs) {
|
|
771
|
+
const fromRead = record?.fromRead;
|
|
772
|
+
if (typeof fromRead !== 'string')
|
|
773
|
+
continue;
|
|
774
|
+
if (!dataFabricReads.has(fromRead)) {
|
|
735
775
|
diags.push({
|
|
736
776
|
level: 'error', code: 'DATAFABRIC_FROMREAD_UNKNOWN', step,
|
|
737
777
|
message: `"${step}" targets record: { fromRead: ${JSON.stringify(fromRead)} }, but no dataFabricRead step has that name.`,
|
|
778
|
+
suggestion: `${factory}({ …, record: { byId: '<record id>' } })`,
|
|
779
|
+
});
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
782
|
+
// A LIST is not a write target: the serializer refuses it and emits a plain
|
|
783
|
+
// no-op task, so the flow validates, runs green, and writes nothing.
|
|
784
|
+
if (dataFabricMultiReads.has(fromRead)) {
|
|
785
|
+
diags.push({
|
|
786
|
+
level: 'error', code: 'DATAFABRIC_FROMREAD_MULTIPLE', step,
|
|
787
|
+
message: `"${step}" targets record: { fromRead: ${JSON.stringify(fromRead)} }, but "${fromRead}" is a `
|
|
788
|
+
+ "resultMode: 'multiple' query. A multi-record read is refused as a write target — the step compiles to "
|
|
789
|
+
+ 'a no-op and the run goes green having written nothing.',
|
|
790
|
+
suggestion: `loop the results and target each record with ${factory}({ …, record: { byId: … } })`,
|
|
738
791
|
});
|
|
739
792
|
}
|
|
740
793
|
}
|
|
@@ -1002,6 +1055,20 @@ function checkFlow(built, ancestors, opts = {}) {
|
|
|
1002
1055
|
});
|
|
1003
1056
|
continue;
|
|
1004
1057
|
}
|
|
1058
|
+
// A Data Fabric delete is the one verb of that family whose definition
|
|
1059
|
+
// declares no outputDefinition at all — the record is gone, so there is
|
|
1060
|
+
// nothing to publish. Read the record on the step that FOUND it instead,
|
|
1061
|
+
// which on the `{ fromRead }` form is already in the flow.
|
|
1062
|
+
if (dataFabricDeletes.has(name)) {
|
|
1063
|
+
diags.push({
|
|
1064
|
+
level: 'error',
|
|
1065
|
+
code: 'DATAFABRIC_DELETE_HAS_NO_OUTPUT',
|
|
1066
|
+
message: `Delete "${name}" produces no output, but "$vars.${name}${field ? '.' + field : ''}" reads one in "${step}". `
|
|
1067
|
+
+ 'A Data Fabric delete declares no outputs — take the value off the dataFabricRead step that found the record, before the delete.',
|
|
1068
|
+
step,
|
|
1069
|
+
});
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1005
1072
|
if (delayNames.has(name)) {
|
|
1006
1073
|
diags.push({
|
|
1007
1074
|
level: 'error',
|
|
@@ -4635,6 +4702,102 @@ function checkCaseValueTypes(s, typeOf, diags, triggerId) {
|
|
|
4635
4702
|
* `output` is the aggregate (after the loop) and `error` the failure detail.
|
|
4636
4703
|
*/
|
|
4637
4704
|
const LOOP_FIELDS = new Set(['currentItem', 'currentIndex', 'collection', 'output', 'error']);
|
|
4705
|
+
/**
|
|
4706
|
+
* Columns Data Fabric assigns and never accepts a write for.
|
|
4707
|
+
*
|
|
4708
|
+
* The canvas hides them from both write editors, but the serializer has no
|
|
4709
|
+
* guard: a hand-authored `Id` row satisfies the node's own "at least one field"
|
|
4710
|
+
* rule, ships in the body, and is rejected — and the rejection is only logged,
|
|
4711
|
+
* so the row comes back unchanged and the run goes green.
|
|
4712
|
+
*/
|
|
4713
|
+
const DATAFABRIC_SYSTEM_COLUMNS = new Set(['Id', 'CreateTime', 'CreatedBy', 'UpdateTime', 'UpdatedBy']);
|
|
4714
|
+
function checkDataFabricColumns(step, columns, option, diags) {
|
|
4715
|
+
const system = columns.filter((c) => DATAFABRIC_SYSTEM_COLUMNS.has(c));
|
|
4716
|
+
if (system.length) {
|
|
4717
|
+
diags.push({
|
|
4718
|
+
level: 'error', code: 'DATAFABRIC_SYSTEM_COLUMN', step,
|
|
4719
|
+
message: `"${step}" writes ${system.map((c) => JSON.stringify(c)).join(', ')} in { ${option} }. `
|
|
4720
|
+
+ 'Data Fabric assigns its system columns (Id, CreateTime, CreatedBy, UpdateTime, UpdatedBy) and rejects a '
|
|
4721
|
+
+ 'write to them — and it only LOGS the rejection, so the row comes back unchanged and the run goes green.',
|
|
4722
|
+
});
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
/**
|
|
4726
|
+
* A folder-scoped entity is portable only with its `Entity` bindings.
|
|
4727
|
+
*
|
|
4728
|
+
* `_folderKey` on its own still serializes — it falls back to a source-org
|
|
4729
|
+
* literal and logs a warning — so the flow looks fine until it is deployed to
|
|
4730
|
+
* another org. Refusing the half-authored pair here is the whole point: the
|
|
4731
|
+
* alternative is a defect that only appears at deploy time, in a different org,
|
|
4732
|
+
* to somebody else.
|
|
4733
|
+
*/
|
|
4734
|
+
function checkDataFabricScope(step, inputs, diags) {
|
|
4735
|
+
if (inputs.folderKey !== undefined && inputs.resourceKey === undefined) {
|
|
4736
|
+
diags.push({
|
|
4737
|
+
level: 'error', code: 'DATAFABRIC_FOLDER_NO_RESOURCE_KEY', step,
|
|
4738
|
+
message: `"${step}" sets { folderKey } without { resourceKey }. A folder-scoped entity needs both — with only `
|
|
4739
|
+
+ 'the folder key the entity serializes as a source-org literal, which validates, runs in this org, and '
|
|
4740
|
+
+ 'breaks on deploy to another one.',
|
|
4741
|
+
suggestion: 'resolve the key with `uip solution resources list --kind Entity`, or drop { folderKey } and keep '
|
|
4742
|
+
+ 'the entity tenant-scoped',
|
|
4743
|
+
});
|
|
4744
|
+
}
|
|
4745
|
+
if (inputs.resourceKey !== undefined && inputs.folderKey === undefined) {
|
|
4746
|
+
diags.push({
|
|
4747
|
+
level: 'error', code: 'DATAFABRIC_RESOURCE_KEY_NO_FOLDER', step,
|
|
4748
|
+
message: `"${step}" sets { resourceKey } without { folderKey }. The pair exists to scope a FOLDER entity; a `
|
|
4749
|
+
+ 'tenant-scoped entity needs neither and serializes as a dotted literal.',
|
|
4750
|
+
});
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
/**
|
|
4754
|
+
* The query options, none of which the node's `inputDefinition` declares — they
|
|
4755
|
+
* are `_`-prefixed extras, so `uip maestro flow validate` checks none of them
|
|
4756
|
+
* and every mistake here is silent at run time.
|
|
4757
|
+
*/
|
|
4758
|
+
function checkDataFabricQuery(step, inputs, diags) {
|
|
4759
|
+
const listOnly = ['limit', 'skip', 'sort', 'fields'].filter((k) => inputs[k] !== undefined);
|
|
4760
|
+
if (listOnly.length && inputs.resultMode !== 'multiple') {
|
|
4761
|
+
diags.push({
|
|
4762
|
+
level: 'error', code: 'DATAFABRIC_QUERY_OPTS_WITHOUT_MULTIPLE', step,
|
|
4763
|
+
message: `"${step}" sets { ${listOnly.join(', ')} }, which only a list query uses, but its resultMode is `
|
|
4764
|
+
+ `${inputs.resultMode ? JSON.stringify(inputs.resultMode) : 'unset (a single-record read)'}.`,
|
|
4765
|
+
suggestion: "resultMode: 'multiple'",
|
|
4766
|
+
});
|
|
4767
|
+
}
|
|
4768
|
+
// The emitted query ALWAYS carries a limit — omitted it resolves to 100 — and
|
|
4769
|
+
// 1000 is a hard ceiling that TRUNCATES rather than erroring above it.
|
|
4770
|
+
if (inputs.limit !== undefined && (!Number.isInteger(inputs.limit) || inputs.limit < 1 || inputs.limit > 1000)) {
|
|
4771
|
+
diags.push({
|
|
4772
|
+
level: 'error', code: 'DATAFABRIC_LIMIT_RANGE', step,
|
|
4773
|
+
message: `"${step}": limit must be a whole number between 1 and 1000 (got ${inputs.limit}). 1000 is a hard `
|
|
4774
|
+
+ 'ceiling — a larger value truncates silently, so page with { skip } instead.',
|
|
4775
|
+
});
|
|
4776
|
+
}
|
|
4777
|
+
// `in` is honoured only on a list query; on a single read the row compiles
|
|
4778
|
+
// away, and a read whose filters compiled away returns EVERY record.
|
|
4779
|
+
if (inputs.resultMode !== 'multiple' && (inputs.filters ?? []).some((f) => f.operator === 'in')) {
|
|
4780
|
+
diags.push({
|
|
4781
|
+
level: 'error', code: 'DATAFABRIC_IN_REQUIRES_MULTIPLE', step,
|
|
4782
|
+
message: `"${step}" filters with the 'in' operator, which is honoured only when resultMode is 'multiple'. `
|
|
4783
|
+
+ 'On a single-record read that row compiles away — and a read whose filters compiled away matches every record.',
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
// A filter expression switched on and left blank is refused by the serializer,
|
|
4787
|
+
// and it refuses the WHOLE query rather than dropping the row, which strands
|
|
4788
|
+
// every downstream reference to this step.
|
|
4789
|
+
for (const f of inputs.filters ?? []) {
|
|
4790
|
+
const blank = f.value instanceof Expr ? f.value.js.trim() === '' : String(f.value ?? '').trim() === '';
|
|
4791
|
+
if (blank) {
|
|
4792
|
+
diags.push({
|
|
4793
|
+
level: 'error', code: 'DATAFABRIC_FILTER_BLANK_VALUE', step,
|
|
4794
|
+
message: `"${step}" has a filter on ${JSON.stringify(f.field)} with a blank value. The serializer refuses the `
|
|
4795
|
+
+ 'ENTIRE query rather than dropping the row, so the step emits nothing and every downstream $vars read of '
|
|
4796
|
+
+ 'it breaks.',
|
|
4797
|
+
});
|
|
4798
|
+
}
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4638
4801
|
function collectActionExprs(s, out, errorSource) {
|
|
4639
4802
|
const push = (val) => {
|
|
4640
4803
|
if (val instanceof Expr && !val.literal)
|
|
@@ -4691,6 +4854,30 @@ function collectActionExprs(s, out, errorSource) {
|
|
|
4691
4854
|
push(val);
|
|
4692
4855
|
return;
|
|
4693
4856
|
}
|
|
4857
|
+
if (s.spec.kind === 'dataFabricRead' || s.spec.kind === 'dataFabricCreate'
|
|
4858
|
+
|| s.spec.kind === 'dataFabricUpdate' || s.spec.kind === 'dataFabricDelete') {
|
|
4859
|
+
// Every value a Data Fabric step carries is authored against flow scope: a
|
|
4860
|
+
// filter's comparison value, the record id, the columns written. The family
|
|
4861
|
+
// was missing here entirely, so a `$vars.` typo in any of them travelled to
|
|
4862
|
+
// the platform unchecked — and the delete verb's no-output rule below has
|
|
4863
|
+
// nothing to fire on until these are collected.
|
|
4864
|
+
if (s.spec.kind === 'dataFabricRead') {
|
|
4865
|
+
for (const f of s.spec.inputs.filters ?? [])
|
|
4866
|
+
push(f.value);
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
if (s.spec.kind === 'dataFabricCreate') {
|
|
4870
|
+
for (const val of Object.values(s.spec.inputs.values ?? {}))
|
|
4871
|
+
push(val);
|
|
4872
|
+
return;
|
|
4873
|
+
}
|
|
4874
|
+
push(s.spec.inputs.record?.byId);
|
|
4875
|
+
if (s.spec.kind === 'dataFabricUpdate') {
|
|
4876
|
+
for (const val of Object.values(s.spec.inputs.set ?? {}))
|
|
4877
|
+
push(val);
|
|
4878
|
+
}
|
|
4879
|
+
return;
|
|
4880
|
+
}
|
|
4694
4881
|
if (s.spec.kind === 'connector') {
|
|
4695
4882
|
// Same gap on the connector surface: `messageToSend: tmpl`…${v('typo')}``
|
|
4696
4883
|
// reached the runtime unchecked.
|
package/dist/core/actions.d.ts
CHANGED
|
@@ -2016,46 +2016,215 @@ export interface QueueItemInputs {
|
|
|
2016
2016
|
*/
|
|
2017
2017
|
returns?: Record<string, ReturnFieldType>;
|
|
2018
2018
|
}
|
|
2019
|
-
/**
|
|
2019
|
+
/**
|
|
2020
|
+
* The comparison operators the Data Fabric query serializer can emit, spelled
|
|
2021
|
+
* exactly as the file carries them.
|
|
2022
|
+
*
|
|
2023
|
+
* @remarks
|
|
2024
|
+
* There is deliberately no `not in`, `not contains`, or null check — the
|
|
2025
|
+
* serializer cannot emit them, and a filter it cannot emit takes the WHOLE
|
|
2026
|
+
* query down rather than dropping one row. `is any of` is the legacy spelling
|
|
2027
|
+
* of `in` and is still read, but author `in`.
|
|
2028
|
+
*/
|
|
2029
|
+
export type DataFabricOperator = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'starts with' | 'ends with' | 'in';
|
|
2030
|
+
/** One filter row on a Data Fabric query — rows AND together unless `or` is set. */
|
|
2020
2031
|
export interface DataFabricFilter {
|
|
2021
|
-
/**
|
|
2032
|
+
/**
|
|
2033
|
+
* The entity column to filter on. A dotted related path (`customer.Name`) is
|
|
2034
|
+
* capped at 3 segments and needs the canvas's `_entityFields` snapshot, which
|
|
2035
|
+
* the SDK does not author — keep from-scratch filters on the entity's own
|
|
2036
|
+
* columns.
|
|
2037
|
+
*/
|
|
2022
2038
|
field: string;
|
|
2023
|
-
/** Comparison operator
|
|
2024
|
-
operator?:
|
|
2025
|
-
/**
|
|
2039
|
+
/** Comparison operator; `=` when omitted. */
|
|
2040
|
+
operator?: DataFabricOperator;
|
|
2041
|
+
/**
|
|
2042
|
+
* The comparison value. An `Expr` re-evaluates at activation time.
|
|
2043
|
+
*
|
|
2044
|
+
* A choice-set column compares against the choice's numeric `numberId`, never
|
|
2045
|
+
* its label — a label matches nothing.
|
|
2046
|
+
*/
|
|
2026
2047
|
value: string | Expr;
|
|
2027
|
-
/**
|
|
2048
|
+
/**
|
|
2049
|
+
* Start a new OR alternative at this row.
|
|
2050
|
+
*
|
|
2051
|
+
* @remarks
|
|
2052
|
+
* The query model is disjunctive — `alt1 OR alt2 OR …`, each alternative an
|
|
2053
|
+
* AND of its own rows — so `or` SPLITS the list rather than joining one row
|
|
2054
|
+
* to the one before it. `[A, B(or), C]` is therefore `A OR (B AND C)`, not
|
|
2055
|
+
* `(A OR B) AND C`; to get the latter, write it out as
|
|
2056
|
+
* `(A AND C) OR (B AND C)`.
|
|
2057
|
+
*
|
|
2058
|
+
* Ignored on the first row, which has no earlier alternative to split from.
|
|
2059
|
+
*/
|
|
2028
2060
|
or?: boolean;
|
|
2029
2061
|
}
|
|
2062
|
+
/** How a multi-record query orders its rows before the limit is applied. */
|
|
2063
|
+
export interface DataFabricSort {
|
|
2064
|
+
/** The column to order by — a real one; a sort on a missing column is not caught by `validate`. */
|
|
2065
|
+
field: string;
|
|
2066
|
+
/** `'asc'` when omitted. */
|
|
2067
|
+
direction?: 'asc' | 'desc';
|
|
2068
|
+
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Which record a Data Fabric write targets — exactly ONE of the two forms.
|
|
2071
|
+
*
|
|
2072
|
+
* @remarks
|
|
2073
|
+
* `{ byId }` names a record id, literal or expression. `{ fromRead }` names an
|
|
2074
|
+
* earlier {@link dataFabricRead} STEP and reuses the record that step found, so
|
|
2075
|
+
* the id never has to be carried by hand; `check` rejects a name no read step
|
|
2076
|
+
* has. Shared by {@link dataFabricUpdate} and {@link dataFabricDelete} — the
|
|
2077
|
+
* platform gives them the same `recordSource` shape.
|
|
2078
|
+
*/
|
|
2079
|
+
export type DataFabricRecordRef = {
|
|
2080
|
+
byId: string | Expr;
|
|
2081
|
+
fromRead?: never;
|
|
2082
|
+
} | {
|
|
2083
|
+
fromRead: string;
|
|
2084
|
+
byId?: never;
|
|
2085
|
+
};
|
|
2030
2086
|
export interface DataFabricReadInputs {
|
|
2031
2087
|
/** The Data Fabric entity's name, e.g. `'Invoices'`. */
|
|
2032
2088
|
entity: string;
|
|
2033
|
-
/** Filter rows selecting the record to
|
|
2089
|
+
/** Filter rows selecting the record(s) to query. Omit to take everything the entity holds. */
|
|
2034
2090
|
filters?: DataFabricFilter[];
|
|
2035
|
-
/**
|
|
2091
|
+
/**
|
|
2092
|
+
* `'single'` publishes ONE record as the step's `output`; `'multiple'`
|
|
2093
|
+
* publishes the matching records under `output.results`.
|
|
2094
|
+
*
|
|
2095
|
+
* Setting either selects the node's **1.4** definition, which is where
|
|
2096
|
+
* `resultMode` exists at all — the SDK's pinned default is 1.0, the
|
|
2097
|
+
* read-one-record node this family started as. Omit it and nothing changes:
|
|
2098
|
+
* the step stays on 1.0 and reads one record, as it always did.
|
|
2099
|
+
*
|
|
2100
|
+
* A `'single'` read faults only on an OVER-match; zero matches completes
|
|
2101
|
+
* normally and leaves the step's output unresolved, so treat "not found" as a
|
|
2102
|
+
* branch rather than an error.
|
|
2103
|
+
*/
|
|
2104
|
+
resultMode?: 'single' | 'multiple';
|
|
2105
|
+
/**
|
|
2106
|
+
* Row cap for a `'multiple'` query. The emitted query ALWAYS carries a limit:
|
|
2107
|
+
* omitting this resolves to 100, and 1000 is a hard ceiling — a larger value
|
|
2108
|
+
* truncates silently, so page with `skip` instead.
|
|
2109
|
+
*/
|
|
2110
|
+
limit?: number;
|
|
2111
|
+
/** Rows to skip before the limit — the paging half of `limit`. */
|
|
2112
|
+
skip?: number;
|
|
2113
|
+
/** Order rows before the limit applies. Without it a limited slice is arbitrary. */
|
|
2114
|
+
sort?: DataFabricSort;
|
|
2115
|
+
/** Only these columns. Omit for every column the entity has. */
|
|
2116
|
+
fields?: string[];
|
|
2117
|
+
/**
|
|
2118
|
+
* Folder key (GUID) for a folder-scoped entity — its `folderId` from
|
|
2119
|
+
* `uip df entities list --include-folders`.
|
|
2120
|
+
*
|
|
2121
|
+
* Requires `resourceKey`: `folderKey` alone serializes the folder as a
|
|
2122
|
+
* source-org LITERAL, which looks portable and breaks on cross-org deploy, so
|
|
2123
|
+
* `check` refuses the pair being half-authored.
|
|
2124
|
+
*/
|
|
2036
2125
|
folderKey?: string;
|
|
2126
|
+
/**
|
|
2127
|
+
* The key the entity's reference is registered under in the solution, from
|
|
2128
|
+
* `uip solution resources list --kind Entity`.
|
|
2129
|
+
*
|
|
2130
|
+
* @remarks
|
|
2131
|
+
* Only meaningful with `folderKey`. Supplying both emits the two
|
|
2132
|
+
* `resource: 'Entity'` binding rows (`propertyAttribute` `name` and
|
|
2133
|
+
* `folderKey`) that let the flow deploy to another org. Nothing mints this
|
|
2134
|
+
* key for a hand-authored flow — if you cannot resolve one, keep the entity
|
|
2135
|
+
* tenant-scoped and omit both.
|
|
2136
|
+
*/
|
|
2137
|
+
resourceKey?: string;
|
|
2037
2138
|
}
|
|
2038
|
-
export interface
|
|
2139
|
+
export interface DataFabricCreateInputs {
|
|
2039
2140
|
/** The Data Fabric entity's name, e.g. `'Invoices'`. */
|
|
2040
2141
|
entity: string;
|
|
2041
2142
|
/**
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2143
|
+
* The columns the new record starts with, by field name. At least one is
|
|
2144
|
+
* required — the node's schema rejects an empty field list rather than
|
|
2145
|
+
* inserting a blank row.
|
|
2044
2146
|
*/
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2147
|
+
values: Record<string, string | Expr>;
|
|
2148
|
+
/**
|
|
2149
|
+
* Folder key (GUID) for a folder-scoped entity — its `folderId` from
|
|
2150
|
+
* `uip df entities list --include-folders`.
|
|
2151
|
+
*
|
|
2152
|
+
* Requires `resourceKey`: `folderKey` alone serializes the folder as a
|
|
2153
|
+
* source-org LITERAL, which looks portable and breaks on cross-org deploy, so
|
|
2154
|
+
* `check` refuses the pair being half-authored.
|
|
2155
|
+
*/
|
|
2156
|
+
folderKey?: string;
|
|
2157
|
+
/**
|
|
2158
|
+
* The key the entity's reference is registered under in the solution, from
|
|
2159
|
+
* `uip solution resources list --kind Entity`.
|
|
2160
|
+
*
|
|
2161
|
+
* @remarks
|
|
2162
|
+
* Only meaningful with `folderKey`. Supplying both emits the two
|
|
2163
|
+
* `resource: 'Entity'` binding rows (`propertyAttribute` `name` and
|
|
2164
|
+
* `folderKey`) that let the flow deploy to another org. Nothing mints this
|
|
2165
|
+
* key for a hand-authored flow — if you cannot resolve one, keep the entity
|
|
2166
|
+
* tenant-scoped and omit both.
|
|
2167
|
+
*/
|
|
2168
|
+
resourceKey?: string;
|
|
2169
|
+
}
|
|
2170
|
+
export interface DataFabricUpdateInputs {
|
|
2171
|
+
/** The Data Fabric entity's name, e.g. `'Invoices'`. */
|
|
2172
|
+
entity: string;
|
|
2173
|
+
/** Which record to update — see {@link DataFabricRecordRef}. */
|
|
2174
|
+
record: DataFabricRecordRef;
|
|
2052
2175
|
/**
|
|
2053
2176
|
* The columns to write, by field name. An empty string is a real write — it
|
|
2054
2177
|
* clears the column.
|
|
2055
2178
|
*/
|
|
2056
2179
|
set: Record<string, string | Expr>;
|
|
2057
|
-
/**
|
|
2180
|
+
/**
|
|
2181
|
+
* Folder key (GUID) for a folder-scoped entity — its `folderId` from
|
|
2182
|
+
* `uip df entities list --include-folders`.
|
|
2183
|
+
*
|
|
2184
|
+
* Requires `resourceKey`: `folderKey` alone serializes the folder as a
|
|
2185
|
+
* source-org LITERAL, which looks portable and breaks on cross-org deploy, so
|
|
2186
|
+
* `check` refuses the pair being half-authored.
|
|
2187
|
+
*/
|
|
2188
|
+
folderKey?: string;
|
|
2189
|
+
/**
|
|
2190
|
+
* The key the entity's reference is registered under in the solution, from
|
|
2191
|
+
* `uip solution resources list --kind Entity`.
|
|
2192
|
+
*
|
|
2193
|
+
* @remarks
|
|
2194
|
+
* Only meaningful with `folderKey`. Supplying both emits the two
|
|
2195
|
+
* `resource: 'Entity'` binding rows (`propertyAttribute` `name` and
|
|
2196
|
+
* `folderKey`) that let the flow deploy to another org. Nothing mints this
|
|
2197
|
+
* key for a hand-authored flow — if you cannot resolve one, keep the entity
|
|
2198
|
+
* tenant-scoped and omit both.
|
|
2199
|
+
*/
|
|
2200
|
+
resourceKey?: string;
|
|
2201
|
+
}
|
|
2202
|
+
export interface DataFabricDeleteInputs {
|
|
2203
|
+
/** The Data Fabric entity's name, e.g. `'Invoices'`. */
|
|
2204
|
+
entity: string;
|
|
2205
|
+
/** Which record to delete — see {@link DataFabricRecordRef}. */
|
|
2206
|
+
record: DataFabricRecordRef;
|
|
2207
|
+
/**
|
|
2208
|
+
* Folder key (GUID) for a folder-scoped entity — its `folderId` from
|
|
2209
|
+
* `uip df entities list --include-folders`.
|
|
2210
|
+
*
|
|
2211
|
+
* Requires `resourceKey`: `folderKey` alone serializes the folder as a
|
|
2212
|
+
* source-org LITERAL, which looks portable and breaks on cross-org deploy, so
|
|
2213
|
+
* `check` refuses the pair being half-authored.
|
|
2214
|
+
*/
|
|
2058
2215
|
folderKey?: string;
|
|
2216
|
+
/**
|
|
2217
|
+
* The key the entity's reference is registered under in the solution, from
|
|
2218
|
+
* `uip solution resources list --kind Entity`.
|
|
2219
|
+
*
|
|
2220
|
+
* @remarks
|
|
2221
|
+
* Only meaningful with `folderKey`. Supplying both emits the two
|
|
2222
|
+
* `resource: 'Entity'` binding rows (`propertyAttribute` `name` and
|
|
2223
|
+
* `folderKey`) that let the flow deploy to another org. Nothing mints this
|
|
2224
|
+
* key for a hand-authored flow — if you cannot resolve one, keep the entity
|
|
2225
|
+
* tenant-scoped and omit both.
|
|
2226
|
+
*/
|
|
2227
|
+
resourceKey?: string;
|
|
2059
2228
|
}
|
|
2060
2229
|
export interface DocumentClassifyInputs {
|
|
2061
2230
|
/** The document to classify — a file reference (`input('file')`, `out('fetch', 'fileRef')`, …). */
|
|
@@ -2191,9 +2360,15 @@ export type ActionSpec = {
|
|
|
2191
2360
|
} | {
|
|
2192
2361
|
kind: 'dataFabricRead';
|
|
2193
2362
|
inputs: DataFabricReadInputs;
|
|
2363
|
+
} | {
|
|
2364
|
+
kind: 'dataFabricCreate';
|
|
2365
|
+
inputs: DataFabricCreateInputs;
|
|
2194
2366
|
} | {
|
|
2195
2367
|
kind: 'dataFabricUpdate';
|
|
2196
2368
|
inputs: DataFabricUpdateInputs;
|
|
2369
|
+
} | {
|
|
2370
|
+
kind: 'dataFabricDelete';
|
|
2371
|
+
inputs: DataFabricDeleteInputs;
|
|
2197
2372
|
} | {
|
|
2198
2373
|
kind: 'waitEvent';
|
|
2199
2374
|
subscription: EventSubscription;
|
|
@@ -2929,63 +3104,97 @@ export declare function documentClassify(inputs: DocumentClassifyInputs): Action
|
|
|
2929
3104
|
*/
|
|
2930
3105
|
export declare function dynamicExtract(inputs: DynamicExtractInputs): ActionSpec;
|
|
2931
3106
|
/**
|
|
2932
|
-
*
|
|
3107
|
+
* Query entity records from Data Fabric (`core.datafabric.read`). The result
|
|
2933
3108
|
* publishes to the step's `output`; downstream references re-fetch fresh data
|
|
2934
3109
|
* at activation time (the engine re-runs the query rather than caching).
|
|
2935
3110
|
*
|
|
2936
3111
|
* @remarks
|
|
2937
|
-
*
|
|
2938
|
-
* `
|
|
2939
|
-
*
|
|
2940
|
-
*
|
|
2941
|
-
*
|
|
2942
|
-
*
|
|
3112
|
+
* This node is **read-one AND query-many**, on its 1.4 definition: `resultMode:
|
|
3113
|
+
* 'multiple'` publishes the matching records under `output.results`, and the
|
|
3114
|
+
* platform renames the node "Query entity records" to say so. The SDK still
|
|
3115
|
+
* pins 1.0 — read-one — as the no-`{ version }` default, so passing
|
|
3116
|
+
* `resultMode` is what selects 1.4; see {@link DataFabricReadInputs.resultMode}.
|
|
3117
|
+
*
|
|
3118
|
+
* The native family covers all four CRUD verbs: this one,
|
|
3119
|
+
* {@link dataFabricCreate}, {@link dataFabricUpdate} and
|
|
3120
|
+
* {@link dataFabricDelete}. What it does NOT cover is get-by-id, a query row
|
|
3121
|
+
* limit, file record fields, and entity events — those are operations on the
|
|
3122
|
+
* SAME product reached through its Integration Service connector,
|
|
2943
3123
|
* `uipath-uipath-dataservice` (the tenant displays it as **UiPath Data
|
|
2944
|
-
* Fabric**)
|
|
2945
|
-
*
|
|
2946
|
-
* Taking this node for the one verb that has a native form leaves the rest of
|
|
2947
|
-
* the same entity on the connector — two connection bindings and two payload
|
|
2948
|
-
* shapes in one flow. So route entity work through the connector unless the
|
|
2949
|
-
* scenario names these nodes; native forms for the remaining verbs are the
|
|
2950
|
-
* direction of travel, and this guidance changes when they land. `check` does
|
|
2951
|
-
* not reject a native node — this is a routing default, not a rule:
|
|
3124
|
+
* Fabric**). So a flow that needs one of those still straddles two surfaces,
|
|
3125
|
+
* and the connector remains the one surface that covers everything:
|
|
2952
3126
|
*
|
|
2953
3127
|
* ```ts
|
|
2954
|
-
* .step('
|
|
2955
|
-
* { entityName: 'Contracts',
|
|
3128
|
+
* .step('byId', connector('uipath-uipath-dataservice', 'get-entity-record-by-id',
|
|
3129
|
+
* { entityName: 'Contracts', recordId: input('id') }, { connection: 'df' }))
|
|
2956
3130
|
* ```
|
|
2957
3131
|
*
|
|
2958
|
-
*
|
|
2959
|
-
* carry them: run `npx flow-sdk registry prepare uipath-uipath-dataservice
|
|
2960
|
-
*
|
|
2961
|
-
* prepare …` is the same command when you are driving through the UiPath CLI).
|
|
2962
|
-
* the `data-fabric.md` reference and the parent-field
|
|
2963
|
-
* `connector-params.md` — cited by name rather than linked, because this
|
|
3132
|
+
* A connector operation's body fields come from the entity, so the library
|
|
3133
|
+
* cannot carry them: run `npx flow-sdk registry prepare uipath-uipath-dataservice
|
|
3134
|
+
* get-entity-record-by-id -f entityName=<Entity>` first (`uip maestro registry
|
|
3135
|
+
* prepare …` is the same command when you are driving through the UiPath CLI).
|
|
3136
|
+
* The routing table is in the `data-fabric.md` reference and the parent-field
|
|
3137
|
+
* loop in `connector-params.md` — cited by name rather than linked, because this
|
|
2964
3138
|
* comment renders both into the flat corpus, where those files sit alongside
|
|
2965
3139
|
* it, and onto the site, where each symbol is its own page and a relative
|
|
2966
3140
|
* `./data-fabric` resolves to nothing.
|
|
2967
3141
|
*
|
|
2968
|
-
* @param inputs - The entity, optional filter rows, and folder scope.
|
|
3142
|
+
* @param inputs - The entity, optional filter rows, result mode, and folder scope.
|
|
2969
3143
|
* @returns An action spec to pass to `.step(name, …)`.
|
|
2970
3144
|
*/
|
|
2971
3145
|
export declare function dataFabricRead(inputs: DataFabricReadInputs): ActionSpec;
|
|
3146
|
+
/**
|
|
3147
|
+
* Create an entity record in Data Fabric (`core.datafabric.create`). The new
|
|
3148
|
+
* record publishes to the step's `output`, so a following
|
|
3149
|
+
* {@link dataFabricUpdate} or {@link dataFabricDelete} can read its id.
|
|
3150
|
+
*
|
|
3151
|
+
* @remarks
|
|
3152
|
+
* `values` must name at least one column — the node's schema rejects an empty
|
|
3153
|
+
* field list rather than inserting a blank row, and `check` says so before the
|
|
3154
|
+
* platform does. Field names are the ENTITY's, so copy them from the scenario
|
|
3155
|
+
* or the tenant; nothing offline can tell a real column from a typo.
|
|
3156
|
+
*
|
|
3157
|
+
* See {@link dataFabricRead} for what the native family still does not cover
|
|
3158
|
+
* and which connector operation covers it.
|
|
3159
|
+
*
|
|
3160
|
+
* @param inputs - The entity, the columns the record starts with, and folder scope.
|
|
3161
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
3162
|
+
*/
|
|
3163
|
+
export declare function dataFabricCreate(inputs: DataFabricCreateInputs): ActionSpec;
|
|
2972
3164
|
/**
|
|
2973
3165
|
* Update an entity record in Data Fabric (`core.datafabric.update`). Target the
|
|
2974
3166
|
* record by id or through an earlier {@link dataFabricRead} step; downstream
|
|
2975
3167
|
* reads of this step observe the record AFTER the write.
|
|
2976
3168
|
*
|
|
2977
3169
|
* @remarks
|
|
2978
|
-
*
|
|
2979
|
-
*
|
|
2980
|
-
*
|
|
2981
|
-
*
|
|
2982
|
-
*
|
|
2983
|
-
* one surface.
|
|
3170
|
+
* `set` must write at least one column: an empty `set` is a no-op the platform
|
|
3171
|
+
* reports as success, so `check` rejects it.
|
|
3172
|
+
*
|
|
3173
|
+
* See {@link dataFabricRead} for what the native family still does not cover
|
|
3174
|
+
* and which connector operation covers it.
|
|
2984
3175
|
*
|
|
2985
3176
|
* @param inputs - The entity, the record selector, and the columns to write.
|
|
2986
3177
|
* @returns An action spec to pass to `.step(name, …)`.
|
|
2987
3178
|
*/
|
|
2988
3179
|
export declare function dataFabricUpdate(inputs: DataFabricUpdateInputs): ActionSpec;
|
|
3180
|
+
/**
|
|
3181
|
+
* Delete an entity record from Data Fabric (`core.datafabric.delete`). Target
|
|
3182
|
+
* the record by id or through an earlier {@link dataFabricRead} step, exactly
|
|
3183
|
+
* as {@link dataFabricUpdate} does.
|
|
3184
|
+
*
|
|
3185
|
+
* @remarks
|
|
3186
|
+
* A delete **publishes nothing** — its definition declares no output — so
|
|
3187
|
+
* `$vars.<step>.output` is undefined at run time and `check` rejects a read of
|
|
3188
|
+
* it. Take what you need off the read step that found the record, before the
|
|
3189
|
+
* delete.
|
|
3190
|
+
*
|
|
3191
|
+
* See {@link dataFabricRead} for what the native family still does not cover
|
|
3192
|
+
* and which connector operation covers it.
|
|
3193
|
+
*
|
|
3194
|
+
* @param inputs - The entity, the record selector, and folder scope.
|
|
3195
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
3196
|
+
*/
|
|
3197
|
+
export declare function dataFabricDelete(inputs: DataFabricDeleteInputs): ActionSpec;
|
|
2989
3198
|
/**
|
|
2990
3199
|
* Declare an Orchestrator QUEUE ITEM step.
|
|
2991
3200
|
*
|