@uipath/maestro-builder-sdk 5.2.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/LICENSE +21 -0
- package/README.md +322 -0
- package/dist/bindings-v2.d.ts +37 -0
- package/dist/bindings-v2.js +155 -0
- package/dist/bindings.d.ts +6 -0
- package/dist/bindings.js +6 -0
- package/dist/bpmn/bpmn-expr-check.d.ts +41 -0
- package/dist/bpmn/bpmn-expr-check.js +218 -0
- package/dist/bpmn/bpmn-sdk.d.ts +2257 -0
- package/dist/bpmn/bpmn-sdk.js +1476 -0
- package/dist/bpmn/check-cli.d.ts +3 -0
- package/dist/bpmn/check-cli.js +32 -0
- package/dist/bpmn/check.d.ts +25 -0
- package/dist/bpmn/check.js +430 -0
- package/dist/bpmn/compile-cli.d.ts +3 -0
- package/dist/bpmn/compile-cli.js +60 -0
- package/dist/bpmn/connector.d.ts +56 -0
- package/dist/bpmn/connector.js +199 -0
- package/dist/bpmn/decompile-cli.d.ts +8 -0
- package/dist/bpmn/decompile-cli.js +54 -0
- package/dist/bpmn/decompile.d.ts +6 -0
- package/dist/bpmn/decompile.js +1108 -0
- package/dist/bpmn/format-profile.d.ts +27 -0
- package/dist/bpmn/format-profile.js +11 -0
- package/dist/bpmn/intsvc.d.ts +77 -0
- package/dist/bpmn/intsvc.js +155 -0
- package/dist/bpmn/load.d.ts +4 -0
- package/dist/bpmn/load.js +22 -0
- package/dist/bpmn/merge-cli.d.ts +3 -0
- package/dist/bpmn/merge-cli.js +45 -0
- package/dist/bpmn/merge.d.ts +19 -0
- package/dist/bpmn/merge.js +293 -0
- package/dist/bpmn/registry-types.json +1869 -0
- package/dist/bpmn/serialize.d.ts +28 -0
- package/dist/bpmn/serialize.js +757 -0
- package/dist/bpmn/tidy-cli.d.ts +2 -0
- package/dist/bpmn/tidy-cli.js +39 -0
- package/dist/bpmn/typed-node.d.ts +382 -0
- package/dist/bpmn/typed-node.js +551 -0
- package/dist/bpmn/uipath-moddle.v1.json +823 -0
- package/dist/bpmn/xml-ranges.d.ts +45 -0
- package/dist/bpmn/xml-ranges.js +151 -0
- package/dist/case/case-expr-check.d.ts +35 -0
- package/dist/case/case-expr-check.js +85 -0
- package/dist/case/case-sdk.d.ts +1282 -0
- package/dist/case/case-sdk.js +923 -0
- package/dist/case/check-cli.d.ts +3 -0
- package/dist/case/check-cli.js +31 -0
- package/dist/case/check.d.ts +18 -0
- package/dist/case/check.js +456 -0
- package/dist/case/compile-cli.d.ts +3 -0
- package/dist/case/compile-cli.js +291 -0
- package/dist/case/decompile-cli.d.ts +9 -0
- package/dist/case/decompile-cli.js +117 -0
- package/dist/case/decompile.d.ts +187 -0
- package/dist/case/decompile.js +1170 -0
- package/dist/case/entry-points.d.ts +79 -0
- package/dist/case/entry-points.js +118 -0
- package/dist/case/format-profile.d.ts +60 -0
- package/dist/case/format-profile.js +79 -0
- package/dist/case/ids.d.ts +24 -0
- package/dist/case/ids.js +76 -0
- package/dist/case/load.d.ts +12 -0
- package/dist/case/load.js +32 -0
- package/dist/case/preserve.d.ts +133 -0
- package/dist/case/preserve.js +105 -0
- package/dist/case/serialize.d.ts +10 -0
- package/dist/case/serialize.js +1414 -0
- package/dist/check-cli.d.ts +3 -0
- package/dist/check-cli.js +118 -0
- package/dist/check.d.ts +146 -0
- package/dist/check.js +4898 -0
- package/dist/cli/commands/bpmn.d.ts +2 -0
- package/dist/cli/commands/bpmn.js +73 -0
- package/dist/cli/commands/case.d.ts +2 -0
- package/dist/cli/commands/case.js +60 -0
- package/dist/cli/commands/flow.d.ts +2 -0
- package/dist/cli/commands/flow.js +99 -0
- package/dist/cli/commands/registry.d.ts +10 -0
- package/dist/cli/commands/registry.js +170 -0
- package/dist/cli/common.d.ts +30 -0
- package/dist/cli/common.js +92 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli-run.d.ts +2 -0
- package/dist/cli-run.js +42 -0
- package/dist/compile-cli.d.ts +3 -0
- package/dist/compile-cli.js +160 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.js +201 -0
- package/dist/core/actions.d.ts +3244 -0
- package/dist/core/actions.js +1062 -0
- package/dist/core/binding-messages.d.ts +1 -0
- package/dist/core/binding-messages.js +16 -0
- package/dist/core/bindings.d.ts +12 -0
- package/dist/core/bindings.js +67 -0
- package/dist/core/ceql.d.ts +73 -0
- package/dist/core/ceql.js +272 -0
- package/dist/core/cli-spelling.d.ts +39 -0
- package/dist/core/cli-spelling.js +62 -0
- package/dist/core/connector-raw-node.d.ts +21 -0
- package/dist/core/connector-raw-node.js +47 -0
- package/dist/core/connectors.d.ts +184 -0
- package/dist/core/connectors.js +128 -0
- package/dist/core/expr-check.d.ts +93 -0
- package/dist/core/expr-check.js +186 -0
- package/dist/core/expr.d.ts +323 -0
- package/dist/core/expr.js +400 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.js +10 -0
- package/dist/core/library.d.ts +440 -0
- package/dist/core/library.js +1183 -0
- package/dist/core/list-envelope.d.ts +45 -0
- package/dist/core/list-envelope.js +97 -0
- package/dist/core/lookup-store.d.ts +22 -0
- package/dist/core/lookup-store.js +85 -0
- package/dist/core/lookups.d.ts +227 -0
- package/dist/core/lookups.js +231 -0
- package/dist/core/node-classes.d.ts +234 -0
- package/dist/core/node-classes.js +158 -0
- package/dist/core/script-return.d.ts +68 -0
- package/dist/core/script-return.js +197 -0
- package/dist/core/stable-id.d.ts +28 -0
- package/dist/core/stable-id.js +37 -0
- package/dist/core-definitions.json +16249 -0
- package/dist/decompile-cli.d.ts +3 -0
- package/dist/decompile-cli.js +131 -0
- package/dist/decompile.d.ts +138 -0
- package/dist/decompile.js +2482 -0
- package/dist/emit.d.ts +10 -0
- package/dist/emit.js +60 -0
- package/dist/event-filters.d.ts +130 -0
- package/dist/event-filters.js +137 -0
- package/dist/flow-expr-check.d.ts +17 -0
- package/dist/flow-expr-check.js +193 -0
- package/dist/flow-sdk.d.ts +1341 -0
- package/dist/flow-sdk.js +1164 -0
- package/dist/flow-variables.d.ts +13 -0
- package/dist/flow-variables.js +42 -0
- package/dist/format-profile.d.ts +72 -0
- package/dist/format-profile.js +97 -0
- package/dist/generators/_connections.py +287 -0
- package/dist/generators/_events.py +355 -0
- package/dist/generators/_lookups.py +114 -0
- package/dist/generators/_naming.py +185 -0
- package/dist/generators/_objects.py +299 -0
- package/dist/generators/_resolve.py +273 -0
- package/dist/generators/convert_library_to_md.py +1441 -0
- package/dist/generators/extract_library.py +125 -0
- package/dist/generators/generate_connectors_ts.py +936 -0
- package/dist/generators/generate_library_json.py +2527 -0
- package/dist/generators/generate_triggers_ts.py +110 -0
- package/dist/generators/materialize_registry.py +155 -0
- package/dist/generators/prepare_connector.py +1688 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +35 -0
- package/dist/ixp-definition.json +1982 -0
- package/dist/library.d.ts +6 -0
- package/dist/library.js +6 -0
- package/dist/load.d.ts +16 -0
- package/dist/load.js +95 -0
- package/dist/merge-cli.d.ts +3 -0
- package/dist/merge-cli.js +47 -0
- package/dist/merge.d.ts +125 -0
- package/dist/merge.js +0 -0
- package/dist/migrate.d.ts +15 -0
- package/dist/migrate.js +245 -0
- package/dist/node-runtime.d.ts +3 -0
- package/dist/node-runtime.js +22 -0
- package/dist/package-name.d.ts +17 -0
- package/dist/package-name.js +17 -0
- package/dist/ref-resolve.d.ts +77 -0
- package/dist/ref-resolve.js +170 -0
- package/dist/registry/cache.d.ts +55 -0
- package/dist/registry/cache.js +134 -0
- package/dist/registry/curated-overlay.d.ts +16 -0
- package/dist/registry/curated-overlay.js +62 -0
- package/dist/registry/extractor.d.ts +22 -0
- package/dist/registry/extractor.js +18 -0
- package/dist/registry/materialize-bin.d.ts +2 -0
- package/dist/registry/materialize-bin.js +7 -0
- package/dist/registry/materialize-cli.d.ts +1 -0
- package/dist/registry/materialize-cli.js +46 -0
- package/dist/registry/materializer.d.ts +23 -0
- package/dist/registry/materializer.js +34 -0
- package/dist/registry/path-cli.d.ts +1 -0
- package/dist/registry/path-cli.js +56 -0
- package/dist/registry/prepare-cli.d.ts +62 -0
- package/dist/registry/prepare-cli.js +185 -0
- package/dist/registry/pull-cli.d.ts +1 -0
- package/dist/registry/pull-cli.js +274 -0
- package/dist/registry/python.d.ts +26 -0
- package/dist/registry/python.js +46 -0
- package/dist/registry/search-cli.d.ts +52 -0
- package/dist/registry/search-cli.js +159 -0
- package/dist/schema-version.d.ts +165 -0
- package/dist/schema-version.js +148 -0
- package/dist/serialize.d.ts +64 -0
- package/dist/serialize.js +6398 -0
- package/lib/README.md +112 -0
- package/lib/library-json.samples/index.json +158 -0
- package/lib/library-json.samples/invariant-collections.json +83 -0
- package/lib/library-json.samples/list-envelopes.json +123 -0
- package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.json +131 -0
- package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.v1def.json +306 -0
- package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.json +86 -0
- package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.v1def.json +208 -0
- package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.json +2040 -0
- package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.v1def.json +195 -0
- package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.json +169 -0
- package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.v1def.json +209 -0
- package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.json +63 -0
- package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.v1def.json +262 -0
- package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.json +63 -0
- package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.v1def.json +213 -0
- package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.json +227 -0
- package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.v1def.json +373 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.json +116 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.v1def.json +369 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.json +56 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.v1def.json +256 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.json +116 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.v1def.json +320 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.json +56 -0
- package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.v1def.json +207 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.json +107 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.v1def.json +264 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.json +142 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.v1def.json +306 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.json +107 -0
- package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.v1def.json +217 -0
- package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.json +85 -0
- package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.v1def.json +209 -0
- package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.json +755 -0
- package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.v1def.json +513 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.json +122 -0
- package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.v1def.json +227 -0
- package/package.json +85 -0
|
@@ -0,0 +1,1476 @@
|
|
|
1
|
+
import { connector as makeConnector } from '../core/actions.js';
|
|
2
|
+
import { checkBpmnExpressions, BpmnBuildError } from './bpmn-expr-check.js';
|
|
3
|
+
import { BPMN_SCHEMA_VERSIONS } from './format-profile.js';
|
|
4
|
+
import { schemaVersionRefusal } from '../schema-version.js';
|
|
5
|
+
import { bindingRequiredFields, REGISTRY_GAPS, typedNodeOutputVar } from './typed-node.js';
|
|
6
|
+
export { BpmnBuildError } from './bpmn-expr-check.js';
|
|
7
|
+
function normTimer(t) {
|
|
8
|
+
return typeof t === 'string' ? { duration: t } : t;
|
|
9
|
+
}
|
|
10
|
+
// ─── Definitions registry (shared across the top process + sub-processes) ─────
|
|
11
|
+
/**
|
|
12
|
+
* Collects `uipath:binding` declarations, de-duped by id.
|
|
13
|
+
*
|
|
14
|
+
* Shared with every scope rather than living on the top-level builder, because a
|
|
15
|
+
* typed node can NEED a binding — `Orchestrator.StartAgentJob` requires its
|
|
16
|
+
* process and folder to be `=bindings.<id>` references — and such a node can be
|
|
17
|
+
* authored inside a sub-process. Same reasoning as {@link DefinitionsRegistry}.
|
|
18
|
+
*/
|
|
19
|
+
class BindingsRegistry {
|
|
20
|
+
/** Every declared binding, in declaration order — `BuiltBpmn.bindings`. */
|
|
21
|
+
bindings = [];
|
|
22
|
+
/**
|
|
23
|
+
* Declare once and keep the FIRST declaration, so an author's own `.binding()`
|
|
24
|
+
* wins over one a typed node would have derived.
|
|
25
|
+
*
|
|
26
|
+
* @param decl - The binding to declare.
|
|
27
|
+
* @returns The declaration in force for that id — the existing one on a collision.
|
|
28
|
+
*/
|
|
29
|
+
declare(decl) {
|
|
30
|
+
const existing = this.bindings.find((b) => b.id === decl.id);
|
|
31
|
+
if (existing)
|
|
32
|
+
return existing;
|
|
33
|
+
this.bindings.push(decl);
|
|
34
|
+
return decl;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @param id - The binding id to look for.
|
|
38
|
+
* @returns Whether that id is already declared.
|
|
39
|
+
*/
|
|
40
|
+
has(id) {
|
|
41
|
+
return this.bindings.some((b) => b.id === id);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Collects definitions-level message/error declarations, de-duped by name. */
|
|
45
|
+
class DefinitionsRegistry {
|
|
46
|
+
/** Every declared message, in declaration order — `BuiltBpmn.messages`. */
|
|
47
|
+
messages = [];
|
|
48
|
+
/** Every declared error, in declaration order — `BuiltBpmn.errors`. */
|
|
49
|
+
errors = [];
|
|
50
|
+
messageByName = new Map();
|
|
51
|
+
errorByName = new Map();
|
|
52
|
+
/**
|
|
53
|
+
* Declare a message once and reuse it, returning the id events reference.
|
|
54
|
+
*
|
|
55
|
+
* @param name - The message's name.
|
|
56
|
+
* @returns The message id to put in an event's definition.
|
|
57
|
+
*/
|
|
58
|
+
messageRef(name) {
|
|
59
|
+
const existing = this.messageByName.get(name);
|
|
60
|
+
if (existing)
|
|
61
|
+
return existing;
|
|
62
|
+
const id = uniqueId('Message', this.messageByName.size);
|
|
63
|
+
this.messageByName.set(name, id);
|
|
64
|
+
this.messages.push({ id, name });
|
|
65
|
+
return id;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Declare an error once and reuse it, returning the id events reference.
|
|
69
|
+
*
|
|
70
|
+
* @param name - The error's name.
|
|
71
|
+
* @param code - The error code the runtime matches on.
|
|
72
|
+
* @returns The error id to put in an event's definition.
|
|
73
|
+
*/
|
|
74
|
+
errorRef(name, code) {
|
|
75
|
+
const existing = this.errorByName.get(name);
|
|
76
|
+
if (existing)
|
|
77
|
+
return existing;
|
|
78
|
+
const id = uniqueId('Error', this.errorByName.size);
|
|
79
|
+
this.errorByName.set(name, id);
|
|
80
|
+
this.errors.push({ id, name, code });
|
|
81
|
+
return id;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function uniqueId(prefix, index) {
|
|
85
|
+
return `${prefix}_${index + 1}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolve an end/boundary error option into an error definition.
|
|
89
|
+
*
|
|
90
|
+
* **The code defaults to the name**, and must: the code is what the runtime
|
|
91
|
+
* matches a failure against, and `uip maestro bpmn validate` rejects an error
|
|
92
|
+
* boundary whose referenced error has none (`ERROR_BOUNDARY_EVENT_REQUIRES_ERROR_CODE`).
|
|
93
|
+
* Omitting it emitted `<bpmn:error name="Boom"/>` with no code, which failed
|
|
94
|
+
* validation and — because the runtime then falls back to the SYNTHESIZED
|
|
95
|
+
* element id (`Error_1`) — could never match a real failure, so the handler was
|
|
96
|
+
* unreachable. Passing `{ name, code }` still sets them independently.
|
|
97
|
+
*/
|
|
98
|
+
function toErrorDef(defs, error) {
|
|
99
|
+
// `true` is catch-any: no `bpmn:error` is declared and no `errorRef` is written.
|
|
100
|
+
if (error === true)
|
|
101
|
+
return { type: 'error' };
|
|
102
|
+
const spec = typeof error === 'string' ? { name: error } : error;
|
|
103
|
+
return { type: 'error', errorRef: defs.errorRef(spec.name, spec.code ?? spec.name) };
|
|
104
|
+
}
|
|
105
|
+
// ─── Graph scope (shared by the top process and sub-processes) ────────────────
|
|
106
|
+
/**
|
|
107
|
+
* The set of node/flow/variable methods common to the process root and every
|
|
108
|
+
* sub-process. Methods return `this`, so fluent chaining preserves the concrete
|
|
109
|
+
* builder type (top-level or sub-process).
|
|
110
|
+
*/
|
|
111
|
+
class ScopeBuilder {
|
|
112
|
+
/** @internal */
|
|
113
|
+
_nodes = [];
|
|
114
|
+
/** @internal */
|
|
115
|
+
_flows = [];
|
|
116
|
+
/** @internal */
|
|
117
|
+
_vars = [];
|
|
118
|
+
// An explicit field, not a constructor parameter property: an inline comment
|
|
119
|
+
// on a parameter property never reaches the emitted `.d.ts` property, so the
|
|
120
|
+
// `@internal` tag would be lost there.
|
|
121
|
+
/** @internal */
|
|
122
|
+
_defs;
|
|
123
|
+
/** @internal */
|
|
124
|
+
_bindingRegistry;
|
|
125
|
+
/**
|
|
126
|
+
* @param defs - Definitions-level message/error declarations, shared with every scope.
|
|
127
|
+
* @param bindings - `uipath:binding` declarations, shared so a typed node can
|
|
128
|
+
* declare one from inside a sub-process.
|
|
129
|
+
* @returns The scope builder.
|
|
130
|
+
*/
|
|
131
|
+
constructor(defs, bindings) {
|
|
132
|
+
this._defs = defs;
|
|
133
|
+
this._bindingRegistry = bindings;
|
|
134
|
+
}
|
|
135
|
+
push(node) {
|
|
136
|
+
this._nodes.push(node);
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
// ── Events ──
|
|
140
|
+
/**
|
|
141
|
+
* A start event (authorable definitions: none / message / timer).
|
|
142
|
+
*
|
|
143
|
+
* @remarks
|
|
144
|
+
* With no definition at all, the process is started by a CALLER — an API call,
|
|
145
|
+
* `uip maestro`, a parent process, or an Orchestrator trigger configured against
|
|
146
|
+
* the deployed process. `timer` moves the schedule INTO the artifact, where the
|
|
147
|
+
* platform's scheduler reads it. `trigger` additionally declares the timed start
|
|
148
|
+
* as a typed platform trigger — see {@link StartOpts.trigger}.
|
|
149
|
+
*
|
|
150
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
151
|
+
* @param opts - `name`, the definition — message or timer — and `trigger`.
|
|
152
|
+
* @returns This builder, so calls chain.
|
|
153
|
+
* @throws If `trigger` is set without `timer`, which would emit a trigger with no
|
|
154
|
+
* schedule that every offline gate still calls valid.
|
|
155
|
+
*/
|
|
156
|
+
startEvent(id, opts = {}) {
|
|
157
|
+
if (opts.trigger !== undefined && opts.timer === undefined) {
|
|
158
|
+
throw new Error(`startEvent "${id}": \`trigger\` needs \`timer\` — the schedule lives in the ` +
|
|
159
|
+
`bpmn:timerEventDefinition, not in the trigger extension, so a trigger without one emits an ` +
|
|
160
|
+
`empty definition and fires never. \`uip maestro bpmn validate\` reports that as Valid.`);
|
|
161
|
+
}
|
|
162
|
+
if (opts.trigger !== undefined && opts.payload !== undefined) {
|
|
163
|
+
throw new Error(`startEvent "${id}": \`trigger\` and \`payload\` both write the event's extension element; pass one.`);
|
|
164
|
+
}
|
|
165
|
+
return this.push({
|
|
166
|
+
kind: 'startEvent',
|
|
167
|
+
id,
|
|
168
|
+
name: opts.name,
|
|
169
|
+
payload: opts.payload,
|
|
170
|
+
// `error` is handled here rather than in `startCatchDef` because it needs the
|
|
171
|
+
// definitions registry to intern the `bpmn:error`, exactly as `endEvent` does —
|
|
172
|
+
// and because an intermediate catch event (the other `startCatchDef` caller)
|
|
173
|
+
// cannot carry one: BPMN catches errors at a boundary or an event sub-process
|
|
174
|
+
// start, never mid-flow.
|
|
175
|
+
event: opts.error !== undefined ? toErrorDef(this._defs, opts.error) : this.startCatchDef(opts),
|
|
176
|
+
trigger: opts.trigger === undefined
|
|
177
|
+
? undefined
|
|
178
|
+
: { type: 'Intsvc.TimerTrigger', outputVar: opts.trigger === true ? undefined : opts.trigger.outputVar },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* An end event (authorable definitions: none / message / error / terminate).
|
|
183
|
+
*
|
|
184
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
185
|
+
* @param opts - `name`, and the definition — message, error, or terminate.
|
|
186
|
+
* @returns This builder, so calls chain.
|
|
187
|
+
*/
|
|
188
|
+
endEvent(id, opts = {}) {
|
|
189
|
+
let event;
|
|
190
|
+
if (opts.terminate)
|
|
191
|
+
event = { type: 'terminate' };
|
|
192
|
+
else if (opts.error !== undefined)
|
|
193
|
+
event = toErrorDef(this._defs, opts.error);
|
|
194
|
+
else if (opts.message !== undefined)
|
|
195
|
+
event = { type: 'message', messageRef: this._defs.messageRef(opts.message) };
|
|
196
|
+
return this.push({ kind: 'endEvent', id, name: opts.name, event, payload: opts.payload });
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* An intermediate catch event (authorable: message / timer).
|
|
200
|
+
*
|
|
201
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
202
|
+
* @param opts - `name`, and the definition — message or timer.
|
|
203
|
+
* @returns This builder, so calls chain.
|
|
204
|
+
*/
|
|
205
|
+
intermediateCatchEvent(id, opts = {}) {
|
|
206
|
+
return this.push({
|
|
207
|
+
kind: 'intermediateCatchEvent',
|
|
208
|
+
id,
|
|
209
|
+
name: opts.name,
|
|
210
|
+
event: this.startCatchDef(opts),
|
|
211
|
+
payload: opts.payload,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* An intermediate throw event (authorable: none / message).
|
|
216
|
+
*
|
|
217
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
218
|
+
* @param opts - `name`, and the definition — none or message.
|
|
219
|
+
* @returns This builder, so calls chain.
|
|
220
|
+
*/
|
|
221
|
+
intermediateThrowEvent(id, opts = {}) {
|
|
222
|
+
const event = opts.message !== undefined ? { type: 'message', messageRef: this._defs.messageRef(opts.message) } : undefined;
|
|
223
|
+
return this.push({ kind: 'intermediateThrowEvent', id, name: opts.name, event, payload: opts.payload });
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* A boundary event on an activity (authorable: message / timer / error).
|
|
227
|
+
*
|
|
228
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
229
|
+
* @param opts - The activity it attaches to, whether it interrupts, and the definition — message, timer, or error.
|
|
230
|
+
* @returns This builder, so calls chain.
|
|
231
|
+
*/
|
|
232
|
+
boundaryEvent(id, opts) {
|
|
233
|
+
let event;
|
|
234
|
+
if (opts.error !== undefined)
|
|
235
|
+
event = toErrorDef(this._defs, opts.error);
|
|
236
|
+
else if (opts.timer !== undefined)
|
|
237
|
+
event = { type: 'timer', timer: normTimer(opts.timer) };
|
|
238
|
+
else if (opts.message !== undefined)
|
|
239
|
+
event = { type: 'message', messageRef: this._defs.messageRef(opts.message) };
|
|
240
|
+
else
|
|
241
|
+
throw new Error(`boundaryEvent "${id}" needs one of { message, timer, error }.`);
|
|
242
|
+
return this.push({
|
|
243
|
+
kind: 'boundaryEvent',
|
|
244
|
+
id,
|
|
245
|
+
name: opts.name,
|
|
246
|
+
attachedTo: opts.attachedTo,
|
|
247
|
+
cancelActivity: opts.cancelActivity ?? true,
|
|
248
|
+
event,
|
|
249
|
+
payload: opts.payload,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
startCatchDef(opts) {
|
|
253
|
+
if (opts.timer !== undefined)
|
|
254
|
+
return { type: 'timer', timer: normTimer(opts.timer) };
|
|
255
|
+
if (opts.message !== undefined)
|
|
256
|
+
return { type: 'message', messageRef: this._defs.messageRef(opts.message) };
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
// ── Gateways ──
|
|
260
|
+
/**
|
|
261
|
+
* An exclusive gateway — exactly one outgoing flow is taken (`bpmn:exclusiveGateway`).
|
|
262
|
+
*
|
|
263
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
264
|
+
* @param opts - `name`, and the `default` flow taken when no condition matches.
|
|
265
|
+
* @returns This builder, so calls chain.
|
|
266
|
+
*/
|
|
267
|
+
exclusiveGateway(id, opts = {}) {
|
|
268
|
+
return this.push({ kind: 'exclusiveGateway', id, name: opts.name, default: opts.default });
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* A parallel gateway — every outgoing flow is taken, and a join waits for every incoming one (`bpmn:parallelGateway`).
|
|
272
|
+
*
|
|
273
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
274
|
+
* @param opts - `name` for the gateway.
|
|
275
|
+
* @returns This builder, so calls chain.
|
|
276
|
+
*/
|
|
277
|
+
parallelGateway(id, opts = {}) {
|
|
278
|
+
return this.push({ kind: 'parallelGateway', id, name: opts.name });
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* An inclusive gateway — every outgoing flow whose condition holds is taken (`bpmn:inclusiveGateway`).
|
|
282
|
+
*
|
|
283
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
284
|
+
* @param opts - `name`, and the `default` flow taken when no condition matches.
|
|
285
|
+
* @returns This builder, so calls chain.
|
|
286
|
+
*/
|
|
287
|
+
inclusiveGateway(id, opts = {}) {
|
|
288
|
+
return this.push({ kind: 'inclusiveGateway', id, name: opts.name, default: opts.default });
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* An event-based gateway — the first of the events it leads to wins, and the rest are cancelled (`bpmn:eventBasedGateway`).
|
|
292
|
+
*
|
|
293
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
294
|
+
* @param opts - `name` for the gateway.
|
|
295
|
+
* @returns This builder, so calls chain.
|
|
296
|
+
*/
|
|
297
|
+
eventBasedGateway(id, opts = {}) {
|
|
298
|
+
return this.push({ kind: 'eventBasedGateway', id, name: opts.name });
|
|
299
|
+
}
|
|
300
|
+
// ── Tasks ──
|
|
301
|
+
/**
|
|
302
|
+
* A script task (Jint JavaScript body + input/output mappings).
|
|
303
|
+
*
|
|
304
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
305
|
+
* @param opts - The Jint JavaScript `script`, and its input/output mappings.
|
|
306
|
+
* @returns This builder, so calls chain.
|
|
307
|
+
*/
|
|
308
|
+
scriptTask(id, opts) {
|
|
309
|
+
return this.push({
|
|
310
|
+
kind: 'scriptTask',
|
|
311
|
+
id,
|
|
312
|
+
name: opts.name,
|
|
313
|
+
script: opts.script,
|
|
314
|
+
scriptFormat: opts.scriptFormat ?? 'JavaScript',
|
|
315
|
+
inputs: opts.inputs ?? {},
|
|
316
|
+
outputs: opts.outputs ?? {},
|
|
317
|
+
outputRows: opts.outputRows,
|
|
318
|
+
type: opts.type ?? 'BPMN.Variables',
|
|
319
|
+
inputSchema: opts.inputSchema,
|
|
320
|
+
tags: opts.tags,
|
|
321
|
+
retry: opts.retry,
|
|
322
|
+
errorMapping: opts.errorMapping,
|
|
323
|
+
loop: opts.loop,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* A plain task that assigns variables (`BPMN.Variables`).
|
|
328
|
+
*
|
|
329
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
330
|
+
* @param opts - `name`, and the variable assignments the task makes.
|
|
331
|
+
* @returns This builder, so calls chain.
|
|
332
|
+
*/
|
|
333
|
+
task(id, opts = {}) {
|
|
334
|
+
return this.push({
|
|
335
|
+
kind: 'task',
|
|
336
|
+
id,
|
|
337
|
+
name: opts.name,
|
|
338
|
+
set: opts.set ?? {},
|
|
339
|
+
tags: opts.tags,
|
|
340
|
+
retry: opts.retry,
|
|
341
|
+
loop: opts.loop,
|
|
342
|
+
errorMapping: opts.errorMapping,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* A task element carrying NO `uipath:*` payload — an abstract task, in BPMN's terms.
|
|
347
|
+
*
|
|
348
|
+
* @remarks
|
|
349
|
+
* The platform accepts all seven task elements bare, so an artifact can legitimately
|
|
350
|
+
* contain one, and until this existed the builder could not express any of them. That
|
|
351
|
+
* made such a file unimportable: `bpmn-decompile` refused six of the seven outright,
|
|
352
|
+
* and the seventh — `bpmn:task` — was worse, because it came back through `.task()`
|
|
353
|
+
* and silently GAINED a `BPMN.Variables` mapping it never had.
|
|
354
|
+
*
|
|
355
|
+
* Not the same as {@link ScopeBuilder.task}, which emits a `BPMN.Variables` mapping to
|
|
356
|
+
* assign variables, or {@link ScopeBuilder.humanTask}, which emits an `Actions.HITL`
|
|
357
|
+
* activity. Those are tasks that DO something; this is a task element that stands for
|
|
358
|
+
* work the process does not model — the shape a diagram-first tool writes before
|
|
359
|
+
* anything is wired up.
|
|
360
|
+
*
|
|
361
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
362
|
+
* @param opts - `name`, and which task `element` to emit (default `bpmn:task`).
|
|
363
|
+
* @returns This builder, so calls chain.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```ts
|
|
367
|
+
* bpmn('review')
|
|
368
|
+
* .startEvent('s')
|
|
369
|
+
* .plainTask('approve', { name: 'Approve', element: 'bpmn:userTask' })
|
|
370
|
+
* .endEvent('e')
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
plainTask(id, opts = {}) {
|
|
374
|
+
return this.push({
|
|
375
|
+
kind: 'plainTask',
|
|
376
|
+
id,
|
|
377
|
+
name: opts.name,
|
|
378
|
+
element: opts.element ?? 'bpmn:task',
|
|
379
|
+
tags: opts.tags,
|
|
380
|
+
retry: opts.retry,
|
|
381
|
+
errorMapping: opts.errorMapping,
|
|
382
|
+
loop: opts.loop,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
connector(id, a, b, c, d) {
|
|
386
|
+
// Reuse the shared connector() overload to parse descriptor-or-string into a
|
|
387
|
+
// ConnectorSpec; then carry its fields onto the BPMN node.
|
|
388
|
+
const spec = typeof a === 'string'
|
|
389
|
+
? makeConnector(a, b, c, d)
|
|
390
|
+
: makeConnector(a, b, c);
|
|
391
|
+
if (spec.kind !== 'connector')
|
|
392
|
+
throw new Error('connector(): unexpected spec kind');
|
|
393
|
+
const bpmnOpts = (typeof a === 'string' ? d : c) ?? {};
|
|
394
|
+
return this.push({
|
|
395
|
+
kind: 'connector',
|
|
396
|
+
id,
|
|
397
|
+
name: bpmnOpts.name,
|
|
398
|
+
key: spec.key,
|
|
399
|
+
action: spec.action,
|
|
400
|
+
version: spec.version,
|
|
401
|
+
connection: spec.connection,
|
|
402
|
+
folder: spec.folder,
|
|
403
|
+
object: spec.object,
|
|
404
|
+
inputs: spec.inputs,
|
|
405
|
+
outputVar: bpmnOpts.outputVar,
|
|
406
|
+
skipCondition: bpmnOpts.skipCondition,
|
|
407
|
+
retry: bpmnOpts.retry,
|
|
408
|
+
loop: bpmnOpts.loop,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* An **HTTP request** service task (`bpmn:sendTask` +
|
|
413
|
+
* `uipath:activity` / `Intsvc.UnifiedHttpRequest`).
|
|
414
|
+
*
|
|
415
|
+
* @remarks
|
|
416
|
+
* The first registry-backed typed node (`docs/BPMN_COVERAGE_DESIGN.md` Phase 3).
|
|
417
|
+
* Its wire shape — element, tag, context fields, output row — comes from the
|
|
418
|
+
* committed registry snapshot rather than hand-written emission, so it cannot
|
|
419
|
+
* drift from what the platform validates. Chosen as the pilot because it needs
|
|
420
|
+
* no tenant discovery (`RequiresDiscovery: No`) and the local engine dispatches
|
|
421
|
+
* it for real in `--mode live`.
|
|
422
|
+
*
|
|
423
|
+
* The response lands in `<id>_response` unless `outputVar` says otherwise, and
|
|
424
|
+
* that variable is readable downstream as `=vars.<name>` with no `.var()`.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* bpmn('sync')
|
|
429
|
+
* .var('body', 'object')
|
|
430
|
+
* .startEvent('start')
|
|
431
|
+
* .http('fetch', { method: 'GET', url: 'https://api.example.com/orders' })
|
|
432
|
+
* .task('keep', { set: { body: '=js:vars.fetch_response' } })
|
|
433
|
+
* .endEvent('done')
|
|
434
|
+
* .sequenceFlow('start', 'fetch')
|
|
435
|
+
* .sequenceFlow('fetch', 'keep')
|
|
436
|
+
* .sequenceFlow('keep', 'done')
|
|
437
|
+
* .build();
|
|
438
|
+
* ```
|
|
439
|
+
*
|
|
440
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
441
|
+
* @param opts - The request, plus `name`, `outputVar`, and the shared activity options.
|
|
442
|
+
* @returns This builder, so calls chain.
|
|
443
|
+
*/
|
|
444
|
+
http(id, opts) {
|
|
445
|
+
const { name, url, method, headers, parameters, body, outputs, outputVar, skipCondition, retry, loop, errorMapping } = opts;
|
|
446
|
+
return this.push({
|
|
447
|
+
kind: 'typed',
|
|
448
|
+
id,
|
|
449
|
+
name,
|
|
450
|
+
type: 'Intsvc.UnifiedHttpRequest',
|
|
451
|
+
// These three are `json` context fields, so they go through as VALUES — the
|
|
452
|
+
// emitter encodes a json field's body. This wrapper used to `JSON.stringify`
|
|
453
|
+
// them itself, working around an emitter that wrote `[object Object]` for
|
|
454
|
+
// anything but a string; now the generic `.activity()` path accepts the same
|
|
455
|
+
// values this one does.
|
|
456
|
+
context: {
|
|
457
|
+
method: method ?? 'GET',
|
|
458
|
+
url,
|
|
459
|
+
...(headers !== undefined ? { headers } : {}),
|
|
460
|
+
...(parameters !== undefined ? { parameters } : {}),
|
|
461
|
+
...(body !== undefined ? { body } : {}),
|
|
462
|
+
},
|
|
463
|
+
inputs: {},
|
|
464
|
+
outputs,
|
|
465
|
+
outputVar,
|
|
466
|
+
skipCondition,
|
|
467
|
+
retry,
|
|
468
|
+
loop,
|
|
469
|
+
errorMapping,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* @internal Turn a literal into a binding reference where the platform demands
|
|
474
|
+
* one, declaring the binding on the author's behalf.
|
|
475
|
+
*
|
|
476
|
+
* `Orchestrator.StartAgentJob` requires its `name` and `folderPath` to be
|
|
477
|
+
* `=bindings.<id>` references AND requires those bindings to target
|
|
478
|
+
* `resource: process` with the right `propertyAttribute` — a literal is rejected,
|
|
479
|
+
* and so is a binding pointing at the wrong property. Both facts are in the
|
|
480
|
+
* registry snapshot, so the SDK can satisfy them from the plain value the author
|
|
481
|
+
* wrote instead of making them hand-build two bindings and get the attributes
|
|
482
|
+
* right. An author who passes an `=`-expression already knows what they want and
|
|
483
|
+
* is left alone.
|
|
484
|
+
*/
|
|
485
|
+
bindRequiredContext(id, type, context) {
|
|
486
|
+
const out = { ...context };
|
|
487
|
+
for (const field of bindingRequiredFields(type)) {
|
|
488
|
+
const value = out[field.name];
|
|
489
|
+
if (typeof value !== 'string' || value.startsWith('='))
|
|
490
|
+
continue;
|
|
491
|
+
const bindingId = `${id}_${field.name}`;
|
|
492
|
+
this._bindingRegistry.declare({
|
|
493
|
+
id: bindingId,
|
|
494
|
+
name: field.displayName ?? field.name,
|
|
495
|
+
resource: field.bindingInfo?.resource ?? 'process',
|
|
496
|
+
propertyAttribute: field.bindingInfo?.propertyAttribute ?? field.name,
|
|
497
|
+
// A fact the registry omits and the validator enforces — see REGISTRY_GAPS.
|
|
498
|
+
resourceSubType: REGISTRY_GAPS[type]?.resourceSubType,
|
|
499
|
+
default: value,
|
|
500
|
+
resourceKey: value,
|
|
501
|
+
});
|
|
502
|
+
out[field.name] = `=bindings.${bindingId}`;
|
|
503
|
+
}
|
|
504
|
+
return out;
|
|
505
|
+
}
|
|
506
|
+
/** @internal Shared body of the Orchestrator process-invocation methods. */
|
|
507
|
+
orchestratorNode(id, type, opts) {
|
|
508
|
+
return this.push({
|
|
509
|
+
kind: 'typed',
|
|
510
|
+
id,
|
|
511
|
+
name: opts.name,
|
|
512
|
+
type,
|
|
513
|
+
context: this.bindRequiredContext(id, type, {
|
|
514
|
+
name: opts.process,
|
|
515
|
+
...(opts.folder !== undefined ? { folderPath: opts.folder } : {}),
|
|
516
|
+
...(opts.releaseKey !== undefined ? { releaseKey: opts.releaseKey } : {}),
|
|
517
|
+
}),
|
|
518
|
+
inputs: opts.input ?? {},
|
|
519
|
+
outputs: opts.outputs,
|
|
520
|
+
outputVar: opts.outputVar,
|
|
521
|
+
skipCondition: opts.skipCondition,
|
|
522
|
+
tags: opts.tags,
|
|
523
|
+
retry: opts.retry,
|
|
524
|
+
errorMapping: opts.errorMapping,
|
|
525
|
+
loop: opts.loop,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Start an **RPA process** and wait for it (`Orchestrator.StartJob`).
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* ```ts
|
|
533
|
+
* bpmn('nightly')
|
|
534
|
+
* .startEvent('start')
|
|
535
|
+
* .startProcess('rpa', { process: 'InvoicePosting', folder: 'Finance', input: { batch: 42 } })
|
|
536
|
+
* .endEvent('done')
|
|
537
|
+
* .sequenceFlow('start', 'rpa')
|
|
538
|
+
* .sequenceFlow('rpa', 'done')
|
|
539
|
+
* .build();
|
|
540
|
+
* ```
|
|
541
|
+
*
|
|
542
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
543
|
+
* @param opts - Which process, folder, and input arguments.
|
|
544
|
+
* @returns This builder, so calls chain.
|
|
545
|
+
*/
|
|
546
|
+
startProcess(id, opts) {
|
|
547
|
+
return this.orchestratorNode(id, 'Orchestrator.StartJob', opts);
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Start an **agent** and wait for it (`Orchestrator.StartAgentJob`).
|
|
551
|
+
*
|
|
552
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
553
|
+
* @param opts - Which agent process, folder, and input arguments.
|
|
554
|
+
* @returns This builder, so calls chain.
|
|
555
|
+
*/
|
|
556
|
+
startAgent(id, opts) {
|
|
557
|
+
return this.orchestratorNode(id, 'Orchestrator.StartAgentJob', opts);
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Invoke an **agentic process** as a call activity
|
|
561
|
+
* (`Orchestrator.StartAgenticProcess`, or `…Async` when `async` is set).
|
|
562
|
+
*
|
|
563
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
564
|
+
* @param opts - Which process, folder, input arguments, and whether to wait.
|
|
565
|
+
* @returns This builder, so calls chain.
|
|
566
|
+
*/
|
|
567
|
+
startAgenticProcess(id, opts) {
|
|
568
|
+
return this.orchestratorNode(id, opts.async ? 'Orchestrator.StartAgenticProcessAsync' : 'Orchestrator.StartAgenticProcess', opts);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Invoke a **case-management process** as a call activity
|
|
572
|
+
* (`Orchestrator.StartCaseMgmtProcess`, or `…Async` when `async` is set).
|
|
573
|
+
*
|
|
574
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
575
|
+
* @param opts - Which case process, folder, input arguments, and whether to wait.
|
|
576
|
+
* @returns This builder, so calls chain.
|
|
577
|
+
*/
|
|
578
|
+
startCaseProcess(id, opts) {
|
|
579
|
+
return this.orchestratorNode(id, opts.async ? 'Orchestrator.StartCaseMgmtProcessAsync' : 'Orchestrator.StartCaseMgmtProcess', opts);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Execute an **API workflow**, fire-and-forget
|
|
583
|
+
* (`Orchestrator.ExecuteApiWorkflowAsync`).
|
|
584
|
+
*
|
|
585
|
+
* @remarks
|
|
586
|
+
* The registry offers only the async form, so there is nothing to wait on: the
|
|
587
|
+
* node maps back an error and nothing else.
|
|
588
|
+
*
|
|
589
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
590
|
+
* @param opts - Which workflow, folder, and input arguments.
|
|
591
|
+
* @returns This builder, so calls chain.
|
|
592
|
+
*/
|
|
593
|
+
executeApiWorkflow(id, opts) {
|
|
594
|
+
return this.orchestratorNode(id, 'Orchestrator.ExecuteApiWorkflowAsync', opts);
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Execute a **business rule** and wait for it (`Orchestrator.BusinessRules`, on a
|
|
598
|
+
* `bpmn:businessRuleTask`).
|
|
599
|
+
*
|
|
600
|
+
* @remarks
|
|
601
|
+
* **Not a DMN decision table**, despite the element and the label. The registry spec
|
|
602
|
+
* is an Orchestrator process invocation — `releaseKey`/`folderId`/`folderPath`/`name`
|
|
603
|
+
* plus `JobArguments`, `BindingPattern: businessRule` over `Resource: process` —
|
|
604
|
+
* structurally identical to {@link ScopeBuilder.startProcess}. `process` names a
|
|
605
|
+
* package whose Orchestrator process type is `BusinessRules`; whatever decision logic
|
|
606
|
+
* exists lives INSIDE that package, not in the `.bpmn`. So this is the job-start
|
|
607
|
+
* family's sixth member, not a rules subsystem, and it shares every option with it.
|
|
608
|
+
*
|
|
609
|
+
* Distinct from the Case SDK's `rule()`, which declares DNF lifecycle conditions
|
|
610
|
+
* (`case-entered`, `required-tasks-completed`, …) deciding when a stage enters or
|
|
611
|
+
* exits. The two share a word and nothing else.
|
|
612
|
+
*
|
|
613
|
+
* The extension type is marked `[Preview]` by the registry. That is a caveat on the
|
|
614
|
+
* SHAPE, not on this method: a preview extension type can gain or rename fields, and
|
|
615
|
+
* the snapshot refresh (`scripts/materialize-bpmn-registry.mjs`) is what would surface
|
|
616
|
+
* it as a data diff.
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* ```ts
|
|
620
|
+
* bpmn('pricing')
|
|
621
|
+
* .var('tier', 'string', { default: 'none' })
|
|
622
|
+
* .startEvent('start')
|
|
623
|
+
* .businessRule('tier', {
|
|
624
|
+
* process: 'DiscountTier',
|
|
625
|
+
* folder: 'Finance',
|
|
626
|
+
* input: { amount: 4200 },
|
|
627
|
+
* outputs: { tier: '=response.tier' },
|
|
628
|
+
* })
|
|
629
|
+
* .endEvent('done')
|
|
630
|
+
* .sequenceFlow('start', 'tier')
|
|
631
|
+
* .sequenceFlow('tier', 'done')
|
|
632
|
+
* .build();
|
|
633
|
+
* ```
|
|
634
|
+
*
|
|
635
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
636
|
+
* @param opts - Which rule package, folder, and input arguments. `outputVar` defaults
|
|
637
|
+
* to `<id>_businessRuleResponse` — see the note in the implementation for why this one
|
|
638
|
+
* type does not take its default from the spec.
|
|
639
|
+
* @returns This builder, so calls chain.
|
|
640
|
+
*/
|
|
641
|
+
businessRule(id, opts) {
|
|
642
|
+
// The ONE place this type departs from its family, and deliberately.
|
|
643
|
+
//
|
|
644
|
+
// Every other member takes its default output variable from the registry's
|
|
645
|
+
// `OutputName` (`Process response` → `<id>_processResponse`). This type's
|
|
646
|
+
// `OutputName` is literally its designer LABEL, `Execute business rule [Preview]`,
|
|
647
|
+
// so the derived default would be `<id>_executeBusinessRulePreview`: unreadable,
|
|
648
|
+
// and — worse — it encodes the preview marker in a name authors write expressions
|
|
649
|
+
// against. When `[Preview]` drops the label becomes `Execute business rule`, the
|
|
650
|
+
// derived default silently becomes `<id>_executeBusinessRule`, and every
|
|
651
|
+
// `vars.<id>_executeBusinessRulePreview` reference in every authored process starts
|
|
652
|
+
// resolving to undefined — a silent wrong-answer change from a cosmetic spec edit.
|
|
653
|
+
//
|
|
654
|
+
// Pinning it here makes the default independent of the label. The output ROW still
|
|
655
|
+
// carries the registry's own `name`, so the artifact is unchanged.
|
|
656
|
+
return this.orchestratorNode(id, 'Orchestrator.BusinessRules', {
|
|
657
|
+
...opts,
|
|
658
|
+
outputVar: opts.outputVar ?? `${id}_businessRuleResponse`,
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Add an item to an Orchestrator **queue** (`Orchestrator.CreateQueueItem`, or
|
|
663
|
+
* `Orchestrator.CreateAndWaitForQueueItem` when `wait` is set).
|
|
664
|
+
*
|
|
665
|
+
* @example
|
|
666
|
+
* ```ts
|
|
667
|
+
* bpmn('intake')
|
|
668
|
+
* .startEvent('start')
|
|
669
|
+
* .queueItem('enqueue', { queue: 'Invoices', folder: 'Finance', item: { id: 'INV-1' } })
|
|
670
|
+
* .endEvent('done')
|
|
671
|
+
* .sequenceFlow('start', 'enqueue')
|
|
672
|
+
* .sequenceFlow('enqueue', 'done')
|
|
673
|
+
* .build();
|
|
674
|
+
* ```
|
|
675
|
+
*
|
|
676
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
677
|
+
* @param opts - Which queue and folder, the item content, and whether to wait for it.
|
|
678
|
+
* @returns This builder, so calls chain.
|
|
679
|
+
*/
|
|
680
|
+
queueItem(id, opts) {
|
|
681
|
+
return this.push({
|
|
682
|
+
kind: 'typed',
|
|
683
|
+
id,
|
|
684
|
+
name: opts.name,
|
|
685
|
+
type: opts.wait ? 'Orchestrator.CreateAndWaitForQueueItem' : 'Orchestrator.CreateQueueItem',
|
|
686
|
+
context: this.bindRequiredContext(id, opts.wait ? 'Orchestrator.CreateAndWaitForQueueItem' : 'Orchestrator.CreateQueueItem', {
|
|
687
|
+
queueName: opts.queue,
|
|
688
|
+
folderPath: opts.folder,
|
|
689
|
+
}),
|
|
690
|
+
inputs: opts.item ?? {},
|
|
691
|
+
outputs: opts.outputs,
|
|
692
|
+
outputVar: opts.outputVar,
|
|
693
|
+
skipCondition: opts.skipCondition,
|
|
694
|
+
tags: opts.tags,
|
|
695
|
+
retry: opts.retry,
|
|
696
|
+
errorMapping: opts.errorMapping,
|
|
697
|
+
loop: opts.loop,
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* A **human task** — an Action App task a person completes (`bpmn:userTask` +
|
|
702
|
+
* `uipath:activity` / `Actions.HITL`).
|
|
703
|
+
*
|
|
704
|
+
* @remarks
|
|
705
|
+
* The offline runtime can stand in for the human — `--hitl-response` injects an
|
|
706
|
+
* outcome — so an approval gate's branches are testable with no tenant and no
|
|
707
|
+
* waiting. That is why this is the one discovery-requiring type worth authoring
|
|
708
|
+
* early:
|
|
709
|
+
*
|
|
710
|
+
* ```bash
|
|
711
|
+
* flow-debug Invoice.bpmn --mock --virtual-time --hitl-response 'approve={"Action":"approve"}'
|
|
712
|
+
* ```
|
|
713
|
+
*
|
|
714
|
+
* Map the decision into a variable with `outputs` if anything branches on it —
|
|
715
|
+
* see {@link HumanTaskOpts.outputs} for why the type's own output is not enough.
|
|
716
|
+
*
|
|
717
|
+
* @example
|
|
718
|
+
* **An approval gate whose branches can be exercised offline**
|
|
719
|
+
* ```ts
|
|
720
|
+
* bpmn('invoice')
|
|
721
|
+
* .var('outcome', 'string', { default: 'none' })
|
|
722
|
+
* .startEvent('start')
|
|
723
|
+
* .humanTask('approve', {
|
|
724
|
+
* app: 'app-123',
|
|
725
|
+
* title: 'Approve the invoice',
|
|
726
|
+
* actions: ['approve', 'reject'],
|
|
727
|
+
* input: { amount: 100 },
|
|
728
|
+
* outputs: { decision: '=Action' },
|
|
729
|
+
* })
|
|
730
|
+
* .exclusiveGateway('gw', { default: 'fReject' })
|
|
731
|
+
* .task('ok', { set: { outcome: 'approved' } })
|
|
732
|
+
* .task('no', { set: { outcome: 'rejected' } })
|
|
733
|
+
* .exclusiveGateway('join', { default: 'fJoin' })
|
|
734
|
+
* .endEvent('done')
|
|
735
|
+
* .sequenceFlow('start', 'approve')
|
|
736
|
+
* .sequenceFlow('approve', 'gw')
|
|
737
|
+
* .sequenceFlow('gw', 'ok', { id: 'fApprove', condition: '=js:vars.decision == "approve"' })
|
|
738
|
+
* .sequenceFlow('gw', 'no', { id: 'fReject' })
|
|
739
|
+
* .sequenceFlow('ok', 'join', { id: 'fOk' })
|
|
740
|
+
* .sequenceFlow('no', 'join', { id: 'fNo' })
|
|
741
|
+
* .sequenceFlow('join', 'done', { id: 'fJoin' })
|
|
742
|
+
* .build();
|
|
743
|
+
* ```
|
|
744
|
+
*
|
|
745
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
746
|
+
* @param opts - The app, the outcomes offered, what the human sees, and which
|
|
747
|
+
* response fields to keep.
|
|
748
|
+
* @returns This builder, so calls chain.
|
|
749
|
+
*/
|
|
750
|
+
humanTask(id, opts) {
|
|
751
|
+
return this.push({
|
|
752
|
+
kind: 'typed',
|
|
753
|
+
id,
|
|
754
|
+
name: opts.name,
|
|
755
|
+
type: 'Actions.HITL',
|
|
756
|
+
context: {
|
|
757
|
+
appId: opts.app,
|
|
758
|
+
...(opts.appVersion !== undefined ? { appVersion: opts.appVersion } : {}),
|
|
759
|
+
...(opts.actions !== undefined ? { actions: opts.actions.join(',') } : {}),
|
|
760
|
+
...(opts.title !== undefined ? { taskTitle: opts.title } : {}),
|
|
761
|
+
...(opts.key !== undefined ? { key: opts.key } : {}),
|
|
762
|
+
},
|
|
763
|
+
inputs: opts.input ?? {},
|
|
764
|
+
outputVar: opts.outputVar,
|
|
765
|
+
outputs: opts.outputs,
|
|
766
|
+
skipCondition: opts.skipCondition,
|
|
767
|
+
tags: opts.tags,
|
|
768
|
+
retry: opts.retry,
|
|
769
|
+
errorMapping: opts.errorMapping,
|
|
770
|
+
loop: opts.loop,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Wait for an internal message from another Maestro process
|
|
775
|
+
* (`Maestro.ReceiveMessageEvent` on a `bpmn:intermediateCatchEvent`).
|
|
776
|
+
*
|
|
777
|
+
* @remarks
|
|
778
|
+
* **No offline behavioural assertion is possible for this node**, and that is
|
|
779
|
+
* worth knowing before relying on it. The local engine treats intermediate catch
|
|
780
|
+
* and throw events as pass-throughs (`engine.ts`: "For lightweight engine, just
|
|
781
|
+
* pass through"), so a local run walks straight past this event without waiting,
|
|
782
|
+
* without correlating, and without populating its output. A green local ladder
|
|
783
|
+
* therefore proves the graph runs and the artifact validates — nothing about the
|
|
784
|
+
* message actually arriving. See Phase 5 in `docs/BPMN_COVERAGE_DESIGN.md`.
|
|
785
|
+
*
|
|
786
|
+
* The throw side (`Maestro.SendMessageEvent`) is deliberately NOT authored: its
|
|
787
|
+
* required `Reference` payload field cannot be expressed in a way the platform
|
|
788
|
+
* validator accepts. See `unsatisfiableRequiredInputs`.
|
|
789
|
+
*
|
|
790
|
+
* @example
|
|
791
|
+
* **Wait for another process to signal a shipment**
|
|
792
|
+
* ```ts
|
|
793
|
+
* bpmn('fulfil')
|
|
794
|
+
* .var('orderId', 'string', { default: 'ORD-1' })
|
|
795
|
+
* .var('shipment', 'object')
|
|
796
|
+
* .startEvent('start')
|
|
797
|
+
* .receiveMessage('await', {
|
|
798
|
+
* message: 'ShipmentReady',
|
|
799
|
+
* reference: '=js:vars.orderId',
|
|
800
|
+
* outputVar: 'shipment',
|
|
801
|
+
* })
|
|
802
|
+
* .endEvent('done')
|
|
803
|
+
* .sequenceFlow('start', 'await')
|
|
804
|
+
* .sequenceFlow('await', 'done')
|
|
805
|
+
* .build();
|
|
806
|
+
* ```
|
|
807
|
+
*
|
|
808
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
809
|
+
* @param opts - The message name, the correlation reference, and what to keep.
|
|
810
|
+
* @returns This builder, so calls chain.
|
|
811
|
+
*/
|
|
812
|
+
receiveMessage(id, opts) {
|
|
813
|
+
return this.push({
|
|
814
|
+
kind: 'typed',
|
|
815
|
+
id,
|
|
816
|
+
name: opts.name,
|
|
817
|
+
type: 'Maestro.ReceiveMessageEvent',
|
|
818
|
+
context: { name: opts.message },
|
|
819
|
+
inputs: { Reference: opts.reference },
|
|
820
|
+
outputVar: opts.outputVar,
|
|
821
|
+
skipCondition: opts.skipCondition,
|
|
822
|
+
tags: opts.tags,
|
|
823
|
+
retry: opts.retry,
|
|
824
|
+
errorMapping: opts.errorMapping,
|
|
825
|
+
loop: opts.loop,
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Wait mid-flow for an Integration Service connector event
|
|
830
|
+
* (`Intsvc.WaitForEvent` on a `bpmn:receiveTask`).
|
|
831
|
+
*
|
|
832
|
+
* @remarks
|
|
833
|
+
* The sibling of {@link ScopeBuilder.eventTrigger}: one connector operation, two
|
|
834
|
+
* placements. This one pauses a RUNNING process; `.eventTrigger()` starts one.
|
|
835
|
+
* The platform ships both for the same operation and only the library namespace
|
|
836
|
+
* differs, which is the same pairing Flow models as `waitForEvent()` / `onEvent()`.
|
|
837
|
+
*
|
|
838
|
+
* **This family DOES have an offline behavioural assertion**, unlike the other
|
|
839
|
+
* wait-shaped nodes: the engine mocks a receive task like any other, so
|
|
840
|
+
* `--mock-data` supplies a payload and a gateway branches on it. Map the field
|
|
841
|
+
* with `outputs` — the type's own `source="."` row is not resolved locally.
|
|
842
|
+
*
|
|
843
|
+
* @example
|
|
844
|
+
* **Wait for an email, then branch on it**
|
|
845
|
+
* ```ts
|
|
846
|
+
* bpmn('intake')
|
|
847
|
+
* .binding('outlook', { value: 'conn-uuid', resource: 'Connection', propertyAttribute: 'ConnectionId' })
|
|
848
|
+
* .binding('shared', { value: 'folder-key', resource: 'Connection', propertyAttribute: 'folderKey' })
|
|
849
|
+
* .var('subject', 'string', { default: '' })
|
|
850
|
+
* .startEvent('start')
|
|
851
|
+
* .waitForEvent('mail', 'uipath-microsoft-outlook365', 'email-received', {
|
|
852
|
+
* connection: 'outlook',
|
|
853
|
+
* folder: 'shared',
|
|
854
|
+
* outputs: { subject: '=subject' },
|
|
855
|
+
* })
|
|
856
|
+
* .endEvent('done')
|
|
857
|
+
* .sequenceFlow('start', 'mail')
|
|
858
|
+
* .sequenceFlow('mail', 'done')
|
|
859
|
+
* .build();
|
|
860
|
+
* ```
|
|
861
|
+
*
|
|
862
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
863
|
+
* @param connector - The connector key, e.g. `'uipath-microsoft-outlook365'`.
|
|
864
|
+
* @param event - The event name, e.g. `'email-received'`.
|
|
865
|
+
* @param opts - Connection/folder bindings, the `where` scope, and what to keep.
|
|
866
|
+
* @returns This builder, so calls chain.
|
|
867
|
+
*/
|
|
868
|
+
waitForEvent(id, connector, event, opts) {
|
|
869
|
+
return this.push({
|
|
870
|
+
kind: 'connectorEvent',
|
|
871
|
+
id,
|
|
872
|
+
name: opts.name,
|
|
873
|
+
subscribe: 'event',
|
|
874
|
+
key: connector,
|
|
875
|
+
eventName: event,
|
|
876
|
+
version: opts.version,
|
|
877
|
+
connection: opts.connection,
|
|
878
|
+
folder: opts.folder,
|
|
879
|
+
folderPath: opts.folderPath,
|
|
880
|
+
filter: opts.filter,
|
|
881
|
+
parameters: opts.parameters,
|
|
882
|
+
outputVar: opts.outputVar,
|
|
883
|
+
outputs: opts.outputs,
|
|
884
|
+
skipCondition: opts.skipCondition,
|
|
885
|
+
tags: opts.tags,
|
|
886
|
+
retry: opts.retry,
|
|
887
|
+
errorMapping: opts.errorMapping,
|
|
888
|
+
loop: opts.loop,
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* START the process when an Integration Service connector event fires
|
|
893
|
+
* (`Intsvc.EventTrigger` on a `bpmn:startEvent` carrying a message event
|
|
894
|
+
* definition).
|
|
895
|
+
*
|
|
896
|
+
* @remarks
|
|
897
|
+
* Its own method rather than a flag on `.startEvent()` — the opposite call from
|
|
898
|
+
* the timer trigger, and for a stated reason. `Intsvc.TimerTrigger` declares NO
|
|
899
|
+
* fields, so the only thing to configure there is an output variable and a flag
|
|
900
|
+
* suffices. This type declares nine, including the connection and folder
|
|
901
|
+
* bindings, which is a method's worth of surface.
|
|
902
|
+
*
|
|
903
|
+
* **No offline behavioural assertion**, unlike `.waitForEvent()`: this is a start
|
|
904
|
+
* event, and the engine applies a start event's output rows against the variable
|
|
905
|
+
* scope rather than a mocked result, so nothing populates the payload locally.
|
|
906
|
+
*
|
|
907
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
908
|
+
* @param connector - The connector key, e.g. `'uipath-http-webhook'`.
|
|
909
|
+
* @param event - The event name, e.g. `'http-webhook'`.
|
|
910
|
+
* @param opts - Connection/folder bindings, the `where` scope, and what to keep.
|
|
911
|
+
* @returns This builder, so calls chain.
|
|
912
|
+
*/
|
|
913
|
+
eventTrigger(id, connector, event, opts) {
|
|
914
|
+
return this.push({
|
|
915
|
+
kind: 'connectorEvent',
|
|
916
|
+
id,
|
|
917
|
+
name: opts.name,
|
|
918
|
+
subscribe: 'trigger',
|
|
919
|
+
key: connector,
|
|
920
|
+
eventName: event,
|
|
921
|
+
version: opts.version,
|
|
922
|
+
connection: opts.connection,
|
|
923
|
+
folder: opts.folder,
|
|
924
|
+
folderPath: opts.folderPath,
|
|
925
|
+
filter: opts.filter,
|
|
926
|
+
parameters: opts.parameters,
|
|
927
|
+
outputVar: opts.outputVar,
|
|
928
|
+
outputs: opts.outputs,
|
|
929
|
+
skipCondition: opts.skipCondition,
|
|
930
|
+
tags: opts.tags,
|
|
931
|
+
retry: opts.retry,
|
|
932
|
+
errorMapping: opts.errorMapping,
|
|
933
|
+
loop: opts.loop,
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Invoke an external agent through an Integration Service connector
|
|
938
|
+
* (`Intsvc.SyncAgentExecution` / `Intsvc.AsyncAgentExecution`).
|
|
939
|
+
*
|
|
940
|
+
* @remarks
|
|
941
|
+
* `mode: 'sync'` waits for the agent's answer; `'async'` starts it and moves on.
|
|
942
|
+
* The descriptor must be an `AgentExecution` operation — the library is the
|
|
943
|
+
* authority, and a plain connector action is refused rather than emitted as a node
|
|
944
|
+
* the validator accepts and the runtime dispatches to the wrong handler.
|
|
945
|
+
*
|
|
946
|
+
* **The shipped library contains very few of these** (2 agent operations, 1
|
|
947
|
+
* workflow), so this is a narrow surface by nature, not by omission.
|
|
948
|
+
*
|
|
949
|
+
* @example
|
|
950
|
+
* ```ts
|
|
951
|
+
* bpmn('triage')
|
|
952
|
+
* .binding('vertex', { value: 'conn-uuid', resource: 'Connection', propertyAttribute: 'ConnectionId' })
|
|
953
|
+
* .binding('shared', { value: 'folder-key', resource: 'Connection', propertyAttribute: 'folderKey' })
|
|
954
|
+
* .startEvent('start')
|
|
955
|
+
* .externalAgent('summarise', 'uipath-google-vertex', 'execute-google-vertex-agent',
|
|
956
|
+
* { prompt: 'Summarise the ticket' },
|
|
957
|
+
* { mode: 'sync', connection: 'vertex', folder: 'shared' })
|
|
958
|
+
* .endEvent('done')
|
|
959
|
+
* .sequenceFlow('start', 'summarise')
|
|
960
|
+
* .sequenceFlow('summarise', 'done')
|
|
961
|
+
* .build();
|
|
962
|
+
* ```
|
|
963
|
+
*
|
|
964
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
965
|
+
* @param connector - The connector key.
|
|
966
|
+
* @param action - The `AgentExecution` operation name.
|
|
967
|
+
* @param inputs - The invocation payload.
|
|
968
|
+
* @param opts - `mode`, the connection/folder bindings, and what to keep.
|
|
969
|
+
* @returns This builder, so calls chain.
|
|
970
|
+
*/
|
|
971
|
+
externalAgent(id, connector, action, inputs, opts) {
|
|
972
|
+
return this.externalTask('agent', id, connector, action, inputs, opts);
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Invoke an external workflow through an Integration Service connector
|
|
976
|
+
* (`Intsvc.SyncWorkflowExecution` / `Intsvc.AsyncWorkflowExecution`).
|
|
977
|
+
*
|
|
978
|
+
* @remarks
|
|
979
|
+
* The workflow counterpart of {@link ScopeBuilder.externalAgent}; the descriptor
|
|
980
|
+
* must be a `ProcessExecution` operation.
|
|
981
|
+
*
|
|
982
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
983
|
+
* @param connector - The connector key.
|
|
984
|
+
* @param action - The `ProcessExecution` operation name.
|
|
985
|
+
* @param inputs - The invocation payload.
|
|
986
|
+
* @param opts - `mode`, the connection/folder bindings, and what to keep.
|
|
987
|
+
* @returns This builder, so calls chain.
|
|
988
|
+
*/
|
|
989
|
+
externalWorkflow(id, connector, action, inputs, opts) {
|
|
990
|
+
return this.externalTask('workflow', id, connector, action, inputs, opts);
|
|
991
|
+
}
|
|
992
|
+
/** @internal Shared body of the two external-invocation methods. */
|
|
993
|
+
externalTask(family, id, connector, action, inputs, opts) {
|
|
994
|
+
return this.push({
|
|
995
|
+
kind: 'externalTask',
|
|
996
|
+
id,
|
|
997
|
+
name: opts.name,
|
|
998
|
+
family,
|
|
999
|
+
mode: opts.mode,
|
|
1000
|
+
key: connector,
|
|
1001
|
+
action,
|
|
1002
|
+
version: opts.version,
|
|
1003
|
+
inputs,
|
|
1004
|
+
connection: opts.connection,
|
|
1005
|
+
folder: opts.folder,
|
|
1006
|
+
outputVar: opts.outputVar,
|
|
1007
|
+
outputs: opts.outputs,
|
|
1008
|
+
skipCondition: opts.skipCondition,
|
|
1009
|
+
tags: opts.tags,
|
|
1010
|
+
retry: opts.retry,
|
|
1011
|
+
errorMapping: opts.errorMapping,
|
|
1012
|
+
loop: opts.loop,
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* ANY registry-backed node, by extension type — the generic form the typed
|
|
1017
|
+
* methods are sugar over.
|
|
1018
|
+
*
|
|
1019
|
+
* @remarks
|
|
1020
|
+
* Reach for a typed method first (`.http()`, `.startProcess()`, `.humanTask()`,
|
|
1021
|
+
* …): it names the fields, defaults what the registry defaults, and declares the
|
|
1022
|
+
* bindings a type demands. This is for the types that have no wrapper yet, and
|
|
1023
|
+
* it is what `bpmn-decompile` emits for them — which is why it exists at all.
|
|
1024
|
+
* Nothing is validated for you beyond what the registry states, so the emitted
|
|
1025
|
+
* node is exactly as correct as the `context` you pass.
|
|
1026
|
+
*
|
|
1027
|
+
* The element, tag, input shape, output row and event definition all come from
|
|
1028
|
+
* the committed registry snapshot, so the wire form is right even when the
|
|
1029
|
+
* ergonomics are bare.
|
|
1030
|
+
*
|
|
1031
|
+
* @example
|
|
1032
|
+
* ```ts
|
|
1033
|
+
* bpmn('agentic')
|
|
1034
|
+
* .startEvent('start')
|
|
1035
|
+
* .activity('call', 'A2A.AgentExecution', { inputs: { prompt: 'summarise' } })
|
|
1036
|
+
* .endEvent('done')
|
|
1037
|
+
* .sequenceFlow('start', 'call')
|
|
1038
|
+
* .sequenceFlow('call', 'done')
|
|
1039
|
+
* .build();
|
|
1040
|
+
* ```
|
|
1041
|
+
*
|
|
1042
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
1043
|
+
* @param type - The registry extension type, e.g. `'A2A.AgentExecution'`.
|
|
1044
|
+
* @param opts - Context values, payload, output mapping and the shared activity options.
|
|
1045
|
+
* @returns This builder, so calls chain.
|
|
1046
|
+
*/
|
|
1047
|
+
activity(id, type, opts = {}) {
|
|
1048
|
+
return this.push({
|
|
1049
|
+
kind: 'typed',
|
|
1050
|
+
id,
|
|
1051
|
+
name: opts.name,
|
|
1052
|
+
type,
|
|
1053
|
+
context: opts.context ?? {},
|
|
1054
|
+
contextRows: opts.contextRows,
|
|
1055
|
+
inputs: opts.inputs ?? {},
|
|
1056
|
+
typeVersion: opts.typeVersion,
|
|
1057
|
+
inputSchema: opts.inputSchema,
|
|
1058
|
+
outputVar: opts.outputVar,
|
|
1059
|
+
outputs: opts.outputs,
|
|
1060
|
+
outputRows: opts.outputRows,
|
|
1061
|
+
skipCondition: opts.skipCondition,
|
|
1062
|
+
contextVerbatim: opts.contextVerbatim,
|
|
1063
|
+
tags: opts.tags,
|
|
1064
|
+
retry: opts.retry,
|
|
1065
|
+
errorMapping: opts.errorMapping,
|
|
1066
|
+
loop: opts.loop,
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
// ── Sub-process (nested graph) ──
|
|
1070
|
+
/**
|
|
1071
|
+
* A sub-process — a scope of its own, with its own elements and flows (`bpmn:subProcess`).
|
|
1072
|
+
*
|
|
1073
|
+
* @param id - The element id, unique in the process and used by `sequenceFlow`.
|
|
1074
|
+
* @param fn - Receives a sub-builder for the elements inside it.
|
|
1075
|
+
* @param opts - `name`, and the loop characteristics when it repeats.
|
|
1076
|
+
* @returns This builder, so calls chain.
|
|
1077
|
+
*/
|
|
1078
|
+
subProcess(id, fn, opts = {}) {
|
|
1079
|
+
const sb = new SubProcessBuilder(this._defs, this._bindingRegistry);
|
|
1080
|
+
fn(sb);
|
|
1081
|
+
return this.push(sb._buildNode(id, opts));
|
|
1082
|
+
}
|
|
1083
|
+
// ── Flows ──
|
|
1084
|
+
/**
|
|
1085
|
+
* A sequence flow from `source` to `target` (1-1 with `bpmn:sequenceFlow`).
|
|
1086
|
+
*
|
|
1087
|
+
* @param source - The id of the element the flow leaves.
|
|
1088
|
+
* @param target - The id of the element it arrives at.
|
|
1089
|
+
* @param opts - `name`, and the `condition` guarding it.
|
|
1090
|
+
* @returns This builder, so calls chain.
|
|
1091
|
+
*/
|
|
1092
|
+
sequenceFlow(source, target, opts = {}) {
|
|
1093
|
+
this._flows.push({
|
|
1094
|
+
id: opts.id ?? `Flow_${source}_${target}`,
|
|
1095
|
+
source,
|
|
1096
|
+
target,
|
|
1097
|
+
name: opts.name,
|
|
1098
|
+
condition: opts.condition,
|
|
1099
|
+
});
|
|
1100
|
+
return this;
|
|
1101
|
+
}
|
|
1102
|
+
// ── Variables ──
|
|
1103
|
+
/**
|
|
1104
|
+
* A mutable flow variable (`uipath:inputOutput`). Root unless `elementId` scopes it.
|
|
1105
|
+
*
|
|
1106
|
+
* @param id - The variable's name.
|
|
1107
|
+
* @param type - A `types.*` descriptor.
|
|
1108
|
+
* @param opts - `direction`, a `default`, and `elementId` to scope it to one element.
|
|
1109
|
+
* @returns This builder, so calls chain.
|
|
1110
|
+
*/
|
|
1111
|
+
var(id, type, opts = {}) {
|
|
1112
|
+
return this.declareVar(id, type, 'inputOutput', opts);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* A read-only entry input (`uipath:input`).
|
|
1116
|
+
*
|
|
1117
|
+
* @param id - The input's name.
|
|
1118
|
+
* @param type - A `types.*` descriptor.
|
|
1119
|
+
* @param opts - A `default`, and `elementId` to scope it to one element.
|
|
1120
|
+
* @returns This builder, so calls chain.
|
|
1121
|
+
*/
|
|
1122
|
+
input(id, type, opts = {}) {
|
|
1123
|
+
return this.declareVar(id, type, 'input', opts);
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* A return value (`uipath:output`).
|
|
1127
|
+
*
|
|
1128
|
+
* @param id - The output's name.
|
|
1129
|
+
* @param type - A `types.*` descriptor.
|
|
1130
|
+
* @param opts - A `default`, and `elementId` to scope it to one element.
|
|
1131
|
+
* @returns This builder, so calls chain.
|
|
1132
|
+
*/
|
|
1133
|
+
output(id, type, opts = {}) {
|
|
1134
|
+
return this.declareVar(id, type, 'output', opts);
|
|
1135
|
+
}
|
|
1136
|
+
declareVar(id, type, direction, opts) {
|
|
1137
|
+
this._vars.push({
|
|
1138
|
+
id,
|
|
1139
|
+
name: opts.name ?? id,
|
|
1140
|
+
type,
|
|
1141
|
+
direction,
|
|
1142
|
+
default: opts.default,
|
|
1143
|
+
elementId: opts.elementId,
|
|
1144
|
+
schema: opts.schema,
|
|
1145
|
+
required: opts.required,
|
|
1146
|
+
});
|
|
1147
|
+
return this;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* The variables a connector task's output rows land in.
|
|
1152
|
+
*
|
|
1153
|
+
* Per-node by default, because a `uipath:output`'s `var` IS the variable
|
|
1154
|
+
* declaration as far as the platform is concerned (its canvas model maps every
|
|
1155
|
+
* node output to a variable keyed by `var`). A shared name would therefore mean
|
|
1156
|
+
* two connectors writing one variable, with the second silently clobbering the
|
|
1157
|
+
* first — and it is the reason both the serializer and the expression check need
|
|
1158
|
+
* the same answer, hence one function.
|
|
1159
|
+
*
|
|
1160
|
+
* @param n - The connector node.
|
|
1161
|
+
* @returns The response and error variable names.
|
|
1162
|
+
*
|
|
1163
|
+
* @internal
|
|
1164
|
+
*/
|
|
1165
|
+
export function connectorOutputVars(n) {
|
|
1166
|
+
return { response: n.outputVar ?? `${n.id}_response`, error: `${n.id}_Error` };
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* The variables a typed node writes — the ONE definition of that set.
|
|
1170
|
+
*
|
|
1171
|
+
* It had grown three: this one (what an expression may read), `implicitNodeVars` in
|
|
1172
|
+
* serialize (what gets declared in `uipath:variables`), and `derivedVariableIds` in
|
|
1173
|
+
* decompile (what a decompiled file must NOT re-declare). All three must agree, and
|
|
1174
|
+
* adding `outputRows` proved they do not stay agreed on their own: two were updated,
|
|
1175
|
+
* this one was missed, and a human task's mapped output stopped being visible to the
|
|
1176
|
+
* expression checker — `vars.decision` reported undeclared for a variable the node
|
|
1177
|
+
* plainly writes. So serialize now calls this instead of repeating it, and only
|
|
1178
|
+
* decompile's copy is separate, which its own comment already flags as load-bearing.
|
|
1179
|
+
*
|
|
1180
|
+
* @param n - The typed node.
|
|
1181
|
+
* @returns The variable ids its output rows write.
|
|
1182
|
+
* @internal
|
|
1183
|
+
*/
|
|
1184
|
+
export function typedNodeDeclaredVars(n) {
|
|
1185
|
+
// Spelled-out rows REPLACE the derived pair, so they are the whole answer.
|
|
1186
|
+
if (n.outputRows)
|
|
1187
|
+
return n.outputRows.map((r) => r.var).filter((v) => v !== undefined);
|
|
1188
|
+
const v = typedNodeOutputVar(n.id, n.type, n.outputVar);
|
|
1189
|
+
return [...(v ? [v] : []), ...Object.keys(n.outputs ?? {})];
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Every variable name a node DECLARES by writing to it — the platform counts a
|
|
1193
|
+
* node's output `var` as a declaration, so a downstream `=vars.<name>` resolves
|
|
1194
|
+
* against it without any `uipath:variables` entry. The expression check mirrors
|
|
1195
|
+
* that, or it would reject reads the platform accepts.
|
|
1196
|
+
*
|
|
1197
|
+
* @param n - The node to inspect.
|
|
1198
|
+
* @returns The variable names it declares, if any.
|
|
1199
|
+
*
|
|
1200
|
+
* @internal
|
|
1201
|
+
*/
|
|
1202
|
+
export function nodeDeclaredVars(n) {
|
|
1203
|
+
if (n.kind === 'connector') {
|
|
1204
|
+
const { response, error } = connectorOutputVars(n);
|
|
1205
|
+
return [response, error];
|
|
1206
|
+
}
|
|
1207
|
+
if (n.kind === 'typed')
|
|
1208
|
+
return typedNodeDeclaredVars(n);
|
|
1209
|
+
if (n.kind === 'scriptTask')
|
|
1210
|
+
return Object.keys(n.outputs);
|
|
1211
|
+
if (n.kind === 'task')
|
|
1212
|
+
return Object.keys(n.set);
|
|
1213
|
+
return [];
|
|
1214
|
+
}
|
|
1215
|
+
/** A sub-process body: the same graph methods, plus an internal node builder. */
|
|
1216
|
+
export class SubProcessBuilder extends ScopeBuilder {
|
|
1217
|
+
/** @internal */
|
|
1218
|
+
_buildNode(id, opts) {
|
|
1219
|
+
return {
|
|
1220
|
+
kind: 'subProcess',
|
|
1221
|
+
id,
|
|
1222
|
+
name: opts.name,
|
|
1223
|
+
payload: opts.payload,
|
|
1224
|
+
triggeredByEvent: opts.triggeredByEvent,
|
|
1225
|
+
tags: opts.tags,
|
|
1226
|
+
loop: opts.loop,
|
|
1227
|
+
retry: opts.retry,
|
|
1228
|
+
errorMapping: opts.errorMapping,
|
|
1229
|
+
nodes: this._nodes,
|
|
1230
|
+
flows: this._flows,
|
|
1231
|
+
variables: this._vars,
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
// ─── Top-level process builder ────────────────────────────────────────────────
|
|
1236
|
+
/**
|
|
1237
|
+
* The top-level process builder `bpmn()` returns — every graph method of the
|
|
1238
|
+
* shared scope (events, gateways, tasks, sub-processes, flows, variables) plus
|
|
1239
|
+
* the process's `.name()` and the `.build()` that finishes it.
|
|
1240
|
+
*/
|
|
1241
|
+
export class BpmnBuilder extends ScopeBuilder {
|
|
1242
|
+
_id;
|
|
1243
|
+
_name;
|
|
1244
|
+
_metadata;
|
|
1245
|
+
/**
|
|
1246
|
+
* @param _id - The process id, as passed to `bpmn()`.
|
|
1247
|
+
* @returns The top-level builder.
|
|
1248
|
+
*/
|
|
1249
|
+
constructor(_id) {
|
|
1250
|
+
super(new DefinitionsRegistry(), new BindingsRegistry());
|
|
1251
|
+
this._id = _id;
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Set the process's display name.
|
|
1255
|
+
*
|
|
1256
|
+
* @param n - The name the designer shows.
|
|
1257
|
+
* @returns This builder, so calls chain.
|
|
1258
|
+
*/
|
|
1259
|
+
name(n) {
|
|
1260
|
+
this._name = n;
|
|
1261
|
+
return this;
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Process-level metadata — see {@link ProcessMetadata}.
|
|
1265
|
+
*
|
|
1266
|
+
* Repeated calls MERGE rather than replace, so a caller can set one field without
|
|
1267
|
+
* knowing what an earlier call set.
|
|
1268
|
+
*
|
|
1269
|
+
* @param meta - The fields to declare; anything omitted stays absent.
|
|
1270
|
+
* @returns This builder, so calls chain.
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```ts
|
|
1274
|
+
* bpmn('order').metadata({ migrationVersion: '11' })
|
|
1275
|
+
* ```
|
|
1276
|
+
*/
|
|
1277
|
+
metadata(meta) {
|
|
1278
|
+
this._metadata = { ...this._metadata, ...meta };
|
|
1279
|
+
return this;
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Declare the Canvas SCHEMA generation this document targets
|
|
1283
|
+
* (`uipath:migrationVersion`).
|
|
1284
|
+
*
|
|
1285
|
+
* @remarks
|
|
1286
|
+
* The same field {@link ProcessMetadata.migrationVersion} sets, under the name
|
|
1287
|
+
* the Flow and Case builders use for the same concept — a document's schema
|
|
1288
|
+
* version, as opposed to anything about the process's own release. Both
|
|
1289
|
+
* spellings stay valid; the later call wins, as with any `.metadata()` field.
|
|
1290
|
+
*
|
|
1291
|
+
* Unlike Flow's file format and Case's grammar, this one does not change what
|
|
1292
|
+
* the serializer emits: the `.bpmn` is the same XML whatever generation is
|
|
1293
|
+
* stamped on it, so any non-empty value is accepted and carried through
|
|
1294
|
+
* verbatim. An empty one is refused, because an empty
|
|
1295
|
+
* `uipath:migrationVersion` fails product validation — absent beats blank.
|
|
1296
|
+
*
|
|
1297
|
+
* `bpmn-decompile` emits this call with the stamp it read, which is what keeps
|
|
1298
|
+
* a decompile → edit → recompile from dropping a generation Studio Web wrote
|
|
1299
|
+
* and some graders require.
|
|
1300
|
+
*
|
|
1301
|
+
* @example
|
|
1302
|
+
* ```ts
|
|
1303
|
+
* bpmn('order').schemaVersion('11.5')
|
|
1304
|
+
* ```
|
|
1305
|
+
*
|
|
1306
|
+
* @param version - The Canvas schema generation, e.g. `'11'` or `'11.5'`.
|
|
1307
|
+
* @returns This builder, so calls chain.
|
|
1308
|
+
* @throws Error when `version` is empty.
|
|
1309
|
+
*/
|
|
1310
|
+
schemaVersion(version) {
|
|
1311
|
+
const refusal = schemaVersionRefusal(BPMN_SCHEMA_VERSIONS, version);
|
|
1312
|
+
if (refusal)
|
|
1313
|
+
throw new Error(refusal);
|
|
1314
|
+
this._metadata = { ...this._metadata, migrationVersion: version };
|
|
1315
|
+
return this;
|
|
1316
|
+
}
|
|
1317
|
+
/** Named schemas declared with `.schema()`, resolved when a row references one. */
|
|
1318
|
+
_schemas = new Map();
|
|
1319
|
+
/**
|
|
1320
|
+
* Name a JSON Schema once so several variables can share it.
|
|
1321
|
+
*
|
|
1322
|
+
* @remarks
|
|
1323
|
+
* Purely a source-level convenience: there is no shared-schema concept on the
|
|
1324
|
+
* wire, so every reference expands back to the same inline body and the emitted
|
|
1325
|
+
* XML is byte-identical either way. What it saves is the source — a real process
|
|
1326
|
+
* repeats a handful of shapes across dozens of variables, and one export carried
|
|
1327
|
+
* 57 schema bodies of which only 13 were distinct.
|
|
1328
|
+
*
|
|
1329
|
+
* `schema: errorSchema` covers the platform's own error envelope, which needs no
|
|
1330
|
+
* declaration at all; this is for the shapes that belong to a particular process.
|
|
1331
|
+
*
|
|
1332
|
+
* @param id - The name to reference it by, in `schema: id`.
|
|
1333
|
+
* @param schema - The JSON Schema, as a value rather than a string.
|
|
1334
|
+
* @returns This builder, so calls chain.
|
|
1335
|
+
*
|
|
1336
|
+
* @example
|
|
1337
|
+
* ```ts
|
|
1338
|
+
* bpmn('orders')
|
|
1339
|
+
* .schema('queueItem', { type: 'object', properties: { Id: { type: 'integer' } } })
|
|
1340
|
+
* .var('response1', 'jsonSchema', { name: 'response', schema: 'queueItem' })
|
|
1341
|
+
* .var('response2', 'jsonSchema', { name: 'response', schema: 'queueItem' })
|
|
1342
|
+
* ```
|
|
1343
|
+
*/
|
|
1344
|
+
schema(id, schema) {
|
|
1345
|
+
this._schemas.set(id, schema);
|
|
1346
|
+
return this;
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Declare an external identifier the process needs supplied — a base URL, a
|
|
1350
|
+
* folder path, a process name (`uipath:binding`). Expressions read it as
|
|
1351
|
+
* `=bindings.<id>`, and an offline run resolves it to `value`.
|
|
1352
|
+
*
|
|
1353
|
+
* @remarks
|
|
1354
|
+
* A connector's `connection`/`folder` already produce their own bindings at
|
|
1355
|
+
* serialize time; this is for everything else, and it is what lets a value be
|
|
1356
|
+
* configured per environment rather than baked into the process. Declaring the
|
|
1357
|
+
* same id twice keeps the FIRST declaration.
|
|
1358
|
+
*
|
|
1359
|
+
* @example
|
|
1360
|
+
* ```ts
|
|
1361
|
+
* bpmn('sync')
|
|
1362
|
+
* .binding('apiBase', { name: 'API base URL', value: 'https://api.example.com' })
|
|
1363
|
+
* .var('url', 'string')
|
|
1364
|
+
* .startEvent('start')
|
|
1365
|
+
* .task('resolve', { set: { url: '=js:bindings.apiBase + "/v1/orders"' } })
|
|
1366
|
+
* ```
|
|
1367
|
+
*
|
|
1368
|
+
* @param id - The binding's id — what `=bindings.<id>` refers to.
|
|
1369
|
+
* @param opts - Display `name`, the `value` it defaults to, and which resource it addresses.
|
|
1370
|
+
* @returns This builder, so calls chain.
|
|
1371
|
+
*/
|
|
1372
|
+
binding(id, opts = {}) {
|
|
1373
|
+
this._bindingRegistry.declare({
|
|
1374
|
+
id,
|
|
1375
|
+
name: opts.name ?? id,
|
|
1376
|
+
resource: opts.resource ?? 'custom',
|
|
1377
|
+
propertyAttribute: opts.propertyAttribute ?? 'value',
|
|
1378
|
+
resourceSubType: opts.resourceSubType,
|
|
1379
|
+
default: opts.value,
|
|
1380
|
+
resourceKey: opts.resourceKey ?? opts.value,
|
|
1381
|
+
});
|
|
1382
|
+
return this;
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Finish the process and return the graph the serializer turns into XML.
|
|
1386
|
+
*
|
|
1387
|
+
* @returns The built process — its elements, flows and variables.
|
|
1388
|
+
*/
|
|
1389
|
+
build() {
|
|
1390
|
+
const built = {
|
|
1391
|
+
id: this._id,
|
|
1392
|
+
name: this._name,
|
|
1393
|
+
metadata: this._metadata,
|
|
1394
|
+
variables: this._vars,
|
|
1395
|
+
messages: this._defs.messages,
|
|
1396
|
+
errors: this._defs.errors,
|
|
1397
|
+
bindings: this._bindingRegistry.bindings,
|
|
1398
|
+
nodes: this._nodes,
|
|
1399
|
+
flows: this._flows,
|
|
1400
|
+
schemas: this._schemas,
|
|
1401
|
+
};
|
|
1402
|
+
// First-level validation, intrinsic to running the SDK: catch a reference to
|
|
1403
|
+
// an undeclared `vars.<name>` HERE — the one thing `uip maestro bpmn validate`
|
|
1404
|
+
// does not check — before the `.bpmn` is serialized. See bpmn-expr-check.
|
|
1405
|
+
const errors = checkBpmnExpressions(built).filter((d) => d.level === 'error');
|
|
1406
|
+
if (errors.length)
|
|
1407
|
+
throw new BpmnBuildError(built, errors);
|
|
1408
|
+
return built;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* The `Error` variable's shape — the platform's own error envelope.
|
|
1413
|
+
*
|
|
1414
|
+
* Every node that can fail writes one, so a real process declares this schema once
|
|
1415
|
+
* per node and an imported one repeats it verbatim: 243 byte-identical copies across
|
|
1416
|
+
* five unrelated customer exports, 27 in a single 71-element process.
|
|
1417
|
+
*
|
|
1418
|
+
* It is a contract, not a convention. `V2EndEventBody.BuildErrorCoreResult` in
|
|
1419
|
+
* PO.BpmnEngine builds it — *"the ErrorEndEvent core result with one `Error` entry
|
|
1420
|
+
* and the six expected fields"* — as `code`, `message`, `detail`, `category`,
|
|
1421
|
+
* `status`, `element`, with `status` an HTTP status code and the rest strings.
|
|
1422
|
+
*
|
|
1423
|
+
* @example
|
|
1424
|
+
* ```ts
|
|
1425
|
+
* bpmn('p').var('error1', 'jsonSchema', { name: 'Error', schema: errorSchema })
|
|
1426
|
+
* ```
|
|
1427
|
+
*
|
|
1428
|
+
* @see errorSchemaWithResponse
|
|
1429
|
+
*/
|
|
1430
|
+
export const errorSchema = {
|
|
1431
|
+
type: 'object',
|
|
1432
|
+
properties: {
|
|
1433
|
+
code: { type: 'string' },
|
|
1434
|
+
message: { type: 'string' },
|
|
1435
|
+
detail: { type: 'string' },
|
|
1436
|
+
category: { type: 'string' },
|
|
1437
|
+
status: { type: 'number' },
|
|
1438
|
+
element: { type: 'string' },
|
|
1439
|
+
},
|
|
1440
|
+
};
|
|
1441
|
+
/**
|
|
1442
|
+
* The same envelope plus `response` — what a node whose failure carries a payload
|
|
1443
|
+
* writes, and what the same source calls *"the generic failure mapping shape, which
|
|
1444
|
+
* includes a `response` key"*, distinguishing it from {@link errorSchema}.
|
|
1445
|
+
*
|
|
1446
|
+
* 42 copies across the corpus, against 243 of the six-field form.
|
|
1447
|
+
*/
|
|
1448
|
+
export const errorSchemaWithResponse = {
|
|
1449
|
+
type: 'object',
|
|
1450
|
+
properties: {
|
|
1451
|
+
...errorSchema.properties,
|
|
1452
|
+
response: { type: 'string' },
|
|
1453
|
+
},
|
|
1454
|
+
};
|
|
1455
|
+
/**
|
|
1456
|
+
* Start building a BPMN process with the given id.
|
|
1457
|
+
*
|
|
1458
|
+
* @example
|
|
1459
|
+
* **A minimal start → task → end process**
|
|
1460
|
+
* ```ts
|
|
1461
|
+
* export default bpmn('intake')
|
|
1462
|
+
* .startEvent('start')
|
|
1463
|
+
* .var('note', 'string', { default: '' })
|
|
1464
|
+
* .task('assign', { set: { note: 'hello' } })
|
|
1465
|
+
* .endEvent('done')
|
|
1466
|
+
* .sequenceFlow('start', 'assign')
|
|
1467
|
+
* .sequenceFlow('assign', 'done')
|
|
1468
|
+
* .build();
|
|
1469
|
+
* ```
|
|
1470
|
+
*
|
|
1471
|
+
* @param id - The process id.
|
|
1472
|
+
* @returns A {@link BpmnBuilder} to add elements to.
|
|
1473
|
+
*/
|
|
1474
|
+
export function bpmn(id) {
|
|
1475
|
+
return new BpmnBuilder(id);
|
|
1476
|
+
}
|