@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.
- package/dist/agent-memory/index.d.ts +4 -1
- package/dist/agents/index.cjs +341 -6
- package/dist/agents/index.d.ts +717 -16
- package/dist/agents/index.mjs +342 -7
- package/dist/assets/index.cjs +25 -9
- package/dist/assets/index.mjs +25 -9
- package/dist/attachments/index.cjs +25 -9
- package/dist/attachments/index.mjs +25 -9
- package/dist/buckets/index.cjs +25 -9
- package/dist/buckets/index.mjs +25 -9
- package/dist/cases/index.cjs +621 -524
- package/dist/cases/index.d.ts +186 -43
- package/dist/cases/index.mjs +621 -524
- package/dist/conversational-agent/index.cjs +25 -9
- package/dist/conversational-agent/index.mjs +25 -9
- package/dist/core/index.cjs +1 -1
- package/dist/core/index.mjs +1 -1
- package/dist/entities/index.cjs +25 -9
- package/dist/entities/index.mjs +25 -9
- package/dist/feedback/index.cjs +25 -9
- package/dist/feedback/index.mjs +25 -9
- package/dist/index.cjs +332 -62
- package/dist/index.d.ts +827 -89
- package/dist/index.mjs +333 -63
- package/dist/index.umd.js +332 -62
- package/dist/jobs/index.cjs +129 -14
- package/dist/jobs/index.d.ts +10 -5
- package/dist/jobs/index.mjs +129 -14
- package/dist/maestro-processes/index.cjs +198 -100
- package/dist/maestro-processes/index.d.ts +188 -43
- package/dist/maestro-processes/index.mjs +198 -100
- package/dist/processes/index.cjs +25 -9
- package/dist/processes/index.d.ts +6 -1
- package/dist/processes/index.mjs +25 -9
- package/dist/queues/index.cjs +25 -9
- package/dist/queues/index.mjs +25 -9
- package/dist/tasks/index.cjs +25 -9
- package/dist/tasks/index.d.ts +4 -1
- package/dist/tasks/index.mjs +25 -9
- package/dist/traces/index.cjs +2 -2
- package/dist/traces/index.d.ts +3 -3
- package/dist/traces/index.mjs +2 -2
- package/package.json +1 -1
package/dist/cases/index.cjs
CHANGED
|
@@ -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(
|
|
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
|
|
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
|
|
228
|
-
* @
|
|
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
|
|
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
|
|
1184
|
-
|
|
1185
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
1220
|
-
* @param
|
|
1221
|
-
* @
|
|
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
|
|
1245
|
-
//
|
|
1246
|
-
|
|
1247
|
-
|
|
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
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
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
|
-
*
|
|
1278
|
-
* @param
|
|
1279
|
-
* @returns
|
|
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
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
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
|
-
*
|
|
1294
|
-
*
|
|
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
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
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
|
-
|
|
1318
|
-
|
|
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
|
-
*
|
|
1360
|
-
* @param
|
|
1361
|
-
* @returns
|
|
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
|
-
* //
|
|
1366
|
-
*
|
|
1367
|
-
* // Result: { UserId: "789", IsActive: true }
|
|
1409
|
+
* // Single header
|
|
1410
|
+
* const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
|
|
1368
1411
|
*
|
|
1369
|
-
* //
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
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
|
-
* //
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
* //
|
|
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
|
|
1391
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
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
|
|
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
|
-
* //
|
|
2407
|
-
* const
|
|
2408
|
-
*
|
|
2409
|
-
*
|
|
2410
|
-
*
|
|
2411
|
-
*
|
|
2412
|
-
*
|
|
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(
|
|
2423
|
-
const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.ELEMENT_COUNT_BY_STATUS,
|
|
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
|