@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.
Files changed (40) hide show
  1. package/dist/assets/index.cjs +1 -1
  2. package/dist/assets/index.d.ts +2 -1
  3. package/dist/assets/index.mjs +1 -1
  4. package/dist/attachments/index.cjs +1944 -0
  5. package/dist/attachments/index.d.ts +399 -0
  6. package/dist/attachments/index.mjs +1941 -0
  7. package/dist/buckets/index.cjs +1 -1
  8. package/dist/buckets/index.d.ts +4 -2
  9. package/dist/buckets/index.mjs +1 -1
  10. package/dist/cases/index.cjs +95 -48
  11. package/dist/cases/index.d.ts +31 -2
  12. package/dist/cases/index.mjs +95 -48
  13. package/dist/conversational-agent/index.cjs +38 -7
  14. package/dist/conversational-agent/index.d.ts +72 -6
  15. package/dist/conversational-agent/index.mjs +38 -7
  16. package/dist/core/index.cjs +118 -17
  17. package/dist/core/index.d.ts +26 -2
  18. package/dist/core/index.mjs +118 -17
  19. package/dist/entities/index.cjs +48 -1
  20. package/dist/entities/index.d.ts +106 -19
  21. package/dist/entities/index.mjs +48 -1
  22. package/dist/index.cjs +585 -267
  23. package/dist/index.d.ts +595 -67
  24. package/dist/index.mjs +586 -268
  25. package/dist/index.umd.js +582 -264
  26. package/dist/jobs/index.cjs +2036 -0
  27. package/dist/jobs/index.d.ts +724 -0
  28. package/dist/jobs/index.mjs +2033 -0
  29. package/dist/maestro-processes/index.cjs +1 -1
  30. package/dist/maestro-processes/index.mjs +1 -1
  31. package/dist/processes/index.cjs +67 -1
  32. package/dist/processes/index.d.ts +80 -15
  33. package/dist/processes/index.mjs +68 -2
  34. package/dist/queues/index.cjs +1 -1
  35. package/dist/queues/index.d.ts +2 -1
  36. package/dist/queues/index.mjs +1 -1
  37. package/dist/tasks/index.cjs +1319 -1272
  38. package/dist/tasks/index.d.ts +331 -287
  39. package/dist/tasks/index.mjs +1319 -1272
  40. package/package.json +25 -3
