@uipath/uipath-typescript 1.3.6 → 1.3.8

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 (44) hide show
  1. package/dist/assets/index.cjs +243 -6
  2. package/dist/assets/index.d.ts +113 -13
  3. package/dist/assets/index.mjs +243 -6
  4. package/dist/attachments/index.cjs +42 -6
  5. package/dist/attachments/index.d.ts +8 -0
  6. package/dist/attachments/index.mjs +42 -6
  7. package/dist/buckets/index.cjs +211 -6
  8. package/dist/buckets/index.d.ts +57 -12
  9. package/dist/buckets/index.mjs +211 -6
  10. package/dist/cases/index.cjs +180 -6
  11. package/dist/cases/index.d.ts +165 -3
  12. package/dist/cases/index.mjs +181 -7
  13. package/dist/conversational-agent/index.cjs +235 -85
  14. package/dist/conversational-agent/index.d.ts +327 -80
  15. package/dist/conversational-agent/index.mjs +234 -84
  16. package/dist/core/index.cjs +18 -6
  17. package/dist/core/index.d.ts +1 -1
  18. package/dist/core/index.mjs +18 -6
  19. package/dist/entities/index.cjs +74 -10
  20. package/dist/entities/index.d.ts +102 -11
  21. package/dist/entities/index.mjs +75 -11
  22. package/dist/feedback/index.cjs +293 -10
  23. package/dist/feedback/index.d.ts +425 -12
  24. package/dist/feedback/index.mjs +293 -10
  25. package/dist/index.cjs +463 -17
  26. package/dist/index.d.ts +885 -39
  27. package/dist/index.mjs +464 -18
  28. package/dist/index.umd.js +463 -17
  29. package/dist/jobs/index.cjs +211 -6
  30. package/dist/jobs/index.d.ts +68 -23
  31. package/dist/jobs/index.mjs +211 -6
  32. package/dist/maestro-processes/index.cjs +79 -6
  33. package/dist/maestro-processes/index.d.ts +8 -0
  34. package/dist/maestro-processes/index.mjs +79 -6
  35. package/dist/processes/index.cjs +279 -7
  36. package/dist/processes/index.d.ts +125 -2
  37. package/dist/processes/index.mjs +279 -7
  38. package/dist/queues/index.cjs +211 -6
  39. package/dist/queues/index.d.ts +57 -12
  40. package/dist/queues/index.mjs +211 -6
  41. package/dist/tasks/index.cjs +42 -6
  42. package/dist/tasks/index.d.ts +8 -0
  43. package/dist/tasks/index.mjs +42 -6
  44. package/package.json +1 -1
@@ -505,6 +505,8 @@ class ErrorFactory {
505
505
  }
506
506
  }
507
507
 
508
+ const FOLDER_KEY = 'X-UIPATH-FolderKey';
509
+ const FOLDER_PATH_ENCODED = 'X-UIPATH-FolderPath-Encoded';
508
510
  const FOLDER_ID = 'X-UIPATH-OrganizationUnitId';
509
511
  const TRACEPARENT = 'traceparent';
510
512
  const UIPATH_TRACEPARENT_ID = 'x-uipath-traceparent-id';
@@ -651,6 +653,27 @@ var PaginationType;
651
653
  /**
652
654
  * Collection of utility functions for working with objects
653
655
  */
