@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.
Files changed (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -0
  3. package/dist/bindings-v2.d.ts +37 -0
  4. package/dist/bindings-v2.js +155 -0
  5. package/dist/bindings.d.ts +6 -0
  6. package/dist/bindings.js +6 -0
  7. package/dist/bpmn/bpmn-expr-check.d.ts +41 -0
  8. package/dist/bpmn/bpmn-expr-check.js +218 -0
  9. package/dist/bpmn/bpmn-sdk.d.ts +2257 -0
  10. package/dist/bpmn/bpmn-sdk.js +1476 -0
  11. package/dist/bpmn/check-cli.d.ts +3 -0
  12. package/dist/bpmn/check-cli.js +32 -0
  13. package/dist/bpmn/check.d.ts +25 -0
  14. package/dist/bpmn/check.js +430 -0
  15. package/dist/bpmn/compile-cli.d.ts +3 -0
  16. package/dist/bpmn/compile-cli.js +60 -0
  17. package/dist/bpmn/connector.d.ts +56 -0
  18. package/dist/bpmn/connector.js +199 -0
  19. package/dist/bpmn/decompile-cli.d.ts +8 -0
  20. package/dist/bpmn/decompile-cli.js +54 -0
  21. package/dist/bpmn/decompile.d.ts +6 -0
  22. package/dist/bpmn/decompile.js +1108 -0
  23. package/dist/bpmn/format-profile.d.ts +27 -0
  24. package/dist/bpmn/format-profile.js +11 -0
  25. package/dist/bpmn/intsvc.d.ts +77 -0
  26. package/dist/bpmn/intsvc.js +155 -0
  27. package/dist/bpmn/load.d.ts +4 -0
  28. package/dist/bpmn/load.js +22 -0
  29. package/dist/bpmn/merge-cli.d.ts +3 -0
  30. package/dist/bpmn/merge-cli.js +45 -0
  31. package/dist/bpmn/merge.d.ts +19 -0
  32. package/dist/bpmn/merge.js +293 -0
  33. package/dist/bpmn/registry-types.json +1869 -0
  34. package/dist/bpmn/serialize.d.ts +28 -0
  35. package/dist/bpmn/serialize.js +757 -0
  36. package/dist/bpmn/tidy-cli.d.ts +2 -0
  37. package/dist/bpmn/tidy-cli.js +39 -0
  38. package/dist/bpmn/typed-node.d.ts +382 -0
  39. package/dist/bpmn/typed-node.js +551 -0
  40. package/dist/bpmn/uipath-moddle.v1.json +823 -0
  41. package/dist/bpmn/xml-ranges.d.ts +45 -0
  42. package/dist/bpmn/xml-ranges.js +151 -0
  43. package/dist/case/case-expr-check.d.ts +35 -0
  44. package/dist/case/case-expr-check.js +85 -0
  45. package/dist/case/case-sdk.d.ts +1282 -0
  46. package/dist/case/case-sdk.js +923 -0
  47. package/dist/case/check-cli.d.ts +3 -0
  48. package/dist/case/check-cli.js +31 -0
  49. package/dist/case/check.d.ts +18 -0
  50. package/dist/case/check.js +456 -0
  51. package/dist/case/compile-cli.d.ts +3 -0
  52. package/dist/case/compile-cli.js +291 -0
  53. package/dist/case/decompile-cli.d.ts +9 -0
  54. package/dist/case/decompile-cli.js +117 -0
  55. package/dist/case/decompile.d.ts +187 -0
  56. package/dist/case/decompile.js +1170 -0
  57. package/dist/case/entry-points.d.ts +79 -0
  58. package/dist/case/entry-points.js +118 -0
  59. package/dist/case/format-profile.d.ts +60 -0
  60. package/dist/case/format-profile.js +79 -0
  61. package/dist/case/ids.d.ts +24 -0
  62. package/dist/case/ids.js +76 -0
  63. package/dist/case/load.d.ts +12 -0
  64. package/dist/case/load.js +32 -0
  65. package/dist/case/preserve.d.ts +133 -0
  66. package/dist/case/preserve.js +105 -0
  67. package/dist/case/serialize.d.ts +10 -0
  68. package/dist/case/serialize.js +1414 -0
  69. package/dist/check-cli.d.ts +3 -0
  70. package/dist/check-cli.js +118 -0
  71. package/dist/check.d.ts +146 -0
  72. package/dist/check.js +4898 -0
  73. package/dist/cli/commands/bpmn.d.ts +2 -0
  74. package/dist/cli/commands/bpmn.js +73 -0
  75. package/dist/cli/commands/case.d.ts +2 -0
  76. package/dist/cli/commands/case.js +60 -0
  77. package/dist/cli/commands/flow.d.ts +2 -0
  78. package/dist/cli/commands/flow.js +99 -0
  79. package/dist/cli/commands/registry.d.ts +10 -0
  80. package/dist/cli/commands/registry.js +170 -0
  81. package/dist/cli/common.d.ts +30 -0
  82. package/dist/cli/common.js +92 -0
  83. package/dist/cli/index.d.ts +2 -0
  84. package/dist/cli/index.js +18 -0
  85. package/dist/cli-run.d.ts +2 -0
  86. package/dist/cli-run.js +42 -0
  87. package/dist/compile-cli.d.ts +3 -0
  88. package/dist/compile-cli.js +160 -0
  89. package/dist/config.d.ts +47 -0
  90. package/dist/config.js +201 -0
  91. package/dist/core/actions.d.ts +3244 -0
  92. package/dist/core/actions.js +1062 -0
  93. package/dist/core/binding-messages.d.ts +1 -0
  94. package/dist/core/binding-messages.js +16 -0
  95. package/dist/core/bindings.d.ts +12 -0
  96. package/dist/core/bindings.js +67 -0
  97. package/dist/core/ceql.d.ts +73 -0
  98. package/dist/core/ceql.js +272 -0
  99. package/dist/core/cli-spelling.d.ts +39 -0
  100. package/dist/core/cli-spelling.js +62 -0
  101. package/dist/core/connector-raw-node.d.ts +21 -0
  102. package/dist/core/connector-raw-node.js +47 -0
  103. package/dist/core/connectors.d.ts +184 -0
  104. package/dist/core/connectors.js +128 -0
  105. package/dist/core/expr-check.d.ts +93 -0
  106. package/dist/core/expr-check.js +186 -0
  107. package/dist/core/expr.d.ts +323 -0
  108. package/dist/core/expr.js +400 -0
  109. package/dist/core/index.d.ts +10 -0
  110. package/dist/core/index.js +10 -0
  111. package/dist/core/library.d.ts +440 -0
  112. package/dist/core/library.js +1183 -0
  113. package/dist/core/list-envelope.d.ts +45 -0
  114. package/dist/core/list-envelope.js +97 -0
  115. package/dist/core/lookup-store.d.ts +22 -0
  116. package/dist/core/lookup-store.js +85 -0
  117. package/dist/core/lookups.d.ts +227 -0
  118. package/dist/core/lookups.js +231 -0
  119. package/dist/core/node-classes.d.ts +234 -0
  120. package/dist/core/node-classes.js +158 -0
  121. package/dist/core/script-return.d.ts +68 -0
  122. package/dist/core/script-return.js +197 -0
  123. package/dist/core/stable-id.d.ts +28 -0
  124. package/dist/core/stable-id.js +37 -0
  125. package/dist/core-definitions.json +16249 -0
  126. package/dist/decompile-cli.d.ts +3 -0
  127. package/dist/decompile-cli.js +131 -0
  128. package/dist/decompile.d.ts +138 -0
  129. package/dist/decompile.js +2482 -0
  130. package/dist/emit.d.ts +10 -0
  131. package/dist/emit.js +60 -0
  132. package/dist/event-filters.d.ts +130 -0
  133. package/dist/event-filters.js +137 -0
  134. package/dist/flow-expr-check.d.ts +17 -0
  135. package/dist/flow-expr-check.js +193 -0
  136. package/dist/flow-sdk.d.ts +1341 -0
  137. package/dist/flow-sdk.js +1164 -0
  138. package/dist/flow-variables.d.ts +13 -0
  139. package/dist/flow-variables.js +42 -0
  140. package/dist/format-profile.d.ts +72 -0
  141. package/dist/format-profile.js +97 -0
  142. package/dist/generators/_connections.py +287 -0
  143. package/dist/generators/_events.py +355 -0
  144. package/dist/generators/_lookups.py +114 -0
  145. package/dist/generators/_naming.py +185 -0
  146. package/dist/generators/_objects.py +299 -0
  147. package/dist/generators/_resolve.py +273 -0
  148. package/dist/generators/convert_library_to_md.py +1441 -0
  149. package/dist/generators/extract_library.py +125 -0
  150. package/dist/generators/generate_connectors_ts.py +936 -0
  151. package/dist/generators/generate_library_json.py +2527 -0
  152. package/dist/generators/generate_triggers_ts.py +110 -0
  153. package/dist/generators/materialize_registry.py +155 -0
  154. package/dist/generators/prepare_connector.py +1688 -0
  155. package/dist/index.d.ts +35 -0
  156. package/dist/index.js +35 -0
  157. package/dist/ixp-definition.json +1982 -0
  158. package/dist/library.d.ts +6 -0
  159. package/dist/library.js +6 -0
  160. package/dist/load.d.ts +16 -0
  161. package/dist/load.js +95 -0
  162. package/dist/merge-cli.d.ts +3 -0
  163. package/dist/merge-cli.js +47 -0
  164. package/dist/merge.d.ts +125 -0
  165. package/dist/merge.js +0 -0
  166. package/dist/migrate.d.ts +15 -0
  167. package/dist/migrate.js +245 -0
  168. package/dist/node-runtime.d.ts +3 -0
  169. package/dist/node-runtime.js +22 -0
  170. package/dist/package-name.d.ts +17 -0
  171. package/dist/package-name.js +17 -0
  172. package/dist/ref-resolve.d.ts +77 -0
  173. package/dist/ref-resolve.js +170 -0
  174. package/dist/registry/cache.d.ts +55 -0
  175. package/dist/registry/cache.js +134 -0
  176. package/dist/registry/curated-overlay.d.ts +16 -0
  177. package/dist/registry/curated-overlay.js +62 -0
  178. package/dist/registry/extractor.d.ts +22 -0
  179. package/dist/registry/extractor.js +18 -0
  180. package/dist/registry/materialize-bin.d.ts +2 -0
  181. package/dist/registry/materialize-bin.js +7 -0
  182. package/dist/registry/materialize-cli.d.ts +1 -0
  183. package/dist/registry/materialize-cli.js +46 -0
  184. package/dist/registry/materializer.d.ts +23 -0
  185. package/dist/registry/materializer.js +34 -0
  186. package/dist/registry/path-cli.d.ts +1 -0
  187. package/dist/registry/path-cli.js +56 -0
  188. package/dist/registry/prepare-cli.d.ts +62 -0
  189. package/dist/registry/prepare-cli.js +185 -0
  190. package/dist/registry/pull-cli.d.ts +1 -0
  191. package/dist/registry/pull-cli.js +274 -0
  192. package/dist/registry/python.d.ts +26 -0
  193. package/dist/registry/python.js +46 -0
  194. package/dist/registry/search-cli.d.ts +52 -0
  195. package/dist/registry/search-cli.js +159 -0
  196. package/dist/schema-version.d.ts +165 -0
  197. package/dist/schema-version.js +148 -0
  198. package/dist/serialize.d.ts +64 -0
  199. package/dist/serialize.js +6398 -0
  200. package/lib/README.md +112 -0
  201. package/lib/library-json.samples/index.json +158 -0
  202. package/lib/library-json.samples/invariant-collections.json +83 -0
  203. package/lib/library-json.samples/list-envelopes.json +123 -0
  204. package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.json +131 -0
  205. package/lib/library-json.samples/uipath-atlassian-jira/create-issue@1.0.0.v1def.json +306 -0
  206. package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.json +86 -0
  207. package/lib/library-json.samples/uipath-atlassian-jira/generic/create_issue/create@1.0.0.v1def.json +208 -0
  208. package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.json +2040 -0
  209. package/lib/library-json.samples/uipath-atlassian-jira/get-issue@1.0.0.v1def.json +195 -0
  210. package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.json +169 -0
  211. package/lib/library-json.samples/uipath-google-vertex/execute-google-vertex-agent@1.0.0.v1def.json +209 -0
  212. package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.json +63 -0
  213. package/lib/library-json.samples/uipath-http-webhook/event-http-webhook@1.0.0.v1def.json +262 -0
  214. package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.json +63 -0
  215. package/lib/library-json.samples/uipath-http-webhook/trigger-http-webhook@1.0.0.v1def.json +213 -0
  216. package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.json +227 -0
  217. package/lib/library-json.samples/uipath-microsoft-azureactivedirectory/list-groups@1.0.0.v1def.json +373 -0
  218. package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.json +116 -0
  219. package/lib/library-json.samples/uipath-microsoft-onedrive/event-file-created@1.0.0.v1def.json +369 -0
  220. package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.json +56 -0
  221. package/lib/library-json.samples/uipath-microsoft-onedrive/event-list-item-added@1.0.0.v1def.json +256 -0
  222. package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.json +116 -0
  223. package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-file-created@1.0.0.v1def.json +320 -0
  224. package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.json +56 -0
  225. package/lib/library-json.samples/uipath-microsoft-onedrive/trigger-list-item-added@1.0.0.v1def.json +207 -0
  226. package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.json +107 -0
  227. package/lib/library-json.samples/uipath-microsoft-outlook365/event-email-received@1.0.0.v1def.json +264 -0
  228. package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.json +142 -0
  229. package/lib/library-json.samples/uipath-microsoft-outlook365/send-email@1.0.0.v1def.json +306 -0
  230. package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.json +107 -0
  231. package/lib/library-json.samples/uipath-microsoft-outlook365/trigger-email-received@1.0.0.v1def.json +217 -0
  232. package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.json +85 -0
  233. package/lib/library-json.samples/uipath-microsoft-powerautomate/invoke-a-microsoft-power-automate-flow@1.0.0.v1def.json +209 -0
  234. package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.json +755 -0
  235. package/lib/library-json.samples/uipath-salesforce-slack/send-message-to-user@1.0.0.v1def.json +513 -0
  236. package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.json +122 -0
  237. package/lib/library-json.samples/uipath-uipath-dataservice/query-entity-records@1.0.0.v1def.json +227 -0
  238. package/package.json +85 -0
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { type CliExitCode } from '../cli-run.js';
3
+ export declare function run(argv: string[]): Promise<CliExitCode>;
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * check-cli — fast static validation of a <Name>.bpmn.ts (no output file).
4
+ *
5
+ * Usage:
6
+ * node --experimental-strip-types check-cli.js <bpmn.ts | BaseName>
7
+ *
8
+ * Exit 0 = clean; exit 1 = at least one error. Warnings print but do not fail.
9
+ */
10
+ import { resolveBpmnFile, loadBuiltBpmn } from './load.js';
11
+ import { check } from './check.js';
12
+ import { runWhenInvokedDirectly } from '../cli-run.js';
13
+ import { ensureTypeScriptRuntime } from '../node-runtime.js';
14
+ export async function run(argv) {
15
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
16
+ console.error('usage: check <bpmn.ts | BaseName>');
17
+ return 2;
18
+ }
19
+ ensureTypeScriptRuntime();
20
+ const built = await loadBuiltBpmn(resolveBpmnFile(argv[0]));
21
+ const diags = check(built);
22
+ for (const d of diags)
23
+ console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
24
+ const errors = diags.filter((d) => d.level === 'error').length;
25
+ if (errors) {
26
+ console.error(`check: ${errors} error(s).`);
27
+ return 1;
28
+ }
29
+ console.error(`check: ok${diags.length ? ` (${diags.length} warning(s))` : ''}.`);
30
+ return 0;
31
+ }
32
+ runWhenInvokedDirectly(import.meta.url, 'check', run);
@@ -0,0 +1,25 @@
1
+ /**
2
+ * bpmn/check — fast static validation of a BuiltBpmn before serialization.
3
+ *
4
+ * Surfaces the common Maestro canvas-rule failures early (dangling flow refs,
5
+ * duplicate ids, a gateway branch with no condition, a superfluous gateway, an
6
+ * implicit join, a missing start event, a boundary event attached to nothing, an
7
+ * empty timer) so authoring gets instant feedback. The authoritative gate is
8
+ * still `uip maestro bpmn validate` (`validateBpmnCanvas`) on the emitted
9
+ * `.bpmn`.
10
+ *
11
+ * **An `error` here must mirror a real platform rule.** Being stricter than
12
+ * `validate` is worse than being looser: it refuses processes that deploy and run
13
+ * correctly, and the author has no way to appeal. Where this file is deliberately
14
+ * stricter than the platform — an unconditioned inclusive-gateway branch, an
15
+ * implicit join — the diagnostic is a `warning`, and its comment says which
16
+ * platform rule it corresponds to and how the two differ.
17
+ */
18
+ import type { BuiltBpmn } from './bpmn-sdk.js';
19
+ export interface Diagnostic {
20
+ level: 'error' | 'warning';
21
+ code: string;
22
+ message: string;
23
+ where?: string;
24
+ }
25
+ export declare function check(built: BuiltBpmn): Diagnostic[];
@@ -0,0 +1,430 @@
1
+ import { processId } from './serialize.js';
2
+ import { bindingRequiredFields, missingRequiredContext, missingRequiredInputs, registryType, REGISTRY_GAPS, unsatisfiableRequiredInputs, } from './typed-node.js';
3
+ const GATEWAY_KINDS = new Set(['exclusiveGateway', 'parallelGateway', 'inclusiveGateway', 'eventBasedGateway']);
4
+ /**
5
+ * What a boundary event may attach to. `connector` belongs here: it serializes to
6
+ * a `bpmn:sendTask`, which is an activity like any other, and catching a
7
+ * connector's failure is the commonest error-handling shape there is.
8
+ */
9
+ const ACTIVITY_KINDS = new Set(['task', 'scriptTask', 'subProcess', 'connector', 'typed', 'connectorEvent', 'externalTask']);
10
+ export function check(built) {
11
+ const diags = [];
12
+ if (!built.id)
13
+ diags.push({ level: 'error', code: 'NO_ID', message: 'bpmn() requires an id.' });
14
+ const seenIds = new Set();
15
+ checkScope(built.nodes, built.flows, 'process', diags, seenIds, true);
16
+ checkScopedVars(built, diags);
17
+ checkDocumentIds(built, diags);
18
+ return diags;
19
+ }
20
+ /**
21
+ * Every `id` in the document must be unique — including across KINDS.
22
+ *
23
+ * Not a style rule. `bpmn-moddle` keeps one document-global id registry, so a
24
+ * second use of an id makes its whole element **unparsable**, and it drops it:
25
+ *
26
+ * unparsable content <bpmn:task> detected … nested error: duplicate ID <after>
27
+ *
28
+ * `.var('after', …)` next to `.task('after', …)` therefore emits a `.bpmn` whose
29
+ * task simply is not there. Both validators still pass it — the canvas one
30
+ * downgrades the now-dangling flows to warnings and `uip maestro bpmn validate`
31
+ * reports `Valid` — and the runtime then dies with `Unknown element 'after'`, or
32
+ * worse, silently does no work if nothing else routes through the hole. So this
33
+ * is the only gate that can catch it, and it has to be an error.
34
+ *
35
+ * The ids in play are every element and flow, every variable and binding, the
36
+ * synthesized `Message_n`/`Error_n` declarations, and the process itself.
37
+ */
38
+ function checkDocumentIds(built, diags) {
39
+ const owners = new Map();
40
+ const claim = (id, kind) => {
41
+ const existing = owners.get(id);
42
+ if (existing === undefined) {
43
+ owners.set(id, kind);
44
+ return;
45
+ }
46
+ diags.push({
47
+ level: 'error',
48
+ code: 'DUPLICATE_DOCUMENT_ID',
49
+ message: `id "${id}" is used by both ${existing} and ${kind}. Every id in a .bpmn must be unique — ` +
50
+ `the XML parser drops the second element that reuses one, so it disappears from the process.`,
51
+ where: id,
52
+ });
53
+ };
54
+ claim(built.id, 'the process');
55
+ const walk = (nodes, flows) => {
56
+ for (const n of nodes) {
57
+ claim(n.id, `element "${n.id}"`);
58
+ if (n.kind === 'subProcess') {
59
+ for (const v of n.variables)
60
+ claim(v.id, `variable "${v.id}"`);
61
+ walk(n.nodes, n.flows);
62
+ }
63
+ }
64
+ for (const f of flows)
65
+ claim(f.id, `flow "${f.id}"`);
66
+ };
67
+ walk(built.nodes, built.flows);
68
+ for (const v of built.variables)
69
+ claim(v.id, `variable "${v.id}"`);
70
+ for (const b of built.bindings)
71
+ claim(b.id, `binding "${b.id}"`);
72
+ for (const mm of built.messages)
73
+ claim(mm.id, `message "${mm.name}"`);
74
+ for (const e of built.errors)
75
+ claim(e.id, `error "${e.name}"`);
76
+ }
77
+ /**
78
+ * A variable scoped with `elementId` must name an element that exists.
79
+ *
80
+ * The runtime resolves the scope by id and has nothing to fall back on, so a typo
81
+ * makes the variable unreachable — silently, with no diagnostic anywhere else.
82
+ */
83
+ function checkScopedVars(built, diags) {
84
+ const ids = new Set();
85
+ const walk = (nodes) => {
86
+ for (const n of nodes) {
87
+ ids.add(n.id);
88
+ if (n.kind === 'subProcess')
89
+ walk(n.nodes);
90
+ }
91
+ };
92
+ walk(built.nodes);
93
+ // The PROCESS is a legal scope for a variable, and its id is not a flow element,
94
+ // so it has to be added by hand. Real exports scope variables to it — the ones
95
+ // an author declares on the canvas rather than on a node — and every one of them
96
+ // was reported as scoped to an element that does not exist.
97
+ ids.add(processId(built.id));
98
+ const allVars = [...built.variables];
99
+ const collect = (nodes) => {
100
+ for (const n of nodes) {
101
+ if (n.kind !== 'subProcess')
102
+ continue;
103
+ allVars.push(...n.variables);
104
+ collect(n.nodes);
105
+ }
106
+ };
107
+ collect(built.nodes);
108
+ for (const v of allVars) {
109
+ if (v.elementId !== undefined && !ids.has(v.elementId))
110
+ diags.push({
111
+ level: 'error',
112
+ code: 'SCOPED_VAR_UNKNOWN_ELEMENT',
113
+ message: `Variable "${v.id}" is scoped to element "${v.elementId}", which does not exist.`,
114
+ where: v.id,
115
+ });
116
+ }
117
+ }
118
+ /**
119
+ * A duration the RUNTIME can parse — days/hours/minutes/seconds only.
120
+ *
121
+ * Deliberately narrower than ISO-8601: the runtime's duration parser accepts
122
+ * `P[nD][T[nH][nM][nS]]` and nothing else, so a spec-legal `P1W` or `P1Y` is
123
+ * accepted by `validate` and then fails at run time. Same reason the canvas has
124
+ * its own `TIMER_DURATION_WEEK_UNSUPPORTED` rule.
125
+ */
126
+ const RUNTIME_DURATION = /^P(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/i;
127
+ function isRuntimeDuration(v) {
128
+ // A bare `P`/`PT` matches the shape but carries no components — the same
129
+ // "validates, then no runtime can parse it" trap the timer eval card exists for.
130
+ return RUNTIME_DURATION.test(v) && /\d/.test(v);
131
+ }
132
+ /** Retry and loop options, checked per activity. */
133
+ function checkActivityFields(n, diags) {
134
+ // A script task whose body is missing or blank. The wire form of a script task IS its
135
+ // `<bpmn:script>` body, so without one the emitter writes an activity that parses,
136
+ // validates and runs — and does nothing. Every gate stays green: `check` passed, the
137
+ // compile succeeded, `uip maestro bpmn validate` returned Success, and the emitted file
138
+ // contained zero `<bpmn:script>` elements. The failure only shows up as a variable that
139
+ // never changed, which is the hardest kind of wrong to attribute.
140
+ //
141
+ // Reachable from ordinary authoring: `script` is a required field, but passing the body
142
+ // under any other key (a plausible `body:`) satisfies the runtime object while leaving
143
+ // `script` undefined, and TypeScript only catches that when the author is compiling
144
+ // types rather than running the file.
145
+ if (n.kind === 'scriptTask' && (n.script === undefined || n.script.trim() === ''))
146
+ diags.push({
147
+ level: 'error',
148
+ code: 'SCRIPT_TASK_NO_BODY',
149
+ message: `Script task "${n.id}" has no script body, so it would emit an activity that runs and does nothing. ` +
150
+ `Pass the Jint JavaScript as \`script\` (\`.scriptTask('${n.id}', { script: 'return { … };' })\`).`,
151
+ where: n.id,
152
+ });
153
+ if (!('retry' in n) && !('loop' in n))
154
+ return;
155
+ const retry = 'retry' in n ? n.retry : undefined;
156
+ if (retry) {
157
+ if (!Number.isInteger(retry.maxRetries) || retry.maxRetries < 1)
158
+ diags.push({
159
+ level: 'error',
160
+ code: 'RETRY_INVALID_COUNT',
161
+ message: `Retry on "${n.id}" needs maxRetries to be a positive integer (got ${retry.maxRetries}); the runtime ignores a policy with fewer.`,
162
+ where: n.id,
163
+ });
164
+ for (const [field, value] of [
165
+ ['backoff', retry.backoff],
166
+ ['maxDuration', retry.maxDuration],
167
+ ]) {
168
+ if (value !== undefined && !isRuntimeDuration(value))
169
+ diags.push({
170
+ level: 'error',
171
+ code: 'RETRY_INVALID_DURATION',
172
+ message: `Retry ${field} on "${n.id}" is "${value}"; the runtime parses days/hours/minutes/seconds only, e.g. "PT30S" or "P1DT12H".`,
173
+ where: n.id,
174
+ });
175
+ }
176
+ if (retry.exponentialBase !== undefined && retry.backoffType !== 'exponential')
177
+ diags.push({
178
+ level: 'warning',
179
+ code: 'RETRY_BASE_WITHOUT_EXPONENTIAL',
180
+ message: `Retry on "${n.id}" sets exponentialBase but backoffType is not 'exponential', so it has no effect.`,
181
+ where: n.id,
182
+ });
183
+ }
184
+ const loop = 'loop' in n ? n.loop : undefined;
185
+ if (loop) {
186
+ if (!loop.collection)
187
+ diags.push({ level: 'error', code: 'LOOP_NO_COLLECTION', message: `Loop on "${n.id}" needs a collection expression.`, where: n.id });
188
+ if (!loop.itemVar)
189
+ diags.push({ level: 'error', code: 'LOOP_NO_ITEM_VAR', message: `Loop on "${n.id}" needs an itemVar to bind each item to.`, where: n.id });
190
+ // The local engine now HONOURS a completion condition, but only on a sequential
191
+ // loop. A parallel loop has dispatched every iteration before the first could
192
+ // report, so there is nothing left to stop — BPMN's answer is to cancel the
193
+ // remaining instances, which the engine does not implement. So the warning
194
+ // narrowed from "never evaluated" to exactly the case that is still not.
195
+ if (loop.completion !== undefined && loop.sequential !== true)
196
+ diags.push({
197
+ level: 'warning',
198
+ code: 'LOOP_COMPLETION_NOT_LOCAL',
199
+ message: `Loop completion on "${n.id}" is emitted for the platform but NOT evaluated by the local engine on a ` +
200
+ `PARALLEL loop, so a local run iterates the whole collection. Set \`sequential: true\` to have it honoured locally.`,
201
+ where: n.id,
202
+ });
203
+ }
204
+ }
205
+ function checkScope(nodes, flows, where, diags, seenIds, isTop,
206
+ /**
207
+ * Whether the CONTAINER of these nodes is an event sub-process. The process root
208
+ * never is, so it defaults false — see ERROR_START_OUTSIDE_EVENT_SUBPROCESS below.
209
+ */
210
+ inEventSubProcess = false) {
211
+ const nodeIds = new Set();
212
+ for (const n of nodes)
213
+ nodeIds.add(n.id);
214
+ // Duplicate ids (globally across the document).
215
+ for (const n of nodes)
216
+ dupId(n.id, seenIds, diags, where);
217
+ for (const f of flows)
218
+ dupId(f.id, seenIds, diags, where);
219
+ // At least one start event per scope that has any nodes.
220
+ //
221
+ // "Start event" is the ELEMENT, not the builder kind. A registry-backed node can
222
+ // be one too — `Intsvc.TimerTrigger` and `Intsvc.EventTrigger` both serialize to
223
+ // `bpmn:StartEvent` — and keying off `kind === 'startEvent'` alone reported
224
+ // NO_START on a process that has one, refusing an artifact the platform accepts.
225
+ if (nodes.length && !nodes.some(isStartElement))
226
+ diags.push({ level: isTop ? 'error' : 'warning', code: 'NO_START', message: `${where} has no start event.`, where });
227
+ // Flow endpoints must resolve within this scope.
228
+ for (const f of flows) {
229
+ if (!nodeIds.has(f.source))
230
+ diags.push({ level: 'error', code: 'DANGLING_FLOW', message: `Flow "${f.id}" source "${f.source}" is not an element in ${where}.`, where: f.id });
231
+ if (!nodeIds.has(f.target))
232
+ diags.push({ level: 'error', code: 'DANGLING_FLOW', message: `Flow "${f.id}" target "${f.target}" is not an element in ${where}.`, where: f.id });
233
+ }
234
+ const outgoing = new Map();
235
+ const incomingCount = new Map();
236
+ for (const f of flows) {
237
+ const outs = outgoing.get(f.source) ?? [];
238
+ outs.push(f);
239
+ outgoing.set(f.source, outs);
240
+ incomingCount.set(f.target, (incomingCount.get(f.target) ?? 0) + 1);
241
+ }
242
+ for (const n of nodes) {
243
+ const outs = outgoing.get(n.id) ?? [];
244
+ const ins = incomingCount.get(n.id) ?? 0;
245
+ // Exclusive/inclusive gateways: every non-default outgoing needs a condition —
246
+ // but only where the platform requires it. Its rule
247
+ // (ConditionalFlowRule/validateConditionalSequenceFlow) fires for a
248
+ // `bpmn:ExclusiveGateway` with MORE THAN ONE outgoing flow. A gateway with one
249
+ // outgoing flow is a JOIN, and its single flow is unconditional by definition;
250
+ // demanding a condition there refused a shape the platform validates and the
251
+ // runtime executes, leaving `default` as a misleading workaround. Inclusive
252
+ // gateways are outside the platform's rule, so an unconditioned branch there is
253
+ // a warning — suspicious, not invalid.
254
+ if (n.kind === 'exclusiveGateway' || n.kind === 'inclusiveGateway') {
255
+ if (n.default !== undefined && !outs.some((o) => o.id === n.default))
256
+ diags.push({ level: 'error', code: 'BAD_DEFAULT', message: `Gateway "${n.id}" default "${n.default}" is not one of its outgoing flows.`, where: n.id });
257
+ if (outs.length > 1) {
258
+ const level = n.kind === 'exclusiveGateway' ? 'error' : 'warning';
259
+ for (const o of outs)
260
+ if (o.id !== n.default && o.condition === undefined)
261
+ diags.push({ level, code: 'MISSING_CONDITION_EXPRESSION', message: `Outgoing flow "${o.id}" of gateway "${n.id}" has no condition.`, where: o.id });
262
+ }
263
+ }
264
+ // A gateway with exactly one in and one out is superfluous.
265
+ if (GATEWAY_KINDS.has(n.kind) && ins === 1 && outs.length === 1)
266
+ diags.push({ level: 'warning', code: 'SUPERFLUOUS_GATEWAY', message: `Gateway "${n.id}" has one incoming and one outgoing flow; remove it.`, where: n.id });
267
+ // An activity or event with >1 incoming flow is an implicit join. A WARNING,
268
+ // not an error: the platform's FAKE_JOIN rule only matches the abstract types
269
+ // `bpmn:Activity`/`bpmn:Event`, which never appear on real exported BPMN, so
270
+ // the rule is dormant there and an implicit merge validates and runs. Joining
271
+ // through a gateway is still the clearer shape, hence the nudge.
272
+ if (!GATEWAY_KINDS.has(n.kind) && n.kind !== 'boundaryEvent' && ins > 1)
273
+ diags.push({
274
+ level: 'warning',
275
+ code: 'FAKE_JOIN',
276
+ message: `"${n.id}" has ${ins} incoming flows; the platform accepts this, but joining with a gateway is clearer.`,
277
+ where: n.id,
278
+ });
279
+ // Boundary events must attach to an activity in the same scope.
280
+ if (n.kind === 'boundaryEvent') {
281
+ const target = nodes.find((x) => x.id === n.attachedTo);
282
+ if (!target)
283
+ diags.push({ level: 'error', code: 'BOUNDARY_UNATTACHED', message: `Boundary event "${n.id}" attaches to unknown element "${n.attachedTo}".`, where: n.id });
284
+ else if (!ACTIVITY_KINDS.has(target.kind))
285
+ diags.push({ level: 'error', code: 'BOUNDARY_NOT_ACTIVITY', message: `Boundary event "${n.id}" must attach to an activity, not "${target.kind}".`, where: n.id });
286
+ }
287
+ // A timer event definition needs one of duration/date/cycle.
288
+ // An error START event only means something inside an event sub-process: that is
289
+ // BPMN's construct for catching an error thrown elsewhere in the same container.
290
+ // At the process root nothing can throw into it, so the whole handler branch is
291
+ // unreachable — and `uip maestro bpmn validate` accepts it silently, so without
292
+ // this the author's first clue is a handler that never runs on a real failure.
293
+ if (n.kind === 'startEvent' && n.event?.type === 'error' && !inEventSubProcess) {
294
+ diags.push({
295
+ level: 'error',
296
+ code: 'ERROR_START_OUTSIDE_EVENT_SUBPROCESS',
297
+ message: `Error start event "${n.id}" is not inside an event sub-process, so nothing can throw into it. ` +
298
+ 'Put it in `.subProcess(id, fn, { triggeredByEvent: true })` as that scope\'s single start event.',
299
+ where: n.id,
300
+ });
301
+ }
302
+ if (n.kind !== 'subProcess' && 'event' in n && n.event?.type === 'timer') {
303
+ const t = n.event.timer;
304
+ if (t.duration === undefined && t.date === undefined && t.cycle === undefined)
305
+ diags.push({ level: 'error', code: 'TIMER_MISSING_FIELD', message: `Timer on "${n.id}" needs a duration, date, or cycle.`, where: n.id });
306
+ }
307
+ // Retry / loop options on any activity.
308
+ checkActivityFields(n, diags);
309
+ // A registry-backed node's required context fields. This is what
310
+ // `uip maestro bpmn validate` reports as EMPTY_REQUIRED_FIELD; hearing it from
311
+ // the SDK is faster, and the registry snapshot already knows the answer.
312
+ if (n.kind === 'typed') {
313
+ // Fields the platform insists be `=bindings.<id>` references rather than
314
+ // literals. The typed builder methods bind these automatically, so this
315
+ // fires on a hand-built node or a family whose wrapper forgot — which is
316
+ // exactly when the CLI would otherwise be the one to say so
317
+ // (`context input "name" must reference project bindings`).
318
+ // Context reaches a node two ways — see the note on `contextNames` below; a
319
+ // binding declared in a verbatim row is still a binding.
320
+ const contextView = { ...n.context };
321
+ for (const row of n.contextRows ?? [])
322
+ contextView[row.name] = row.value ?? row.body ?? '';
323
+ for (const field of bindingRequiredFields(n.type)) {
324
+ const value = contextView[field.name];
325
+ if (typeof value === 'string' && value.startsWith('=bindings.'))
326
+ continue;
327
+ diags.push({
328
+ level: 'error',
329
+ code: 'BINDING_REQUIRED',
330
+ message: `"${n.id}" (${n.type}) field "${field.name}" must reference a binding ` +
331
+ `(=bindings.<id>) targeting resource "${field.bindingInfo?.resource}" / ` +
332
+ `"${field.bindingInfo?.propertyAttribute}", not a literal.`,
333
+ where: n.id,
334
+ });
335
+ }
336
+ // Context reaches a node two ways — the `context` record, or the verbatim
337
+ // `contextRows` an importer uses when a row carries detail the record cannot
338
+ // hold (its own type, a `target`, or the absence of a value). Both are context,
339
+ // so both satisfy a required field.
340
+ //
341
+ // Reading only the record meant an imported node whose rows happened to need
342
+ // spelling out reported EVERY required field missing — on an artifact that
343
+ // carries all of them. `contextRowsNeedSpellingOut` decides which form decompile
344
+ // emits, so whether this fired depended on a detail of the source document that
345
+ // has nothing to do with whether the field is set.
346
+ const contextNames = contextView;
347
+ for (const field of missingRequiredContext(n.type, contextNames)) {
348
+ diags.push({
349
+ level: 'error',
350
+ code: 'EMPTY_REQUIRED_FIELD',
351
+ message: `"${n.id}" (${n.type}) is missing required field "${field}".`,
352
+ where: n.id,
353
+ });
354
+ }
355
+ // The same rule over the PAYLOAD fields — the platform's RequiredFieldsRule
356
+ // draws on both, so an unset required input is the same EMPTY_REQUIRED_FIELD.
357
+ for (const field of missingRequiredInputs(n.type, n.inputs, contextNames)) {
358
+ diags.push({
359
+ level: 'error',
360
+ code: 'EMPTY_REQUIRED_FIELD',
361
+ message: `"${n.id}" (${n.type}) is missing required input "${field}".`,
362
+ where: n.id,
363
+ });
364
+ }
365
+ // A type that permits only the output row its spec declares. Reachable via
366
+ // the generic `.activity()`; the typed wrapper does not offer the option.
367
+ if (REGISTRY_GAPS[n.type]?.outputRowsFixed && Object.keys(n.outputs ?? {}).length) {
368
+ diags.push({
369
+ level: 'error',
370
+ code: 'OUTPUT_ROWS_FIXED',
371
+ message: `"${n.id}" (${n.type}) permits only its declared output row, so the extra row(s) ` +
372
+ `${Object.keys(n.outputs ?? {}).map((k) => `"${k}"`).join(', ')} will be refused ` +
373
+ `("output name must be \\"${registryType(n.type).output?.name}\\""). Use outputVar and read the ` +
374
+ `typed row instead.`,
375
+ where: n.id,
376
+ });
377
+ }
378
+ // A type whose required payload fields cannot be expressed at all. Warning,
379
+ // not error: the node is as correct as the registry allows, so refusing it
380
+ // would block work the platform, not the author, has to fix. Saying nothing
381
+ // is worse — the artifact validates here and is rejected by the CLI.
382
+ const unsatisfiable = unsatisfiableRequiredInputs(n.type);
383
+ if (unsatisfiable.length) {
384
+ diags.push({
385
+ level: 'warning',
386
+ code: 'REQUIRED_INPUT_UNSATISFIABLE',
387
+ message: `"${n.id}" (${n.type}) declares required input(s) ${unsatisfiable.map((f) => `"${f}"`).join(', ')}, ` +
388
+ `but its "${registryType(n.type).inputPattern}" pattern merges every input into one row, so the ` +
389
+ `platform's required-field rule cannot see them. \`uip maestro bpmn validate\` will report ` +
390
+ `EMPTY_REQUIRED_FIELD whatever this node carries — a platform defect, not an authoring error. ` +
391
+ `See docs/BPMN_COVERAGE_DESIGN.md D13.`,
392
+ where: n.id,
393
+ });
394
+ }
395
+ }
396
+ // Recurse into sub-process bodies.
397
+ if (n.kind === 'subProcess')
398
+ checkScope(n.nodes, n.flows, `subProcess "${n.id}"`, diags, seenIds, false, n.triggeredByEvent === true);
399
+ }
400
+ }
401
+ /**
402
+ * Whether this node serializes to a `bpmn:StartEvent`.
403
+ *
404
+ * Two ways to be one: the builder's own `startEvent` kind, or a registry-backed
405
+ * node whose spec places it on that element. An unknown extension type answers
406
+ * `false` rather than throwing — a bad type has its own diagnostic, and NO_START is
407
+ * the wrong place to report it.
408
+ */
409
+ function isStartElement(n) {
410
+ if (n.kind === 'startEvent')
411
+ return true;
412
+ // A connector EVENT TRIGGER is a start event too — `Intsvc.EventTrigger`
413
+ // serializes to `bpmn:StartEvent`. Its mid-flow sibling (`subscribe: 'event'`,
414
+ // a receive task) is not.
415
+ if (n.kind === 'connectorEvent')
416
+ return n.subscribe === 'trigger';
417
+ if (n.kind !== 'typed')
418
+ return false;
419
+ try {
420
+ return registryType(n.type).element === 'bpmn:StartEvent';
421
+ }
422
+ catch {
423
+ return false;
424
+ }
425
+ }
426
+ function dupId(id, seen, diags, where) {
427
+ if (seen.has(id))
428
+ diags.push({ level: 'error', code: 'DUP_ID', message: `Duplicate element id "${id}" in ${where}.`, where: id });
429
+ seen.add(id);
430
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { type CliExitCode } from '../cli-run.js';
3
+ export declare function run(argv: string[]): Promise<CliExitCode>;
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * compile-cli — <Name>.bpmn.ts → <Name>.bpmn
4
+ *
5
+ * Usage:
6
+ * node --experimental-strip-types compile-cli.js <bpmn.ts | BaseName> [-o out.bpmn]
7
+ *
8
+ * Runs the fast static check first; if it passes, serializes to Maestro `.bpmn`
9
+ * XML (semantic-only — no diagram). The authoritative deploy gate is
10
+ * `uip maestro bpmn validate`; a separate "tidy" step lays the diagram out.
11
+ */
12
+ import { writeFileSync, existsSync } from 'node:fs';
13
+ import { basename, join } from 'node:path';
14
+ import { resolveBpmnFile, loadBuiltBpmn } from './load.js';
15
+ import { serialize } from './serialize.js';
16
+ import { check } from './check.js';
17
+ import { Library } from '../core/library.js';
18
+ import { Bindings } from '../core/bindings.js';
19
+ import { runWhenInvokedDirectly } from '../cli-run.js';
20
+ import { ensureTypeScriptRuntime } from '../node-runtime.js';
21
+ import { resolveLibraryDir } from '../registry/cache.js';
22
+ function opt(argv, name) {
23
+ const i = argv.indexOf(name);
24
+ return i >= 0 ? argv[i + 1] : undefined;
25
+ }
26
+ export async function run(argv) {
27
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
28
+ console.error('usage: compile <bpmn.ts | BaseName> [-o out.bpmn]');
29
+ return 2;
30
+ }
31
+ const flags = new Set(['-o', '--library', '--bindings']);
32
+ const pos = argv.find((a, i) => !flags.has(a) && !flags.has(argv[i - 1]));
33
+ if (!pos) {
34
+ console.error('compile: missing <bpmn.ts | BaseName>');
35
+ return 2;
36
+ }
37
+ const file = resolveBpmnFile(pos);
38
+ ensureTypeScriptRuntime();
39
+ const built = await loadBuiltBpmn(file);
40
+ const diags = check(built);
41
+ for (const d of diags)
42
+ console.error(` ${d.level === 'error' ? '✗' : '⚠'} [${d.code}] ${d.message}`);
43
+ if (diags.some((d) => d.level === 'error')) {
44
+ console.error(`compile: ${diags.filter((d) => d.level === 'error').length} error(s); not emitting.`);
45
+ return 1;
46
+ }
47
+ // Connector service tasks resolve against the library (like Flow's/Case's
48
+ // compile-cli); load it only when present, and bindings.json alongside the .ts.
49
+ const libDir = resolveLibraryDir(opt(argv, '--library'));
50
+ const library = libDir && existsSync(join(libDir, 'index.json')) ? new Library(libDir) : undefined;
51
+ const bindFile = opt(argv, '--bindings') ?? (existsSync('bindings.json') ? 'bindings.json' : undefined);
52
+ const bindings = new Bindings(bindFile);
53
+ const xml = await serialize(built, { library, bindings });
54
+ const base = basename(file).replace(/\.bpmn\.ts$|\.ts$/, '');
55
+ const out = opt(argv, '-o') ?? `${base}.bpmn`;
56
+ writeFileSync(out, xml);
57
+ console.log(`compile: wrote ${out} (${built.nodes.length} element(s))`);
58
+ return 0;
59
+ }
60
+ runWhenInvokedDirectly(import.meta.url, 'compile', run);
@@ -0,0 +1,56 @@
1
+ /**
2
+ * bpmn/connector — emit an Integration Service connector service task as a
3
+ * `bpmn:sendTask` carrying a `uipath:activity` (`Intsvc.ActivityExecution`).
4
+ *
5
+ * The connector DATA (wiring context, path/query/body input split, output schema,
6
+ * metadata blob, connection/folder bindings) is exactly what the Flow node and the
7
+ * Case task carry — all derived from the same `ResolvedConnector` (`Library.resolve`)
8
+ * — only the ENVELOPE differs: moddle `uipath:*` elements here vs. caseplan JSON in
9
+ * `case/serialize.ts`. The shape was verified against real Studio Web `.bpmn`
10
+ * exports (`Intsvc.ActivityExecution` on a `bpmn:sendTask`; see CONNECTORS_DESIGN.md
11
+ * §D) and passes `uip maestro bpmn validate`.
12
+ *
13
+ * NOTE: the DATA computation mirrors `case/serialize.ts` (`connectorTaskData`/
14
+ * `connectorMetadata`/`connectorOutputs`); the two could be unified into a shared
15
+ * `core/` helper in a later cleanup — kept separate here to keep this change
16
+ * BPMN-only.
17
+ *
18
+ * All values are embedded via `bpmn-moddle` (`m.create`), which escapes attributes,
19
+ * text, and CDATA — never string-concatenated into XML.
20
+ */
21
+ import type BpmnModdle from 'bpmn-moddle';
22
+ import type { ModdleElement } from 'bpmn-moddle';
23
+ import { type BpmnNode } from './bpmn-sdk.js';
24
+ import type { Library } from '../core/library.js';
25
+ import type { Bindings } from '../core/bindings.js';
26
+ type El = ModdleElement;
27
+ type ConnectorNode = Extract<BpmnNode, {
28
+ kind: 'connector';
29
+ }>;
30
+ /** The subset of the serializer context this emitter needs. */
31
+ export interface ConnectorCtx {
32
+ m: BpmnModdle;
33
+ library?: Library;
34
+ bindings?: Bindings;
35
+ bindingSink: Map<string, Record<string, unknown>>;
36
+ /**
37
+ * Declared Maestro `type` for a variable id, for typing an author-mapped output
38
+ * row. Optional so the connector emitter (which writes its own rows) is
39
+ * unaffected; the Phase 3d families pass it through to `createTypedNode`.
40
+ */
41
+ varTypeOf?: (varId: string) => string | undefined;
42
+ }
43
+ export declare function createConnectorTask(ctx: ConnectorCtx, n: ConnectorNode): El;
44
+ /**
45
+ * Resolve a symbolic connection/folder to a process-level binding.
46
+ *
47
+ * Exported for the Phase 3d nodes, which need the identical closure: a connector
48
+ * event and an external agent/workflow each reference a connection and a folder
49
+ * the same way a connector activity does, and duplicating this was how the two
50
+ * families drifted apart in `case/serialize.ts`.
51
+ */
52
+ export declare function connectorBindingRef(ctx: ConnectorCtx, name: string | undefined, resource: string, propertyAttribute: string, displayName: string): {
53
+ id: string;
54
+ resourceKey: string;
55
+ } | undefined;
56
+ export {};