@uipath/maestro-builder-sdk 6.7.0 → 6.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api-index.md CHANGED
@@ -406,8 +406,8 @@ could hand you spans for a version you do not have.
406
406
  | `ThrowOpts` | interface | `dist/bpmn/bpmn-sdk.d.ts:616-624` | Option shapes | Options for `.intermediateThrowEvent()` — a `message` to throw, or none. |
407
407
  | `TimerLike` | type | `dist/bpmn/bpmn-sdk.d.ts:37-38` | Supporting types | A timer as an ISO-8601 duration string (shorthand for `{ duration }`) or a full spec. |
408
408
  | `TimerSpec` | interface | `dist/bpmn/bpmn-sdk.d.ts:28-36` | Supporting types | ISO-8601 timer specification (one of duration / date / cycle). |
409
- | `TypedContextRow` | interface | `dist/bpmn/typed-node.d.ts:141-172` | Supporting types | One `uipath:context` input row, spelled out. |
409
+ | `TypedContextRow` | interface | `dist/bpmn/typed-node.d.ts:152-183` | Supporting types | One `uipath:context` input row, spelled out. |
410
410
  | `TypeDesc` | type | `dist/core/expr.d.ts:323` | Supporting types | |
411
- | `TypedOutputRow` | interface | `dist/bpmn/typed-node.d.ts:173-197` | Supporting types | 8 field(s) |
411
+ | `TypedOutputRow` | interface | `dist/bpmn/typed-node.d.ts:184-208` | Supporting types | 8 field(s) |
412
412
  | `VarDirection` | type | `dist/bpmn/bpmn-sdk.d.ts:330-334` | Supporting types | How a variable is exposed: `'input'` (read-only entry input), `'output'` (a return value), or `'inputOutput'` (a mutable… |
413
413
  | `VarOpts` | interface | `dist/bpmn/bpmn-sdk.d.ts:1231-1255` | Option shapes | Options for `.var()` / `.input()` / `.output()`. |
@@ -84,7 +84,7 @@ not find it either.
84
84
  | `body` | property | `JsonSchemaType` | `dist/case/case-sdk.d.ts:539` |
85
85
  | `body` | property | `PortArm` | `dist/flow-sdk.d.ts:305-306` |
86
86
  | `body` | property | `SwitchArm` | `dist/flow-sdk.d.ts:293` |
87
- | `body` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:162-167` |
87
+ | `body` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:173-178` |
88
88
  | `boundaryEvent` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:1370-1377` |
89
89
  | `branch` | method | `StepList` | `dist/flow-sdk.d.ts:865-883` |
90
90
  | `branches` | property | `HttpInputsBase` | `dist/core/actions.d.ts:31-36` |
@@ -160,7 +160,7 @@ not find it either.
160
160
  | `conversationId` | property | `WaitForMessageInputs` | `dist/core/actions.d.ts:632-633` |
161
161
  | `count` | property | `BuiltSla` | `dist/case/case-sdk.d.ts:188` |
162
162
  | `count` | property | `SlaOpts` | `dist/case/case-sdk.d.ts:167-168` |
163
- | `custom` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:184-188` |
163
+ | `custom` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:195-199` |
164
164
  | `cycle` | property | `TimerSpec` | `dist/bpmn/bpmn-sdk.d.ts:34-35` |
165
165
  | `date` | property | `TimerSpec` | `dist/bpmn/bpmn-sdk.d.ts:32-33` |
166
166
  | `declare` | method | `BindingsRegistry` | `dist/bpmn/bpmn-sdk.d.ts:1267-1274` |
@@ -200,7 +200,7 @@ not find it either.
200
200
  | `description` | method | `StageBuilder` | `dist/case/case-sdk.d.ts:970-976` |
201
201
  | `description` | method | `TaskBuilder` | `dist/case/case-sdk.d.ts:906-912` |
202
202
  | `description` | property | `TimerTriggerOpts` | `dist/case/case-sdk.d.ts:223` |
203
- | `description` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:189-190` |
203
+ | `description` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:200-201` |
204
204
  | `description` | property | `VarDecl` | `dist/flow-sdk.d.ts:51-52` |
205
205
  | `description` | property | `VarSpec` | `dist/flow-sdk.d.ts:68-69` |
206
206
  | `detail` | property | `ErrorMappingRow` | `dist/bpmn/bpmn-sdk.d.ts:298-299` |
@@ -581,8 +581,8 @@ not find it either.
581
581
  | `name` | property | `TaskRef` | `dist/case/case-sdk.d.ts:410` |
582
582
  | `name` | property | `ThrowOpts` | `dist/bpmn/bpmn-sdk.d.ts:618-619` |
583
583
  | `name` | property | `TimerTriggerOpts` | `dist/case/case-sdk.d.ts:222` |
584
- | `name` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:156-157` |
585
- | `name` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:174-175` |
584
+ | `name` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:167-168` |
585
+ | `name` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:185-186` |
586
586
  | `name` | property | `VarDecl` | `dist/flow-sdk.d.ts:48` |
587
587
  | `name` | property | `VarOpts` | `dist/bpmn/bpmn-sdk.d.ts:1233-1234` |
588
588
  | `nodes` | property | `BuiltBpmn` | `dist/bpmn/bpmn-sdk.d.ts:411-412` |
@@ -704,7 +704,7 @@ not find it either.
704
704
  | `required` | property | `InOutField` | `dist/core/actions.d.ts:367-368` |
705
705
  | `required` | method | `StageBuilder` | `dist/case/case-sdk.d.ts:977-983` |
706
706
  | `required` | method | `TaskBuilder` | `dist/case/case-sdk.d.ts:884-890` |
707
- | `required` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:170-171` |
707
+ | `required` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:181-182` |
708
708
  | `required` | property | `VarOpts` | `dist/bpmn/bpmn-sdk.d.ts:1253-1254` |
709
709
  | `requiresConnection` | property | `ConnectorMeta` | `dist/core/connectors.d.ts:64` |
710
710
  | `requiresFolderKey` | property | `ConnectorMeta` | `dist/core/connectors.d.ts:65` |
@@ -760,7 +760,7 @@ not find it either.
760
760
  | `schema` | method | `BpmnBuilder` | `dist/bpmn/bpmn-sdk.d.ts:2105-2130` |
761
761
  | `schema` | property | `BpmnVarDecl` | `dist/bpmn/bpmn-sdk.d.ts:349-350` |
762
762
  | `schema` | property | `DynamicExtractInputs` | `dist/core/actions.d.ts:2262-2268` |
763
- | `schema` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:182-183` |
763
+ | `schema` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:193-194` |
764
764
  | `schema` | property | `VarDecl` | `dist/flow-sdk.d.ts:55-56` |
765
765
  | `schema` | property | `VarOpts` | `dist/bpmn/bpmn-sdk.d.ts:1239-1252` |
766
766
  | `schema` | property | `VarSpec` | `dist/flow-sdk.d.ts:72-73` |
@@ -814,7 +814,7 @@ not find it either.
814
814
  | `source` | property | `GuardrailFieldReference` | `dist/core/actions.d.ts:1272` |
815
815
  | `source` | property | `InlineAgentInputs` | `dist/core/actions.d.ts:1464-1473` |
816
816
  | `source` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:496-497` |
817
- | `source` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:180-181` |
817
+ | `source` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:191-192` |
818
818
  | `source` | property | `VoiceAgentInputs` | `dist/core/actions.d.ts:777-782` |
819
819
  | `sourceTrigger` | property | `CaseVarDecl` | `dist/case/case-sdk.d.ts:564-570` |
820
820
  | `splitPages` | property | `DocumentClassifyInputs` | `dist/core/actions.d.ts:2234-2235` |
@@ -855,8 +855,8 @@ not find it either.
855
855
  | `tags` | property | `ProcessMetadata` | `dist/bpmn/bpmn-sdk.d.ts:442-443` |
856
856
  | `target` | property | `BpmnFlow` | `dist/bpmn/bpmn-sdk.d.ts:323-324` |
857
857
  | `target` | property | `EscalationRecipient` | `dist/case/case-sdk.d.ts:122-123` |
858
- | `target` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:168-169` |
859
- | `target` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:191-196` |
858
+ | `target` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:179-180` |
859
+ | `target` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:202-207` |
860
860
  | `task` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:1423-1430` |
861
861
  | `task` | method | `StageBuilder` | `dist/case/case-sdk.d.ts:984-1003` |
862
862
  | `tasks` | property | `RuleOpts` | `dist/case/case-sdk.d.ts:40-55` |
@@ -910,8 +910,8 @@ not find it either.
910
910
  | `type` | property | `ShownField` | `dist/core/actions.d.ts:331` |
911
911
  | `type` | property | `TaskInputBinding` | `dist/case/case-sdk.d.ts:487` |
912
912
  | `type` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:498` |
913
- | `type` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:158-159` |
914
- | `type` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:176-177` |
913
+ | `type` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:169-170` |
914
+ | `type` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:187-188` |
915
915
  | `type` | property | `VarDecl` | `dist/flow-sdk.d.ts:49` |
916
916
  | `type` | property | `VarSpec` | `dist/flow-sdk.d.ts:66-67` |
917
917
  | `typeVersion` | property | `ActivityNodeOpts` | `dist/bpmn/bpmn-sdk.d.ts:1173-1188` |
@@ -939,13 +939,13 @@ not find it either.
939
939
  | `value` | property | `ShownField` | `dist/core/actions.d.ts:333-339` |
940
940
  | `value` | property | `SwitchArm` | `dist/flow-sdk.d.ts:291` |
941
941
  | `value` | property | `TaskInputBinding` | `dist/case/case-sdk.d.ts:485-486` |
942
- | `value` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:160-161` |
942
+ | `value` | property | `TypedContextRow` | `dist/bpmn/typed-node.d.ts:171-172` |
943
943
  | `values` | property | `DataFabricCreateInputs` | `dist/core/actions.d.ts:2142-2147` |
944
944
  | `var` | method | `CaseBuilder` | `dist/case/case-sdk.d.ts:1199-1223` |
945
945
  | `var` | method | `FlowBuilder` | `dist/flow-sdk.d.ts:1329-1338` |
946
946
  | `var` | method | `ScopeBuilder` | `dist/bpmn/bpmn-sdk.d.ts:1926-1934` |
947
947
  | `var` | property | `TaskOutputBinding` | `dist/case/case-sdk.d.ts:494-495` |
948
- | `var` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:178-179` |
948
+ | `var` | property | `TypedOutputRow` | `dist/bpmn/typed-node.d.ts:189-190` |
949
949
  | `variables` | property | `BuiltBpmn` | `dist/bpmn/bpmn-sdk.d.ts:403-404` |
950
950
  | `variant` | property | `EscalationRef` | `dist/core/actions.d.ts:1868-1876` |
951
951
  | `variant` | property | `HitlInputs` | `dist/core/actions.d.ts:540-544` |
@@ -0,0 +1,22 @@
1
+ import type { RegistryTypeSpec } from './typed-node.js';
2
+ /**
3
+ * Shape a raw registry `ExtensionType` into the spec the emitter reads.
4
+ *
5
+ * Deliberately the same field-for-field mapping as `trim()` in
6
+ * `scripts/materialize-bpmn-registry.mjs`. They are pinned together by
7
+ * `bpmn-registry-fallback.test.ts`, which resolves a type the snapshot ALREADY
8
+ * carries through this path and asserts the result deep-equals the committed
9
+ * entry — so the two cannot drift for any type that matters without a red test.
10
+ */
11
+ export declare function shapeExtensionType(spec: Record<string, any>): RegistryTypeSpec;
12
+ /**
13
+ * Resolve an extension type the snapshot does not carry, from the registry.
14
+ *
15
+ * @param type - The extension type, e.g. `'Maestro.CasePlanScheduler'`.
16
+ * @returns Its emission spec, or `undefined` when the fallback is disabled, `uip`
17
+ * cannot answer, or the registry has no such type either — in which case the type
18
+ * really is wrong, not merely new.
19
+ */
20
+ export declare function resolveFromRegistry(type: string): RegistryTypeSpec | undefined;
21
+ /** Test seam: forget resolved specs, the pull, and the warning. */
22
+ export declare function resetRegistryFallback(): void;
@@ -0,0 +1,206 @@
1
+ /**
2
+ * bpmn/registry-fallback — resolve an extension type the committed snapshot does
3
+ * not carry, by asking the registry through `uip`.
4
+ *
5
+ * `registry-types.json` is a snapshot, and a snapshot is always behind the
6
+ * platform by however long it has been since someone ran
7
+ * `scripts/materialize-bpmn-registry.mjs`. Until now a type outside it was simply
8
+ * unauthorable: `registryType()` threw, and the author had nowhere to go, because
9
+ * the SDK's whole discovery surface — the typed methods, `dist/api-members.md`,
10
+ * `registryTypeNames()` — is generated from that same snapshot. A type it has
11
+ * never heard of is invisible, not merely unsupported.
12
+ *
13
+ * That cost a full point on `skill-bpmn-contract-variant-wrappers` in the
14
+ * 2026-09-23 v1-vs-v2 run: the task wanted `Maestro.CasePlanScheduler`, the
15
+ * snapshot was stamped `uipVersion: 1.201.0-preview.122` against a `1.204.0-dev`
16
+ * CLI, the type was not in its 30, and the agent had no way to learn the name.
17
+ * The v1 arm ran `uip maestro bpmn registry search` and found it in one command.
18
+ *
19
+ * So: snapshot first, CLI second. The snapshot stays the fast, offline,
20
+ * reviewable default and nothing about a hit changes. A miss is no longer fatal
21
+ * — it costs one subprocess, warns loudly, and tells the author to refresh the
22
+ * snapshot so the next build is offline again.
23
+ *
24
+ * What this deliberately does NOT do:
25
+ *
26
+ * - **Write the snapshot back.** A build that silently rewrites its own spec
27
+ * source stops being reproducible, and `registry-types.json` exists so a spec
28
+ * change is a reviewable diff. The warning points at the materializer instead.
29
+ * - **Run for a type the snapshot already has.** Offline compilation of known
30
+ * types is the common path and must not acquire a tenant dependency.
31
+ * - **Retry forever.** One `registry get`; if that misses, one
32
+ * `registry pull --force` and one more `get`. Both outcomes are remembered
33
+ * for the process, so a file with ten unknown nodes costs at most two CLI
34
+ * calls, not twenty.
35
+ */
36
+ import { execFileSync } from 'node:child_process';
37
+ /** The `uip` binary. Matches `scripts/materialize-bpmn-registry.mjs`. */
38
+ const UIP = () => process.env.UIP ?? 'uip';
39
+ /**
40
+ * Set `FLOW_SDK_BPMN_REGISTRY_FALLBACK=0` to keep the resolver snapshot-only.
41
+ *
42
+ * For hermetic builds and for tests that must not reach a tenant: with it off, a
43
+ * miss throws exactly as it did before this module existed.
44
+ */
45
+ function fallbackEnabled() {
46
+ const v = process.env.FLOW_SDK_BPMN_REGISTRY_FALLBACK;
47
+ return v !== '0' && v !== 'false';
48
+ }
49
+ /** Resolved specs, and misses, for the life of the process. */
50
+ const resolved = new Map();
51
+ /** `registry pull --force` is tried at most once, however many types miss. */
52
+ let pulled = false;
53
+ /** One "you are resolving live" warning per process, not one per type. */
54
+ let warnedLive = false;
55
+ /**
56
+ * Run `uip` and return the `Data` of its JSON envelope, or `undefined`.
57
+ *
58
+ * Never throws: every failure mode here — no `uip` on PATH, not logged in, a
59
+ * `Result: Failure` envelope, a timeout — means the same thing to the caller
60
+ * (the type could not be resolved live) and the caller's error message is better
61
+ * than anything this could raise.
62
+ *
63
+ * `uip` prints a self-update failure to stderr before its real output, so stderr
64
+ * is ignored and stdout is parsed from its first `{`.
65
+ */
66
+ function uip(args, timeoutMs) {
67
+ let out;
68
+ try {
69
+ out = execFileSync(UIP(), args, {
70
+ encoding: 'utf8',
71
+ stdio: ['ignore', 'pipe', 'ignore'],
72
+ timeout: timeoutMs,
73
+ maxBuffer: 64 * 1024 * 1024,
74
+ });
75
+ }
76
+ catch {
77
+ return undefined;
78
+ }
79
+ const start = out.indexOf('{');
80
+ if (start === -1)
81
+ return undefined;
82
+ try {
83
+ const parsed = JSON.parse(out.slice(start));
84
+ if (parsed.Result !== 'Success')
85
+ return undefined;
86
+ return parsed.Data;
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ }
92
+ /**
93
+ * The element-specific child a typed node needs beyond its extension payload.
94
+ *
95
+ * Same rule as the materializer's: a message event is only a message event
96
+ * because of its `<bpmn:messageEventDefinition />`, and nothing else in the spec
97
+ * records that.
98
+ */
99
+ function eventDefinitionOf(template) {
100
+ const m = /<(bpmn:\w*EventDefinition)\s*\/?>/i.exec(typeof template === 'string' ? template : '');
101
+ return m ? m[1] : null;
102
+ }
103
+ /**
104
+ * Shape a raw registry `ExtensionType` into the spec the emitter reads.
105
+ *
106
+ * Deliberately the same field-for-field mapping as `trim()` in
107
+ * `scripts/materialize-bpmn-registry.mjs`. They are pinned together by
108
+ * `bpmn-registry-fallback.test.ts`, which resolves a type the snapshot ALREADY
109
+ * carries through this path and asserts the result deep-equals the committed
110
+ * entry — so the two cannot drift for any type that matters without a red test.
111
+ */
112
+ export function shapeExtensionType(spec) {
113
+ const context = (spec.ContextFields ?? []).map((f) => ({
114
+ name: f.Name,
115
+ displayName: f.DisplayName ?? null,
116
+ type: f.Type ?? 'string',
117
+ required: Boolean(f.Required),
118
+ hidden: Boolean(f.Hidden),
119
+ binding: Boolean(f.Binding),
120
+ default: f.DefaultValue ?? null,
121
+ bindingInfo: f.BindingInfo
122
+ ? {
123
+ resource: f.BindingInfo.Resource ?? null,
124
+ propertyAttribute: f.BindingInfo.PropertyAttribute ?? null,
125
+ }
126
+ : null,
127
+ }));
128
+ const inputs = (spec.InputFields ?? []).map((f) => ({
129
+ name: f.Name,
130
+ displayName: f.DisplayName ?? null,
131
+ type: f.Type ?? 'string',
132
+ required: Boolean(f.Required),
133
+ hidden: Boolean(f.Hidden),
134
+ target: f.Target ?? null,
135
+ default: f.DefaultValue ?? null,
136
+ }));
137
+ // The output is FLAT on the payload — `OutputName`/`OutputType`/`OutputSource`/
138
+ // `UseRelativeSource`, not a nested `Output` object — and its type defaults to
139
+ // `jsonSchema`, not `json`. Both were guessed wrong first and caught by the
140
+ // drift pin in `bpmn-registry-fallback.test.ts`.
141
+ const output = spec.OutputName == null
142
+ ? null
143
+ : {
144
+ name: spec.OutputName,
145
+ type: spec.OutputType ?? 'jsonSchema',
146
+ source: spec.OutputSource ?? null,
147
+ relative: Boolean(spec.UseRelativeSource),
148
+ };
149
+ return {
150
+ element: spec.BpmnElement ?? null,
151
+ tag: spec.ExtensionTag ?? null,
152
+ inputPattern: spec.InputPattern ?? 'none',
153
+ inputName: spec.InputName ?? null,
154
+ inputTarget: spec.InputTarget ?? null,
155
+ context,
156
+ inputs,
157
+ output,
158
+ eventDefinition: eventDefinitionOf(spec.XmlTemplate),
159
+ requiresDiscovery: Boolean(spec.RequiresDiscovery),
160
+ bindingPattern: spec.BindingPattern ?? 'none',
161
+ };
162
+ }
163
+ /** `registry get <type>`, shaped, or `undefined` when the registry has no such type. */
164
+ function get(type) {
165
+ const data = uip(['maestro', 'bpmn', 'registry', 'get', type, '--output', 'json'], 60_000);
166
+ const spec = data?.ExtensionType;
167
+ return spec ? shapeExtensionType(spec) : undefined;
168
+ }
169
+ /**
170
+ * Resolve an extension type the snapshot does not carry, from the registry.
171
+ *
172
+ * @param type - The extension type, e.g. `'Maestro.CasePlanScheduler'`.
173
+ * @returns Its emission spec, or `undefined` when the fallback is disabled, `uip`
174
+ * cannot answer, or the registry has no such type either — in which case the type
175
+ * really is wrong, not merely new.
176
+ */
177
+ export function resolveFromRegistry(type) {
178
+ if (!fallbackEnabled())
179
+ return undefined;
180
+ const seen = resolved.get(type);
181
+ if (seen !== undefined)
182
+ return seen ?? undefined;
183
+ let spec = get(type);
184
+ // `registry get` answers from a local cache that does not refresh itself, so a
185
+ // type added since the last pull reads as absent. One forced pull per process,
186
+ // then one retry — beyond that the type is genuinely unknown.
187
+ if (!spec && !pulled) {
188
+ pulled = true;
189
+ uip(['maestro', 'bpmn', 'registry', 'pull', '--force', '--output', 'json'], 180_000);
190
+ spec = get(type);
191
+ }
192
+ resolved.set(type, spec ?? null);
193
+ if (spec && !warnedLive) {
194
+ warnedLive = true;
195
+ process.stderr.write(` warn: extension type "${type}" is not in the committed registry snapshot; resolved it live `
196
+ + `through \`uip maestro bpmn registry get\`. This build needed a tenant. Run \`node `
197
+ + `scripts/materialize-bpmn-registry.mjs\` and commit the result to make it offline again.\n`);
198
+ }
199
+ return spec;
200
+ }
201
+ /** Test seam: forget resolved specs, the pull, and the warning. */
202
+ export function resetRegistryFallback() {
203
+ resolved.clear();
204
+ pulled = false;
205
+ warnedLive = false;
206
+ }
@@ -98,12 +98,23 @@ export declare function registryTypeNames(): string[];
98
98
  /**
99
99
  * The spec for one extension type.
100
100
  *
101
+ * Snapshot first — that is the offline, reviewable, common path, and a hit costs
102
+ * a property read. On a MISS the registry is asked directly through `uip`
103
+ * ({@link resolveFromRegistry}), because a snapshot is always behind the platform
104
+ * by however long it has been since the last refresh, and a type outside it used
105
+ * to be unauthorable rather than merely unsupported: the typed methods,
106
+ * `dist/api-members.md` and {@link registryTypeNames} are all generated from this
107
+ * same file, so an author had no way even to learn the name. Set
108
+ * `FLOW_SDK_BPMN_REGISTRY_FALLBACK=0` to keep resolution snapshot-only.
109
+ *
101
110
  * @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
102
111
  * @returns Its emission spec.
103
- * @throws If the type is not in the committed snapshot — which means either a
104
- * typo or a registry refresh the snapshot has not caught up with.
112
+ * @throws If the type is in neither the snapshot nor the registry — which means a
113
+ * typo, or no `uip` to ask.
105
114
  */
106
115
  export declare function registryType(type: string): RegistryTypeSpec;
116
+ /** True when the snapshot itself carries the type — no tenant needed to emit it. */
117
+ export declare function isSnapshotType(type: string): boolean;
107
118
  /**
108
119
  * Facts the platform enforces but the registry does not state.
109
120
  *
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from 'node:module';
2
+ import { resolveFromRegistry } from './registry-fallback.js';
2
3
  const require = createRequire(import.meta.url);
3
4
  const REGISTRY = require('./registry-types.json');
4
5
  /** Every extension type in the snapshot, sorted. */
@@ -8,19 +9,35 @@ export function registryTypeNames() {
8
9
  /**
9
10
  * The spec for one extension type.
10
11
  *
12
+ * Snapshot first — that is the offline, reviewable, common path, and a hit costs
13
+ * a property read. On a MISS the registry is asked directly through `uip`
14
+ * ({@link resolveFromRegistry}), because a snapshot is always behind the platform
15
+ * by however long it has been since the last refresh, and a type outside it used
16
+ * to be unauthorable rather than merely unsupported: the typed methods,
17
+ * `dist/api-members.md` and {@link registryTypeNames} are all generated from this
18
+ * same file, so an author had no way even to learn the name. Set
19
+ * `FLOW_SDK_BPMN_REGISTRY_FALLBACK=0` to keep resolution snapshot-only.
20
+ *
11
21
  * @param type - The extension type, e.g. `'Intsvc.UnifiedHttpRequest'`.
12
22
  * @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.
23
+ * @throws If the type is in neither the snapshot nor the registry — which means a
24
+ * typo, or no `uip` to ask.
15
25
  */
16
26
  export function registryType(type) {
17
- const spec = REGISTRY.types[type];
27
+ const spec = REGISTRY.types[type] ?? resolveFromRegistry(type);
18
28
  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.');
29
+ throw new Error(`unknown extension type "${type}". The committed registry snapshot has ${REGISTRY.provenance.typeCount} types `
30
+ + `(uip ${REGISTRY.provenance.uipVersion}) and the registry could not be asked for this one either — `
31
+ + 'no `uip` on PATH, not logged in, or the type does not exist. '
32
+ + 'Check the spelling with `uip maestro bpmn registry search <term>`, then refresh the snapshot with '
33
+ + '`node scripts/materialize-bpmn-registry.mjs`.');
21
34
  }
22
35
  return spec;
23
36
  }
37
+ /** True when the snapshot itself carries the type — no tenant needed to emit it. */
38
+ export function isSnapshotType(type) {
39
+ return Object.hasOwn(REGISTRY.types, type);
40
+ }
24
41
  /**
25
42
  * Facts the platform enforces but the registry does not state.
26
43
  *
package/dist/check.js CHANGED
@@ -1250,7 +1250,7 @@ function checkConnectorLookups(step, spec, opts, diags) {
1250
1250
  const declared = specs?.[named];
1251
1251
  const by = value.__lookup.by;
1252
1252
  if (declared && typeof by === 'string' && !declared.by.includes(by)) {
1253
- const { target, call } = lookupPhrases(named, declared);
1253
+ const { target, call } = lookupPhrases(named, declared, spec);
1254
1254
  diags.push({
1255
1255
  level: 'error',
1256
1256
  code: 'LOOKUP_UNKNOWN_MATCH_KEY',
@@ -1302,7 +1302,7 @@ function checkConnectorLookups(step, spec, opts, diags) {
1302
1302
  const literal = value instanceof Expr ? value.value : value;
1303
1303
  if (typeof literal !== 'string')
1304
1304
  return;
1305
- const { target, call } = lookupPhrases(field, lookup);
1305
+ const { target, call } = lookupPhrases(field, lookup, spec);
1306
1306
  diags.push({
1307
1307
  level: 'warning',
1308
1308
  code: 'LOOKUP_LITERAL_ID',
@@ -1439,13 +1439,32 @@ function checkConnectorContract(step, spec, opts, diags) {
1439
1439
  }
1440
1440
  }
1441
1441
  }
1442
- /** The two phrases every lookup diagnostic needs: what the field sends, and how to resolve it. */
1443
- function lookupPhrases(field, lookup) {
1442
+ /**
1443
+ * The two phrases every lookup diagnostic needs: what the field sends, and how
1444
+ * to resolve it.
1445
+ *
1446
+ * The `call` names BOTH authoring forms, and names which one the alias belongs
1447
+ * to. Printing `lookup(<Descriptor>, 'entityName').byDisplayName('<value>')`
1448
+ * alone — the old text — was a remedy with an unstated precondition: aliases
1449
+ * are generated onto the descriptor, and `<Descriptor>` is a placeholder the
1450
+ * reader has to fill from somewhere. An author holding the connector key and
1451
+ * action instead (the form the library's Generic CRUD half is authored in, and
1452
+ * the majority of its lookup fields) substitutes those for the placeholder,
1453
+ * keeps the alias, and gets `lookup(...).byDisplayName is not a function`. Six
1454
+ * flow-eval tasks did precisely that, each losing a check-edit-check round to
1455
+ * a message that had told them to.
1456
+ */
1457
+ function lookupPhrases(field, lookup, spec) {
1444
1458
  const target = `${lookup.objectName ?? lookup.path}.${lookup.value}`;
1459
+ const by = lookup.by[0] ?? 'id';
1445
1460
  const alias = Object.keys(lookup.aliases)[0];
1461
+ // The key/action form first: it needs no import, so it is the one line that
1462
+ // is paste-ready from the message alone.
1463
+ const generic = `lookup('${spec.key}', '${spec.action}', '${field}').by('${by}', '<value>')`;
1446
1464
  const call = alias
1447
- ? `lookup(<Descriptor>, '${field}').${alias}('<value>')`
1448
- : `lookup(<Descriptor>, '${field}').by('${lookup.by[0] ?? 'id'}', '<value>')`;
1465
+ ? `${generic}\n or \`lookup(D, '${field}').${alias}('<value>')\`, where D is the `
1466
+ + `descriptor \`${prepareCommand(spec.key, spec.action)}\` generates — the aliases exist only there`
1467
+ : generic;
1449
1468
  return { target, call };
1450
1469
  }
1451
1470
  /**
@@ -1502,7 +1521,7 @@ function runtimeLookupDiagnostic(step, spec, field, lookup, value) {
1502
1521
  || leaf.toLowerCase() === valueLeaf.toLowerCase()
1503
1522
  || (valueIsEmail && EMAIL_LEAF.test(leaf))))
1504
1523
  return undefined;
1505
- const { target, call } = lookupPhrases(field, lookup);
1524
+ const { target, call } = lookupPhrases(field, lookup, spec);
1506
1525
  const searchesByEmail = lookup.by.some((b) => EMAIL_LEAF.test(b));
1507
1526
  const isEmail = !!leaf && EMAIL_LEAF.test(leaf) && !valueIsEmail && !searchesByEmail;
1508
1527
  const message = `Connector step "${step}": \`${field}\` is a lookup field bound to the runtime expression `
@@ -1401,7 +1401,7 @@ export interface InlineAgentInputs {
1401
1401
  * argument after the reference PATH, `__`-joined. For a flow input the two
1402
1402
  * coincide (`$vars.notes` → `notes`); for a step output they do not, and a sidecar
1403
1403
  * still saying `{{input.claim}}` templates against a key that is not there — the
1404
- * literal text reaches the model. See `skill/references/inline-agent.md`
1404
+ * literal text reaches the model. See the inline-agent node reference (`website/reference/inline-agent.md`)
1405
1405
  * §"The three prompt DIALECTS".
1406
1406
  *
1407
1407
  * If the agent has to answer in a shape the flow then reads, say so here. The
@@ -2611,7 +2611,7 @@ export declare function batchTransform(inputs: BatchTransformInputs): ActionSpec
2611
2611
  * with zero envelopes among them. The RUNTIME
2612
2612
  * accepts both, so only `uip maestro flow validate` sees a wrong one; the
2613
2613
  * emitter's exemption lives in `migrate.ts` (`UNWRAPPED_INPUTS`).
2614
- * See `skill/references/ixp.md` §3.
2614
+ * See the IxP node reference (`website/reference/ixp.md`) §3.
2615
2615
  *
2616
2616
  * @example
2617
2617
  * **Extract an invoice total and read it out of the nested result**
@@ -3130,9 +3130,9 @@ export declare function dynamicExtract(inputs: DynamicExtractInputs): ActionSpec
3130
3130
  * ```
3131
3131
  *
3132
3132
  * A connector operation's body fields come from the entity, so the library
3133
- * cannot carry them: run `npx flow-sdk registry prepare uipath-uipath-dataservice
3134
- * get-entity-record-by-id -f entityName=<Entity>` first (`uip maestro registry
3135
- * prepare …` is the same command when you are driving through the UiPath CLI).
3133
+ * cannot carry them: run `uip maestro registry prepare uipath-uipath-dataservice
3134
+ * get-entity-record-by-id -f entityName=<Entity>` first (`npx flow-sdk registry
3135
+ * prepare …` is the same command when invoking the package's own bin directly).
3136
3136
  * The routing table is in the `data-fabric.md` reference and the parent-field
3137
3137
  * loop in `connector-params.md` — cited by name rather than linked, because this
3138
3138
  * comment renders both into the flat corpus, where those files sit alongside
@@ -345,7 +345,7 @@ export function batchTransform(inputs) {
345
345
  * with zero envelopes among them. The RUNTIME
346
346
  * accepts both, so only `uip maestro flow validate` sees a wrong one; the
347
347
  * emitter's exemption lives in `migrate.ts` (`UNWRAPPED_INPUTS`).
348
- * See `skill/references/ixp.md` §3.
348
+ * See the IxP node reference (`website/reference/ixp.md`) §3.
349
349
  *
350
350
  * @example
351
351
  * **Extract an invoice total and read it out of the nested result**
@@ -917,9 +917,9 @@ export function dynamicExtract(inputs) {
917
917
  * ```
918
918
  *
919
919
  * A connector operation's body fields come from the entity, so the library
920
- * cannot carry them: run `npx flow-sdk registry prepare uipath-uipath-dataservice
921
- * get-entity-record-by-id -f entityName=<Entity>` first (`uip maestro registry
922
- * prepare …` is the same command when you are driving through the UiPath CLI).
920
+ * cannot carry them: run `uip maestro registry prepare uipath-uipath-dataservice
921
+ * get-entity-record-by-id -f entityName=<Entity>` first (`npx flow-sdk registry
922
+ * prepare …` is the same command when invoking the package's own bin directly).
923
923
  * The routing table is in the `data-fabric.md` reference and the parent-field
924
924
  * loop in `connector-params.md` — cited by name rather than linked, because this
925
925
  * comment renders both into the flat corpus, where those files sit alongside
@@ -46,7 +46,53 @@ export function isLookupToken(v) {
46
46
  export function lookupKey(nodeType, field, by, value) {
47
47
  return JSON.stringify([nodeType, field, by, value]);
48
48
  }
49
- function makeBuilder(nodeType, field, spec) {
49
+ /**
50
+ * An alias-shaped property: `byEmail`, `byDisplayName`, `byAccountId`.
51
+ *
52
+ * Narrow on purpose. The builder is handed to whatever inspects it next —
53
+ * `util.inspect`, a `then` probe on an accidental `await`, a spread — and a
54
+ * trap that answered for EVERY absent name would turn those into throws. Only
55
+ * a name the author could have meant as an alias is intercepted.
56
+ */
57
+ const ALIAS_SHAPE = /^by[A-Z]/;
58
+ /**
59
+ * Why `.byDisplayName()` is absent, in the terms of the form that was used.
60
+ *
61
+ * Aliases are generated from the descriptor's own `lookups` table, so the
62
+ * string form — which has no table to read — offers only `.by(name, value)`.
63
+ * That is a deliberate trade (see the overload's `@remarks`), but the author
64
+ * who trips it learns it as `lookup(...).byDisplayName is not a function`: a
65
+ * bare `TypeError` naming neither the field, the form, nor the way out. Six
66
+ * flow-eval tasks lost turns to exactly that message, every one of them having
67
+ * copied an alias out of a diagnostic or a descriptor's doc comment and pasted
68
+ * it onto the key/action form they happened to be holding.
69
+ */
70
+ function missingAliasMessage(nodeType, field, alias, spec, generic) {
71
+ const head = `lookup(${nodeType}, '${field}'): \`.${alias}()\` does not exist. `;
72
+ if (!spec) {
73
+ // The remedy names the author's OWN key and action rather than a
74
+ // placeholder: a remedy with a hole in it is what produced this call.
75
+ const here = generic
76
+ ? `lookup('${generic.key}', '${generic.action}', '${field}')`
77
+ : `lookup(…, '${field}')`;
78
+ return head
79
+ + `Aliases are generated onto the descriptor, and this call has no descriptor `
80
+ + `to read them from, so only \`.by(name, value)\` exists here. Search by name:\n`
81
+ + ` ${here}.by('<searchable name>', <value>)\n`
82
+ + `\`check\` and \`${prepareCommand()}\` both print the names this field is `
83
+ + `searchable by. Or import the descriptor `
84
+ + (generic ? `\`${prepareCommand(generic.key, generic.action)}\` generates ` : '')
85
+ + `and call \`.${alias}(<value>)\` on that.`;
86
+ }
87
+ const aliases = Object.keys(spec.aliases);
88
+ return head
89
+ + (aliases.length
90
+ ? `Generated aliases for this field: ${aliases.map((a) => `\`.${a}()\``).join(', ')}. `
91
+ : `This field earns no alias — two of its names camelise to one, so both were dropped. `)
92
+ + `Every searchable name is reachable as `
93
+ + `\`.by(${spec.by.map((b) => `'${b}'`).join(' | ')}, <value>)\`.`;
94
+ }
95
+ function makeBuilder(nodeType, field, spec, generic) {
50
96
  const token = (by, value) => ({ __lookup: { nodeType, field, by, value } });
51
97
  const builder = {
52
98
  by(name, value) {
@@ -63,7 +109,19 @@ function makeBuilder(nodeType, field, spec) {
63
109
  for (const [alias, byName] of Object.entries(spec?.aliases ?? {})) {
64
110
  builder[alias] = (value) => token(byName, value);
65
111
  }
66
- return builder;
112
+ // The throw is deferred to the CALL rather than raised on the property read,
113
+ // so the stack points at `.byDisplayName('Inbox')` — the line the author
114
+ // wrote — instead of at the property access the engine desugared it into.
115
+ return new Proxy(builder, {
116
+ get(target, prop, receiver) {
117
+ if (typeof prop === 'string' && !(prop in target) && ALIAS_SHAPE.test(prop)) {
118
+ return () => {
119
+ throw new Error(missingAliasMessage(nodeType, field, prop, spec, generic));
120
+ };
121
+ }
122
+ return Reflect.get(target, prop, receiver);
123
+ },
124
+ });
67
125
  }
68
126
  export function lookup(a, b, c) {
69
127
  if (typeof a === 'string') {
@@ -71,7 +129,7 @@ export function lookup(a, b, c) {
71
129
  throw new Error("lookup(key, action, field) needs all three arguments; " +
72
130
  "did you mean lookup(descriptor, field)?");
73
131
  }
74
- return makeBuilder(`uipath.connector.${a}.${b}`, c);
132
+ return makeBuilder(`uipath.connector.${a}.${b}`, c, undefined, { key: a, action: b });
75
133
  }
76
134
  if (!('nodeType' in a) || a.nodeType === undefined) {
77
135
  const event = a;
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ export { serialize as serializeCase } from './case/serialize.js';
25
25
  export { decompile as decompileCase, decompileWithDiagnostics as decompileCaseWithDiagnostics } from './case/decompile.js';
26
26
  export { bpmn } from './bpmn/bpmn-sdk.js';
27
27
  export type { BuiltBpmn, BpmnNode, BpmnFlow, BpmnVarDecl, EventDef, GatewayKind, EventKind, LoopSpec, RetrySpec, ActivityOpts, HttpOpts, } from './bpmn/bpmn-sdk.js';
28
- export { registryTypeNames, registryType } from './bpmn/typed-node.js';
28
+ export { registryTypeNames, registryType, isSnapshotType } from './bpmn/typed-node.js';
29
29
  export type { RegistryTypeSpec, RegistryContextField, RegistryOutput } from './bpmn/typed-node.js';
30
30
  export { serialize as serializeBpmn } from './bpmn/serialize.js';
31
31
  export { check as checkBpmn } from './bpmn/check.js';
package/dist/index.js CHANGED
@@ -28,8 +28,10 @@ export { decompile as decompileCase, decompileWithDiagnostics as decompileCaseWi
28
28
  // BPMN authoring API. `bpmn()` exposes only BPMN methods.
29
29
  export { bpmn } from './bpmn/bpmn-sdk.js';
30
30
  // The registry snapshot the typed nodes emit from — exposed so the coverage
31
- // ledger and its audit read the same source the emitter does.
32
- export { registryTypeNames, registryType } from './bpmn/typed-node.js';
31
+ // ledger and its audit read the same source the emitter does. `isSnapshotType`
32
+ // separates the two answers `registryType` now gives: a type the snapshot carries
33
+ // emits offline, one it does not is resolved from the registry through `uip`.
34
+ export { registryTypeNames, registryType, isSnapshotType } from './bpmn/typed-node.js';
33
35
  export { serialize as serializeBpmn } from './bpmn/serialize.js';
34
36
  export { check as checkBpmn } from './bpmn/check.js';
35
37
  export { check as checkCase } from './case/check.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.7.0",
3
+ "version": "6.8.1",
4
4
  "description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.uipath.com/maestro",
@@ -87,5 +87,5 @@
87
87
  "@types/node": "^22.7.0",
88
88
  "esbuild": "^0.28.1"
89
89
  },
90
- "gitref": "598c3b8dd2e0f063680d817fee10b2a6dd21ec6a"
90
+ "gitref": "5ec4e9cb4aeac6a5297078cfd071d7c38784fed3"
91
91
  }