@uipath/uipath-typescript 1.4.2 → 1.5.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 (43) hide show
  1. package/dist/agent-memory/index.d.ts +4 -1
  2. package/dist/agents/index.cjs +341 -6
  3. package/dist/agents/index.d.ts +717 -16
  4. package/dist/agents/index.mjs +342 -7
  5. package/dist/assets/index.cjs +25 -9
  6. package/dist/assets/index.mjs +25 -9
  7. package/dist/attachments/index.cjs +25 -9
  8. package/dist/attachments/index.mjs +25 -9
  9. package/dist/buckets/index.cjs +25 -9
  10. package/dist/buckets/index.mjs +25 -9
  11. package/dist/cases/index.cjs +621 -524
  12. package/dist/cases/index.d.ts +186 -43
  13. package/dist/cases/index.mjs +621 -524
  14. package/dist/conversational-agent/index.cjs +25 -9
  15. package/dist/conversational-agent/index.mjs +25 -9
  16. package/dist/core/index.cjs +1 -1
  17. package/dist/core/index.mjs +1 -1
  18. package/dist/entities/index.cjs +25 -9
  19. package/dist/entities/index.mjs +25 -9
  20. package/dist/feedback/index.cjs +25 -9
  21. package/dist/feedback/index.mjs +25 -9
  22. package/dist/index.cjs +332 -62
  23. package/dist/index.d.ts +827 -89
  24. package/dist/index.mjs +333 -63
  25. package/dist/index.umd.js +332 -62
  26. package/dist/jobs/index.cjs +129 -14
  27. package/dist/jobs/index.d.ts +10 -5
  28. package/dist/jobs/index.mjs +129 -14
  29. package/dist/maestro-processes/index.cjs +198 -100
  30. package/dist/maestro-processes/index.d.ts +188 -43
  31. package/dist/maestro-processes/index.mjs +198 -100
  32. package/dist/processes/index.cjs +25 -9
  33. package/dist/processes/index.d.ts +6 -1
  34. package/dist/processes/index.mjs +25 -9
  35. package/dist/queues/index.cjs +25 -9
  36. package/dist/queues/index.mjs +25 -9
  37. package/dist/tasks/index.cjs +25 -9
  38. package/dist/tasks/index.d.ts +4 -1
  39. package/dist/tasks/index.mjs +25 -9
  40. package/dist/traces/index.cjs +2 -2
  41. package/dist/traces/index.d.ts +3 -3
  42. package/dist/traces/index.mjs +2 -2
  43. package/package.json +1 -1
@@ -44,6 +44,299 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
44
44
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
45
45
  };
46
46
 
