@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.
Files changed (134) hide show
  1. package/dist/api-index.md +185 -184
  2. package/dist/api-members.md +506 -473
  3. package/dist/check.js +358 -695
  4. package/dist/cli/commands/flow.js +3 -0
  5. package/dist/compile-cli.js +51 -0
  6. package/dist/core/actions.d.ts +132 -765
  7. package/dist/core/actions.js +1 -307
  8. package/dist/core/binding-identity.d.ts +22 -0
  9. package/dist/core/binding-identity.js +28 -0
  10. package/dist/core/context-index.d.ts +34 -0
  11. package/dist/core/context-index.js +38 -0
  12. package/dist/core/definitionless-node-types.d.ts +16 -0
  13. package/dist/core/definitionless-node-types.js +16 -0
  14. package/dist/core/error-port.d.ts +6 -0
  15. package/dist/core/error-port.js +9 -0
  16. package/dist/core/form-field-type.d.ts +33 -0
  17. package/dist/core/form-field-type.js +30 -0
  18. package/dist/core/hitl-routing.d.ts +8 -0
  19. package/dist/core/hitl-routing.js +17 -1
  20. package/dist/core/node-classes.d.ts +4 -63
  21. package/dist/core/node-classes.js +0 -112
  22. package/dist/core/nodes/family.d.ts +36 -0
  23. package/dist/core/nodes/family.js +1 -0
  24. package/dist/core/nodes/node-type.d.ts +136 -0
  25. package/dist/core/nodes/node-type.js +1 -0
  26. package/dist/core/nodes/registry.d.ts +57 -0
  27. package/dist/core/nodes/registry.js +122 -0
  28. package/dist/core/nodes/versioned.d.ts +50 -0
  29. package/dist/core/nodes/versioned.js +46 -0
  30. package/dist/core/process-resource-sort-order.d.ts +40 -0
  31. package/dist/core/process-resource-sort-order.js +44 -0
  32. package/dist/core/typed-raw-node.d.ts +13 -62
  33. package/dist/core/typed-raw-node.js +40 -154
  34. package/dist/core/wire-expr.d.ts +27 -0
  35. package/dist/core/wire-expr.js +34 -0
  36. package/dist/decompile-cli.js +11 -1
  37. package/dist/decompile.d.ts +8 -3
  38. package/dist/decompile.js +665 -354
  39. package/dist/flow-definitions.d.ts +10 -0
  40. package/dist/flow-definitions.js +35 -0
  41. package/dist/flow-expr-check.js +1 -1
  42. package/dist/flow-node-registry.d.ts +13 -0
  43. package/dist/flow-node-registry.js +19 -0
  44. package/dist/flow-node-type.d.ts +192 -0
  45. package/dist/flow-node-type.js +1 -0
  46. package/dist/flow-sdk.d.ts +40 -1
  47. package/dist/flow-sdk.js +29 -2
  48. package/dist/flow-step-tree.js +2 -1
  49. package/dist/index.d.ts +2 -1
  50. package/dist/index.js +1 -0
  51. package/dist/merge-cli.js +25 -8
  52. package/dist/merge-roundtrip.d.ts +81 -0
  53. package/dist/merge-roundtrip.js +404 -0
  54. package/dist/merge.d.ts +35 -6
  55. package/dist/merge.js +124 -24
  56. package/dist/node-placement.d.ts +93 -0
  57. package/dist/node-placement.js +163 -0
  58. package/dist/nodes/data-fabric/flow/check.d.ts +13 -0
  59. package/dist/nodes/data-fabric/flow/check.js +164 -0
  60. package/dist/nodes/data-fabric/flow/factories.d.ts +113 -0
  61. package/dist/nodes/data-fabric/flow/factories.js +134 -0
  62. package/dist/nodes/data-fabric/flow/family.d.ts +7 -0
  63. package/dist/nodes/data-fabric/flow/family.js +9 -0
  64. package/dist/nodes/data-fabric/flow/index.d.ts +8 -0
  65. package/dist/nodes/data-fabric/flow/index.js +8 -0
  66. package/dist/nodes/data-fabric/flow/raw.d.ts +32 -0
  67. package/dist/nodes/data-fabric/flow/raw.js +100 -0
  68. package/dist/nodes/data-fabric/flow/shared.d.ts +77 -0
  69. package/dist/nodes/data-fabric/flow/shared.js +174 -0
  70. package/dist/nodes/data-fabric/flow/spec.d.ts +238 -0
  71. package/dist/nodes/data-fabric/flow/spec.js +1 -0
  72. package/dist/nodes/data-fabric/flow/verbs.d.ts +29 -0
  73. package/dist/nodes/data-fabric/flow/verbs.js +239 -0
  74. package/dist/nodes/delay/flow/check.d.ts +16 -0
  75. package/dist/nodes/delay/flow/check.js +86 -0
  76. package/dist/nodes/delay/flow/factories.d.ts +28 -0
  77. package/dist/nodes/delay/flow/factories.js +38 -0
  78. package/dist/nodes/delay/flow/family.d.ts +3 -0
  79. package/dist/nodes/delay/flow/family.js +8 -0
  80. package/dist/nodes/delay/flow/index.d.ts +3 -0
  81. package/dist/nodes/delay/flow/index.js +3 -0
  82. package/dist/nodes/delay/flow/node-type.d.ts +13 -0
  83. package/dist/nodes/delay/flow/node-type.js +71 -0
  84. package/dist/nodes/delay/flow/spec.d.ts +43 -0
  85. package/dist/nodes/delay/flow/spec.js +16 -0
  86. package/dist/nodes/document/flow/factories.d.ts +27 -0
  87. package/dist/nodes/document/flow/factories.js +30 -0
  88. package/dist/nodes/document/flow/family.d.ts +3 -0
  89. package/dist/nodes/document/flow/family.js +7 -0
  90. package/dist/nodes/document/flow/index.d.ts +3 -0
  91. package/dist/nodes/document/flow/index.js +3 -0
  92. package/dist/nodes/document/flow/node-type.d.ts +14 -0
  93. package/dist/nodes/document/flow/node-type.js +150 -0
  94. package/dist/nodes/document/flow/spec.d.ts +65 -0
  95. package/dist/nodes/document/flow/spec.js +1 -0
  96. package/dist/nodes/mock/flow/factories.d.ts +51 -0
  97. package/dist/nodes/mock/flow/factories.js +47 -0
  98. package/dist/nodes/mock/flow/family.d.ts +3 -0
  99. package/dist/nodes/mock/flow/family.js +7 -0
  100. package/dist/nodes/mock/flow/index.d.ts +2 -0
  101. package/dist/nodes/mock/flow/index.js +2 -0
  102. package/dist/nodes/mock/flow/node-type.d.ts +11 -0
  103. package/dist/nodes/mock/flow/node-type.js +51 -0
  104. package/dist/nodes/script/flow/check.d.ts +19 -0
  105. package/dist/nodes/script/flow/check.js +49 -0
  106. package/dist/nodes/script/flow/factories.d.ts +14 -0
  107. package/dist/nodes/script/flow/factories.js +15 -0
  108. package/dist/nodes/script/flow/family.d.ts +3 -0
  109. package/dist/nodes/script/flow/family.js +8 -0
  110. package/dist/nodes/script/flow/index.d.ts +3 -0
  111. package/dist/nodes/script/flow/index.js +3 -0
  112. package/dist/nodes/script/flow/node-type.d.ts +7 -0
  113. package/dist/nodes/script/flow/node-type.js +125 -0
  114. package/dist/nodes/script/flow/spec.d.ts +52 -0
  115. package/dist/nodes/script/flow/spec.js +1 -0
  116. package/dist/nodes/transform/flow/check.d.ts +6 -0
  117. package/dist/nodes/transform/flow/check.js +229 -0
  118. package/dist/nodes/transform/flow/factories.d.ts +52 -0
  119. package/dist/nodes/transform/flow/factories.js +53 -0
  120. package/dist/nodes/transform/flow/family.d.ts +3 -0
  121. package/dist/nodes/transform/flow/family.js +8 -0
  122. package/dist/nodes/transform/flow/index.d.ts +3 -0
  123. package/dist/nodes/transform/flow/index.js +3 -0
  124. package/dist/nodes/transform/flow/node-type.d.ts +7 -0
  125. package/dist/nodes/transform/flow/node-type.js +245 -0
  126. package/dist/nodes/transform/flow/spec.d.ts +116 -0
  127. package/dist/nodes/transform/flow/spec.js +10 -0
  128. package/dist/raw-node-advice.d.ts +16 -0
  129. package/dist/raw-node-advice.js +36 -0
  130. package/dist/raw-node.d.ts +71 -0
  131. package/dist/raw-node.js +116 -0
  132. package/dist/registry/uip/pipeline-front-door.js +5 -3
  133. package/dist/serialize.js +246 -549
  134. 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,3 @@
