@uipath/maestro-builder-sdk 6.18.10 → 6.20.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 +185 -184
- package/dist/api-members.md +506 -473
- package/dist/check.js +358 -695
- package/dist/cli/commands/flow.js +3 -0
- package/dist/compile-cli.js +51 -0
- package/dist/core/actions.d.ts +132 -765
- package/dist/core/actions.js +1 -307
- package/dist/core/binding-identity.d.ts +22 -0
- package/dist/core/binding-identity.js +28 -0
- package/dist/core/context-index.d.ts +34 -0
- package/dist/core/context-index.js +38 -0
- package/dist/core/definitionless-node-types.d.ts +16 -0
- package/dist/core/definitionless-node-types.js +16 -0
- package/dist/core/error-port.d.ts +6 -0
- package/dist/core/error-port.js +9 -0
- package/dist/core/form-field-type.d.ts +33 -0
- package/dist/core/form-field-type.js +30 -0
- package/dist/core/hitl-routing.d.ts +8 -0
- package/dist/core/hitl-routing.js +17 -1
- package/dist/core/node-classes.d.ts +4 -63
- package/dist/core/node-classes.js +0 -112
- package/dist/core/nodes/family.d.ts +36 -0
- package/dist/core/nodes/family.js +1 -0
- package/dist/core/nodes/node-type.d.ts +136 -0
- package/dist/core/nodes/node-type.js +1 -0
- package/dist/core/nodes/registry.d.ts +57 -0
- package/dist/core/nodes/registry.js +122 -0
- package/dist/core/nodes/versioned.d.ts +50 -0
- package/dist/core/nodes/versioned.js +46 -0
- package/dist/core/process-resource-sort-order.d.ts +40 -0
- package/dist/core/process-resource-sort-order.js +44 -0
- package/dist/core/typed-raw-node.d.ts +13 -62
- package/dist/core/typed-raw-node.js +40 -154
- package/dist/core/wire-expr.d.ts +27 -0
- package/dist/core/wire-expr.js +34 -0
- package/dist/decompile-cli.js +11 -1
- package/dist/decompile.d.ts +8 -3
- package/dist/decompile.js +665 -354
- package/dist/flow-definitions.d.ts +10 -0
- package/dist/flow-definitions.js +35 -0
- package/dist/flow-expr-check.js +1 -1
- package/dist/flow-node-registry.d.ts +13 -0
- package/dist/flow-node-registry.js +19 -0
- package/dist/flow-node-type.d.ts +192 -0
- package/dist/flow-node-type.js +1 -0
- package/dist/flow-sdk.d.ts +40 -1
- package/dist/flow-sdk.js +29 -2
- package/dist/flow-step-tree.js +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/merge-cli.js +25 -8
- package/dist/merge-roundtrip.d.ts +81 -0
- package/dist/merge-roundtrip.js +404 -0
- package/dist/merge.d.ts +35 -6
- package/dist/merge.js +124 -24
- package/dist/node-placement.d.ts +93 -0
- package/dist/node-placement.js +163 -0
- package/dist/nodes/data-fabric/flow/check.d.ts +13 -0
- package/dist/nodes/data-fabric/flow/check.js +164 -0
- package/dist/nodes/data-fabric/flow/factories.d.ts +113 -0
- package/dist/nodes/data-fabric/flow/factories.js +134 -0
- package/dist/nodes/data-fabric/flow/family.d.ts +7 -0
- package/dist/nodes/data-fabric/flow/family.js +9 -0
- package/dist/nodes/data-fabric/flow/index.d.ts +8 -0
- package/dist/nodes/data-fabric/flow/index.js +8 -0
- package/dist/nodes/data-fabric/flow/raw.d.ts +32 -0
- package/dist/nodes/data-fabric/flow/raw.js +100 -0
- package/dist/nodes/data-fabric/flow/shared.d.ts +77 -0
- package/dist/nodes/data-fabric/flow/shared.js +174 -0
- package/dist/nodes/data-fabric/flow/spec.d.ts +238 -0
- package/dist/nodes/data-fabric/flow/spec.js +1 -0
- package/dist/nodes/data-fabric/flow/verbs.d.ts +29 -0
- package/dist/nodes/data-fabric/flow/verbs.js +239 -0
- package/dist/nodes/delay/flow/check.d.ts +16 -0
- package/dist/nodes/delay/flow/check.js +86 -0
- package/dist/nodes/delay/flow/factories.d.ts +28 -0
- package/dist/nodes/delay/flow/factories.js +38 -0
- package/dist/nodes/delay/flow/family.d.ts +3 -0
- package/dist/nodes/delay/flow/family.js +8 -0
- package/dist/nodes/delay/flow/index.d.ts +3 -0
- package/dist/nodes/delay/flow/index.js +3 -0
- package/dist/nodes/delay/flow/node-type.d.ts +13 -0
- package/dist/nodes/delay/flow/node-type.js +71 -0
- package/dist/nodes/delay/flow/spec.d.ts +43 -0
- package/dist/nodes/delay/flow/spec.js +16 -0
- package/dist/nodes/document/flow/factories.d.ts +27 -0
- package/dist/nodes/document/flow/factories.js +30 -0
- package/dist/nodes/document/flow/family.d.ts +3 -0
- package/dist/nodes/document/flow/family.js +7 -0
- package/dist/nodes/document/flow/index.d.ts +3 -0
- package/dist/nodes/document/flow/index.js +3 -0
- package/dist/nodes/document/flow/node-type.d.ts +14 -0
- package/dist/nodes/document/flow/node-type.js +150 -0
- package/dist/nodes/document/flow/spec.d.ts +65 -0
- package/dist/nodes/document/flow/spec.js +1 -0
- package/dist/nodes/mock/flow/factories.d.ts +51 -0
- package/dist/nodes/mock/flow/factories.js +47 -0
- package/dist/nodes/mock/flow/family.d.ts +3 -0
- package/dist/nodes/mock/flow/family.js +7 -0
- package/dist/nodes/mock/flow/index.d.ts +2 -0
- package/dist/nodes/mock/flow/index.js +2 -0
- package/dist/nodes/mock/flow/node-type.d.ts +11 -0
- package/dist/nodes/mock/flow/node-type.js +51 -0
- package/dist/nodes/script/flow/check.d.ts +19 -0
- package/dist/nodes/script/flow/check.js +49 -0
- package/dist/nodes/script/flow/factories.d.ts +14 -0
- package/dist/nodes/script/flow/factories.js +15 -0
- package/dist/nodes/script/flow/family.d.ts +3 -0
- package/dist/nodes/script/flow/family.js +8 -0
- package/dist/nodes/script/flow/index.d.ts +3 -0
- package/dist/nodes/script/flow/index.js +3 -0
- package/dist/nodes/script/flow/node-type.d.ts +7 -0
- package/dist/nodes/script/flow/node-type.js +125 -0
- package/dist/nodes/script/flow/spec.d.ts +52 -0
- package/dist/nodes/script/flow/spec.js +1 -0
- package/dist/nodes/transform/flow/check.d.ts +6 -0
- package/dist/nodes/transform/flow/check.js +229 -0
- package/dist/nodes/transform/flow/factories.d.ts +52 -0
- package/dist/nodes/transform/flow/factories.js +53 -0
- package/dist/nodes/transform/flow/family.d.ts +3 -0
- package/dist/nodes/transform/flow/family.js +8 -0
- package/dist/nodes/transform/flow/index.d.ts +3 -0
- package/dist/nodes/transform/flow/index.js +3 -0
- package/dist/nodes/transform/flow/node-type.d.ts +7 -0
- package/dist/nodes/transform/flow/node-type.js +245 -0
- package/dist/nodes/transform/flow/spec.d.ts +116 -0
- package/dist/nodes/transform/flow/spec.js +10 -0
- package/dist/raw-node-advice.d.ts +16 -0
- package/dist/raw-node-advice.js +36 -0
- package/dist/raw-node.d.ts +71 -0
- package/dist/raw-node.js +116 -0
- package/dist/registry/uip/pipeline-front-door.js +5 -3
- package/dist/serialize.js +246 -549
- package/package.json +2 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { documentClassifyNodeType, DOCUMENT_DIAGNOSTICS, dynamicExtractNodeType } from './node-type.js';
|
|
2
|
+
export const documentFlowFamily = {
|
|
3
|
+
id: 'document',
|
|
4
|
+
title: 'Document understanding',
|
|
5
|
+
types: [documentClassifyNodeType, dynamicExtractNodeType],
|
|
6
|
+
diagnostics: DOCUMENT_DIAGNOSTICS,
|
|
7
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DiagnosticCatalog } from '../../../core/nodes/family.js';
|
|
2
|
+
import type { FlowNodeType } from '../../../flow-node-type.js';
|
|
3
|
+
import type { DocumentClassifyInputs, DynamicExtractInputs } from './spec.js';
|
|
4
|
+
export type DocumentClassifySpec = {
|
|
5
|
+
kind: 'documentClassify';
|
|
6
|
+
inputs: DocumentClassifyInputs;
|
|
7
|
+
};
|
|
8
|
+
export type DynamicExtractSpec = {
|
|
9
|
+
kind: 'dynamicExtract';
|
|
10
|
+
inputs: DynamicExtractInputs;
|
|
11
|
+
};
|
|
12
|
+
export declare const DOCUMENT_DIAGNOSTICS: DiagnosticCatalog;
|
|
13
|
+
export declare const documentClassifyNodeType: FlowNodeType<DocumentClassifySpec>;
|
|
14
|
+
export declare const dynamicExtractNodeType: FlowNodeType<DynamicExtractSpec>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two document node types: Document Classify (`uipath.document.classify@1.0`)
|
|
3
|
+
* and Dynamic Extract (`uipath.ixp.extract-document-builder@1.0.0`). Moved from
|
|
4
|
+
* serialize.ts / check.ts / decompile.ts in Phase 4 of
|
|
5
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; serialized output, printed source,
|
|
6
|
+
* codes and messages unchanged.
|
|
7
|
+
*
|
|
8
|
+
* Not here: `ixpExtract()` (`uipath.ixp.<project type>`), whose type name comes
|
|
9
|
+
* from the model rather than being one fixed name, which the contract does not
|
|
10
|
+
* express yet.
|
|
11
|
+
*/
|
|
12
|
+
import { toExpr } from '../../../core/expr.js';
|
|
13
|
+
import { jsonClone } from '../../../core/json-file.js';
|
|
14
|
+
export const DOCUMENT_DIAGNOSTICS = {
|
|
15
|
+
DOC_NO_FILEREF: { severity: 'error', summary: 'no fileRef, so nothing to classify or extract from' },
|
|
16
|
+
EXTRACT_SCHEMA_SHAPE: { severity: 'error', summary: 'a Dynamic Extract schema that is not an object' },
|
|
17
|
+
};
|
|
18
|
+
function checkFileRef(inputs, verb, ctx) {
|
|
19
|
+
const fr = inputs.fileRef;
|
|
20
|
+
const empty = fr === undefined || fr === null || (typeof fr === 'string' && fr.trim() === '');
|
|
21
|
+
if (empty) {
|
|
22
|
+
ctx.report('DOC_NO_FILEREF', `"${ctx.step}" has no fileRef — nothing to ${verb}. Reference a file input or an upstream attachment.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** The definition's `inputDefaults`, which both nodes spread first. */
|
|
26
|
+
function defaults(typeName, version, ctx) {
|
|
27
|
+
return jsonClone((ctx.definition(typeName, version)?.inputDefaults) ?? {});
|
|
28
|
+
}
|
|
29
|
+
/** `fileRef`, as the lift reads it: `=js:` text as an Expr, anything else as text. */
|
|
30
|
+
function liftFileRef(node, ctx) {
|
|
31
|
+
const fr = ctx.sourceText(node.inputs?.fileRef) ?? '';
|
|
32
|
+
return fr.startsWith('=js:') ? ctx.expr(fr) : fr;
|
|
33
|
+
}
|
|
34
|
+
/** `pageRange` when it is a non-empty string, as the lift reads it. */
|
|
35
|
+
function liftPageRange(node) {
|
|
36
|
+
const p = node.inputs?.pageRange;
|
|
37
|
+
return typeof p === 'string' && p !== '' ? p : undefined;
|
|
38
|
+
}
|
|
39
|
+
export const documentClassifyNodeType = {
|
|
40
|
+
kind: 'documentClassify', typeName: 'uipath.document.classify', version: '1.0', factory: 'documentClassify',
|
|
41
|
+
definition: 'bundled', rawNode: { factory: 'documentClassify()' },
|
|
42
|
+
serialize: ({ inputs }, ctx) => {
|
|
43
|
+
const d = defaults('uipath.document.classify', '1.0', ctx);
|
|
44
|
+
// Classify follows the default envelope rules for fileRef (unlike the
|
|
45
|
+
// `uipath.ixp.*` extractors — see migrate's UNWRAPPED_INPUTS).
|
|
46
|
+
return {
|
|
47
|
+
inputs: {
|
|
48
|
+
...d,
|
|
49
|
+
fileRef: ctx.render(toExpr(inputs.fileRef)),
|
|
50
|
+
...(inputs.pageRange !== undefined ? { pageRange: inputs.pageRange } : {}),
|
|
51
|
+
...(inputs.splitPages !== undefined ? { splitPages: inputs.splitPages } : {}),
|
|
52
|
+
...(inputs.modelConfig !== undefined
|
|
53
|
+
? { modelConfig: { ...(d.modelConfig ?? {}), ...inputs.modelConfig } }
|
|
54
|
+
: {}),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
deserialize: (node, ctx) => {
|
|
59
|
+
const pageRange = liftPageRange(node);
|
|
60
|
+
const split = ctx.plainValue(node.inputs?.splitPages);
|
|
61
|
+
return {
|
|
62
|
+
kind: 'documentClassify',
|
|
63
|
+
inputs: {
|
|
64
|
+
fileRef: liftFileRef(node, ctx),
|
|
65
|
+
...(pageRange !== undefined ? { pageRange } : {}),
|
|
66
|
+
...(split === true ? { splitPages: true } : {}),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
print: ({ inputs }, ctx) => ({
|
|
71
|
+
factory: 'documentClassify',
|
|
72
|
+
options: [
|
|
73
|
+
['fileRef', ctx.value(inputs.fileRef)],
|
|
74
|
+
['pageRange', inputs.pageRange !== undefined ? ctx.string(inputs.pageRange) : undefined],
|
|
75
|
+
['splitPages', inputs.splitPages === true ? 'true' : undefined],
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
check: ({ inputs }, ctx) => checkFileRef(inputs, 'classify', ctx),
|
|
79
|
+
// check collected no expressions for this kind before the port; unchanged by it.
|
|
80
|
+
expressions: () => [],
|
|
81
|
+
output: () => ({ kind: 'opaque' }),
|
|
82
|
+
};
|
|
83
|
+
export const dynamicExtractNodeType = {
|
|
84
|
+
kind: 'dynamicExtract', typeName: 'uipath.ixp.extract-document-builder', version: '1.0.0', factory: 'dynamicExtract',
|
|
85
|
+
definition: 'bundled', rawNode: { factory: 'dynamicExtract()' },
|
|
86
|
+
serialize: ({ inputs }, ctx) => {
|
|
87
|
+
const d = defaults('uipath.ixp.extract-document-builder', '1.0.0', ctx);
|
|
88
|
+
const m = inputs.model;
|
|
89
|
+
return {
|
|
90
|
+
inputs: {
|
|
91
|
+
...d,
|
|
92
|
+
// The deployment identity Studio Web's panel destructures — both the
|
|
93
|
+
// nested `model` object and the flat mirrors the definition declares.
|
|
94
|
+
model: { modelName: m.modelName, folderKey: m.folderKey },
|
|
95
|
+
modelName: m.modelName,
|
|
96
|
+
folderKey: m.folderKey,
|
|
97
|
+
...(m.projectId !== undefined ? { projectId: m.projectId } : {}),
|
|
98
|
+
...(m.projectName !== undefined ? { projectName: m.projectName } : {}),
|
|
99
|
+
...(m.folderName !== undefined ? { folderName: m.folderName } : {}),
|
|
100
|
+
...(m.versionTag !== undefined ? { versionTag: m.versionTag } : {}),
|
|
101
|
+
// A `uipath.ixp.*` fileRef must stay a PLAIN `=js:` string — the
|
|
102
|
+
// platform reads it unwrapped (see migrate's UNWRAPPED_INPUTS).
|
|
103
|
+
fileRef: ctx.render(toExpr(inputs.fileRef)),
|
|
104
|
+
...(inputs.pageRange !== undefined ? { pageRange: inputs.pageRange } : {}),
|
|
105
|
+
...(inputs.modelConfig !== undefined
|
|
106
|
+
? { modelConfig: { ...(d.modelConfig ?? {}), ...inputs.modelConfig } }
|
|
107
|
+
: {}),
|
|
108
|
+
...(inputs.schema !== undefined ? { schemaDocument: inputs.schema } : {}),
|
|
109
|
+
// The definition's model declares `source: true`: the platform mints a
|
|
110
|
+
// stable storage slot per instance; omit it and the node validates then
|
|
111
|
+
// faults. Deterministic, like every other minted identity here.
|
|
112
|
+
source: ctx.mint('source'),
|
|
113
|
+
},
|
|
114
|
+
// IxP instances must NOT carry the manifest's model block — the slim
|
|
115
|
+
// { type, serviceType } lives only in definitions[] (product validate
|
|
116
|
+
// rejects a node-level copy). Per call, not `nodeModel`: a rawNode of this
|
|
117
|
+
// type keeps the model it always had.
|
|
118
|
+
model: 'omit',
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
deserialize: (node, ctx) => {
|
|
122
|
+
const pageRange = liftPageRange(node);
|
|
123
|
+
const schema = node.inputs?.schemaDocument;
|
|
124
|
+
return {
|
|
125
|
+
kind: 'dynamicExtract',
|
|
126
|
+
inputs: {
|
|
127
|
+
fileRef: liftFileRef(node, ctx),
|
|
128
|
+
...(schema !== undefined ? { schema: schema } : {}),
|
|
129
|
+
...(pageRange !== undefined ? { pageRange } : {}),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
print: ({ inputs }, ctx) => ({
|
|
134
|
+
factory: 'dynamicExtract',
|
|
135
|
+
options: [
|
|
136
|
+
['fileRef', ctx.value(inputs.fileRef)],
|
|
137
|
+
['schema', inputs.schema !== undefined ? ctx.json(inputs.schema) : undefined],
|
|
138
|
+
['pageRange', inputs.pageRange !== undefined ? ctx.string(inputs.pageRange) : undefined],
|
|
139
|
+
],
|
|
140
|
+
}),
|
|
141
|
+
check: ({ inputs }, ctx) => {
|
|
142
|
+
checkFileRef(inputs, 'extract from', ctx);
|
|
143
|
+
if (inputs.schema !== undefined && (typeof inputs.schema !== 'object' || Array.isArray(inputs.schema))) {
|
|
144
|
+
ctx.report('EXTRACT_SCHEMA_SHAPE', `"${ctx.step}"'s schema must be an object (the inline extraction schema document).`);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
// check collected no expressions for this kind before the port; unchanged by it.
|
|
148
|
+
expressions: () => [],
|
|
149
|
+
output: () => ({ kind: 'opaque' }),
|
|
150
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The document family's authoring types — Document Classify
|
|
3
|
+
* (`uipath.document.classify`) and Dynamic Extract
|
|
4
|
+
* (`uipath.ixp.extract-document-builder`) — and their kinds' entries in
|
|
5
|
+
* `FlowActionSpecs`. Moved from core/actions.ts in Phase 4 of
|
|
6
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md.
|
|
7
|
+
*/
|
|
8
|
+
import type { Expr } from '../../../core/expr.js';
|
|
9
|
+
export interface DocumentClassifyInputs {
|
|
10
|
+
/** The document to classify — a file reference (`input('file')`, `out('fetch', 'fileRef')`, …). */
|
|
11
|
+
fileRef: string | Expr;
|
|
12
|
+
/** Page range to classify, e.g. `'1-3'`. Omit for the whole document. */
|
|
13
|
+
pageRange?: string;
|
|
14
|
+
/** Split multi-document files into per-type page ranges. */
|
|
15
|
+
splitPages?: boolean;
|
|
16
|
+
/** Model configuration overrides; omit for the platform defaults (gemini_2_5_flash). */
|
|
17
|
+
modelConfig?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface DynamicExtractInputs {
|
|
20
|
+
/** The document to extract from — a file reference. */
|
|
21
|
+
fileRef: string | Expr;
|
|
22
|
+
/**
|
|
23
|
+
* The IXP model deployment the extraction runs against. Dynamic Extract
|
|
24
|
+
* authors its SCHEMA inline, but execution still needs a model: Studio Web's
|
|
25
|
+
* panel destructures `modelName` and `folderKey`, and the platform rejects an
|
|
26
|
+
* instance without them.
|
|
27
|
+
*/
|
|
28
|
+
model: {
|
|
29
|
+
/** The deployment's model name, e.g. `'invoiceixp-cef0d447-ixp'`. */
|
|
30
|
+
modelName: string;
|
|
31
|
+
/** Folder key (GUID) the deployment lives in. */
|
|
32
|
+
folderKey: string;
|
|
33
|
+
/** The IXP project's id (GUID). */
|
|
34
|
+
projectId?: string;
|
|
35
|
+
/** The IXP project's display name. */
|
|
36
|
+
projectName?: string;
|
|
37
|
+
/** Folder display name. */
|
|
38
|
+
folderName?: string;
|
|
39
|
+
/** Deployment version tag; omit for the live version. */
|
|
40
|
+
versionTag?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The extraction schema (the node's inline taxonomy): a JSON-schema-shaped
|
|
44
|
+
* document describing the fields to extract. This is the Dynamic Extract
|
|
45
|
+
* node's defining input — authored inline rather than referencing a deployed
|
|
46
|
+
* IXP project (use {@link ixpExtract} for those).
|
|
47
|
+
*/
|
|
48
|
+
schema?: Record<string, unknown>;
|
|
49
|
+
/** Page range to extract, e.g. `'1-3'`. Omit for the whole document. */
|
|
50
|
+
pageRange?: string;
|
|
51
|
+
/** Model configuration overrides; omit for the platform defaults. */
|
|
52
|
+
modelConfig?: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
declare module '../../../core/actions.js' {
|
|
55
|
+
interface FlowActionSpecs {
|
|
56
|
+
/** The spec {@link documentClassify} builds. */
|
|
57
|
+
documentClassify: {
|
|
58
|
+
inputs: DocumentClassifyInputs;
|
|
59
|
+
};
|
|
60
|
+
/** The spec {@link dynamicExtract} builds. */
|
|
61
|
+
dynamicExtract: {
|
|
62
|
+
inputs: DynamicExtractInputs;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The placeholder factory, `mock()`. Moved from core/actions.ts in Phase 4 of
|
|
3
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the package entry re-exports it.
|
|
4
|
+
*/
|
|
5
|
+
import { type ActionSpec } from '../../../core/actions.js';
|
|
6
|
+
/**
|
|
7
|
+
* Declare a PLACEHOLDER step — "a real node goes here later".
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* A mock takes **no inputs and publishes nothing**. It is a marker on the canvas
|
|
11
|
+
* that keeps the graph wired and the flow deployable while one step is still
|
|
12
|
+
* missing — not a stub that returns test data. `out('extractInvoice')` is
|
|
13
|
+
* refused at compile time (`MOCK_HAS_NO_OUTPUT`) because it would read `null` at
|
|
14
|
+
* run time, always.
|
|
15
|
+
*
|
|
16
|
+
* Say what belongs there in the step's own name and in the label the canvas
|
|
17
|
+
* shows; the corpus's placeholders read like
|
|
18
|
+
* `"Extract Invoice Fields (mock — IxP model not yet published)"`.
|
|
19
|
+
*
|
|
20
|
+
* ### Why there are no arguments (convention #191 — the family contract)
|
|
21
|
+
*
|
|
22
|
+
* The platform's `core.logic.mock@1.0.0` declares **no `inputDefinition`** and one
|
|
23
|
+
* output whose `source` is the literal `"null"`. Measured over the 4,033 distinct
|
|
24
|
+
* archived `.flow` artifacts: **74 mock instances in 62 flows, and 0 carrying a
|
|
25
|
+
* fixture anywhere in the node** — 71 of them with `inputs: {}` or no `inputs`
|
|
26
|
+
* key. The 3 exceptions carry free-text `placeholder` / `_placeholder` keys the
|
|
27
|
+
* definition never declares, invented by agents on runs that scored 0.9 and 0.4.
|
|
28
|
+
*
|
|
29
|
+
* **This is NOT a local runner's `kind: 'mock'` test construct**, which returns a
|
|
30
|
+
* baked fixture. They are different things that share
|
|
31
|
+
* a name, and a `mock({ fixture })` surface would emit a node whose local
|
|
32
|
+
* behaviour and deployed behaviour disagree silently — see
|
|
33
|
+
* [#125](https://github.com/UiPath/flow-builder-sdk/issues/125). Nothing this SDK
|
|
34
|
+
* emits opens that channel: an SDK-authored mock publishes `null` locally,
|
|
35
|
+
* exactly as the platform does.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* **Hold a step's place until the real node exists**
|
|
39
|
+
* ```ts
|
|
40
|
+
* .step('extractInvoice', mock()) // ← swap for the IxP node once the project exists
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mock(): ActionSpec;
|
|
46
|
+
declare module '../../../core/actions.js' {
|
|
47
|
+
interface FlowActionSpecs {
|
|
48
|
+
/** A placeholder — no inputs, publishes nothing. See {@link mock}. */
|
|
49
|
+
mock: {};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The placeholder factory, `mock()`. Moved from core/actions.ts in Phase 4 of
|
|
3
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the package entry re-exports it.
|
|
4
|
+
*/
|
|
5
|
+
import { builtinActionSpec } from '../../../core/actions.js';
|
|
6
|
+
/**
|
|
7
|
+
* Declare a PLACEHOLDER step — "a real node goes here later".
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* A mock takes **no inputs and publishes nothing**. It is a marker on the canvas
|
|
11
|
+
* that keeps the graph wired and the flow deployable while one step is still
|
|
12
|
+
* missing — not a stub that returns test data. `out('extractInvoice')` is
|
|
13
|
+
* refused at compile time (`MOCK_HAS_NO_OUTPUT`) because it would read `null` at
|
|
14
|
+
* run time, always.
|
|
15
|
+
*
|
|
16
|
+
* Say what belongs there in the step's own name and in the label the canvas
|
|
17
|
+
* shows; the corpus's placeholders read like
|
|
18
|
+
* `"Extract Invoice Fields (mock — IxP model not yet published)"`.
|
|
19
|
+
*
|
|
20
|
+
* ### Why there are no arguments (convention #191 — the family contract)
|
|
21
|
+
*
|
|
22
|
+
* The platform's `core.logic.mock@1.0.0` declares **no `inputDefinition`** and one
|
|
23
|
+
* output whose `source` is the literal `"null"`. Measured over the 4,033 distinct
|
|
24
|
+
* archived `.flow` artifacts: **74 mock instances in 62 flows, and 0 carrying a
|
|
25
|
+
* fixture anywhere in the node** — 71 of them with `inputs: {}` or no `inputs`
|
|
26
|
+
* key. The 3 exceptions carry free-text `placeholder` / `_placeholder` keys the
|
|
27
|
+
* definition never declares, invented by agents on runs that scored 0.9 and 0.4.
|
|
28
|
+
*
|
|
29
|
+
* **This is NOT a local runner's `kind: 'mock'` test construct**, which returns a
|
|
30
|
+
* baked fixture. They are different things that share
|
|
31
|
+
* a name, and a `mock({ fixture })` surface would emit a node whose local
|
|
32
|
+
* behaviour and deployed behaviour disagree silently — see
|
|
33
|
+
* [#125](https://github.com/UiPath/flow-builder-sdk/issues/125). Nothing this SDK
|
|
34
|
+
* emits opens that channel: an SDK-authored mock publishes `null` locally,
|
|
35
|
+
* exactly as the platform does.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* **Hold a step's place until the real node exists**
|
|
39
|
+
* ```ts
|
|
40
|
+
* .step('extractInvoice', mock()) // ← swap for the IxP node once the project exists
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
44
|
+
*/
|
|
45
|
+
export function mock() {
|
|
46
|
+
return builtinActionSpec({ kind: 'mock' });
|
|
47
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The placeholder node type, `core.logic.mock` (bundled 1.0.0 and 1.0). Moved
|
|
3
|
+
* from serialize.ts / check.ts / decompile.ts in Phase 4 of
|
|
4
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; serialized output, codes and messages
|
|
5
|
+
* unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import type { FlowVersionedNodeType } from '../../../flow-node-type.js';
|
|
8
|
+
export type MockSpec = {
|
|
9
|
+
kind: 'mock';
|
|
10
|
+
};
|
|
11
|
+
export declare const mockNodeType: FlowVersionedNodeType<MockSpec>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
function mockAt(version) {
|
|
2
|
+
return {
|
|
3
|
+
kind: 'mock', typeName: 'core.logic.mock', version, factory: 'mock', definition: 'bundled',
|
|
4
|
+
rawNode: { factory: 'mock()' },
|
|
5
|
+
// A placeholder is a pure definition node: the definition supplies `model`
|
|
6
|
+
// and the single `output` (`source: "null"`), and there is nothing else to
|
|
7
|
+
// write. `inputs: {}` rather than an omitted key because that is what the
|
|
8
|
+
// vendored Studio-Web golden writes (`shared/sample-flows/new.flow`, all
|
|
9
|
+
// three of its mock nodes) and what 36 of the 74 archived instances carry.
|
|
10
|
+
//
|
|
11
|
+
// Nothing here can open a fixture channel: a runner that honours one looks
|
|
12
|
+
// for `fixture`/`output`/`value` in the node's `inputs`, and the factory
|
|
13
|
+
// takes no arguments, so `inputs` is always the empty object. That
|
|
14
|
+
// is the #125 fence, made unrepresentable rather than documented.
|
|
15
|
+
serialize: () => ({ inputs: {} }),
|
|
16
|
+
deserialize: () => ({ kind: 'mock' }),
|
|
17
|
+
// A `mock()` is a PLACEHOLDER: `core.logic.mock`'s definition declares one
|
|
18
|
+
// output whose `source` is the literal `"null"`, so the value is null at run
|
|
19
|
+
// time whatever the flow does. Unlike the other no-output rules, the node
|
|
20
|
+
// DOES declare an output slot — which is exactly why the read is silent: it
|
|
21
|
+
// resolves in the designer, it resolves in `variables.nodes`, and it hands
|
|
22
|
+
// the downstream step a null.
|
|
23
|
+
//
|
|
24
|
+
// WHY THIS RULE LIVES IN THE AUTHORING CHECKER rather than in a pass over the
|
|
25
|
+
// compiled artifact (convention #191). Reading a placeholder's output is the
|
|
26
|
+
// ARCHIVE's dominant idiom, not a rarity: 55 of the 62 archived mock-carrying
|
|
27
|
+
// artifacts do it — 110 read sites, 87 of them inside a script's body and 19
|
|
28
|
+
// in a decision's expression — and **39 of those 55 come from runs that
|
|
29
|
+
// scored 1.0**. That is an author writing the downstream code for the real
|
|
30
|
+
// node the placeholder stands in for, and a `.flow`-level rule refusing it
|
|
31
|
+
// would refuse the deployed corpus (lesson 47). An SDK author is in the
|
|
32
|
+
// other position: they wrote `mock()` here, in this file, and the SDK can
|
|
33
|
+
// say at compile time that the read is dead.
|
|
34
|
+
// Measured 2026-08-02 over 4,033 distinct archived artifacts —
|
|
35
|
+
// runs/flow-sdk-cleanup-2026-08-02/step0/mock-output-read-sites.txt.
|
|
36
|
+
// A placeholder carries no authored values.
|
|
37
|
+
expressions: () => [],
|
|
38
|
+
output: () => ({
|
|
39
|
+
kind: 'none',
|
|
40
|
+
code: 'MOCK_HAS_NO_OUTPUT',
|
|
41
|
+
message: ({ node, ref, reader }) => `Placeholder "${node}" publishes nothing, but "${ref}" reads it in "${reader}". `
|
|
42
|
+
+ 'A mock() is a marker for a node that does not exist yet — its output is null at run time, always. '
|
|
43
|
+
+ 'Keep the placeholder while the real node does not exist, and have the reader use a value you supply instead (a flow input, as example/ClaimScaffold.flow.ts does). '
|
|
44
|
+
+ 'Replace the placeholder only with the real node, once `registry search` finds it; a script returning fixed values is not the real node.',
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export const mockNodeType = {
|
|
49
|
+
kind: 'mock', typeName: 'core.logic.mock', factory: 'mock', defaultVersion: '1.0.0',
|
|
50
|
+
versions: { '1.0.0': mockAt('1.0.0'), '1.0': mockAt('1.0') },
|
|
51
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Script family's rules. Moved verbatim from check.ts in Phase 4 of
|
|
3
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; codes and messages unchanged.
|
|
4
|
+
*/
|
|
5
|
+
import type { DiagnosticCatalog } from '../../../core/nodes/family.js';
|
|
6
|
+
import type { FlowCheckContext } from '../../../flow-node-type.js';
|
|
7
|
+
export declare const SCRIPT_DIAGNOSTICS: DiagnosticCatalog;
|
|
8
|
+
/**
|
|
9
|
+
* A script step's `returns` — the author overriding what the body looks like.
|
|
10
|
+
*
|
|
11
|
+
* TypeScript already refuses a bad value at the call site, so this is the fence
|
|
12
|
+
* for everything that does NOT go through the type checker: a `.flow.ts` loaded
|
|
13
|
+
* as plain JS, a generated flow, a value read from config. Both mistakes below
|
|
14
|
+
* reach the emitted file silently and are then the designer's problem instead of
|
|
15
|
+
* the author's, which is precisely the failure this whole feature exists to undo.
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkScript(inputs: {
|
|
18
|
+
returns?: unknown;
|
|
19
|
+
}, ctx: FlowCheckContext): void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const SCRIPT_DIAGNOSTICS = {
|
|
2
|
+
SCRIPT_RETURNS_UNKNOWN_TYPE: { severity: 'error', summary: '`returns` names a type the wire format does not know' },
|
|
3
|
+
SCRIPT_EMPTY_RETURNS: { severity: 'warning', summary: '`returns: {}` names no fields' },
|
|
4
|
+
};
|
|
5
|
+
/** The type vocabulary a script's `returns` may name — what the wire format accepts. */
|
|
6
|
+
const SCRIPT_RETURN_TYPES = new Set(['string', 'number', 'boolean', 'object', 'array']);
|
|
7
|
+
/**
|
|
8
|
+
* A script step's `returns` — the author overriding what the body looks like.
|
|
9
|
+
*
|
|
10
|
+
* TypeScript already refuses a bad value at the call site, so this is the fence
|
|
11
|
+
* for everything that does NOT go through the type checker: a `.flow.ts` loaded
|
|
12
|
+
* as plain JS, a generated flow, a value read from config. Both mistakes below
|
|
13
|
+
* reach the emitted file silently and are then the designer's problem instead of
|
|
14
|
+
* the author's, which is precisely the failure this whole feature exists to undo.
|
|
15
|
+
*/
|
|
16
|
+
export function checkScript(inputs, ctx) {
|
|
17
|
+
const step = ctx.step;
|
|
18
|
+
const returns = inputs?.returns;
|
|
19
|
+
if (returns === undefined)
|
|
20
|
+
return;
|
|
21
|
+
if (typeof returns === 'string') {
|
|
22
|
+
if (!SCRIPT_RETURN_TYPES.has(returns)) {
|
|
23
|
+
ctx.report('SCRIPT_RETURNS_UNKNOWN_TYPE', `Script step "${step}" declares \`returns: ${JSON.stringify(returns)}\`, which is not a type the `
|
|
24
|
+
+ `wire format knows. Use one of ${[...SCRIPT_RETURN_TYPES].map((t) => `"${t}"`).join(', ')}, or a `
|
|
25
|
+
+ `field map like \`{ total: "number" }\` to name an object's fields.`);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (typeof returns !== 'object' || returns === null || Array.isArray(returns)) {
|
|
30
|
+
ctx.report('SCRIPT_RETURNS_UNKNOWN_TYPE', `Script step "${step}"'s \`returns\` is ${JSON.stringify(returns)}. It takes either a type name or a `
|
|
31
|
+
+ `map of field names to types (\`{ total: "number" }\`).`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const fields = returns;
|
|
35
|
+
// Same call as `APIWF_EMPTY_RETURNS` one surface over: an empty map declares
|
|
36
|
+
// nothing, emits nothing, and reads exactly like omitting the key — so it is
|
|
37
|
+
// almost always a half-finished edit rather than a statement.
|
|
38
|
+
if (Object.keys(fields).length === 0) {
|
|
39
|
+
ctx.report('SCRIPT_EMPTY_RETURNS', `Script step "${step}" declares \`returns: {}\`, which names no fields and emits nothing — the same `
|
|
40
|
+
+ `as omitting it. Name the fields, or drop the key and let the body speak for itself.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const [name, type] of Object.entries(fields)) {
|
|
44
|
+
if (typeof type !== 'string' || !SCRIPT_RETURN_TYPES.has(type)) {
|
|
45
|
+
ctx.report('SCRIPT_RETURNS_UNKNOWN_TYPE', `Script step "${step}" declares field "${name}" as ${JSON.stringify(type)}, which is not a type the `
|
|
46
|
+
+ `wire format knows. Use one of ${[...SCRIPT_RETURN_TYPES].map((t) => `"${t}"`).join(', ')}.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Script factory, `script()`. Moved from core/actions.ts in Phase 4 of
|
|
3
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the package entry re-exports it.
|
|
4
|
+
*/
|
|
5
|
+
import { type ActionSpec } from '../../../core/actions.js';
|
|
6
|
+
import type { ScriptInputs } from './spec.js';
|
|
7
|
+
/**
|
|
8
|
+
* Declare an inline script action.
|
|
9
|
+
*
|
|
10
|
+
* @param inputs - The JavaScript body (`code`, which must `return`) and what it
|
|
11
|
+
* returns (`returns`).
|
|
12
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function script(inputs: ScriptInputs): ActionSpec;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Script factory, `script()`. Moved from core/actions.ts in Phase 4 of
|
|
3
|
+
* docs/NODE_TYPE_ARCHITECTURE_DESIGN.md; the package entry re-exports it.
|
|
4
|
+
*/
|
|
5
|
+
import { builtinActionSpec } from '../../../core/actions.js';
|
|
6
|
+
/**
|
|
7
|
+
* Declare an inline script action.
|
|
8
|
+
*
|
|
9
|
+
* @param inputs - The JavaScript body (`code`, which must `return`) and what it
|
|
10
|
+
* returns (`returns`).
|
|
11
|
+
* @returns An action spec to pass to `.step(name, …)`.
|
|
12
|
+
*/
|
|
13
|
+
export function script(inputs) {
|
|
14
|
+
return builtinActionSpec({ kind: 'script', inputs });
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FlowVersionedNodeType } from '../../../flow-node-type.js';
|
|
2
|
+
import type { ScriptInputs } from './spec.js';
|
|
3
|
+
export type ScriptSpec = {
|
|
4
|
+
kind: 'script';
|
|
5
|
+
inputs: ScriptInputs;
|
|
6
|
+
};
|
|
7
|
+
export declare const scriptNodeType: FlowVersionedNodeType<ScriptSpec>;
|