47
+ /**
48
+ * Maps API field names (countOf*) to SDK field names (*Count) for InstanceStats,
49
+ * aligning naming with ElementStats and other count-suffixed conventions.
50
+ */
51
+ const InstanceStatsMap = {
52
+ countOfAllInstances: 'totalCount',
53
+ countOfRunning: 'runningCount',
54
+ countOfTransitioning: 'transitioningCount',
55
+ countOfPaused: 'pausedCount',
56
+ countOfFaulted: 'faultedCount',
57
+ countOfCompleted: 'completedCount',
58
+ countOfCancelled: 'cancelledCount',
59
+ countOfDeleted: 'deletedCount'
60
+ };
61
+
62
+ /**
63
+ * Converts a UTC timestamp string (e.g., "5/8/2026 11:20:17 AM") to ISO 8601 UTC format.
64
+ * Returns the original value if parsing fails.
65
+ */
66
+ function toISOUtc(value) {
67
+ const date = new Date(value + ' UTC');
68
+ return isNaN(date.getTime()) ? value : date.toISOString();
69
+ }
70
+ /**
71
+ * Transforms data by renaming each key in `data` exactly once, using the
72
+ * mapping (`sourceField → targetField`). Keys not present in the mapping
73
+ * pass through unchanged. The original (pre-rename) key is dropped — the
74
+ * result contains only the renamed key.
75
+ *
76
+ * Each rename is independent. If the mapping happens to contain chained
77
+ * entries (`a → b` and `b → c`), they do NOT compose: a field named `a`
78
+ * in `data` becomes `b` (not `c`), because the renames are applied based
79
+ * on the original data's keys, not the running result.
80
+ *
81
+ * @param data The source data to transform
82
+ * @param fieldMapping Object mapping source field names to target field names
83
+ * @returns Transformed data with mapped field names
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Single object transformation
88
+ * const data = { id: '123', userName: 'john' };
89
+ * const mapping = { id: 'userId', userName: 'name' };
90
+ * const result = transformData(data, mapping);
91
+ * // result = { userId: '123', name: 'john' }
92
+ *
93
+ * // Array transformation
94
+ * const dataArray = [
95
+ * { id: '123', userName: 'john' },
96
+ * { id: '456', userName: 'jane' }
97
+ * ];
98
+ * const result = transformData(dataArray, mapping);
99
+ * // result = [
100
+ * // { userId: '123', name: 'john' },
101
+ * // { userId: '456', name: 'jane' }
102
+ * // ]
103
+ *
104
+ * // No chaining — `a → b` does not become `a → c` even if the map has `b → c`.
105
+ * transformData({ a: 1 }, { a: 'b', b: 'c' });
106
+ * // result = { b: 1 }
107
+ * ```
108
+ */
109
+ function transformData(data, fieldMapping) {
110
+ // Pass null/undefined through unchanged — callers (e.g. AttachmentService.getById)
111
+ // may invoke this on optional fields that an OData `select` excluded.
112
+ if (data == null) {
113
+ return data;
114
+ }
115
+ // Handle array of objects
116
+ if (Array.isArray(data)) {
117
+ return data.map(item => transformData(item, fieldMapping));
118
+ }
119
+ // Walk the ORIGINAL data's keys, look up each in the mapping. One rename
120
+ // per data key — no mutation of an in-progress result, so chains can't form.
121
+ const result = {};
122
+ for (const [key, value] of Object.entries(data)) {
123
+ const renamedKey = fieldMapping[key] ?? key;
124
+ result[renamedKey] = value;
125
+ }
126
+ return result;
127
+ }
128
+ /**
129
+ * Converts a string from PascalCase to camelCase
130
+ * @param str The PascalCase string to convert
131
+ * @returns The camelCase version of the string
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * pascalToCamelCase('HelloWorld'); // 'helloWorld'
136
+ * pascalToCamelCase('TaskAssignmentCriteria'); // 'taskAssignmentCriteria'
137
+ * ```
138
+ */
139
+ function pascalToCamelCase(str) {
140
+ if (!str)
141
+ return str;
142
+ return str.charAt(0).toLowerCase() + str.slice(1);
143
+ }
144
+ /**
145
+ * Converts a string from camelCase to PascalCase
146
+ * @param str The camelCase string to convert
147
+ * @returns The PascalCase version of the string
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * camelToPascalCase('helloWorld'); // 'HelloWorld'
152
+ * camelToPascalCase('taskAssignmentCriteria'); // 'TaskAssignmentCriteria'
153
+ * ```
154
+ */
155
+ function camelToPascalCase(str) {
156
+ if (!str)
157
+ return str;
158
+ return str.charAt(0).toUpperCase() + str.slice(1);
159
+ }
160
+ /**
161
+ * Generic function to transform object keys using a provided case conversion function
162
+ * @param data The object to transform
163
+ * @param convertCase The function to convert each key
164
+ * @returns A new object with transformed keys
165
+ */
166
+ function transformCaseKeys(data, convertCase) {
167
+ // Handle array of objects
168
+ if (Array.isArray(data)) {
169
+ return data.map(item => {
170
+ // If the array element is a primitive (string, number, etc.), return it as is
171
+ if (item === null || typeof item !== 'object' || typeof item === 'string') {
172
+ return item;
173
+ }
174
+ // Only recursively transform if it's actually an object
175
+ return transformCaseKeys(item, convertCase);
176
+ });
177
+ }
178
+ const result = {};
179
+ for (const [key, value] of Object.entries(data)) {
180
+ const transformedKey = convertCase(key);
181
+ // Recursively transform nested objects and arrays
182
+ if (value !== null && typeof value === 'object') {
183
+ result[transformedKey] = transformCaseKeys(value, convertCase);
184
+ }
185
+ else {
186
+ result[transformedKey] = value;
187
+ }
188
+ }
189
+ return result;
190
+ }
191
+ /**
192
+ * Transforms an object's keys from PascalCase to camelCase
193
+ * @param data The object with PascalCase keys
194
+ * @returns A new object with all keys converted to camelCase
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * // Simple object
199
+ * pascalToCamelCaseKeys({ Id: "123", TaskName: "Invoice" });
200
+ * // Result: { id: "123", taskName: "Invoice" }
201
+ *
202
+ * // Nested object
203
+ * pascalToCamelCaseKeys({
204
+ * TaskId: "456",
205
+ * TaskDetails: { AssignedUser: "John", Priority: "High" }
206
+ * });
207
+ * // Result: {
208
+ * // taskId: "456",
209
+ * // taskDetails: { assignedUser: "John", priority: "High" }
210
+ * // }
211
+ *
212
+ * // Array of objects
213
+ * pascalToCamelCaseKeys([
214
+ * { Id: "1", IsComplete: false },
215
+ * { Id: "2", IsComplete: true }
216
+ * ]);
217
+ * // Result: [
218
+ * // { id: "1", isComplete: false },
219
+ * // { id: "2", isComplete: true }
220
+ * // ]
221
+ * ```
222
+ */
223
+ function pascalToCamelCaseKeys(data) {
224
+ return transformCaseKeys(data, pascalToCamelCase);
225
+ }
226
+ /**
227
+ * Transforms an object's keys from camelCase to PascalCase
228
+ * @param data The object with camelCase keys
229
+ * @returns A new object with all keys converted to PascalCase
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * // Simple object
234
+ * camelToPascalCaseKeys({ userId: "789", isActive: true });
235
+ * // Result: { UserId: "789", IsActive: true }
236
+ *
237
+ * // Nested object
238
+ * camelToPascalCaseKeys({
239
+ * taskId: "ABC123",
240
+ * submissionData: { customerName: "XYZ Corp" }
241
+ * });
242
+ * // Result: {
243
+ * // TaskId: "ABC123",
244
+ * // SubmissionData: { CustomerName: "XYZ Corp" }
245
+ * // }
246
+ *
247
+ * // Array of objects
248
+ * camelToPascalCaseKeys([
249
+ * { userId: "u1", roleType: "admin" },
250
+ * { userId: "u2", roleType: "user" }
251
+ * ]);
252
+ * // Result: [
253
+ * // { UserId: "u1", RoleType: "admin" },
254
+ * // { UserId: "u2", RoleType: "user" }
255
+ * // ]
256
+ * ```
257
+ */
258
+ function camelToPascalCaseKeys(data) {
259
+ return transformCaseKeys(data, camelToPascalCase);
260
+ }
261
+ /**
262
+ * Maps a field value in an object using a provided mapping object.
263
+ * Returns a new object with the mapped field value.
264
+ *
265
+ * @param obj The object to map
266
+ * @param field The field name to map
267
+ * @param valueMap The mapping object (from input value to output value)
268
+ * @returns A new object with the mapped field value
269
+ *
270
+ * @example
271
+ * const statusMap = { 0: 'Unassigned', 1: 'Pending', 2: 'Completed' };
272
+ * const task = { status: 1, id: 123 };
273
+ * const mapped = mapFieldValue(task, 'status', statusMap);
274
+ * // mapped = { status: 'Pending', id: 123 }
275
+ */
276
+ function _mapFieldValue(obj, field, valueMap) {
277
+ const lookupKey = String(obj[field]);
278
+ return {
279
+ ...obj,
280
+ [field]: lookupKey in valueMap
281
+ ? valueMap[lookupKey]
282
+ : obj[field],
283
+ };
284
+ }
285
+ /**
286
+ * General API response transformer with optional field value mapping.
287
+ *
288
+ * @param data - The API response data to transform
289
+ * @param options - Optional mapping options:
290
+ * - field: The field name to map (optional)
291
+ * - valueMap: The mapping object for the field (optional)
292
+ * - transform: A function to further transform the data (optional)
293
+ * @returns The transformed data, with field value mapped if specified
294
+ *
295
+ * @example
296
+ * // Just transform
297
+ * const result = applyDataTransforms(data);
298
+ *
299
+ * // Map a field value, then transform
300
+ * const result = applyDataTransforms(data, { field: 'status', valueMap: StatusMap });
301
+ *
302
+ * // Map a field value, then apply a custom transform
303
+ * const result = applyDataTransforms(data, { field: 'status', valueMap: StatusMap, transform: customTransform });
304
+ */
305
+ function applyDataTransforms(data, options) {
306
+ let result = data;
307
+ if (options?.field && options?.valueMap) {
308
+ result = _mapFieldValue(result, options.field, options.valueMap);
309
+ }
310
+ if (options?.transform) {
311
+ result = options.transform(result);
312
+ }
313
+ return result;
314
+ }
315
+ /**
316
+ * Adds a prefix to specified keys in an object, returning a new object.
317
+ * Only the provided keys are prefixed; all others are left unchanged.
318
+ *
319
+ * @param obj The source object
320
+ * @param prefix The prefix to add (e.g., '$')
321
+ * @param keys The keys to prefix (e.g., ['expand', 'filter'])
322
+ * @returns A new object with specified keys prefixed
323
+ *
324
+ * @example
325
+ * addPrefixToKeys({ expand: 'a', foo: 1 }, '$', ['expand']) // { $expand: 'a', foo: 1 }
326
+ */
327
+ function addPrefixToKeys(obj, prefix, keys) {
328
+ const result = {};
329
+ for (const [key, value] of Object.entries(obj)) {
330
+ if (keys.includes(key)) {
331
+ result[`${prefix}${key}`] = value;
332
+ }
333
+ else {
334
+ result[key] = value;
335
+ }
336
+ }
337
+ return result;
338
+ }
339
+
47
340
  /**
48
341
  * Internal types for Maestro Cases
49
342
  * These types are used internally by the cases service
@@ -136,6 +429,8 @@ const MAESTRO_ENDPOINTS = {
136
429
  INSTANCE_STATUS_BY_DATE: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/InstanceStatusByDate`,
137
430
  /** Top processes ranked by total duration */