656
+ /**
657
+ * Resolves a field value from an object, supporting both direct keys (e.g., '@odata.count')
658
+ * and dot-separated nested paths (e.g., 'pagination.totalCount').
659
+ * Direct key match takes priority over nested traversal.
660
+ */
661
+ function resolveNestedField(data, fieldPath) {
662
+ if (!data) {
663
+ return undefined;
664
+ }
665
+ if (fieldPath in data) {
666
+ return data[fieldPath];
667
+ }
668
+ if (!fieldPath.includes('.')) {
669
+ return undefined;
670
+ }
671
+ let value = data;
672
+ for (const part of fieldPath.split('.')) {
673
+ value = value?.[part];
674
+ }
675
+ return value;
676
+ }
654
677
  /**
655
678
  * Filters out undefined values from an object
656
679
  * @param obj The source object
@@ -900,6 +923,10 @@ const BUCKET_TOKEN_PARAMS = {
900
923
  TOKEN_PARAM: 'continuationToken'
901
924
  };
902
925
 
926
+ /**
927
+ * Converts a UTC timestamp string (e.g., "5/8/2026 11:20:17 AM") to ISO 8601 UTC format.
928
+ * Returns the original value if parsing fails.
929
+ */
903
930
  /**
904
931
  * Transforms data by mapping fields according to the provided field mapping
905
932
  * @param data The source data to transform
@@ -1288,7 +1315,8 @@ class PaginationHelpers {
1288
1315
  // Extract and transform items from response
1289
1316
  // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
1290
1317
  const rawItems = Array.isArray(response.data) ? response.data : response.data?.[itemsField];
1291
- const totalCount = Array.isArray(response.data) ? undefined : response.data?.[totalCountField];
1318
+ const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
1319
+ const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
1292
1320
  // Parse items - automatically handle JSON string responses
1293
1321
  const parsedItems = typeof rawItems === 'string' ? JSON.parse(rawItems) : (rawItems || []);
1294
1322
  const items = transformFn ? parsedItems.map(transformFn) : parsedItems;
@@ -1464,8 +1492,9 @@ class BaseService {
1464
1492
  constructor(instance, headers) {
1465
1493
  // Private field - not visible via Object.keys() or any reflection
1466
1494
  _BaseService_apiClient.set(this, void 0);
1467
- const { config, context, tokenManager } = SDKInternalsRegistry.get(instance);
1495
+ const { config, context, tokenManager, folderKey } = SDKInternalsRegistry.get(instance);
1468
1496
  __classPrivateFieldSet(this, _BaseService_apiClient, new ApiClient(config, context, tokenManager, headers ? { headers } : {}), "f");
1497
+ this.config = { folderKey };
1469
1498
  }
1470
1499
  /**
1471
1500
  * Gets a valid authentication token, refreshing if necessary.
@@ -1584,9 +1613,17 @@ class BaseService {
1584
1613
  const pageSizeParam = paginationParams?.pageSizeParam || ODATA_OFFSET_PARAMS.PAGE_SIZE_PARAM;
1585
1614
  const offsetParam = paginationParams?.offsetParam || ODATA_OFFSET_PARAMS.OFFSET_PARAM;
1586
1615
  const countParam = paginationParams?.countParam || ODATA_OFFSET_PARAMS.COUNT_PARAM;
1616
+ // When true (default), converts pageNumber to a skip/offset value (e.g., page 3 with pageSize 10 → skip 20).
1617
+ // When false, passes pageNumber directly as the offset param — used by APIs that accept a page number instead of a record offset.
1618
+ const convertToSkip = paginationParams?.convertToSkip ?? true;
1587
1619
  requestParams[pageSizeParam] = limitedPageSize;
1588
- if (params.pageNumber && params.pageNumber > 1) {
1589
- requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
1620
+ if (convertToSkip) {
1621
+ if (params.pageNumber && params.pageNumber > 1) {
1622
+ requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
1623
+ }
1624
+ }
1625
+ else {
1626
+ requestParams[offsetParam] = params.pageNumber || 1;
1590
1627
  }
1591
1628
  {
1592
1629
  requestParams[countParam] = true;
@@ -1617,7 +1654,8 @@ class BaseService {
1617
1654
  // Extract items and metadata
1618
1655
  // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
1619
1656
  const items = Array.isArray(response.data) ? response.data : (response.data[itemsField] || []);
1620
- const totalCount = Array.isArray(response.data) ? undefined : response.data[totalCountField];
1657
+ const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
1658
+ const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
1621
1659
  const continuationToken = response.data[continuationTokenField];
1622
1660
  // Determine if there are more pages
1623
1661
  const hasMore = this.determineHasMorePages(paginationType, {
@@ -1662,6 +1700,111 @@ class BaseService {
1662
1700
  }
1663
1701
  _BaseService_apiClient = new WeakMap();
1664
1702
 
1703
+ /**
1704
+ * Validates the `name` argument passed to a `getByName(name, ...)` method.
1705
+ * Trims whitespace and rejects empty/whitespace-only names.
1706
+ *
1707
+ * @param resourceType - Resource label used in error messages (e.g. 'Asset', 'Process')
1708
+ * @param name - Resource name to validate
1709
+ * @returns The trimmed name
1710
+ * @throws ValidationError when `name` is missing or empty after trimming
1711
+ */
1712
+ function validateName(resourceType, name) {
1713
+ if (!name) {
1714
+ throw new ValidationError({
1715
+ message: `${resourceType} name is required and cannot be empty.`,
1716
+ });
1717
+ }
1718
+ const trimmed = name.trim();
1719
+ if (!trimmed) {
1720
+ throw new ValidationError({
1721
+ message: `${resourceType} name is required and cannot be empty.`,
1722
+ });
1723
+ }
1724
+ return trimmed;
1725
+ }
1726
+
1727
+ /**
1728
+ * Encodes a folder path for the `X-UIPATH-FolderPath-Encoded` header.
1729
+ *
1730
+ * Orchestrator decodes this header as **base64-encoded UTF-16 LE bytes**
1731
+ * (see `HttpHeadersProviderExtensions.GetDecoded` + `OrganizationUnitProvider`
1732
+ * in the Orchestrator repo, which call `Encoding.Unicode.GetString(...)`).
1733
+ * URL-encoding is NOT what the server expects — it must be base64-of-UTF-16-LE
1734
+ * bytes.
1735
+ *
1736
+ * @param folderPath - The folder path (e.g. 'Shared/Finance')
1737
+ * @returns Base64 string suitable for the `X-UIPATH-FolderPath-Encoded` header
1738
+ */
1739
+ function encodeFolderPathHeader(folderPath) {
1740
+ // Force little-endian regardless of host byte order. `Uint16Array` viewed
1741
+ // as `Uint8Array` would use the host's native order — correct on LE hosts
1742
+ // (x86/ARM-LE) but wrong on BE hosts. `DataView.setUint16(..., true)`
1743
+ // pins LE.
1744
+ const buf = new ArrayBuffer(folderPath.length * 2);
1745
+ const view = new DataView(buf);
1746
+ for (let i = 0; i < folderPath.length; i++) {
1747
+ view.setUint16(i * 2, folderPath.charCodeAt(i), true);
1748
+ }
1749
+ const bytes = new Uint8Array(buf);
1750
+ let binary = '';
1751
+ for (let i = 0; i < bytes.byteLength; i++) {
1752
+ binary += String.fromCharCode(bytes[i]);
1753
+ }
1754
+ // btoa is browser-native; Node 16+ also has it as a global
1755
+ return btoa(binary);
1756
+ }
1757
+
1758
+ /**
1759
+ * Resolves folder context into the appropriate Orchestrator folder headers.
1760
+ *
1761
+ * Centralized so all folder-scoped methods (e.g. `assets.getByName`,
1762
+ * `processes.getByName`, future Queues/Buckets/Jobs) share one implementation.
1763
+ *
1764
+ * Each input field maps directly to its header — no auto-detection or type
1765
+ * coercion. When multiple fields are supplied, all corresponding headers
1766
+ * are forwarded and the server resolves precedence.
1767
+ *
1768
+ * Routing:
1769
+ * - `folderId` → `X-UIPATH-OrganizationUnitId`
1770
+ * - `folderKey` → `X-UIPATH-FolderKey`
1771
+ * - `folderPath` → `X-UIPATH-FolderPath-Encoded`
1772
+ * - none set + `fallbackFolderKey` → fallback used as `X-UIPATH-FolderKey`
1773
+ * - none set + no fallback → `ValidationError`
1774
+ *
1775
+ * @throws ValidationError when no folder context can be resolved.
1776
+ */
1777
+ function resolveFolderHeaders(input) {
1778
+ const { folderId, folderKey, folderPath, resourceType, fallbackFolderKey } = input;
1779
+ const trimmedKey = folderKey?.trim();
1780
+ const trimmedPath = folderPath?.trim();
1781
+ const headers = {};
1782
+ if (folderId !== undefined) {
1783
+ headers[FOLDER_ID] = folderId;
1784
+ }
1785
+ if (trimmedKey) {
1786
+ headers[FOLDER_KEY] = trimmedKey;
1787
+ }
1788
+ if (trimmedPath) {
1789
+ headers[FOLDER_PATH_ENCODED] = encodeFolderPathHeader(trimmedPath);
1790
+ }
1791
+ // No explicit folder context → meta-tag fallback or error.
1792
+ if (Object.keys(headers).length === 0) {
1793
+ if (!fallbackFolderKey) {
1794
+ throw new ValidationError({
1795
+ message: `${resourceType} requires folder context: pass \`folderId\`, \`folderKey\`, or \`folderPath\`, or initialize the SDK with a folder context.`,
1796
+ });
1797
+ }
1798
+ headers[FOLDER_KEY] = fallbackFolderKey;
1799
+ }
1800
+ return createHeaders(headers);
1801
+ }
1802
+
1803
+ /**
1804
+ * Matches single-quote characters in OData string literals — escaped to `''`
1805
+ * inside the `$filter=Name eq '…'` clause built by `getByNameLookup`.
1806
+ */
1807
+ const SINGLE_QUOTE_RE = /'/g;
1665
1808
  /**
1666
1809
  * Base service for services that need folder-specific functionality.
1667
1810
  *
@@ -1695,6 +1838,68 @@ class FolderScopedService extends BaseService {
1695
1838
  }
1696
1839
  return response.data?.value;
1697
1840
  }
1841
+ /**
1842
+ * Look up a single resource by name on a folder-scoped OData collection.
1843
+ *
1844
+ * Shared by `getByName` implementations across services (Assets, Processes, etc).
1845
+ * Handles:
1846
+ * - Name validation via `validateName`
1847
+ * - Folder header resolution via `resolveFolderHeaders` (folderId → ID/key
1848
+ * header by type, folderPath → encoded path header, falls back to
1849
+ * init-time `config.folderKey` from the `uipath:folder-key` meta tag)
1850
+ * - OData `$filter=Name eq '…'` with single-quote escaping + `$top=1`
1851
+ * - Empty-result → `NotFoundError` with folder context in the message
1852
+ *
1853
+ * The transform step is caller-provided because each resource has its own
1854
+ * PascalCase → camelCase field mapping.
1855
+ *
1856
+ * @param resourceType - Resource label used in validation + error messages (e.g. 'Asset', 'Process')
1857
+ * @param endpoint - Folder-scoped OData collection endpoint
1858
+ * @param name - Resource name to search for
1859
+ * @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) + OData query options (`expand`, `select`)
1860
+ * @param transform - Maps a raw OData item to the typed response (e.g. PascalCase → camelCase via field map)
1861
+ * @throws ValidationError when inputs are malformed; NotFoundError when no match
1862
+ */
1863
+ async getByNameLookup(resourceType, endpoint, name, options, transform) {
1864
+ const validatedName = validateName(resourceType, name);
1865
+ const { folderId, folderKey, folderPath, ...queryOptions } = options;
1866
+ const headers = resolveFolderHeaders({
1867
+ folderId,
1868
+ folderKey,
1869
+ folderPath,
1870
+ resourceType: `${resourceType}.getByName`,
1871
+ fallbackFolderKey: this.config.folderKey,
1872
+ });
1873
+ const apiOptions = {
1874
+ ...addPrefixToKeys(queryOptions, ODATA_PREFIX, Object.keys(queryOptions)),
1875
+ '$filter': `Name eq '${validatedName.replace(SINGLE_QUOTE_RE, "''")}'`,
1876
+ '$top': '1',
1877
+ };
1878
+ const response = await this.get(endpoint, {
1879
+ headers,
1880
+ params: apiOptions,
1881
+ });
1882
+ const items = response.data?.value;
1883
+ if (!items?.length) {
1884
+ const folderHint = describeFolderForError(folderId, folderKey, folderPath);
1885
+ throw new NotFoundError({
1886
+ message: `${resourceType} '${validatedName}' not found${folderHint}.`,
1887
+ });
1888
+ }
1889
+ return transform(items[0]);
1890
+ }
1891
+ }
1892
+ /** Renders the supplied folder for a NotFoundError message. */
1893
+ function describeFolderForError(folderId, folderKey, folderPath) {
1894
+ const path = folderPath?.trim();
1895
+ if (path)
1896
+ return ` in folder '${path}'`;
1897
+ const key = folderKey?.trim();
1898
+ if (key)
1899
+ return ` in folder (key: ${key})`;
1900
+ if (typeof folderId === 'number')
1901
+ return ` in folder (id: ${folderId})`;
1902
+ return '';
1698
1903
  }