@@ -0,0 +1,1944 @@
1
+ 'use strict';
2
+
3
+ var sdkLogs = require('@opentelemetry/sdk-logs');
4
+
5
+ /******************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
20
+
21
+
22
+ function __decorate(decorators, target, key, desc) {
23
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
26
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
27
+ }
28
+
29
+ function __classPrivateFieldGet(receiver, state, kind, f) {
30
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
31
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
32
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
33
+ }
34
+
35
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
36
+ if (kind === "m") throw new TypeError("Private method is not writable");
37
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
38
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
39
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
40
+ }
41
+
42
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
43
+ var e = new Error(message);
44
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
45
+ };
46
+
47
+ /**
48
+ * Base error class for all UiPath SDK errors
49
+ * Extends Error for standard error handling compatibility
50
+ */
51
+ class UiPathError extends Error {
52
+ constructor(type, params) {
53
+ super(params.message);
54
+ this.name = type;
55
+ this.type = type;
56
+ this.statusCode = params.statusCode;
57
+ this.requestId = params.requestId;
58
+ this.timestamp = new Date();
59
+ // Maintains proper stack trace for where our error was thrown
60
+ if (Error.captureStackTrace) {
61
+ Error.captureStackTrace(this, this.constructor);
62
+ }
63
+ }
64
+ /**
65
+ * Returns a clean JSON representation of the error
66
+ */
67
+ toJSON() {
68
+ return {
69
+ type: this.type,
70
+ message: this.message,
71
+ statusCode: this.statusCode,
72
+ requestId: this.requestId,
73
+ timestamp: this.timestamp
74
+ };
75
+ }
76
+ /**
77
+ * Returns detailed debug information including stack trace
78
+ */
79
+ getDebugInfo() {
80
+ return {
81
+ ...this.toJSON(),
82
+ stack: this.stack
83
+ };
84
+ }
85
+ }
86
+
87
+ /**
88
+ * HTTP status code constants for error handling
89
+ */
90
+ const HttpStatus = {
91
+ // Client errors (4xx)
92
+ BAD_REQUEST: 400,
93
+ UNAUTHORIZED: 401,
94
+ FORBIDDEN: 403,
95
+ NOT_FOUND: 404,
96
+ TOO_MANY_REQUESTS: 429,
97
+ // Server errors (5xx)
98
+ INTERNAL_SERVER_ERROR: 500,
99
+ BAD_GATEWAY: 502,
100
+ SERVICE_UNAVAILABLE: 503,
101
+ GATEWAY_TIMEOUT: 504
102
+ };
103
+ /**
104
+ * Error type constants for consistent error identification
105
+ */
106
+ const ErrorType = {
107
+ AUTHENTICATION: 'AuthenticationError',
108
+ AUTHORIZATION: 'AuthorizationError',
109
+ VALIDATION: 'ValidationError',
110
+ NOT_FOUND: 'NotFoundError',
111
+ RATE_LIMIT: 'RateLimitError',
112
+ SERVER: 'ServerError',
113
+ NETWORK: 'NetworkError'
114
+ };
115
+ /**
116
+ * HTTP header constants for error handling
117
+ */
118
+ const HttpHeaders = {
119
+ X_REQUEST_ID: 'x-request-id'
120
+ };
121
+ /**
122
+ * Standard error message constants
123
+ */
124
+ const ErrorMessages = {
125
+ // Authentication errors
126
+ AUTHENTICATION_FAILED: 'Authentication failed',
127
+ // Authorization errors
128
+ ACCESS_DENIED: 'Access denied',
129
+ // Validation errors
130
+ VALIDATION_FAILED: 'Validation failed',
131
+ // Not found errors
132
+ RESOURCE_NOT_FOUND: 'Resource not found',
133
+ // Rate limit errors
134
+ RATE_LIMIT_EXCEEDED: 'Rate limit exceeded',
135
+ // Server errors
136
+ INTERNAL_SERVER_ERROR: 'Internal Server error occurred',
137
+ // Network errors
138
+ NETWORK_ERROR: 'Network error occurred',
139
+ REQUEST_TIMEOUT: 'Request timed out',
140
+ REQUEST_ABORTED: 'Request was aborted',
141
+ };
142
+ /**
143
+ * Error name constants for network error identification
144
+ */
145
+ const ErrorNames = {
146
+ ABORT_ERROR: 'AbortError'};
147
+
148
+ /**
149
+ * Error thrown when authentication fails (401 errors)
150
+ * Common scenarios:
151
+ * - Invalid credentials
152
+ * - Expired token
153
+ * - Missing authentication
154
+ */
155
+ class AuthenticationError extends UiPathError {
156
+ constructor(params = {}) {
157
+ super(ErrorType.AUTHENTICATION, {
158
+ message: params.message || ErrorMessages.AUTHENTICATION_FAILED,
159
+ statusCode: params.statusCode ?? HttpStatus.UNAUTHORIZED,
160
+ requestId: params.requestId
161
+ });
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Error thrown when authorization fails (403 errors)
167
+ * Common scenarios:
168
+ * - Insufficient permissions
169
+ * - Access denied to resource
170
+ * - Invalid scope
171
+ */
172
+ class AuthorizationError extends UiPathError {
173
+ constructor(params = {}) {
174
+ super(ErrorType.AUTHORIZATION, {
175
+ message: params.message || ErrorMessages.ACCESS_DENIED,
176
+ statusCode: params.statusCode ?? HttpStatus.FORBIDDEN,
177
+ requestId: params.requestId
178
+ });
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Error thrown when validation fails (400 errors or client-side validation)
184
+ * Common scenarios:
185
+ * - Invalid input parameters
186
+ * - Missing required fields
187
+ * - Invalid data format
188
+ */
189
+ class ValidationError extends UiPathError {
190
+ constructor(params = {}) {
191
+ super(ErrorType.VALIDATION, {
192
+ message: params.message || ErrorMessages.VALIDATION_FAILED,
193
+ statusCode: params.statusCode ?? HttpStatus.BAD_REQUEST,
194
+ requestId: params.requestId
195
+ });
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Error thrown when a resource is not found (404 errors)
201
+ * Common scenarios:
202
+ * - Resource doesn't exist
203
+ * - Invalid ID provided
204
+ * - Resource deleted
205
+ */
206
+ class NotFoundError extends UiPathError {
207
+ constructor(params = {}) {
208
+ super(ErrorType.NOT_FOUND, {
209
+ message: params.message || ErrorMessages.RESOURCE_NOT_FOUND,
210
+ statusCode: params.statusCode ?? HttpStatus.NOT_FOUND,
211
+ requestId: params.requestId
212
+ });
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Error thrown when rate limit is exceeded (429 errors)
218
+ * Common scenarios:
219
+ * - Too many requests in a time window
220
+ * - API throttling
221
+ */
222
+ class RateLimitError extends UiPathError {
223
+ constructor(params = {}) {
224
+ super(ErrorType.RATE_LIMIT, {
225
+ message: params.message || ErrorMessages.RATE_LIMIT_EXCEEDED,
226
+ statusCode: params.statusCode ?? HttpStatus.TOO_MANY_REQUESTS,
227
+ requestId: params.requestId
228
+ });
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Error thrown when server encounters an error (5xx errors)
234
+ * Common scenarios:
235
+ * - Internal server error
236
+ * - Service unavailable
237
+ * - Gateway timeout
238
+ */
239
+ class ServerError extends UiPathError {
240
+ constructor(params = {}) {
241
+ super(ErrorType.SERVER, {
242
+ message: params.message || ErrorMessages.INTERNAL_SERVER_ERROR,
243
+ statusCode: params.statusCode ?? HttpStatus.INTERNAL_SERVER_ERROR,
244
+ requestId: params.requestId
245
+ });
246
+ }
247
+ /**
248
+ * Checks if this is a temporary error that might succeed on retry
249
+ */
250
+ get isRetryable() {
251
+ return this.statusCode === HttpStatus.BAD_GATEWAY ||
252
+ this.statusCode === HttpStatus.SERVICE_UNAVAILABLE ||
253
+ this.statusCode === HttpStatus.GATEWAY_TIMEOUT;
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Error thrown when network/connection issues occur
259
+ * Common scenarios:
260
+ * - Connection timeout
261
+ * - DNS resolution failure
262
+ * - Network unreachable
263
+ * - Request aborted
264
+ */
265
+ class NetworkError extends UiPathError {
266
+ constructor(params = {}) {
267
+ super(ErrorType.NETWORK, {
268
+ message: params.message || ErrorMessages.NETWORK_ERROR,
269
+ statusCode: params.statusCode, // Network errors typically don't have HTTP status codes
270
+ requestId: params.requestId
271
+ });
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Transforms data by mapping fields according to the provided field mapping
277
+ * @param data The source data to transform
278
+ * @param fieldMapping Object mapping source field names to target field names
279
+ * @returns Transformed data with mapped field names
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * // Single object transformation
284
+ * const data = { id: '123', userName: 'john' };
285
+ * const mapping = { id: 'userId', userName: 'name' };
286
+ * const result = transformData(data, mapping);
287
+ * // result = { userId: '123', name: 'john' }
288
+ *
289
+ * // Array transformation
290
+ * const dataArray = [
291
+ * { id: '123', userName: 'john' },
292
+ * { id: '456', userName: 'jane' }
293
+ * ];
294
+ * const result = transformData(dataArray, mapping);
295
+ * // result = [
296
+ * // { userId: '123', name: 'john' },
297
+ * // { userId: '456', name: 'jane' }
298
+ * // ]
299
+ * ```
300
+ */
301
+ function transformData(data, fieldMapping) {
302
+ // Handle array of objects
303
+ if (Array.isArray(data)) {
304
+ return data.map(item => transformData(item, fieldMapping));
305
+ }
306
+ // Handle single object
307
+ const result = { ...data };
308
+ for (const [sourceField, targetField] of Object.entries(fieldMapping)) {
309
+ if (sourceField in result) {
310
+ const value = result[sourceField];
311
+ delete result[sourceField];
312
+ result[targetField] = value;
313
+ }
314
+ }
315
+ return result;
316
+ }
317
+ /**
318
+ * Converts a string from PascalCase to camelCase
319
+ * @param str The PascalCase string to convert
320
+ * @returns The camelCase version of the string
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * pascalToCamelCase('HelloWorld'); // 'helloWorld'
325
+ * pascalToCamelCase('TaskAssignmentCriteria'); // 'taskAssignmentCriteria'
326
+ * ```
327
+ */
328
+ function pascalToCamelCase(str) {
329
+ if (!str)
330
+ return str;
331
+ return str.charAt(0).toLowerCase() + str.slice(1);
332
+ }
333
+ /**
334
+ * Generic function to transform object keys using a provided case conversion function
335
+ * @param data The object to transform
336
+ * @param convertCase The function to convert each key
337
+ * @returns A new object with transformed keys
338
+ */
339
+ function transformCaseKeys(data, convertCase) {
340
+ // Handle array of objects
341
+ if (Array.isArray(data)) {
342
+ return data.map(item => {
343
+ // If the array element is a primitive (string, number, etc.), return it as is
344
+ if (item === null || typeof item !== 'object' || typeof item === 'string') {
345
+ return item;
346
+ }
347
+ // Only recursively transform if it's actually an object
348
+ return transformCaseKeys(item, convertCase);
349
+ });
350
+ }
351
+ const result = {};
352
+ for (const [key, value] of Object.entries(data)) {
353
+ const transformedKey = convertCase(key);
354
+ // Recursively transform nested objects and arrays
355
+ if (value !== null && typeof value === 'object') {
356
+ result[transformedKey] = transformCaseKeys(value, convertCase);
357
+ }
358
+ else {
359
+ result[transformedKey] = value;
360
+ }
361
+ }
362
+ return result;
363
+ }
364
+ /**
365
+ * Transforms an object's keys from PascalCase to camelCase
366
+ * @param data The object with PascalCase keys
367
+ * @returns A new object with all keys converted to camelCase
368
+ *
369
+ * @example
370
+ * ```typescript
371
+ * // Simple object
372
+ * pascalToCamelCaseKeys({ Id: "123", TaskName: "Invoice" });
373
+ * // Result: { id: "123", taskName: "Invoice" }
374
+ *
375
+ * // Nested object
376
+ * pascalToCamelCaseKeys({
377
+ * TaskId: "456",
378
+ * TaskDetails: { AssignedUser: "John", Priority: "High" }
379
+ * });
380
+ * // Result: {
381
+ * // taskId: "456",
382
+ * // taskDetails: { assignedUser: "John", priority: "High" }
383
+ * // }
384
+ *
385
+ * // Array of objects
386
+ * pascalToCamelCaseKeys([
387
+ * { Id: "1", IsComplete: false },
388
+ * { Id: "2", IsComplete: true }
389
+ * ]);
390
+ * // Result: [
391
+ * // { id: "1", isComplete: false },
392
+ * // { id: "2", isComplete: true }
393
+ * // ]
394
+ * ```
395
+ */
396
+ function pascalToCamelCaseKeys(data) {
397
+ return transformCaseKeys(data, pascalToCamelCase);
398
+ }
399
+ /**
400
+ * Adds a prefix to specified keys in an object, returning a new object.
401
+ * Only the provided keys are prefixed; all others are left unchanged.
402
+ *
403
+ * @param obj The source object
404
+ * @param prefix The prefix to add (e.g., '$')
405
+ * @param keys The keys to prefix (e.g., ['expand', 'filter'])
406
+ * @returns A new object with specified keys prefixed
407
+ *
408
+ * @example
409
+ * addPrefixToKeys({ expand: 'a', foo: 1 }, '$', ['expand']) // { $expand: 'a', foo: 1 }
410
+ */
411
+ function addPrefixToKeys(obj, prefix, keys) {
412
+ const result = {};
413
+ for (const [key, value] of Object.entries(obj)) {
414
+ if (keys.includes(key)) {
415
+ result[`${prefix}${key}`] = value;
416
+ }
417
+ else {
418
+ result[key] = value;
419
+ }
420
+ }
421
+ return result;
422
+ }
423
+
424
+ /**
425
+ * Base path constants for different services
426
+ */
427
+ const ORCHESTRATOR_BASE = 'orchestrator_';
428
+
429
+ /**
430
+ * Orchestrator Service Endpoints
431
+ */
432
+ /**
433
+ * Orchestrator Attachment Service Endpoints
434
+ */
435
+ const ORCHESTRATOR_ATTACHMENT_ENDPOINTS = {
436
+ GET_BY_ID: (id) => `${ORCHESTRATOR_BASE}/odata/Attachments(${id})`,
437
+ };
438
+
439
+ /**
440
+ * Common constants used across the SDK
441
+ */
442
+ /**
443
+ * Prefix used for OData query parameters
444
+ */
445
+ const ODATA_PREFIX = '$';
446
+ /**
447
+ * HTTP methods
448
+ */
449
+ const HTTP_METHODS = {
450
+ GET: 'GET',
451
+ POST: 'POST'};
452
+ /**
453
+ * OData OFFSET pagination parameter names (ODATA-style)
454
+ */
455
+ const ODATA_OFFSET_PARAMS = {
456
+ /** OData page size parameter name */
457
+ PAGE_SIZE_PARAM: '$top',
458
+ /** OData offset parameter name */
459
+ OFFSET_PARAM: '$skip',
460
+ /** OData count parameter name */
461
+ COUNT_PARAM: '$count'
462
+ };
463
+ /**
464
+ * Bucket TOKEN pagination parameter names
465
+ */
466
+ const BUCKET_TOKEN_PARAMS = {
467
+ /** Bucket page size parameter name */
468
+ PAGE_SIZE_PARAM: 'takeHint',
469
+ /** Bucket token parameter name */
470
+ TOKEN_PARAM: 'continuationToken'
471
+ };
472
+
473
+ /**
474
+ * SDK Telemetry constants
475
+ */
476
+ // Connection string placeholder that will be replaced during build
477
+ 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";
478
+ // SDK Version placeholder
479
+ const SDK_VERSION = "1.2.2";
480
+ const VERSION = "Version";
481
+ const SERVICE = "Service";
482
+ const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
483
+ const CLOUD_TENANT_NAME = "CloudTenantName";
484
+ const CLOUD_URL = "CloudUrl";
485
+ const CLOUD_CLIENT_ID = "CloudClientId";
486
+ const CLOUD_REDIRECT_URI = "CloudRedirectUri";
487
+ const APP_NAME = "ApplicationName";
488
+ const CLOUD_ROLE_NAME = "uipath-ts-sdk";
489
+ // Service and logger names
490
+ const SDK_SERVICE_NAME = "UiPath.TypeScript.Sdk";
491
+ const SDK_LOGGER_NAME = "uipath-ts-sdk-telemetry";
492
+ // Event names
493
+ const SDK_RUN_EVENT = "Sdk.Run";
494
+ // Default value for unknown/empty attributes
495
+ const UNKNOWN = "";
496
+
497
+ /**
498
+ * Log exporter that sends ALL logs as Application Insights custom events
499
+ */
500
+ class ApplicationInsightsEventExporter {
501
+ constructor(connectionString) {
502
+ this.connectionString = connectionString;
503
+ }
504
+ export(logs, resultCallback) {
505
+ try {
506
+ logs.forEach(logRecord => {
507
+ this.sendAsCustomEvent(logRecord);
508
+ });
509
+ resultCallback({ code: 0 });
510
+ }
511
+ catch (error) {
512
+ console.debug('Failed to export logs to Application Insights:', error);
513
+ resultCallback({ code: 2, error });
514
+ }
515
+ }
516
+ shutdown() {
517
+ return Promise.resolve();
518
+ }
519
+ sendAsCustomEvent(logRecord) {
520
+ // Get event name from body or attributes
521
+ const eventName = logRecord.body || SDK_RUN_EVENT;
522
+ const payload = {
523
+ name: 'Microsoft.ApplicationInsights.Event',
524
+ time: new Date().toISOString(),
525
+ iKey: this.extractInstrumentationKey(),
526
+ data: {
527
+ baseType: 'EventData',
528
+ baseData: {
529
+ ver: 2,
530
+ name: eventName,
531
+ properties: this.convertAttributesToProperties(logRecord.attributes || {})
532
+ }
533
+ },
534
+ tags: {
535
+ 'ai.cloud.role': CLOUD_ROLE_NAME,
536
+ 'ai.cloud.roleInstance': SDK_VERSION
537
+ }
538
+ };
539
+ this.sendToApplicationInsights(payload);
540
+ }
541
+ extractInstrumentationKey() {
542
+ const match = this.connectionString.match(/InstrumentationKey=([^;]+)/);
543
+ return match ? match[1] : '';
544
+ }
545
+ convertAttributesToProperties(attributes) {
546
+ const properties = {};
547
+ Object.entries(attributes || {}).forEach(([key, value]) => {
548
+ properties[key] = String(value);
549
+ });
550
+ return properties;
551
+ }
552
+ async sendToApplicationInsights(payload) {
553
+ try {
554
+ const ingestionEndpoint = this.extractIngestionEndpoint();
555
+ if (!ingestionEndpoint) {
556
+ console.debug('No ingestion endpoint found in connection string');
557
+ return;
558
+ }
559
+ const url = `${ingestionEndpoint}/v2/track`;
560
+ const response = await fetch(url, {
561
+ method: 'POST',
562
+ headers: {
563
+ 'Content-Type': 'application/json',
564
+ },
565
+ body: JSON.stringify(payload)
566
+ });
567
+ if (!response.ok) {
568
+ console.debug(`Failed to send event telemetry: ${response.status} ${response.statusText}`);
569
+ }
570
+ }
571
+ catch (error) {
572
+ console.debug('Error sending event telemetry to Application Insights:', error);
573
+ }
574
+ }
575
+ extractIngestionEndpoint() {
576
+ const match = this.connectionString.match(/IngestionEndpoint=([^;]+)/);
577
+ return match ? match[1] : '';
578
+ }
579
+ }
580
+ /**
581
+ * Singleton telemetry client
582
+ */
583
+ class TelemetryClient {
584
+ constructor() {
585
+ this.isInitialized = false;
586
+ }
587
+ static getInstance() {
588
+ if (!TelemetryClient.instance) {
589
+ TelemetryClient.instance = new TelemetryClient();
590
+ }
591
+ return TelemetryClient.instance;
592
+ }
593
+ /**
594
+ * Initialize telemetry
595
+ */
596
+ initialize(config) {
597
+ if (this.isInitialized) {
598
+ return;
599
+ }
600
+ this.isInitialized = true;
601
+ if (config) {
602
+ this.telemetryContext = config;
603
+ }
604
+ try {
605
+ const connectionString = this.getConnectionString();
606
+ if (!connectionString) {
607
+ return;
608
+ }
609
+ this.setupTelemetryProvider(connectionString);
610
+ }
611
+ catch (error) {
612
+ // Silent failure - telemetry errors shouldn't break functionality
613
+ console.debug('Failed to initialize OpenTelemetry:', error);
614
+ }
615
+ }
616
+ getConnectionString() {
617
+ const connectionString = CONNECTION_STRING;
618
+ return connectionString;
619
+ }
620
+ setupTelemetryProvider(connectionString) {
621
+ const exporter = new ApplicationInsightsEventExporter(connectionString);
622
+ const processor = new sdkLogs.BatchLogRecordProcessor(exporter);
623
+ this.logProvider = new sdkLogs.LoggerProvider({
624
+ processors: [processor]
625
+ });
626
+ this.logger = this.logProvider.getLogger(SDK_LOGGER_NAME);
627
+ }
628
+ /**
629
+ * Track a telemetry event
630
+ */
631
+ track(eventName, name, extraAttributes = {}) {
632
+ try {
633
+ // Skip if logger not initialized
634
+ if (!this.logger) {
635
+ return;
636
+ }
637
+ const finalDisplayName = name || eventName;
638
+ const attributes = this.getEnrichedAttributes(extraAttributes, eventName);
639
+ // Emit as log
640
+ this.logger.emit({
641
+ body: finalDisplayName,
642
+ attributes: attributes,
643
+ timestamp: Date.now(),
644
+ });
645
+ }
646
+ catch (error) {
647
+ // Silent failure
648
+ console.debug('Failed to track telemetry event:', error);
649
+ }
650
+ }
651
+ /**
652
+ * Get enriched attributes for telemetry events
653
+ */
654
+ getEnrichedAttributes(extraAttributes, eventName) {
655
+ const attributes = {
656
+ [APP_NAME]: SDK_SERVICE_NAME,
657
+ [VERSION]: SDK_VERSION,
658
+ [SERVICE]: eventName,
659
+ [CLOUD_URL]: this.createCloudUrl(),
660
+ [CLOUD_ORGANIZATION_NAME]: this.telemetryContext?.orgName || UNKNOWN,
661
+ [CLOUD_TENANT_NAME]: this.telemetryContext?.tenantName || UNKNOWN,
662
+ [CLOUD_REDIRECT_URI]: this.telemetryContext?.redirectUri || UNKNOWN,
663
+ [CLOUD_CLIENT_ID]: this.telemetryContext?.clientId || UNKNOWN,
664
+ ...extraAttributes,
665
+ };
666
+ return attributes;
667
+ }
668
+ /**
669
+ * Create cloud URL from base URL, organization ID, and tenant ID
670
+ */
671
+ createCloudUrl() {
672
+ const baseUrl = this.telemetryContext?.baseUrl;
673
+ const orgId = this.telemetryContext?.orgName;
674
+ const tenantId = this.telemetryContext?.tenantName;
675
+ if (!baseUrl || !orgId || !tenantId) {
676
+ return UNKNOWN;
677
+ }
678
+ return `${baseUrl}/${orgId}/${tenantId}`;
679
+ }
680
+ }
681
+ // Export singleton instance
682
+ const telemetryClient = TelemetryClient.getInstance();
683
+
684
+ /**
685
+ * SDK Track decorator and function for telemetry
686
+ */
687
+ /**
688
+ * Common tracking logic shared between method and function decorators
689
+ */
690
+ function createTrackedFunction(originalFunction, nameOrOptions, fallbackName, opts) {
691
+ return function (...args) {
692
+ // Determine if we should track this call
693
+ let shouldTrack = true;
694
+ if (opts.condition !== undefined) {
695
+ if (typeof opts.condition === 'function') {
696
+ shouldTrack = opts.condition.apply(this, args);
697
+ }
698
+ else {
699
+ shouldTrack = opts.condition;
700
+ }
701
+ }
702
+ // Track the event if enabled
703
+ if (shouldTrack) {
704
+ // Use the full name provided in the decorator (e.g., "Queue.GetAll")
705
+ const serviceMethod = nameOrOptions
706
+ ;
707
+ // Use 'Sdk.Run' as the name and serviceMethod as the service
708
+ telemetryClient.track(serviceMethod, SDK_RUN_EVENT, opts.attributes);
709
+ }
710
+ // Execute the original function
711
+ return originalFunction.apply(this, args);
712
+ };
713
+ }
714
+ /**
715
+ * Track decorator that can be used to automatically track function calls
716
+ *
717
+ * Usage:
718
+ * @track("Service.Method")
719
+ * function myFunction() { ... }
720
+ *
721
+ * @track("Queue.GetAll")
722
+ * async getAll() { ... }
723
+ *
724
+ * @track("Tasks.Create")
725
+ * async create() { ... }
726
+ *
727
+ * @track("Assets.Update", { condition: false })
728
+ * function myFunction() { ... }
729
+ *
730
+ * @track("Processes.Start", { attributes: { customProp: "value" } })
731
+ * function myFunction() { ... }
732
+ */
733
+ function track(nameOrOptions, options) {
734
+ return function decorator(_target, propertyKey, descriptor) {
735
+ const opts = {};
736
+ if (descriptor && typeof descriptor.value === 'function') {
737
+ // Method decorator
738
+ descriptor.value = createTrackedFunction(descriptor.value, nameOrOptions, propertyKey || 'unknown_method', opts);
739
+ return descriptor;
740
+ }
741
+ // Function decorator
742
+ return (originalFunction) => createTrackedFunction(originalFunction, nameOrOptions, originalFunction.name || 'unknown_function', opts);
743
+ };
744
+ }
745
+
746
+ /**
747
+ * Maps fields for Attachment entities to ensure consistent naming
748
+ */
749
+ const AttachmentsMap = {
750
+ creationTime: 'createdTime',
751
+ lastModificationTime: 'lastModifiedTime'
752
+ };
753
+
754
+ /**
755
+ * Type guards for error response types
756
+ */
757
+ function isOrchestratorError(error) {
758
+ return typeof error === 'object' &&
759
+ error !== null &&
760
+ 'message' in error &&
761
+ 'errorCode' in error &&
762
+ typeof error.message === 'string' &&
763
+ typeof error.errorCode === 'number';
764
+ }
765
+ function isEntityError(error) {
766
+ return typeof error === 'object' &&
767
+ error !== null &&
768
+ 'error' in error &&
769
+ typeof error.error === 'string';
770
+ }
771
+ function isPimsError(error) {
772
+ return typeof error === 'object' &&
773
+ error !== null &&
774
+ 'type' in error &&
775
+ 'title' in error &&
776
+ 'status' in error &&
777
+ typeof error.type === 'string' &&
778
+ typeof error.title === 'string' &&
779
+ typeof error.status === 'number';
780
+ }
781
+
782
+ /**
783
+ * Parser for Orchestrator/Task error format
784
+ */
785
+ class OrchestratorErrorParser {
786
+ canParse(errorBody) {
787
+ return isOrchestratorError(errorBody);
788
+ }
789
+ parse(errorBody, response) {
790
+ const error = errorBody;
791
+ return {
792
+ message: error.message,
793
+ code: response?.status?.toString(),
794
+ details: {
795
+ errorCode: error.errorCode,
796
+ traceId: error.traceId,
797
+ originalResponse: error
798
+ },
799
+ requestId: error.traceId
800
+ };
801
+ }
802
+ }
803
+ /**
804
+ * Parser for Entity (Data Fabric) error format
805
+ */
806
+ class EntityErrorParser {
807
+ canParse(errorBody) {
808
+ return isEntityError(errorBody);
809
+ }
810
+ parse(errorBody, response) {
811
+ const error = errorBody;
812
+ return {
813
+ message: error.error,
814
+ code: response?.status?.toString(),
815
+ details: {
816
+ error: error.error,
817
+ traceId: error.traceId,
818
+ originalResponse: error
819
+ },
820
+ requestId: error.traceId
821
+ };
822
+ }
823
+ }
824
+ /**
825
+ * Parser for PIMS error format
826
+ */
827
+ class PimsErrorParser {
828
+ canParse(errorBody) {
829
+ return isPimsError(errorBody);
830
+ }
831
+ parse(errorBody, response) {
832
+ const error = errorBody;
833
+ let message = error.title;
834
+ // If there are validation errors, append them to the message for better visibility
835
+ if (error.errors && Object.keys(error.errors).length > 0) {
836
+ const errorMessages = Object.entries(error.errors)
837
+ .map(([field, messages]) => `${field}: ${messages.join(', ')}`)
838
+ .join('; ');
839
+ message += `. Validation errors: ${errorMessages}`;
840
+ }
841
+ return {
842
+ message,
843
+ code: response?.status?.toString(),
844
+ details: {
845
+ type: error.type,
846
+ title: error.title,
847
+ status: error.status,
848
+ errors: error.errors,
849
+ traceId: error.traceId,
850
+ originalResponse: error
851
+ },
852
+ requestId: error.traceId
853
+ };
854
+ }
855
+ }
856
+ /**
857
+ * Fallback parser for unrecognized formats
858
+ */
859
+ class GenericErrorParser {
860
+ canParse(_errorBody) {
861
+ return true; // Always can parse as last resort
862
+ }
863
+ parse(errorBody, response) {
864
+ // For unknown error formats, just pass through the raw error with fallback message
865
+ const message = response?.statusText || 'An error occurred';
866
+ return {
867
+ message,
868
+ code: response?.status?.toString(),
869
+ details: {
870
+ originalResponse: errorBody
871
+ },
872
+ };
873
+ }
874
+ }
875
+ /**
876
+ * Main error response parser using Chain of Responsibility pattern
877
+ *
878
+ * This parser standardizes error responses from different UiPath services into a
879
+ * consistent format, regardless of the original error structure.
880
+ *
881
+ * Supported formats:
882
+ * 1. Orchestrator/Task: { message, errorCode, traceId }
883
+ * 2. Entity (Data Fabric): { error, traceId }
884
+ * 3. PIMS/Maestro: { type, title, status, errors?, traceId? }
885
+ * 4. Generic: Fallback for any other format
886
+ *
887
+ * @example
888
+ * const parser = new ErrorResponseParser();
889
+ * const errorInfo = await parser.parse(response);
890
+ * // errorInfo will have consistent structure regardless of service
891
+ */
892
+ class ErrorResponseParser {
893
+ constructor() {
894
+ this.strategies = [
895
+ new OrchestratorErrorParser(),
896
+ new EntityErrorParser(),
897
+ new PimsErrorParser(),
898
+ new GenericErrorParser() // Must be last
899
+ ];
900
+ }
901
+ /**
902
+ * Parses error response body into standardized format
903
+ * @param response - The HTTP response object
904
+ * @returns Standardized error information
905
+ */
906
+ async parse(response) {
907
+ try {
908
+ const errorBody = await response.json();
909
+ // Find the first strategy that can parse this error format
910
+ const strategy = this.strategies.find(s => s.canParse(errorBody));
911
+ // GenericErrorParser always returns true, so this will never be null
912
+ return strategy.parse(errorBody, response);
913
+ }
914
+ catch {
915
+ // Handle non-JSON responses
916
+ const responseText = await response.text().catch(() => '');
917
+ return {
918
+ message: response.statusText,
919
+ code: response.status.toString(),
920
+ details: {
921
+ parseError: 'Failed to parse error response as JSON',
922
+ responseText
923
+ },
924
+ requestId: response.headers.get(HttpHeaders.X_REQUEST_ID) || undefined
925
+ };
926
+ }
927
+ }
928
+ }
929
+ // Export singleton instance
930
+ const errorResponseParser = new ErrorResponseParser();
931
+
932
+ /**
933
+ * Factory for creating typed errors based on HTTP status codes
934
+ * Follows the Factory pattern for clean error instantiation
935
+ */
936
+ class ErrorFactory {
937
+ /**
938
+ * Creates appropriate error instance based on HTTP status code
939
+ */
940
+ static createFromHttpStatus(statusCode, errorInfo) {
941
+ const { message, requestId } = errorInfo;
942
+ // Map status codes to error types
943
+ switch (statusCode) {
944
+ case HttpStatus.BAD_REQUEST:
945
+ return new ValidationError({ message, statusCode, requestId });
946
+ case HttpStatus.UNAUTHORIZED:
947
+ return new AuthenticationError({ message, statusCode, requestId });
948
+ case HttpStatus.FORBIDDEN:
949
+ return new AuthorizationError({ message, statusCode, requestId });
950
+ case HttpStatus.NOT_FOUND:
951
+ return new NotFoundError({ message, statusCode, requestId });
952
+ case HttpStatus.TOO_MANY_REQUESTS:
953
+ return new RateLimitError({ message, statusCode, requestId });
954
+ default:
955
+ // For 5xx errors or any other status code
956
+ if (statusCode >= HttpStatus.INTERNAL_SERVER_ERROR) {
957
+ return new ServerError({ message, statusCode, requestId });
958
+ }
959
+ // For unknown client errors, treat as validation error
960
+ return new ValidationError({
961
+ message: `${message} (HTTP ${statusCode})`,
962
+ statusCode,
963
+ requestId
964
+ });
965
+ }
966
+ }
967
+ /**
968
+ * Creates a NetworkError from a fetch/network error
969
+ */
970
+ static createNetworkError(error) {
971
+ let message = ErrorMessages.NETWORK_ERROR;
972
+ if (error instanceof Error) {
973
+ if (error.name === ErrorNames.ABORT_ERROR) {
974
+ message = ErrorMessages.REQUEST_ABORTED;
975
+ }
976
+ else if (error.message.includes('timeout')) {
977
+ message = ErrorMessages.REQUEST_TIMEOUT;
978
+ }
979
+ else {
980
+ message = error.message;
981
+ }
982
+ }
983
+ return new NetworkError({ message });
984
+ }
985
+ }
986
+
987
+ const FOLDER_ID = 'X-UIPATH-OrganizationUnitId';
988
+ /**
989
+ * Content type constants for HTTP requests/responses
990
+ */
991
+ const CONTENT_TYPES = {
992
+ JSON: 'application/json',
993
+ XML: 'application/xml',
994
+ OCTET_STREAM: 'application/octet-stream'
995
+ };
996
+ /**
997
+ * Response type constants for HTTP requests
998
+ */
999
+ const RESPONSE_TYPES = {
1000
+ JSON: 'json',
1001
+ TEXT: 'text',
1002
+ BLOB: 'blob',
1003
+ ARRAYBUFFER: 'arraybuffer'
1004
+ };
1005
+
1006
+ class ApiClient {
1007
+ constructor(config, executionContext, tokenManager, clientConfig = {}) {
1008
+ this.defaultHeaders = {};
1009
+ this.config = config;
1010
+ this.executionContext = executionContext;
1011
+ this.clientConfig = clientConfig;
1012
+ this.tokenManager = tokenManager;
1013
+ }
1014
+ setDefaultHeaders(headers) {
1015
+ this.defaultHeaders = { ...this.defaultHeaders, ...headers };
1016
+ }
1017
+ /**
1018
+ * Gets a valid authentication token, refreshing if necessary.
1019
+ * Used internally for API requests and exposed for services that need manual auth headers.
1020
+ *
1021
+ * @returns The valid token
1022
+ * @throws AuthenticationError if no token available or refresh fails
1023
+ */
1024
+ async getValidToken() {
1025
+ return this.tokenManager.getValidToken();
1026
+ }
1027
+ async getDefaultHeaders() {
1028
+ const token = await this.getValidToken();
1029
+ return {
1030
+ 'Authorization': `Bearer ${token}`,
1031
+ 'Content-Type': CONTENT_TYPES.JSON,
1032
+ ...this.defaultHeaders,
1033
+ ...this.clientConfig.headers
1034
+ };
1035
+ }
1036
+ async request(method, path, options = {}) {
1037
+ // Ensure path starts with a forward slash
1038
+ const normalizedPath = path.startsWith('/') ? path.substring(1) : path;
1039
+ // Construct URL with org and tenant names
1040
+ const url = new URL(`${this.config.orgName}/${this.config.tenantName}/${normalizedPath}`, this.config.baseUrl).toString();
1041
+ const isFormData = options.body instanceof FormData;
1042
+ const defaultHeaders = await this.getDefaultHeaders();
1043
+ if (isFormData) {
1044
+ delete defaultHeaders['Content-Type'];
1045
+ }
1046
+ const headers = {
1047
+ ...defaultHeaders,
1048
+ ...options.headers
1049
+ };
1050
+ // Convert params to URLSearchParams
1051
+ const searchParams = new URLSearchParams();
1052
+ if (options.params) {
1053
+ Object.entries(options.params).forEach(([key, value]) => {
1054
+ searchParams.append(key, value.toString());
1055
+ });
1056
+ }
1057
+ const fullUrl = searchParams.toString() ? `${url}?${searchParams.toString()}` : url;
1058
+ let body = undefined;
1059
+ if (options.body) {
1060
+ body = isFormData ? options.body : JSON.stringify(options.body);
1061
+ }
1062
+ try {
1063
+ const response = await fetch(fullUrl, {
1064
+ method,
1065
+ headers,
1066
+ body,
1067
+ signal: options.signal
1068
+ });
1069
+ if (!response.ok) {
1070
+ const errorInfo = await errorResponseParser.parse(response);
1071
+ throw ErrorFactory.createFromHttpStatus(response.status, errorInfo);
1072
+ }
1073
+ if (response.status === 204) {
1074
+ return undefined;
1075
+ }
1076
+ // Handle blob response type for binary data (e.g., file downloads)
1077
+ if (options.responseType === RESPONSE_TYPES.BLOB) {
1078
+ const blob = await response.blob();
1079
+ return blob;
1080
+ }
1081
+ // Check if we're expecting XML
1082
+ const acceptHeader = headers['Accept'] || headers['accept'];
1083
+ if (acceptHeader === CONTENT_TYPES.XML) {
1084
+ const text = await response.text();
1085
+ return text;
1086
+ }
1087
+ return response.json();
1088
+ }
1089
+ catch (error) {
1090
+ // If it's already one of our errors, re-throw it
1091
+ if (error.type && error.type.includes('Error')) {
1092
+ throw error;
1093
+ }
1094
+ // Otherwise, it's likely a network error
1095
+ throw ErrorFactory.createNetworkError(error);
1096
+ }
1097
+ }
1098
+ async get(path, options = {}) {
1099
+ return this.request('GET', path, options);
1100
+ }
1101
+ async post(path, data, options = {}) {
1102
+ return this.request('POST', path, { ...options, body: data });
1103
+ }
1104
+ async put(path, data, options = {}) {
1105
+ return this.request('PUT', path, { ...options, body: data });
1106
+ }
1107
+ async patch(path, data, options = {}) {
1108
+ return this.request('PATCH', path, { ...options, body: data });
1109
+ }
1110
+ async delete(path, options = {}) {
1111
+ return this.request('DELETE', path, options);
1112
+ }
1113
+ }
1114
+
1115
+ /**
1116
+ * Pagination types supported by the SDK
1117
+ */
1118
+ var PaginationType;
1119
+ (function (PaginationType) {
1120
+ PaginationType["OFFSET"] = "offset";
1121
+ PaginationType["TOKEN"] = "token";
1122
+ })(PaginationType || (PaginationType = {}));
1123
+
1124
+ /**
1125
+ * Collection of utility functions for working with objects
1126
+ */
1127
+ /**
1128
+ * Filters out undefined values from an object
1129
+ * @param obj The source object
1130
+ * @returns A new object without undefined values
1131
+ *
1132
+ * @example
1133
+ * ```typescript
1134
+ * // Object with undefined values
1135
+ * const options = {
1136
+ * name: 'test',
1137
+ * count: 5,
1138
+ * prefix: undefined,
1139
+ * suffix: null
1140
+ * };
1141
+ * const result = filterUndefined(options);
1142
+ * // result = { name: 'test', count: 5, suffix: null }
1143
+ * ```
1144
+ */
1145
+ function filterUndefined(obj) {
1146
+ const result = {};
1147
+ for (const [key, value] of Object.entries(obj)) {
1148
+ if (value !== undefined) {
1149
+ result[key] = value;
1150
+ }
1151
+ }
1152
+ return result;
1153
+ }
1154
+
1155
+ /**
1156
+ * Utility functions for platform detection
1157
+ */
1158
+ /**
1159
+ * Checks if code is running in a browser environment
1160
+ */
1161
+ const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
1162
+ isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
1163
+
1164
+ /**
1165
+ * Base64 encoding/decoding
1166
+ */
1167
+ /**
1168
+ * Encodes a string to base64
1169
+ * @param str - The string to encode
1170
+ * @returns Base64 encoded string
1171
+ */
1172
+ function encodeBase64(str) {
1173
+ // TextEncoder for UTF-8 encoding (works in both browser and Node.js)
1174
+ const encoder = new TextEncoder();
1175
+ const data = encoder.encode(str);
1176
+ // Convert Uint8Array to base64
1177
+ if (isBrowser) {
1178
+ // Browser environment
1179
+ // Convert Uint8Array to binary string then to base64
1180
+ const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
1181
+ return btoa(binaryString);
1182
+ }
1183
+ else {
1184
+ // Node.js environment
1185
+ return Buffer.from(data).toString('base64');
1186
+ }
1187
+ }
1188
+ /**
1189
+ * Decodes a base64 string
1190
+ * @param base64 - The base64 string to decode
1191
+ * @returns Decoded string
1192
+ */
1193
+ function decodeBase64(base64) {
1194
+ let bytes;
1195
+ if (isBrowser) {
1196
+ // Browser environment
1197
+ const binaryString = atob(base64);
1198
+ bytes = new Uint8Array(binaryString.length);
1199
+ for (let i = 0; i < binaryString.length; i++) {
1200
+ bytes[i] = binaryString.charCodeAt(i);
1201
+ }
1202
+ }
1203
+ else {
1204
+ // Node.js environment
1205
+ bytes = new Uint8Array(Buffer.from(base64, 'base64'));
1206
+ }
1207
+ // TextDecoder for UTF-8 decoding (works in both browser and Node.js)
1208
+ const decoder = new TextDecoder();
1209
+ return decoder.decode(bytes);
1210
+ }
1211
+
1212
+ /**
1213
+ * PaginationManager handles the conversion between uniform cursor-based pagination
1214
+ * and the specific pagination type for each service
1215
+ */
1216
+ class PaginationManager {
1217
+ /**
1218
+ * Create a pagination cursor for subsequent page requests
1219
+ */
1220
+ static createCursor({ pageInfo, type }) {
1221
+ if (!pageInfo.hasMore) {
1222
+ return undefined;
1223
+ }
1224
+ const cursorData = {
1225
+ type,
1226
+ pageSize: pageInfo.pageSize,
1227
+ };
1228
+ switch (type) {
1229
+ case PaginationType.OFFSET:
1230
+ if (pageInfo.currentPage) {
1231
+ cursorData.pageNumber = pageInfo.currentPage + 1;
1232
+ }
1233
+ break;
1234
+ case PaginationType.TOKEN:
1235
+ if (pageInfo.continuationToken) {
1236
+ cursorData.continuationToken = pageInfo.continuationToken;
1237
+ }
1238
+ else {
1239
+ return undefined; // No continuation token, can't continue
1240
+ }
1241
+ break;
1242
+ }
1243
+ return {
1244
+ value: encodeBase64(JSON.stringify(cursorData))
1245
+ };
1246
+ }
1247
+ /**
1248
+ * Create a paginated response with navigation cursors
1249
+ */
1250
+ static createPaginatedResponse({ pageInfo, type }, items) {
1251
+ const nextCursor = PaginationManager.createCursor({ pageInfo, type });
1252
+ // Create previous page cursor if applicable
1253
+ let previousCursor = undefined;
1254
+ if (pageInfo.currentPage && pageInfo.currentPage > 1) {
1255
+ const prevCursorData = {
1256
+ type,
1257
+ pageNumber: pageInfo.currentPage - 1,
1258
+ pageSize: pageInfo.pageSize,
1259
+ };
1260
+ previousCursor = {
1261
+ value: encodeBase64(JSON.stringify(prevCursorData))
1262
+ };
1263
+ }
1264
+ // Calculate total pages if we have totalCount and pageSize
1265
+ let totalPages = undefined;
1266
+ if (pageInfo.totalCount !== undefined && pageInfo.pageSize) {
1267
+ totalPages = Math.ceil(pageInfo.totalCount / pageInfo.pageSize);
1268
+ }
1269
+ // Determine if this pagination type supports page jumping
1270
+ const supportsPageJump = type === PaginationType.OFFSET;
1271
+ // Create the result object with all fields, then filter out undefined values
1272
+ const result = filterUndefined({
1273
+ items,
1274
+ totalCount: pageInfo.totalCount,
1275
+ hasNextPage: pageInfo.hasMore,
1276
+ nextCursor: nextCursor,
1277
+ previousCursor: previousCursor,
1278
+ currentPage: pageInfo.currentPage,
1279
+ totalPages,
1280
+ supportsPageJump
1281
+ });
1282
+ return result;
1283
+ }
1284
+ }
1285
+
1286
+ /**
1287
+ * Creates headers object from key-value pairs
1288
+ * @param headersObj - Object containing header key-value pairs
1289
+ * @returns Headers object with all values converted to strings
1290
+ *
1291
+ * @example
1292
+ * ```typescript
1293
+ * // Single header
1294
+ * const headers = createHeaders({ 'X-UIPATH-FolderKey': '1234567890' });
1295
+ *
1296
+ * // Multiple headers
1297
+ * const headers = createHeaders({
1298
+ * 'X-UIPATH-FolderKey': '1234567890',
1299
+ * 'X-UIPATH-OrganizationUnitId': 123,
1300
+ * 'Accept': 'application/json'
1301
+ * });
1302
+ *
1303
+ * // Using constants
1304
+ * import { FOLDER_KEY, FOLDER_ID } from '../constants/headers';
1305
+ * const headers = createHeaders({
1306
+ * [FOLDER_KEY]: 'abc-123',
1307
+ * [FOLDER_ID]: 456
1308
+ * });
1309
+ *
1310
+ * // Empty headers
1311
+ * const headers = createHeaders();
1312
+ * ```
1313
+ */
1314
+ function createHeaders(headersObj) {
1315
+ const headers = {};
1316
+ for (const [key, value] of Object.entries(headersObj)) {
1317
+ if (value !== undefined && value !== null) {
1318
+ headers[key] = value.toString();
1319
+ }
1320
+ }
1321
+ return headers;
1322
+ }
1323
+
1324
+ /**
1325
+ * Constants used throughout the pagination system
1326
+ */
1327
+ /** Maximum number of items that can be requested in a single page */
1328
+ const MAX_PAGE_SIZE = 1000;
1329
+ /** Default page size when jumpToPage is used without specifying pageSize */
1330
+ const DEFAULT_PAGE_SIZE = 50;
1331
+ /** Default field name for items in a paginated response */
1332
+ const DEFAULT_ITEMS_FIELD = 'value';
1333
+ /** Default field name for total count in a paginated response */
1334
+ const DEFAULT_TOTAL_COUNT_FIELD = '@odata.count';
1335
+ /**
1336
+ * Limits the page size to the maximum allowed value
1337
+ * @param pageSize - Requested page size
1338
+ * @returns Limited page size value
1339
+ */
1340
+ function getLimitedPageSize(pageSize) {
1341
+ if (pageSize === undefined || pageSize === null) {
1342
+ return DEFAULT_PAGE_SIZE;
1343
+ }
1344
+ return Math.max(1, Math.min(pageSize, MAX_PAGE_SIZE));
1345
+ }
1346
+
1347
+ /**
1348
+ * Helper functions for pagination that can be used across services
1349
+ */
1350
+ class PaginationHelpers {
1351
+ /**
1352
+ * Checks if any pagination parameters are provided
1353
+ *
1354
+ * @param options - The options object to check
1355
+ * @returns True if any pagination parameter is defined, false otherwise
1356
+ */
1357
+ static hasPaginationParameters(options = {}) {
1358
+ const { cursor, pageSize, jumpToPage } = options;
1359
+ return cursor !== undefined || pageSize !== undefined || jumpToPage !== undefined;
1360
+ }
1361
+ /**
1362
+ * Parse a pagination cursor string into cursor data
1363
+ */
1364
+ static parseCursor(cursorString) {
1365
+ try {
1366
+ const cursorData = JSON.parse(decodeBase64(cursorString));
1367
+ return cursorData;
1368
+ }
1369
+ catch {
1370
+ throw new Error('Invalid pagination cursor');
1371
+ }
1372
+ }
1373
+ /**
1374
+ * Validates cursor format and structure
1375
+ *
1376
+ * @param paginationOptions - The pagination options containing the cursor
1377
+ * @param paginationType - Optional pagination type to validate against
1378
+ */
1379
+ static validateCursor(paginationOptions, paginationType) {
1380
+ if (paginationOptions.cursor !== undefined) {
1381
+ if (!paginationOptions.cursor || typeof paginationOptions.cursor.value !== 'string' || !paginationOptions.cursor.value) {
1382
+ throw new Error('cursor must contain a valid cursor string');
1383
+ }
1384
+ try {
1385
+ // Try to parse the cursor to validate it
1386
+ const cursorData = PaginationHelpers.parseCursor(paginationOptions.cursor.value);
1387
+ // If type is provided, validate cursor contains expected type information
1388
+ if (paginationType) {
1389
+ if (!cursorData.type) {
1390
+ throw new Error('Invalid cursor: missing pagination type');
1391
+ }
1392
+ // Check pagination type compatibility
1393
+ if (cursorData.type !== paginationType) {
1394
+ throw new Error(`Pagination type mismatch: cursor is for ${cursorData.type} but service uses ${paginationType}`);
1395
+ }
1396
+ }
1397
+ }
1398
+ catch (error) {
1399
+ if (error instanceof Error) {
1400
+ // If it's already our error with specific message, pass it through
1401
+ if (error.message.startsWith('Invalid cursor') ||
1402
+ error.message.startsWith('Pagination type mismatch')) {
1403
+ throw error;
1404
+ }
1405
+ }
1406
+ throw new Error('Invalid pagination cursor format');
1407
+ }
1408
+ }
1409
+ }
1410
+ /**
1411
+ * Comprehensive validation for pagination options
1412
+ *
1413
+ * @param options - The pagination options to validate
1414
+ * @param paginationType - The pagination type these options will be used with
1415
+ * @returns Processed pagination parameters ready for use
1416
+ */
1417
+ static validatePaginationOptions(options, paginationType) {
1418
+ // Validate pageSize
1419
+ if (options.pageSize !== undefined && options.pageSize <= 0) {
1420
+ throw new Error('pageSize must be a positive number');
1421
+ }
1422
+ // Validate jumpToPage
1423
+ if (options.jumpToPage !== undefined && options.jumpToPage <= 0) {
1424
+ throw new Error('jumpToPage must be a positive number');
1425
+ }
1426
+ // Validate cursor
1427
+ PaginationHelpers.validateCursor(options, paginationType);
1428
+ // Validate service compatibility
1429
+ if (options.jumpToPage !== undefined && paginationType === PaginationType.TOKEN) {
1430
+ throw new Error('jumpToPage is not supported for token-based pagination. Use cursor-based navigation instead.');
1431
+ }
1432
+ // Get processed parameters
1433
+ return PaginationHelpers.getRequestParameters(options, paginationType);
1434
+ }
1435
+ /**
1436
+ * Convert a unified pagination options to service-specific parameters
1437
+ */
1438
+ static getRequestParameters(options, paginationType) {
1439
+ // Handle jumpToPage
1440
+ if (options.jumpToPage !== undefined) {
1441
+ const jumpToPageOptions = {
1442
+ pageSize: options.pageSize,
1443
+ pageNumber: options.jumpToPage
1444
+ };
1445
+ return filterUndefined(jumpToPageOptions);
1446
+ }
1447
+ // If no cursor is provided, it's a first page request
1448
+ if (!options.cursor) {
1449
+ const firstPageOptions = {
1450
+ pageSize: options.pageSize,
1451
+ // Only set pageNumber for OFFSET pagination
1452
+ pageNumber: paginationType === PaginationType.OFFSET ? 1 : undefined
1453
+ };
1454
+ return filterUndefined(firstPageOptions);
1455
+ }
1456
+ // Parse the cursor
1457
+ try {
1458
+ const cursorData = PaginationHelpers.parseCursor(options.cursor.value);
1459
+ const cursorBasedOptions = {
1460
+ pageSize: cursorData.pageSize || options.pageSize,
1461
+ pageNumber: cursorData.pageNumber,
1462
+ continuationToken: cursorData.continuationToken,
1463
+ type: cursorData.type,
1464
+ };
1465
+ return filterUndefined(cursorBasedOptions);
1466
+ }
1467
+ catch {
1468
+ throw new Error('Invalid pagination cursor');
1469
+ }
1470
+ }
1471
+ /**
1472
+ * Helper method for paginated resource retrieval
1473
+ *
1474
+ * @param params - Parameters for pagination
1475
+ * @returns Promise resolving to a paginated result
1476
+ */
1477
+ static async getAllPaginated(params) {
1478
+ const { serviceAccess, getEndpoint, folderId, paginationParams, additionalParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
1479
+ const endpoint = getEndpoint(folderId);
1480
+ const headers = folderId ? createHeaders({ [FOLDER_ID]: folderId }) : {};
1481
+ const paginatedResponse = await serviceAccess.requestWithPagination(method, endpoint, paginationParams, {
1482
+ headers,
1483
+ params: additionalParams,
1484
+ pagination: {
1485
+ paginationType: options.paginationType || PaginationType.OFFSET,
1486
+ itemsField: options.itemsField || DEFAULT_ITEMS_FIELD,
1487
+ totalCountField: options.totalCountField || DEFAULT_TOTAL_COUNT_FIELD,
1488
+ continuationTokenField: options.continuationTokenField,
1489
+ paginationParams: options.paginationParams
1490
+ }
1491
+ });
1492
+ // Parse items - automatically handle JSON string responses
1493
+ const rawItems = paginatedResponse.items;
1494
+ const parsedItems = typeof rawItems === 'string' ? JSON.parse(rawItems) : (rawItems || []);
1495
+ const transformedItems = transformFn ? parsedItems.map(transformFn) : parsedItems;
1496
+ return {
1497
+ ...paginatedResponse,
1498
+ items: transformedItems
1499
+ };
1500
+ }
1501
+ /**
1502
+ * Helper method for non-paginated resource retrieval
1503
+ *
1504
+ * @param params - Parameters for non-paginated resource retrieval
1505
+ * @returns Promise resolving to an object with data and totalCount
1506
+ */
1507
+ static async getAllNonPaginated(params) {
1508
+ const { serviceAccess, getAllEndpoint, getByFolderEndpoint, folderId, additionalParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
1509
+ // Set default field names
1510
+ const itemsField = options.itemsField || DEFAULT_ITEMS_FIELD;
1511
+ const totalCountField = options.totalCountField || DEFAULT_TOTAL_COUNT_FIELD;
1512
+ // Determine endpoint and headers based on folderId
1513
+ const endpoint = folderId ? getByFolderEndpoint : getAllEndpoint;
1514
+ const headers = folderId ? createHeaders({ [FOLDER_ID]: folderId }) : {};
1515
+ // Make the API call based on method
1516
+ let response;
1517
+ if (method === HTTP_METHODS.POST) {
1518
+ response = await serviceAccess.post(endpoint, additionalParams, { headers });
1519
+ }
1520
+ else {
1521
+ response = await serviceAccess.get(endpoint, {
1522
+ params: additionalParams,
1523
+ headers
1524
+ });
1525
+ }
1526
+ // Extract and transform items from response
1527
+ const rawItems = response.data?.[itemsField];
1528
+ const totalCount = response.data?.[totalCountField];
1529
+ // Parse items - automatically handle JSON string responses
1530
+ const parsedItems = typeof rawItems === 'string' ? JSON.parse(rawItems) : (rawItems || []);
1531
+ const items = transformFn ? parsedItems.map(transformFn) : parsedItems;
1532
+ return {
1533
+ items,
1534
+ totalCount
1535
+ };
1536
+ }
1537
+ /**
1538
+ * Centralized getAll implementation that handles both paginated and non-paginated requests
1539
+ *
1540
+ * @param config - Configuration for the getAll operation
1541
+ * @param options - Request options including pagination parameters
1542
+ * @returns Promise resolving to either paginated or non-paginated response based on options
1543
+ */
1544
+ static async getAll(config, options) {
1545
+ const optionsWithDefaults = options || {};
1546
+ const { folderId, pageSize, cursor, jumpToPage, ...restOptions } = optionsWithDefaults;
1547
+ // Determine if pagination is requested
1548
+ const isPaginationRequested = PaginationHelpers.hasPaginationParameters(options || {});
1549
+ // Process parameters (custom processing if provided, otherwise default)
1550
+ let processedOptions = restOptions;
1551
+ if (config.processParametersFn) {
1552
+ processedOptions = config.processParametersFn(restOptions, folderId);
1553
+ }
1554
+ // Apply ODATA prefix to keys (excluding specified keys)
1555
+ const excludeKeys = config.excludeFromPrefix || [];
1556
+ const keysToPrefix = Object.keys(processedOptions).filter(k => !excludeKeys.includes(k));
1557
+ const prefixedOptions = addPrefixToKeys(processedOptions, ODATA_PREFIX, keysToPrefix);
1558
+ // Default pagination options
1559
+ const paginationOptions = {
1560
+ paginationType: PaginationType.OFFSET,
1561
+ itemsField: DEFAULT_ITEMS_FIELD,
1562
+ totalCountField: DEFAULT_TOTAL_COUNT_FIELD,
1563
+ ...config.pagination
1564
+ };
1565
+ // Paginated flow
1566
+ if (isPaginationRequested) {
1567
+ return PaginationHelpers.getAllPaginated({
1568
+ serviceAccess: config.serviceAccess,
1569
+ getEndpoint: config.getEndpoint,
1570
+ folderId,
1571
+ paginationParams: cursor ? { cursor, pageSize } : jumpToPage ? { jumpToPage, pageSize } : { pageSize },
1572
+ additionalParams: prefixedOptions,
1573
+ transformFn: config.transformFn,
1574
+ method: config.method,
1575
+ options: {
1576
+ ...paginationOptions,
1577
+ paginationParams: config.pagination?.paginationParams
1578
+ }
1579
+ }); // Type assertion needed due to conditional return
1580
+ }
1581
+ // Non-paginated flow
1582
+ const byFolderEndpoint = config.getByFolderEndpoint || config.getEndpoint(folderId);
1583
+ return PaginationHelpers.getAllNonPaginated({
1584
+ serviceAccess: config.serviceAccess,
1585
+ getAllEndpoint: config.getEndpoint(),
1586
+ getByFolderEndpoint: byFolderEndpoint,
1587
+ folderId,
1588
+ additionalParams: prefixedOptions,
1589
+ transformFn: config.transformFn,
1590
+ method: config.method,
1591
+ options: {
1592
+ itemsField: paginationOptions.itemsField,
1593
+ totalCountField: paginationOptions.totalCountField
1594
+ }
1595
+ });
1596
+ }
1597
+ }
1598
+
1599
+ /**
1600
+ * SDK Internals Registry - Internal registry for SDK instances
1601
+ *
1602
+ * This class is NOT exported in the public API.
1603
+ * It provides a secure way to share SDK internals between
1604
+ * the UiPath class and service classes without exposing them publicly.
1605
+ *
1606
+ * @internal
1607
+ */
1608
+ // Global symbol key to ensure WeakMap is shared across module instances
1609
+ // This prevents issues when core and service modules are bundled separately
1610
+ const REGISTRY_KEY = Symbol.for('@uipath/sdk-internals-registry');
1611
+ // Get or create the global WeakMap store
1612
+ const getGlobalStore = () => {
1613
+ const globalObj = globalThis;
1614
+ if (!globalObj[REGISTRY_KEY]) {
1615
+ globalObj[REGISTRY_KEY] = new WeakMap();
1616
+ }
1617
+ return globalObj[REGISTRY_KEY];
1618
+ };
1619
+ /**
1620
+ * Internal registry for SDK private components.
1621
+ * Uses WeakMap to prevent memory leaks - entries are automatically
1622
+ * garbage collected when the SDK instance is no longer referenced.
1623
+ *
1624
+ * Uses a global singleton pattern to ensure the same WeakMap is shared
1625
+ * across separately bundled modules (core, entities, tasks, etc.).
1626
+ *
1627
+ * @internal - Not exported in public API
1628
+ */
1629
+ class SDKInternalsRegistry {
1630
+ // Use global store to ensure sharing across module bundles
1631
+ static get store() {
1632
+ return getGlobalStore();
1633
+ }
1634
+ /**
1635
+ * Register SDK instance internals
1636
+ * Called by UiPath constructor
1637
+ */
1638
+ static set(instance, internals) {
1639
+ this.store.set(instance, internals);
1640
+ }
1641
+ /**
1642
+ * Retrieve SDK instance internals
1643
+ * Called by BaseService constructor
1644
+ */
1645
+ static get(instance) {
1646
+ const internals = this.store.get(instance);
1647
+ if (!internals) {
1648
+ throw new Error('Invalid SDK instance. Make sure to pass a valid UiPath instance to the service constructor.');
1649
+ }
1650
+ return internals;
1651
+ }
1652
+ }
1653
+
1654
+ var _BaseService_apiClient;
1655
+ /**
1656
+ * Base class for all UiPath SDK services.
1657
+ *
1658
+ * Provides common functionality for authentication, configuration, and API communication.
1659
+ * All service classes extend this base to inherit dependency injection and HTTP client access.
1660
+ *
1661
+ * This class implements the dependency injection pattern where services receive a configured
1662
+ * UiPath instance. The ApiClient is created internally and handles all HTTP operations
1663
+ * including authentication token management.
1664
+ *
1665
+ * @remarks
1666
+ * Service classes should extend this base and call `super(uiPath)` in their constructor.
1667
+ * Protected HTTP methods (get, post, put, patch, delete) are available to all subclasses.
1668
+ *
1669
+ */
1670
+ class BaseService {
1671
+ /**
1672
+ * Creates a base service instance with dependency injection.
1673
+ *
1674
+ * Extracts configuration, execution context, and token manager from the UiPath instance
1675
+ * to initialize an authenticated API client. The ApiClient handles all HTTP operations
1676
+ * and token management internally.
1677
+ *
1678
+ * @param instance - UiPath SDK instance providing authentication and configuration.
1679
+ * Services receive this via dependency injection in the modular pattern.
1680
+ *
1681
+ * @example
1682
+ * ```typescript
1683
+ * // Services automatically call this via super()
1684
+ * export class EntityService extends BaseService {
1685
+ * constructor(instance: IUiPath) {
1686
+ * super(instance); // Initializes the internal ApiClient
1687
+ * }
1688
+ * }
1689
+ *
1690
+ * // Usage in modular pattern
1691
+ * import { UiPath } from '@uipath/uipath-typescript/core';
1692
+ * import { Entities } from '@uipath/uipath-typescript/entities';
1693
+ *
1694
+ * const sdk = new UiPath(config);
1695
+ * await sdk.initialize();
1696
+ * const entities = new Entities(sdk);
1697
+ * ```
1698
+ */
1699
+ constructor(instance) {
1700
+ // Private field - not visible via Object.keys() or any reflection
1701
+ _BaseService_apiClient.set(this, void 0);
1702
+ const { config, context, tokenManager } = SDKInternalsRegistry.get(instance);
1703
+ __classPrivateFieldSet(this, _BaseService_apiClient, new ApiClient(config, context, tokenManager), "f");
1704
+ }
1705
+ /**
1706
+ * Gets a valid authentication token, refreshing if necessary.
1707
+ * Use this when you need to manually add Authorization headers (e.g., direct uploads).
1708
+ *
1709
+ * @returns Promise resolving to a valid access token string
1710
+ * @throws AuthenticationError if no token is available or refresh fails
1711
+ */
1712
+ async getValidAuthToken() {
1713
+ return __classPrivateFieldGet(this, _BaseService_apiClient, "f").getValidToken();
1714
+ }
1715
+ /**
1716
+ * Creates a service accessor for pagination helpers
1717
+ * This allows pagination helpers to access protected methods without making them public
1718
+ */
1719
+ createPaginationServiceAccess() {
1720
+ return {
1721
+ get: (path, options) => this.get(path, options || {}),
1722
+ post: (path, body, options) => this.post(path, body, options || {}),
1723
+ requestWithPagination: (method, path, paginationOptions, options) => this.requestWithPagination(method, path, paginationOptions, options)
1724
+ };
1725
+ }
1726
+ async request(method, path, options = {}) {
1727
+ switch (method.toUpperCase()) {
1728
+ case 'GET':
1729
+ return this.get(path, options);
1730
+ case 'POST':
1731
+ return this.post(path, options.body, options);
1732
+ case 'PUT':
1733
+ return this.put(path, options.body, options);
1734
+ case 'PATCH':
1735
+ return this.patch(path, options.body, options);
1736
+ case 'DELETE':
1737
+ return this.delete(path, options);
1738
+ default:
1739
+ throw new Error(`Unsupported HTTP method: ${method}`);
1740
+ }
1741
+ }
1742
+ async requestWithSpec(spec) {
1743
+ if (!spec.method || !spec.url) {
1744
+ throw new Error('Request spec must include method and url');
1745
+ }
1746
+ return this.request(spec.method, spec.url, spec);
1747
+ }
1748
+ async get(path, options = {}) {
1749
+ const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").get(path, options);
1750
+ return { data: response };
1751
+ }
1752
+ async post(path, data, options = {}) {
1753
+ const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").post(path, data, options);
1754
+ return { data: response };
1755
+ }
1756
+ async put(path, data, options = {}) {
1757
+ const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").put(path, data, options);
1758
+ return { data: response };
1759
+ }
1760
+ async patch(path, data, options = {}) {
1761
+ const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").patch(path, data, options);
1762
+ return { data: response };
1763
+ }
1764
+ async delete(path, options = {}) {
1765
+ const response = await __classPrivateFieldGet(this, _BaseService_apiClient, "f").delete(path, options);
1766
+ return { data: response };
1767
+ }
1768
+ /**
1769
+ * Execute a request with cursor-based pagination
1770
+ */
1771
+ async requestWithPagination(method, path, paginationOptions, options) {
1772
+ const paginationType = options.pagination.paginationType;
1773
+ // Validate and prepare pagination parameters
1774
+ const params = this.validateAndPreparePaginationParams(paginationType, paginationOptions);
1775
+ // Prepare request parameters based on pagination type
1776
+ const requestParams = this.preparePaginationRequestParams(paginationType, params, options.pagination);
1777
+ // For POST requests, merge pagination params into body; for GET, use query params
1778
+ if (method.toUpperCase() === 'POST') {
1779
+ const existingBody = (options.body && typeof options.body === 'object') ? options.body : {};
1780
+ options.body = {
1781
+ ...existingBody,
1782
+ ...options.params,
1783
+ ...requestParams
1784
+ };
1785
+ }
1786
+ else {
1787
+ // Merge pagination parameters with existing parameters
1788
+ options.params = {
1789
+ ...options.params,
1790
+ ...requestParams
1791
+ };
1792
+ }
1793
+ // Make the request
1794
+ const response = await this.request(method, path, options);
1795
+ // Extract data from the response and create page result
1796
+ return this.createPaginatedResponseFromResponse(response, params, paginationType, {
1797
+ itemsField: options.pagination.itemsField,
1798
+ totalCountField: options.pagination.totalCountField,
1799
+ continuationTokenField: options.pagination.continuationTokenField
1800
+ });
1801
+ }
1802
+ /**
1803
+ * Validates and prepares pagination parameters from options
1804
+ */
1805
+ validateAndPreparePaginationParams(paginationType, paginationOptions) {
1806
+ return PaginationHelpers.validatePaginationOptions(paginationOptions, paginationType);
1807
+ }
1808
+ /**
1809
+ * Prepares request parameters for pagination based on pagination type
1810
+ */
1811
+ preparePaginationRequestParams(paginationType, params, paginationConfig) {
1812
+ const requestParams = {};
1813
+ let limitedPageSize;
1814
+ const paginationParams = paginationConfig?.paginationParams;
1815
+ switch (paginationType) {
1816
+ case PaginationType.OFFSET:
1817
+ limitedPageSize = getLimitedPageSize(params.pageSize);
1818
+ const pageSizeParam = paginationParams?.pageSizeParam || ODATA_OFFSET_PARAMS.PAGE_SIZE_PARAM;
1819
+ const offsetParam = paginationParams?.offsetParam || ODATA_OFFSET_PARAMS.OFFSET_PARAM;
1820
+ const countParam = paginationParams?.countParam || ODATA_OFFSET_PARAMS.COUNT_PARAM;
1821
+ requestParams[pageSizeParam] = limitedPageSize;
1822
+ if (params.pageNumber && params.pageNumber > 1) {
1823
+ requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
1824
+ }
1825
+ // Include total count for ODATA APIs
1826
+ {
1827
+ requestParams[countParam] = true;
1828
+ }
1829
+ break;
1830
+ case PaginationType.TOKEN:
1831
+ const tokenPageSizeParam = paginationParams?.pageSizeParam || BUCKET_TOKEN_PARAMS.PAGE_SIZE_PARAM;
1832
+ const tokenParam = paginationParams?.tokenParam || BUCKET_TOKEN_PARAMS.TOKEN_PARAM;
1833
+ if (params.pageSize) {
1834
+ requestParams[tokenPageSizeParam] = getLimitedPageSize(params.pageSize);
1835
+ }
1836
+ if (params.continuationToken) {
1837
+ requestParams[tokenParam] = params.continuationToken;
1838
+ }
1839
+ break;
1840
+ }
1841
+ return requestParams;
1842
+ }
1843
+ /**
1844
+ * Creates a paginated response from API response
1845
+ */
1846
+ createPaginatedResponseFromResponse(response, params, paginationType, fields) {
1847
+ // Extract fields from response
1848
+ const itemsField = fields.itemsField ||
1849
+ (paginationType === PaginationType.TOKEN ? 'items' : 'value');
1850
+ const totalCountField = fields.totalCountField || 'totalRecordCount';
1851
+ const continuationTokenField = fields.continuationTokenField || 'continuationToken';
1852
+ // Extract items and metadata
1853
+ const items = response.data[itemsField] || [];
1854
+ const totalCount = response.data[totalCountField];
1855
+ const continuationToken = response.data[continuationTokenField];
1856
+ // Determine if there are more pages
1857
+ const hasMore = this.determineHasMorePages(paginationType, {
1858
+ totalCount,
1859
+ pageSize: params.pageSize,
1860
+ currentPage: params.pageNumber || 1,
1861
+ itemsCount: items.length,
1862
+ continuationToken
1863
+ });
1864
+ // Create and return the page result
1865
+ return PaginationManager.createPaginatedResponse({
1866
+ pageInfo: {
1867
+ hasMore,
1868
+ totalCount,
1869
+ currentPage: params.pageNumber,
1870
+ pageSize: params.pageSize,
1871
+ continuationToken
1872
+ },
1873
+ type: paginationType,
1874
+ }, items);
1875
+ }
1876
+ /**
1877
+ * Determines if there are more pages based on pagination type and metadata
1878
+ */
1879
+ determineHasMorePages(paginationType, info) {
1880
+ switch (paginationType) {
1881
+ case PaginationType.OFFSET:
1882
+ const effectivePageSize = info.pageSize ?? DEFAULT_PAGE_SIZE;
1883
+ // If totalCount is available, use it for precise calculation
1884
+ if (info.totalCount !== undefined) {
1885
+ return (info.currentPage * effectivePageSize) < info.totalCount;
1886
+ }
1887
+ // Fallback when totalCount is not available
1888
+ // NOTE: This code path should rarely be executed as the APIs typically return totalCount
1889
+ return info.itemsCount === effectivePageSize;
1890
+ case PaginationType.TOKEN:
1891
+ return !!info.continuationToken;
1892
+ default:
1893
+ return false;
1894
+ }
1895
+ }
1896
+ }
1897
+ _BaseService_apiClient = new WeakMap();
1898
+
1899
+ /**
1900
+ * Maps fields for Bucket entities to ensure consistent naming
1901
+ */
1902
+ const BucketMap = {
1903
+ fullPath: 'path',
1904
+ items: 'blobItems',
1905
+ verb: 'httpMethod'
1906
+ };
1907
+
1908
+ class AttachmentService extends BaseService {
1909
+ /**
1910
+ * Gets an attachment by ID
1911
+ * @param id - The UUID of the attachment to retrieve
1912
+ * @param options - Optional query parameters (expand, select)
1913
+ * @returns Promise resolving to the attachment
1914
+ *
1915
+ * @example
1916
+ * ```typescript
1917
+ * import { Attachments } from '@uipath/uipath-typescript/attachments';
1918
+ *
1919
+ * const attachments = new Attachments(sdk);
1920
+ * const attachment = await attachments.getById('12345678-1234-1234-1234-123456789abc');
1921
+ * ```
1922
+ */
1923
+ async getById(id, options = {}) {
1924
+ if (!id) {
1925
+ throw new ValidationError({ message: 'id is required for getById' });
1926
+ }
1927
+ // Prefix all keys in options with $ for OData
1928
+ const keysToPrefix = Object.keys(options);
1929
+ const apiOptions = addPrefixToKeys(options, ODATA_PREFIX, keysToPrefix);
1930
+ const response = await this.get(ORCHESTRATOR_ATTACHMENT_ENDPOINTS.GET_BY_ID(id), {
1931
+ params: apiOptions,
1932
+ });
1933
+ // Transform response from PascalCase to camelCase, then apply field maps
1934
+ const camelCased = pascalToCamelCaseKeys(response.data);
1935
+ camelCased.blobFileAccess = transformData(camelCased.blobFileAccess, BucketMap);
1936
+ return transformData(camelCased, AttachmentsMap);
1937
+ }
1938
+ }
1939
+ __decorate([
1940
+ track('Attachments.GetById')
1941
+ ], AttachmentService.prototype, "getById", null);
1942
+
1943
+ exports.AttachmentService = AttachmentService;
1944
+ exports.Attachments = AttachmentService;