138
431
  TOP_PROCESSES_BY_DURATION: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/TopProcessesByDuration`,
432
+ /** Instance stats (counts by status + duration percentiles) */
433
+ INSTANCE_COUNT_BY_STATUS: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/InstanceCountByStatus`,
139
434
  /** Element count by status for agentic instances (process and case) */
140
435
  ELEMENT_COUNT_BY_STATUS: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/ElementCountByStatus`,
141
436
  },
@@ -159,7 +454,26 @@ function createCaseMethods(caseData, service) {
159
454
  throw new Error('Process key is undefined');
160
455
  if (!caseData.packageId)
161
456
  throw new Error('Package ID is undefined');
162
- return service.getElementStats(caseData.processKey, caseData.packageId, startTime, endTime, packageVersion);
457
+ return service.getElementStats({
458
+ processKey: caseData.processKey,
459
+ packageId: caseData.packageId,
460
+ packageVersion,
461
+ startTime,
462
+ endTime,
463
+ });
464
+ },
465
+ getInstanceStats(startTime, endTime, packageVersion) {
466
+ if (!caseData.processKey)
467
+ throw new Error('Process key is undefined');
468
+ if (!caseData.packageId)
469
+ throw new Error('Package ID is undefined');
470
+ return service.getInstanceStats({
471
+ processKey: caseData.processKey,
472
+ packageId: caseData.packageId,
473
+ packageVersion,
474
+ startTime,
475
+ endTime,
476
+ });
163
477
  }
164
478
  };
165
479
  }
@@ -222,24 +536,21 @@ async function fetchInstanceStatusTimeline(postFn, startTime, endTime, isCaseMan
222
536
  return response.data ?? [];
223
537
  }
224
538
  /**
225
- * Builds the request body for the ElementCountByStatus endpoint.
539
+ * Builds the commonParams request body for Insights RTM endpoints
540
+ * that filter by process key, package, time range, and version.
226
541
  *
227
- * @param processKey - Process key to filter by
228
- * @param packageId - Package identifier
229
- * @param startTime - Start of the time range to query
230
- * @param endTime - End of the time range to query
231
- * @param packageVersion - Package version to filter by
232
- * @returns Request body for the ElementCountByStatus endpoint
542
+ * @param request - Process scope + time range to aggregate over
543
+ * @returns Request body with commonParams
233
544
  * @internal
234
545
  */
235
- function buildElementCountByStatusBody(processKey, packageId, startTime, endTime, packageVersion) {
546
+ function buildInsightsCommonBody(request) {
236
547
  return {
237
548
  commonParams: {
238
- processKey,
239
- packageId,
240
- startTime: startTime.getTime(),
241
- endTime: endTime.getTime(),
242
- version: packageVersion
549
+ processKey: request.processKey,
550
+ packageId: request.packageId,
551
+ startTime: request.startTime.getTime(),
552
+ endTime: request.endTime.getTime(),
553
+ version: request.packageVersion
243
554
  }
244
555
  };
245
556
  }
@@ -935,539 +1246,277 @@ function processODataArrayResponse(oDataResponse, successData) {
935
1246
  * Utility functions for platform detection
936
1247
  */
937
1248
  /**
938
- * Checks if code is running in a browser environment
939
- */
940
- const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
941
- isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
942
- const _params = isBrowser ? new URLSearchParams(window.location.search) : null;
943
- /**
944
- * True when the coded app has been loaded inside a host frame that explicitly
945
- * opted into token delegation by adding `?host=embed` to the iframe src URL.
946
- */
947
- const isHostEmbedded = isBrowser && window.self !== window.top && _params?.get('host') === 'embed';
948
- /**
949
- * The validated parent origin, read from the `?basedomain=` query param set
950
- * by the embedding host in the iframe src URL.
951
- * Mirrors the same mechanism used by ActionCenterTokenManager.
952
- * Non-null only when `?host=embed` is present and `?basedomain=` is a valid URL.
953
- */
954
- (() => {
955
- if (!isHostEmbedded)
956
- return null;
957
- const basedomain = _params?.get('basedomain');
958
- if (!basedomain)
959
- return null;
960
- try {
961
- return new URL(basedomain).origin;
962
- }
963
- catch {
964
- console.warn('embeddingOrigin: basedomain query param is not a valid URL', basedomain);
965
- return null;
966
- }
967
- })();
968
-
969
- /**
970
- * Base64 encoding/decoding
971
- */
972
- /**
973
- * Encodes a string to base64
974
- * @param str - The string to encode
975
- * @returns Base64 encoded string
976
- */
977
- function encodeBase64(str) {
978
- // TextEncoder for UTF-8 encoding (works in both browser and Node.js)
979
- const encoder = new TextEncoder();
980
- const data = encoder.encode(str);
981
- // Convert Uint8Array to base64
982
- if (isBrowser) {
983
- // Browser environment
984
- // Convert Uint8Array to binary string then to base64
985
- const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
986
- return btoa(binaryString);
987
- }
988
- else {
989
- // Node.js environment
990
- return Buffer.from(data).toString('base64');
991
- }
992
- }
993
- /**
994
- * Decodes a base64 string
995
- * @param base64 - The base64 string to decode
996
- * @returns Decoded string
997
- */
998
- function decodeBase64(base64) {
999
- let bytes;
1000
- if (isBrowser) {
1001
- // Browser environment
1002
- const binaryString = atob(base64);
1003
- bytes = new Uint8Array(binaryString.length);
1004
- for (let i = 0; i < binaryString.length; i++) {
1005
- bytes[i] = binaryString.charCodeAt(i);
1006
- }
1007
- }
1008
- else {
1009
- // Node.js environment
1010
- bytes = new Uint8Array(Buffer.from(base64, 'base64'));
1011
- }
1012
- // TextDecoder for UTF-8 decoding (works in both browser and Node.js)
1013
- const decoder = new TextDecoder();
1014
- return decoder.decode(bytes);
1015
- }
1016
-
1017
- /**
1018
- * PaginationManager handles the conversion between uniform cursor-based pagination
1019
- * and the specific pagination type for each service
1020
- */
1021
- class PaginationManager {
1022
- /**
1023
- * Create a pagination cursor for subsequent page requests
1024
- */
1025
- static createCursor({ pageInfo, type }) {
1026
- if (!pageInfo.hasMore) {
1027
- return undefined;
1028
- }
1029
- const cursorData = {
1030
- type,
1031
- pageSize: pageInfo.pageSize,
1032
- };
1033
- switch (type) {
1034
- case PaginationType.OFFSET:
1035
- if (pageInfo.currentPage) {
1036
- cursorData.pageNumber = pageInfo.currentPage + 1;
1037
- }
1038
- break;
1039
- case PaginationType.TOKEN:
1040
- if (pageInfo.continuationToken) {
1041
- cursorData.continuationToken = pageInfo.continuationToken;
1042
- }
1043
- else {
1044
- return undefined; // No continuation token, can't continue
1045
- }
1046
- break;
1047
- }
1048
- return {
1049
- value: encodeBase64(JSON.stringify(cursorData))
1050
- };
1051
- }
1052
- /**
1053
- * Create a paginated response with navigation cursors
1054
- */
1055
- static createPaginatedResponse({ pageInfo, type }, items) {
1056
- const nextCursor = PaginationManager.createCursor({ pageInfo, type });
1057
- // Create previous page cursor if applicable
1058
- let previousCursor = undefined;
1059
- if (pageInfo.currentPage && pageInfo.currentPage > 1) {
1060
- const prevCursorData = {
1061
- type,
1062
- pageNumber: pageInfo.currentPage - 1,
1063
- pageSize: pageInfo.pageSize,
1064
- };
1065
- previousCursor = {
1066
- value: encodeBase64(JSON.stringify(prevCursorData))
1067
- };
1068
- }
1069
- // Calculate total pages if we have totalCount and pageSize
1070
- let totalPages = undefined;
1071
- if (pageInfo.totalCount !== undefined && pageInfo.pageSize) {
1072
- totalPages = Math.ceil(pageInfo.totalCount / pageInfo.pageSize);
1073
- }
1074
- // Determine if this pagination type supports page jumping
1075
- const supportsPageJump = type === PaginationType.OFFSET;
1076
- // Create the result object with all fields, then filter out undefined values
1077
- const result = filterUndefined({
1078
- items,
1079
- totalCount: pageInfo.totalCount,
1080
- hasNextPage: pageInfo.hasMore,
1081
- nextCursor: nextCursor,
1082
- previousCursor: previousCursor,
1083
- currentPage: pageInfo.currentPage,
1084
- totalPages,
1085
- supportsPageJump
1086
- });
1087
- return result;
1088
- }
1089
- }
1090
-
1091
- /**
1092
- * Creates headers object from key-value pairs
1093
- * @param headersObj - Object containing header key-value pairs
1094
- * @returns Headers object with all values converted to strings
1095
- *
1096
- * @example
1097
- * ```typescript
1098
- * // Single header
1099
- * const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
1100
- *
1101
- * // Multiple headers
1102
- * const headers = createHeaders({
1103
- * 'X-UIPATH-FolderKey': '1234567890',
1104
- * 'X-UIPATH-OrganizationUnitId': 123,
1105
- * 'Accept': 'application/json'
1106
- * });
1107
- *
1108
- * // Using constants
1109
- * import { FOLDER_KEY, FOLDER_ID } from '../constants/headers';
1110
- * const headers = createHeaders({
1111
- * [FOLDER_KEY]: 'abc-123',
1112
- * [FOLDER_ID]: 456
1113
- * });
1114
- *
1115
- * // Empty headers
1116
- * const headers = createHeaders();
1117
- * ```
1118
- */
1119
- function createHeaders(headersObj) {
1120
- const headers = {};
1121
- for (const [key, value] of Object.entries(headersObj)) {
1122
- if (value !== undefined && value !== null) {
1123
- headers[key] = value.toString();
1124
- }
1125
- }
1126
- return headers;
1127
- }
1128
-
1129
- /**
1130
- * Common constants used across the SDK
1131
- */
1132
- /**
1133
- * Prefix used for OData query parameters
1134
- */
1135
- const ODATA_PREFIX = '$';
1136
- /**
1137
- * HTTP methods
1138
- */
1139
- const HTTP_METHODS = {
1140
- GET: 'GET',
1141
- POST: 'POST'};
1142
- /**
1143
- * OData pagination constants
1144
- */
1145
- const ODATA_PAGINATION = {
1146
- /** Default field name for items in a paginated OData response */
1147
- ITEMS_FIELD: 'value',
1148
- /** Default field name for total count in a paginated OData response */
1149
- TOTAL_COUNT_FIELD: '@odata.count'
1150
- };
1151
- /**
1152
- * SLA Summary pagination constants for page-number-based pagination
1153
- */
1154
- const SLA_SUMMARY_PAGINATION = {
1155
- /** Field name for items in SLA summary response */
1156
- ITEMS_FIELD: 'data',
1157
- /** Dot-notation path for total count in nested pagination object */
1158
- TOTAL_COUNT_FIELD: 'pagination.totalCount'
1159
- };
1160
- /**
1161
- * SLA Summary OFFSET pagination parameter names (page-number style, no skip conversion)
1162
- */
1163
- const SLA_SUMMARY_OFFSET_PARAMS = {
1164
- /** Page size parameter name */
1165
- PAGE_SIZE_PARAM: 'PageSize',
1166
- /** Page number parameter name (sent directly, not converted to skip) */
1167
- OFFSET_PARAM: 'PageNumber',
1168
- /** No count param needed */
1169
- COUNT_PARAM: undefined
1170
- };
1171
- /**
1172
- * Process Instance pagination constants for token-based pagination
1173
- */
1174
- const PROCESS_INSTANCE_PAGINATION = {
1175
- /** Field name for items in process instance response */
1176
- ITEMS_FIELD: 'instances',
1177
- /** Field name for continuation token in process instance response */
1178
- CONTINUATION_TOKEN_FIELD: 'nextPage'
1179
- };
1180
- /**
1181
- * OData OFFSET pagination parameter names (ODATA-style)
1249
+ * Checks if code is running in a browser environment
1182
1250
  */
1183
- const ODATA_OFFSET_PARAMS = {
1184
- /** OData page size parameter name */
1185
- PAGE_SIZE_PARAM: '$top',
1186
- /** OData offset parameter name */
1187
- OFFSET_PARAM: '$skip',
1188
- /** OData count parameter name */
1189
- COUNT_PARAM: '$count'
1190
- };
1251
+ const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
1252
+ isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
1253
+ const _params = isBrowser ? new URLSearchParams(window.location.search) : null;
1191
1254
  /**
1192
- * Bucket TOKEN pagination parameter names
1255
+ * True when the coded app has been loaded inside a host frame that explicitly
1256
+ * opted into token delegation by adding `?host=embed` to the iframe src URL.
1193
1257
  */
1194
- const BUCKET_TOKEN_PARAMS = {
1195
- /** Bucket page size parameter name */
1196
- PAGE_SIZE_PARAM: 'takeHint',
1197
- /** Bucket token parameter name */
1198
- TOKEN_PARAM: 'continuationToken'
1199
- };
1258
+ const isHostEmbedded = isBrowser && window.self !== window.top && _params?.get('host') === 'embed';
1200
1259
  /**
1201
- * Process Instance TOKEN pagination parameter names
1260
+ * The validated parent origin, read from the `?basedomain=` query param set
1261
+ * by the embedding host in the iframe src URL.
1262
+ * Mirrors the same mechanism used by ActionCenterTokenManager.
1263
+ * Non-null only when `?host=embed` is present and `?basedomain=` is a valid URL.
1202
1264
  */
1203
- const PROCESS_INSTANCE_TOKEN_PARAMS = {
1204
- /** Process instance page size parameter name */
1205
- PAGE_SIZE_PARAM: 'pageSize',
1206
- /** Process instance token parameter name */
1207
- TOKEN_PARAM: 'nextPage'
1208
- };
1265
+ (() => {
1266
+ if (!isHostEmbedded)
1267
+ return null;
1268
+ const basedomain = _params?.get('basedomain');
1269
+ if (!basedomain)
1270
+ return null;
1271
+ try {
1272
+ return new URL(basedomain).origin;
1273
+ }
1274
+ catch {
1275
+ console.warn('embeddingOrigin: basedomain query param is not a valid URL', basedomain);
1276
+ return null;
1277
+ }
1278
+ })();
1209
1279
 
1210
1280
  /**
1211
- * Converts a UTC timestamp string (e.g., "5/8/2026 11:20:17 AM") to ISO 8601 UTC format.
1212
- * Returns the original value if parsing fails.
1281
+ * Base64 encoding/decoding
1213
1282
  */
1214
- function toISOUtc(value) {
1215
- const date = new Date(value + ' UTC');
1216
- return isNaN(date.getTime()) ? value : date.toISOString();
1217
- }
1218
1283
  /**
1219
- * Transforms data by mapping fields according to the provided field mapping
1220
- * @param data The source data to transform
1221
- * @param fieldMapping Object mapping source field names to target field names
1222
- * @returns Transformed data with mapped field names
1223
- *
1224
- * @example
1225
- * ```typescript
1226
- * // Single object transformation
1227
- * const data = { id: '123', userName: 'john' };
1228
- * const mapping = { id: 'userId', userName: 'name' };
1229
- * const result = transformData(data, mapping);
1230
- * // result = { userId: '123', name: 'john' }
1231
- *
1232
- * // Array transformation
1233
- * const dataArray = [
1234
- * { id: '123', userName: 'john' },
1235
- * { id: '456', userName: 'jane' }
1236
- * ];
1237
- * const result = transformData(dataArray, mapping);
1238
- * // result = [
1239
- * // { userId: '123', name: 'john' },
1240
- * // { userId: '456', name: 'jane' }
1241
- * // ]
1242
- * ```
1284
+ * Encodes a string to base64
1285
+ * @param str - The string to encode
1286
+ * @returns Base64 encoded string
1243
1287
  */
1244
- function transformData(data, fieldMapping) {
1245
- // Handle array of objects
1246
- if (Array.isArray(data)) {
1247
- return data.map(item => transformData(item, fieldMapping));
1288
+ function encodeBase64(str) {
1289
+ // TextEncoder for UTF-8 encoding (works in both browser and Node.js)
1290
+ const encoder = new TextEncoder();
1291
+ const data = encoder.encode(str);
1292
+ // Convert Uint8Array to base64
1293
+ if (isBrowser) {
1294
+ // Browser environment
1295
+ // Convert Uint8Array to binary string then to base64
1296
+ const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
1297
+ return btoa(binaryString);
1248
1298
  }
1249
- // Handle single object
1250
- const result = { ...data };
1251
- for (const [sourceField, targetField] of Object.entries(fieldMapping)) {
1252
- if (sourceField in result) {
1253
- const value = result[sourceField];
1254
- delete result[sourceField];
1255
- result[targetField] = value;
1256
- }
1299
+ else {
1300
+ // Node.js environment
1301
+ return Buffer.from(data).toString('base64');
1257
1302
  }
1258
- return result;
1259
- }
1260
- /**
1261
- * Converts a string from PascalCase to camelCase
1262
- * @param str The PascalCase string to convert
1263
- * @returns The camelCase version of the string
1264
- *
1265
- * @example
1266
- * ```typescript
1267
- * pascalToCamelCase('HelloWorld'); // 'helloWorld'
1268
- * pascalToCamelCase('TaskAssignmentCriteria'); // 'taskAssignmentCriteria'
1269
- * ```
1270
- */
1271
- function pascalToCamelCase(str) {
1272
- if (!str)
1273
- return str;
1274
- return str.charAt(0).toLowerCase() + str.slice(1);
1275
1303
  }
1276
1304
  /**
1277
- * Converts a string from camelCase to PascalCase
1278
- * @param str The camelCase string to convert
1279
- * @returns The PascalCase version of the string
1280
- *
1281
- * @example
1282
- * ```typescript
1283
- * camelToPascalCase('helloWorld'); // 'HelloWorld'
1284
- * camelToPascalCase('taskAssignmentCriteria'); // 'TaskAssignmentCriteria'
1285
- * ```
1305
+ * Decodes a base64 string
1306
+ * @param base64 - The base64 string to decode
1307
+ * @returns Decoded string
1286
1308
  */
1287
- function camelToPascalCase(str) {
1288
- if (!str)
1289
- return str;
1290
- return str.charAt(0).toUpperCase() + str.slice(1);
1309
+ function decodeBase64(base64) {
1310
+ let bytes;
1311
+ if (isBrowser) {
1312
+ // Browser environment
1313
+ const binaryString = atob(base64);
1314
+ bytes = new Uint8Array(binaryString.length);
1315
+ for (let i = 0; i < binaryString.length; i++) {
1316
+ bytes[i] = binaryString.charCodeAt(i);
1317
+ }
1318
+ }
1319
+ else {
1320
+ // Node.js environment
1321
+ bytes = new Uint8Array(Buffer.from(base64, 'base64'));
1322
+ }
1323
+ // TextDecoder for UTF-8 decoding (works in both browser and Node.js)
1324
+ const decoder = new TextDecoder();
1325
+ return decoder.decode(bytes);
1291
1326
  }
1327
+
1292
1328
  /**
1293
- * Generic function to transform object keys using a provided case conversion function
1294
- * @param data The object to transform
1295
- * @param convertCase The function to convert each key
1296
- * @returns A new object with transformed keys
1329
+ * PaginationManager handles the conversion between uniform cursor-based pagination
1330
+ * and the specific pagination type for each service
1297
1331
  */
1298
- function transformCaseKeys(data, convertCase) {
1299
- // Handle array of objects
1300
- if (Array.isArray(data)) {
1301
- return data.map(item => {
1302
- // If the array element is a primitive (string, number, etc.), return it as is
1303
- if (item === null || typeof item !== 'object' || typeof item === 'string') {
1304
- return item;
1305
- }
1306
- // Only recursively transform if it's actually an object
1307
- return transformCaseKeys(item, convertCase);
1308
- });
1309
- }
1310
- const result = {};
1311
- for (const [key, value] of Object.entries(data)) {
1312
- const transformedKey = convertCase(key);
1313
- // Recursively transform nested objects and arrays
1314
- if (value !== null && typeof value === 'object') {
1315
- result[transformedKey] = transformCaseKeys(value, convertCase);
1332
+ class PaginationManager {
1333
+ /**
1334
+ * Create a pagination cursor for subsequent page requests
1335
+ */
1336
+ static createCursor({ pageInfo, type }) {
1337
+ if (!pageInfo.hasMore) {
1338
+ return undefined;
1316
1339
  }
1317
- else {
1318
- result[transformedKey] = value;
1340
+ const cursorData = {
1341
+ type,
1342
+ pageSize: pageInfo.pageSize,
1343
+ };
1344
+ switch (type) {
1345
+ case PaginationType.OFFSET:
1346
+ if (pageInfo.currentPage) {
1347
+ cursorData.pageNumber = pageInfo.currentPage + 1;
1348
+ }
1349
+ break;
1350
+ case PaginationType.TOKEN:
1351
+ if (pageInfo.continuationToken) {
1352
+ cursorData.continuationToken = pageInfo.continuationToken;
1353
+ }
1354
+ else {
1355
+ return undefined; // No continuation token, can't continue
1356
+ }
1357
+ break;
1319
1358
  }
1359
+ return {
1360
+ value: encodeBase64(JSON.stringify(cursorData))
1361
+ };
1362
+ }
1363
+ /**
1364
+ * Create a paginated response with navigation cursors
1365
+ */
1366
+ static createPaginatedResponse({ pageInfo, type }, items) {
1367
+ const nextCursor = PaginationManager.createCursor({ pageInfo, type });
1368
+ // Create previous page cursor if applicable
1369
+ let previousCursor = undefined;
1370
+ if (pageInfo.currentPage && pageInfo.currentPage > 1) {
1371
+ const prevCursorData = {
1372
+ type,
1373
+ pageNumber: pageInfo.currentPage - 1,
1374
+ pageSize: pageInfo.pageSize,
1375
+ };
1376
+ previousCursor = {
1377
+ value: encodeBase64(JSON.stringify(prevCursorData))
1378
+ };
1379
+ }
1380
+ // Calculate total pages if we have totalCount and pageSize
1381
+ let totalPages = undefined;
1382
+ if (pageInfo.totalCount !== undefined && pageInfo.pageSize) {
1383
+ totalPages = Math.ceil(pageInfo.totalCount / pageInfo.pageSize);
1384
+ }
1385
+ // Determine if this pagination type supports page jumping
1386
+ const supportsPageJump = type === PaginationType.OFFSET;
1387
+ // Create the result object with all fields, then filter out undefined values
1388
+ const result = filterUndefined({
1389
+ items,
1390
+ totalCount: pageInfo.totalCount,
1391
+ hasNextPage: pageInfo.hasMore,
1392
+ nextCursor: nextCursor,
1393
+ previousCursor: previousCursor,
1394
+ currentPage: pageInfo.currentPage,
1395
+ totalPages,
1396
+ supportsPageJump
1397
+ });
1398
+ return result;
1320
1399
  }
1321
- return result;
1322
- }
1323
- /**
1324
- * Transforms an object's keys from PascalCase to camelCase
1325
- * @param data The object with PascalCase keys
1326
- * @returns A new object with all keys converted to camelCase
1327
- *
1328
- * @example
1329
- * ```typescript
1330
- * // Simple object
1331
- * pascalToCamelCaseKeys({ Id: "123", TaskName: "Invoice" });
1332
- * // Result: { id: "123", taskName: "Invoice" }
1333
- *
1334
- * // Nested object
1335
- * pascalToCamelCaseKeys({
1336
- * TaskId: "456",
1337
- * TaskDetails: { AssignedUser: "John", Priority: "High" }
1338
- * });
1339
- * // Result: {
1340
- * // taskId: "456",
1341
- * // taskDetails: { assignedUser: "John", priority: "High" }
1342
- * // }
1343
- *
1344
- * // Array of objects
1345
- * pascalToCamelCaseKeys([
1346
- * { Id: "1", IsComplete: false },
1347
- * { Id: "2", IsComplete: true }
1348
- * ]);
1349
- * // Result: [
1350
- * // { id: "1", isComplete: false },
1351
- * // { id: "2", isComplete: true }
1352
- * // ]
1353
- * ```
1354
- */
1355
- function pascalToCamelCaseKeys(data) {
1356
- return transformCaseKeys(data, pascalToCamelCase);
1357
1400
  }
1401
+
1358
1402
  /**
1359
- * Transforms an object's keys from camelCase to PascalCase
1360
- * @param data The object with camelCase keys
1361
- * @returns A new object with all keys converted to PascalCase
1403
+ * Creates headers object from key-value pairs
1404
+ * @param headersObj - Object containing header key-value pairs
1405
+ * @returns Headers object with all values converted to strings
1362
1406
  *
1363
1407
  * @example
1364
1408
  * ```typescript