1699
1904
 
1700
1905
  /**
@@ -1732,7 +1937,7 @@ const BucketMap = {
1732
1937
  // Connection string placeholder that will be replaced during build
1733
1938
  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";
1734
1939
  // SDK Version placeholder
1735
- const SDK_VERSION = "1.3.6";
1940
+ const SDK_VERSION = "1.3.8";
1736
1941
  const VERSION = "Version";
1737
1942
  const SERVICE = "Service";
1738
1943
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
@@ -106,6 +106,7 @@ interface RequestWithPaginationOptions extends RequestSpec {
106
106
  offsetParam?: string;
107
107
  tokenParam?: string;
108
108
  countParam?: string;
109
+ convertToSkip?: boolean;
109
110
  };
110
111
  };
111
112
  }
@@ -218,6 +219,13 @@ interface ApiResponse<T> {
218
219
  */
219
220
  declare class BaseService {
220
221
  #private;
222
+ /**
223
+ * SDK configuration (read-only). Available to subclasses so they can
224
+ * fall back to init-time defaults like `folderKey`.
225
+ */
226
+ protected readonly config: {
227
+ folderKey?: string;
228
+ };
221
229
  /**
222
230
  * Creates a base service instance with dependency injection.
223
231
  *
@@ -291,6 +299,32 @@ declare class BaseService {
291
299
  private determineHasMorePages;
292
300
  }
293
301
 
302
+ interface BaseOptions {
303
+ expand?: string;
304
+ select?: string;
305
+ }
306
+ /**
307
+ * Common request options interface used across services for querying data
308
+ */
309
+ interface RequestOptions extends BaseOptions {
310
+ filter?: string;
311
+ orderby?: string;
312
+ }
313
+ /**
314
+ * Options that scope a name-based lookup (e.g. `getByName`) to a folder.
315
+ * Provide one of `folderId`, `folderKey`, or `folderPath`. When more than
316
+ * one is supplied, all are forwarded; the server applies precedence
317
+ * `folderPath` > `folderKey` > `folderId`.
318
+ */
319
+ interface FolderScopedOptions extends BaseOptions {
320
+ /** Numeric folder ID. */
321
+ folderId?: number;
322
+ /** Folder key (GUID-formatted string). */
323
+ folderKey?: string;
324
+ /** Slash-delimited folder path, e.g. `'Shared/Finance'`. */
325
+ folderPath?: string;
326
+ }
327
+
294
328
  /**
295
329
  * Base service for services that need folder-specific functionality.
296
330
  *
@@ -312,18 +346,29 @@ declare class FolderScopedService extends BaseService {
312
346
  * @returns Promise resolving to an array of resources
313
347
  */
314
348
  protected _getByFolder<T, R = T>(endpoint: string, folderId: number, options?: Record<string, any>, transformFn?: (item: T) => R): Promise<R[]>;
315
- }
316
-
317
- interface BaseOptions {
318
- expand?: string;
319
- select?: string;
320
- }
321
- /**
322
- * Common request options interface used across services for querying data
323
- */
324
- interface RequestOptions extends BaseOptions {
325
- filter?: string;
326
- orderby?: string;
349
+ /**
350
+ * Look up a single resource by name on a folder-scoped OData collection.
351
+ *
352
+ * Shared by `getByName` implementations across services (Assets, Processes, etc).
353
+ * Handles:
354
+ * - Name validation via `validateName`
355
+ * - Folder header resolution via `resolveFolderHeaders` (folderId → ID/key
356
+ * header by type, folderPath encoded path header, falls back to
357
+ * init-time `config.folderKey` from the `uipath:folder-key` meta tag)
358
+ * - OData `$filter=Name eq '…'` with single-quote escaping + `$top=1`
359
+ * - Empty-result → `NotFoundError` with folder context in the message
360
+ *
361
+ * The transform step is caller-provided because each resource has its own
362
+ * PascalCase → camelCase field mapping.
363
+ *
364
+ * @param resourceType - Resource label used in validation + error messages (e.g. 'Asset', 'Process')
365
+ * @param endpoint - Folder-scoped OData collection endpoint
366
+ * @param name - Resource name to search for
367
+ * @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) + OData query options (`expand`, `select`)
368
+ * @param transform - Maps a raw OData item to the typed response (e.g. PascalCase → camelCase via field map)
369
+ * @throws ValidationError when inputs are malformed; NotFoundError when no match
370
+ */
371
+ protected getByNameLookup<TRaw extends object, T>(resourceType: string, endpoint: string, name: string, options: FolderScopedOptions, transform: (raw: TRaw) => T): Promise<T>;
327
372
  }
