@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,184 @@
1
+ /**
2
+ * core/connectors — the typed connector-descriptor surface.
3
+ *
4
+ * A *descriptor* is a tiny, generated value that identifies one connector
5
+ * operation (`nodeType` + `version`) and carries its input/output **types** as
6
+ * phantom brands (zero runtime cost). The generated per-connector modules
7
+ * (materialized from the connector library — see `lib/`) export one descriptor
8
+ * per op, so authoring a connector step is statically checked:
9
+ *
10
+ * ```ts
11
+ * import { connector } from './sdk';
12
+ * import { CreateIssue } from '@uipath/flow-connectors/uipath-atlassian-jira';
13
+ * connector(CreateIssue, { fields: { project: { key: 'TS' }, summary: '…' } },
14
+ * { connection: 'jira', folder: 'shared' });
15
+ * ```
16
+ *
17
+ * The descriptor is a **typed index over the library**, not a replacement: it
18
+ * only carries the id + types; `serialize()` still resolves the full node
19
+ * payload from `library-json` via `Library.resolve()`. Both are generated from
20
+ * the same library snapshot. Generated inputs expose natural nested objects and
21
+ * arrays; `buildConnectorInputs` validates them and projects them back to the
22
+ * registry's flat field ids when emitting Flow JSON.
23
+ */
24
+ import type { Expr } from './expr.js';
25
+ import type { LookupSpec, LookupToken } from './lookups.js';
26
+ /**
27
+ * What a generated `Inputs` property accepts: the value, or an expression.
28
+ *
29
+ * The generator used to type a string field as `string`, full stop. That was
30
+ * never what the SDK accepts — `input('x')`, `out('step','f')`, `` tmpl`…` ``
31
+ * and `` js`…` `` all produce an {@link Expr}, and passing one is the ordinary
32
+ * way to author a connector step. So `connector(CreateIssue, { summary:
33
+ * input('summary') })` did not typecheck.
34
+ *
35
+ * Nothing caught it because no shipped example uses a descriptor (they all use
36
+ * the string form, which takes `Record<string, unknown>`), and because `compile`
37
+ * runs under `--experimental-strip-types` — types are erased, never checked.
38
+ * The typed surface was decorative.
39
+ *
40
+ * Arrays distribute, so BOTH shapes an author reaches for are legal: the whole
41
+ * collection as one expression (`tags: input('tags')`) and a literal array with
42
+ * an expression in a slot (`tags: ['a', out('s','b')]`). Without the
43
+ * distribution the second form forced every element to be a bare literal.
44
+ *
45
+ * This does NOT loosen which FIELDS are accepted, which is the property the
46
+ * closed `Inputs` type exists for. Only which value forms, and to exactly the
47
+ * set the serializer already renders.
48
+ */
49
+ export type ConnectorValue<T> = Expr | (T extends readonly (infer E)[] ? Array<E | Expr> : T);
50
+ /**
51
+ * {@link ConnectorValue} for a field that also accepts an unresolved lookup.
52
+ *
53
+ * Deliberately separate. If every property accepted a {@link LookupToken}, a
54
+ * `lookup(...)` could be attached to a field with no `reference` at all, and
55
+ * the mistake would survive to `prepare`, which has nothing to resolve it
56
+ * against. Confining the token to fields that declare a lookup makes that a
57
+ * compile error at the call site instead.
58
+ */
59
+ export type ConnectorLookupValue<T> = LookupToken | (T extends readonly (infer E)[] ? Array<E | Expr | LookupToken> : T | Expr);
60
+ /** Runtime metadata a generated descriptor carries. `nodeType` is `uipath.connector.<key>.<action>` (no `@version`). */
61
+ export interface ConnectorMeta {
62
+ nodeType: string;
63
+ version?: string;
64
+ requiresConnection?: boolean;
65
+ requiresFolderKey?: boolean;
66
+ /**
67
+ * Which OBJECT this descriptor addresses, for a **generic** operation whose
68
+ * nodeType covers many (`…netsuite.get-record` covers 182). Baked in by the
69
+ * generator so `connector(D, …)` needs no `{ object }`; an explicit
70
+ * `{ object }` still wins.
71
+ *
72
+ * @remarks
73
+ * Precedence is the call option first, the descriptor's baked constant second.
74
+ */
75
+ objectName?: string;
76
+ /**
77
+ * The operation's resolvable lookup fields, keyed by field name — generated
78
+ * from each input's `reference` block. Absent when the operation has none.
79
+ *
80
+ * Consumed by {@link lookup}, and readable as plain source: the generator
81
+ * also writes the same facts as a comment above the descriptor, because the
82
+ * agents this surface is for run with `grep` and no language server, so a
83
+ * `.byEmail` discoverable only by hovering is invisible.
84
+ *
85
+ * Degenerate lookups are deliberately absent — see `_lookups.py`.
86
+ */
87
+ lookups?: Readonly<Record<string, LookupSpec>>;
88
+ }
89
+ /**
90
+ * A generated, typed connector descriptor: {@link ConnectorMeta} branded with
91
+ * phantom input/output types. `__inputs`/`__outputs` never materialize at
92
+ * runtime — they exist only so `connector(descriptor, inputs)` can infer types.
93
+ */
94
+ export type ConnectorDescriptor<I = Record<string, unknown>, O = Record<string, unknown>> = ConnectorMeta & {
95
+ readonly __inputs?: I;
96
+ readonly __outputs?: O;
97
+ };
98
+ /**
99
+ * Brand a descriptor literal with its input/output types (zero runtime cost).
100
+ * Used by codegen: `descriptor<CreateIssueInputs, CreateIssueOutputs>()({ … } as const)`.
101
+ * Curried so the generator names `I`/`O` explicitly while TS still narrows the
102
+ * literal (`nodeType`, flags) from `as const`.
103
+ *
104
+ * @returns A branding function: call it with the descriptor literal (`as const`) to get
105
+ * that literal typed as a {@link ConnectorDescriptor}.
106
+ */
107
+ export declare function descriptor<I = Record<string, unknown>, O = Record<string, unknown>>(): <const D extends ConnectorMeta>(d: D) => D & {
108
+ readonly __inputs?: I;
109
+ readonly __outputs?: O;
110
+ };
111
+ /**
112
+ * Split a connector `nodeType` into its `{ key, action }`.
113
+ *
114
+ * @internal Public for compatibility; not an authoring factory.
115
+ */
116
+ export declare function splitConnectorNodeType(nodeType: string): {
117
+ key: string;
118
+ action: string;
119
+ };
120
+ /** Runtime metadata a generated trigger descriptor carries. */
121
+ export interface TriggerMeta {
122
+ /** Connector key, e.g. `'uipath-atlassian-jira'`. */
123
+ connector: string;
124
+ /** Curated event id, e.g. `'issue-created'` (the last segment of the nodeType). */
125
+ event: string;
126
+ version?: string;
127
+ /** Human label from the registry catalog, e.g. `'Issue Created'` (docs only). */
128
+ displayName?: string;
129
+ }
130
+ /**
131
+ * A generated, typed connector-trigger descriptor: {@link TriggerMeta} branded
132
+ * with phantom `where`/output types. Offline both are loose; a connection-scoped
133
+ * generator can narrow them. `__where`/`__output` never materialize at runtime.
134
+ */
135
+ export type TriggerDescriptor<W = Record<string, string>, O = Record<string, unknown>> = TriggerMeta & {
136
+ readonly __where?: W;
137
+ readonly __output?: O;
138
+ };
139
+ /**
140
+ * Brand a trigger descriptor literal with its where/output types. Used by codegen:
141
+ * `triggerDescriptor<IssueCreatedWhere>()({ … } as const)`. Curried so the
142
+ * generator names `W`/`O` explicitly while TS narrows the literal.
143
+ *
144
+ * @remarks
145
+ * It also stamps a non-enumerable runtime marker — see `isTriggerDescriptor`
146
+ * for why a type-level-only brand was not enough.
147
+ *
148
+ * @returns A branding function: call it with the descriptor literal (`as const`) to get
149
+ * that literal typed as a {@link TriggerDescriptor}.
150
+ */
151
+ export declare function triggerDescriptor<W = Record<string, string>, O = Record<string, unknown>>(): <const D extends TriggerMeta>(d: D) => D & TriggerDescriptor<W, O>;
152
+ /**
153
+ * Distinguish the typed `onEvent(descriptor, opts)` form from the stringly
154
+ * `onEvent(subscription)` form.
155
+ *
156
+ * ## This used to test for the ABSENCE of `where`, and that was load-bearing on an
157
+ * assumption that turned out to be false
158
+ *
159
+ * The old rule was *"both carry `connector` + `event`; only an `EventSubscription`
160
+ * carries `where`, so its ABSENCE marks a bare descriptor"*. It held only while
161
+ * every connector event HAD event parameters. The HTTP Webhook connector has none
162
+ * — it is scoped by the connection, so `{ connector: 'uipath-http-webhook',
163
+ * event: 'http-webhook', connection: 'bWebhook', folder: 'bFolder' }` is a
164
+ * complete, correct subscription with no `where` at all — and the old test read it
165
+ * as a descriptor. The consequence was not a type error: `subscriptionFrom` then
166
+ * rebuilt the subscription from the descriptor's three fields and **silently
167
+ * dropped `connection`, `folder` and `filters`**, emitting a start trigger bound
168
+ * to no connection. 162 of 164 deployed connector start triggers carry a
169
+ * `detail.connectionId`; ours carried none, and every rung stayed green because a
170
+ * local run resolves connectors from the library rather than from the binding.
171
+ *
172
+ * So the test is now POSITIVE and belt-and-braces:
173
+ *
174
+ * 1. a descriptor is what `triggerDescriptor()` stamped (the only producer — the
175
+ * generated `<key>.triggers.ts` modules all go through it);
176
+ * 2. and nothing carrying a SUBSCRIPTION-ONLY key is ever a descriptor, so an
177
+ * unbranded hand-written subscription cannot be misread either.
178
+ *
179
+ * Rule of thumb this cost: **never discriminate a union on a field that is allowed
180
+ * to be absent.**
181
+ *
182
+ * @internal Public for compatibility; not an authoring factory.
183
+ */
184
+ export declare function isTriggerDescriptor(x: unknown): x is TriggerDescriptor;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * core/connectors — the typed connector-descriptor surface.
3
+ *
4
+ * A *descriptor* is a tiny, generated value that identifies one connector
5
+ * operation (`nodeType` + `version`) and carries its input/output **types** as
6
+ * phantom brands (zero runtime cost). The generated per-connector modules
7
+ * (materialized from the connector library — see `lib/`) export one descriptor
8
+ * per op, so authoring a connector step is statically checked:
9
+ *
10
+ * ```ts
11
+ * import { connector } from './sdk';
12
+ * import { CreateIssue } from '@uipath/flow-connectors/uipath-atlassian-jira';
13
+ * connector(CreateIssue, { fields: { project: { key: 'TS' }, summary: '…' } },
14
+ * { connection: 'jira', folder: 'shared' });
15
+ * ```
16
+ *
17
+ * The descriptor is a **typed index over the library**, not a replacement: it
18
+ * only carries the id + types; `serialize()` still resolves the full node
19
+ * payload from `library-json` via `Library.resolve()`. Both are generated from
20
+ * the same library snapshot. Generated inputs expose natural nested objects and
21
+ * arrays; `buildConnectorInputs` validates them and projects them back to the
22
+ * registry's flat field ids when emitting Flow JSON.
23
+ */
24
+ /**
25
+ * Brand a descriptor literal with its input/output types (zero runtime cost).
26
+ * Used by codegen: `descriptor<CreateIssueInputs, CreateIssueOutputs>()({ … } as const)`.
27
+ * Curried so the generator names `I`/`O` explicitly while TS still narrows the
28
+ * literal (`nodeType`, flags) from `as const`.
29
+ *
30
+ * @returns A branding function: call it with the descriptor literal (`as const`) to get
31
+ * that literal typed as a {@link ConnectorDescriptor}.
32
+ */
33
+ export function descriptor() {
34
+ // Returns `D & brand`, NOT `D & ConnectorDescriptor<I, O>`. The two are
35
+ // equivalent for assignability — `D extends ConnectorMeta` already — but not
36
+ // for `keyof`: re-intersecting `ConnectorMeta` puts its wide
37
+ // `lookups?: Record<string, LookupSpec>` beside the literal's narrow one, and
38
+ // `keyof (A & B)` is the UNION of their keys, so `keyof D['lookups']`
39
+ // collapsed to `string`. That silently disabled every lookup field-name check
40
+ // — `lookup(D, 'nonexistent')` type-checked clean and failed at run time.
41
+ return (d) => d;
42
+ }
43
+ /**
44
+ * Split a connector `nodeType` into its `{ key, action }`.
45
+ *
46
+ * @internal Public for compatibility; not an authoring factory.
47
+ */
48
+ export function splitConnectorNodeType(nodeType) {
49
+ const rest = nodeType.replace(/^uipath\.connector\./, '');
50
+ const dot = rest.lastIndexOf('.');
51
+ if (dot <= 0)
52
+ throw new Error(`invalid connector nodeType "${nodeType}" (expected uipath.connector.<key>.<action>).`);
53
+ return { key: rest.slice(0, dot), action: rest.slice(dot + 1) };
54
+ }
55
+ /**
56
+ * The runtime marker `triggerDescriptor()` stamps on a descriptor. Non-enumerable,
57
+ * so it never reaches a `JSON.stringify`, an emitted `.flow`, or a spread — it
58
+ * exists only so `isTriggerDescriptor` can answer POSITIVELY.
59
+ */
60
+ const TRIGGER_DESCRIPTOR = Symbol.for('uipath.flow-sdk.triggerDescriptor');
61
+ /** Keys only an `EventSubscription` ever carries. */
62
+ const SUBSCRIPTION_ONLY_KEYS = ['where', 'object', 'filters', 'connection', 'folder'];
63
+ /**
64
+ * Brand a trigger descriptor literal with its where/output types. Used by codegen:
65
+ * `triggerDescriptor<IssueCreatedWhere>()({ … } as const)`. Curried so the
66
+ * generator names `W`/`O` explicitly while TS narrows the literal.
67
+ *
68
+ * @remarks
69
+ * It also stamps a non-enumerable runtime marker — see `isTriggerDescriptor`
70
+ * for why a type-level-only brand was not enough.
71
+ *
72
+ * @returns A branding function: call it with the descriptor literal (`as const`) to get
73
+ * that literal typed as a {@link TriggerDescriptor}.
74
+ */
75
+ export function triggerDescriptor() {
76
+ return (d) => {
77
+ // A descriptor literal is freshly written at its call site, so defining a
78
+ // property on it is safe; guard anyway for a frozen or reused object.
79
+ try {
80
+ Object.defineProperty(d, TRIGGER_DESCRIPTOR, { value: true, enumerable: false });
81
+ }
82
+ catch { /* a frozen literal still works — SUBSCRIPTION_ONLY_KEYS decides */ }
83
+ return d;
84
+ };
85
+ }
86
+ /**
87
+ * Distinguish the typed `onEvent(descriptor, opts)` form from the stringly
88
+ * `onEvent(subscription)` form.
89
+ *
90
+ * ## This used to test for the ABSENCE of `where`, and that was load-bearing on an
91
+ * assumption that turned out to be false
92
+ *
93
+ * The old rule was *"both carry `connector` + `event`; only an `EventSubscription`
94
+ * carries `where`, so its ABSENCE marks a bare descriptor"*. It held only while
95
+ * every connector event HAD event parameters. The HTTP Webhook connector has none
96
+ * — it is scoped by the connection, so `{ connector: 'uipath-http-webhook',
97
+ * event: 'http-webhook', connection: 'bWebhook', folder: 'bFolder' }` is a
98
+ * complete, correct subscription with no `where` at all — and the old test read it
99
+ * as a descriptor. The consequence was not a type error: `subscriptionFrom` then
100
+ * rebuilt the subscription from the descriptor's three fields and **silently
101
+ * dropped `connection`, `folder` and `filters`**, emitting a start trigger bound
102
+ * to no connection. 162 of 164 deployed connector start triggers carry a
103
+ * `detail.connectionId`; ours carried none, and every rung stayed green because a
104
+ * local run resolves connectors from the library rather than from the binding.
105
+ *
106
+ * So the test is now POSITIVE and belt-and-braces:
107
+ *
108
+ * 1. a descriptor is what `triggerDescriptor()` stamped (the only producer — the
109
+ * generated `<key>.triggers.ts` modules all go through it);
110
+ * 2. and nothing carrying a SUBSCRIPTION-ONLY key is ever a descriptor, so an
111
+ * unbranded hand-written subscription cannot be misread either.
112
+ *
113
+ * Rule of thumb this cost: **never discriminate a union on a field that is allowed
114
+ * to be absent.**
115
+ *
116
+ * @internal Public for compatibility; not an authoring factory.
117
+ */
118
+ export function isTriggerDescriptor(x) {
119
+ if (typeof x !== 'object' || x === null)
120
+ return false;
121
+ if (typeof x.connector !== 'string')
122
+ return false;
123
+ if (typeof x.event !== 'string')
124
+ return false;
125
+ if (SUBSCRIPTION_ONLY_KEYS.some((k) => k in x))
126
+ return false;
127
+ return x[TRIGGER_DESCRIPTOR] === true;
128
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * core/expr-check — a FORMAT-AGNOSTIC first-level check of the references inside
3
+ * an expression, shared by Flow, Case, and BPMN.
4
+ *
5
+ * This is the piece each SDK's `build()` runs BEFORE it hands back the model to
6
+ * be serialized: cheap, high-confidence checks that catch a broken expression at
7
+ * the moment the SDK code runs, rather than three steps later at
8
+ * `uip maestro flow validate`. Its guiding rule is **conservative**: only flag
9
+ * what it can be certain of, so it never produces a misleading error. Deeper,
10
+ * heavier checks (does step X actually output `.foo`, is the comparison
11
+ * type-sound) belong to the `validate` CLI, which can afford them.
12
+ *
13
+ * The first thing it checks: every `$vars.<root>` reference resolves to a name the
14
+ * runtime will provide — a declared input, variable, or step/task/node. A
15
+ * reference to nothing is a definite bug (a typo, or a renamed step), and the
16
+ * runtime's variable bag is pre-declared, so an unknown root reads `null` forever
17
+ * and every guard built on it silently takes the wrong path.
18
+ *
19
+ * The second: the expression PARSES as JavaScript. That sounds like something a
20
+ * later rung would catch, and nothing did — `validate` checks the artifact's
21
+ * contract, not the contents of an expression string, so
22
+ * `$vars.searchIssues.output.issues[*]` reached a live run and faulted there
23
+ * (`[400008] Failed to evaluate the input collection variable`). `[*]` is
24
+ * JSONPath; the runtime evaluates JavaScript. Reference resolution alone could
25
+ * not see it, because the root (`searchIssues`) was perfectly real.
26
+ *
27
+ * It is deliberately NOT tied to any one format's model: a caller passes the set
28
+ * of valid roots (which it alone knows how to compute) and the expression string,
29
+ * and gets back diagnostics with no location. The caller stamps the location
30
+ * (which node / task / field) it came from.
31
+ */
32
+ /** A `$vars.*` reference found in an expression. */
33
+ export interface ExprRef {
34
+ /** The first segment after `$vars.` — the name the reference is rooted at. */
35
+ root: string;
36
+ /** The remaining dotted / indexed segments, e.g. `['output', 'items', '[0]', 'id']`. */
37
+ path: string[];
38
+ /** The whole matched reference text, for messages. */
39
+ raw: string;
40
+ }
41
+ /** A problem found in an expression. Location is stamped by the caller. */
42
+ export interface ExprDiagnostic {
43
+ level: 'error' | 'warning';
44
+ code: string;
45
+ message: string;
46
+ suggestion?: string;
47
+ }
48
+ /**
49
+ * What the caller knows and the checker does not: which `$vars` roots are valid.
50
+ *
51
+ * `roots` is every name a reference may be rooted at — declared inputs, working
52
+ * variables, and the names of steps/tasks/nodes whose output is referenceable.
53
+ * `noun` names them in the message (`'input, variable, or step'` for a flow), so
54
+ * the same checker reads naturally for a case ('field or task') or a bpmn model.
55
+ */
56
+ export interface ExprScope {
57
+ roots: Set<string>;
58
+ noun?: string;
59
+ /**
60
+ * The reference NAMESPACE this check owns — the leading token whose roots are
61
+ * author-declared and therefore checkable. Flow uses `$vars` (its default); Case
62
+ * uses `vars` (a case gate reads a declared variable as `=js:vars.<name>`). Every
63
+ * OTHER namespace the engine provides (`outputs`, `result`, `metadata`,
64
+ * `orchestrator`, …) is a runtime built-in, so a reference into one is left alone
65
+ * rather than flagged.
66
+ */
67
+ namespace?: string;
68
+ /**
69
+ * Parse the expression as JavaScript and report a syntax error.
70
+ *
71
+ * OFF by default, because "expression" does not mean the same thing in all
72
+ * three formats and only the caller knows. A Flow `Expr` carries the bare
73
+ * JavaScript the runtime evaluates, so it parses. A BPMN condition is
74
+ * `=vars.total` and a Case gate is `=js:vars.total` — both carry a leading
75
+ * `=` sigil and are not JavaScript as given, so parsing them would report a
76
+ * syntax error on every well-formed expression in those formats.
77
+ */
78
+ syntax?: 'javascript';
79
+ }
80
+ /**
81
+ * Every `<namespace>.*` reference in an expression, in source order, with literals
82
+ * masked so a reference-shaped substring inside a string is not counted.
83
+ * `namespace` defaults to `$vars` (Flow); Case passes `case`.
84
+ */
85
+ export declare function extractRefs(expr: string, namespace?: string): ExprRef[];
86
+ /**
87
+ * First-level check of ONE expression: every reference's root must resolve.
88
+ *
89
+ * Returns a diagnostic per unresolved root (deduped, so `$vars.x + $vars.x` is one
90
+ * message). An empty result means "nothing this check is sure is wrong" — never
91
+ * "fully valid"; the `validate` CLI is what proves the rest.
92
+ */
93
+ export declare function checkExpression(expr: string, scope: ExprScope): ExprDiagnostic[];
@@ -0,0 +1,186 @@
1
+ /**
2
+ * core/expr-check — a FORMAT-AGNOSTIC first-level check of the references inside
3
+ * an expression, shared by Flow, Case, and BPMN.
4
+ *
5
+ * This is the piece each SDK's `build()` runs BEFORE it hands back the model to
6
+ * be serialized: cheap, high-confidence checks that catch a broken expression at
7
+ * the moment the SDK code runs, rather than three steps later at
8
+ * `uip maestro flow validate`. Its guiding rule is **conservative**: only flag
9
+ * what it can be certain of, so it never produces a misleading error. Deeper,
10
+ * heavier checks (does step X actually output `.foo`, is the comparison
11
+ * type-sound) belong to the `validate` CLI, which can afford them.
12
+ *
13
+ * The first thing it checks: every `$vars.<root>` reference resolves to a name the
14
+ * runtime will provide — a declared input, variable, or step/task/node. A
15
+ * reference to nothing is a definite bug (a typo, or a renamed step), and the
16
+ * runtime's variable bag is pre-declared, so an unknown root reads `null` forever
17
+ * and every guard built on it silently takes the wrong path.
18
+ *
19
+ * The second: the expression PARSES as JavaScript. That sounds like something a
20
+ * later rung would catch, and nothing did — `validate` checks the artifact's
21
+ * contract, not the contents of an expression string, so
22
+ * `$vars.searchIssues.output.issues[*]` reached a live run and faulted there
23
+ * (`[400008] Failed to evaluate the input collection variable`). `[*]` is
24
+ * JSONPath; the runtime evaluates JavaScript. Reference resolution alone could
25
+ * not see it, because the root (`searchIssues`) was perfectly real.
26
+ *
27
+ * It is deliberately NOT tied to any one format's model: a caller passes the set
28
+ * of valid roots (which it alone knows how to compute) and the expression string,
29
+ * and gets back diagnostics with no location. The caller stamps the location
30
+ * (which node / task / field) it came from.
31
+ */
32
+ import * as ts from 'typescript';
33
+ /**
34
+ * A JSONPath wildcard/filter step — the spelling that reaches for JavaScript and
35
+ * misses. Used only to add a suggestion; the parse decides.
36
+ */
37
+ const JSONPATH_WILDCARD = /\[\s*(?:\*|\?|'[^']*'|"[^"]*")\s*\]|\.\.[A-Za-z_$]/;
38
+ /**
39
+ * The first syntax error in `expr` read as a JavaScript EXPRESSION, or
40
+ * `undefined` when it parses.
41
+ *
42
+ * Wrapped in parentheses so it is parsed in expression position: a bare
43
+ * `{ a: 1 }` is a block with a label otherwise, and object literals are ordinary
44
+ * here. The newline before the closing paren keeps a trailing line comment from
45
+ * swallowing it.
46
+ *
47
+ * `ts.createSourceFile` is a parse, not an evaluation — nothing in `expr` runs.
48
+ * TypeScript is already a runtime dependency of this package (see
49
+ * `core/script-return.ts`, which infers a script's return type the same way), so
50
+ * this adds no dependency.
51
+ */
52
+ function syntaxError(expr) {
53
+ const source = ts.createSourceFile('expression.ts', `(${expr}\n)`, ts.ScriptTarget.ES2020,
54
+ /* setParentNodes */ false);
55
+ // `parseDiagnostics` is where the scanner records syntax problems. It is not on
56
+ // the public `SourceFile` type, hence the cast; there is no public API that
57
+ // parses a fragment and hands back its syntax diagnostics without also running
58
+ // a full program's type-check.
59
+ const problems = source.parseDiagnostics;
60
+ if (!problems || problems.length === 0)
61
+ return undefined;
62
+ return ts.flattenDiagnosticMessageText(problems[0].messageText, ' ');
63
+ }
64
+ const DEFAULT_NAMESPACE = '$vars';
65
+ /**
66
+ * Blank out the CONTENTS of single- and double-quoted string literals, preserving
67
+ * length and the quotes, so a `$vars.`-looking substring INSIDE a literal is not
68
+ * mistaken for a reference.
69
+ *
70
+ * `js`${input('a')} === ${'$vars.notAName'}`` renders to
71
+ * `$vars.a === "$vars.notAName"`; only the first is a reference. Template literals
72
+ * (backticks) are LEFT INTACT on purpose — the SDK's `tmpl` emits real references
73
+ * inside their `${…}`, and a literal `$vars.` in the surrounding URL/message text
74
+ * is not a thing the serializer produces. Escapes are honored so a quote inside a
75
+ * literal does not end it early.
76
+ */
77
+ function maskStringLiterals(expr) {
78
+ return expr.replace(/'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/g, (m) => m[0] + ' '.repeat(m.length - 2) + m[m.length - 1]);
79
+ }
80
+ const SEGMENT = /\??\.([A-Za-z_$][\w$]*)|\[(\d+)\]/g;
81
+ function escapeRegExp(s) {
82
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
83
+ }
84
+ /**
85
+ * A `<namespace>.<root><path>` reference matcher. The root is a JS identifier;
86
+ * the path is any run of `.ident`, `?.ident`, or `[<digits>]` selectors — the
87
+ * same shape the platform's variable-path grammar admits. The leading
88
+ * `(?<![\w.$])` keeps `case` from matching inside `mycase` or as the `.case`
89
+ * member of something else — only a namespace at a token boundary counts (the
90
+ * engine's own `DetectIdentifiers` uses the same guard).
91
+ */
92
+ function refRegex(namespace) {
93
+ return new RegExp(`(?<![\\w.$])${escapeRegExp(namespace)}\\.([A-Za-z_$][\\w$]*)((?:\\??\\.[A-Za-z_$][\\w$]*|\\[\\d+\\])*)`, 'g');
94
+ }
95
+ /**
96
+ * Every `<namespace>.*` reference in an expression, in source order, with literals
97
+ * masked so a reference-shaped substring inside a string is not counted.
98
+ * `namespace` defaults to `$vars` (Flow); Case passes `case`.
99
+ */
100
+ export function extractRefs(expr, namespace = DEFAULT_NAMESPACE) {
101
+ const masked = maskStringLiterals(expr);
102
+ const refs = [];
103
+ for (const m of masked.matchAll(refRegex(namespace))) {
104
+ const [raw, root, tail] = m;
105
+ const path = tail
106
+ ? Array.from(tail.matchAll(SEGMENT), (s) => (s[2] !== undefined ? `[${s[2]}]` : s[1]))
107
+ : [];
108
+ refs.push({ root, path, raw });
109
+ }
110
+ return refs;
111
+ }
112
+ /** True when `a` and `b` are equal or one edit (insert/delete/substitute) apart. */
113
+ function editDistanceLE1(a, b) {
114
+ if (a === b)
115
+ return true;
116
+ const la = a.length;
117
+ const lb = b.length;
118
+ if (Math.abs(la - lb) > 1)
119
+ return false;
120
+ let i = 0;
121
+ while (i < la && i < lb && a[i] === b[i])
122
+ i++;
123
+ if (la === lb)
124
+ return a.slice(i + 1) === b.slice(i + 1); // substitution
125
+ return la > lb ? a.slice(i + 1) === b.slice(i) : a.slice(i) === b.slice(i + 1); // insert/delete
126
+ }
127
+ /**
128
+ * The declared root `name` is most likely a typo of, if any: a case-only mismatch
129
+ * (strongest signal, any length) or — for names long enough that an edit is
130
+ * unlikely to be a coincidence (≥ 4 chars) — one edit away.
131
+ */
132
+ function nearMiss(name, roots) {
133
+ const lower = name.toLowerCase();
134
+ let oneEdit;
135
+ for (const r of roots) {
136
+ const rl = r.toLowerCase();
137
+ if (rl === lower)
138
+ return r; // case-only difference — the strongest typo signal
139
+ if (oneEdit === undefined && Math.max(rl.length, lower.length) >= 4 && editDistanceLE1(lower, rl)) {
140
+ oneEdit = r;
141
+ }
142
+ }
143
+ return oneEdit;
144
+ }
145
+ /**
146
+ * First-level check of ONE expression: every reference's root must resolve.
147
+ *
148
+ * Returns a diagnostic per unresolved root (deduped, so `$vars.x + $vars.x` is one
149
+ * message). An empty result means "nothing this check is sure is wrong" — never
150
+ * "fully valid"; the `validate` CLI is what proves the rest.
151
+ */
152
+ export function checkExpression(expr, scope) {
153
+ const namespace = scope.namespace ?? DEFAULT_NAMESPACE;
154
+ const noun = scope.noun ?? 'input, variable, or step';
155
+ const diags = [];
156
+ const seen = new Set();
157
+ // Syntax first: an expression that does not parse cannot have meaningful
158
+ // references, and reporting both would just be noise on one root cause.
159
+ const syntax = scope.syntax === 'javascript' ? syntaxError(expr) : undefined;
160
+ if (syntax) {
161
+ return [{
162
+ level: 'error',
163
+ code: 'EXPR_SYNTAX',
164
+ message: `Expression is not valid JavaScript: ${syntax}`,
165
+ ...(JSONPATH_WILDCARD.test(expr)
166
+ ? {
167
+ suggestion: 'This looks like JSONPath. The runtime evaluates JavaScript, so index or map '
168
+ + 'explicitly — `…issues` for the whole array, `…issues.map(i => i.key)` for one field.',
169
+ }
170
+ : {}),
171
+ }];
172
+ }
173
+ for (const ref of extractRefs(expr, namespace)) {
174
+ if (scope.roots.has(ref.root) || seen.has(ref.root))
175
+ continue;
176
+ seen.add(ref.root);
177
+ const near = nearMiss(ref.root, scope.roots);
178
+ diags.push({
179
+ level: 'error',
180
+ code: 'EXPR_UNDECLARED_REF',
181
+ message: `Expression references \`${namespace}.${ref.root}\`, but no ${noun} named "${ref.root}" is declared.`,
182
+ ...(near ? { suggestion: near } : {}),
183
+ });
184
+ }
185
+ return diags;
186
+ }