1365
- * // Simple object
1366
- * camelToPascalCaseKeys({ userId: "789", isActive: true });
1367
- * // Result: { UserId: "789", IsActive: true }
1409
+ * // Single header
1410
+ * const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
1368
1411
  *
1369
- * // Nested object
1370
- * camelToPascalCaseKeys({
1371
- * taskId: "ABC123",
1372
- * submissionData: { customerName: "XYZ Corp" }
1412
+ * // Multiple headers
1413
+ * const headers = createHeaders({
1414
+ * 'X-UIPATH-FolderKey': '1234567890',
1415
+ * 'X-UIPATH-OrganizationUnitId': 123,
1416
+ * 'Accept': 'application/json'
1373
1417
  * });
1374
- * // Result: {
1375
- * // TaskId: "ABC123",
1376
- * // SubmissionData: { CustomerName: "XYZ Corp" }
1377
- * // }
1378
1418
  *
1379
- * // Array of objects
1380
- * camelToPascalCaseKeys([
1381
- * { userId: "u1", roleType: "admin" },
1382
- * { userId: "u2", roleType: "user" }
1383
- * ]);
1384
- * // Result: [
1385
- * // { UserId: "u1", RoleType: "admin" },
1386
- * // { UserId: "u2", RoleType: "user" }
1387
- * // ]
1419
+ * // Using constants
1420
+ * import { FOLDER_KEY, FOLDER_ID } from '../constants/headers';
1421
+ * const headers = createHeaders({
1422
+ * [FOLDER_KEY]: 'abc-123',
1423
+ * [FOLDER_ID]: 456
1424
+ * });
1425
+ *
1426
+ * // Empty headers
1427
+ * const headers = createHeaders();
1388
1428
  * ```
1389
1429
  */
1390
- function camelToPascalCaseKeys(data) {
1391
- return transformCaseKeys(data, camelToPascalCase);
1430
+ function createHeaders(headersObj) {
1431
+ const headers = {};
1432
+ for (const [key, value] of Object.entries(headersObj)) {
1433
+ if (value !== undefined && value !== null) {
1434
+ headers[key] = value.toString();
1435
+ }
1436
+ }
1437
+ return headers;
1392
1438
  }
1439
+
1393
1440
  /**
1394
- * Maps a field value in an object using a provided mapping object.
1395
- * Returns a new object with the mapped field value.
1396
- *
1397
- * @param obj The object to map
1398
- * @param field The field name to map
1399
- * @param valueMap The mapping object (from input value to output value)
1400
- * @returns A new object with the mapped field value
1401
- *
1402
- * @example
1403
- * const statusMap = { 0: 'Unassigned', 1: 'Pending', 2: 'Completed' };
1404
- * const task = { status: 1, id: 123 };
1405
- * const mapped = mapFieldValue(task, 'status', statusMap);
1406
- * // mapped = { status: 'Pending', id: 123 }
1441
+ * Common constants used across the SDK
1407
1442
  */
1408
- function _mapFieldValue(obj, field, valueMap) {
1409
- const lookupKey = String(obj[field]);
1410
- return {
1411
- ...obj,
1412
- [field]: lookupKey in valueMap
1413
- ? valueMap[lookupKey]
1414
- : obj[field],
1415
- };
1416
- }
1417
1443
  /**
1418
- * General API response transformer with optional field value mapping.
1419
- *
1420
- * @param data - The API response data to transform
1421
- * @param options - Optional mapping options:
1422
- * - field: The field name to map (optional)
1423
- * - valueMap: The mapping object for the field (optional)
1424
- * - transform: A function to further transform the data (optional)
1425
- * @returns The transformed data, with field value mapped if specified
1426
- *
1427
- * @example
1428
- * // Just transform
1429
- * const result = applyDataTransforms(data);
1430
- *
1431
- * // Map a field value, then transform
1432
- * const result = applyDataTransforms(data, { field: 'status', valueMap: StatusMap });
1433
- *
1434
- * // Map a field value, then apply a custom transform
1435
- * const result = applyDataTransforms(data, { field: 'status', valueMap: StatusMap, transform: customTransform });
1444
+ * Prefix used for OData query parameters
1436
1445
  */
1437
- function applyDataTransforms(data, options) {
1438
- let result = data;
1439
- if (options?.field && options?.valueMap) {
1440
- result = _mapFieldValue(result, options.field, options.valueMap);
1441
- }
1442
- if (options?.transform) {
1443
- result = options.transform(result);
1444
- }
1445
- return result;
1446
- }
1446
+ const ODATA_PREFIX = '$';
1447
1447
  /**
1448
- * Adds a prefix to specified keys in an object, returning a new object.
1449
- * Only the provided keys are prefixed; all others are left unchanged.
1450
- *
1451
- * @param obj The source object
1452
- * @param prefix The prefix to add (e.g., '$')
1453
- * @param keys The keys to prefix (e.g., ['expand', 'filter'])
1454
- * @returns A new object with specified keys prefixed
1455
- *
1456
- * @example
1457
- * addPrefixToKeys({ expand: 'a', foo: 1 }, '$', ['expand']) // { $expand: 'a', foo: 1 }
1448
+ * HTTP methods
1458
1449
  */
1459
- function addPrefixToKeys(obj, prefix, keys) {
1460
- const result = {};
1461
- for (const [key, value] of Object.entries(obj)) {
1462
- if (keys.includes(key)) {
1463
- result[`${prefix}${key}`] = value;
1464
- }
1465
- else {
1466
- result[key] = value;
1467
- }
1468
- }
1469
- return result;
1470
- }
1450
+ const HTTP_METHODS = {
1451
+ GET: 'GET',
1452
+ POST: 'POST'};
1453
+ /**
1454
+ * OData pagination constants
1455
+ */
1456
+ const ODATA_PAGINATION = {
1457
+ /** Default field name for items in a paginated OData response */
1458
+ ITEMS_FIELD: 'value',
1459
+ /** Default field name for total count in a paginated OData response */
1460
+ TOTAL_COUNT_FIELD: '@odata.count'
1461
+ };
1462
+ /**
1463
+ * SLA Summary pagination constants for page-number-based pagination
1464
+ */
1465
+ const SLA_SUMMARY_PAGINATION = {
1466
+ /** Field name for items in SLA summary response */
1467
+ ITEMS_FIELD: 'data',
1468
+ /** Dot-notation path for total count in nested pagination object */
1469
+ TOTAL_COUNT_FIELD: 'pagination.totalCount'
1470
+ };
1471
+ /**
1472
+ * SLA Summary OFFSET pagination parameter names (page-number style, no skip conversion)
1473
+ */
1474
+ const SLA_SUMMARY_OFFSET_PARAMS = {
1475
+ /** Page size parameter name */
1476
+ PAGE_SIZE_PARAM: 'PageSize',
1477
+ /** Page number parameter name (sent directly, not converted to skip) */
1478
+ OFFSET_PARAM: 'PageNumber',
1479
+ /** No count param needed */
1480
+ COUNT_PARAM: undefined
1481
+ };
1482
+ /**
1483
+ * Process Instance pagination constants for token-based pagination
1484
+ */
1485
+ const PROCESS_INSTANCE_PAGINATION = {
1486
+ /** Field name for items in process instance response */
1487
+ ITEMS_FIELD: 'instances',
1488
+ /** Field name for continuation token in process instance response */
1489
+ CONTINUATION_TOKEN_FIELD: 'nextPage'
1490
+ };
1491
+ /**
1492
+ * OData OFFSET pagination parameter names (ODATA-style)
1493
+ */
1494
+ const ODATA_OFFSET_PARAMS = {
1495
+ /** OData page size parameter name */
1496
+ PAGE_SIZE_PARAM: '$top',
1497
+ /** OData offset parameter name */
1498
+ OFFSET_PARAM: '$skip',
1499
+ /** OData count parameter name */
1500
+ COUNT_PARAM: '$count'
1501
+ };
1502
+ /**
1503
+ * Bucket TOKEN pagination parameter names
1504
+ */
1505
+ const BUCKET_TOKEN_PARAMS = {
1506
+ /** Bucket page size parameter name */
1507
+ PAGE_SIZE_PARAM: 'takeHint',
1508
+ /** Bucket token parameter name */
1509
+ TOKEN_PARAM: 'continuationToken'
1510
+ };
1511
+ /**
1512
+ * Process Instance TOKEN pagination parameter names
1513
+ */
1514
+ const PROCESS_INSTANCE_TOKEN_PARAMS = {
1515
+ /** Process instance page size parameter name */
1516
+ PAGE_SIZE_PARAM: 'pageSize',
1517
+ /** Process instance token parameter name */
1518
+ TOKEN_PARAM: 'nextPage'
1519
+ };
1471
1520
 
1472
1521
  /**
1473
1522
  * Constants used throughout the pagination system
@@ -2395,34 +2444,79 @@ class CasesService extends BaseService {
2395
2444
  * Returns per-element execution counts (success, fail, terminated, paused, in-progress) and
2396
2445
  * duration percentile metrics (min, max, avg, p50, p95, p99) for BPMN elements within a case.
2397
2446
  *
2398
- * @param processKey - Process key to filter by
2399
- * @param packageId - Package identifier
2400
- * @param startTime - Start of the time range to query
2401
- * @param endTime - End of the time range to query
2402
- * @param packageVersion - Package version to filter by
2447
+ * @param request - Process scope + time range to aggregate over
2403
2448
  * @returns Promise resolving to an array of {@link ElementStats}
2404
2449
  * @example
2405
2450
  * ```typescript
2406
- * // Get element metrics for a case
2407
- * const elements = await cases.getElementStats(
2408
- * '<processKey>',
2409
- * '<packageId>',
2410
- * new Date('2026-04-01'),
2411
- * new Date(),
2412
- * '1.0.1'
2413
- * );
2451
+ * // First, list cases to find the processKey, packageId, and available versions
2452
+ * const allCases = await cases.getAll();
2453
+ * const caseItem = allCases[0];
2454
+ *
2455
+ * // Get element metrics for that case
2456
+ * const elements = await cases.getElementStats({
2457
+ * processKey: caseItem.processKey,
2458
+ * packageId: caseItem.packageId,
2459
+ * packageVersion: caseItem.packageVersions[0],
2460
+ * startTime: new Date('2026-04-01'),
2461
+ * endTime: new Date(),
2462
+ * });
2414
2463
  *
2415
2464
  * // Find elements with failures
2416
2465
  * const failedElements = elements.filter(e => e.failCount > 0);
2417
2466
  * for (const element of failedElements) {
2418
2467
  * console.log(`Failed element: ${element.elementId}, failures: ${element.failCount}`);
2419
2468
  * }
2469
+ *
2470
+ * // Using bound method on a case — auto-fills processKey and packageId
2471
+ * const boundElements = await caseItem.getElementStats(
2472
+ * new Date('2026-04-01'),
2473
+ * new Date(),
2474
+ * caseItem.packageVersions[0]
2475
+ * );
2420
2476
  * ```
2421
2477
  */
2422
- async getElementStats(processKey, packageId, startTime, endTime, packageVersion) {
2423
- const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.ELEMENT_COUNT_BY_STATUS, buildElementCountByStatusBody(processKey, packageId, startTime, endTime, packageVersion));
2478
+ async getElementStats(request) {
2479
+ const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.ELEMENT_COUNT_BY_STATUS, buildInsightsCommonBody(request));
2424
2480
  return data ?? [];
2425
2481
  }
2482
+ /**
2483
+ * Get instance stats for a case.
2484
+ *
2485
+ * Returns total instance counts broken down by status (running, completed, faulted, etc.)
2486
+ * and the average execution duration for all instances of a case within a time range.
2487
+ *
2488
+ * @param request - Process scope + time range to aggregate over
2489
+ * @returns Promise resolving to {@link InstanceStats}
2490
+ * @example
2491
+ * ```typescript
2492
+ * // First, list cases to find the processKey, packageId, and available versions
2493
+ * const allCases = await cases.getAll();
2494
+ * const caseItem = allCases[0];
2495
+ *
2496
+ * // Get instance status breakdown for that case
2497
+ * const counts = await cases.getInstanceStats({
2498
+ * processKey: caseItem.processKey,
2499
+ * packageId: caseItem.packageId,
2500
+ * packageVersion: caseItem.packageVersions[0],
2501
+ * startTime: new Date('2026-04-01'),
2502
+ * endTime: new Date(),
2503
+ * });
2504
+ *
2505
+ * console.log(`Total: ${counts.totalCount}`);
2506
+ * console.log(`Completed: ${counts.completedCount}, Faulted: ${counts.faultedCount}`);
2507
+ *
2508
+ * // Using bound method on a case — auto-fills processKey and packageId
2509
+ * const boundCounts = await caseItem.getInstanceStats(
2510
+ * new Date('2026-04-01'),
2511
+ * new Date(),
2512
+ * caseItem.packageVersions[0]
2513
+ * );
2514
+ * ```
2515
+ */
2516
+ async getInstanceStats(request) {
2517
+ const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.INSTANCE_COUNT_BY_STATUS, buildInsightsCommonBody(request));
2518
+ return transformData(data, InstanceStatsMap);
2519
+ }
2426
2520
  /**
2427
2521
  * Extract a readable case name from the packageId
2428
2522
  * @param packageId - The full package identifier
@@ -2463,6 +2557,9 @@ __decorate([
2463
2557
  __decorate([
2464
2558
  track('Cases.GetElementStats')
2465
2559
  ], CasesService.prototype, "getElementStats", null);
2560
+ __decorate([
2561
+ track('Cases.GetInstanceStats')
2562
+ ], CasesService.prototype, "getInstanceStats", null);
2466
2563
 
2467
2564
  /**
2468
2565
  * Process Incident Status