1
+ /** The document family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -0,0 +1,3 @@
1
+ /** The document family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -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,3 @@
1
+ /** The placeholder node family, as flow-node-registry.ts lists it: `core.logic.mock`. */
2
+ import type { FlowNodeFamily } from '../../../flow-node-type.js';
3
+ export declare const mockFlowFamily: FlowNodeFamily;
@@ -0,0 +1,7 @@
1
+ import { mockNodeType } from './node-type.js';
2
+ export const mockFlowFamily = {
3
+ id: 'mock',
4
+ title: 'Placeholder',
5
+ types: [mockNodeType],
6
+ diagnostics: { MOCK_HAS_NO_OUTPUT: { severity: 'error', summary: "a read of a placeholder's output" } },
7
+ };
@@ -0,0 +1,2 @@
1
+ /** The placeholder family's public surface, which the package entry re-exports. */
2
+ export * from './factories.js';
@@ -0,0 +1,2 @@
1
+ /** The placeholder family's public surface, which the package entry re-exports. */
2
+ export * from './factories.js';
@@ -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,3 @@
1
+ /** The Script node family, as flow-node-registry.ts lists it: `core.action.script`. */
2
+ import type { FlowNodeFamily } from '../../../flow-node-type.js';
3
+ export declare const scriptFlowFamily: FlowNodeFamily;
@@ -0,0 +1,8 @@
1
+ import { SCRIPT_DIAGNOSTICS } from './check.js';
2
+ import { scriptNodeType } from './node-type.js';
3
+ export const scriptFlowFamily = {
4
+ id: 'script',
5
+ title: 'Script',
6
+ types: [scriptNodeType],
7
+ diagnostics: SCRIPT_DIAGNOSTICS,
8
+ };
@@ -0,0 +1,3 @@
1
+ /** The Script family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -0,0 +1,3 @@
1
+ /** The Script family's public surface, which the package entry re-exports. */
2
+ export * from './spec.js';
3
+ export * from './factories.js';
@@ -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>;