@uipath/uipath-typescript 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/index.cjs +1 -1
- package/dist/assets/index.d.ts +2 -1
- package/dist/assets/index.mjs +1 -1
- package/dist/attachments/index.cjs +1944 -0
- package/dist/attachments/index.d.ts +399 -0
- package/dist/attachments/index.mjs +1941 -0
- package/dist/buckets/index.cjs +1 -1
- package/dist/buckets/index.d.ts +4 -2
- package/dist/buckets/index.mjs +1 -1
- package/dist/cases/index.cjs +95 -48
- package/dist/cases/index.d.ts +31 -2
- package/dist/cases/index.mjs +95 -48
- package/dist/conversational-agent/index.cjs +38 -7
- package/dist/conversational-agent/index.d.ts +72 -6
- package/dist/conversational-agent/index.mjs +38 -7
- package/dist/core/index.cjs +118 -17
- package/dist/core/index.d.ts +26 -2
- package/dist/core/index.mjs +118 -17
- package/dist/entities/index.cjs +48 -1
- package/dist/entities/index.d.ts +106 -19
- package/dist/entities/index.mjs +48 -1
- package/dist/index.cjs +585 -267
- package/dist/index.d.ts +595 -67
- package/dist/index.mjs +586 -268
- package/dist/index.umd.js +582 -264
- package/dist/jobs/index.cjs +2036 -0
- package/dist/jobs/index.d.ts +724 -0
- package/dist/jobs/index.mjs +2033 -0
- package/dist/maestro-processes/index.cjs +1 -1
- package/dist/maestro-processes/index.mjs +1 -1
- package/dist/processes/index.cjs +67 -1
- package/dist/processes/index.d.ts +80 -15
- package/dist/processes/index.mjs +68 -2
- package/dist/queues/index.cjs +1 -1
- package/dist/queues/index.d.ts +2 -1
- package/dist/queues/index.mjs +1 -1
- package/dist/tasks/index.cjs +1319 -1272
- package/dist/tasks/index.d.ts +331 -287
- package/dist/tasks/index.mjs +1319 -1272
- package/package.json +25 -3
package/dist/tasks/index.cjs
CHANGED
|
@@ -45,31 +45,43 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Base error class for all UiPath SDK errors
|
|
49
|
+
* Extends Error for standard error handling compatibility
|
|
49
50
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
class UiPathError extends Error {
|
|
52
|
+
constructor(type, params) {
|
|
53
|
+
super(params.message);
|
|
54
|
+
this.name = type;
|
|
55
|
+
this.type = type;
|
|
56
|
+
this.statusCode = params.statusCode;
|
|
57
|
+
this.requestId = params.requestId;
|
|
58
|
+
this.timestamp = new Date();
|
|
59
|
+
// Maintains proper stack trace for where our error was thrown
|
|
60
|
+
if (Error.captureStackTrace) {
|
|
61
|
+
Error.captureStackTrace(this, this.constructor);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns a clean JSON representation of the error
|
|
66
|
+
*/
|
|
67
|
+
toJSON() {
|
|
68
|
+
return {
|
|
69
|
+
type: this.type,
|
|
70
|
+
message: this.message,
|
|
71
|
+
statusCode: this.statusCode,
|
|
72
|
+
requestId: this.requestId,
|
|
73
|
+
timestamp: this.timestamp
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns detailed debug information including stack trace
|
|
78
|
+
*/
|
|
79
|
+
getDebugInfo() {
|
|
80
|
+
return {
|
|
81
|
+
...this.toJSON(),
|
|
82
|
+
stack: this.stack
|
|
83
|
+
};
|
|
84
|
+
}
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
/**
|
|
@@ -133,196 +145,6 @@ const ErrorMessages = {
|
|
|
133
145
|
const ErrorNames = {
|
|
134
146
|
ABORT_ERROR: 'AbortError'};
|
|
135
147
|
|
|
136
|
-
/**
|
|
137
|
-
* Parser for Orchestrator/Task error format
|
|
138
|
-
*/
|
|
139
|
-
class OrchestratorErrorParser {
|
|
140
|
-
canParse(errorBody) {
|
|
141
|
-
return isOrchestratorError(errorBody);
|
|
142
|
-
}
|
|
143
|
-
parse(errorBody, response) {
|
|
144
|
-
const error = errorBody;
|
|
145
|
-
return {
|
|
146
|
-
message: error.message,
|
|
147
|
-
code: response?.status?.toString(),
|
|
148
|
-
details: {
|
|
149
|
-
errorCode: error.errorCode,
|
|
150
|
-
traceId: error.traceId,
|
|
151
|
-
originalResponse: error
|
|
152
|
-
},
|
|
153
|
-
requestId: error.traceId
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Parser for Entity (Data Fabric) error format
|
|
159
|
-
*/
|
|
160
|
-
class EntityErrorParser {
|
|
161
|
-
canParse(errorBody) {
|
|
162
|
-
return isEntityError(errorBody);
|
|
163
|
-
}
|
|
164
|
-
parse(errorBody, response) {
|
|
165
|
-
const error = errorBody;
|
|
166
|
-
return {
|
|
167
|
-
message: error.error,
|
|
168
|
-
code: response?.status?.toString(),
|
|
169
|
-
details: {
|
|
170
|
-
error: error.error,
|
|
171
|
-
traceId: error.traceId,
|
|
172
|
-
originalResponse: error
|
|
173
|
-
},
|
|
174
|
-
requestId: error.traceId
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Parser for PIMS error format
|
|
180
|
-
*/
|
|
181
|
-
class PimsErrorParser {
|
|
182
|
-
canParse(errorBody) {
|
|
183
|
-
return isPimsError(errorBody);
|
|
184
|
-
}
|
|
185
|
-
parse(errorBody, response) {
|
|
186
|
-
const error = errorBody;
|
|
187
|
-
let message = error.title;
|
|
188
|
-
// If there are validation errors, append them to the message for better visibility
|
|
189
|
-
if (error.errors && Object.keys(error.errors).length > 0) {
|
|
190
|
-
const errorMessages = Object.entries(error.errors)
|
|
191
|
-
.map(([field, messages]) => `${field}: ${messages.join(', ')}`)
|
|
192
|
-
.join('; ');
|
|
193
|
-
message += `. Validation errors: ${errorMessages}`;
|
|
194
|
-
}
|
|
195
|
-
return {
|
|
196
|
-
message,
|
|
197
|
-
code: response?.status?.toString(),
|
|
198
|
-
details: {
|
|
199
|
-
type: error.type,
|
|
200
|
-
title: error.title,
|
|
201
|
-
status: error.status,
|
|
202
|
-
errors: error.errors,
|
|
203
|
-
traceId: error.traceId,
|
|
204
|
-
originalResponse: error
|
|
205
|
-
},
|
|
206
|
-
requestId: error.traceId
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Fallback parser for unrecognized formats
|
|
212
|
-
*/
|
|
213
|
-
class GenericErrorParser {
|
|
214
|
-
canParse(_errorBody) {
|
|
215
|
-
return true; // Always can parse as last resort
|
|
216
|
-
}
|
|
217
|
-
parse(errorBody, response) {
|
|
218
|
-
// For unknown error formats, just pass through the raw error with fallback message
|
|
219
|
-
const message = response?.statusText || 'An error occurred';
|
|
220
|
-
return {
|
|
221
|
-
message,
|
|
222
|
-
code: response?.status?.toString(),
|
|
223
|
-
details: {
|
|
224
|
-
originalResponse: errorBody
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Main error response parser using Chain of Responsibility pattern
|
|
231
|
-
*
|
|
232
|
-
* This parser standardizes error responses from different UiPath services into a
|
|
233
|
-
* consistent format, regardless of the original error structure.
|
|
234
|
-
*
|
|
235
|
-
* Supported formats:
|
|
236
|
-
* 1. Orchestrator/Task: { message, errorCode, traceId }
|
|
237
|
-
* 2. Entity (Data Fabric): { error, traceId }
|
|
238
|
-
* 3. PIMS/Maestro: { type, title, status, errors?, traceId? }
|
|
239
|
-
* 4. Generic: Fallback for any other format
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* const parser = new ErrorResponseParser();
|
|
243
|
-
* const errorInfo = await parser.parse(response);
|
|
244
|
-
* // errorInfo will have consistent structure regardless of service
|
|
245
|
-
*/
|
|
246
|
-
class ErrorResponseParser {
|
|
247
|
-
constructor() {
|
|
248
|
-
this.strategies = [
|
|
249
|
-
new OrchestratorErrorParser(),
|
|
250
|
-
new EntityErrorParser(),
|
|
251
|
-
new PimsErrorParser(),
|
|
252
|
-
new GenericErrorParser() // Must be last
|
|
253
|
-
];
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Parses error response body into standardized format
|
|
257
|
-
* @param response - The HTTP response object
|
|
258
|
-
* @returns Standardized error information
|
|
259
|
-
*/
|
|
260
|
-
async parse(response) {
|
|
261
|
-
try {
|
|
262
|
-
const errorBody = await response.json();
|
|
263
|
-
// Find the first strategy that can parse this error format
|
|
264
|
-
const strategy = this.strategies.find(s => s.canParse(errorBody));
|
|
265
|
-
// GenericErrorParser always returns true, so this will never be null
|
|
266
|
-
return strategy.parse(errorBody, response);
|
|
267
|
-
}
|
|
268
|
-
catch {
|
|
269
|
-
// Handle non-JSON responses
|
|
270
|
-
const responseText = await response.text().catch(() => '');
|
|
271
|
-
return {
|
|
272
|
-
message: response.statusText,
|
|
273
|
-
code: response.status.toString(),
|
|
274
|
-
details: {
|
|
275
|
-
parseError: 'Failed to parse error response as JSON',
|
|
276
|
-
responseText
|
|
277
|
-
},
|
|
278
|
-
requestId: response.headers.get(HttpHeaders.X_REQUEST_ID) || undefined
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
// Export singleton instance
|
|
284
|
-
const errorResponseParser = new ErrorResponseParser();
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Base error class for all UiPath SDK errors
|
|
288
|
-
* Extends Error for standard error handling compatibility
|
|
289
|
-
*/
|
|
290
|
-
class UiPathError extends Error {
|
|
291
|
-
constructor(type, params) {
|
|
292
|
-
super(params.message);
|
|
293
|
-
this.name = type;
|
|
294
|
-
this.type = type;
|
|
295
|
-
this.statusCode = params.statusCode;
|
|
296
|
-
this.requestId = params.requestId;
|
|
297
|
-
this.timestamp = new Date();
|
|
298
|
-
// Maintains proper stack trace for where our error was thrown
|
|
299
|
-
if (Error.captureStackTrace) {
|
|
300
|
-
Error.captureStackTrace(this, this.constructor);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Returns a clean JSON representation of the error
|
|
305
|
-
*/
|
|
306
|
-
toJSON() {
|
|
307
|
-
return {
|
|
308
|
-
type: this.type,
|
|
309
|
-
message: this.message,
|
|
310
|
-
statusCode: this.statusCode,
|
|
311
|
-
requestId: this.requestId,
|
|
312
|
-
timestamp: this.timestamp
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Returns detailed debug information including stack trace
|
|
317
|
-
*/
|
|
318
|
-
getDebugInfo() {
|
|
319
|
-
return {
|
|
320
|
-
...this.toJSON(),
|
|
321
|
-
stack: this.stack
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
148
|
/**
|
|
327
149
|
* Error thrown when authentication fails (401 errors)
|
|
328
150
|
* Common scenarios:
|
|
@@ -451,414 +273,469 @@ class NetworkError extends UiPathError {
|
|
|
451
273
|
}
|
|
452
274
|
|
|
453
275
|
/**
|
|
454
|
-
*
|
|
455
|
-
* Follows the Factory pattern for clean error instantiation
|
|
276
|
+
* SDK Telemetry constants
|
|
456
277
|
*/
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
278
|
+
// Connection string placeholder that will be replaced during build
|
|
279
|
+
const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
|
|
280
|
+
// SDK Version placeholder
|
|
281
|
+
const SDK_VERSION = "1.2.2";
|
|
282
|
+
const VERSION = "Version";
|
|
283
|
+
const SERVICE = "Service";
|
|
284
|
+
const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
|
|
285
|
+
const CLOUD_TENANT_NAME = "CloudTenantName";
|
|
286
|
+
const CLOUD_URL = "CloudUrl";
|
|
287
|
+
const CLOUD_CLIENT_ID = "CloudClientId";
|
|
288
|
+
const CLOUD_REDIRECT_URI = "CloudRedirectUri";
|
|
289
|
+
const APP_NAME = "ApplicationName";
|
|
290
|
+
const CLOUD_ROLE_NAME = "uipath-ts-sdk";
|
|
291
|
+
// Service and logger names
|
|
292
|
+
const SDK_SERVICE_NAME = "UiPath.TypeScript.Sdk";
|
|
293
|
+
const SDK_LOGGER_NAME = "uipath-ts-sdk-telemetry";
|
|
294
|
+
// Event names
|
|
295
|
+
const SDK_RUN_EVENT = "Sdk.Run";
|
|
296
|
+
// Default value for unknown/empty attributes
|
|
297
|
+
const UNKNOWN = "";
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Log exporter that sends ALL logs as Application Insights custom events
|
|
301
|
+
*/
|
|
302
|
+
class ApplicationInsightsEventExporter {
|
|
303
|
+
constructor(connectionString) {
|
|
304
|
+
this.connectionString = connectionString;
|
|
305
|
+
}
|
|
306
|
+
export(logs, resultCallback) {
|
|
307
|
+
try {
|
|
308
|
+
logs.forEach(logRecord => {
|
|
309
|
+
this.sendAsCustomEvent(logRecord);
|
|
310
|
+
});
|
|
311
|
+
resultCallback({ code: 0 });
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.debug('Failed to export logs to Application Insights:', error);
|
|
315
|
+
resultCallback({ code: 2, error });
|
|
486
316
|
}
|
|
487
317
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
318
|
+
shutdown() {
|
|
319
|
+
return Promise.resolve();
|
|
320
|
+
}
|
|
321
|
+
sendAsCustomEvent(logRecord) {
|
|
322
|
+
// Get event name from body or attributes
|
|
323
|
+
const eventName = logRecord.body || SDK_RUN_EVENT;
|
|
324
|
+
const payload = {
|
|
325
|
+
name: 'Microsoft.ApplicationInsights.Event',
|
|
326
|
+
time: new Date().toISOString(),
|
|
327
|
+
iKey: this.extractInstrumentationKey(),
|
|
328
|
+
data: {
|
|
329
|
+
baseType: 'EventData',
|
|
330
|
+
baseData: {
|
|
331
|
+
ver: 2,
|
|
332
|
+
name: eventName,
|
|
333
|
+
properties: this.convertAttributesToProperties(logRecord.attributes || {})
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
tags: {
|
|
337
|
+
'ai.cloud.role': CLOUD_ROLE_NAME,
|
|
338
|
+
'ai.cloud.roleInstance': SDK_VERSION
|
|
496
339
|
}
|
|
497
|
-
|
|
498
|
-
|
|
340
|
+
};
|
|
341
|
+
this.sendToApplicationInsights(payload);
|
|
342
|
+
}
|
|
343
|
+
extractInstrumentationKey() {
|
|
344
|
+
const match = this.connectionString.match(/InstrumentationKey=([^;]+)/);
|
|
345
|
+
return match ? match[1] : '';
|
|
346
|
+
}
|
|
347
|
+
convertAttributesToProperties(attributes) {
|
|
348
|
+
const properties = {};
|
|
349
|
+
Object.entries(attributes || {}).forEach(([key, value]) => {
|
|
350
|
+
properties[key] = String(value);
|
|
351
|
+
});
|
|
352
|
+
return properties;
|
|
353
|
+
}
|
|
354
|
+
async sendToApplicationInsights(payload) {
|
|
355
|
+
try {
|
|
356
|
+
const ingestionEndpoint = this.extractIngestionEndpoint();
|
|
357
|
+
if (!ingestionEndpoint) {
|
|
358
|
+
console.debug('No ingestion endpoint found in connection string');
|
|
359
|
+
return;
|
|
499
360
|
}
|
|
500
|
-
|
|
501
|
-
|
|
361
|
+
const url = `${ingestionEndpoint}/v2/track`;
|
|
362
|
+
const response = await fetch(url, {
|
|
363
|
+
method: 'POST',
|
|
364
|
+
headers: {
|
|
365
|
+
'Content-Type': 'application/json',
|
|
366
|
+
},
|
|
367
|
+
body: JSON.stringify(payload)
|
|
368
|
+
});
|
|
369
|
+
if (!response.ok) {
|
|
370
|
+
console.debug(`Failed to send event telemetry: ${response.status} ${response.statusText}`);
|
|
502
371
|
}
|
|
503
372
|
}
|
|
504
|
-
|
|
373
|
+
catch (error) {
|
|
374
|
+
console.debug('Error sending event telemetry to Application Insights:', error);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
extractIngestionEndpoint() {
|
|
378
|
+
const match = this.connectionString.match(/IngestionEndpoint=([^;]+)/);
|
|
379
|
+
return match ? match[1] : '';
|
|
505
380
|
}
|
|
506
381
|
}
|
|
507
|
-
|
|
508
|
-
const FOLDER_ID = 'X-UIPATH-OrganizationUnitId';
|
|
509
|
-
/**
|
|
510
|
-
* Content type constants for HTTP requests/responses
|
|
511
|
-
*/
|
|
512
|
-
const CONTENT_TYPES = {
|
|
513
|
-
JSON: 'application/json',
|
|
514
|
-
XML: 'application/xml',
|
|
515
|
-
OCTET_STREAM: 'application/octet-stream'
|
|
516
|
-
};
|
|
517
382
|
/**
|
|
518
|
-
*
|
|
383
|
+
* Singleton telemetry client
|
|
519
384
|
*/
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
BLOB: 'blob',
|
|
524
|
-
ARRAYBUFFER: 'arraybuffer'
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
class ApiClient {
|
|
528
|
-
constructor(config, executionContext, tokenManager, clientConfig = {}) {
|
|
529
|
-
this.defaultHeaders = {};
|
|
530
|
-
this.config = config;
|
|
531
|
-
this.executionContext = executionContext;
|
|
532
|
-
this.clientConfig = clientConfig;
|
|
533
|
-
this.tokenManager = tokenManager;
|
|
385
|
+
class TelemetryClient {
|
|
386
|
+
constructor() {
|
|
387
|
+
this.isInitialized = false;
|
|
534
388
|
}
|
|
535
|
-
|
|
536
|
-
|
|
389
|
+
static getInstance() {
|
|
390
|
+
if (!TelemetryClient.instance) {
|
|
391
|
+
TelemetryClient.instance = new TelemetryClient();
|
|
392
|
+
}
|
|
393
|
+
return TelemetryClient.instance;
|
|
537
394
|
}
|
|
538
395
|
/**
|
|
539
|
-
*
|
|
540
|
-
* Used internally for API requests and exposed for services that need manual auth headers.
|
|
541
|
-
*
|
|
542
|
-
* @returns The valid token
|
|
543
|
-
* @throws AuthenticationError if no token available or refresh fails
|
|
396
|
+
* Initialize telemetry
|
|
544
397
|
*/
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
async getDefaultHeaders() {
|
|
549
|
-
const token = await this.getValidToken();
|
|
550
|
-
return {
|
|
551
|
-
'Authorization': `Bearer ${token}`,
|
|
552
|
-
'Content-Type': CONTENT_TYPES.JSON,
|
|
553
|
-
...this.defaultHeaders,
|
|
554
|
-
...this.clientConfig.headers
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
async request(method, path, options = {}) {
|
|
558
|
-
// Ensure path starts with a forward slash
|
|
559
|
-
const normalizedPath = path.startsWith('/') ? path.substring(1) : path;
|
|
560
|
-
// Construct URL with org and tenant names
|
|
561
|
-
const url = new URL(`${this.config.orgName}/${this.config.tenantName}/${normalizedPath}`, this.config.baseUrl).toString();
|
|
562
|
-
const isFormData = options.body instanceof FormData;
|
|
563
|
-
const defaultHeaders = await this.getDefaultHeaders();
|
|
564
|
-
if (isFormData) {
|
|
565
|
-
delete defaultHeaders['Content-Type'];
|
|
566
|
-
}
|
|
567
|
-
const headers = {
|
|
568
|
-
...defaultHeaders,
|
|
569
|
-
...options.headers
|
|
570
|
-
};
|
|
571
|
-
// Convert params to URLSearchParams
|
|
572
|
-
const searchParams = new URLSearchParams();
|
|
573
|
-
if (options.params) {
|
|
574
|
-
Object.entries(options.params).forEach(([key, value]) => {
|
|
575
|
-
searchParams.append(key, value.toString());
|
|
576
|
-
});
|
|
398
|
+
initialize(config) {
|
|
399
|
+
if (this.isInitialized) {
|
|
400
|
+
return;
|
|
577
401
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
body = isFormData ? options.body : JSON.stringify(options.body);
|
|
402
|
+
this.isInitialized = true;
|
|
403
|
+
if (config) {
|
|
404
|
+
this.telemetryContext = config;
|
|
582
405
|
}
|
|
583
406
|
try {
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
body,
|
|
588
|
-
signal: options.signal
|
|
589
|
-
});
|
|
590
|
-
if (!response.ok) {
|
|
591
|
-
const errorInfo = await errorResponseParser.parse(response);
|
|
592
|
-
throw ErrorFactory.createFromHttpStatus(response.status, errorInfo);
|
|
593
|
-
}
|
|
594
|
-
if (response.status === 204) {
|
|
595
|
-
return undefined;
|
|
596
|
-
}
|
|
597
|
-
// Handle blob response type for binary data (e.g., file downloads)
|
|
598
|
-
if (options.responseType === RESPONSE_TYPES.BLOB) {
|
|
599
|
-
const blob = await response.blob();
|
|
600
|
-
return blob;
|
|
601
|
-
}
|
|
602
|
-
// Check if we're expecting XML
|
|
603
|
-
const acceptHeader = headers['Accept'] || headers['accept'];
|
|
604
|
-
if (acceptHeader === CONTENT_TYPES.XML) {
|
|
605
|
-
const text = await response.text();
|
|
606
|
-
return text;
|
|
407
|
+
const connectionString = this.getConnectionString();
|
|
408
|
+
if (!connectionString) {
|
|
409
|
+
return;
|
|
607
410
|
}
|
|
608
|
-
|
|
411
|
+
this.setupTelemetryProvider(connectionString);
|
|
609
412
|
}
|
|
610
413
|
catch (error) {
|
|
611
|
-
//
|
|
612
|
-
|
|
613
|
-
throw error;
|
|
614
|
-
}
|
|
615
|
-
// Otherwise, it's likely a network error
|
|
616
|
-
throw ErrorFactory.createNetworkError(error);
|
|
414
|
+
// Silent failure - telemetry errors shouldn't break functionality
|
|
415
|
+
console.debug('Failed to initialize OpenTelemetry:', error);
|
|
617
416
|
}
|
|
618
417
|
}
|
|
619
|
-
|
|
620
|
-
|
|
418
|
+
getConnectionString() {
|
|
419
|
+
const connectionString = CONNECTION_STRING;
|
|
420
|
+
return connectionString;
|
|
621
421
|
}
|
|
622
|
-
|
|
623
|
-
|
|
422
|
+
setupTelemetryProvider(connectionString) {
|
|
423
|
+
const exporter = new ApplicationInsightsEventExporter(connectionString);
|
|
424
|
+
const processor = new sdkLogs.BatchLogRecordProcessor(exporter);
|
|
425
|
+
this.logProvider = new sdkLogs.LoggerProvider({
|
|
426
|
+
processors: [processor]
|
|
427
|
+
});
|
|
428
|
+
this.logger = this.logProvider.getLogger(SDK_LOGGER_NAME);
|
|
624
429
|
}
|
|
625
|
-
|
|
626
|
-
|
|
430
|
+
/**
|
|
431
|
+
* Track a telemetry event
|
|
432
|
+
*/
|
|
433
|
+
track(eventName, name, extraAttributes = {}) {
|
|
434
|
+
try {
|
|
435
|
+
// Skip if logger not initialized
|
|
436
|
+
if (!this.logger) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const finalDisplayName = name || eventName;
|
|
440
|
+
const attributes = this.getEnrichedAttributes(extraAttributes, eventName);
|
|
441
|
+
// Emit as log
|
|
442
|
+
this.logger.emit({
|
|
443
|
+
body: finalDisplayName,
|
|
444
|
+
attributes: attributes,
|
|
445
|
+
timestamp: Date.now(),
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
catch (error) {
|
|
449
|
+
// Silent failure
|
|
450
|
+
console.debug('Failed to track telemetry event:', error);
|
|
451
|
+
}
|
|
627
452
|
}
|
|
628
|
-
|
|
629
|
-
|
|
453
|
+
/**
|
|
454
|
+
* Get enriched attributes for telemetry events
|
|
455
|
+
*/
|
|
456
|
+
getEnrichedAttributes(extraAttributes, eventName) {
|
|
457
|
+
const attributes = {
|
|
458
|
+
[APP_NAME]: SDK_SERVICE_NAME,
|
|
459
|
+
[VERSION]: SDK_VERSION,
|
|
460
|
+
[SERVICE]: eventName,
|
|
461
|
+
[CLOUD_URL]: this.createCloudUrl(),
|
|
462
|
+
[CLOUD_ORGANIZATION_NAME]: this.telemetryContext?.orgName || UNKNOWN,
|
|
463
|
+
[CLOUD_TENANT_NAME]: this.telemetryContext?.tenantName || UNKNOWN,
|
|
464
|
+
[CLOUD_REDIRECT_URI]: this.telemetryContext?.redirectUri || UNKNOWN,
|
|
465
|
+
[CLOUD_CLIENT_ID]: this.telemetryContext?.clientId || UNKNOWN,
|
|
466
|
+
...extraAttributes,
|
|
467
|
+
};
|
|
468
|
+
return attributes;
|
|
630
469
|
}
|
|
631
|
-
|
|
632
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Create cloud URL from base URL, organization ID, and tenant ID
|
|
472
|
+
*/
|
|
473
|
+
createCloudUrl() {
|
|
474
|
+
const baseUrl = this.telemetryContext?.baseUrl;
|
|
475
|
+
const orgId = this.telemetryContext?.orgName;
|
|
476
|
+
const tenantId = this.telemetryContext?.tenantName;
|
|
477
|
+
if (!baseUrl || !orgId || !tenantId) {
|
|
478
|
+
return UNKNOWN;
|
|
479
|
+
}
|
|
480
|
+
return `${baseUrl}/${orgId}/${tenantId}`;
|
|
633
481
|
}
|
|
634
482
|
}
|
|
483
|
+
// Export singleton instance
|
|
484
|
+
const telemetryClient = TelemetryClient.getInstance();
|
|
635
485
|
|
|
636
486
|
/**
|
|
637
|
-
*
|
|
487
|
+
* SDK Track decorator and function for telemetry
|
|
638
488
|
*/
|
|
639
|
-
var PaginationType;
|
|
640
|
-
(function (PaginationType) {
|
|
641
|
-
PaginationType["OFFSET"] = "offset";
|
|
642
|
-
PaginationType["TOKEN"] = "token";
|
|
643
|
-
})(PaginationType || (PaginationType = {}));
|
|
644
|
-
|
|
645
489
|
/**
|
|
646
|
-
*
|
|
490
|
+
* Common tracking logic shared between method and function decorators
|
|
647
491
|
*/
|
|
492
|
+
function createTrackedFunction(originalFunction, nameOrOptions, fallbackName, opts) {
|
|
493
|
+
return function (...args) {
|
|
494
|
+
// Determine if we should track this call
|
|
495
|
+
let shouldTrack = true;
|
|
496
|
+
if (opts.condition !== undefined) {
|
|
497
|
+
if (typeof opts.condition === 'function') {
|
|
498
|
+
shouldTrack = opts.condition.apply(this, args);
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
shouldTrack = opts.condition;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Track the event if enabled
|
|
505
|
+
if (shouldTrack) {
|
|
506
|
+
// Use the full name provided in the decorator (e.g., "Queue.GetAll")
|
|
507
|
+
const serviceMethod = typeof nameOrOptions === 'string'
|
|
508
|
+
? nameOrOptions
|
|
509
|
+
: fallbackName;
|
|
510
|
+
// Use 'Sdk.Run' as the name and serviceMethod as the service
|
|
511
|
+
telemetryClient.track(serviceMethod, SDK_RUN_EVENT, opts.attributes);
|
|
512
|
+
}
|
|
513
|
+
// Execute the original function
|
|
514
|
+
return originalFunction.apply(this, args);
|
|
515
|
+
};
|
|
516
|
+
}
|
|
648
517
|
/**
|
|
649
|
-
*
|
|
650
|
-
* @param obj The source object
|
|
651
|
-
* @returns A new object without undefined values
|
|
518
|
+
* Track decorator that can be used to automatically track function calls
|
|
652
519
|
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
* }
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
520
|
+
* Usage:
|
|
521
|
+
* @track("Service.Method")
|
|
522
|
+
* function myFunction() { ... }
|
|
523
|
+
*
|
|
524
|
+
* @track("Queue.GetAll")
|
|
525
|
+
* async getAll() { ... }
|
|
526
|
+
*
|
|
527
|
+
* @track("Tasks.Create")
|
|
528
|
+
* async create() { ... }
|
|
529
|
+
*
|
|
530
|
+
* @track("Assets.Update", { condition: false })
|
|
531
|
+
* function myFunction() { ... }
|
|
532
|
+
*
|
|
533
|
+
* @track("Processes.Start", { attributes: { customProp: "value" } })
|
|
534
|
+
* function myFunction() { ... }
|
|
665
535
|
*/
|
|
666
|
-
function
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
if (value
|
|
670
|
-
|
|
536
|
+
function track(nameOrOptions, options) {
|
|
537
|
+
return function decorator(_target, propertyKey, descriptor) {
|
|
538
|
+
const opts = typeof nameOrOptions === 'object' ? nameOrOptions : {};
|
|
539
|
+
if (descriptor && typeof descriptor.value === 'function') {
|
|
540
|
+
// Method decorator
|
|
541
|
+
descriptor.value = createTrackedFunction(descriptor.value, nameOrOptions, propertyKey || 'unknown_method', opts);
|
|
542
|
+
return descriptor;
|
|
671
543
|
}
|
|
672
|
-
|
|
673
|
-
|
|
544
|
+
// Function decorator
|
|
545
|
+
return (originalFunction) => createTrackedFunction(originalFunction, nameOrOptions, originalFunction.name || 'unknown_function', opts);
|
|
546
|
+
};
|
|
674
547
|
}
|
|
548
|
+
|
|
675
549
|
/**
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
* Used for task assignment APIs that don't use HTTP status codes for errors
|
|
550
|
+
* Types of tasks available in Action Center.
|
|
551
|
+
* Each type determines the task's behavior, UI rendering, and completion requirements.
|
|
679
552
|
*/
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
553
|
+
exports.TaskType = void 0;
|
|
554
|
+
(function (TaskType) {
|
|
555
|
+
/** A form-based task that renders a UiPath form layout for user input */
|
|
556
|
+
TaskType["Form"] = "FormTask";
|
|
557
|
+
/** An externally managed task handled outside of Action Center */
|
|
558
|
+
TaskType["External"] = "ExternalTask";
|
|
559
|
+
/** A task powered by a UiPath App */
|
|
560
|
+
TaskType["App"] = "AppTask";
|
|
561
|
+
/** A document validation task for reviewing and correcting extracted document data */
|
|
562
|
+
TaskType["DocumentValidation"] = "DocumentValidationTask";
|
|
563
|
+
/** A document classification task for categorizing documents */
|
|
564
|
+
TaskType["DocumentClassification"] = "DocumentClassificationTask";
|
|
565
|
+
/** A data labeling task for annotating training data */
|
|
566
|
+
TaskType["DataLabeling"] = "DataLabelingTask";
|
|
567
|
+
})(exports.TaskType || (exports.TaskType = {}));
|
|
568
|
+
exports.TaskPriority = void 0;
|
|
569
|
+
(function (TaskPriority) {
|
|
570
|
+
TaskPriority["Low"] = "Low";
|
|
571
|
+
TaskPriority["Medium"] = "Medium";
|
|
572
|
+
TaskPriority["High"] = "High";
|
|
573
|
+
TaskPriority["Critical"] = "Critical";
|
|
574
|
+
})(exports.TaskPriority || (exports.TaskPriority = {}));
|
|
575
|
+
exports.TaskStatus = void 0;
|
|
576
|
+
(function (TaskStatus) {
|
|
577
|
+
TaskStatus["Unassigned"] = "Unassigned";
|
|
578
|
+
TaskStatus["Pending"] = "Pending";
|
|
579
|
+
TaskStatus["Completed"] = "Completed";
|
|
580
|
+
})(exports.TaskStatus || (exports.TaskStatus = {}));
|
|
581
|
+
exports.TaskSlaCriteria = void 0;
|
|
582
|
+
(function (TaskSlaCriteria) {
|
|
583
|
+
TaskSlaCriteria["TaskCreated"] = "TaskCreated";
|
|
584
|
+
TaskSlaCriteria["TaskAssigned"] = "TaskAssigned";
|
|
585
|
+
TaskSlaCriteria["TaskCompleted"] = "TaskCompleted";
|
|
586
|
+
})(exports.TaskSlaCriteria || (exports.TaskSlaCriteria = {}));
|
|
587
|
+
exports.TaskSlaStatus = void 0;
|
|
588
|
+
(function (TaskSlaStatus) {
|
|
589
|
+
TaskSlaStatus["OverdueLater"] = "OverdueLater";
|
|
590
|
+
TaskSlaStatus["OverdueSoon"] = "OverdueSoon";
|
|
591
|
+
TaskSlaStatus["Overdue"] = "Overdue";
|
|
592
|
+
TaskSlaStatus["CompletedInTime"] = "CompletedInTime";
|
|
593
|
+
})(exports.TaskSlaStatus || (exports.TaskSlaStatus = {}));
|
|
594
|
+
exports.TaskSourceName = void 0;
|
|
595
|
+
(function (TaskSourceName) {
|
|
596
|
+
TaskSourceName["Agent"] = "Agent";
|
|
597
|
+
TaskSourceName["Workflow"] = "Workflow";
|
|
598
|
+
TaskSourceName["Maestro"] = "Maestro";
|
|
599
|
+
TaskSourceName["Default"] = "Default";
|
|
600
|
+
})(exports.TaskSourceName || (exports.TaskSourceName = {}));
|
|
601
|
+
/**
|
|
602
|
+
* Task activity types
|
|
603
|
+
*/
|
|
604
|
+
exports.TaskActivityType = void 0;
|
|
605
|
+
(function (TaskActivityType) {
|
|
606
|
+
TaskActivityType["Created"] = "Created";
|
|
607
|
+
TaskActivityType["Assigned"] = "Assigned";
|
|
608
|
+
TaskActivityType["Reassigned"] = "Reassigned";
|
|
609
|
+
TaskActivityType["Unassigned"] = "Unassigned";
|
|
610
|
+
TaskActivityType["Saved"] = "Saved";
|
|
611
|
+
TaskActivityType["Forwarded"] = "Forwarded";
|
|
612
|
+
TaskActivityType["Completed"] = "Completed";
|
|
613
|
+
TaskActivityType["Commented"] = "Commented";
|
|
614
|
+
TaskActivityType["Deleted"] = "Deleted";
|
|
615
|
+
TaskActivityType["BulkSaved"] = "BulkSaved";
|
|
616
|
+
TaskActivityType["BulkCompleted"] = "BulkCompleted";
|
|
617
|
+
TaskActivityType["FirstOpened"] = "FirstOpened";
|
|
618
|
+
})(exports.TaskActivityType || (exports.TaskActivityType = {}));
|
|
694
619
|
|
|
695
620
|
/**
|
|
696
|
-
*
|
|
621
|
+
* Maps numeric TaskStatus values (from API) to TaskStatus enum values.
|
|
622
|
+
* Extend this file with additional field mappings as needed.
|
|
697
623
|
*/
|
|
624
|
+
const TaskStatusMap = {
|
|
625
|
+
0: exports.TaskStatus.Unassigned,
|
|
626
|
+
1: exports.TaskStatus.Pending,
|
|
627
|
+
2: exports.TaskStatus.Completed,
|
|
628
|
+
};
|
|
629
|
+
// Field mapping for time-related fields to ensure consistent naming
|
|
630
|
+
const TaskMap = {
|
|
631
|
+
completionTime: 'completedTime',
|
|
632
|
+
deletionTime: 'deletedTime',
|
|
633
|
+
lastModificationTime: 'lastModifiedTime',
|
|
634
|
+
creationTime: 'createdTime',
|
|
635
|
+
organizationUnitId: 'folderId'
|
|
636
|
+
};
|
|
698
637
|
/**
|
|
699
|
-
*
|
|
638
|
+
* Default expand parameters
|
|
700
639
|
*/
|
|
701
|
-
const
|
|
702
|
-
isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
|
|
640
|
+
const DEFAULT_TASK_EXPAND = 'AssignedToUser,CreatorUser,LastModifierUser';
|
|
703
641
|
|
|
704
642
|
/**
|
|
705
|
-
*
|
|
643
|
+
* Base path constants for different services
|
|
706
644
|
*/
|
|
645
|
+
const ORCHESTRATOR_BASE = 'orchestrator_';
|
|
646
|
+
|
|
707
647
|
/**
|
|
708
|
-
*
|
|
709
|
-
* @param str - The string to encode
|
|
710
|
-
* @returns Base64 encoded string
|
|
648
|
+
* Orchestrator Service Endpoints
|
|
711
649
|
*/
|
|
712
|
-
function encodeBase64(str) {
|
|
713
|
-
// TextEncoder for UTF-8 encoding (works in both browser and Node.js)
|
|
714
|
-
const encoder = new TextEncoder();
|
|
715
|
-
const data = encoder.encode(str);
|
|
716
|
-
// Convert Uint8Array to base64
|
|
717
|
-
if (isBrowser) {
|
|
718
|
-
// Browser environment
|
|
719
|
-
// Convert Uint8Array to binary string then to base64
|
|
720
|
-
const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
|
|
721
|
-
return btoa(binaryString);
|
|
722
|
-
}
|
|
723
|
-
else {
|
|
724
|
-
// Node.js environment
|
|
725
|
-
return Buffer.from(data).toString('base64');
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
650
|
/**
|
|
729
|
-
*
|
|
730
|
-
* @param base64 - The base64 string to decode
|
|
731
|
-
* @returns Decoded string
|
|
651
|
+
* Task Service (Action Center) Endpoints
|
|
732
652
|
*/
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
653
|
+
const TASK_ENDPOINTS = {
|
|
654
|
+
CREATE_GENERIC_TASK: `${ORCHESTRATOR_BASE}/tasks/GenericTasks/CreateTask`,
|
|
655
|
+
GET_TASK_USERS: (folderId) => `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTaskUsers(organizationUnitId=${folderId})`,
|
|
656
|
+
GET_TASKS_ACROSS_FOLDERS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTasksAcrossFolders`,
|
|
657
|
+
GET_TASKS_ACROSS_FOLDERS_ADMIN: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTasksAcrossFoldersForAdmin`,
|
|
658
|
+
GET_BY_ID: (id) => `${ORCHESTRATOR_BASE}/odata/Tasks(${id})`,
|
|
659
|
+
ASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.AssignTasks`,
|
|
660
|
+
REASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.ReassignTasks`,
|
|
661
|
+
UNASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.UnassignTasks`,
|
|
662
|
+
COMPLETE_FORM_TASK: `${ORCHESTRATOR_BASE}/forms/TaskForms/CompleteTask`,
|
|
663
|
+
COMPLETE_APP_TASK: `${ORCHESTRATOR_BASE}/tasks/AppTasks/CompleteAppTask`,
|
|
664
|
+
COMPLETE_GENERIC_TASK: `${ORCHESTRATOR_BASE}/tasks/GenericTasks/CompleteTask`,
|
|
665
|
+
GET_TASK_FORM_BY_ID: `${ORCHESTRATOR_BASE}/forms/TaskForms/GetTaskFormById`,
|
|
666
|
+
GET_GENERIC_TASK_BY_ID: `${ORCHESTRATOR_BASE}/tasks/GenericTasks/GetTaskDataById`,
|
|
667
|
+
GET_APP_TASK_BY_ID: `${ORCHESTRATOR_BASE}/tasks/AppTasks/GetAppTaskById`,
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
const TASK_TYPE_ENDPOINTS = {
|
|
671
|
+
[exports.TaskType.Form]: TASK_ENDPOINTS.GET_TASK_FORM_BY_ID,
|
|
672
|
+
[exports.TaskType.App]: TASK_ENDPOINTS.GET_APP_TASK_BY_ID,
|
|
673
|
+
[exports.TaskType.DocumentValidation]: TASK_ENDPOINTS.GET_GENERIC_TASK_BY_ID,
|
|
674
|
+
[exports.TaskType.DocumentClassification]: TASK_ENDPOINTS.GET_GENERIC_TASK_BY_ID,
|
|
675
|
+
[exports.TaskType.External]: TASK_ENDPOINTS.GET_GENERIC_TASK_BY_ID,
|
|
676
|
+
[exports.TaskType.DataLabeling]: TASK_ENDPOINTS.GET_GENERIC_TASK_BY_ID,
|
|
677
|
+
};
|
|
678
|
+
var ActionCenterEventNames;
|
|
679
|
+
(function (ActionCenterEventNames) {
|
|
680
|
+
ActionCenterEventNames["TOKENREFRESHED"] = "AC.tokenRefreshed";
|
|
681
|
+
ActionCenterEventNames["REFRESHTOKEN"] = "AC.refreshToken";
|
|
682
|
+
})(ActionCenterEventNames || (ActionCenterEventNames = {}));
|
|
751
683
|
|
|
752
684
|
/**
|
|
753
|
-
*
|
|
754
|
-
*
|
|
685
|
+
* Creates methods for a task
|
|
686
|
+
*
|
|
687
|
+
* @param taskData - The task data (response from API)
|
|
688
|
+
* @param service - The task service instance
|
|
689
|
+
* @returns Object containing task methods
|
|
755
690
|
*/
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
const nextCursor = PaginationManager.createCursor({ pageInfo, type });
|
|
792
|
-
// Create previous page cursor if applicable
|
|
793
|
-
let previousCursor = undefined;
|
|
794
|
-
if (pageInfo.currentPage && pageInfo.currentPage > 1) {
|
|
795
|
-
const prevCursorData = {
|
|
796
|
-
type,
|
|
797
|
-
pageNumber: pageInfo.currentPage - 1,
|
|
798
|
-
pageSize: pageInfo.pageSize,
|
|
799
|
-
};
|
|
800
|
-
previousCursor = {
|
|
801
|
-
value: encodeBase64(JSON.stringify(prevCursorData))
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
// Calculate total pages if we have totalCount and pageSize
|
|
805
|
-
let totalPages = undefined;
|
|
806
|
-
if (pageInfo.totalCount !== undefined && pageInfo.pageSize) {
|
|
807
|
-
totalPages = Math.ceil(pageInfo.totalCount / pageInfo.pageSize);
|
|
691
|
+
function createTaskMethods(taskData, service) {
|
|
692
|
+
return {
|
|
693
|
+
async assign(options) {
|
|
694
|
+
if (!taskData.id)
|
|
695
|
+
throw new Error('Task ID is undefined');
|
|
696
|
+
const assignmentOptions = 'userId' in options && options.userId !== undefined
|
|
697
|
+
? { taskId: taskData.id, userId: options.userId }
|
|
698
|
+
: { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
|
|
699
|
+
return service.assign(assignmentOptions);
|
|
700
|
+
},
|
|
701
|
+
async reassign(options) {
|
|
702
|
+
if (!taskData.id)
|
|
703
|
+
throw new Error('Task ID is undefined');
|
|
704
|
+
const assignmentOptions = 'userId' in options && options.userId !== undefined
|
|
705
|
+
? { taskId: taskData.id, userId: options.userId }
|
|
706
|
+
: { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
|
|
707
|
+
return service.reassign(assignmentOptions);
|
|
708
|
+
},
|
|
709
|
+
async unassign() {
|
|
710
|
+
if (!taskData.id)
|
|
711
|
+
throw new Error('Task ID is undefined');
|
|
712
|
+
return service.unassign(taskData.id);
|
|
713
|
+
},
|
|
714
|
+
async complete(options) {
|
|
715
|
+
if (!taskData.id)
|
|
716
|
+
throw new Error('Task ID is undefined');
|
|
717
|
+
const folderId = taskData.folderId;
|
|
718
|
+
if (!folderId)
|
|
719
|
+
throw new Error('Folder ID is required');
|
|
720
|
+
return service.complete({
|
|
721
|
+
type: options.type,
|
|
722
|
+
taskId: taskData.id,
|
|
723
|
+
data: options.data,
|
|
724
|
+
action: options.action
|
|
725
|
+
}, folderId);
|
|
808
726
|
}
|
|
809
|
-
|
|
810
|
-
const supportsPageJump = type === PaginationType.OFFSET;
|
|
811
|
-
// Create the result object with all fields, then filter out undefined values
|
|
812
|
-
const result = filterUndefined({
|
|
813
|
-
items,
|
|
814
|
-
totalCount: pageInfo.totalCount,
|
|
815
|
-
hasNextPage: pageInfo.hasMore,
|
|
816
|
-
nextCursor: nextCursor,
|
|
817
|
-
previousCursor: previousCursor,
|
|
818
|
-
currentPage: pageInfo.currentPage,
|
|
819
|
-
totalPages,
|
|
820
|
-
supportsPageJump
|
|
821
|
-
});
|
|
822
|
-
return result;
|
|
823
|
-
}
|
|
727
|
+
};
|
|
824
728
|
}
|
|
825
|
-
|
|
826
729
|
/**
|
|
827
|
-
* Creates
|
|
828
|
-
* @param headersObj - Object containing header key-value pairs
|
|
829
|
-
* @returns Headers object with all values converted to strings
|
|
830
|
-
*
|
|
831
|
-
* @example
|
|
832
|
-
* ```typescript
|
|
833
|
-
* // Single header
|
|
834
|
-
* const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
|
|
835
|
-
*
|
|
836
|
-
* // Multiple headers
|
|
837
|
-
* const headers = createHeaders({
|
|
838
|
-
* 'X-UIPATH-FolderKey': '1234567890',
|
|
839
|
-
* 'X-UIPATH-OrganizationUnitId': 123,
|
|
840
|
-
* 'Accept': 'application/json'
|
|
841
|
-
* });
|
|
842
|
-
*
|
|
843
|
-
* // Using constants
|
|
844
|
-
* import { FOLDER_KEY, FOLDER_ID } from '../constants/headers';
|
|
845
|
-
* const headers = createHeaders({
|
|
846
|
-
* [FOLDER_KEY]: 'abc-123',
|
|
847
|
-
* [FOLDER_ID]: 456
|
|
848
|
-
* });
|
|
730
|
+
* Creates an actionable task by combining API task data with operational methods.
|
|
849
731
|
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
732
|
+
* @param taskData - The task data from API
|
|
733
|
+
* @param service - The task service instance
|
|
734
|
+
* @returns A task object with added methods
|
|
853
735
|
*/
|
|
854
|
-
function
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
if (value !== undefined && value !== null) {
|
|
858
|
-
headers[key] = value.toString();
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
return headers;
|
|
736
|
+
function createTaskWithMethods(taskData, service) {
|
|
737
|
+
const methods = createTaskMethods(taskData, service);
|
|
738
|
+
return Object.assign({}, taskData, methods);
|
|
862
739
|
}
|
|
863
740
|
|
|
864
741
|
/**
|
|
@@ -904,38 +781,154 @@ const BUCKET_TOKEN_PARAMS = {
|
|
|
904
781
|
TOKEN_PARAM: 'continuationToken'
|
|
905
782
|
};
|
|
906
783
|
|
|
784
|
+
const FOLDER_ID = 'X-UIPATH-OrganizationUnitId';
|
|
907
785
|
/**
|
|
908
|
-
*
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
786
|
+
* Content type constants for HTTP requests/responses
|
|
787
|
+
*/
|
|
788
|
+
const CONTENT_TYPES = {
|
|
789
|
+
JSON: 'application/json',
|
|
790
|
+
XML: 'application/xml',
|
|
791
|
+
OCTET_STREAM: 'application/octet-stream'
|
|
792
|
+
};
|
|
793
|
+
/**
|
|
794
|
+
* Response type constants for HTTP requests
|
|
795
|
+
*/
|
|
796
|
+
const RESPONSE_TYPES = {
|
|
797
|
+
JSON: 'json',
|
|
798
|
+
TEXT: 'text',
|
|
799
|
+
BLOB: 'blob',
|
|
800
|
+
ARRAYBUFFER: 'arraybuffer'
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Creates headers object from key-value pairs
|
|
805
|
+
* @param headersObj - Object containing header key-value pairs
|
|
806
|
+
* @returns Headers object with all values converted to strings
|
|
912
807
|
*
|
|
913
808
|
* @example
|
|
914
809
|
* ```typescript
|
|
915
|
-
* // Single
|
|
916
|
-
* const
|
|
917
|
-
* const mapping = { id: 'userId', userName: 'name' };
|
|
918
|
-
* const result = transformData(data, mapping);
|
|
919
|
-
* // result = { userId: '123', name: 'john' }
|
|
810
|
+
* // Single header
|
|
811
|
+
* const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
|
|
920
812
|
*
|
|
921
|
-
* //
|
|
922
|
-
* const
|
|
923
|
-
*
|
|
924
|
-
*
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
* //
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
813
|
+
* // Multiple headers
|
|
814
|
+
* const headers = createHeaders({
|
|
815
|
+
* 'X-UIPATH-FolderKey': '1234567890',
|
|
816
|
+
* 'X-UIPATH-OrganizationUnitId': 123,
|
|
817
|
+
* 'Accept': 'application/json'
|
|
818
|
+
* });
|
|
819
|
+
*
|
|
820
|
+
* // Using constants
|
|
821
|
+
* import { FOLDER_KEY, FOLDER_ID } from '../constants/headers';
|
|
822
|
+
* const headers = createHeaders({
|
|
823
|
+
* [FOLDER_KEY]: 'abc-123',
|
|
824
|
+
* [FOLDER_ID]: 456
|
|
825
|
+
* });
|
|
826
|
+
*
|
|
827
|
+
* // Empty headers
|
|
828
|
+
* const headers = createHeaders();
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
function createHeaders(headersObj) {
|
|
832
|
+
const headers = {};
|
|
833
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
834
|
+
if (value !== undefined && value !== null) {
|
|
835
|
+
headers[key] = value.toString();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return headers;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Collection of utility functions for working with objects
|
|
843
|
+
*/
|
|
844
|
+
/**
|
|
845
|
+
* Filters out undefined values from an object
|
|
846
|
+
* @param obj The source object
|
|
847
|
+
* @returns A new object without undefined values
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* ```typescript
|
|
851
|
+
* // Object with undefined values
|
|
852
|
+
* const options = {
|
|
853
|
+
* name: 'test',
|
|
854
|
+
* count: 5,
|
|
855
|
+
* prefix: undefined,
|
|
856
|
+
* suffix: null
|
|
857
|
+
* };
|
|
858
|
+
* const result = filterUndefined(options);
|
|
859
|
+
* // result = { name: 'test', count: 5, suffix: null }
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
function filterUndefined(obj) {
|
|
863
|
+
const result = {};
|
|
864
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
865
|
+
if (value !== undefined) {
|
|
866
|
+
result[key] = value;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Helper function for OData responses that ALWAYS return 200 with array indication
|
|
873
|
+
* Empty array = success, Non-empty array = error
|
|
874
|
+
* Used for task assignment APIs that don't use HTTP status codes for errors
|
|
875
|
+
*/
|
|
876
|
+
function processODataArrayResponse(oDataResponse, successData) {
|
|
877
|
+
// Empty array = success
|
|
878
|
+
if (oDataResponse.value.length === 0) {
|
|
879
|
+
return {
|
|
880
|
+
success: true,
|
|
881
|
+
data: successData
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
// Non-empty array = error details
|
|
885
|
+
return {
|
|
886
|
+
success: false,
|
|
887
|
+
data: oDataResponse.value
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Pagination types supported by the SDK
|
|
893
|
+
*/
|
|
894
|
+
var PaginationType;
|
|
895
|
+
(function (PaginationType) {
|
|
896
|
+
PaginationType["OFFSET"] = "offset";
|
|
897
|
+
PaginationType["TOKEN"] = "token";
|
|
898
|
+
})(PaginationType || (PaginationType = {}));
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Transforms data by mapping fields according to the provided field mapping
|
|
902
|
+
* @param data The source data to transform
|
|
903
|
+
* @param fieldMapping Object mapping source field names to target field names
|
|
904
|
+
* @returns Transformed data with mapped field names
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```typescript
|
|
908
|
+
* // Single object transformation
|
|
909
|
+
* const data = { id: '123', userName: 'john' };
|
|
910
|
+
* const mapping = { id: 'userId', userName: 'name' };
|
|
911
|
+
* const result = transformData(data, mapping);
|
|
912
|
+
* // result = { userId: '123', name: 'john' }
|
|
913
|
+
*
|
|
914
|
+
* // Array transformation
|
|
915
|
+
* const dataArray = [
|
|
916
|
+
* { id: '123', userName: 'john' },
|
|
917
|
+
* { id: '456', userName: 'jane' }
|
|
918
|
+
* ];
|
|
919
|
+
* const result = transformData(dataArray, mapping);
|
|
920
|
+
* // result = [
|
|
921
|
+
* // { userId: '123', name: 'john' },
|
|
922
|
+
* // { userId: '456', name: 'jane' }
|
|
923
|
+
* // ]
|
|
924
|
+
* ```
|
|
925
|
+
*/
|
|
926
|
+
function transformData(data, fieldMapping) {
|
|
927
|
+
// Handle array of objects
|
|
928
|
+
if (Array.isArray(data)) {
|
|
929
|
+
return data.map(item => transformData(item, fieldMapping));
|
|
930
|
+
}
|
|
931
|
+
// Handle single object
|
|
939
932
|
const result = { ...data };
|
|
940
933
|
for (const [sourceField, targetField] of Object.entries(fieldMapping)) {
|
|
941
934
|
if (sourceField in result) {
|
|
@@ -1181,6 +1174,63 @@ function getLimitedPageSize(pageSize) {
|
|
|
1181
1174
|
return Math.max(1, Math.min(pageSize, MAX_PAGE_SIZE));
|
|
1182
1175
|
}
|
|
1183
1176
|
|
|
1177
|
+
/**
|
|
1178
|
+
* Utility functions for platform detection
|
|
1179
|
+
*/
|
|
1180
|
+
/**
|
|
1181
|
+
* Checks if code is running in a browser environment
|
|
1182
|
+
*/
|
|
1183
|
+
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
1184
|
+
isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
|
|
1185
|
+
|
|
1186
|
+
/**
|
|
1187
|
+
* Base64 encoding/decoding
|
|
1188
|
+
*/
|
|
1189
|
+
/**
|
|
1190
|
+
* Encodes a string to base64
|
|
1191
|
+
* @param str - The string to encode
|
|
1192
|
+
* @returns Base64 encoded string
|
|
1193
|
+
*/
|
|
1194
|
+
function encodeBase64(str) {
|
|
1195
|
+
// TextEncoder for UTF-8 encoding (works in both browser and Node.js)
|
|
1196
|
+
const encoder = new TextEncoder();
|
|
1197
|
+
const data = encoder.encode(str);
|
|
1198
|
+
// Convert Uint8Array to base64
|
|
1199
|
+
if (isBrowser) {
|
|
1200
|
+
// Browser environment
|
|
1201
|
+
// Convert Uint8Array to binary string then to base64
|
|
1202
|
+
const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
|
|
1203
|
+
return btoa(binaryString);
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
// Node.js environment
|
|
1207
|
+
return Buffer.from(data).toString('base64');
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Decodes a base64 string
|
|
1212
|
+
* @param base64 - The base64 string to decode
|
|
1213
|
+
* @returns Decoded string
|
|
1214
|
+
*/
|
|
1215
|
+
function decodeBase64(base64) {
|
|
1216
|
+
let bytes;
|
|
1217
|
+
if (isBrowser) {
|
|
1218
|
+
// Browser environment
|
|
1219
|
+
const binaryString = atob(base64);
|
|
1220
|
+
bytes = new Uint8Array(binaryString.length);
|
|
1221
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
1222
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
else {
|
|
1226
|
+
// Node.js environment
|
|
1227
|
+
bytes = new Uint8Array(Buffer.from(base64, 'base64'));
|
|
1228
|
+
}
|
|
1229
|
+
// TextDecoder for UTF-8 decoding (works in both browser and Node.js)
|
|
1230
|
+
const decoder = new TextDecoder();
|
|
1231
|
+
return decoder.decode(bytes);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1184
1234
|
/**
|
|
1185
1235
|
* Helper functions for pagination that can be used across services
|
|
1186
1236
|
*/
|
|
@@ -1434,741 +1484,720 @@ class PaginationHelpers {
|
|
|
1434
1484
|
}
|
|
1435
1485
|
|
|
1436
1486
|
/**
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
1439
|
-
* This class is NOT exported in the public API.
|
|
1440
|
-
* It provides a secure way to share SDK internals between
|
|
1441
|
-
* the UiPath class and service classes without exposing them publicly.
|
|
1442
|
-
*
|
|
1443
|
-
* @internal
|
|
1487
|
+
* Type guards for error response types
|
|
1444
1488
|
*/
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
return
|
|
1455
|
-
|
|
1489
|
+
function isOrchestratorError(error) {
|
|
1490
|
+
return typeof error === 'object' &&
|
|
1491
|
+
error !== null &&
|
|
1492
|
+
'message' in error &&
|
|
1493
|
+
'errorCode' in error &&
|
|
1494
|
+
typeof error.message === 'string' &&
|
|
1495
|
+
typeof error.errorCode === 'number';
|
|
1496
|
+
}
|
|
1497
|
+
function isEntityError(error) {
|
|
1498
|
+
return typeof error === 'object' &&
|
|
1499
|
+
error !== null &&
|
|
1500
|
+
'error' in error &&
|
|
1501
|
+
typeof error.error === 'string';
|
|
1502
|
+
}
|
|
1503
|
+
function isPimsError(error) {
|
|
1504
|
+
return typeof error === 'object' &&
|
|
1505
|
+
error !== null &&
|
|
1506
|
+
'type' in error &&
|
|
1507
|
+
'title' in error &&
|
|
1508
|
+
'status' in error &&
|
|
1509
|
+
typeof error.type === 'string' &&
|
|
1510
|
+
typeof error.title === 'string' &&
|
|
1511
|
+
typeof error.status === 'number';
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1456
1514
|
/**
|
|
1457
|
-
*
|
|
1458
|
-
* Uses WeakMap to prevent memory leaks - entries are automatically
|
|
1459
|
-
* garbage collected when the SDK instance is no longer referenced.
|
|
1460
|
-
*
|
|
1461
|
-
* Uses a global singleton pattern to ensure the same WeakMap is shared
|
|
1462
|
-
* across separately bundled modules (core, entities, tasks, etc.).
|
|
1463
|
-
*
|
|
1464
|
-
* @internal - Not exported in public API
|
|
1515
|
+
* Parser for Orchestrator/Task error format
|
|
1465
1516
|
*/
|
|
1466
|
-
class
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
return getGlobalStore();
|
|
1517
|
+
class OrchestratorErrorParser {
|
|
1518
|
+
canParse(errorBody) {
|
|
1519
|
+
return isOrchestratorError(errorBody);
|
|
1470
1520
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
const internals = this.store.get(instance);
|
|
1484
|
-
if (!internals) {
|
|
1485
|
-
throw new Error('Invalid SDK instance. Make sure to pass a valid UiPath instance to the service constructor.');
|
|
1486
|
-
}
|
|
1487
|
-
return internals;
|
|
1521
|
+
parse(errorBody, response) {
|
|
1522
|
+
const error = errorBody;
|
|
1523
|
+
return {
|
|
1524
|
+
message: error.message,
|
|
1525
|
+
code: response?.status?.toString(),
|
|
1526
|
+
details: {
|
|
1527
|
+
errorCode: error.errorCode,
|
|
1528
|
+
traceId: error.traceId,
|
|
1529
|
+
originalResponse: error
|
|
1530
|
+
},
|
|
1531
|
+
requestId: error.traceId
|
|
1532
|
+
};
|
|
1488
1533
|
}
|
|
1489
1534
|
}
|
|
1490
|
-
|
|
1491
|
-
var _BaseService_apiClient;
|
|
1492
1535
|
/**
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
* Provides common functionality for authentication, configuration, and API communication.
|
|
1496
|
-
* All service classes extend this base to inherit dependency injection and HTTP client access.
|
|
1497
|
-
*
|
|
1498
|
-
* This class implements the dependency injection pattern where services receive a configured
|
|
1499
|
-
* UiPath instance. The ApiClient is created internally and handles all HTTP operations
|
|
1500
|
-
* including authentication token management.
|
|
1501
|
-
*
|
|
1502
|
-
* @remarks
|
|
1503
|
-
* Service classes should extend this base and call `super(uiPath)` in their constructor.
|
|
1504
|
-
* Protected HTTP methods (get, post, put, patch, delete) are available to all subclasses.
|
|
1505
|
-
*
|
|
1536
|
+
* Parser for Entity (Data Fabric) error format
|
|
1506
1537
|
*/
|
|
1507
|
-
class
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
*
|
|
1511
|
-
* Extracts configuration, execution context, and token manager from the UiPath instance
|
|
1512
|
-
* to initialize an authenticated API client. The ApiClient handles all HTTP operations
|
|
1513
|
-
* and token management internally.
|
|
1514
|
-
*
|
|
1515
|
-
* @param instance - UiPath SDK instance providing authentication and configuration.
|
|
1516
|
-
* Services receive this via dependency injection in the modular pattern.
|
|
1517
|
-
*
|
|
1518
|
-
* @example
|
|
1519
|
-
* ```typescript
|
|
1520
|
-
* // Services automatically call this via super()
|
|
1521
|
-
* export class EntityService extends BaseService {
|
|
1522
|
-
* constructor(instance: IUiPath) {
|
|
1523
|
-
* super(instance); // Initializes the internal ApiClient
|
|
1524
|
-
* }
|
|
1525
|
-
* }
|
|
1526
|
-
*
|
|
1527
|
-
* // Usage in modular pattern
|
|
1528
|
-
* import { UiPath } from '@uipath/uipath-typescript/core';
|
|
1529
|
-
* import { Entities } from '@uipath/uipath-typescript/entities';
|
|
1530
|
-
*
|
|
1531
|
-
* const sdk = new UiPath(config);
|
|
1532
|
-
* await sdk.initialize();
|
|
1533
|
-
* const entities = new Entities(sdk);
|
|
1534
|
-
* ```
|
|
1535
|
-
*/
|
|
1536
|
-
constructor(instance) {
|
|
1537
|
-
// Private field - not visible via Object.keys() or any reflection
|
|
1538
|
-
_BaseService_apiClient.set(this, void 0);
|
|
1539
|
-
const { config, context, tokenManager } = SDKInternalsRegistry.get(instance);
|
|
1540
|
-
__classPrivateFieldSet(this, _BaseService_apiClient, new ApiClient(config, context, tokenManager), "f");
|
|
1541
|
-
}
|
|
1542
|
-
/**
|
|
1543
|
-
* Gets a valid authentication token, refreshing if necessary.
|
|
1544
|
-
* Use this when you need to manually add Authorization headers (e.g., direct uploads).
|
|
1545
|
-
*
|
|
1546
|
-
* @returns Promise resolving to a valid access token string
|
|
1547
|
-
* @throws AuthenticationError if no token is available or refresh fails
|
|
1548
|
-
*/
|
|
1549
|
-
async getValidAuthToken() {
|
|
1550
|
-
return __classPrivateFieldGet(this, _BaseService_apiClient, "f").getValidToken();
|
|
1538
|
+
class EntityErrorParser {
|
|
1539
|
+
canParse(errorBody) {
|
|
1540
|
+
return isEntityError(errorBody);
|
|
1551
1541
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
* This allows pagination helpers to access protected methods without making them public
|
|
1555
|
-
*/
|
|
1556
|
-
createPaginationServiceAccess() {
|
|
1542
|
+
parse(errorBody, response) {
|
|
1543
|
+
const error = errorBody;
|
|
1557
1544
|
return {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1545
|
+
message: error.error,
|
|
1546
|
+
code: response?.status?.toString(),
|
|
1547
|
+
details: {
|
|
1548
|
+
error: error.error,
|
|
1549
|
+
traceId: error.traceId,
|
|
1550
|
+
originalResponse: error
|
|
1551
|
+
},
|
|
1552
|
+
requestId: error.traceId
|
|
1561
1553
|
};
|
|
1562
1554
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
return this.put(path, options.body, options);
|
|
1571
|
-
case 'PATCH':
|
|
1572
|
-
return this.patch(path, options.body, options);
|
|
1573
|
-
case 'DELETE':
|
|
1574
|
-
return this.delete(path, options);
|
|
1575
|
-
default:
|
|
1576
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
1577
|
-
}
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Parser for PIMS error format
|
|
1558
|
+
*/
|
|
1559
|
+
class PimsErrorParser {
|
|
1560
|
+
canParse(errorBody) {
|
|
1561
|
+
return isPimsError(errorBody);
|
|
1578
1562
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1563
|
+
parse(errorBody, response) {
|
|
1564
|
+
const error = errorBody;
|
|
1565
|
+
let message = error.title;
|
|
1566
|
+
// If there are validation errors, append them to the message for better visibility
|
|
1567
|
+
if (error.errors && Object.keys(error.errors).length > 0) {
|
|
1568
|
+
const errorMessages = Object.entries(error.errors)
|
|
1569
|
+
.map(([field, messages]) => `${field}: ${messages.join(', ')}`)
|
|
1570
|
+
.join('; ');
|
|
1571
|
+
message += `. Validation errors: ${errorMessages}`;
|
|
1582
1572
|
}
|
|
1583
|
-
return
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1573
|
+
return {
|
|
1574
|
+
message,
|
|
1575
|
+
code: response?.status?.toString(),
|
|
1576
|
+
details: {
|
|
1577
|
+
type: error.type,
|
|
1578
|
+
title: error.title,
|
|
1579
|
+
status: error.status,
|
|
1580
|
+
errors: error.errors,
|
|
1581
|
+
traceId: error.traceId,
|
|
1582
|
+
originalResponse: error
|
|
1583
|
+
},
|
|
1584
|
+
requestId: error.traceId
|
|
1585
|
+
};
|
|
1592
1586
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Fallback parser for unrecognized formats
|
|
1590
|
+
*/
|
|
1591
|
+
class GenericErrorParser {
|
|
1592
|
+
canParse(_errorBody) {
|
|
1593
|
+
return true; // Always can parse as last resort
|
|
1596
1594
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1595
|
+
parse(errorBody, response) {
|
|
1596
|
+
// For unknown error formats, just pass through the raw error with fallback message
|
|
1597
|
+
const message = response?.statusText || 'An error occurred';
|
|
1598
|
+
return {
|
|
1599
|
+
message,
|
|
1600
|
+
code: response?.status?.toString(),
|
|
1601
|
+
details: {
|
|
1602
|
+
originalResponse: errorBody
|
|
1603
|
+
},
|
|
1604
|
+
};
|
|
1600
1605
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Main error response parser using Chain of Responsibility pattern
|
|
1609
|
+
*
|
|
1610
|
+
* This parser standardizes error responses from different UiPath services into a
|
|
1611
|
+
* consistent format, regardless of the original error structure.
|
|
1612
|
+
*
|
|
1613
|
+
* Supported formats:
|
|
1614
|
+
* 1. Orchestrator/Task: { message, errorCode, traceId }
|
|
1615
|
+
* 2. Entity (Data Fabric): { error, traceId }
|
|
1616
|
+
* 3. PIMS/Maestro: { type, title, status, errors?, traceId? }
|
|
1617
|
+
* 4. Generic: Fallback for any other format
|
|
1618
|
+
*
|
|
1619
|
+
* @example
|
|
1620
|
+
* const parser = new ErrorResponseParser();
|
|
1621
|
+
* const errorInfo = await parser.parse(response);
|
|
1622
|
+
* // errorInfo will have consistent structure regardless of service
|
|
1623
|
+
*/
|
|
1624
|
+
class ErrorResponseParser {
|
|
1625
|
+
constructor() {
|
|
1626
|
+
this.strategies = [
|
|
1627
|
+
new OrchestratorErrorParser(),
|
|
1628
|
+
new EntityErrorParser(),
|
|
1629
|
+
new PimsErrorParser(),
|
|
1630
|
+
new GenericErrorParser() // Must be last
|
|
1631
|
+
];
|
|
1604
1632
|
}
|
|
1605
1633
|
/**
|
|
1606
|
-
*
|
|
1634
|
+
* Parses error response body into standardized format
|
|
1635
|
+
* @param response - The HTTP response object
|
|
1636
|
+
* @returns Standardized error information
|
|
1607
1637
|
*/
|
|
1608
|
-
async
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (method.toUpperCase() === 'POST') {
|
|
1616
|
-
const existingBody = (options.body && typeof options.body === 'object') ? options.body : {};
|
|
1617
|
-
options.body = {
|
|
1618
|
-
...existingBody,
|
|
1619
|
-
...options.params,
|
|
1620
|
-
...requestParams
|
|
1621
|
-
};
|
|
1638
|
+
async parse(response) {
|
|
1639
|
+
try {
|
|
1640
|
+
const errorBody = await response.json();
|
|
1641
|
+
// Find the first strategy that can parse this error format
|
|
1642
|
+
const strategy = this.strategies.find(s => s.canParse(errorBody));
|
|
1643
|
+
// GenericErrorParser always returns true, so this will never be null
|
|
1644
|
+
return strategy.parse(errorBody, response);
|
|
1622
1645
|
}
|
|
1623
|
-
|
|
1624
|
-
//
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1646
|
+
catch {
|
|
1647
|
+
// Handle non-JSON responses
|
|
1648
|
+
const responseText = await response.text().catch(() => '');
|
|
1649
|
+
return {
|
|
1650
|
+
message: response.statusText,
|
|
1651
|
+
code: response.status.toString(),
|
|
1652
|
+
details: {
|
|
1653
|
+
parseError: 'Failed to parse error response as JSON',
|
|
1654
|
+
responseText
|
|
1655
|
+
},
|
|
1656
|
+
requestId: response.headers.get(HttpHeaders.X_REQUEST_ID) || undefined
|
|
1628
1657
|
};
|
|
1629
1658
|
}
|
|
1630
|
-
// Make the request
|
|
1631
|
-
const response = await this.request(method, path, options);
|
|
1632
|
-
// Extract data from the response and create page result
|
|
1633
|
-
return this.createPaginatedResponseFromResponse(response, params, paginationType, {
|
|
1634
|
-
itemsField: options.pagination.itemsField,
|
|
1635
|
-
totalCountField: options.pagination.totalCountField,
|
|
1636
|
-
continuationTokenField: options.pagination.continuationTokenField
|
|
1637
|
-
});
|
|
1638
1659
|
}
|
|
1660
|
+
}
|
|
1661
|
+
// Export singleton instance
|
|
1662
|
+
const errorResponseParser = new ErrorResponseParser();
|
|
1663
|
+
|
|
1664
|
+
/**
|
|
1665
|
+
* Factory for creating typed errors based on HTTP status codes
|
|
1666
|
+
* Follows the Factory pattern for clean error instantiation
|
|
1667
|
+
*/
|
|
1668
|
+
class ErrorFactory {
|
|
1639
1669
|
/**
|
|
1640
|
-
*
|
|
1641
|
-
*/
|
|
1642
|
-
validateAndPreparePaginationParams(paginationType, paginationOptions) {
|
|
1643
|
-
return PaginationHelpers.validatePaginationOptions(paginationOptions, paginationType);
|
|
1644
|
-
}
|
|
1645
|
-
/**
|
|
1646
|
-
* Prepares request parameters for pagination based on pagination type
|
|
1670
|
+
* Creates appropriate error instance based on HTTP status code
|
|
1647
1671
|
*/
|
|
1648
|
-
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
break;
|
|
1667
|
-
case PaginationType.TOKEN:
|
|
1668
|
-
const tokenPageSizeParam = paginationParams?.pageSizeParam || BUCKET_TOKEN_PARAMS.PAGE_SIZE_PARAM;
|
|
1669
|
-
const tokenParam = paginationParams?.tokenParam || BUCKET_TOKEN_PARAMS.TOKEN_PARAM;
|
|
1670
|
-
if (params.pageSize) {
|
|
1671
|
-
requestParams[tokenPageSizeParam] = getLimitedPageSize(params.pageSize);
|
|
1672
|
-
}
|
|
1673
|
-
if (params.continuationToken) {
|
|
1674
|
-
requestParams[tokenParam] = params.continuationToken;
|
|
1672
|
+
static createFromHttpStatus(statusCode, errorInfo) {
|
|
1673
|
+
const { message, requestId } = errorInfo;
|
|
1674
|
+
// Map status codes to error types
|
|
1675
|
+
switch (statusCode) {
|
|
1676
|
+
case HttpStatus.BAD_REQUEST:
|
|
1677
|
+
return new ValidationError({ message, statusCode, requestId });
|
|
1678
|
+
case HttpStatus.UNAUTHORIZED:
|
|
1679
|
+
return new AuthenticationError({ message, statusCode, requestId });
|
|
1680
|
+
case HttpStatus.FORBIDDEN:
|
|
1681
|
+
return new AuthorizationError({ message, statusCode, requestId });
|
|
1682
|
+
case HttpStatus.NOT_FOUND:
|
|
1683
|
+
return new NotFoundError({ message, statusCode, requestId });
|
|
1684
|
+
case HttpStatus.TOO_MANY_REQUESTS:
|
|
1685
|
+
return new RateLimitError({ message, statusCode, requestId });
|
|
1686
|
+
default:
|
|
1687
|
+
// For 5xx errors or any other status code
|
|
1688
|
+
if (statusCode >= HttpStatus.INTERNAL_SERVER_ERROR) {
|
|
1689
|
+
return new ServerError({ message, statusCode, requestId });
|
|
1675
1690
|
}
|
|
1676
|
-
|
|
1691
|
+
// For unknown client errors, treat as validation error
|
|
1692
|
+
return new ValidationError({
|
|
1693
|
+
message: `${message} (HTTP ${statusCode})`,
|
|
1694
|
+
statusCode,
|
|
1695
|
+
requestId
|
|
1696
|
+
});
|
|
1677
1697
|
}
|
|
1678
|
-
return requestParams;
|
|
1679
1698
|
}
|
|
1680
1699
|
/**
|
|
1681
|
-
* Creates a
|
|
1700
|
+
* Creates a NetworkError from a fetch/network error
|
|
1682
1701
|
*/
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
(
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
type: paginationType,
|
|
1711
|
-
}, items);
|
|
1702
|
+
static createNetworkError(error) {
|
|
1703
|
+
let message = ErrorMessages.NETWORK_ERROR;
|
|
1704
|
+
if (error instanceof Error) {
|
|
1705
|
+
if (error.name === ErrorNames.ABORT_ERROR) {
|
|
1706
|
+
message = ErrorMessages.REQUEST_ABORTED;
|
|
1707
|
+
}
|
|
1708
|
+
else if (error.message.includes('timeout')) {
|
|
1709
|
+
message = ErrorMessages.REQUEST_TIMEOUT;
|
|
1710
|
+
}
|
|
1711
|
+
else {
|
|
1712
|
+
message = error.message;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
return new NetworkError({ message });
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
class ApiClient {
|
|
1720
|
+
constructor(config, executionContext, tokenManager, clientConfig = {}) {
|
|
1721
|
+
this.defaultHeaders = {};
|
|
1722
|
+
this.config = config;
|
|
1723
|
+
this.executionContext = executionContext;
|
|
1724
|
+
this.clientConfig = clientConfig;
|
|
1725
|
+
this.tokenManager = tokenManager;
|
|
1726
|
+
}
|
|
1727
|
+
setDefaultHeaders(headers) {
|
|
1728
|
+
this.defaultHeaders = { ...this.defaultHeaders, ...headers };
|
|
1712
1729
|
}
|
|
1713
1730
|
/**
|
|
1714
|
-
*
|
|
1731
|
+
* Gets a valid authentication token, refreshing if necessary.
|
|
1732
|
+
* Used internally for API requests and exposed for services that need manual auth headers.
|
|
1733
|
+
*
|
|
1734
|
+
* @returns The valid token
|
|
1735
|
+
* @throws AuthenticationError if no token available or refresh fails
|
|
1715
1736
|
*/
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1737
|
+
async getValidToken() {
|
|
1738
|
+
return this.tokenManager.getValidToken();
|
|
1739
|
+
}
|
|
1740
|
+
async getDefaultHeaders() {
|
|
1741
|
+
const token = await this.getValidToken();
|
|
1742
|
+
return {
|
|
1743
|
+
'Authorization': `Bearer ${token}`,
|
|
1744
|
+
'Content-Type': CONTENT_TYPES.JSON,
|
|
1745
|
+
...this.defaultHeaders,
|
|
1746
|
+
...this.clientConfig.headers
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
async request(method, path, options = {}) {
|
|
1750
|
+
// Ensure path starts with a forward slash
|
|
1751
|
+
const normalizedPath = path.startsWith('/') ? path.substring(1) : path;
|
|
1752
|
+
// Construct URL with org and tenant names
|
|
1753
|
+
const url = new URL(`${this.config.orgName}/${this.config.tenantName}/${normalizedPath}`, this.config.baseUrl).toString();
|
|
1754
|
+
const isFormData = options.body instanceof FormData;
|
|
1755
|
+
const defaultHeaders = await this.getDefaultHeaders();
|
|
1756
|
+
if (isFormData) {
|
|
1757
|
+
delete defaultHeaders['Content-Type'];
|
|
1758
|
+
}
|
|
1759
|
+
const headers = {
|
|
1760
|
+
...defaultHeaders,
|
|
1761
|
+
...options.headers
|
|
1762
|
+
};
|
|
1763
|
+
// Convert params to URLSearchParams
|
|
1764
|
+
const searchParams = new URLSearchParams();
|
|
1765
|
+
if (options.params) {
|
|
1766
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
1767
|
+
searchParams.append(key, value.toString());
|
|
1768
|
+
});
|
|
1731
1769
|
}
|
|
1770
|
+
const fullUrl = searchParams.toString() ? `${url}?${searchParams.toString()}` : url;
|
|
1771
|
+
let body = undefined;
|
|
1772
|
+
if (options.body) {
|
|
1773
|
+
body = isFormData ? options.body : JSON.stringify(options.body);
|
|
1774
|
+
}
|
|
1775
|
+
try {
|
|
1776
|
+
const response = await fetch(fullUrl, {
|
|
1777
|
+
method,
|
|
1778
|
+
headers,
|
|
1779
|
+
body,
|
|
1780
|
+
signal: options.signal
|
|
1781
|
+
});
|
|
1782
|
+
if (!response.ok) {
|
|
1783
|
+
const errorInfo = await errorResponseParser.parse(response);
|
|
1784
|
+
throw ErrorFactory.createFromHttpStatus(response.status, errorInfo);
|
|
1785
|
+
}
|
|
1786
|
+
if (response.status === 204) {
|
|
1787
|
+
return undefined;
|
|
1788
|
+
}
|
|
1789
|
+
// Handle blob response type for binary data (e.g., file downloads)
|
|
1790
|
+
if (options.responseType === RESPONSE_TYPES.BLOB) {
|
|
1791
|
+
const blob = await response.blob();
|
|
1792
|
+
return blob;
|
|
1793
|
+
}
|
|
1794
|
+
// Check if we're expecting XML
|
|
1795
|
+
const acceptHeader = headers['Accept'] || headers['accept'];
|
|
1796
|
+
if (acceptHeader === CONTENT_TYPES.XML) {
|
|
1797
|
+
const text = await response.text();
|
|
1798
|
+
return text;
|
|
1799
|
+
}
|
|
1800
|
+
return response.json();
|
|
1801
|
+
}
|
|
1802
|
+
catch (error) {
|
|
1803
|
+
// If it's already one of our errors, re-throw it
|
|
1804
|
+
if (error.type && error.type.includes('Error')) {
|
|
1805
|
+
throw error;
|
|
1806
|
+
}
|
|
1807
|
+
// Otherwise, it's likely a network error
|
|
1808
|
+
throw ErrorFactory.createNetworkError(error);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
async get(path, options = {}) {
|
|
1812
|
+
return this.request('GET', path, options);
|
|
1813
|
+
}
|
|
1814
|
+
async post(path, data, options = {}) {
|
|
1815
|
+
return this.request('POST', path, { ...options, body: data });
|
|
1816
|
+
}
|
|
1817
|
+
async put(path, data, options = {}) {
|
|
1818
|
+
return this.request('PUT', path, { ...options, body: data });
|
|
1819
|
+
}
|
|
1820
|
+
async patch(path, data, options = {}) {
|
|
1821
|
+
return this.request('PATCH', path, { ...options, body: data });
|
|
1822
|
+
}
|
|
1823
|
+
async delete(path, options = {}) {
|
|
1824
|
+
return this.request('DELETE', path, options);
|
|
1732
1825
|
}
|
|
1733
1826
|
}
|
|
1734
|
-
_BaseService_apiClient = new WeakMap();
|
|
1735
|
-
|
|
1736
|
-
exports.TaskType = void 0;
|
|
1737
|
-
(function (TaskType) {
|
|
1738
|
-
TaskType["Form"] = "FormTask";
|
|
1739
|
-
TaskType["External"] = "ExternalTask";
|
|
1740
|
-
TaskType["App"] = "AppTask";
|
|
1741
|
-
})(exports.TaskType || (exports.TaskType = {}));
|
|
1742
|
-
exports.TaskPriority = void 0;
|
|
1743
|
-
(function (TaskPriority) {
|
|
1744
|
-
TaskPriority["Low"] = "Low";
|
|
1745
|
-
TaskPriority["Medium"] = "Medium";
|
|
1746
|
-
TaskPriority["High"] = "High";
|
|
1747
|
-
TaskPriority["Critical"] = "Critical";
|
|
1748
|
-
})(exports.TaskPriority || (exports.TaskPriority = {}));
|
|
1749
|
-
exports.TaskStatus = void 0;
|
|
1750
|
-
(function (TaskStatus) {
|
|
1751
|
-
TaskStatus["Unassigned"] = "Unassigned";
|
|
1752
|
-
TaskStatus["Pending"] = "Pending";
|
|
1753
|
-
TaskStatus["Completed"] = "Completed";
|
|
1754
|
-
})(exports.TaskStatus || (exports.TaskStatus = {}));
|
|
1755
|
-
exports.TaskSlaCriteria = void 0;
|
|
1756
|
-
(function (TaskSlaCriteria) {
|
|
1757
|
-
TaskSlaCriteria["TaskCreated"] = "TaskCreated";
|
|
1758
|
-
TaskSlaCriteria["TaskAssigned"] = "TaskAssigned";
|
|
1759
|
-
TaskSlaCriteria["TaskCompleted"] = "TaskCompleted";
|
|
1760
|
-
})(exports.TaskSlaCriteria || (exports.TaskSlaCriteria = {}));
|
|
1761
|
-
exports.TaskSlaStatus = void 0;
|
|
1762
|
-
(function (TaskSlaStatus) {
|
|
1763
|
-
TaskSlaStatus["OverdueLater"] = "OverdueLater";
|
|
1764
|
-
TaskSlaStatus["OverdueSoon"] = "OverdueSoon";
|
|
1765
|
-
TaskSlaStatus["Overdue"] = "Overdue";
|
|
1766
|
-
TaskSlaStatus["CompletedInTime"] = "CompletedInTime";
|
|
1767
|
-
})(exports.TaskSlaStatus || (exports.TaskSlaStatus = {}));
|
|
1768
|
-
exports.TaskSourceName = void 0;
|
|
1769
|
-
(function (TaskSourceName) {
|
|
1770
|
-
TaskSourceName["Agent"] = "Agent";
|
|
1771
|
-
TaskSourceName["Workflow"] = "Workflow";
|
|
1772
|
-
TaskSourceName["Maestro"] = "Maestro";
|
|
1773
|
-
TaskSourceName["Default"] = "Default";
|
|
1774
|
-
})(exports.TaskSourceName || (exports.TaskSourceName = {}));
|
|
1775
|
-
/**
|
|
1776
|
-
* Task activity types
|
|
1777
|
-
*/
|
|
1778
|
-
exports.TaskActivityType = void 0;
|
|
1779
|
-
(function (TaskActivityType) {
|
|
1780
|
-
TaskActivityType["Created"] = "Created";
|
|
1781
|
-
TaskActivityType["Assigned"] = "Assigned";
|
|
1782
|
-
TaskActivityType["Reassigned"] = "Reassigned";
|
|
1783
|
-
TaskActivityType["Unassigned"] = "Unassigned";
|
|
1784
|
-
TaskActivityType["Saved"] = "Saved";
|
|
1785
|
-
TaskActivityType["Forwarded"] = "Forwarded";
|
|
1786
|
-
TaskActivityType["Completed"] = "Completed";
|
|
1787
|
-
TaskActivityType["Commented"] = "Commented";
|
|
1788
|
-
TaskActivityType["Deleted"] = "Deleted";
|
|
1789
|
-
TaskActivityType["BulkSaved"] = "BulkSaved";
|
|
1790
|
-
TaskActivityType["BulkCompleted"] = "BulkCompleted";
|
|
1791
|
-
TaskActivityType["FirstOpened"] = "FirstOpened";
|
|
1792
|
-
})(exports.TaskActivityType || (exports.TaskActivityType = {}));
|
|
1793
1827
|
|
|
1794
1828
|
/**
|
|
1795
|
-
*
|
|
1796
|
-
*
|
|
1797
|
-
* @param taskData - The task data (response from API)
|
|
1798
|
-
* @param service - The task service instance
|
|
1799
|
-
* @returns Object containing task methods
|
|
1829
|
+
* PaginationManager handles the conversion between uniform cursor-based pagination
|
|
1830
|
+
* and the specific pagination type for each service
|
|
1800
1831
|
*/
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
: { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
|
|
1809
|
-
return service.assign(assignmentOptions);
|
|
1810
|
-
},
|
|
1811
|
-
async reassign(options) {
|
|
1812
|
-
if (!taskData.id)
|
|
1813
|
-
throw new Error('Task ID is undefined');
|
|
1814
|
-
const assignmentOptions = 'userId' in options && options.userId !== undefined
|
|
1815
|
-
? { taskId: taskData.id, userId: options.userId }
|
|
1816
|
-
: { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
|
|
1817
|
-
return service.reassign(assignmentOptions);
|
|
1818
|
-
},
|
|
1819
|
-
async unassign() {
|
|
1820
|
-
if (!taskData.id)
|
|
1821
|
-
throw new Error('Task ID is undefined');
|
|
1822
|
-
return service.unassign(taskData.id);
|
|
1823
|
-
},
|
|
1824
|
-
async complete(options) {
|
|
1825
|
-
if (!taskData.id)
|
|
1826
|
-
throw new Error('Task ID is undefined');
|
|
1827
|
-
const folderId = taskData.folderId;
|
|
1828
|
-
if (!folderId)
|
|
1829
|
-
throw new Error('Folder ID is required');
|
|
1830
|
-
return service.complete({
|
|
1831
|
-
type: options.type,
|
|
1832
|
-
taskId: taskData.id,
|
|
1833
|
-
data: options.data,
|
|
1834
|
-
action: options.action
|
|
1835
|
-
}, folderId);
|
|
1832
|
+
class PaginationManager {
|
|
1833
|
+
/**
|
|
1834
|
+
* Create a pagination cursor for subsequent page requests
|
|
1835
|
+
*/
|
|
1836
|
+
static createCursor({ pageInfo, type }) {
|
|
1837
|
+
if (!pageInfo.hasMore) {
|
|
1838
|
+
return undefined;
|
|
1836
1839
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
};
|
|
1860
|
-
// Field mapping for time-related fields to ensure consistent naming
|
|
1861
|
-
const TaskMap = {
|
|
1862
|
-
completionTime: 'completedTime',
|
|
1863
|
-
deletionTime: 'deletedTime',
|
|
1864
|
-
lastModificationTime: 'lastModifiedTime',
|
|
1865
|
-
creationTime: 'createdTime',
|
|
1866
|
-
organizationUnitId: 'folderId'
|
|
1867
|
-
};
|
|
1868
|
-
/**
|
|
1869
|
-
* Default expand parameters
|
|
1870
|
-
*/
|
|
1871
|
-
const DEFAULT_TASK_EXPAND = 'AssignedToUser,CreatorUser,LastModifierUser';
|
|
1872
|
-
|
|
1873
|
-
/**
|
|
1874
|
-
* Base path constants for different services
|
|
1875
|
-
*/
|
|
1876
|
-
const ORCHESTRATOR_BASE = 'orchestrator_';
|
|
1877
|
-
|
|
1878
|
-
/**
|
|
1879
|
-
* Orchestrator Service Endpoints
|
|
1880
|
-
*/
|
|
1881
|
-
/**
|
|
1882
|
-
* Task Service (Action Center) Endpoints
|
|
1883
|
-
*/
|
|
1884
|
-
const TASK_ENDPOINTS = {
|
|
1885
|
-
CREATE_GENERIC_TASK: `${ORCHESTRATOR_BASE}/tasks/GenericTasks/CreateTask`,
|
|
1886
|
-
GET_TASK_USERS: (folderId) => `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTaskUsers(organizationUnitId=${folderId})`,
|
|
1887
|
-
GET_TASKS_ACROSS_FOLDERS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTasksAcrossFolders`,
|
|
1888
|
-
GET_TASKS_ACROSS_FOLDERS_ADMIN: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.GetTasksAcrossFoldersForAdmin`,
|
|
1889
|
-
GET_BY_ID: (id) => `${ORCHESTRATOR_BASE}/odata/Tasks(${id})`,
|
|
1890
|
-
ASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.AssignTasks`,
|
|
1891
|
-
REASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.ReassignTasks`,
|
|
1892
|
-
UNASSIGN_TASKS: `${ORCHESTRATOR_BASE}/odata/Tasks/UiPath.Server.Configuration.OData.UnassignTasks`,
|
|
1893
|
-
COMPLETE_FORM_TASK: `${ORCHESTRATOR_BASE}/forms/TaskForms/CompleteTask`,
|
|
1894
|
-
COMPLETE_APP_TASK: `${ORCHESTRATOR_BASE}/tasks/AppTasks/CompleteAppTask`,
|
|
1895
|
-
COMPLETE_GENERIC_TASK: `${ORCHESTRATOR_BASE}/tasks/GenericTasks/CompleteTask`,
|
|
1896
|
-
GET_TASK_FORM_BY_ID: `${ORCHESTRATOR_BASE}/forms/TaskForms/GetTaskFormById`,
|
|
1897
|
-
};
|
|
1898
|
-
|
|
1899
|
-
/**
|
|
1900
|
-
* SDK Telemetry constants
|
|
1901
|
-
*/
|
|
1902
|
-
// Connection string placeholder that will be replaced during build
|
|
1903
|
-
const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
|
|
1904
|
-
// SDK Version placeholder
|
|
1905
|
-
const SDK_VERSION = "1.2.0";
|
|
1906
|
-
const VERSION = "Version";
|
|
1907
|
-
const SERVICE = "Service";
|
|
1908
|
-
const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
|
|
1909
|
-
const CLOUD_TENANT_NAME = "CloudTenantName";
|
|
1910
|
-
const CLOUD_URL = "CloudUrl";
|
|
1911
|
-
const CLOUD_CLIENT_ID = "CloudClientId";
|
|
1912
|
-
const CLOUD_REDIRECT_URI = "CloudRedirectUri";
|
|
1913
|
-
const APP_NAME = "ApplicationName";
|
|
1914
|
-
const CLOUD_ROLE_NAME = "uipath-ts-sdk";
|
|
1915
|
-
// Service and logger names
|
|
1916
|
-
const SDK_SERVICE_NAME = "UiPath.TypeScript.Sdk";
|
|
1917
|
-
const SDK_LOGGER_NAME = "uipath-ts-sdk-telemetry";
|
|
1918
|
-
// Event names
|
|
1919
|
-
const SDK_RUN_EVENT = "Sdk.Run";
|
|
1920
|
-
// Default value for unknown/empty attributes
|
|
1921
|
-
const UNKNOWN = "";
|
|
1922
|
-
|
|
1923
|
-
/**
|
|
1924
|
-
* Log exporter that sends ALL logs as Application Insights custom events
|
|
1925
|
-
*/
|
|
1926
|
-
class ApplicationInsightsEventExporter {
|
|
1927
|
-
constructor(connectionString) {
|
|
1928
|
-
this.connectionString = connectionString;
|
|
1840
|
+
const cursorData = {
|
|
1841
|
+
type,
|
|
1842
|
+
pageSize: pageInfo.pageSize,
|
|
1843
|
+
};
|
|
1844
|
+
switch (type) {
|
|
1845
|
+
case PaginationType.OFFSET:
|
|
1846
|
+
if (pageInfo.currentPage) {
|
|
1847
|
+
cursorData.pageNumber = pageInfo.currentPage + 1;
|
|
1848
|
+
}
|
|
1849
|
+
break;
|
|
1850
|
+
case PaginationType.TOKEN:
|
|
1851
|
+
if (pageInfo.continuationToken) {
|
|
1852
|
+
cursorData.continuationToken = pageInfo.continuationToken;
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
return undefined; // No continuation token, can't continue
|
|
1856
|
+
}
|
|
1857
|
+
break;
|
|
1858
|
+
}
|
|
1859
|
+
return {
|
|
1860
|
+
value: encodeBase64(JSON.stringify(cursorData))
|
|
1861
|
+
};
|
|
1929
1862
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1863
|
+
/**
|
|
1864
|
+
* Create a paginated response with navigation cursors
|
|
1865
|
+
*/
|
|
1866
|
+
static createPaginatedResponse({ pageInfo, type }, items) {
|
|
1867
|
+
const nextCursor = PaginationManager.createCursor({ pageInfo, type });
|
|
1868
|
+
// Create previous page cursor if applicable
|
|
1869
|
+
let previousCursor = undefined;
|
|
1870
|
+
if (pageInfo.currentPage && pageInfo.currentPage > 1) {
|
|
1871
|
+
const prevCursorData = {
|
|
1872
|
+
type,
|
|
1873
|
+
pageNumber: pageInfo.currentPage - 1,
|
|
1874
|
+
pageSize: pageInfo.pageSize,
|
|
1875
|
+
};
|
|
1876
|
+
previousCursor = {
|
|
1877
|
+
value: encodeBase64(JSON.stringify(prevCursorData))
|
|
1878
|
+
};
|
|
1936
1879
|
}
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1880
|
+
// Calculate total pages if we have totalCount and pageSize
|
|
1881
|
+
let totalPages = undefined;
|
|
1882
|
+
if (pageInfo.totalCount !== undefined && pageInfo.pageSize) {
|
|
1883
|
+
totalPages = Math.ceil(pageInfo.totalCount / pageInfo.pageSize);
|
|
1940
1884
|
}
|
|
1885
|
+
// Determine if this pagination type supports page jumping
|
|
1886
|
+
const supportsPageJump = type === PaginationType.OFFSET;
|
|
1887
|
+
// Create the result object with all fields, then filter out undefined values
|
|
1888
|
+
const result = filterUndefined({
|
|
1889
|
+
items,
|
|
1890
|
+
totalCount: pageInfo.totalCount,
|
|
1891
|
+
hasNextPage: pageInfo.hasMore,
|
|
1892
|
+
nextCursor: nextCursor,
|
|
1893
|
+
previousCursor: previousCursor,
|
|
1894
|
+
currentPage: pageInfo.currentPage,
|
|
1895
|
+
totalPages,
|
|
1896
|
+
supportsPageJump
|
|
1897
|
+
});
|
|
1898
|
+
return result;
|
|
1941
1899
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
'ai.cloud.role': CLOUD_ROLE_NAME,
|
|
1962
|
-
'ai.cloud.roleInstance': SDK_VERSION
|
|
1963
|
-
}
|
|
1964
|
-
};
|
|
1965
|
-
this.sendToApplicationInsights(payload);
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
/**
|
|
1903
|
+
* SDK Internals Registry - Internal registry for SDK instances
|
|
1904
|
+
*
|
|
1905
|
+
* This class is NOT exported in the public API.
|
|
1906
|
+
* It provides a secure way to share SDK internals between
|
|
1907
|
+
* the UiPath class and service classes without exposing them publicly.
|
|
1908
|
+
*
|
|
1909
|
+
* @internal
|
|
1910
|
+
*/
|
|
1911
|
+
// Global symbol key to ensure WeakMap is shared across module instances
|
|
1912
|
+
// This prevents issues when core and service modules are bundled separately
|
|
1913
|
+
const REGISTRY_KEY = Symbol.for('@uipath/sdk-internals-registry');
|
|
1914
|
+
// Get or create the global WeakMap store
|
|
1915
|
+
const getGlobalStore = () => {
|
|
1916
|
+
const globalObj = globalThis;
|
|
1917
|
+
if (!globalObj[REGISTRY_KEY]) {
|
|
1918
|
+
globalObj[REGISTRY_KEY] = new WeakMap();
|
|
1966
1919
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1920
|
+
return globalObj[REGISTRY_KEY];
|
|
1921
|
+
};
|
|
1922
|
+
/**
|
|
1923
|
+
* Internal registry for SDK private components.
|
|
1924
|
+
* Uses WeakMap to prevent memory leaks - entries are automatically
|
|
1925
|
+
* garbage collected when the SDK instance is no longer referenced.
|
|
1926
|
+
*
|
|
1927
|
+
* Uses a global singleton pattern to ensure the same WeakMap is shared
|
|
1928
|
+
* across separately bundled modules (core, entities, tasks, etc.).
|
|
1929
|
+
*
|
|
1930
|
+
* @internal - Not exported in public API
|
|
1931
|
+
*/
|
|
1932
|
+
class SDKInternalsRegistry {
|
|
1933
|
+
// Use global store to ensure sharing across module bundles
|
|
1934
|
+
static get store() {
|
|
1935
|
+
return getGlobalStore();
|
|
1970
1936
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1937
|
+
/**
|
|
1938
|
+
* Register SDK instance internals
|
|
1939
|
+
* Called by UiPath constructor
|
|
1940
|
+
*/
|
|
1941
|
+
static set(instance, internals) {
|
|
1942
|
+
this.store.set(instance, internals);
|
|
1977
1943
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
const response = await fetch(url, {
|
|
1987
|
-
method: 'POST',
|
|
1988
|
-
headers: {
|
|
1989
|
-
'Content-Type': 'application/json',
|
|
1990
|
-
},
|
|
1991
|
-
body: JSON.stringify(payload)
|
|
1992
|
-
});
|
|
1993
|
-
if (!response.ok) {
|
|
1994
|
-
console.debug(`Failed to send event telemetry: ${response.status} ${response.statusText}`);
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
catch (error) {
|
|
1998
|
-
console.debug('Error sending event telemetry to Application Insights:', error);
|
|
1944
|
+
/**
|
|
1945
|
+
* Retrieve SDK instance internals
|
|
1946
|
+
* Called by BaseService constructor
|
|
1947
|
+
*/
|
|
1948
|
+
static get(instance) {
|
|
1949
|
+
const internals = this.store.get(instance);
|
|
1950
|
+
if (!internals) {
|
|
1951
|
+
throw new Error('Invalid SDK instance. Make sure to pass a valid UiPath instance to the service constructor.');
|
|
1999
1952
|
}
|
|
2000
|
-
|
|
2001
|
-
extractIngestionEndpoint() {
|
|
2002
|
-
const match = this.connectionString.match(/IngestionEndpoint=([^;]+)/);
|
|
2003
|
-
return match ? match[1] : '';
|
|
1953
|
+
return internals;
|
|
2004
1954
|
}
|
|
2005
1955
|
}
|
|
1956
|
+
|
|
1957
|
+
var _BaseService_apiClient;
|
|
2006
1958
|
/**
|
|
2007
|
-
*
|
|
1959
|
+
* Base class for all UiPath SDK services.
|
|
1960
|
+
*
|
|
1961
|
+
* Provides common functionality for authentication, configuration, and API communication.
|
|
1962
|
+
* All service classes extend this base to inherit dependency injection and HTTP client access.
|
|
1963
|
+
*
|
|
1964
|
+
* This class implements the dependency injection pattern where services receive a configured
|
|
1965
|
+
* UiPath instance. The ApiClient is created internally and handles all HTTP operations
|
|
1966
|
+
* including authentication token management.
|
|
1967
|
+
*
|
|
1968
|
+
* @remarks
|
|
1969
|
+
* Service classes should extend this base and call `super(uiPath)` in their constructor.
|
|
1970
|
+
* Protected HTTP methods (get, post, put, patch, delete) are available to all subclasses.
|
|
1971
|
+
*
|
|
2008
1972
|
*/
|
|
2009
|
-
class
|
|
2010
|
-
|
|
2011
|
-
|
|
1973
|
+
class BaseService {
|
|
1974
|
+
/**
|
|
1975
|
+
* Creates a base service instance with dependency injection.
|
|
1976
|
+
*
|
|
1977
|
+
* Extracts configuration, execution context, and token manager from the UiPath instance
|
|
1978
|
+
* to initialize an authenticated API client. The ApiClient handles all HTTP operations
|
|
1979
|
+
* and token management internally.
|
|
1980
|
+
*
|
|
1981
|
+
* @param instance - UiPath SDK instance providing authentication and configuration.
|
|
1982
|
+
* Services receive this via dependency injection in the modular pattern.
|
|
1983
|
+
*
|
|
1984
|
+
* @example
|
|
1985
|
+
* ```typescript
|
|
1986
|
+
* // Services automatically call this via super()
|
|
1987
|
+
* export class EntityService extends BaseService {
|
|
1988
|
+
* constructor(instance: IUiPath) {
|
|
1989
|
+
* super(instance); // Initializes the internal ApiClient
|
|
1990
|
+
* }
|
|
1991
|
+
* }
|
|
1992
|
+
*
|
|
1993
|
+
* // Usage in modular pattern
|
|
1994
|
+
* import { UiPath } from '@uipath/uipath-typescript/core';
|
|
1995
|
+
* import { Entities } from '@uipath/uipath-typescript/entities';
|
|
1996
|
+
*
|
|
1997
|
+
* const sdk = new UiPath(config);
|
|
1998
|
+
* await sdk.initialize();
|
|
1999
|
+
* const entities = new Entities(sdk);
|
|
2000
|
+
* ```
|
|
2001
|
+
*/
|
|
2002
|
+
constructor(instance) {
|
|
2003
|
+
// Private field - not visible via Object.keys() or any reflection
|
|
2004
|
+
_BaseService_apiClient.set(this, void 0);
|
|
2005
|
+
const { config, context, tokenManager } = SDKInternalsRegistry.get(instance);
|
|
2006
|
+
__classPrivateFieldSet(this, _BaseService_apiClient, new ApiClient(config, context, tokenManager), "f");
|
|
2012
2007
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2008
|
+
/**
|
|
2009
|
+
* Gets a valid authentication token, refreshing if necessary.
|
|
2010
|
+
* Use this when you need to manually add Authorization headers (e.g., direct uploads).
|
|
2011
|
+
*
|
|
2012
|
+
* @returns Promise resolving to a valid access token string
|
|
2013
|
+
* @throws AuthenticationError if no token is available or refresh fails
|
|
2014
|
+
*/
|
|
2015
|
+
async getValidAuthToken() {
|
|
2016
|
+
return __classPrivateFieldGet(this, _BaseService_apiClient, "f").getValidToken();
|
|
2018
2017
|
}
|
|
2019
2018
|
/**
|
|
2020
|
-
*
|
|
2019
|
+
* Creates a service accessor for pagination helpers
|
|
2020
|
+
* This allows pagination helpers to access protected methods without making them public
|
|
2021
2021
|
*/
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2022
|
+
createPaginationServiceAccess() {
|
|
2023
|
+
return {
|
|
2024
|
+
get: (path, options) => this.get(path, options || {}),
|
|
2025
|
+
post: (path, body, options) => this.post(path, body, options || {}),
|
|
2026
|
+
requestWithPagination: (method, path, paginationOptions, options) => this.requestWithPagination(method, path, paginationOptions, options)
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
async request(method, path, options = {}) {
|
|
2030
|
+
switch (method.toUpperCase()) {
|
|
2031
|
+
case 'GET':
|
|
2032
|
+
return this.get(path, options);
|
|
2033
|
+
case 'POST':
|
|
2034
|
+
return this.post(path, options.body, options);
|
|
2035
|
+
case 'PUT':
|
|
2036
|
+
return this.put(path, options.body, options);
|
|
2037
|
+
case 'PATCH':
|
|
2038
|
+
return this.patch(path, options.body, options);
|
|
2039
|
+
case 'DELETE':
|
|
2040
|
+
return this.delete(path, options);
|
|
2041
|
+
default:
|
|
2042
|
+
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
2036
2043
|
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2044
|
+
}
|
|
2045
|
+
async requestWithSpec(spec) {
|
|
2046
|
+
if (!spec.method || !spec.url) {
|
|
2047
|
+
throw new Error('Request spec must include method and url');
|
|
2040
2048
|
}
|
|
2049
|
+
return this.request(spec.method, spec.url, spec);
|
|
2050
|
+
}
|
|
2051
|
+
async get(path, options = {}) {
|
|
2052
|
+
const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").get(path, options);
|
|
2053
|
+
return { data: response };
|
|
2041
2054
|
}
|
|
2042
|
-
|
|
2043
|
-
const
|
|
2044
|
-
return
|
|
2055
|
+
async post(path, data, options = {}) {
|
|
2056
|
+
const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").post(path, data, options);
|
|
2057
|
+
return { data: response };
|
|
2045
2058
|
}
|
|
2046
|
-
|
|
2047
|
-
const
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2059
|
+
async put(path, data, options = {}) {
|
|
2060
|
+
const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").put(path, data, options);
|
|
2061
|
+
return { data: response };
|
|
2062
|
+
}
|
|
2063
|
+
async patch(path, data, options = {}) {
|
|
2064
|
+
const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").patch(path, data, options);
|
|
2065
|
+
return { data: response };
|
|
2066
|
+
}
|
|
2067
|
+
async delete(path, options = {}) {
|
|
2068
|
+
const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").delete(path, options);
|
|
2069
|
+
return { data: response };
|
|
2053
2070
|
}
|
|
2054
2071
|
/**
|
|
2055
|
-
*
|
|
2072
|
+
* Execute a request with cursor-based pagination
|
|
2056
2073
|
*/
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
}
|
|
2074
|
+
async requestWithPagination(method, path, paginationOptions, options) {
|
|
2075
|
+
const paginationType = options.pagination.paginationType;
|
|
2076
|
+
// Validate and prepare pagination parameters
|
|
2077
|
+
const params = this.validateAndPreparePaginationParams(paginationType, paginationOptions);
|
|
2078
|
+
// Prepare request parameters based on pagination type
|
|
2079
|
+
const requestParams = this.preparePaginationRequestParams(paginationType, params, options.pagination);
|
|
2080
|
+
// For POST requests, merge pagination params into body; for GET, use query params
|
|
2081
|
+
if (method.toUpperCase() === 'POST') {
|
|
2082
|
+
const existingBody = (options.body && typeof options.body === 'object') ? options.body : {};
|
|
2083
|
+
options.body = {
|
|
2084
|
+
...existingBody,
|
|
2085
|
+
...options.params,
|
|
2086
|
+
...requestParams
|
|
2087
|
+
};
|
|
2071
2088
|
}
|
|
2072
|
-
|
|
2073
|
-
//
|
|
2074
|
-
|
|
2089
|
+
else {
|
|
2090
|
+
// Merge pagination parameters with existing parameters
|
|
2091
|
+
options.params = {
|
|
2092
|
+
...options.params,
|
|
2093
|
+
...requestParams
|
|
2094
|
+
};
|
|
2075
2095
|
}
|
|
2096
|
+
// Make the request
|
|
2097
|
+
const response = await this.request(method, path, options);
|
|
2098
|
+
// Extract data from the response and create page result
|
|
2099
|
+
return this.createPaginatedResponseFromResponse(response, params, paginationType, {
|
|
2100
|
+
itemsField: options.pagination.itemsField,
|
|
2101
|
+
totalCountField: options.pagination.totalCountField,
|
|
2102
|
+
continuationTokenField: options.pagination.continuationTokenField
|
|
2103
|
+
});
|
|
2076
2104
|
}
|
|
2077
2105
|
/**
|
|
2078
|
-
*
|
|
2106
|
+
* Validates and prepares pagination parameters from options
|
|
2079
2107
|
*/
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
[APP_NAME]: SDK_SERVICE_NAME,
|
|
2083
|
-
[VERSION]: SDK_VERSION,
|
|
2084
|
-
[SERVICE]: eventName,
|
|
2085
|
-
[CLOUD_URL]: this.createCloudUrl(),
|
|
2086
|
-
[CLOUD_ORGANIZATION_NAME]: this.telemetryContext?.orgName || UNKNOWN,
|
|
2087
|
-
[CLOUD_TENANT_NAME]: this.telemetryContext?.tenantName || UNKNOWN,
|
|
2088
|
-
[CLOUD_REDIRECT_URI]: this.telemetryContext?.redirectUri || UNKNOWN,
|
|
2089
|
-
[CLOUD_CLIENT_ID]: this.telemetryContext?.clientId || UNKNOWN,
|
|
2090
|
-
...extraAttributes,
|
|
2091
|
-
};
|
|
2092
|
-
return attributes;
|
|
2108
|
+
validateAndPreparePaginationParams(paginationType, paginationOptions) {
|
|
2109
|
+
return PaginationHelpers.validatePaginationOptions(paginationOptions, paginationType);
|
|
2093
2110
|
}
|
|
2094
2111
|
/**
|
|
2095
|
-
*
|
|
2112
|
+
* Prepares request parameters for pagination based on pagination type
|
|
2096
2113
|
*/
|
|
2097
|
-
|
|
2098
|
-
const
|
|
2099
|
-
|
|
2100
|
-
const
|
|
2101
|
-
|
|
2102
|
-
|
|
2114
|
+
preparePaginationRequestParams(paginationType, params, paginationConfig) {
|
|
2115
|
+
const requestParams = {};
|
|
2116
|
+
let limitedPageSize;
|
|
2117
|
+
const paginationParams = paginationConfig?.paginationParams;
|
|
2118
|
+
switch (paginationType) {
|
|
2119
|
+
case PaginationType.OFFSET:
|
|
2120
|
+
limitedPageSize = getLimitedPageSize(params.pageSize);
|
|
2121
|
+
const pageSizeParam = paginationParams?.pageSizeParam || ODATA_OFFSET_PARAMS.PAGE_SIZE_PARAM;
|
|
2122
|
+
const offsetParam = paginationParams?.offsetParam || ODATA_OFFSET_PARAMS.OFFSET_PARAM;
|
|
2123
|
+
const countParam = paginationParams?.countParam || ODATA_OFFSET_PARAMS.COUNT_PARAM;
|
|
2124
|
+
requestParams[pageSizeParam] = limitedPageSize;
|
|
2125
|
+
if (params.pageNumber && params.pageNumber > 1) {
|
|
2126
|
+
requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
|
|
2127
|
+
}
|
|
2128
|
+
// Include total count for ODATA APIs
|
|
2129
|
+
{
|
|
2130
|
+
requestParams[countParam] = true;
|
|
2131
|
+
}
|
|
2132
|
+
break;
|
|
2133
|
+
case PaginationType.TOKEN:
|
|
2134
|
+
const tokenPageSizeParam = paginationParams?.pageSizeParam || BUCKET_TOKEN_PARAMS.PAGE_SIZE_PARAM;
|
|
2135
|
+
const tokenParam = paginationParams?.tokenParam || BUCKET_TOKEN_PARAMS.TOKEN_PARAM;
|
|
2136
|
+
if (params.pageSize) {
|
|
2137
|
+
requestParams[tokenPageSizeParam] = getLimitedPageSize(params.pageSize);
|
|
2138
|
+
}
|
|
2139
|
+
if (params.continuationToken) {
|
|
2140
|
+
requestParams[tokenParam] = params.continuationToken;
|
|
2141
|
+
}
|
|
2142
|
+
break;
|
|
2103
2143
|
}
|
|
2104
|
-
return
|
|
2144
|
+
return requestParams;
|
|
2105
2145
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
:
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
*
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
* @track("Processes.Start", { attributes: { customProp: "value" } })
|
|
2158
|
-
* function myFunction() { ... }
|
|
2159
|
-
*/
|
|
2160
|
-
function track(nameOrOptions, options) {
|
|
2161
|
-
return function decorator(_target, propertyKey, descriptor) {
|
|
2162
|
-
const opts = typeof nameOrOptions === 'object' ? nameOrOptions : {};
|
|
2163
|
-
if (descriptor && typeof descriptor.value === 'function') {
|
|
2164
|
-
// Method decorator
|
|
2165
|
-
descriptor.value = createTrackedFunction(descriptor.value, nameOrOptions, propertyKey || 'unknown_method', opts);
|
|
2166
|
-
return descriptor;
|
|
2146
|
+
/**
|
|
2147
|
+
* Creates a paginated response from API response
|
|
2148
|
+
*/
|
|
2149
|
+
createPaginatedResponseFromResponse(response, params, paginationType, fields) {
|
|
2150
|
+
// Extract fields from response
|
|
2151
|
+
const itemsField = fields.itemsField ||
|
|
2152
|
+
(paginationType === PaginationType.TOKEN ? 'items' : 'value');
|
|
2153
|
+
const totalCountField = fields.totalCountField || 'totalRecordCount';
|
|
2154
|
+
const continuationTokenField = fields.continuationTokenField || 'continuationToken';
|
|
2155
|
+
// Extract items and metadata
|
|
2156
|
+
const items = response.data[itemsField] || [];
|
|
2157
|
+
const totalCount = response.data[totalCountField];
|
|
2158
|
+
const continuationToken = response.data[continuationTokenField];
|
|
2159
|
+
// Determine if there are more pages
|
|
2160
|
+
const hasMore = this.determineHasMorePages(paginationType, {
|
|
2161
|
+
totalCount,
|
|
2162
|
+
pageSize: params.pageSize,
|
|
2163
|
+
currentPage: params.pageNumber || 1,
|
|
2164
|
+
itemsCount: items.length,
|
|
2165
|
+
continuationToken
|
|
2166
|
+
});
|
|
2167
|
+
// Create and return the page result
|
|
2168
|
+
return PaginationManager.createPaginatedResponse({
|
|
2169
|
+
pageInfo: {
|
|
2170
|
+
hasMore,
|
|
2171
|
+
totalCount,
|
|
2172
|
+
currentPage: params.pageNumber,
|
|
2173
|
+
pageSize: params.pageSize,
|
|
2174
|
+
continuationToken
|
|
2175
|
+
},
|
|
2176
|
+
type: paginationType,
|
|
2177
|
+
}, items);
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* Determines if there are more pages based on pagination type and metadata
|
|
2181
|
+
*/
|
|
2182
|
+
determineHasMorePages(paginationType, info) {
|
|
2183
|
+
switch (paginationType) {
|
|
2184
|
+
case PaginationType.OFFSET:
|
|
2185
|
+
const effectivePageSize = info.pageSize ?? DEFAULT_PAGE_SIZE;
|
|
2186
|
+
// If totalCount is available, use it for precise calculation
|
|
2187
|
+
if (info.totalCount !== undefined) {
|
|
2188
|
+
return (info.currentPage * effectivePageSize) < info.totalCount;
|
|
2189
|
+
}
|
|
2190
|
+
// Fallback when totalCount is not available
|
|
2191
|
+
// NOTE: This code path should rarely be executed as the APIs typically return totalCount
|
|
2192
|
+
return info.itemsCount === effectivePageSize;
|
|
2193
|
+
case PaginationType.TOKEN:
|
|
2194
|
+
return !!info.continuationToken;
|
|
2195
|
+
default:
|
|
2196
|
+
return false;
|
|
2167
2197
|
}
|
|
2168
|
-
|
|
2169
|
-
return (originalFunction) => createTrackedFunction(originalFunction, nameOrOptions, originalFunction.name || 'unknown_function', opts);
|
|
2170
|
-
};
|
|
2198
|
+
}
|
|
2171
2199
|
}
|
|
2200
|
+
_BaseService_apiClient = new WeakMap();
|
|
2172
2201
|
|
|
2173
2202
|
/**
|
|
2174
2203
|
* Service for interacting with UiPath Tasks API
|
|
@@ -2364,29 +2393,38 @@ class TaskService extends BaseService {
|
|
|
2364
2393
|
}
|
|
2365
2394
|
/**
|
|
2366
2395
|
* Gets a task by ID
|
|
2367
|
-
* IMPORTANT: For form tasks, folderId must be provided.
|
|
2368
|
-
*
|
|
2369
2396
|
* @param id - The ID of the task to retrieve
|
|
2370
|
-
* @param options - Optional query parameters
|
|
2371
|
-
* @param folderId - Optional folder ID (REQUIRED
|
|
2372
|
-
* @returns Promise resolving to the task
|
|
2373
|
-
*
|
|
2397
|
+
* @param options - Optional query parameters including taskType for faster retrieval {@link TaskGetByIdOptions}
|
|
2398
|
+
* @param folderId - Optional folder ID (REQUIRED when options.taskType is provided)
|
|
2399
|
+
* @returns Promise resolving to the task
|
|
2400
|
+
* {@link TaskGetResponse}
|
|
2374
2401
|
* @example
|
|
2375
2402
|
* ```typescript
|
|
2376
|
-
*
|
|
2403
|
+
* // Get a task by ID
|
|
2404
|
+
* const task = await tasks.getById(<taskId>);
|
|
2377
2405
|
*
|
|
2378
|
-
*
|
|
2406
|
+
* // Get a form task by ID
|
|
2407
|
+
* const formTask = await tasks.getById(<taskId>, {}, <folderId>);
|
|
2379
2408
|
*
|
|
2380
|
-
* //
|
|
2381
|
-
*
|
|
2409
|
+
* // Access form task properties
|
|
2410
|
+
* console.log(formTask.formLayout);
|
|
2382
2411
|
*
|
|
2383
|
-
* //
|
|
2412
|
+
* // Get a document validation task by ID (faster with taskType provided in the options)
|
|
2413
|
+
* const dvTask = await tasks.getById(<taskId>, { taskType: TaskType.DocumentValidation }, <folderId>);
|
|
2384
2414
|
* ```
|
|
2385
2415
|
*/
|
|
2386
2416
|
async getById(id, options = {}, folderId) {
|
|
2417
|
+
const { taskType, ...restOptions } = options;
|
|
2418
|
+
// If taskType is provided, skip the generic GET_BY_ID call and go directly to the type-specific endpoint
|
|
2419
|
+
if (taskType && taskType in TASK_TYPE_ENDPOINTS) {
|
|
2420
|
+
if (!folderId) {
|
|
2421
|
+
throw new ValidationError({ message: 'folderId is required when taskType is provided' });
|
|
2422
|
+
}
|
|
2423
|
+
return this.getByTaskType(id, folderId, taskType, restOptions);
|
|
2424
|
+
}
|
|
2387
2425
|
const headers = createHeaders({ [FOLDER_ID]: folderId });
|
|
2388
2426
|
// Add default expand parameters
|
|
2389
|
-
const modifiedOptions = this.addDefaultExpand(
|
|
2427
|
+
const modifiedOptions = this.addDefaultExpand(restOptions);
|
|
2390
2428
|
// prefix all keys in options
|
|
2391
2429
|
const keysToPrefix = Object.keys(modifiedOptions);
|
|
2392
2430
|
const apiOptions = addPrefixToKeys(modifiedOptions, ODATA_PREFIX, keysToPrefix);
|
|
@@ -2396,10 +2434,10 @@ class TaskService extends BaseService {
|
|
|
2396
2434
|
});
|
|
2397
2435
|
// Transform response from PascalCase to camelCase and normalize time fields
|
|
2398
2436
|
const transformedTask = transformData(pascalToCamelCaseKeys(response.data), TaskMap);
|
|
2399
|
-
//
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
return this.
|
|
2437
|
+
// Get task type from response and fetch type-specific data
|
|
2438
|
+
const resolvedFolderId = folderId || transformedTask.folderId;
|
|
2439
|
+
if (transformedTask.type in TASK_TYPE_ENDPOINTS) {
|
|
2440
|
+
return this.getByTaskType(id, resolvedFolderId, transformedTask.type, restOptions);
|
|
2403
2441
|
}
|
|
2404
2442
|
return createTaskWithMethods(applyDataTransforms(transformedTask, { field: 'status', valueMap: TaskStatusMap }), this);
|
|
2405
2443
|
}
|
|
@@ -2588,24 +2626,33 @@ class TaskService extends BaseService {
|
|
|
2588
2626
|
};
|
|
2589
2627
|
}
|
|
2590
2628
|
/**
|
|
2591
|
-
*
|
|
2629
|
+
* Routes to the type-specific endpoint based on task type.
|
|
2630
|
+
*/
|
|
2631
|
+
getByTaskType(id, folderId, taskType, options = {}) {
|
|
2632
|
+
const endpoint = TASK_TYPE_ENDPOINTS[taskType];
|
|
2633
|
+
const extraParams = taskType === exports.TaskType.Form ? { expandOnFormLayout: true, ...options } : options;
|
|
2634
|
+
return this.getTaskByTypeEndpoint(id, folderId, endpoint, extraParams);
|
|
2635
|
+
}
|
|
2636
|
+
/**
|
|
2637
|
+
* Fetches a task from a type-specific endpoint.
|
|
2592
2638
|
*
|
|
2593
|
-
* @param id - The
|
|
2639
|
+
* @param id - The task ID
|
|
2594
2640
|
* @param folderId - Required folder ID
|
|
2595
|
-
* @param
|
|
2596
|
-
* @
|
|
2641
|
+
* @param endpoint - The type-specific endpoint to call
|
|
2642
|
+
* @param extraParams - Additional query parameters (e.g. form options)
|
|
2643
|
+
* @returns Promise resolving to the task
|
|
2597
2644
|
*/
|
|
2598
|
-
async
|
|
2645
|
+
async getTaskByTypeEndpoint(id, folderId, endpoint, extraParams = {}) {
|
|
2599
2646
|
const headers = createHeaders({ [FOLDER_ID]: folderId });
|
|
2600
|
-
const response = await this.get(
|
|
2647
|
+
const response = await this.get(endpoint, {
|
|
2601
2648
|
params: {
|
|
2602
2649
|
taskId: id,
|
|
2603
|
-
...
|
|
2650
|
+
...extraParams
|
|
2604
2651
|
},
|
|
2605
2652
|
headers
|
|
2606
2653
|
});
|
|
2607
|
-
const
|
|
2608
|
-
return createTaskWithMethods(applyDataTransforms(
|
|
2654
|
+
const transformedTask = transformData(response.data, TaskMap);
|
|
2655
|
+
return createTaskWithMethods(applyDataTransforms(transformedTask, { field: 'status', valueMap: TaskStatusMap }), this);
|
|
2609
2656
|
}
|
|
2610
2657
|
/**
|
|
2611
2658
|
* Adds default expand parameters to options
|