@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,551 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const REGISTRY = require('./registry-types.json');
4
+ /** Every extension type in the snapshot, sorted. */
5
+ export function registryTypeNames() {
6
+ return Object.keys(REGISTRY.types).sort();
7
+ }
8
+ /**
9
+ * The spec for one extension type.
10
+ *
11
+ * @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
12
+ * @returns Its emission spec.
13
+ * @throws If the type is not in the committed snapshot — which means either a
14
+ * typo or a registry refresh the snapshot has not caught up with.
15
+ */
16
+ export function registryType(type) {
17
+ const spec = REGISTRY.types[type];
18
+ if (!spec) {
19
+ throw new Error(`unknown extension type "${type}". The committed registry snapshot has ${REGISTRY.provenance.typeCount} types; ` +
20
+ 'refresh it with `node scripts/materialize-bpmn-registry.mjs` if the platform added one.');
21
+ }
22
+ return spec;
23
+ }
24
+ /**
25
+ * Facts the platform enforces but the registry does not state.
26
+ *
27
+ * Every entry here was found by probing `uip maestro bpmn validate`, not read out
28
+ * of a spec — so every entry is a liability: it can drift without the snapshot
29
+ * changing, and nothing upstream promises it. Keeping them in one visible table
30
+ * beats burying them in a builder method, and each is pinned by a test so a
31
+ * platform change fails loudly instead of silently emitting a rejected artifact.
32
+ *
33
+ * `resourceSubType` — `Orchestrator.StartAgentJob` requires its process bindings to
34
+ * carry `resourceSubType="Agent"` on top of the `resource`/`propertyAttribute` the
35
+ * registry does give:
36
+ *
37
+ * [error] Orchestrator.StartAgentJob binding "x" must target Agent name.
38
+ *
39
+ * `resource="Agent"` and `resource="agent"` are both rejected; only
40
+ * `resource="process"` + `resourceSubType="Agent"` validates. The string matches the
41
+ * field's `DisplayName`, but nothing says that is the rule, so it is recorded as a
42
+ * constant for the one type known to need it rather than derived.
43
+ */
44
+ export const REGISTRY_GAPS = {
45
+ 'Orchestrator.StartAgentJob': { resourceSubType: 'Agent' },
46
+ // `notEnforcedInputs` — required InputFields the platform does NOT actually enforce.
47
+ //
48
+ // MEASURED, on a real trigger that carries `connection`, `folderKey`, `connectorKey`,
49
+ // `operation`, `objectName` in its `uipath:context` and none of them as `uipath:input`
50
+ // rows. `uip maestro bpmn validate` reports exactly ONE error for it —
51
+ // `connectionId` — so it satisfies required fields from context (which
52
+ // `missingRequiredInputs` now does too) and does not ask for `folderId` or
53
+ // `folderPath` at all, though the registry marks both required.
54
+ //
55
+ // Without this the SDK rejects a trigger the CLI accepts. An earlier attempt
56
+ // suppressed the whole type instead, on the unfounded belief that the CLI accepted
57
+ // that artifact — it does not, and that made the SDK accept what the platform
58
+ // rejects. This is the narrow, checked version of that.
59
+ 'Intsvc.EventTrigger': { notEnforcedInputs: ['folderId', 'folderPath'] },
60
+ 'Intsvc.WaitForEvent': { notEnforcedInputs: ['folderId', 'folderPath'] },
61
+ // `extraContext` — context fields the PLATFORM accepts for a type but the
62
+ // registry's `ContextFields` does not list. Found when `bpmn-decompile`
63
+ // round-tripped a connector task and the strict unknown-field guard rejected
64
+ // `activity` and `resourceKey`, which `bpmn/connector.ts` has always emitted and
65
+ // which `uip maestro bpmn validate` has always accepted. So the guard was right
66
+ // that they are undeclared and wrong that they are invalid — recorded here rather
67
+ // than by loosening the guard, which is what catches an author's typo.
68
+ 'Intsvc.ActivityExecution': { extraContext: ['activity', 'resourceKey'] },
69
+ // `outputRowsFixed` — the type permits EXACTLY the output row its spec declares.
70
+ // A mapped second row is refused:
71
+ //
72
+ // [error] Maestro.ReceiveMessageEvent output name must be "response".
73
+ // [error] Maestro.ReceiveMessageEvent output type must be "Maestro.ReceiveMessageEvent".
74
+ //
75
+ // Recorded rather than derived because the registry gives no way to tell. Compare
76
+ // `Actions.HITL`: a structurally IDENTICAL output declaration (typed row, no
77
+ // `source`, `relative: true`) which accepts a mapped second row — and has to, since
78
+ // that row is the only thing an offline approval branch can read. Two types, the
79
+ // same spec, opposite enforcement.
80
+ 'Maestro.ReceiveMessageEvent': { outputRowsFixed: true },
81
+ };
82
+ /**
83
+ * An output name reduced to something an expression can actually read.
84
+ *
85
+ * Registry output names are DISPLAY names, and some contain spaces — the whole
86
+ * Orchestrator job family calls its output `Process response`. Interpolated
87
+ * straight into a default variable that yields `start_Process response`, which no
88
+ * `vars.<name>` reference can address. Camel-casing the words keeps the default
89
+ * predictable (`start_processResponse`) and legal; an author who wants a nicer name
90
+ * passes `outputVar`.
91
+ */
92
+ function identifierize(name) {
93
+ const words = name.split(/[^A-Za-z0-9]+/).filter(Boolean);
94
+ if (words.length === 0)
95
+ return 'response';
96
+ return words
97
+ .map((w, i) => (i === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)))
98
+ .join('');
99
+ }
100
+ /** The variable a typed node's output row writes, or `undefined` when it has none. */
101
+ export function typedNodeOutputVar(id, type, outputVar) {
102
+ const spec = registryType(type);
103
+ if (!spec.output)
104
+ return undefined;
105
+ return outputVar ?? `${id}_${identifierize(spec.output.name)}`;
106
+ }
107
+ /**
108
+ * `uipath:context` — one scalar `uipath:input` per field the author supplied, or
109
+ * that the registry gives a default.
110
+ *
111
+ * A field is emitted when the author set it OR the registry declares a default.
112
+ * The registry's defaults are not cosmetic: `Intsvc.UnifiedHttpRequest` declares
113
+ * `mode: "manual"` as REQUIRED and HIDDEN, so an author never passes it and the
114
+ * artifact fails validation without it.
115
+ */
116
+ /**
117
+ * A `json` context field's CDATA body.
118
+ *
119
+ * The field IS JSON — `metadata`, `headers`, `parameters`, `body`, `decisions` and
120
+ * the two case-rule fields are all declared `type="json"` in the registry — so an
121
+ * author writes the value, not a hand-encoded string of it. Before this,
122
+ * `String(value)` wrote `[object Object]` into the artifact for anything but a
123
+ * string, silently, and nothing offline caught it.
124
+ *
125
+ * A string still goes through untouched, which is both what every existing artifact
126
+ * and every prior caller passes, and the only way to write a body this SDK could
127
+ * not otherwise spell.
128
+ */
129
+ function jsonBody(value) {
130
+ return typeof value === 'string' ? value : JSON.stringify(value);
131
+ }
132
+ function contextRows(m, type, spec, supplied, verbatim = false) {
133
+ const rows = [];
134
+ const emitted = new Set();
135
+ if (verbatim) {
136
+ // Supplied order, supplied fields, nothing added. The declared TYPE is still
137
+ // honoured, so a json field lands in the body rather than an attribute.
138
+ const byName = new Map(spec.context.map((f) => [f.name, f]));
139
+ for (const [name, value] of Object.entries(supplied)) {
140
+ if (value === undefined || value === null)
141
+ continue;
142
+ const fieldType = byName.get(name)?.type ?? 'string';
143
+ rows.push(fieldType === 'json'
144
+ ? m.create('uipath:Input', { name, type: fieldType, body: jsonBody(value) })
145
+ : m.create('uipath:Input', { name, type: fieldType, value: String(value) }));
146
+ }
147
+ return rows;
148
+ }
149
+ for (const field of spec.context) {
150
+ const value = supplied[field.name] ?? field.default;
151
+ if (value === undefined || value === null)
152
+ continue;
153
+ emitted.add(field.name);
154
+ // A `json` field goes in the CDATA BODY, not a `value` attribute. The product
155
+ // validator parses that field as JSON and reads the attribute WITHOUT XML
156
+ // entity decoding, so an attribute-borne object arrives as
157
+ // `{&#34;a&#34;:1}` and is reported as `context input "…" contains malformed
158
+ // JSON`. The connector emitter has always used the body for json inputs; this
159
+ // matches it. (Neither offline validator catches this — only the CLI does.)
160
+ rows.push(field.type === 'json'
161
+ ? m.create('uipath:Input', { name: field.name, type: field.type, body: jsonBody(value) })
162
+ : m.create('uipath:Input', { name: field.name, type: field.type, value: String(value) }));
163
+ }
164
+ // A value the registry does not declare is USUALLY a typo — the platform ignores
165
+ // it and the author never learns why their setting did nothing — so it is
166
+ // refused. The exception is a type with a recorded `extraContext` gap, where the
167
+ // platform is known to accept fields the registry omits.
168
+ const known = new Set([...spec.context.map((f) => f.name), ...(REGISTRY_GAPS[type]?.extraContext ?? [])]);
169
+ const unknown = Object.keys(supplied).filter((k) => !known.has(k));
170
+ if (unknown.length) {
171
+ throw new Error(`context field(s) ${unknown.map((u) => `"${u}"`).join(', ')} are not declared by this extension type. ` +
172
+ `Declared: ${[...known].join(', ') || '(none)'}.`);
173
+ }
174
+ // Permitted-but-undeclared fields (a recorded `extraContext` gap) still have to
175
+ // be WRITTEN. The loop above walks the registry's own list, so without this they
176
+ // passed the guard and were then silently dropped — which a round-trip caught.
177
+ for (const [name, value] of Object.entries(supplied)) {
178
+ if (emitted.has(name) || value === undefined || value === null)
179
+ continue;
180
+ rows.push(m.create('uipath:Input', { name, type: 'string', value: String(value) }));
181
+ }
182
+ return rows;
183
+ }
184
+ /**
185
+ * The payload rows, per the type's `inputPattern`.
186
+ *
187
+ * - `none` — the type takes no payload; anything supplied is an author error.
188
+ * - `mergedBody` / `splitInputsItemData` — one json input under the spec's
189
+ * `inputName`/`inputTarget`, carrying the whole object.
190
+ * - `separateInputs` — the payload's own keys become sibling json inputs, which is
191
+ * how the HTTP node's `headers`/`parameters`/`body` are addressed individually.
192
+ * - `scriptArgs` — handled by the script-task emitter, not here.
193
+ */
194
+ function inputRows(m, spec, inputs) {
195
+ const keys = Object.keys(inputs);
196
+ if (spec.inputPattern === 'none') {
197
+ if (keys.length) {
198
+ throw new Error(`this extension type takes no inputs, but ${keys.length} were supplied (${keys.join(', ')}).`);
199
+ }
200
+ return [];
201
+ }
202
+ if (spec.inputPattern === 'separateInputs') {
203
+ // Sibling rows, one per supplied key.
204
+ //
205
+ // The target is NOT `spec.inputTarget`. That field names the single target for
206
+ // the one-row patterns, and applying it here collapsed every sibling onto the
207
+ // same target: a connector's three rows all came out `target="body"` instead of
208
+ // `pathParameters` / `queryParameters` / `body`, so an artifact authored through
209
+ // the generic `.activity()` sent path and query parameters in the request body.
210
+ //
211
+ // Nor is it always the key. The key was the fix for that collapse, and it is
212
+ // right for a type whose inputs are DYNAMIC — a connector's fields come from
213
+ // the connector library, not the registry, so the key is the only thing to go
214
+ // on. But a type that DECLARES its payload fields declares their target too,
215
+ // and the key is then wrong: `Maestro.ReceiveMessageEvent.Reference` targets
216
+ // `bodyField`, so keying it produced `target="Reference"` — a target the
217
+ // platform does not read, and one no validator complains about.
218
+ //
219
+ // So: the declared field decides when there is one, the key when there is not.
220
+ const declared = new Map(spec.inputs.map((f) => [f.name, f]));
221
+ return keys.map((k) => {
222
+ const field = declared.get(k);
223
+ return payloadInput(m, k, field?.target ?? k, inputs[k], field?.type ?? 'json');
224
+ });
225
+ }
226
+ if (!spec.inputName)
227
+ return [];
228
+ return [jsonInput(m, spec.inputName, spec.inputTarget ?? 'body', inputs)];
229
+ }
230
+ function jsonInput(m, name, target, value) {
231
+ const props = { name, type: 'json', body: JSON.stringify(value ?? {}) };
232
+ if (target)
233
+ props.target = target;
234
+ return m.create('uipath:Input', props);
235
+ }
236
+ /**
237
+ * One payload row, typed as the registry declares the field.
238
+ *
239
+ * The body/attribute split is the same rule `contextRows` follows and for the same
240
+ * measured reason: a structured value must be a CDATA BODY, because the product
241
+ * validator reads a `value` attribute without XML entity decoding and an
242
+ * object-bearing attribute comes back as `{&#34;a&#34;:1}`. A SCALAR is the
243
+ * opposite — JSON-encoding it into a body double-quotes it, so a string
244
+ * correlation reference arrived as `"ORD-1"` rather than `ORD-1`. Neither
245
+ * offline validator catches either direction.
246
+ *
247
+ * A structured field stays in the body even when its value is an `=`-expression.
248
+ * That is deliberate rather than an oversight: an expression inside a JSON body IS
249
+ * resolved — `<uipath:input name="ItemData" type="json" target="body">
250
+ * {"Reference":"=vars.ref"}` reports `VARIABLE_DOES_NOT_EXIST` against an
251
+ * undeclared variable, so the platform is reading it — whereas an expression in a
252
+ * `type="json"` ATTRIBUTE is a shape nothing here has verified.
253
+ */
254
+ function payloadInput(m, name, target, value, type) {
255
+ const structured = type === 'json' || type === 'object' || type === 'array' || type === 'jsonSchema';
256
+ const props = structured
257
+ ? { name, type: 'json', body: JSON.stringify(value ?? {}) }
258
+ : { name, type, value: String(value ?? '') };
259
+ if (target)
260
+ props.target = target;
261
+ return m.create('uipath:Input', props);
262
+ }
263
+ /** The `uipath:output` row, when the type declares one. */
264
+ function outputRow(m, spec, varName) {
265
+ if (!spec.output)
266
+ return undefined;
267
+ const props = { name: spec.output.name, type: spec.output.type, var: varName };
268
+ // Only when the registry gives one: several types declare an output with no
269
+ // source at all, and inventing `=<name>` for them would not round-trip.
270
+ if (spec.output.source)
271
+ props.source = spec.output.source;
272
+ return m.create('uipath:Output', props);
273
+ }
274
+ /** The moddle type name for an instance tag, e.g. `uipath:activity` → `uipath:Activity`. */
275
+ function moddleTypeOf(tag) {
276
+ const [ns, local] = tag.split(':');
277
+ return `${ns}:${local.charAt(0).toUpperCase()}${local.slice(1)}`;
278
+ }
279
+ /**
280
+ * Emit a registry-backed typed node.
281
+ *
282
+ * @param m - The moddle instance to create elements with.
283
+ * @param id - The BPMN element id.
284
+ * @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
285
+ * @param input - Author-supplied name, context, payload, output variable and skip.
286
+ * @returns The moddle element, ready for the serializer to wire flows onto.
287
+ */
288
+ export function createTypedNode(m, id, type, input,
289
+ /**
290
+ * Declared Maestro `type` for a variable id, for typing the extra output rows below.
291
+ * Optional so a caller with no variable context still gets today's behaviour.
292
+ */
293
+ varType) {
294
+ const spec = registryType(type);
295
+ if (!spec.element || !spec.tag) {
296
+ throw new Error(`extension type "${type}" has no element/tag in the registry snapshot; it cannot be authored.`);
297
+ }
298
+ const payload = {
299
+ version: 'v1',
300
+ type: m.create('uipath:Type', { value: type, version: input.typeVersion ?? 'v1' }),
301
+ };
302
+ // `skipCondition` exists on the activity/event tags only — a mapping cannot
303
+ // carry it, and moddle would silently drop it (see ActivityOpts in bpmn-sdk).
304
+ if (input.skipCondition !== undefined) {
305
+ if (spec.tag === 'uipath:mapping') {
306
+ throw new Error(`extension type "${type}" serializes a uipath:mapping, which cannot carry a skipCondition.`);
307
+ }
308
+ payload.skipCondition = input.skipCondition;
309
+ }
310
+ const ctx = input.contextRows
311
+ ? input.contextRows.map((row) => {
312
+ const props = { name: row.name, type: row.type ?? 'string' };
313
+ if (row.required)
314
+ props.required = 'true';
315
+ if (row.target !== undefined)
316
+ props.target = row.target;
317
+ if (row.value !== undefined)
318
+ props.value = row.value;
319
+ if (row.body !== undefined)
320
+ props.body = jsonBody(row.body);
321
+ return m.create('uipath:Input', props);
322
+ })
323
+ : contextRows(m, type, spec, input.context ?? {}, input.contextVerbatim);
324
+ // The schema is a sibling of the context's rows, and can be the only thing in it —
325
+ // a script task's context carries an inputSchema and no rows at all.
326
+ if (ctx.length || input.inputSchema !== undefined) {
327
+ const context = {};
328
+ if (ctx.length)
329
+ context.input = ctx;
330
+ if (input.inputSchema !== undefined) {
331
+ context.inputSchema = m.create('uipath:InputSchema', {
332
+ type: 'jsonSchema',
333
+ body: typeof input.inputSchema === 'string' ? input.inputSchema : JSON.stringify(input.inputSchema),
334
+ });
335
+ }
336
+ payload.context = m.create('uipath:Context', context);
337
+ }
338
+ const ins = inputRows(m, spec, input.inputs ?? {});
339
+ if (ins.length)
340
+ payload.input = ins;
341
+ const rows = [];
342
+ if (input.outputRows) {
343
+ // Spelled out by the caller: emit exactly these, deriving nothing. See
344
+ // TypedNodeInput.outputRows — this is what lets a connector's response schema
345
+ // survive a round trip.
346
+ rows.push(...verbatimOutputRows(m, input.outputRows));
347
+ if (rows.length)
348
+ payload.output = rows;
349
+ return finish(m, spec, id, input.name, payload);
350
+ }
351
+ const outVar = typedNodeOutputVar(id, type, input.outputVar);
352
+ const out = outVar ? outputRow(m, spec, outVar) : undefined;
353
+ if (out)
354
+ rows.push(out);
355
+ for (const [varId, source] of Object.entries(input.outputs ?? {})) {
356
+ // Type the row from the variable it writes, not `'string'` unconditionally.
357
+ //
358
+ // The runtime coerces a value by switching on this `type`, so a boolean captured as
359
+ // `type="string"` is the D1 hazard one layer along: the local engine evaluates the
360
+ // expression and gets a real boolean, but the platform is told the row is a string, and a
361
+ // gateway guarded on it can then branch on the truthy string `"false"`. It also made a
362
+ // boolean HITL decision unauthorable — `check_quality_boolean_decision.py` requires an
363
+ // output whose `type` is boolean and whose `var` binds a boolean variable.
364
+ //
365
+ // `'string'` remains the fallback for a variable this node writes without declaring,
366
+ // which is what every row did before.
367
+ rows.push(m.create('uipath:Output', { name: varId, type: varType?.(varId) ?? 'string', source, var: varId }));
368
+ }
369
+ if (rows.length)
370
+ payload.output = rows;
371
+ return finish(m, spec, id, input.name, payload);
372
+ }
373
+ /** `uipath:Output` rows exactly as the caller spelled them, deriving nothing. */
374
+ export function verbatimOutputRows(m, rows) {
375
+ return rows.map((row) => {
376
+ const props = { name: row.name, type: row.type ?? 'string' };
377
+ if (row.source !== undefined)
378
+ props.source = row.source;
379
+ if (row.var !== undefined)
380
+ props.var = row.var;
381
+ if (row.custom)
382
+ props.custom = true;
383
+ if (row.description !== undefined)
384
+ props.description = row.description;
385
+ if (row.target !== undefined)
386
+ props.target = row.target;
387
+ if (row.schema !== undefined) {
388
+ props.body = typeof row.schema === 'string' ? row.schema : JSON.stringify(row.schema);
389
+ }
390
+ return m.create('uipath:Output', props);
391
+ });
392
+ }
393
+ /**
394
+ * The extension payload for a type and its output rows, with NO element around it.
395
+ *
396
+ * `createTypedNode` takes the element from the registry, which is right for an
397
+ * activity and wrong everywhere the product uses a payload as DECORATION: a
398
+ * `uipath:mapping` on a start event, an end event or a sub-process, a
399
+ * `uipath:activity` on an error boundary. Those arms of `createNode` build their
400
+ * own element and attach this to it, rather than letting `BPMN.Variables` turn a
401
+ * start event into a `bpmn:Task`.
402
+ *
403
+ * @param m - The moddle instance.
404
+ * @param type - The extension type, e.g. `BPMN.Variables` or `uipath:Activity`.
405
+ * @param rows - Output rows, emitted verbatim.
406
+ * @returns The payload element, ready to go inside a `bpmn:ExtensionElements`.
407
+ */
408
+ export function createExtensionPayload(m, type, rows) {
409
+ const spec = registryType(type);
410
+ if (!spec.tag) {
411
+ throw new Error(`extension type "${type}" has no tag in the registry snapshot; it cannot be authored.`);
412
+ }
413
+ const payload = {
414
+ version: 'v1',
415
+ type: m.create('uipath:Type', { value: type, version: 'v1' }),
416
+ };
417
+ const out = verbatimOutputRows(m, rows);
418
+ if (out.length)
419
+ payload.output = out;
420
+ return m.create(moddleTypeOf(spec.tag), payload);
421
+ }
422
+ /** Wrap a finished payload in its BPMN element. */
423
+ function finish(m, spec, id, name, payload) {
424
+ const props = {
425
+ id,
426
+ name,
427
+ extensionElements: m.create('bpmn:ExtensionElements', { values: [m.create(moddleTypeOf(spec.tag), payload)] }),
428
+ };
429
+ // What makes a message event a message event — without it the platform reads a
430
+ // plain intermediate event and the correlation never happens.
431
+ if (spec.eventDefinition) {
432
+ props.eventDefinitions = [m.create(moddleTypeOf(spec.eventDefinition), {})];
433
+ }
434
+ return m.create(moddleElementOf(spec.element), props);
435
+ }
436
+ /** `bpmn:SendTask` is already the moddle type name; keep it, but validate the shape. */
437
+ function moddleElementOf(element) {
438
+ if (!/^bpmn:[A-Z]/.test(element)) {
439
+ throw new Error(`registry element "${element}" is not a moddle type name (expected e.g. bpmn:SendTask).`);
440
+ }
441
+ return element;
442
+ }
443
+ /**
444
+ * The context fields this type requires to be a `=bindings.<id>` reference rather
445
+ * than a literal.
446
+ *
447
+ * Narrower than it looks, and the narrowness is measured. `binding: true` marks a
448
+ * field the designer OFFERS a binding picker for — `Intsvc.UnifiedHttpRequest`'s
449
+ * `url` is one, and a literal URL validates fine. What the platform actually
450
+ * enforces is `bindingInfo` AND `required`, which today selects exactly
451
+ * `Orchestrator.StartAgentJob`'s `name` and `folderPath`:
452
+ *
453
+ * [error] Orchestrator.StartAgentJob context input "name" must reference project bindings.
454
+ * [error] Orchestrator.StartAgentJob binding "x" must target Agent name.
455
+ *
456
+ * Both halves are enforced — a literal is rejected, and so is a binding pointing
457
+ * at the wrong property.
458
+ *
459
+ * @param type - The extension type.
460
+ * @returns Its fields that must be bound, with the target each binding needs.
461
+ */
462
+ export function bindingRequiredFields(type) {
463
+ return registryType(type).context.filter((f) => f.bindingInfo !== null && f.required);
464
+ }
465
+ /**
466
+ * Required context fields the author left unset and the registry cannot default.
467
+ *
468
+ * Separate from emission so `check()` can report them at authoring time. Missing
469
+ * them is what `uip maestro bpmn validate` reports as `EMPTY_REQUIRED_FIELD`, and
470
+ * hearing it from the SDK is faster than hearing it from the CLI.
471
+ *
472
+ * @param type - The extension type.
473
+ * @param context - The context values the author supplied.
474
+ * @returns The names of required fields with no value and no default.
475
+ */
476
+ export function missingRequiredContext(type, context = {}) {
477
+ return registryType(type)
478
+ .context.filter((f) => f.required && context[f.name] === undefined && (f.default ?? '') === '')
479
+ .map((f) => f.name);
480
+ }
481
+ /**
482
+ * Required PAYLOAD fields the author left unset.
483
+ *
484
+ * The counterpart of {@link missingRequiredContext}, and reported the same way: the
485
+ * platform's `RequiredFieldsRule` draws on `InputFields` as well as `ContextFields`,
486
+ * so an unset required payload field is the same `EMPTY_REQUIRED_FIELD` the CLI
487
+ * would report a build later.
488
+ *
489
+ * @param type - The extension type.
490
+ * @param inputs - The payload the author supplied.
491
+ * @returns The names of required payload fields with no value and no default.
492
+ */
493
+ export function missingRequiredInputs(type, inputs = {},
494
+ /**
495
+ * The node's `uipath:context` values, which SATISFY a required payload field too.
496
+ *
497
+ * The platform's `RequiredFieldsRule` draws on both, and a trigger is where that
498
+ * shows: `Intsvc.EventTrigger` declares seven required inputs, and a real one
499
+ * carries every one of them as a `uipath:context` row rather than a
500
+ * `uipath:input`. Checking inputs alone reported all seven; `uip maestro bpmn
501
+ * validate` reports exactly one — `connectionId`, the only name the artifact
502
+ * genuinely does not spell (it writes `connection`). Reading both makes this
503
+ * agree with the CLI instead of guessing on either side of it.
504
+ */
505
+ context = {}) {
506
+ const notEnforced = new Set(REGISTRY_GAPS[type]?.notEnforcedInputs ?? []);
507
+ return registryType(type)
508
+ .inputs.filter((f) => f.required &&
509
+ !notEnforced.has(f.name) &&
510
+ inputs[f.name] === undefined &&
511
+ context[f.name] === undefined &&
512
+ (f.default ?? '') === '')
513
+ .map((f) => f.name);
514
+ }
515
+ /**
516
+ * Whether this type's required payload fields are UNSATISFIABLE on the wire.
517
+ *
518
+ * A platform defect, recorded here because the SDK cannot emit its way around it.
519
+ * `RequiredFieldsRule` builds its required-name set from `InputFields` and then
520
+ * fires when a name is absent from the serialized rows **by name**. Under
521
+ * `mergedBody` and `splitInputsItemData` every payload field collapses into ONE row
522
+ * — named `body` or `ItemData` — so a required input field is never present by
523
+ * name and the rule fires however the node is filled in:
524
+ *
525
+ * [error] [call] EMPTY_REQUIRED_FIELD: The field 'agentUrl' in node 'call' is
526
+ * required but has no value.
527
+ *
528
+ * Note the registry's own `XmlTemplate` for `A2A.AgentExecution` emits exactly the
529
+ * body-only shape that fails, which is the clearest statement that the two halves
530
+ * of the platform disagree rather than that the SDK is writing the wrong thing.
531
+ *
532
+ * Whether a workaround exists is per-type and not derivable from the spec, so it is
533
+ * not encoded here. Measured: `A2A.AgentExecution` accepts redundant sibling rows
534
+ * alongside the merged body (`Valid`); `Maestro.SendMessageEvent` refuses them
535
+ * outright — `does not support input payload "Reference"` as a row, `does not
536
+ * support context input "Reference"` in context, and `ItemData`'s `target="body"`
537
+ * is enforced — so for that type NO artifact satisfies both gates.
538
+ *
539
+ * Selects exactly `A2A.AgentExecution` and `Maestro.SendMessageEvent` today. The
540
+ * three other types with required payload fields are `separateInputs`, whose rows
541
+ * DO carry their own names, and are unaffected.
542
+ *
543
+ * @param type - The extension type.
544
+ * @returns The required payload field names that cannot be expressed, or `[]`.
545
+ */
546
+ export function unsatisfiableRequiredInputs(type) {
547
+ const spec = registryType(type);
548
+ if (spec.inputPattern !== 'mergedBody' && spec.inputPattern !== 'splitInputsItemData')
549
+ return [];
550
+ return spec.inputs.filter((f) => f.required).map((f) => f.name);
551
+ }