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