328
373
 
329
374
  declare enum BucketOptions {
@@ -503,6 +503,8 @@ class ErrorFactory {
503
503
  }
504
504
  }
505
505
 
506
+ const FOLDER_KEY = 'X-UIPATH-FolderKey';
507
+ const FOLDER_PATH_ENCODED = 'X-UIPATH-FolderPath-Encoded';
506
508
  const FOLDER_ID = 'X-UIPATH-OrganizationUnitId';
507
509
  const TRACEPARENT = 'traceparent';
508
510
  const UIPATH_TRACEPARENT_ID = 'x-uipath-traceparent-id';
@@ -649,6 +651,27 @@ var PaginationType;
649
651
  /**
650
652
  * Collection of utility functions for working with objects
651
653
  */
654
+ /**
655
+ * Resolves a field value from an object, supporting both direct keys (e.g., '@odata.count')
656
+ * and dot-separated nested paths (e.g., 'pagination.totalCount').
657
+ * Direct key match takes priority over nested traversal.
658
+ */
659
+ function resolveNestedField(data, fieldPath) {
660
+ if (!data) {
661
+ return undefined;
662
+ }
663
+ if (fieldPath in data) {
664
+ return data[fieldPath];
665
+ }
666
+ if (!fieldPath.includes('.')) {
667
+ return undefined;
668
+ }
669
+ let value = data;
670
+ for (const part of fieldPath.split('.')) {
671
+ value = value?.[part];
672
+ }
673
+ return value;
674
+ }
652
675
  /**
653
676
  * Filters out undefined values from an object
654
677
  * @param obj The source object
@@ -898,6 +921,10 @@ const BUCKET_TOKEN_PARAMS = {
898
921
  TOKEN_PARAM: 'continuationToken'
899
922
  };
900
923
 
924
+ /**
925
+ * Converts a UTC timestamp string (e.g., "5/8/2026 11:20:17 AM") to ISO 8601 UTC format.
926
+ * Returns the original value if parsing fails.
927
+ */
901
928
  /**
902
929
  * Transforms data by mapping fields according to the provided field mapping
903
930
  * @param data The source data to transform
@@ -1286,7 +1313,8 @@ class PaginationHelpers {
1286
1313
  // Extract and transform items from response
1287
1314
  // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
1288
1315
  const rawItems = Array.isArray(response.data) ? response.data : response.data?.[itemsField];
1289
- const totalCount = Array.isArray(response.data) ? undefined : response.data?.[totalCountField];
1316
+ const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
1317
+ const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
1290
1318
  // Parse items - automatically handle JSON string responses
1291
1319
  const parsedItems = typeof rawItems === 'string' ? JSON.parse(rawItems) : (rawItems || []);
1292
1320
  const items = transformFn ? parsedItems.map(transformFn) : parsedItems;
@@ -1462,8 +1490,9 @@ class BaseService {
1462
1490
  constructor(instance, headers) {
1463
1491
  // Private field - not visible via Object.keys() or any reflection
1464
1492
  _BaseService_apiClient.set(this, void 0);
1465
- const { config, context, tokenManager } = SDKInternalsRegistry.get(instance);
1493
+ const { config, context, tokenManager, folderKey } = SDKInternalsRegistry.get(instance);
1466
1494
  __classPrivateFieldSet(this, _BaseService_apiClient, new ApiClient(config, context, tokenManager, headers ? { headers } : {}), "f");
1495
+ this.config = { folderKey };
1467
1496
  }
1468
1497
  /**
1469
1498
  * Gets a valid authentication token, refreshing if necessary.
@@ -1582,9 +1611,17 @@ class BaseService {
1582
1611
  const pageSizeParam = paginationParams?.pageSizeParam || ODATA_OFFSET_PARAMS.PAGE_SIZE_PARAM;
1583
1612
  const offsetParam = paginationParams?.offsetParam || ODATA_OFFSET_PARAMS.OFFSET_PARAM;
1584
1613
  const countParam = paginationParams?.countParam || ODATA_OFFSET_PARAMS.COUNT_PARAM;
1614
+ // When true (default), converts pageNumber to a skip/offset value (e.g., page 3 with pageSize 10 → skip 20).
1615
+ // When false, passes pageNumber directly as the offset param — used by APIs that accept a page number instead of a record offset.
1616
+ const convertToSkip = paginationParams?.convertToSkip ?? true;
1585
1617
  requestParams[pageSizeParam] = limitedPageSize;
1586
- if (params.pageNumber && params.pageNumber > 1) {
1587
- requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
1618
+ if (convertToSkip) {
1619
+ if (params.pageNumber && params.pageNumber > 1) {
1620
+ requestParams[offsetParam] = (params.pageNumber - 1) * limitedPageSize;
1621
+ }
1622
+ }
1623
+ else {
1624
+ requestParams[offsetParam] = params.pageNumber || 1;
1588
1625
  }
1589
1626
  {
1590
1627
  requestParams[countParam] = true;
@@ -1615,7 +1652,8 @@ class BaseService {
1615
1652
  // Extract items and metadata
1616
1653
  // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
1617
1654
  const items = Array.isArray(response.data) ? response.data : (response.data[itemsField] || []);
1618
- const totalCount = Array.isArray(response.data) ? undefined : response.data[totalCountField];
1655
+ const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
1656
+ const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
1619
1657
  const continuationToken = response.data[continuationTokenField];
1620
1658
  // Determine if there are more pages
1621
1659
  const hasMore = this.determineHasMorePages(paginationType, {
@@ -1660,6 +1698,111 @@ class BaseService {
1660
1698
  }
1661
1699
  _BaseService_apiClient = new WeakMap();
1662
1700
 
1701
+ /**
1702
+ * Validates the `name` argument passed to a `getByName(name, ...)` method.
1703
+ * Trims whitespace and rejects empty/whitespace-only names.
1704
+ *
1705
+ * @param resourceType - Resource label used in error messages (e.g. 'Asset', 'Process')
1706
+ * @param name - Resource name to validate
1707
+ * @returns The trimmed name
1708
+ * @throws ValidationError when `name` is missing or empty after trimming
1709
+ */
1710
+ function validateName(resourceType, name) {
1711
+ if (!name) {
1712
+ throw new ValidationError({
1713
+ message: `${resourceType} name is required and cannot be empty.`,
1714
+ });
1715
+ }
1716
+ const trimmed = name.trim();
1717
+ if (!trimmed) {
1718
+ throw new ValidationError({
1719
+ message: `${resourceType} name is required and cannot be empty.`,
1720
+ });
1721
+ }
1722
+ return trimmed;
1723
+ }
1724
+
1725
+ /**
1726
+ * Encodes a folder path for the `X-UIPATH-FolderPath-Encoded` header.
1727
+ *
1728
+ * Orchestrator decodes this header as **base64-encoded UTF-16 LE bytes**
1729
+ * (see `HttpHeadersProviderExtensions.GetDecoded` + `OrganizationUnitProvider`
1730
+ * in the Orchestrator repo, which call `Encoding.Unicode.GetString(...)`).
1731
+ * URL-encoding is NOT what the server expects — it must be base64-of-UTF-16-LE
1732
+ * bytes.
1733
+ *
1734
+ * @param folderPath - The folder path (e.g. 'Shared/Finance')
1735
+ * @returns Base64 string suitable for the `X-UIPATH-FolderPath-Encoded` header
1736
+ */
1737
+ function encodeFolderPathHeader(folderPath) {
1738
+ // Force little-endian regardless of host byte order. `Uint16Array` viewed
1739
+ // as `Uint8Array` would use the host's native order — correct on LE hosts
1740
+ // (x86/ARM-LE) but wrong on BE hosts. `DataView.setUint16(..., true)`
1741
+ // pins LE.
1742
+ const buf = new ArrayBuffer(folderPath.length * 2);
1743
+ const view = new DataView(buf);
1744
+ for (let i = 0; i < folderPath.length; i++) {
1745
+ view.setUint16(i * 2, folderPath.charCodeAt(i), true);
1746
+ }
1747
+ const bytes = new Uint8Array(buf);
1748
+ let binary = '';
1749
+ for (let i = 0; i < bytes.byteLength; i++) {
1750
+ binary += String.fromCharCode(bytes[i]);
1751
+ }
1752
+ // btoa is browser-native; Node 16+ also has it as a global
1753
+ return btoa(binary);
1754
+ }
1755
+
1756
+ /**
1757
+ * Resolves folder context into the appropriate Orchestrator folder headers.
1758
+ *
1759
+ * Centralized so all folder-scoped methods (e.g. `assets.getByName`,
1760
+ * `processes.getByName`, future Queues/Buckets/Jobs) share one implementation.
1761
+ *
1762
+ * Each input field maps directly to its header — no auto-detection or type
1763
+ * coercion. When multiple fields are supplied, all corresponding headers
1764
+ * are forwarded and the server resolves precedence.
1765
+ *
1766
+ * Routing:
1767
+ * - `folderId` → `X-UIPATH-OrganizationUnitId`
1768
+ * - `folderKey` → `X-UIPATH-FolderKey`
1769
+ * - `folderPath` → `X-UIPATH-FolderPath-Encoded`
1770
+ * - none set + `fallbackFolderKey` → fallback used as `X-UIPATH-FolderKey`
1771
+ * - none set + no fallback → `ValidationError`
1772
+ *
1773
+ * @throws ValidationError when no folder context can be resolved.
1774
+ */
1775
+ function resolveFolderHeaders(input) {
1776
+ const { folderId, folderKey, folderPath, resourceType, fallbackFolderKey } = input;
1777
+ const trimmedKey = folderKey?.trim();
1778
+ const trimmedPath = folderPath?.trim();
1779
+ const headers = {};
1780
+ if (folderId !== undefined) {
1781
+ headers[FOLDER_ID] = folderId;
1782
+ }
1783
+ if (trimmedKey) {
1784
+ headers[FOLDER_KEY] = trimmedKey;
1785
+ }
1786
+ if (trimmedPath) {
1787
+ headers[FOLDER_PATH_ENCODED] = encodeFolderPathHeader(trimmedPath);
1788
+ }
1789
+ // No explicit folder context → meta-tag fallback or error.
1790
+ if (Object.keys(headers).length === 0) {
1791
+ if (!fallbackFolderKey) {
1792
+ throw new ValidationError({
1793
+ message: `${resourceType} requires folder context: pass \`folderId\`, \`folderKey\`, or \`folderPath\`, or initialize the SDK with a folder context.`,
1794
+ });
1795
+ }
1796
+ headers[FOLDER_KEY] = fallbackFolderKey;
1797
+ }
1798
+ return createHeaders(headers);
1799
+ }
1800
+
1801
+ /**
1802
+ * Matches single-quote characters in OData string literals — escaped to `''`
1803
+ * inside the `$filter=Name eq '…'` clause built by `getByNameLookup`.
1804
+ */
1805
+ const SINGLE_QUOTE_RE = /'/g;
1663
1806
  /**
1664
1807
  * Base service for services that need folder-specific functionality.
1665
1808
  *
@@ -1693,6 +1836,68 @@ class FolderScopedService extends BaseService {
1693
1836
  }
1694
1837
  return response.data?.value;
1695
1838
  }
1839
+ /**
1840
+ * Look up a single resource by name on a folder-scoped OData collection.
1841
+ *
1842
+ * Shared by `getByName` implementations across services (Assets, Processes, etc).
1843
+ * Handles:
1844
+ * - Name validation via `validateName`
1845
+ * - Folder header resolution via `resolveFolderHeaders` (folderId → ID/key
1846
+ * header by type, folderPath → encoded path header, falls back to
1847
+ * init-time `config.folderKey` from the `uipath:folder-key` meta tag)
1848
+ * - OData `$filter=Name eq '…'` with single-quote escaping + `$top=1`
1849
+ * - Empty-result → `NotFoundError` with folder context in the message
1850
+ *
1851
+ * The transform step is caller-provided because each resource has its own
1852
+ * PascalCase → camelCase field mapping.
1853
+ *
1854
+ * @param resourceType - Resource label used in validation + error messages (e.g. 'Asset', 'Process')
1855
+ * @param endpoint - Folder-scoped OData collection endpoint
1856
+ * @param name - Resource name to search for
1857
+ * @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) + OData query options (`expand`, `select`)
1858
+ * @param transform - Maps a raw OData item to the typed response (e.g. PascalCase → camelCase via field map)
1859
+ * @throws ValidationError when inputs are malformed; NotFoundError when no match
1860
+ */
1861
+ async getByNameLookup(resourceType, endpoint, name, options, transform) {
1862
+ const validatedName = validateName(resourceType, name);
1863
+ const { folderId, folderKey, folderPath, ...queryOptions } = options;
1864
+ const headers = resolveFolderHeaders({
1865
+ folderId,
1866
+ folderKey,
1867
+ folderPath,
1868
+ resourceType: `${resourceType}.getByName`,
1869
+ fallbackFolderKey: this.config.folderKey,
1870
+ });
1871
+ const apiOptions = {
1872
+ ...addPrefixToKeys(queryOptions, ODATA_PREFIX, Object.keys(queryOptions)),
1873
+ '$filter': `Name eq '${validatedName.replace(SINGLE_QUOTE_RE, "''")}'`,
1874
+ '$top': '1',
1875
+ };
1876
+ const response = await this.get(endpoint, {
1877
+ headers,
1878
+ params: apiOptions,
1879
+ });
1880
+ const items = response.data?.value;
1881
+ if (!items?.length) {
1882
+ const folderHint = describeFolderForError(folderId, folderKey, folderPath);
1883
+ throw new NotFoundError({
1884
+ message: `${resourceType} '${validatedName}' not found${folderHint}.`,
1885
+ });
1886
+ }
1887
+ return transform(items[0]);
1888
+ }
1889
+ }
1890
+ /** Renders the supplied folder for a NotFoundError message. */
1891
+ function describeFolderForError(folderId, folderKey, folderPath) {
1892
+ const path = folderPath?.trim();
1893
+ if (path)
1894
+ return ` in folder '${path}'`;
1895
+ const key = folderKey?.trim();
1896
+ if (key)
1897
+ return ` in folder (key: ${key})`;
1898
+ if (typeof folderId === 'number')
1899
+ return ` in folder (id: ${folderId})`;
1900
+ return '';
1696
1901
  }
1697
1902
 
1698
1903
  /**
@@ -1730,7 +1935,7 @@ const BucketMap = {
1730
1935
  // Connection string placeholder that will be replaced during build
1731
1936
  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";
1732
1937
  // SDK Version placeholder
1733
- const SDK_VERSION = "1.3.6";
1938
+ const SDK_VERSION = "1.3.8";
1734
1939
  const VERSION = "Version";
1735
1940
  const SERVICE = "Service";
1736
1941
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";