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