@uipath/maestro-builder-sdk 6.68.1 → 6.68.2

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.
@@ -383,15 +383,23 @@ export interface BuiltCaseExitCondition {
383
383
  export type TaskKind = 'process' | 'agent' | 'rpa' | 'api-workflow' | 'case-management' | 'flow-process' | 'function' | 'business-rule' | 'external-agent' | 'external-workflow' | 'action' | 'connector' | 'wait-for-timer' | 'wait-for-connector';
384
384
  /**
385
385
  * Task kinds that the Case schema permits as unresolved skeletons: the
386
- * published-resource kinds, and `action` (a human task whose Action App or form
387
- * is not known yet). Each compiles to a task whose `data` is `{}`, which
388
- * `uip maestro case validate` reports as a `TASK_NOT_CONFIGURED` warning.
386
+ * published-resource kinds, `action` (a human task whose Action App or form is
387
+ * not known yet), and the two connector kinds, `connector` (an
388
+ * `execute-connector-activity` task) and `wait-for-connector`, for a connector
389
+ * or event the spec leaves unresolved. Each compiles to a task whose `data` is
390
+ * `{}`, which `uip maestro case validate` reports as a `TASK_NOT_CONFIGURED`
391
+ * warning.
389
392
  */
390
- export type UnresolvedReferenceTaskKind = 'process' | 'agent' | 'rpa' | 'api-workflow' | 'case-management' | 'function' | 'action';
393
+ export type UnresolvedReferenceTaskKind = 'process' | 'agent' | 'rpa' | 'api-workflow' | 'case-management' | 'function' | 'action' | 'connector' | 'wait-for-connector';
391
394
  /**
392
395
  * A `wait-for-connector` subscription: suspend on an Integration Service event.
393
- * Omit `connectorKey`/`operation` for a bare **placeholder** (for a connector not
394
- * yet registered — `data.uipath` carries only `serviceType`).
396
+ * Omit `connectorKey`/`operation` for a bare **placeholder**, the same task as
397
+ * `.unresolved('wait-for-connector')`: its `data` is `{}`.
398
+ *
399
+ * Setting them is the legacy named form, which `uip maestro case validate`
400
+ * refuses on a task (`CASE_MGMT_CONNECTOR_ACTIVITY_UNRESOLVED`, #1560): for an
401
+ * unresolved event use `.unresolved('wait-for-connector')`, and for a known one
402
+ * a trigger descriptor or `{ connector, event }`.
395
403
  */
396
404
  export interface WaitConnectorPlaceholderSpec {
397
405
  /** Connector key, e.g. `uipath-microsoft-outlook365`. */
@@ -875,8 +883,20 @@ declare class TaskBuilder {
875
883
  * `unresolved('action')` is the human-task skeleton: no Action App, title,
876
884
  * recipient or form fields, for an app that is not published yet. Use
877
885
  * `.action({ ... })` instead once the form is known.
886
+ * `unresolved('connector')` and `unresolved('wait-for-connector')` are the
887
+ * connector placeholders, for a connector key, activity or event the spec
888
+ * leaves unresolved: do not pick a real connector to stand in for it. Use
889
+ * `.connector(...)` or `.waitForConnector(...)` once it is known.
890
+ *
891
+ * @example
892
+ * **Leave both connector tasks of an SDD with an `<UNRESOLVED>` connector as placeholders**
893
+ * ```ts
894
+ * casePlan('notice').stage('Notice', (s) => s
895
+ * .task('Notify regulator', (t) => t.unresolved('connector'))
896
+ * .task('Await notice', (t) => t.unresolved('wait-for-connector')))
897
+ * ```
878
898
  *
879
- * @param kind - The task kind to preserve: a published-resource family, or `'action'` for a human task.
899
+ * @param kind - The task kind to preserve: a published-resource family, `'action'` for a human task, or `'connector'` / `'wait-for-connector'` for a connector task.
880
900
  * @returns This builder, so calls chain.
881
901
  */
882
902
  unresolved(kind: UnresolvedReferenceTaskKind): this;
@@ -1061,7 +1081,7 @@ declare class TaskBuilder {
1061
1081
  /**
1062
1082
  * A wait-for-connector task in placeholder or stringly-resolved form.
1063
1083
  *
1064
- * @param spec - Omit for a placeholder, pass `connectorKey`/`operation` for the legacy named placeholder,
1084
+ * @param spec - Omit for a placeholder (`data: {}`, the same task as `.unresolved('wait-for-connector')`), pass `connectorKey`/`operation` for the legacy named form, which `uip maestro case validate` refuses on a task (#1560; for an unresolved event use `.unresolved('wait-for-connector')`),
1065
1085
  * or pass a symbolic `{ connector, event, ... }` subscription for library resolution.
1066
1086
  * @returns This builder, so calls chain.
1067
1087
  */
@@ -4,6 +4,7 @@ import { checkCaseExpressions, CaseBuildError } from './case-expr-check.js';
4
4
  import { CASE_FORMAT_PROFILE, CASE_SCHEMA_VERSIONS, recordAuthoredCaseVersion } from './format-profile.js';
5
5
  import { schemaVersionRefusal } from '../schema-version.js';
6
6
  import { CompileRefusal } from '../core/compile-refusal.js';
7
+ import { isConnectorPlaceholder } from './connector-placeholder.js';
7
8
  export { preserveCaseJson } from './preserve.js';
8
9
  export { CaseBuildError } from './case-expr-check.js';
9
10
  /**
@@ -208,8 +209,20 @@ class TaskBuilder {
208
209
  * `unresolved('action')` is the human-task skeleton: no Action App, title,
209
210
  * recipient or form fields, for an app that is not published yet. Use
210
211
  * `.action({ ... })` instead once the form is known.
212
+ * `unresolved('connector')` and `unresolved('wait-for-connector')` are the
213
+ * connector placeholders, for a connector key, activity or event the spec
214
+ * leaves unresolved: do not pick a real connector to stand in for it. Use
215
+ * `.connector(...)` or `.waitForConnector(...)` once it is known.
211
216
  *
212
- * @param kind - The task kind to preserve: a published-resource family, or `'action'` for a human task.
217
+ * @example
218
+ * **Leave both connector tasks of an SDD with an `<UNRESOLVED>` connector as placeholders**
219
+ * ```ts
220
+ * casePlan('notice').stage('Notice', (s) => s
221
+ * .task('Notify regulator', (t) => t.unresolved('connector'))
222
+ * .task('Await notice', (t) => t.unresolved('wait-for-connector')))
223
+ * ```
224
+ *
225
+ * @param kind - The task kind to preserve: a published-resource family, `'action'` for a human task, or `'connector'` / `'wait-for-connector'` for a connector task.
213
226
  * @returns This builder, so calls chain.
214
227
  */
215
228
  unresolved(kind) {
@@ -585,6 +598,14 @@ class TaskBuilder {
585
598
  throw new CompileRefusal('TASK_IO_UNRESOLVED_REFERENCE', `task "${this._name}": an unresolved reference task cannot declare inputs or outputs.`);
586
599
  if (!this._action && !this._ref && this._kind === 'action' && this._outputs)
587
600
  throw new CompileRefusal('TASK_IO_UNRESOLVED_REFERENCE', `task "${this._name}": an unresolved action task cannot declare outputs.`);
601
+ // A connector placeholder's `data` must stay `{}` (connector-placeholder.ts):
602
+ // any output row, an `{ assign }` one included, would make it a configured
603
+ // task the CLI refuses for naming no activity.
604
+ if (this._kind === 'connector' && this._outputs?.length && isConnectorPlaceholder({ kind: this._kind, connector: this._connector, waitConnector: this._waitConnector }))
605
+ throw new CompileRefusal('TASK_IO_UNRESOLVED_REFERENCE', `task "${this._name}": an unresolved connector task cannot declare outputs. Remove the outputs, or resolve the connector with .connector(...) first.`);
606
+ if (this._kind === 'wait-for-connector' && this._outputs?.length && !extract
607
+ && isConnectorPlaceholder({ kind: this._kind, connector: this._connector, waitConnector: this._waitConnector }))
608
+ throw new CompileRefusal('TASK_IO_UNRESOLVED_REFERENCE', `task "${this._name}": an unresolved wait-for-connector task cannot declare outputs. Remove the outputs, or name the event with .waitForConnector(<trigger descriptor>) first.`);
588
609
  if (this._kind === 'wait-for-connector' && extract
589
610
  && !(this._waitConnector && 'connector' in this._waitConnector && 'event' in this._waitConnector))
590
611
  throw new CompileRefusal('TASK_OUTPUTS_PLACEHOLDER_EVENT', `task "${this._name}": a placeholder wait-for-connector task has no event response to extract outputs from — name the event (.waitForConnector(<trigger descriptor>) or { connector, event }).`);
@@ -9,6 +9,7 @@ import { checkEventResolution } from '../core/event-checks.js';
9
9
  import { EXTERNAL_TASK_DESCRIPTOR_CONTRACT, EXTERNAL_TASK_HYBRID_UNSUPPORTED, externalHybridRefusal, isExternalExecutionMode } from './external.js';
10
10
  import { isResourceLabelRefusal, resolveResourceRef } from './resource-identity.js';
11
11
  import { taskShapeProblems } from './task-shape.js';
12
+ import { isConnectorPlaceholder } from './connector-placeholder.js';
12
13
  const TYPE_NAMES = new Set(Object.values(types));
13
14
  // audit-case-coverage: rule-slot table start
14
15
  // This runtime table must equal the committed matrix's rejected cells. The audit
@@ -362,7 +363,8 @@ function checkLibraryConnectors(built, opts, diags) {
362
363
  rules(stage.exit, `stage "${stage.label}" exit`);
363
364
  for (const t of stage.lanes.flat()) {
364
365
  rules(t.entry, `task "${t.name}" entry`);
365
- if (t.kind === 'connector' && t.connector) {
366
+ // A placeholder (`.unresolved('connector')`) names no operation to resolve.
367
+ if (t.kind === 'connector' && t.connector && !isConnectorPlaceholder(t)) {
366
368
  const where = `Connector task "${t.name}"`;
367
369
  const spec = t.connector;
368
370
  checkConnectorLookups(where, spec, opts, EQUALS_EXPR_DIALECT, reporter(where, t.name));
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The one definition of a Case **connector placeholder**: a connector task
3
+ * (`execute-connector-activity`) or a wait-for-connector task whose connector
4
+ * is not known yet (#1354).
5
+ *
6
+ * The contract is the CLI's. `uip maestro case validate` treats an empty task
7
+ * `data` as the unresolved placeholder and reports it with the
8
+ * `TASK_NOT_CONFIGURED` warning. Any other connector task `data`, however
9
+ * small, is judged as a configured task, and one without `metadata` and
10
+ * `objectName` context entries is refused with
11
+ * `CASE_MGMT_CONNECTOR_ACTIVITY_UNRESOLVED` (cli
12
+ * `packages/case-tool/src/services/case-validators/connector-activity-validator.ts`,
13
+ * `appliesTo` = connector task type and non-empty `data`).
14
+ *
15
+ * So, for example:
16
+ *
17
+ * t.unresolved('wait-for-connector') -> { type: 'wait-for-connector', data: {} }
18
+ * t.unresolved('connector') -> { type: 'execute-connector-activity', data: {} }
19
+ * t.waitForConnector() -> { type: 'wait-for-connector', data: {} }
20
+ *
21
+ * The SDK once wrote `{ serviceType: 'Intsvc.WaitForEvent' }` for the bare
22
+ * wait-for-connector task, after an older caseplan. The CLI refuses that, so
23
+ * it is only read here (decompile lifts it back to the placeholder) and never
24
+ * written.
25
+ *
26
+ * `serialize` writes the placeholder, `check` skips the library checks for it,
27
+ * the builder refuses outputs on it, and `decompile` reads it back, all through
28
+ * this module. A wait-for-connector *rule* is not a task and keeps its own
29
+ * subscription bag. A task that names its connector without resolving it
30
+ * (`.waitForConnector({ connectorKey, operation })`) is not a placeholder and
31
+ * still writes its `context`; the CLI refuses that too (#1560).
32
+ */
33
+ import type { BuiltTask, TaskKind } from './case-sdk.js';
34
+ /** The SDK task kinds that have a connector placeholder. */
35
+ export type ConnectorPlaceholderKind = Extract<TaskKind, 'connector' | 'wait-for-connector'>;
36
+ /**
37
+ * Whether a built task is a connector placeholder: a connector task with no
38
+ * connector call, or a wait-for-connector task that names no event (no
39
+ * resolved subscription and no `connectorKey` / `operation`).
40
+ *
41
+ * @param task - The task as the builder recorded it.
42
+ * @returns True when the task compiles to the placeholder `data: {}`.
43
+ */
44
+ export declare function isConnectorPlaceholder(task: Pick<BuiltTask, 'kind' | 'connector' | 'waitConnector'>): boolean;
45
+ /** The placeholder's `data`: empty, the shape the CLI reads as unresolved. */
46
+ export declare function connectorPlaceholderData(): Record<string, unknown>;
47
+ /**
48
+ * The SDK kind of a caseplan task that is a connector placeholder, or
49
+ * undefined when it is not one.
50
+ *
51
+ * Reads the CLI's placeholder (`data` empty or absent) on both connector task
52
+ * types, and, on a wait-for-connector task, the two shapes older SDKs wrote
53
+ * for it: `{ serviceType: 'Intsvc.WaitForEvent' }`, optionally with empty
54
+ * `inputs` / `outputs` / `bindings`, and that plus a `connectorKey` /
55
+ * `operation` context whose values are both `"placeholder"`.
56
+ *
57
+ * @param type - The task's wire `type`.
58
+ * @param data - The task's `data`.
59
+ * @returns The kind to lift it to with `.unresolved(kind)`, or undefined.
60
+ */
61
+ export declare function connectorPlaceholderKindOf(type: unknown, data: unknown): ConnectorPlaceholderKind | undefined;
@@ -0,0 +1,70 @@
1
+ import { CASE_FORMAT_PROFILE } from './format-profile.js';
2
+ /** The keys an older SDK's wait-for-connector placeholder bag carried. */
3
+ const LEGACY_WAIT_KEYS = new Set(['serviceType', 'context', 'inputs', 'outputs', 'bindings']);
4
+ /**
5
+ * Whether a built task is a connector placeholder: a connector task with no
6
+ * connector call, or a wait-for-connector task that names no event (no
7
+ * resolved subscription and no `connectorKey` / `operation`).
8
+ *
9
+ * @param task - The task as the builder recorded it.
10
+ * @returns True when the task compiles to the placeholder `data: {}`.
11
+ */
12
+ export function isConnectorPlaceholder(task) {
13
+ if (task.kind === 'connector')
14
+ return task.connector === undefined;
15
+ if (task.kind !== 'wait-for-connector')
16
+ return false;
17
+ const spec = task.waitConnector;
18
+ if (spec === undefined)
19
+ return true;
20
+ if ('connector' in spec && 'event' in spec)
21
+ return false;
22
+ return spec.connectorKey === undefined && spec.operation === undefined;
23
+ }
24
+ /** The placeholder's `data`: empty, the shape the CLI reads as unresolved. */
25
+ export function connectorPlaceholderData() {
26
+ return {};
27
+ }
28
+ /**
29
+ * The SDK kind of a caseplan task that is a connector placeholder, or
30
+ * undefined when it is not one.
31
+ *
32
+ * Reads the CLI's placeholder (`data` empty or absent) on both connector task
33
+ * types, and, on a wait-for-connector task, the two shapes older SDKs wrote
34
+ * for it: `{ serviceType: 'Intsvc.WaitForEvent' }`, optionally with empty
35
+ * `inputs` / `outputs` / `bindings`, and that plus a `connectorKey` /
36
+ * `operation` context whose values are both `"placeholder"`.
37
+ *
38
+ * @param type - The task's wire `type`.
39
+ * @param data - The task's `data`.
40
+ * @returns The kind to lift it to with `.unresolved(kind)`, or undefined.
41
+ */
42
+ export function connectorPlaceholderKindOf(type, data) {
43
+ const kind = type === CASE_FORMAT_PROFILE.connectorActivityNodeType ? 'connector'
44
+ : type === 'wait-for-connector' ? 'wait-for-connector'
45
+ : undefined;
46
+ if (!kind)
47
+ return undefined;
48
+ if (data === undefined || data === null)
49
+ return kind;
50
+ if (typeof data !== 'object' || Array.isArray(data))
51
+ return undefined;
52
+ const bag = data;
53
+ const keys = Object.keys(bag);
54
+ if (keys.length === 0)
55
+ return kind;
56
+ if (kind !== 'wait-for-connector' || bag.serviceType !== CASE_FORMAT_PROFILE.waitConnectorServiceType)
57
+ return undefined;
58
+ const emptyList = (value) => value === undefined || (Array.isArray(value) && value.length === 0);
59
+ if (!keys.every((key) => LEGACY_WAIT_KEYS.has(key)))
60
+ return undefined;
61
+ if (!['inputs', 'outputs', 'bindings'].every((key) => emptyList(bag[key])))
62
+ return undefined;
63
+ const context = bag.context;
64
+ if (context === undefined)
65
+ return kind;
66
+ const placeholderContext = Array.isArray(context) && context.length === 2
67
+ && ['connectorKey', 'operation'].every((name) => context
68
+ .some((row) => row?.name === name && row.value === 'placeholder'));
69
+ return placeholderContext ? kind : undefined;
70
+ }
@@ -7,6 +7,7 @@ import { ownEntry } from '../core/own-entry.js';
7
7
  import { isUnrestorableSlotId, taskFingerprint } from './preserve.js';
8
8
  import { isInSolutionKey, SOLUTION_FOLDER } from './resource-identity.js';
9
9
  import { offlineBindingLabel } from './ids.js';
10
+ import { connectorPlaceholderKindOf } from './connector-placeholder.js';
10
11
  const TASK_KIND_METHOD = {
11
12
  process: 'process',
12
13
  agent: 'agent',
@@ -698,6 +699,12 @@ function externalCall(task, refs, library) {
698
699
  function emitTaskKind(task, refs, library) {
699
700
  const kind = task.type;
700
701
  const data = task.data ?? {};
702
+ // A connector placeholder (connector-placeholder.ts): `data: {}`, or an older
703
+ // SDK's serviceType-only wait bag. It names no connector, so it needs no
704
+ // library and lifts to the call that compiles to `{}` again.
705
+ const placeholder = connectorPlaceholderKindOf(kind, task.data);
706
+ if (placeholder)
707
+ return `.unresolved(${tsLiteral(placeholder)})`;
701
708
  const method = ownEntry(TASK_KIND_METHOD, kind);
702
709
  if (method) {
703
710
  if (kind !== 'flow-process' && data.name === undefined && data.folderPath === undefined) {
@@ -756,7 +763,10 @@ function emitTaskKind(task, refs, library) {
756
763
  }
757
764
  if (kind === 'wait-for-connector') {
758
765
  const spec = waitConnectorSpec(data, `wait-for-connector task "${task.displayName ?? task.id ?? '?'}"`, refs);
759
- return spec === undefined ? '.waitForConnector()' : `.waitForConnector(${spec})`;
766
+ // A bag with no context and no resolved rows is the placeholder, lifted above.
767
+ if (spec === undefined)
768
+ throw new Error(`internal SDK error: wait-for-connector task "${task.displayName ?? task.id ?? '?'}" is a placeholder the lift above missed.`);
769
+ return `.waitForConnector(${spec})`;
760
770
  }
761
771
  const message = kind === 'business-rule'
762
772
  // The converter reads a missing version as v2, whose result shape differs
@@ -32,6 +32,7 @@ import { responseJsonSchema } from '../core/connector-response-schema.js';
32
32
  import { ruleShapeProblems } from './rule-options.js';
33
33
  import { CompileRefusal } from '../core/compile-refusal.js';
34
34
  import { taskShapeProblems } from './task-shape.js';
35
+ import { connectorPlaceholderData, isConnectorPlaceholder } from './connector-placeholder.js';
35
36
  /** The ids a serialize pass hashed from element ids, by the document it returned. */
36
37
  const ELEMENT_SEEDED_IDS = new WeakMap();
37
38
  function elementSeededId(resolver, elementId, suffix) {
@@ -1195,6 +1196,11 @@ function taskData(task, resolver, taskId, stageId, ids) {
1195
1196
  const [shape] = taskShapeProblems(task);
1196
1197
  if (shape)
1197
1198
  throw new CompileRefusal(shape.code, shape.message);
1199
+ // `.unresolved('connector' | 'wait-for-connector')` and a bare
1200
+ // `.waitForConnector()`: `data: {}`, the CLI's placeholder (validate warns
1201
+ // TASK_NOT_CONFIGURED). The builder lets no output reach one.
1202
+ if (isConnectorPlaceholder(task))
1203
+ return connectorPlaceholderData();
1198
1204
  switch (task.kind) {
1199
1205
  case 'process':
1200
1206
  case 'agent':
@@ -1280,8 +1286,8 @@ function taskData(task, resolver, taskId, stageId, ids) {
1280
1286
  return withCustomOutputs(data, task, resolver);
1281
1287
  }
1282
1288
  case 'wait-for-connector':
1283
- // Floor placeholder (no connector named) = `serviceType` only; naming the
1284
- // connector/operation emits the `context` subscription.
1289
+ // A placeholder returned `{}` above; naming the connector/operation emits
1290
+ // the `context` subscription, and a resolved one the full bag.
1285
1291
  return withOutputExtracts(waitConnectorBag(task.waitConnector, { alwaysContext: false }, resolver, `${stageId}-${taskId}`, `Wait-for-connector task "${task.name}"`), task, ids, resolver);
1286
1292
  }
1287
1293
  }
@@ -1327,12 +1333,14 @@ function withCustomOutputs(data, task, resolver) {
1327
1333
  return data;
1328
1334
  }
1329
1335
  /**
1330
- * The `wait-for-connector` subscription bag (`data` on the task, `uipath` on the
1331
- * rule). Verified against a real `uip maestro case` caseplan: a placeholder
1332
- * carries `serviceType: "Intsvc.WaitForEvent"`; naming the connector adds a
1333
- * two-entry `context` (connectorKey + operation, defaulting to `"placeholder"`)
1334
- * and empty `inputs`/`outputs`/`bindings`. A *rule* always carries the context —
1335
- * `validate` rejects a bare `uipath` ("connector activity missing").
1336
+ * The `wait-for-connector` subscription bag (`data` on a task that names its
1337
+ * connector, `uipath` on the rule). The bag carries
1338
+ * `serviceType: "Intsvc.WaitForEvent"`; naming the connector adds a two-entry
1339
+ * `context` (connectorKey + operation, defaulting to `"placeholder"`) and empty
1340
+ * `inputs`/`outputs`/`bindings`. A *rule* always carries the context —
1341
+ * `validate` rejects a bare `uipath` ("connector activity missing"). A task
1342
+ * that names no connector never gets here: its `data` is the placeholder `{}`
1343
+ * (connector-placeholder.ts).
1336
1344
  */
1337
1345
  function waitConnectorBag(spec, opts, resolver, elementId, where) {
1338
1346
  if (isResolvedSubscription(spec))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/maestro-builder-sdk",
3
- "version": "6.68.1",
3
+ "version": "6.68.2",
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",
@@ -100,5 +100,5 @@
100
100
  "@types/node": "^22.7.0",
101
101
  "esbuild": "^0.28.1"
102
102
  },
103
- "gitref": "cc5d3156131d305c073258591e362deb7f4fbbde"
103
+ "gitref": "169cc7e0b99153458305df193dd0336b44955b84"
104
104
  }