@uipath/uipath-typescript 1.3.11 → 1.4.1

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 (59) hide show
  1. package/dist/agent-memory/index.cjs +1772 -0
  2. package/dist/agent-memory/index.d.ts +588 -0
  3. package/dist/agent-memory/index.mjs +1770 -0
  4. package/dist/agents/index.cjs +1995 -0
  5. package/dist/agents/index.d.ts +961 -0
  6. package/dist/agents/index.mjs +1993 -0
  7. package/dist/assets/index.cjs +171 -39
  8. package/dist/assets/index.d.ts +84 -5
  9. package/dist/assets/index.mjs +171 -39
  10. package/dist/attachments/index.cjs +53 -15
  11. package/dist/attachments/index.d.ts +1 -0
  12. package/dist/attachments/index.mjs +53 -15
  13. package/dist/buckets/index.cjs +151 -130
  14. package/dist/buckets/index.d.ts +198 -84
  15. package/dist/buckets/index.mjs +151 -130
  16. package/dist/cases/index.cjs +220 -23
  17. package/dist/cases/index.d.ts +148 -10
  18. package/dist/cases/index.mjs +220 -24
  19. package/dist/conversational-agent/index.cjs +140 -66
  20. package/dist/conversational-agent/index.d.ts +190 -122
  21. package/dist/conversational-agent/index.mjs +140 -66
  22. package/dist/core/index.cjs +445 -108
  23. package/dist/core/index.d.ts +15 -0
  24. package/dist/core/index.mjs +445 -108
  25. package/dist/entities/index.cjs +365 -102
  26. package/dist/entities/index.d.ts +446 -114
  27. package/dist/entities/index.mjs +365 -102
  28. package/dist/feedback/index.cjs +53 -15
  29. package/dist/feedback/index.d.ts +1 -0
  30. package/dist/feedback/index.mjs +53 -15
  31. package/dist/governance/index.cjs +1789 -0
  32. package/dist/governance/index.d.ts +598 -0
  33. package/dist/governance/index.mjs +1787 -0
  34. package/dist/index.cjs +1453 -444
  35. package/dist/index.d.ts +4150 -1742
  36. package/dist/index.mjs +1452 -445
  37. package/dist/index.umd.js +5035 -4009
  38. package/dist/jobs/index.cjs +53 -15
  39. package/dist/jobs/index.d.ts +1 -0
  40. package/dist/jobs/index.mjs +53 -15
  41. package/dist/maestro-processes/index.cjs +189 -27
  42. package/dist/maestro-processes/index.d.ts +131 -9
  43. package/dist/maestro-processes/index.mjs +189 -27
  44. package/dist/orchestrator-du-module/index.cjs +1788 -0
  45. package/dist/orchestrator-du-module/index.d.ts +757 -0
  46. package/dist/orchestrator-du-module/index.mjs +1785 -0
  47. package/dist/processes/index.cjs +53 -15
  48. package/dist/processes/index.d.ts +1 -0
  49. package/dist/processes/index.mjs +53 -15
  50. package/dist/queues/index.cjs +53 -15
  51. package/dist/queues/index.d.ts +1 -0
  52. package/dist/queues/index.mjs +53 -15
  53. package/dist/tasks/index.cjs +116 -19
  54. package/dist/tasks/index.d.ts +110 -4
  55. package/dist/tasks/index.mjs +117 -20
  56. package/dist/traces/index.cjs +340 -15
  57. package/dist/traces/index.d.ts +483 -2
  58. package/dist/traces/index.mjs +339 -16
  59. package/package.json +42 -2
package/dist/index.cjs CHANGED
@@ -4020,7 +4020,7 @@ object({
4020
4020
  secret: string().optional(),
4021
4021
  clientId: string().optional(),
4022
4022
  redirectUri: string().url().optional(),
4023
- scope: string().optional()
4023
+ scope: string().optional(),
4024
4024
  });
4025
4025
  class UiPathConfig {
4026
4026
  constructor(options) {
@@ -4071,6 +4071,32 @@ class ExecutionContext {
4071
4071
  */
4072
4072
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
4073
4073
  const isInActionCenter = isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
4074
+ const _params = isBrowser ? new URLSearchParams(window.location.search) : null;
4075
+ /**
4076
+ * True when the coded app has been loaded inside a host frame that explicitly
4077
+ * opted into token delegation by adding `?host=embed` to the iframe src URL.
4078
+ */
4079
+ const isHostEmbedded = isBrowser && window.self !== window.top && _params?.get('host') === 'embed';
4080
+ /**
4081
+ * The validated parent origin, read from the `?basedomain=` query param set
4082
+ * by the embedding host in the iframe src URL.
4083
+ * Mirrors the same mechanism used by ActionCenterTokenManager.
4084
+ * Non-null only when `?host=embed` is present and `?basedomain=` is a valid URL.
4085
+ */
4086
+ const embeddingOrigin = (() => {
4087
+ if (!isHostEmbedded)
4088
+ return null;
4089
+ const basedomain = _params?.get('basedomain');
4090
+ if (!basedomain)
4091
+ return null;
4092
+ try {
4093
+ return new URL(basedomain).origin;
4094
+ }
4095
+ catch {
4096
+ console.warn('embeddingOrigin: basedomain query param is not a valid URL', basedomain);
4097
+ return null;
4098
+ }
4099
+ })();
4074
4100
 
4075
4101
  /**
4076
4102
  * Session storage keys used by the auth module
@@ -4472,6 +4498,24 @@ exports.TaskActivityType = void 0;
4472
4498
  TaskActivityType["BulkCompleted"] = "BulkCompleted";
4473
4499
  TaskActivityType["FirstOpened"] = "FirstOpened";
4474
4500
  })(exports.TaskActivityType || (exports.TaskActivityType = {}));
4501
+ /**
4502
+ * Defines how a task assignment is distributed.
4503
+ *
4504
+ * Defaults to {@link TaskAssignmentCriteria.SingleUser} (a direct single-user
4505
+ * assignment) when not specified. The group-based criteria tell Action Center
4506
+ * how to distribute the task across the members of a directory group.
4507
+ */
4508
+ exports.TaskAssignmentCriteria = void 0;
4509
+ (function (TaskAssignmentCriteria) {
4510
+ /** Assigned to a single user, like a direct assignment. */
4511
+ TaskAssignmentCriteria["SingleUser"] = "SingleUser";
4512
+ /** Assigned to the group member with the fewest pending tasks. */
4513
+ TaskAssignmentCriteria["Workload"] = "Workload";
4514
+ /** Assigned to all users in the group. */
4515
+ TaskAssignmentCriteria["AllUsers"] = "AllUsers";
4516
+ /** Assigned in a round-robin manner across the group's members. */
4517
+ TaskAssignmentCriteria["RoundRobin"] = "RoundRobin";
4518
+ })(exports.TaskAssignmentCriteria || (exports.TaskAssignmentCriteria = {}));
4475
4519
 
4476
4520
  /**
4477
4521
  * Base path constants for different services
@@ -4480,6 +4524,7 @@ const ORCHESTRATOR_BASE = 'orchestrator_';
4480
4524
  const PIMS_BASE = 'pims_';
4481
4525
  const DATAFABRIC_BASE = 'datafabric_';
4482
4526
  const IDENTITY_BASE = 'identity_';
4527
+ const LLMOPS_BASE = 'llmopstenant_';
4483
4528
  const INSIGHTS_RTM_BASE = 'insightsrtm_';
4484
4529
 
4485
4530
  /**
@@ -4572,7 +4617,7 @@ const MAESTRO_ENDPOINTS = {
4572
4617
  INSTANCES: {
4573
4618
  GET_ALL: `${PIMS_BASE}/api/v1/instances`,
4574
4619
  GET_BY_ID: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}`,
4575
- GET_EXECUTION_HISTORY: (instanceId) => `${PIMS_BASE}/api/v1/spans/${instanceId}`,
4620
+ GET_ELEMENT_EXECUTIONS: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}/element-executions`,
4576
4621
  GET_BPMN: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}/bpmn`,
4577
4622
  GET_VARIABLES: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}/variables`,
4578
4623
  CANCEL: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}/cancel`,
@@ -4584,6 +4629,9 @@ const MAESTRO_ENDPOINTS = {
4584
4629
  GET_BY_PROCESS: (processKey) => `${PIMS_BASE}/api/v1/incidents/process/${processKey}`,
4585
4630
  GET_BY_INSTANCE: (instanceId) => `${PIMS_BASE}/api/v1/instances/${instanceId}/incidents`,
4586
4631
  },
4632
+ TRACES: {
4633
+ GET_SPANS: (traceId) => `${LLMOPS_BASE}/api/Traces/spans?traceId=${traceId}`,
4634
+ },
4587
4635
  CASES: {
4588
4636
  GET_CASE_JSON: (instanceId) => `${PIMS_BASE}/api/v1/cases/${instanceId}/case-json`,
4589
4637
  GET_ELEMENT_EXECUTIONS: (instanceId) => `${PIMS_BASE}/api/v1/element-executions/case-instances/${instanceId}`,
@@ -4604,6 +4652,8 @@ const MAESTRO_ENDPOINTS = {
4604
4652
  INSTANCE_STATUS_BY_DATE: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/InstanceStatusByDate`,
4605
4653
  /** Top processes ranked by total duration */
4606
4654
  TOP_PROCESSES_BY_DURATION: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/TopProcessesByDuration`,
4655
+ /** Element count by status for agentic instances (process and case) */
4656
+ ELEMENT_COUNT_BY_STATUS: `${INSIGHTS_RTM_BASE}/agenticInstanceStatus/ElementCountByStatus`,
4607
4657
  },
4608
4658
  };
4609
4659
 
@@ -4622,6 +4672,9 @@ const DATA_FABRIC_TENANT_FOLDER_ID = '00000000-0000-0000-0000-000000000000';
4622
4672
  const DATA_FABRIC_ENDPOINTS = {
4623
4673
  ENTITY: {
4624
4674
  GET_ALL: `${DATAFABRIC_BASE}/api/Entity`,
4675
+ // Lists tenant-level and folder-level entities together.
4676
+ // Used by getAll when includeFolderEntities is true.
4677
+ GET_ALL_V2: `${DATAFABRIC_BASE}/api/v2/Entity`,
4625
4678
  GET_ENTITY_RECORDS: (entityId) => `${DATAFABRIC_BASE}/api/EntityService/entity/${entityId}/read`,
4626
4679
  GET_BY_ID: (entityId) => `${DATAFABRIC_BASE}/api/Entity/${entityId}`,
4627
4680
  GET_RECORD_BY_ID: (entityId, recordId) => `${DATAFABRIC_BASE}/api/EntityService/entity/${entityId}/read/${recordId}`,
@@ -4678,6 +4731,105 @@ var ActionCenterEventNames;
4678
4731
  })(ActionCenterEventNames || (ActionCenterEventNames = {}));
4679
4732
 
4680
4733
  const AUTHENTICATION_TIMEOUT = 8000;
4734
+ const ALLOWED_HOST_ORIGINS = new Set([
4735
+ 'https://alpha.uipath.com',
4736
+ 'https://staging.uipath.com',
4737
+ 'https://cloud.uipath.com',
4738
+ ]);
4739
+ /**
4740
+ * Returns true if the origin is a trusted UiPath host that may initiate
4741
+ * token delegation. Mirrors the same allowlist used by ActionCenterTokenManager.
4742
+ */
4743
+ function isValidHostOrigin(origin) {
4744
+ if (!origin)
4745
+ return false;
4746
+ if (ALLOWED_HOST_ORIGINS.has(origin))
4747
+ return true;
4748
+ try {
4749
+ return new URL(origin).hostname === 'localhost';
4750
+ }
4751
+ catch {
4752
+ console.warn('isValidHostOrigin: received a malformed origin URL', origin);
4753
+ return false;
4754
+ }
4755
+ }
4756
+ function isTokenExpired(tokenInfo) {
4757
+ if (!tokenInfo?.expiresAt)
4758
+ return true;
4759
+ return new Date() >= tokenInfo.expiresAt;
4760
+ }
4761
+ /**
4762
+ * The validated host origin when the app is running as a trusted, generic
4763
+ * host-embedded app (`?host=embed&basedomain=<origin>` with an allowlisted
4764
+ * UiPath origin); otherwise null. Shared by TokenManager (to create the
4765
+ * EmbeddedTokenManager) and UiPath init (to seed an empty token so getValidToken
4766
+ * can bootstrap the postMessage token flow), which previously duplicated this
4767
+ * condition inline.
4768
+ */
4769
+ const trustedEmbeddingOrigin = isHostEmbedded && embeddingOrigin && isValidHostOrigin(embeddingOrigin) ? embeddingOrigin : null;
4770
+ /**
4771
+ * Waits for the next window message that satisfies `filter`.
4772
+ * Rejects if the AbortSignal fires before a matching message arrives.
4773
+ */
4774
+ function waitForMessage(filter, signal) {
4775
+ return new Promise((resolve, reject) => {
4776
+ const handler = (event) => {
4777
+ if (!filter(event))
4778
+ return;
4779
+ window.removeEventListener('message', handler);
4780
+ resolve(event);
4781
+ };
4782
+ signal.addEventListener('abort', () => {
4783
+ window.removeEventListener('message', handler);
4784
+ reject(signal.reason);
4785
+ }, { once: true });
4786
+ window.addEventListener('message', handler);
4787
+ });
4788
+ }
4789
+ /**
4790
+ * Sends a token-refresh request to a parent host frame and waits for the
4791
+ * response. Handles timeout, origin filtering, and listener cleanup.
4792
+ *
4793
+ * Both ActionCenterTokenManager and EmbeddedTokenManager delegate to this
4794
+ * function; they differ only in the event names and message shape they use.
4795
+ */
4796
+ function requestHostToken(options) {
4797
+ const { pinnedOrigin, sendRequest, responseEventType, extractToken, onTokenRefreshed } = options;
4798
+ const controller = new AbortController();
4799
+ const cancel = () => controller.abort(new AuthenticationError({
4800
+ message: 'Token refresh cancelled',
4801
+ statusCode: HttpStatus.UNAUTHORIZED,
4802
+ }));
4803
+ const promise = (async () => {
4804
+ const timer = setTimeout(() => controller.abort(new AuthenticationError({
4805
+ message: `Token refresh timed out after ${AUTHENTICATION_TIMEOUT}ms waiting for host response`,
4806
+ statusCode: HttpStatus.UNAUTHORIZED,
4807
+ })), AUTHENTICATION_TIMEOUT);
4808
+ try {
4809
+ // Register listener before sending — avoids any race between send and response
4810
+ const responsePromise = waitForMessage(event => event.origin === pinnedOrigin && event.data?.eventType === responseEventType, controller.signal);
4811
+ sendRequest();
4812
+ const event = await responsePromise;
4813
+ const token = extractToken(event.data);
4814
+ if (!token) {
4815
+ throw new AuthenticationError({
4816
+ message: 'Host responded but did not include a valid access token',
4817
+ statusCode: HttpStatus.UNAUTHORIZED,
4818
+ });
4819
+ }
4820
+ // type: 'secret' intentionally prevents the SDK's internal OAuth refresh path
4821
+ // from running — the host manager owns the refresh cycle via requestHostToken.
4822
+ // This mirrors the same pattern used by ActionCenterTokenManager.
4823
+ onTokenRefreshed({ token: token.accessToken, type: 'secret', expiresAt: token.expiresAt });
4824
+ return token.accessToken;
4825
+ }
4826
+ finally {
4827
+ clearTimeout(timer);
4828
+ }
4829
+ })();
4830
+ return { promise, cancel };
4831
+ }
4832
+
4681
4833
  class ActionCenterTokenManager {
4682
4834
  constructor(config, onTokenRefreshed) {
4683
4835
  this.config = config;
@@ -4686,84 +4838,334 @@ class ActionCenterTokenManager {
4686
4838
  this.refreshPromise = null;
4687
4839
  }
4688
4840
  async refreshAccessToken(tokenInfo) {
4689
- if (!this.isTokenExpired(tokenInfo)) {
4841
+ if (!isTokenExpired(tokenInfo)) {
4690
4842
  return tokenInfo.token;
4691
4843
  }
4692
4844
  if (this.refreshPromise) {
4693
4845
  return this.refreshPromise;
4694
4846
  }
4695
- this.refreshPromise = new Promise((resolve, reject) => {
4696
- const content = {
4847
+ const parentOrigin = this.parentOrigin;
4848
+ if (!parentOrigin) {
4849
+ return Promise.reject(new AuthenticationError({
4850
+ message: 'Cannot refresh token: basedomain query parameter is missing',
4851
+ statusCode: HttpStatus.UNAUTHORIZED,
4852
+ }));
4853
+ }
4854
+ // Guard before requestHostToken registers the inbound listener — an untrusted
4855
+ // basedomain would otherwise leave the listener live for the full timeout window,
4856
+ // accepting a forged TOKENREFRESHED from that origin.
4857
+ if (!isValidHostOrigin(parentOrigin)) {
4858
+ return Promise.reject(new AuthenticationError({
4859
+ message: 'Cannot refresh token: basedomain is not a trusted UiPath host origin',
4860
+ statusCode: HttpStatus.UNAUTHORIZED,
4861
+ }));
4862
+ }
4863
+ const { promise } = requestHostToken({
4864
+ pinnedOrigin: parentOrigin,
4865
+ sendRequest: () => this.sendMessageToParent(ActionCenterEventNames.REFRESHTOKEN, {
4697
4866
  clientId: this.config.clientId,
4698
4867
  scope: this.config.scope,
4699
- };
4700
- this.sendMessageToParent(ActionCenterEventNames.REFRESHTOKEN, content);
4701
- const messageListener = (event) => {
4702
- if (event.origin !== this.parentOrigin)
4703
- return;
4704
- if (event.data?.eventType !== ActionCenterEventNames.TOKENREFRESHED)
4705
- return;
4706
- clearTimeout(timer);
4707
- if (event.data?.content?.token) {
4708
- const { accessToken, expiresAt } = event.data.content.token;
4709
- this.onTokenRefreshed({ token: accessToken, type: 'secret', expiresAt });
4710
- resolve(accessToken);
4711
- }
4712
- else {
4713
- reject(new AuthenticationError({
4714
- message: 'Failed to fetch access token',
4715
- statusCode: HttpStatus.UNAUTHORIZED,
4716
- }));
4717
- }
4718
- this.refreshPromise = null;
4719
- this.cleanup(messageListener);
4720
- };
4721
- const timer = setTimeout(() => {
4722
- reject(new AuthenticationError({
4723
- message: 'Failed to fetch access token',
4724
- statusCode: HttpStatus.UNAUTHORIZED,
4725
- }));
4726
- this.refreshPromise = null;
4727
- this.cleanup(messageListener);
4728
- }, AUTHENTICATION_TIMEOUT);
4729
- window.addEventListener('message', messageListener);
4868
+ }),
4869
+ responseEventType: ActionCenterEventNames.TOKENREFRESHED,
4870
+ extractToken: (data) => {
4871
+ const token = data?.content?.token;
4872
+ if (!token?.accessToken)
4873
+ return undefined;
4874
+ return { accessToken: token.accessToken, expiresAt: token.expiresAt };
4875
+ },
4876
+ onTokenRefreshed: this.onTokenRefreshed,
4730
4877
  });
4731
- return this.refreshPromise;
4732
- }
4733
- isTokenExpired(tokenInfo) {
4734
- if (!tokenInfo?.expiresAt) {
4735
- return true;
4878
+ this.refreshPromise = promise;
4879
+ try {
4880
+ return await this.refreshPromise;
4881
+ }
4882
+ finally {
4883
+ this.refreshPromise = null;
4736
4884
  }
4737
- return new Date() >= tokenInfo.expiresAt;
4738
4885
  }
4739
4886
  sendMessageToParent(eventType, content) {
4740
- if (window.parent && this.isValidOrigin(this.parentOrigin)) {
4887
+ if (window.parent && isValidHostOrigin(this.parentOrigin)) {
4741
4888
  try {
4742
4889
  window.parent.postMessage({ eventType, content }, this.parentOrigin);
4743
4890
  }
4744
4891
  catch (error) {
4745
- console.warn('Failed to send message to Action Center', JSON.stringify(error));
4892
+ console.warn('ActionCenterTokenManager: postMessage to host failed', JSON.stringify(error));
4746
4893
  }
4747
4894
  }
4748
4895
  }
4749
- cleanup(messageListener) {
4750
- window.removeEventListener('message', messageListener);
4896
+ }
4897
+
4898
+ /**
4899
+ * Event names and payload types for the UIP.* postMessage protocol used
4900
+ * when a coded app is embedded inside a UiPath host (e.g. Governance Portal, Insights UI).
4901
+ *
4902
+ * Flow — app-initiated, mirrors the Action Center protocol:
4903
+ * App → Host: UIP.refreshToken (requests a token; carries clientId + scope
4904
+ * so the host knows which OAuth client to use)
4905
+ * Host → App: UIP.tokenRefreshed (delivers the access token)
4906
+ *
4907
+ * Detection: the host signals embedding via `?host=embed&basedomain=<origin>` in
4908
+ * the iframe src URL. No explicit init message from the host is required.
4909
+ */
4910
+ var UipEmbeddedEventNames;
4911
+ (function (UipEmbeddedEventNames) {
4912
+ UipEmbeddedEventNames["REFRESH_TOKEN"] = "UIP.refreshToken";
4913
+ UipEmbeddedEventNames["TOKEN_REFRESHED"] = "UIP.tokenRefreshed";
4914
+ })(UipEmbeddedEventNames || (UipEmbeddedEventNames = {}));
4915
+
4916
+ function parseExpiresAt(raw) {
4917
+ const d = new Date(raw);
4918
+ if (isNaN(d.getTime())) {
4919
+ console.warn('EmbeddedTokenManager: host sent a malformed expiresAt value — treating token as already expired', raw);
4920
+ return new Date(0);
4921
+ }
4922
+ return d;
4923
+ }
4924
+ function extractToken(data) {
4925
+ const token = data?.content?.token;
4926
+ if (!token?.accessToken)
4927
+ return undefined;
4928
+ return { accessToken: token.accessToken, expiresAt: parseExpiresAt(token.expiresAt) };
4929
+ }
4930
+ /**
4931
+ * Handles token delegation for coded apps embedded inside a UiPath host
4932
+ * (e.g. Governance Portal, Insights UI).
4933
+ *
4934
+ * Detection: the host signals embedding via `?host=embed&basedomain=<origin>`
4935
+ * in the iframe src URL. `parentOrigin` is read from `?basedomain=` and validated
4936
+ * against the trusted UiPath host allowlist before this manager is constructed.
4937
+ * This mirrors the mechanism used by ActionCenterTokenManager.
4938
+ *
4939
+ * On every token expiry the SDK sends `UIP.refreshToken` with `clientId` and
4940
+ * `scope`; the host performs silent SSO and responds with `UIP.tokenRefreshed`.
4941
+ */
4942
+ class EmbeddedTokenManager {
4943
+ /**
4944
+ * @param parentOrigin Validated UiPath host origin from the `?basedomain=` query parameter.
4945
+ * @param config SDK configuration — `clientId` and `scope` are required and forwarded
4946
+ * in every `UIP.refreshToken` request so the host knows which OAuth client to use.
4947
+ * @param onTokenRefreshed Called with the refreshed TokenInfo so the caller
4948
+ * can persist it in the execution context.
4949
+ * @throws {AuthenticationError} if `config.clientId` or `config.scope` are not set.
4950
+ */
4951
+ constructor(parentOrigin, config, onTokenRefreshed) {
4952
+ this.parentOrigin = parentOrigin;
4953
+ this.onTokenRefreshed = onTokenRefreshed;
4954
+ this.refreshPromise = null;
4955
+ this.cancelRefresh = null;
4956
+ if (!config.clientId || !config.scope) {
4957
+ throw new ValidationError({
4958
+ message: 'EmbeddedTokenManager requires clientId and scope to be configured for host-delegated authentication',
4959
+ });
4960
+ }
4961
+ this.clientId = config.clientId;
4962
+ this.scope = config.scope;
4751
4963
  }
4752
- isValidOrigin(origin) {
4753
- const ALLOWED_ORIGINS = ['https://alpha.uipath.com', 'https://staging.uipath.com', 'https://cloud.uipath.com'];
4754
- if (!origin) {
4755
- return false;
4964
+ async refreshAccessToken(tokenInfo) {
4965
+ if (!isTokenExpired(tokenInfo)) {
4966
+ return tokenInfo.token;
4756
4967
  }
4757
- if (ALLOWED_ORIGINS.includes(origin)) {
4758
- return true;
4968
+ if (this.refreshPromise) {
4969
+ return this.refreshPromise;
4759
4970
  }
4971
+ const { promise, cancel } = requestHostToken({
4972
+ pinnedOrigin: this.parentOrigin,
4973
+ sendRequest: () => {
4974
+ try {
4975
+ const message = {
4976
+ eventType: UipEmbeddedEventNames.REFRESH_TOKEN,
4977
+ content: { clientId: this.clientId, scope: this.scope },
4978
+ };
4979
+ window.parent.postMessage(message, this.parentOrigin);
4980
+ }
4981
+ catch (error) {
4982
+ console.warn('EmbeddedTokenManager: postMessage to host failed', error);
4983
+ }
4984
+ },
4985
+ responseEventType: UipEmbeddedEventNames.TOKEN_REFRESHED,
4986
+ extractToken,
4987
+ onTokenRefreshed: this.onTokenRefreshed,
4988
+ });
4989
+ this.cancelRefresh = cancel;
4990
+ this.refreshPromise = promise;
4760
4991
  try {
4761
- const url = new URL(origin);
4762
- return url.hostname === 'localhost';
4992
+ return await this.refreshPromise;
4763
4993
  }
4764
- catch {
4765
- return false;
4994
+ finally {
4995
+ this.refreshPromise = null;
4996
+ this.cancelRefresh = null;
4997
+ }
4998
+ }
4999
+ /** Cancels any in-flight token-refresh request. */
5000
+ destroy() {
5001
+ this.cancelRefresh?.();
5002
+ }
5003
+ }
5004
+
5005
+ /**
5006
+ * SDK Telemetry constants.
5007
+ *
5008
+ * Only the SDK's identity (version, service name, role name, …) lives
5009
+ * here. The Application Insights connection string is injected into
5010
+ * `@uipath/core-telemetry` itself at publish time, and the generic attribute
5011
+ * keys (`Version`, `Service`, `CloudOrganizationName`, …) are owned by
5012
+ * `@uipath/core-telemetry` and consumed there — they are not part of the
5013
+ * SDK's public API.
5014
+ */
5015
+ /** SDK version placeholder — patched by the SDK publish workflow. */
5016
+ const SDK_VERSION = '1.4.1';
5017
+ const CLOUD_ROLE_NAME = 'uipath-ts-sdk';
5018
+ const SDK_SERVICE_NAME = 'UiPath.TypeScript.Sdk';
5019
+ const SDK_LOGGER_NAME = 'uipath-ts-sdk-telemetry';
5020
+ const SDK_RUN_EVENT = 'Sdk.Run';
5021
+
5022
+ /**
5023
+ * UiPath TypeScript SDK Telemetry
5024
+ *
5025
+ * Constructs the SDK's own `TelemetryClient` and binds the SDK-local
5026
+ * `track` / `trackEvent` to it. Each consumer of `@uipath/core-telemetry`
5027
+ * does this independently, so events carry their own consumer's identity
5028
+ * and tenant context.
5029
+ */
5030
+ // Keyed by `CLOUD_ROLE_NAME` so every SDK subpath bundle resolves to the
5031
+ // same `TelemetryClient` instance at runtime. A single `initialize(...)`
5032
+ // from the `UiPath` constructor therefore wires up `@track` decorators
5033
+ // across every subpath bundle (`assets`, `feedback`, `tasks`, …).
5034
+ const sdkClient = coreTelemetry.getOrCreateClient(CLOUD_ROLE_NAME);
5035
+ const track = coreTelemetry.createTrack(sdkClient);
5036
+ const trackEvent = coreTelemetry.createTrackEvent(sdkClient);
5037
+ const telemetryClient = {
5038
+ initialize(context) {
5039
+ sdkClient.initialize({
5040
+ sdkVersion: SDK_VERSION,
5041
+ serviceName: SDK_SERVICE_NAME,
5042
+ cloudRoleName: CLOUD_ROLE_NAME,
5043
+ loggerName: SDK_LOGGER_NAME,
5044
+ defaultEventName: SDK_RUN_EVENT,
5045
+ context,
5046
+ });
5047
+ },
5048
+ /**
5049
+ * Sets the authenticated user's id so every subsequently emitted event
5050
+ * carries it as `CloudUserId`.
5051
+ */
5052
+ setUserId(userId) {
5053
+ sdkClient.setUserId(userId);
5054
+ },
5055
+ };
5056
+
5057
+ /**
5058
+ * Base64 encoding/decoding
5059
+ */
5060
+ /**
5061
+ * Encodes a string to base64
5062
+ * @param str - The string to encode
5063
+ * @returns Base64 encoded string
5064
+ */
5065
+ function encodeBase64(str) {
5066
+ // TextEncoder for UTF-8 encoding (works in both browser and Node.js)
5067
+ const encoder = new TextEncoder();
5068
+ const data = encoder.encode(str);
5069
+ // Convert Uint8Array to base64
5070
+ if (isBrowser) {
5071
+ // Browser environment
5072
+ // Convert Uint8Array to binary string then to base64
5073
+ const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
5074
+ return btoa(binaryString);
5075
+ }
5076
+ else {
5077
+ // Node.js environment
5078
+ return Buffer.from(data).toString('base64');
5079
+ }
5080
+ }
5081
+ /**
5082
+ * Decodes a base64 string
5083
+ * @param base64 - The base64 string to decode
5084
+ * @returns Decoded string
5085
+ */
5086
+ function decodeBase64(base64) {
5087
+ let bytes;
5088
+ if (isBrowser) {
5089
+ // Browser environment
5090
+ const binaryString = atob(base64);
5091
+ bytes = new Uint8Array(binaryString.length);
5092
+ for (let i = 0; i < binaryString.length; i++) {
5093
+ bytes[i] = binaryString.charCodeAt(i);
5094
+ }
5095
+ }
5096
+ else {
5097
+ // Node.js environment
5098
+ bytes = new Uint8Array(Buffer.from(base64, 'base64'));
5099
+ }
5100
+ // TextDecoder for UTF-8 decoding (works in both browser and Node.js)
5101
+ const decoder = new TextDecoder();
5102
+ return decoder.decode(bytes);
5103
+ }
5104
+
5105
+ /**
5106
+ * Encodes a folder path for the `X-UIPATH-FolderPath-Encoded` header.
5107
+ *
5108
+ * Orchestrator decodes this header as **base64-encoded UTF-16 LE bytes**
5109
+ * (see `HttpHeadersProviderExtensions.GetDecoded` + `OrganizationUnitProvider`
5110
+ * in the Orchestrator repo, which call `Encoding.Unicode.GetString(...)`).
5111
+ * URL-encoding is NOT what the server expects — it must be base64-of-UTF-16-LE
5112
+ * bytes.
5113
+ *
5114
+ * @param folderPath - The folder path (e.g. 'Shared/Finance')
5115
+ * @returns Base64 string suitable for the `X-UIPATH-FolderPath-Encoded` header
5116
+ */
5117
+ function encodeFolderPathHeader(folderPath) {
5118
+ // Force little-endian regardless of host byte order. `Uint16Array` viewed
5119
+ // as `Uint8Array` would use the host's native order — correct on LE hosts
5120
+ // (x86/ARM-LE) but wrong on BE hosts. `DataView.setUint16(..., true)`
5121
+ // pins LE.
5122
+ const buf = new ArrayBuffer(folderPath.length * 2);
5123
+ const view = new DataView(buf);
5124
+ for (let i = 0; i < folderPath.length; i++) {
5125
+ view.setUint16(i * 2, folderPath.charCodeAt(i), true);
5126
+ }
5127
+ const bytes = new Uint8Array(buf);
5128
+ let binary = '';
5129
+ for (let i = 0; i < bytes.byteLength; i++) {
5130
+ binary += String.fromCharCode(bytes[i]);
5131
+ }
5132
+ // btoa is browser-native; Node 16+ also has it as a global
5133
+ return btoa(binary);
5134
+ }
5135
+
5136
+ /**
5137
+ * JWT decoding helpers — payload inspection only, no signature verification.
5138
+ */
5139
+ const BASE64URL_DASH_RE = /-/g;
5140
+ const BASE64URL_UNDERSCORE_RE = /_/g;
5141
+ /**
5142
+ * Converts a base64url-encoded JWT segment to standard base64 with padding.
5143
+ */
5144
+ function base64UrlToBase64(value) {
5145
+ const base64 = value
5146
+ .replace(BASE64URL_DASH_RE, '+')
5147
+ .replace(BASE64URL_UNDERSCORE_RE, '/');
5148
+ return base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
5149
+ }
5150
+ /**
5151
+ * Extracts the user id (`sub` claim) from a JWT access token payload.
5152
+ * Returns an empty string for opaque (non-JWT) tokens or malformed payloads.
5153
+ *
5154
+ * @param token - The access token to inspect
5155
+ * @returns The user id, or an empty string if it cannot be extracted
5156
+ */
5157
+ function extractUserIdFromToken(token) {
5158
+ try {
5159
+ const payload = token.split('.')[1];
5160
+ if (!payload) {
5161
+ return '';
4766
5162
  }
5163
+ const claims = JSON.parse(decodeBase64(base64UrlToBase64(payload)));
5164
+ const sub = claims['sub'];
5165
+ return typeof sub === 'string' && sub ? sub : '';
5166
+ }
5167
+ catch {
5168
+ return '';
4767
5169
  }
4768
5170
  }
4769
5171
 
@@ -4786,10 +5188,15 @@ class TokenManager {
4786
5188
  this.isOAuth = isOAuth;
4787
5189
  this.refreshPromise = null;
4788
5190
  this.actionCenterTokenManager = null;
5191
+ this.embeddedTokenManager = null;
4789
5192
  if (isInActionCenter) {
4790
5193
  this.actionCenterTokenManager = new ActionCenterTokenManager(config, (tokenInfo) => this.setToken(tokenInfo));
4791
5194
  this.isOAuth = false;
4792
5195
  }
5196
+ else if (trustedEmbeddingOrigin) {
5197
+ this.embeddedTokenManager = new EmbeddedTokenManager(trustedEmbeddingOrigin, config, tokenInfo => this.setToken(tokenInfo));
5198
+ this.isOAuth = false;
5199
+ }
4793
5200
  }
4794
5201
  /**
4795
5202
  * Checks if a token is expired
@@ -4820,6 +5227,10 @@ class TokenManager {
4820
5227
  if (this.actionCenterTokenManager) {
4821
5228
  return await this.actionCenterTokenManager.refreshAccessToken(tokenInfo);
4822
5229
  }
5230
+ // Generic embedded path — active whenever the app is embedded in a UiPath host page
5231
+ if (this.embeddedTokenManager) {
5232
+ return await this.embeddedTokenManager.refreshAccessToken(tokenInfo);
5233
+ }
4823
5234
  // For secret-based tokens, they never expire
4824
5235
  if (tokenInfo.type === 'secret') {
4825
5236
  return tokenInfo.token;
@@ -4958,6 +5369,13 @@ class TokenManager {
4958
5369
  }
4959
5370
  return true;
4960
5371
  }
5372
+ /**
5373
+ * Releases resources held by this instance.
5374
+ * Must be called when the TokenManager is no longer needed to prevent listener leaks.
5375
+ */
5376
+ destroy() {
5377
+ this.embeddedTokenManager?.destroy();
5378
+ }
4961
5379
  /**
4962
5380
  * Clears the current token
4963
5381
  */
@@ -4979,6 +5397,7 @@ class TokenManager {
4979
5397
  */
4980
5398
  _updateExecutionContext(tokenInfo) {
4981
5399
  this.executionContext.set('tokenInfo', tokenInfo);
5400
+ telemetryClient.setUserId(extractUserIdFromToken(tokenInfo.token));
4982
5401
  }
4983
5402
  /**
4984
5403
  * Refreshes the access token using the stored refresh token.
@@ -5008,6 +5427,9 @@ class TokenManager {
5008
5427
  * Internal method to perform the actual token refresh
5009
5428
  */
5010
5429
  async _doRefreshToken() {
5430
+ // Destructure before the type guard — hasOAuthConfig narrows this.config to
5431
+ // { clientId, redirectUri, scope } which does not include BaseConfig fields.
5432
+ const { orgName, baseUrl } = this.config;
5011
5433
  // Check if we're in OAuth flow
5012
5434
  if (!hasOAuthConfig(this.config)) {
5013
5435
  throw new Error('refreshAccessToken is only available in OAuth flow');
@@ -5017,13 +5439,12 @@ class TokenManager {
5017
5439
  if (!tokenInfo?.refreshToken) {
5018
5440
  throw new Error('No refresh token available. User may need to re-authenticate.');
5019
5441
  }
5020
- const orgName = this.config.orgName;
5021
5442
  const body = new URLSearchParams({
5022
5443
  grant_type: 'refresh_token',
5023
5444
  client_id: this.config.clientId,
5024
5445
  refresh_token: tokenInfo.refreshToken
5025
5446
  });
5026
- const response = await fetch(`${this.config.baseUrl}/${orgName}/identity_/connect/token`, {
5447
+ const response = await fetch(`${baseUrl}/${orgName}/identity_/connect/token`, {
5027
5448
  method: 'POST',
5028
5449
  headers: {
5029
5450
  'Content-Type': 'application/x-www-form-urlencoded'
@@ -5483,51 +5904,6 @@ function normalizeBaseUrl(url) {
5483
5904
  return url.endsWith('/') ? url.slice(0, -1) : url;
5484
5905
  }
5485
5906
 
5486
- /**
5487
- * SDK Telemetry constants.
5488
- *
5489
- * Only the SDK's identity (version, service name, role name, …) lives
5490
- * here. The Application Insights connection string is injected into
5491
- * `@uipath/core-telemetry` itself at publish time, and the generic attribute
5492
- * keys (`Version`, `Service`, `CloudOrganizationName`, …) are owned by
5493
- * `@uipath/core-telemetry` and consumed there — they are not part of the
5494
- * SDK's public API.
5495
- */
5496
- /** SDK version placeholder — patched by the SDK publish workflow. */
5497
- const SDK_VERSION = '1.3.11';
5498
- const CLOUD_ROLE_NAME = 'uipath-ts-sdk';
5499
- const SDK_SERVICE_NAME = 'UiPath.TypeScript.Sdk';
5500
- const SDK_LOGGER_NAME = 'uipath-ts-sdk-telemetry';
5501
- const SDK_RUN_EVENT = 'Sdk.Run';
5502
-
5503
- /**
5504
- * UiPath TypeScript SDK Telemetry
5505
- *
5506
- * Constructs the SDK's own `TelemetryClient` and binds the SDK-local
5507
- * `track` / `trackEvent` to it. Each consumer of `@uipath/core-telemetry`
5508
- * does this independently, so events carry their own consumer's identity
5509
- * and tenant context.
5510
- */
5511
- // Keyed by `CLOUD_ROLE_NAME` so every SDK subpath bundle resolves to the
5512
- // same `TelemetryClient` instance at runtime. A single `initialize(...)`
5513
- // from the `UiPath` constructor therefore wires up `@track` decorators
5514
- // across every subpath bundle (`assets`, `feedback`, `tasks`, …).
5515
- const sdkClient = coreTelemetry.getOrCreateClient(CLOUD_ROLE_NAME);
5516
- const track = coreTelemetry.createTrack(sdkClient);
5517
- const trackEvent = coreTelemetry.createTrackEvent(sdkClient);
5518
- const telemetryClient = {
5519
- initialize(context) {
5520
- sdkClient.initialize({
5521
- sdkVersion: SDK_VERSION,
5522
- serviceName: SDK_SERVICE_NAME,
5523
- cloudRoleName: CLOUD_ROLE_NAME,
5524
- loggerName: SDK_LOGGER_NAME,
5525
- defaultEventName: SDK_RUN_EVENT,
5526
- context,
5527
- });
5528
- },
5529
- };
5530
-
5531
5907
  /**
5532
5908
  * SDK Internals Registry - Internal registry for SDK instances
5533
5909
  *
@@ -5637,7 +6013,7 @@ function loadFromMetaTags() {
5637
6013
  return hasAnyValue ? config : null;
5638
6014
  }
5639
6015
 
5640
- var _UiPath_instances, _UiPath_config, _UiPath_authService, _UiPath_initialized, _UiPath_partialConfig, _UiPath_multiLogin, _UiPath_metaFolderKey, _UiPath_initializeWithConfig, _UiPath_loadConfig;
6016
+ var _UiPath_instances, _UiPath_config, _UiPath_authService, _UiPath_initialized, _UiPath_partialConfig, _UiPath_multiLogin, _UiPath_metaFolderKey, _UiPath_metaOrgId, _UiPath_metaTenantId, _UiPath_initializeWithConfig, _UiPath_loadConfig;
5641
6017
  /**
5642
6018
  * UiPath - Core SDK class for authentication and configuration management.
5643
6019
  *
@@ -5682,9 +6058,18 @@ let UiPath$1 = class UiPath {
5682
6058
  // deployments). Not accepted via the public constructor; lives here so the
5683
6059
  // SDK can flow it through to BaseService.config without polluting BaseConfig.
5684
6060
  _UiPath_metaFolderKey.set(this, void 0);
6061
+ // Org/tenant ids captured from the meta tags before the constructor config
6062
+ // is merged in. The `uipath:org-name`/`uipath:tenant-name` meta tags always
6063
+ // carry org/tenant *ids* in coded-app deployments, whereas a
6064
+ // constructor-supplied `orgName`/`tenantName` may be actual names — so the
6065
+ // telemetry ids must be read from the meta tags.
6066
+ _UiPath_metaOrgId.set(this, void 0);
6067
+ _UiPath_metaTenantId.set(this, void 0);
5685
6068
  // Load configuration from meta tags
5686
6069
  const configFromMetaTags = loadFromMetaTags();
5687
6070
  __classPrivateFieldSet(this, _UiPath_metaFolderKey, configFromMetaTags?.folderKey, "f");
6071
+ __classPrivateFieldSet(this, _UiPath_metaOrgId, configFromMetaTags?.orgName, "f");
6072
+ __classPrivateFieldSet(this, _UiPath_metaTenantId, configFromMetaTags?.tenantName, "f");
5688
6073
  // Merge configuration: constructor config overrides meta tags
5689
6074
  const mergedConfig = config ? { ...configFromMetaTags, ...config } : configFromMetaTags;
5690
6075
  if (mergedConfig && isCompleteConfig(mergedConfig)) {
@@ -5791,6 +6176,13 @@ let UiPath$1 = class UiPath {
5791
6176
  getToken() {
5792
6177
  return __classPrivateFieldGet(this, _UiPath_authService, "f")?.getToken();
5793
6178
  }
6179
+ /**
6180
+ * Releases resources held by this SDK instance.
6181
+ * Cancels any in-flight token-refresh request. Call this when the coded app is unmounted.
6182
+ */
6183
+ destroy() {
6184
+ __classPrivateFieldGet(this, _UiPath_authService, "f")?.getTokenManager()?.destroy();
6185
+ }
5794
6186
  /**
5795
6187
  * Logout from the SDK, clearing all authentication state.
5796
6188
  * After calling this method, the user will need to re-initialize to authenticate again.
@@ -5813,7 +6205,7 @@ let UiPath$1 = class UiPath {
5813
6205
  __classPrivateFieldGet(this, _UiPath_authService, "f")?.updateToken(tokenInfo);
5814
6206
  }
5815
6207
  };
5816
- _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap(), _UiPath_partialConfig = new WeakMap(), _UiPath_multiLogin = new WeakMap(), _UiPath_metaFolderKey = new WeakMap(), _UiPath_instances = new WeakSet(), _UiPath_initializeWithConfig = function _UiPath_initializeWithConfig(config) {
6208
+ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap(), _UiPath_partialConfig = new WeakMap(), _UiPath_multiLogin = new WeakMap(), _UiPath_metaFolderKey = new WeakMap(), _UiPath_metaOrgId = new WeakMap(), _UiPath_metaTenantId = new WeakMap(), _UiPath_instances = new WeakSet(), _UiPath_initializeWithConfig = function _UiPath_initializeWithConfig(config) {
5817
6209
  // Validate and normalize the configuration
5818
6210
  validateConfig(config);
5819
6211
  const hasSecretAuth = hasSecretConfig(config);
@@ -5849,9 +6241,11 @@ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_ini
5849
6241
  orgName: internalConfig.orgName,
5850
6242
  tenantName: internalConfig.tenantName
5851
6243
  };
5852
- // Initialize telemetry with SDK configuration
6244
+ // Initialize telemetry with SDK configuration.
5853
6245
  telemetryClient.initialize({
5854
6246
  baseUrl: config.baseUrl,
6247
+ orgId: __classPrivateFieldGet(this, _UiPath_metaOrgId, "f"),
6248
+ tenantId: __classPrivateFieldGet(this, _UiPath_metaTenantId, "f"),
5855
6249
  orgName: config.orgName,
5856
6250
  tenantName: config.tenantName,
5857
6251
  clientId: hasOAuthAuth ? config.clientId : undefined,
@@ -5859,10 +6253,12 @@ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_ini
5859
6253
  });
5860
6254
  // Track SDK initialization
5861
6255
  trackEvent('Sdk.Auth');
5862
- /** Auto-initialize for secret-based auth
5863
- * When viewed in Action Center, initialize tokenInfo with empty token. When an sdk call is made Action Center passes the token to sdk.
6256
+ /** Auto-initialize for secret-based auth, Action Center, and generic host-embedded apps.
6257
+ * When viewed in Action Center or embedded in a UiPath host frame via the UIP protocol,
6258
+ * initialize tokenInfo with an empty token so getValidToken() can bootstrap via postMessage.
6259
+ * When an sdk call is made, the host passes the token to the sdk.
5864
6260
  */
5865
- if (hasSecretAuth || isInActionCenter) {
6261
+ if (hasSecretAuth || isInActionCenter || trustedEmbeddingOrigin) {
5866
6262
  __classPrivateFieldGet(this, _UiPath_authService, "f").authenticateWithSecret(config.secret ?? '');
5867
6263
  __classPrivateFieldSet(this, _UiPath_initialized, true, "f");
5868
6264
  }
@@ -5870,6 +6266,8 @@ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_ini
5870
6266
  // Load from meta tags
5871
6267
  const metaConfig = loadFromMetaTags();
5872
6268
  __classPrivateFieldSet(this, _UiPath_metaFolderKey, metaConfig?.folderKey, "f");
6269
+ __classPrivateFieldSet(this, _UiPath_metaOrgId, metaConfig?.orgName, "f");
6270
+ __classPrivateFieldSet(this, _UiPath_metaTenantId, metaConfig?.tenantName, "f");
5873
6271
  // Merge with any partial config from constructor (constructor overrides meta tags)
5874
6272
  const merged = { ...metaConfig, ...__classPrivateFieldGet(this, _UiPath_partialConfig, "f") };
5875
6273
  if (!isCompleteConfig(merged)) {
@@ -6339,54 +6737,6 @@ function processODataArrayResponse(oDataResponse, successData) {
6339
6737
  };
6340
6738
  }
6341
6739
 
6342
- /**
6343
- * Base64 encoding/decoding
6344
- */
6345
- /**
6346
- * Encodes a string to base64
6347
- * @param str - The string to encode
6348
- * @returns Base64 encoded string
6349
- */
6350
- function encodeBase64(str) {
6351
- // TextEncoder for UTF-8 encoding (works in both browser and Node.js)
6352
- const encoder = new TextEncoder();
6353
- const data = encoder.encode(str);
6354
- // Convert Uint8Array to base64
6355
- if (isBrowser) {
6356
- // Browser environment
6357
- // Convert Uint8Array to binary string then to base64
6358
- const binaryString = Array.from(data, byte => String.fromCharCode(byte)).join('');
6359
- return btoa(binaryString);
6360
- }
6361
- else {
6362
- // Node.js environment
6363
- return Buffer.from(data).toString('base64');
6364
- }
6365
- }
6366
- /**
6367
- * Decodes a base64 string
6368
- * @param base64 - The base64 string to decode
6369
- * @returns Decoded string
6370
- */
6371
- function decodeBase64(base64) {
6372
- let bytes;
6373
- if (isBrowser) {
6374
- // Browser environment
6375
- const binaryString = atob(base64);
6376
- bytes = new Uint8Array(binaryString.length);
6377
- for (let i = 0; i < binaryString.length; i++) {
6378
- bytes[i] = binaryString.charCodeAt(i);
6379
- }
6380
- }
6381
- else {
6382
- // Node.js environment
6383
- bytes = new Uint8Array(Buffer.from(base64, 'base64'));
6384
- }
6385
- // TextDecoder for UTF-8 decoding (works in both browser and Node.js)
6386
- const decoder = new TextDecoder();
6387
- return decoder.decode(bytes);
6388
- }
6389
-
6390
6740
  /**
6391
6741
  * PaginationManager handles the conversion between uniform cursor-based pagination
6392
6742
  * and the specific pagination type for each service
@@ -7134,12 +7484,18 @@ class PaginationHelpers {
7134
7484
  * @returns Promise resolving to a paginated result
7135
7485
  */
7136
7486
  static async getAllPaginated(params) {
7137
- const { serviceAccess, getEndpoint, folderId, headers: providedHeaders, paginationParams, additionalParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
7487
+ const { serviceAccess, getEndpoint, folderId, headers: providedHeaders, paginationParams, additionalParams, queryParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
7138
7488
  const endpoint = getEndpoint(folderId);
7139
7489
  const headers = providedHeaders ?? (folderId ? createHeaders({ [FOLDER_ID]: folderId }) : {});
7490
+ // On POST, the caller's options go in the body; queryParams stays in the URL.
7491
+ // On GET, everything is URL — queryParams merges with additionalParams.
7492
+ const isPost = method === HTTP_METHODS.POST;
7493
+ const requestSpec = isPost
7494
+ ? { body: additionalParams, params: queryParams }
7495
+ : { params: { ...additionalParams, ...queryParams } };
7140
7496
  const paginatedResponse = await serviceAccess.requestWithPagination(method, endpoint, paginationParams, {
7141
7497
  headers,
7142
- params: additionalParams,
7498
+ ...requestSpec,
7143
7499
  pagination: {
7144
7500
  paginationType: options.paginationType || PaginationType.OFFSET,
7145
7501
  itemsField: options.itemsField || DEFAULT_ITEMS_FIELD,
@@ -7164,7 +7520,7 @@ class PaginationHelpers {
7164
7520
  * @returns Promise resolving to an object with data and totalCount
7165
7521
  */
7166
7522
  static async getAllNonPaginated(params) {
7167
- const { serviceAccess, getAllEndpoint, getByFolderEndpoint, folderId, headers: providedHeaders, additionalParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
7523
+ const { serviceAccess, getAllEndpoint, getByFolderEndpoint, folderId, headers: providedHeaders, additionalParams, queryParams, transformFn, method = HTTP_METHODS.GET, options = {} } = params;
7168
7524
  // Set default field names
7169
7525
  const itemsField = options.itemsField || DEFAULT_ITEMS_FIELD;
7170
7526
  const totalCountField = options.totalCountField || DEFAULT_TOTAL_COUNT_FIELD;
@@ -7174,17 +7530,18 @@ class PaginationHelpers {
7174
7530
  // Make the API call based on method
7175
7531
  let response;
7176
7532
  if (method === HTTP_METHODS.POST) {
7177
- response = await serviceAccess.post(endpoint, additionalParams, { headers });
7533
+ response = await serviceAccess.post(endpoint, additionalParams, { headers, params: queryParams });
7178
7534
  }
7179
7535
  else {
7180
7536
  response = await serviceAccess.get(endpoint, {
7181
- params: additionalParams,
7537
+ params: { ...additionalParams, ...queryParams },
7182
7538
  headers
7183
7539
  });
7184
7540
  }
7185
7541
  // Extract and transform items from response
7186
- // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
7187
- const rawItems = Array.isArray(response.data) ? response.data : response.data?.[itemsField];
7542
+ // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N }).
7543
+ // itemsField may be a dotted path (e.g. 'data.agents') for nested envelopes.
7544
+ const rawItems = Array.isArray(response.data) ? response.data : resolveNestedField(response.data, itemsField);
7188
7545
  const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
7189
7546
  const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
7190
7547
  // Parse items - automatically handle JSON string responses
@@ -7230,8 +7587,9 @@ class PaginationHelpers {
7230
7587
  getEndpoint: config.getEndpoint,
7231
7588
  folderId,
7232
7589
  headers: config.headers,
7233
- paginationParams: cursor ? { cursor, pageSize } : jumpToPage ? { jumpToPage, pageSize } : { pageSize },
7590
+ paginationParams: cursor ? { cursor, pageSize } : jumpToPage !== undefined ? { jumpToPage, pageSize } : { pageSize },
7234
7591
  additionalParams: prefixedOptions,
7592
+ queryParams: config.queryParams,
7235
7593
  transformFn: config.transformFn,
7236
7594
  method: config.method,
7237
7595
  options: {
@@ -7249,6 +7607,7 @@ class PaginationHelpers {
7249
7607
  folderId,
7250
7608
  headers: config.headers,
7251
7609
  additionalParams: prefixedOptions,
7610
+ queryParams: config.queryParams,
7252
7611
  transformFn: config.transformFn,
7253
7612
  method: config.method,
7254
7613
  options: {
@@ -7385,18 +7744,17 @@ class BaseService {
7385
7744
  const params = this.validateAndPreparePaginationParams(paginationType, paginationOptions);
7386
7745
  // Prepare request parameters based on pagination type
7387
7746
  const requestParams = this.preparePaginationRequestParams(paginationType, params, options.pagination);
7388
- // For POST requests, merge pagination params into body and set params to undefined; for GET, use query params
7747
+ // Route pagination state to wherever the API expects it (body for POST, URL for GET).
7748
+ // Caller-supplied options.body / options.params are respected as-is — the api-client
7749
+ // already handles params (URL) and body (request body) independently for every method.
7389
7750
  if (method.toUpperCase() === 'POST') {
7390
7751
  const existingBody = (options.body && typeof options.body === 'object') ? options.body : {};
7391
7752
  options.body = {
7392
7753
  ...existingBody,
7393
- ...options.params,
7394
7754
  ...requestParams
7395
7755
  };
7396
- options.params = undefined;
7397
7756
  }
7398
7757
  else {
7399
- // Merge pagination parameters with existing parameters
7400
7758
  options.params = {
7401
7759
  ...options.params,
7402
7760
  ...requestParams
@@ -7433,6 +7791,8 @@ class BaseService {
7433
7791
  // When true (default), converts pageNumber to a skip/offset value (e.g., page 3 with pageSize 10 → skip 20).
7434
7792
  // When false, passes pageNumber directly as the offset param — used by APIs that accept a page number instead of a record offset.
7435
7793
  const convertToSkip = paginationParams?.convertToSkip ?? true;
7794
+ // When true, sends pageNumber - 1 (for 0-based APIs). Default false (1-based).
7795
+ const zeroBased = paginationParams?.zeroBased ?? false;
7436
7796
  requestParams[pageSizeParam] = limitedPageSize;
7437
7797
  if (convertToSkip) {
7438
7798
  if (params.pageNumber && params.pageNumber > 1) {
@@ -7440,7 +7800,8 @@ class BaseService {
7440
7800
  }
7441
7801
  }
7442
7802
  else {
7443
- requestParams[offsetParam] = params.pageNumber || 1;
7803
+ const sdkPageNumber = params.pageNumber || 1;
7804
+ requestParams[offsetParam] = zeroBased ? sdkPageNumber - 1 : sdkPageNumber;
7444
7805
  }
7445
7806
  {
7446
7807
  requestParams[countParam] = true;
@@ -7469,8 +7830,9 @@ class BaseService {
7469
7830
  const totalCountField = fields.totalCountField || 'totalRecordCount';
7470
7831
  const continuationTokenField = fields.continuationTokenField || 'continuationToken';
7471
7832
  // Extract items and metadata
7472
- // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N })
7473
- const items = Array.isArray(response.data) ? response.data : (response.data[itemsField] || []);
7833
+ // Handle both plain array responses and envelope responses ({ value: [...], totalRecordCount: N }).
7834
+ // itemsField may be a dotted path (e.g. 'data.agents') for nested envelopes.
7835
+ const items = Array.isArray(response.data) ? response.data : (resolveNestedField(response.data, itemsField) || []);
7474
7836
  const rawTotalCount = Array.isArray(response.data) ? undefined : resolveNestedField(response.data, totalCountField);
7475
7837
  const totalCount = typeof rawTotalCount === 'number' ? rawTotalCount : undefined;
7476
7838
  const continuationToken = response.data[continuationTokenField];
@@ -7553,12 +7915,12 @@ function createEntityMethods(entityData, service) {
7553
7915
  throw new Error('Entity ID is undefined');
7554
7916
  return service.deleteRecordsById(entityData.id, recordIds, options);
7555
7917
  },
7556
- async deleteRecord(recordId) {
7918
+ async deleteRecord(recordId, options) {
7557
7919
  if (!entityData.id)
7558
7920
  throw new Error('Entity ID is undefined');
7559
7921
  if (!recordId)
7560
7922
  throw new Error('Record ID is undefined');
7561
- return service.deleteRecordById(entityData.id, recordId);
7923
+ return service.deleteRecordById(entityData.id, recordId, options);
7562
7924
  },
7563
7925
  async getAllRecords(options) {
7564
7926
  if (!entityData.id)
@@ -7572,30 +7934,30 @@ function createEntityMethods(entityData, service) {
7572
7934
  throw new Error('Record ID is undefined');
7573
7935
  return service.getRecordById(entityData.id, recordId, options);
7574
7936
  },
7575
- async downloadAttachment(recordId, fieldName) {
7937
+ async downloadAttachment(recordId, fieldName, options) {
7576
7938
  if (!entityData.id)
7577
7939
  throw new Error('Entity ID is undefined');
7578
- return service.downloadAttachment(entityData.id, recordId, fieldName);
7940
+ return service.downloadAttachment(entityData.id, recordId, fieldName, options);
7579
7941
  },
7580
7942
  async uploadAttachment(recordId, fieldName, file, options) {
7581
7943
  if (!entityData.id)
7582
7944
  throw new Error('Entity ID is undefined');
7583
7945
  return service.uploadAttachment(entityData.id, recordId, fieldName, file, options);
7584
7946
  },
7585
- async deleteAttachment(recordId, fieldName) {
7947
+ async deleteAttachment(recordId, fieldName, options) {
7586
7948
  if (!entityData.id)
7587
7949
  throw new Error('Entity ID is undefined');
7588
- return service.deleteAttachment(entityData.id, recordId, fieldName);
7950
+ return service.deleteAttachment(entityData.id, recordId, fieldName, options);
7589
7951
  },
7590
7952
  async queryRecords(options) {
7591
7953
  if (!entityData.id)
7592
7954
  throw new Error('Entity ID is undefined');
7593
7955
  return service.queryRecordsById(entityData.id, options);
7594
7956
  },
7595
- async importRecords(file) {
7957
+ async importRecords(file, options) {
7596
7958
  if (!entityData.id)
7597
7959
  throw new Error('Entity ID is undefined');
7598
- return service.importRecordsById(entityData.id, file);
7960
+ return service.importRecordsById(entityData.id, file, options);
7599
7961
  },
7600
7962
  async insert(data, options) {
7601
7963
  return this.insertRecord(data, options);
@@ -7606,10 +7968,10 @@ function createEntityMethods(entityData, service) {
7606
7968
  async getRecords(options) {
7607
7969
  return this.getAllRecords(options);
7608
7970
  },
7609
- async delete() {
7971
+ async delete(options) {
7610
7972
  if (!entityData.id)
7611
7973
  throw new Error('Entity ID is undefined');
7612
- return service.deleteById(entityData.id);
7974
+ return service.deleteById(entityData.id, options);
7613
7975
  },
7614
7976
  async update(options) {
7615
7977
  if (!entityData.id)
@@ -7806,6 +8168,14 @@ var SqlFieldType;
7806
8168
  SqlFieldType["MULTILINE"] = "MULTILINE";
7807
8169
  })(SqlFieldType || (SqlFieldType = {}));
7808
8170
 
8171
+ /**
8172
+ * Numeric type IDs that pair with {@link EntityType} on reference payloads
8173
+ * (entityType + entityTypeId travel together in `referenceEntity` /
8174
+ * `referenceChoiceSet` bodies on cross-folder schema upserts).
8175
+ */
8176
+ const ENTITY_TYPE_IDS = {
8177
+ [exports.EntityType.ChoiceSet]: 1,
8178
+ };
7809
8179
  /**
7810
8180
  * Maps fields for Entities
7811
8181
  */
@@ -7939,6 +8309,7 @@ class EntityService extends BaseService {
7939
8309
  * Gets entity metadata by entity ID with attached operation methods
7940
8310
  *
7941
8311
  * @param id - UUID of the entity
8312
+ * @param options - Optional {@link EntityGetByIdOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
7942
8313
  * @returns Promise resolving to entity metadata with schema information and operation methods
7943
8314
  *
7944
8315
  * @example
@@ -7948,6 +8319,9 @@ class EntityService extends BaseService {
7948
8319
  * const entities = new Entities(sdk);
7949
8320
  * const entity = await entities.getById("<entityId>");
7950
8321
  *
8322
+ * // Folder-scoped: pass the entity's folder key
8323
+ * const folderEntity = await entities.getById("<entityId>", { folderKey: "<folderKey>" });
8324
+ *
7951
8325
  * // Call operations directly on the entity
7952
8326
  * const records = await entity.getAllRecords();
7953
8327
  *
@@ -7961,9 +8335,9 @@ class EntityService extends BaseService {
7961
8335
  * ]);
7962
8336
  * ```
7963
8337
  */
7964
- async getById(id) {
8338
+ async getById(id, options) {
7965
8339
  // Get entity metadata
7966
- const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_BY_ID(id));
8340
+ const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_BY_ID(id), { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
7967
8341
  // Apply EntityMap transformations
7968
8342
  const metadata = transformData(response.data, EntityMap);
7969
8343
  // Transform metadata with field mappers
@@ -7975,7 +8349,7 @@ class EntityService extends BaseService {
7975
8349
  * Gets entity records by entity ID
7976
8350
  *
7977
8351
  * @param entityId - UUID of the entity
7978
- * @param options - Query options including expansionLevel and pagination options
8352
+ * @param options - Query options including expansionLevel and pagination options The `folderKey` property is **experimental**.
7979
8353
  * @returns Promise resolving to an array of entity records or paginated response
7980
8354
  *
7981
8355
  * @example
@@ -8003,12 +8377,20 @@ class EntityService extends BaseService {
8003
8377
  * cursor: paginatedResponse.nextCursor,
8004
8378
  * expansionLevel: 1
8005
8379
  * });
8380
+ *
8381
+ * // Folder-scoped entity: pass the entity's folder key
8382
+ * const records = await entities.getAllRecords("<entityId>", { folderKey: "<folderKey>" });
8006
8383
  * ```
8007
8384
  */
8008
8385
  async getAllRecords(entityId, options) {
8386
+ // folderKey is header-only — destructure it out so PaginationHelpers doesn't serialise it
8387
+ // into the query string as $folderKey.
8388
+ const { folderKey, ...rest } = options ?? {};
8389
+ const downstreamOptions = options === undefined ? undefined : rest;
8009
8390
  return PaginationHelpers.getAll({
8010
8391
  serviceAccess: this.createPaginationServiceAccess(),
8011
8392
  getEndpoint: () => DATA_FABRIC_ENDPOINTS.ENTITY.GET_ENTITY_RECORDS(entityId),
8393
+ headers: createHeaders({ [FOLDER_KEY]: folderKey }),
8012
8394
  pagination: {
8013
8395
  paginationType: PaginationType.OFFSET,
8014
8396
  itemsField: ENTITY_PAGINATION.ITEMS_FIELD,
@@ -8020,14 +8402,14 @@ class EntityService extends BaseService {
8020
8402
  }
8021
8403
  },
8022
8404
  excludeFromPrefix: ['expansionLevel'] // Don't add ODATA prefix to expansionLevel
8023
- }, options);
8405
+ }, downstreamOptions);
8024
8406
  }
8025
8407
  /**
8026
8408
  * Gets a single entity record by entity ID and record ID
8027
8409
  *
8028
8410
  * @param entityId - UUID of the entity
8029
8411
  * @param recordId - UUID of the record
8030
- * @param options - Query options including expansionLevel
8412
+ * @param options - Query options including `expansionLevel` and `folderKey` The `folderKey` property is **experimental**.
8031
8413
  * @returns Promise resolving to the entity record
8032
8414
  *
8033
8415
  * @example
@@ -8039,13 +8421,18 @@ class EntityService extends BaseService {
8039
8421
  * const record = await sdk.entities.getRecordById(<entityId>, <recordId>, {
8040
8422
  * expansionLevel: 1
8041
8423
  * });
8424
+ *
8425
+ * // Folder-scoped entity: pass the entity's folder key
8426
+ * const record = await sdk.entities.getRecordById(<entityId>, <recordId>, {
8427
+ * folderKey: "<folderKey>"
8428
+ * });
8042
8429
  * ```
8043
8430
  */
8044
8431
  async getRecordById(entityId, recordId, options = {}) {
8045
8432
  const params = createParams({
8046
8433
  expansionLevel: options.expansionLevel
8047
8434
  });
8048
- const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_RECORD_BY_ID(entityId, recordId), { params });
8435
+ const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_RECORD_BY_ID(entityId, recordId), { params, headers: createHeaders({ [FOLDER_KEY]: options.folderKey }) });
8049
8436
  return response.data;
8050
8437
  }
8051
8438
  /**
@@ -8053,7 +8440,7 @@ class EntityService extends BaseService {
8053
8440
  *
8054
8441
  * @param entityId - UUID of the entity
8055
8442
  * @param data - Record to insert
8056
- * @param options - Insert options
8443
+ * @param options - Insert options The `folderKey` property is **experimental**.
8057
8444
  * @returns Promise resolving to the inserted record with generated record ID
8058
8445
  *
8059
8446
  * @example
@@ -8069,6 +8456,11 @@ class EntityService extends BaseService {
8069
8456
  * const result = await entities.insertRecordById("<entityId>", { name: "John", age: 30 }, {
8070
8457
  * expansionLevel: 1
8071
8458
  * });
8459
+ *
8460
+ * // Folder-scoped entity: pass the entity's folder key
8461
+ * await entities.insertRecordById("<entityId>", { name: "John", age: 30 }, {
8462
+ * folderKey: "<folderKey>"
8463
+ * });
8072
8464
  * ```
8073
8465
  */
8074
8466
  async insertRecordById(id, data, options = {}) {
@@ -8077,7 +8469,7 @@ class EntityService extends BaseService {
8077
8469
  });
8078
8470
  const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.INSERT_BY_ID(id), data, {
8079
8471
  params,
8080
- ...options
8472
+ headers: createHeaders({ [FOLDER_KEY]: options.folderKey }),
8081
8473
  });
8082
8474
  return response.data;
8083
8475
  }
@@ -8086,7 +8478,7 @@ class EntityService extends BaseService {
8086
8478
  *
8087
8479
  * @param entityId - UUID of the entity
8088
8480
  * @param data - Array of records to insert
8089
- * @param options - Insert options
8481
+ * @param options - Insert options The `folderKey` property is **experimental**.
8090
8482
  * @returns Promise resolving to insert response
8091
8483
  *
8092
8484
  * @example
@@ -8109,6 +8501,12 @@ class EntityService extends BaseService {
8109
8501
  * expansionLevel: 1,
8110
8502
  * failOnFirst: true
8111
8503
  * });
8504
+ *
8505
+ * // Folder-scoped entity: pass the entity's folder key
8506
+ * await entities.insertRecordsById("<entityId>", [
8507
+ * { name: "John", age: 30 },
8508
+ * { name: "Jane", age: 25 }
8509
+ * ], { folderKey: "<folderKey>" });
8112
8510
  * ```
8113
8511
  */
8114
8512
  async insertRecordsById(id, data, options = {}) {
@@ -8118,7 +8516,7 @@ class EntityService extends BaseService {
8118
8516
  });
8119
8517
  const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.BATCH_INSERT_BY_ID(id), data, {
8120
8518
  params,
8121
- ...options
8519
+ headers: createHeaders({ [FOLDER_KEY]: options.folderKey }),
8122
8520
  });
8123
8521
  return response.data;
8124
8522
  }
@@ -8128,7 +8526,7 @@ class EntityService extends BaseService {
8128
8526
  * @param entityId - UUID of the entity
8129
8527
  * @param recordId - UUID of the record to update
8130
8528
  * @param data - Key-value pairs of fields to update
8131
- * @param options - Update options
8529
+ * @param options - Update options The `folderKey` property is **experimental**.
8132
8530
  * @returns Promise resolving to the updated record
8133
8531
  *
8134
8532
  * @example
@@ -8144,6 +8542,11 @@ class EntityService extends BaseService {
8144
8542
  * const result = await entities.updateRecordById("<entityId>", "<recordId>", { name: "John Updated", age: 31 }, {
8145
8543
  * expansionLevel: 1
8146
8544
  * });
8545
+ *
8546
+ * // Folder-scoped entity: pass the entity's folder key
8547
+ * await entities.updateRecordById("<entityId>", "<recordId>", { name: "John Updated" }, {
8548
+ * folderKey: "<folderKey>"
8549
+ * });
8147
8550
  * ```
8148
8551
  */
8149
8552
  async updateRecordById(entityId, recordId, data, options = {}) {
@@ -8152,7 +8555,7 @@ class EntityService extends BaseService {
8152
8555
  });
8153
8556
  const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPDATE_RECORD_BY_ID(entityId, recordId), data, {
8154
8557
  params,
8155
- ...options
8558
+ headers: createHeaders({ [FOLDER_KEY]: options.folderKey }),
8156
8559
  });
8157
8560
  return response.data;
8158
8561
  }
@@ -8162,7 +8565,7 @@ class EntityService extends BaseService {
8162
8565
  * @param entityId - UUID of the entity
8163
8566
  * @param data - Array of records to update. Each record MUST contain the record Id,
8164
8567
  * otherwise the update will fail.
8165
- * @param options - Update options
8568
+ * @param options - Update options The `folderKey` property is **experimental**.
8166
8569
  * @returns Promise resolving to update response
8167
8570
  *
8168
8571
  * @example
@@ -8185,6 +8588,11 @@ class EntityService extends BaseService {
8185
8588
  * expansionLevel: 1,
8186
8589
  * failOnFirst: true
8187
8590
  * });
8591
+ *
8592
+ * // Folder-scoped entity: pass the entity's folder key
8593
+ * await entities.updateRecordsById("<entityId>", [
8594
+ * { Id: "123", name: "John Updated" }
8595
+ * ], { folderKey: "<folderKey>" });
8188
8596
  * ```
8189
8597
  */
8190
8598
  async updateRecordsById(id, data, options = {}) {
@@ -8194,7 +8602,7 @@ class EntityService extends BaseService {
8194
8602
  });
8195
8603
  const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPDATE_BY_ID(id), data, {
8196
8604
  params,
8197
- ...options
8605
+ headers: createHeaders({ [FOLDER_KEY]: options.folderKey }),
8198
8606
  });
8199
8607
  return response.data;
8200
8608
  }
@@ -8205,7 +8613,7 @@ class EntityService extends BaseService {
8205
8613
  *
8206
8614
  * @param entityId - UUID of the entity
8207
8615
  * @param recordIds - Array of record UUIDs to delete
8208
- * @param options - Delete options
8616
+ * @param options - Delete options The `folderKey` property is **experimental**.
8209
8617
  * @returns Promise resolving to delete response
8210
8618
  *
8211
8619
  * @example
@@ -8218,6 +8626,11 @@ class EntityService extends BaseService {
8218
8626
  * const result = await entities.deleteRecordsById("<entityId>", [
8219
8627
  * "<recordId-1>", "<recordId-2>"
8220
8628
  * ]);
8629
+ *
8630
+ * // Folder-scoped entity: pass the entity's folder key
8631
+ * await entities.deleteRecordsById("<entityId>", [
8632
+ * "<recordId-1>", "<recordId-2>"
8633
+ * ], { folderKey: "<folderKey>" });
8221
8634
  * ```
8222
8635
  */
8223
8636
  async deleteRecordsById(id, recordIds, options = {}) {
@@ -8226,7 +8639,7 @@ class EntityService extends BaseService {
8226
8639
  });
8227
8640
  const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE_BY_ID(id), recordIds, {
8228
8641
  params,
8229
- ...options
8642
+ headers: createHeaders({ [FOLDER_KEY]: options.folderKey }),
8230
8643
  });
8231
8644
  return response.data;
8232
8645
  }
@@ -8238,6 +8651,7 @@ class EntityService extends BaseService {
8238
8651
  *
8239
8652
  * @param entityId - UUID of the entity
8240
8653
  * @param recordId - UUID of the record to delete
8654
+ * @param options - Optional {@link EntityDeleteRecordByIdOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8241
8655
  * @returns Promise resolving to void on success
8242
8656
  * @example
8243
8657
  * ```typescript
@@ -8246,14 +8660,23 @@ class EntityService extends BaseService {
8246
8660
  * const entities = new Entities(sdk);
8247
8661
  *
8248
8662
  * await entities.deleteRecordById("<entityId>", "<recordId>");
8663
+ *
8664
+ * // Folder-scoped: pass the entity's folder key
8665
+ * await entities.deleteRecordById("<entityId>", "<recordId>", { folderKey: "<folderKey>" });
8249
8666
  * ```
8250
8667
  */
8251
- async deleteRecordById(entityId, recordId) {
8252
- await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE_RECORD_BY_ID(entityId, recordId));
8668
+ async deleteRecordById(entityId, recordId, options) {
8669
+ await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE_RECORD_BY_ID(entityId, recordId), { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
8253
8670
  }
8254
8671
  /**
8255
- * Gets all entities in the system
8672
+ * Gets entities in the tenant.
8256
8673
  *
8674
+ * Three call modes:
8675
+ * - `getAll()` — default. Returns only tenant-level entities.
8676
+ * - `getAll({ folderKey: "<uuid>" })` — preferred for folder-scoped data. Returns only entities in that folder.
8677
+ * - `getAll({ includeFolderEntities: true })` — returns tenant-level **and** folder-level entities together. `folderKey` is preferred over `includeFolderEntities` when both are set.
8678
+ *
8679
+ * @param options - Optional {@link EntityGetAllOptions} (`folderKey` to list a single folder's entities — preferred when scoping to a folder; `includeFolderEntities: true` to list tenant + folder entities together) The `folderKey` property is **experimental**.
8257
8680
  * @returns Promise resolving to an array of entity metadata
8258
8681
  *
8259
8682
  * @example
@@ -8262,15 +8685,29 @@ class EntityService extends BaseService {
8262
8685
  *
8263
8686
  * const entities = new Entities(sdk);
8264
8687
  *
8265
- * // Get all entities
8266
- * const allEntities = await entities.getAll();
8688
+ * // Tenant-only (default)
8689
+ * const tenantEntities = await entities.getAll();
8690
+ *
8691
+ * // A single folder's entities (preferred when targeting a specific folder)
8692
+ * const folderEntities = await entities.getAll({ folderKey: "<folderKey>" });
8693
+ *
8694
+ * // Tenant + folder entities together
8695
+ * const allEntities = await entities.getAll({ includeFolderEntities: true });
8267
8696
  *
8268
8697
  * // Call operations on an entity
8269
- * const records = await allEntities[0].getAllRecords();
8698
+ * const records = await tenantEntities[0].getAllRecords();
8270
8699
  * ```
8271
8700
  */
8272
- async getAll() {
8273
- const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_ALL);
8701
+ async getAll(options) {
8702
+ // folderKey is preferred over includeFolderEntities: when present, scope to that folder
8703
+ // via the v1 endpoint + header. Only when no folderKey is given AND includeFolderEntities
8704
+ // is explicitly true does the SDK switch to the v2 endpoint (returns tenant + folder
8705
+ // entities together). Default (no options or includeFolderEntities omitted) stays on
8706
+ // the v1 endpoint = tenant only.
8707
+ const endpoint = !options?.folderKey && options?.includeFolderEntities
8708
+ ? DATA_FABRIC_ENDPOINTS.ENTITY.GET_ALL_V2
8709
+ : DATA_FABRIC_ENDPOINTS.ENTITY.GET_ALL;
8710
+ const response = await this.get(endpoint, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
8274
8711
  // Apply transformations
8275
8712
  const entities = response.data.map(entity => {
8276
8713
  // Transform each entity
@@ -8285,7 +8722,7 @@ class EntityService extends BaseService {
8285
8722
  * Queries entity records with filters, sorting, aggregates, and pagination
8286
8723
  *
8287
8724
  * @param id - UUID of the entity
8288
- * @param options - Query options including filterGroup, selectedFields, sortOptions, aggregates, groupBy, and pagination
8725
+ * @param options - Query options including filterGroup, selectedFields, sortOptions, aggregates, groupBy, and pagination The `folderKey` property is **experimental**.
8289
8726
  * @returns Promise resolving to {@link NonPaginatedResponse} without pagination options,
8290
8727
  * or {@link PaginatedResponse} when `pageSize`, `cursor`, or `jumpToPage` are provided
8291
8728
  *
@@ -8332,13 +8769,24 @@ class EntityService extends BaseService {
8332
8769
  * { function: EntityAggregateFunction.Avg, field: "amount", alias: "avgAmount" },
8333
8770
  * ],
8334
8771
  * });
8772
+ *
8773
+ * // Folder-scoped entity: pass the entity's folder key
8774
+ * await entities.queryRecordsById("<entityId>", {
8775
+ * filterGroup: { queryFilters: [{ fieldName: "status", operator: QueryFilterOperator.Equals, value: "active" }] },
8776
+ * folderKey: "<folderKey>",
8777
+ * });
8335
8778
  * ```
8336
8779
  */
8337
8780
  async queryRecordsById(id, options) {
8781
+ // folderKey is header-only; expansionLevel must be sent as a query param by PaginationHelpers.
8782
+ const { folderKey, expansionLevel, ...rest } = options ?? {};
8783
+ const downstreamOptions = options === undefined ? undefined : rest;
8338
8784
  return PaginationHelpers.getAll({
8339
8785
  serviceAccess: this.createPaginationServiceAccess(),
8340
8786
  getEndpoint: () => DATA_FABRIC_ENDPOINTS.ENTITY.QUERY_BY_ID(id),
8341
8787
  method: HTTP_METHODS.POST,
8788
+ headers: createHeaders({ [FOLDER_KEY]: folderKey }),
8789
+ queryParams: createParams({ expansionLevel }),
8342
8790
  pagination: {
8343
8791
  paginationType: PaginationType.OFFSET,
8344
8792
  itemsField: ENTITY_PAGINATION.ITEMS_FIELD,
@@ -8349,14 +8797,15 @@ class EntityService extends BaseService {
8349
8797
  countParam: ENTITY_OFFSET_PARAMS.COUNT_PARAM
8350
8798
  }
8351
8799
  },
8352
- excludeFromPrefix: ['expansionLevel', 'filterGroup', 'selectedFields', 'sortOptions', 'aggregates', 'groupBy']
8353
- }, options);
8800
+ excludeFromPrefix: ['filterGroup', 'selectedFields', 'sortOptions', 'aggregates', 'groupBy']
8801
+ }, downstreamOptions);
8354
8802
  }
8355
8803
  /**
8356
8804
  * Imports records from a CSV file into an entity
8357
8805
  *
8358
8806
  * @param id - UUID of the entity
8359
8807
  * @param file - CSV file to import (Blob, File, or Uint8Array)
8808
+ * @param options - Optional {@link EntityImportRecordsByIdOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8360
8809
  * @returns Promise resolving to import result with record counts
8361
8810
  *
8362
8811
  * @example
@@ -8377,10 +8826,12 @@ class EntityService extends BaseService {
8377
8826
  * if (result.errorFileLink) {
8378
8827
  * console.log(`Error file link: ${result.errorFileLink}`);
8379
8828
  * }
8829
+ *
8830
+ * // Folder-scoped entity: pass the entity's folder key
8831
+ * await entities.importRecordsById("<entityId>", fileInput.files[0], { folderKey: "<folderKey>" });
8380
8832
  * ```
8381
- * @internal
8382
8833
  */
8383
- async importRecordsById(id, file) {
8834
+ async importRecordsById(id, file, options) {
8384
8835
  const formData = new FormData();
8385
8836
  if (file instanceof Uint8Array) {
8386
8837
  formData.append('file', new Blob([file.buffer]));
@@ -8388,7 +8839,7 @@ class EntityService extends BaseService {
8388
8839
  else {
8389
8840
  formData.append('file', file);
8390
8841
  }
8391
- const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.BULK_UPLOAD_BY_ID(id), formData);
8842
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.BULK_UPLOAD_BY_ID(id), formData, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
8392
8843
  return response.data;
8393
8844
  }
8394
8845
  /**
@@ -8397,6 +8848,7 @@ class EntityService extends BaseService {
8397
8848
  * @param entityId - UUID of the entity
8398
8849
  * @param recordId - UUID of the record containing the attachment
8399
8850
  * @param fieldName - Name of the File-type field containing the attachment
8851
+ * @param options - Optional {@link EntityDownloadAttachmentOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8400
8852
  * @returns Promise resolving to Blob containing the file content
8401
8853
  *
8402
8854
  * @example
@@ -8415,11 +8867,15 @@ class EntityService extends BaseService {
8415
8867
  *
8416
8868
  * // Download attachment for a specific record and field
8417
8869
  * const blob = await entities.downloadAttachment(entityId, recordId, 'Documents');
8870
+ *
8871
+ * // Folder-scoped: pass the entity's folder key
8872
+ * const blob = await entities.downloadAttachment(entityId, recordId, 'Documents', { folderKey: "<folderKey>" });
8418
8873
  * ```
8419
8874
  */
8420
- async downloadAttachment(entityId, recordId, fieldName) {
8875
+ async downloadAttachment(entityId, recordId, fieldName, options) {
8421
8876
  const response = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.DOWNLOAD_ATTACHMENT(entityId, recordId, fieldName), {
8422
- responseType: RESPONSE_TYPES.BLOB
8877
+ responseType: RESPONSE_TYPES.BLOB,
8878
+ headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }),
8423
8879
  });
8424
8880
  return response.data;
8425
8881
  }
@@ -8430,7 +8886,7 @@ class EntityService extends BaseService {
8430
8886
  * @param recordId - UUID of the record to upload the attachment to
8431
8887
  * @param fieldName - Name of the File-type field
8432
8888
  * @param file - File to upload (Blob, File, or Uint8Array)
8433
- * @param options - Optional {@link EntityUploadAttachmentOptions} (e.g. expansionLevel)
8889
+ * @param options - Optional {@link EntityUploadAttachmentOptions} (e.g. `expansionLevel`, `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8434
8890
  * @returns Promise resolving to {@link EntityUploadAttachmentResponse}
8435
8891
  *
8436
8892
  * @example
@@ -8449,6 +8905,9 @@ class EntityService extends BaseService {
8449
8905
  *
8450
8906
  * // Upload a file attachment
8451
8907
  * const response = await entities.uploadAttachment(entityId, recordId, 'Documents', file);
8908
+ *
8909
+ * // Folder-scoped entity: pass the entity's folder key
8910
+ * await entities.uploadAttachment(entityId, recordId, 'Documents', file, { folderKey: "<folderKey>" });
8452
8911
  * ```
8453
8912
  */
8454
8913
  async uploadAttachment(entityId, recordId, fieldName, file, options) {
@@ -8460,7 +8919,10 @@ class EntityService extends BaseService {
8460
8919
  formData.append('file', file);
8461
8920
  }
8462
8921
  const params = createParams({ expansionLevel: options?.expansionLevel });
8463
- const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPLOAD_ATTACHMENT(entityId, recordId, fieldName), formData, { params });
8922
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPLOAD_ATTACHMENT(entityId, recordId, fieldName), formData, {
8923
+ params,
8924
+ headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }),
8925
+ });
8464
8926
  return response.data;
8465
8927
  }
8466
8928
  /**
@@ -8469,6 +8931,7 @@ class EntityService extends BaseService {
8469
8931
  * @param entityId - UUID of the entity
8470
8932
  * @param recordId - UUID of the record containing the attachment
8471
8933
  * @param fieldName - Name of the File-type field containing the attachment
8934
+ * @param options - Optional {@link EntityDeleteAttachmentOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8472
8935
  * @returns Promise resolving to {@link EntityDeleteAttachmentResponse}
8473
8936
  *
8474
8937
  * @example
@@ -8487,10 +8950,13 @@ class EntityService extends BaseService {
8487
8950
  *
8488
8951
  * // Delete attachment for a specific record and field
8489
8952
  * await entities.deleteAttachment(entityId, recordId, 'Documents');
8953
+ *
8954
+ * // Folder-scoped: pass the entity's folder key
8955
+ * await entities.deleteAttachment(entityId, recordId, 'Documents', { folderKey: "<folderKey>" });
8490
8956
  * ```
8491
8957
  */
8492
- async deleteAttachment(entityId, recordId, fieldName) {
8493
- const response = await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE_ATTACHMENT(entityId, recordId, fieldName));
8958
+ async deleteAttachment(entityId, recordId, fieldName, options) {
8959
+ const response = await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE_ATTACHMENT(entityId, recordId, fieldName), { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
8494
8960
  return response.data;
8495
8961
  }
8496
8962
  /**
@@ -8520,7 +8986,7 @@ class EntityService extends BaseService {
8520
8986
  * @param name - Entity name — must start with a letter and contain
8521
8987
  * only letters, numbers, and underscores (e.g., `"productCatalog"`).
8522
8988
  * @param fields - Array of field definitions
8523
- * @param options - Optional entity-level settings ({@link EntityCreateOptions})
8989
+ * @param options - Optional entity-level settings ({@link EntityCreateOptions}) The `folderKey` property is **experimental**.
8524
8990
  * @returns Promise resolving to the ID of the created entity
8525
8991
  *
8526
8992
  * @example
@@ -8536,40 +9002,63 @@ class EntityService extends BaseService {
8536
9002
  * { fieldName: "price", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
8537
9003
  * { fieldName: "quantity", type: EntityFieldDataType.INTEGER, maxValue: 10000, minValue: 1, defaultValue: "0" },
8538
9004
  * ]);
9005
+ *
9006
+ * // Cross-folder references — link a folder-scoped entity to entities and
9007
+ * // system choice sets that live in another folder or at the tenant level.
9008
+ * await entities.create("orderLine", [
9009
+ * {
9010
+ * fieldName: "order",
9011
+ * type: EntityFieldDataType.RELATIONSHIP,
9012
+ * referenceEntityId: "<orderEntityId>",
9013
+ * referenceFieldId: "<orderEntityPkId>",
9014
+ * referenceFolderKey: "<otherFolderKey>", // target lives in a different folder
9015
+ * },
9016
+ * {
9017
+ * fieldName: "userType",
9018
+ * type: EntityFieldDataType.CHOICE_SET_SINGLE,
9019
+ * choiceSetId: "<systemUserTypeChoiceSetId>", // tenant-level system choice set
9020
+ * // referenceFolderKey omitted → SDK looks up the target at tenant scope
9021
+ * },
9022
+ * ], { folderKey: "<sourceFolderKey>" });
8539
9023
  * ```
8540
9024
  * @internal
8541
9025
  */
8542
9026
  async create(name, fields, options) {
8543
9027
  const opts = options ?? {};
9028
+ const fieldPayloads = await this.buildFieldsWithReferenceMeta(fields);
8544
9029
  const payload = {
8545
9030
  ...(opts.description !== undefined && { description: opts.description }),
8546
9031
  displayName: opts.displayName ?? name,
8547
9032
  entityDefinition: {
8548
9033
  name,
8549
- fields: fields.map(f => this.buildSchemaFieldPayload(f)),
9034
+ fields: fieldPayloads,
8550
9035
  folderId: opts.folderKey ?? DATA_FABRIC_TENANT_FOLDER_ID,
8551
9036
  isRbacEnabled: opts.isRbacEnabled ?? false,
8552
9037
  isInsightsEnabled: opts.isAnalyticsEnabled ?? false,
8553
9038
  externalFields: opts.externalFields ?? [],
8554
9039
  },
8555
9040
  };
8556
- const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPSERT, payload);
9041
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPSERT, payload, { headers: createHeaders({ [FOLDER_KEY]: opts.folderKey }) });
8557
9042
  return response.data;
8558
9043
  }
8559
9044
  /**
8560
9045
  * Deletes a Data Fabric entity and all its records
8561
9046
  *
8562
9047
  * @param id - UUID of the entity to delete
9048
+ * @param options - Optional {@link EntityDeleteByIdOptions} (e.g. `folderKey` for folder-scoped entities) The `folderKey` property is **experimental**.
8563
9049
  * @returns Promise resolving when the entity is deleted
8564
9050
  *
8565
9051
  * @example
8566
9052
  * ```typescript
8567
9053
  * await entities.deleteById("<entityId>");
9054
+ *
9055
+ * // Folder-scoped: pass the entity's folder key
9056
+ * await entities.deleteById("<entityId>", { folderKey: "<folderKey>" });
8568
9057
  * ```
8569
9058
  * @internal
8570
9059
  */
8571
- async deleteById(id) {
8572
- await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE(id));
9060
+ async deleteById(id, options) {
9061
+ await this.delete(DATA_FABRIC_ENDPOINTS.ENTITY.DELETE(id), { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
8573
9062
  }
8574
9063
  /**
8575
9064
  * Updates an existing Data Fabric entity — schema and/or metadata.
@@ -8583,7 +9072,7 @@ class EntityService extends BaseService {
8583
9072
  * overwrite each other's changes.
8584
9073
  *
8585
9074
  * @param id - UUID of the entity to update
8586
- * @param options - Changes to apply ({@link EntityUpdateByIdOptions})
9075
+ * @param options - Changes to apply ({@link EntityUpdateByIdOptions}) The `folderKey` property is **experimental**.
8587
9076
  * @returns Promise resolving when the update is complete
8588
9077
  *
8589
9078
  * @example
@@ -8616,6 +9105,12 @@ class EntityService extends BaseService {
8616
9105
  * { id: "<fieldId>", lengthLimit: 1000 },
8617
9106
  * ],
8618
9107
  * });
9108
+ *
9109
+ * // Folder-scoped entity: add a field to an entity that lives in a non-tenant folder
9110
+ * await entities.updateById("<entityId>", {
9111
+ * folderKey: "<folderKey>",
9112
+ * addFields: [{ fieldName: "notes", type: EntityFieldDataType.MULTILINE_TEXT }],
9113
+ * });
8619
9114
  * ```
8620
9115
  * @internal
8621
9116
  */
@@ -8631,7 +9126,7 @@ class EntityService extends BaseService {
8631
9126
  ...(opts.displayName !== undefined && { displayName: opts.displayName }),
8632
9127
  ...(opts.description !== undefined && { description: opts.description }),
8633
9128
  ...(opts.isRbacEnabled !== undefined && { isRbacEnabled: opts.isRbacEnabled }),
8634
- });
9129
+ }, { headers: createHeaders({ [FOLDER_KEY]: opts.folderKey }) });
8635
9130
  }
8636
9131
  }
8637
9132
  /**
@@ -8642,7 +9137,8 @@ class EntityService extends BaseService {
8642
9137
  * @private
8643
9138
  */
8644
9139
  async applySchemaUpdate(entityId, options) {
8645
- const entityResponse = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_BY_ID(entityId));
9140
+ const folderHeaders = createHeaders({ [FOLDER_KEY]: options.folderKey });
9141
+ const entityResponse = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_BY_ID(entityId), { headers: folderHeaders });
8646
9142
  const raw = entityResponse.data;
8647
9143
  // Carry forward existing non-system fields from GET response (skip system/primary-key fields)
8648
9144
  let fields = (raw.fields ?? [])
@@ -8688,10 +9184,9 @@ class EntityService extends BaseService {
8688
9184
  };
8689
9185
  });
8690
9186
  }
8691
- // Build and append new fields
8692
9187
  const newFields = [];
8693
9188
  if (options.addFields?.length) {
8694
- newFields.push(...options.addFields.map(f => this.buildSchemaFieldPayload(f)));
9189
+ newFields.push(...await this.buildFieldsWithReferenceMeta(options.addFields));
8695
9190
  }
8696
9191
  await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPSERT, {
8697
9192
  displayName: raw.displayName,
@@ -8705,7 +9200,7 @@ class EntityService extends BaseService {
8705
9200
  isInsightsEnabled: raw.isInsightsEnabled ?? false,
8706
9201
  externalFields: raw.externalFields ?? [],
8707
9202
  },
8708
- });
9203
+ }, { headers: folderHeaders });
8709
9204
  }
8710
9205
  /**
8711
9206
  * Orchestrates all field mapping transformations
@@ -8789,8 +9284,39 @@ class EntityService extends BaseService {
8789
9284
  return externalSource;
8790
9285
  });
8791
9286
  }
9287
+ async buildFieldsWithReferenceMeta(fields) {
9288
+ const metas = await Promise.all(fields.map(f => this.buildReferenceMeta(f)));
9289
+ return fields.map((f, i) => this.buildSchemaFieldPayload(f, metas[i]));
9290
+ }
9291
+ // Choice-set targets resolve server-side by NAME (the API rejects cross-folder
9292
+ // refs with empty target name even when folderId is supplied), so the SDK
9293
+ // fetches the name once for each cross-folder choice-set field. Relationship
9294
+ // targets resolve by folderId — no lookup needed.
9295
+ async buildReferenceMeta(field) {
9296
+ if (field.referenceFolderKey === undefined)
9297
+ return undefined;
9298
+ if (field.referenceEntityId === undefined && field.choiceSetId === undefined)
9299
+ return undefined;
9300
+ const folderId = field.referenceFolderKey;
9301
+ const meta = {};
9302
+ if (field.referenceEntityId !== undefined) {
9303
+ meta.referenceEntity = { id: field.referenceEntityId, folderId };
9304
+ }
9305
+ if (field.choiceSetId !== undefined) {
9306
+ const lookupFolderKey = folderId === DATA_FABRIC_TENANT_FOLDER_ID ? undefined : folderId;
9307
+ const target = await this.get(DATA_FABRIC_ENDPOINTS.ENTITY.GET_BY_ID(field.choiceSetId), { headers: createHeaders({ [FOLDER_KEY]: lookupFolderKey }) });
9308
+ meta.referenceChoiceSet = {
9309
+ id: field.choiceSetId,
9310
+ name: target.data.name,
9311
+ folderId,
9312
+ entityType: exports.EntityType.ChoiceSet,
9313
+ entityTypeId: ENTITY_TYPE_IDS[exports.EntityType.ChoiceSet],
9314
+ };
9315
+ }
9316
+ return meta;
9317
+ }
8792
9318
  /** Converts a user-facing EntityCreateFieldOptions to the raw API field payload */
8793
- buildSchemaFieldPayload(field) {
9319
+ buildSchemaFieldPayload(field, refMeta) {
8794
9320
  const fieldType = field.type ?? exports.EntityFieldDataType.STRING;
8795
9321
  this.validateFieldConstraints(fieldType, field, field.fieldName);
8796
9322
  const isRelationship = fieldType === exports.EntityFieldDataType.RELATIONSHIP;
@@ -8801,6 +9327,10 @@ class EntityService extends BaseService {
8801
9327
  });
8802
9328
  }
8803
9329
  const mapping = EntitySchemaFieldTypeMap[fieldType];
9330
+ // Prefer the resolved {id, name, folderId} body so cross-folder targets resolve
9331
+ // server-side; fall back to a bare {id} when no meta was fetched.
9332
+ const referenceEntityBody = refMeta?.referenceEntity ?? (field.referenceEntityId === undefined ? undefined : { id: field.referenceEntityId });
9333
+ const referenceChoiceSetBody = refMeta?.referenceChoiceSet;
8804
9334
  return {
8805
9335
  name: field.fieldName,
8806
9336
  displayName: field.displayName ?? field.fieldName,
@@ -8819,7 +9349,8 @@ class EntityService extends BaseService {
8819
9349
  ...(field.choiceSetId !== undefined && { choiceSetId: field.choiceSetId }),
8820
9350
  ...((isRelationship || isFile) && { isForeignKey: true }),
8821
9351
  ...(isRelationship && { referenceType: exports.ReferenceType.ManyToOne }),
8822
- ...(field.referenceEntityId !== undefined && { referenceEntity: { id: field.referenceEntityId } }),
9352
+ ...(referenceEntityBody !== undefined && { referenceEntity: referenceEntityBody }),
9353
+ ...(referenceChoiceSetBody !== undefined && { referenceChoiceSet: referenceChoiceSetBody }),
8823
9354
  ...(field.referenceFieldId !== undefined && { referenceField: { id: field.referenceFieldId } }),
8824
9355
  };
8825
9356
  }
@@ -8982,8 +9513,14 @@ __decorate([
8982
9513
 
8983
9514
  class ChoiceSetService extends BaseService {
8984
9515
  /**
8985
- * Gets all choice sets in the system
9516
+ * Gets choice sets in the tenant.
8986
9517
  *
9518
+ * Three call modes:
9519
+ * - `getAll()` — default. Returns only tenant-level choice sets.
9520
+ * - `getAll({ folderKey: "<uuid>" })` — preferred for folder-scoped data. Returns only choice sets in that folder.
9521
+ * - `getAll({ includeFolderChoiceSets: true })` — returns tenant-level **and** folder-level choice sets together. `folderKey` is preferred over `includeFolderChoiceSets` when both are set.
9522
+ *
9523
+ * @param options - Optional {@link ChoiceSetGetAllOptions} (`folderKey` to list a single folder's choice sets — preferred when scoping to a folder; `includeFolderChoiceSets: true` to list tenant + folder choice sets together) The `folderKey` property is **experimental**.
8987
9524
  * @returns Promise resolving to an array of choice set metadata
8988
9525
  *
8989
9526
  * @example
@@ -8992,18 +9529,33 @@ class ChoiceSetService extends BaseService {
8992
9529
  *
8993
9530
  * const choiceSets = new ChoiceSets(sdk);
8994
9531
  *
8995
- * // Get all choice sets
8996
- * const allChoiceSets = await choiceSets.getAll();
9532
+ * // Tenant-only (default)
9533
+ * const tenantChoiceSets = await choiceSets.getAll();
8997
9534
  *
8998
- * // Iterate through choice sets
8999
- * allChoiceSets.forEach(choiceSet => {
9000
- * console.log(`ChoiceSet: ${choiceSet.displayName} (${choiceSet.name})`);
9001
- * console.log(`Description: ${choiceSet.description}`);
9002
- * });
9535
+ * // A single folder's choice sets (preferred when targeting a specific folder)
9536
+ * const folderChoiceSets = await choiceSets.getAll({ folderKey: "<folderKey>" });
9537
+ *
9538
+ * // Tenant + folder choice sets together
9539
+ * const allChoiceSets = await choiceSets.getAll({ includeFolderChoiceSets: true });
9003
9540
  * ```
9004
9541
  */
9005
- async getAll() {
9006
- const rawResponse = await this.get(DATA_FABRIC_ENDPOINTS.CHOICESETS.GET_ALL);
9542
+ async getAll(options) {
9543
+ return this.fetchAllChoiceSets(options);
9544
+ }
9545
+ /**
9546
+ * Internal helper that performs the choice-set fetch. Kept separate from the
9547
+ * public `getAll()` so that internal callers (e.g. `resolveChoiceSetName`)
9548
+ * can reuse it without triggering double `@track` telemetry.
9549
+ */
9550
+ async fetchAllChoiceSets(options) {
9551
+ // The choice-set endpoint returns cross-scope results when called without
9552
+ // a folder header. To stay tenant-only by default, send the tenant-marker
9553
+ // UUID as the folder key unless the caller explicitly opts into cross-scope
9554
+ // via includeFolderChoiceSets: true. folderKey is preferred over
9555
+ // includeFolderChoiceSets when both are set.
9556
+ const folderKey = options?.folderKey
9557
+ ?? (options?.includeFolderChoiceSets ? undefined : DATA_FABRIC_TENANT_FOLDER_ID);
9558
+ const rawResponse = await this.get(DATA_FABRIC_ENDPOINTS.CHOICESETS.GET_ALL, { headers: createHeaders({ [FOLDER_KEY]: folderKey }) });
9007
9559
  // Transform field names
9008
9560
  const data = rawResponse.data || [];
9009
9561
  return data.map(choiceSet => transformData(choiceSet, EntityMap));
@@ -9016,7 +9568,7 @@ class ChoiceSetService extends BaseService {
9016
9568
  * - A PaginatedResponse with navigation cursors (when any pagination parameter is provided)
9017
9569
  *
9018
9570
  * @param choiceSetId - UUID of the choice set
9019
- * @param options - Pagination options
9571
+ * @param options - Pagination options and optional `folderKey` for folder-scoped choice sets The `folderKey` property is **experimental**.
9020
9572
  * @returns Promise resolving to choice set values or paginated result
9021
9573
  *
9022
9574
  * @example
@@ -9045,6 +9597,9 @@ class ChoiceSetService extends BaseService {
9045
9597
  * if (page1.hasNextPage) {
9046
9598
  * const page2 = await choiceSets.getById(choiceSetId, { cursor: page1.nextCursor });
9047
9599
  * }
9600
+ *
9601
+ * // Folder-scoped choice set
9602
+ * const folderValues = await choiceSets.getById(choiceSetId, { folderKey: "<folderKey>" });
9048
9603
  * ```
9049
9604
  */
9050
9605
  async getById(choiceSetId, options) {
@@ -9053,11 +9608,16 @@ class ChoiceSetService extends BaseService {
9053
9608
  const camelCased = pascalToCamelCaseKeys(item);
9054
9609
  return transformData(camelCased, EntityMap);
9055
9610
  };
9611
+ // folderKey is header-only — destructure it out so PaginationHelpers doesn't
9612
+ // include it in the POST body alongside pagination params.
9613
+ const { folderKey, ...rest } = options ?? {};
9614
+ const downstreamOptions = options === undefined ? undefined : rest;
9056
9615
  return PaginationHelpers.getAll({
9057
9616
  serviceAccess: this.createPaginationServiceAccess(),
9058
9617
  getEndpoint: () => DATA_FABRIC_ENDPOINTS.CHOICESETS.GET_BY_ID(choiceSetId),
9059
9618
  transformFn,
9060
9619
  method: HTTP_METHODS.POST,
9620
+ headers: createHeaders({ [FOLDER_KEY]: folderKey }),
9061
9621
  pagination: {
9062
9622
  paginationType: PaginationType.OFFSET,
9063
9623
  itemsField: CHOICESET_VALUES_PAGINATION.ITEMS_FIELD,
@@ -9068,7 +9628,7 @@ class ChoiceSetService extends BaseService {
9068
9628
  countParam: ENTITY_OFFSET_PARAMS.COUNT_PARAM
9069
9629
  }
9070
9630
  }
9071
- }, options);
9631
+ }, downstreamOptions);
9072
9632
  }
9073
9633
  /**
9074
9634
  * Creates a new Data Fabric choice set
@@ -9076,7 +9636,7 @@ class ChoiceSetService extends BaseService {
9076
9636
  * @param name - Choice set name. Must start with a
9077
9637
  * letter, may contain only letters, numbers, and underscores, length
9078
9638
  * 3–100 characters (e.g., `"expenseTypes"`).
9079
- * @param options - Optional choice-set-level settings ({@link ChoiceSetCreateOptions})
9639
+ * @param options - Optional choice-set-level settings ({@link ChoiceSetCreateOptions}) The `folderKey` property is **experimental**.
9080
9640
  * @returns Promise resolving to the UUID of the created choice set
9081
9641
  *
9082
9642
  * @example
@@ -9107,7 +9667,7 @@ class ChoiceSetService extends BaseService {
9107
9667
  folderId: opts.folderKey ?? DATA_FABRIC_TENANT_FOLDER_ID,
9108
9668
  },
9109
9669
  };
9110
- const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.CREATE, payload);
9670
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.CREATE, payload, { headers: createHeaders({ [FOLDER_KEY]: opts.folderKey }) });
9111
9671
  return response.data;
9112
9672
  }
9113
9673
  /**
@@ -9117,7 +9677,7 @@ class ChoiceSetService extends BaseService {
9117
9677
  * the call throws `ValidationError` if both are omitted.
9118
9678
  *
9119
9679
  * @param choiceSetId - UUID of the choice set to update
9120
- * @param options - Metadata fields to change ({@link ChoiceSetUpdateOptions})
9680
+ * @param options - Metadata fields to change ({@link ChoiceSetUpdateOptions}) The `folderKey` property is **experimental**.
9121
9681
  * @returns Promise resolving when the update is complete
9122
9682
  *
9123
9683
  * @example
@@ -9142,12 +9702,13 @@ class ChoiceSetService extends BaseService {
9142
9702
  await this.patch(DATA_FABRIC_ENDPOINTS.CHOICESETS.UPDATE(choiceSetId), {
9143
9703
  ...(options.displayName !== undefined && { displayName: options.displayName }),
9144
9704
  ...(options.description !== undefined && { description: options.description }),
9145
- });
9705
+ }, { headers: createHeaders({ [FOLDER_KEY]: options.folderKey }) });
9146
9706
  }
9147
9707
  /**
9148
9708
  * Deletes a Data Fabric choice set and all its values.
9149
9709
  *
9150
9710
  * @param choiceSetId - UUID of the choice set to delete
9711
+ * @param options - Optional {@link ChoiceSetDeleteByIdOptions} (e.g. `folderKey` for folder-scoped choice sets) The `folderKey` property is **experimental**.
9151
9712
  * @returns Promise resolving when the choice set is deleted
9152
9713
  *
9153
9714
  * @example
@@ -9157,18 +9718,21 @@ class ChoiceSetService extends BaseService {
9157
9718
  * const expenseTypes = allChoiceSets.find(cs => cs.name === 'expense_types');
9158
9719
  *
9159
9720
  * await choicesets.deleteById(expenseTypes.id);
9721
+ *
9722
+ * // Folder-scoped choice set
9723
+ * await choicesets.deleteById(expenseTypes.id, { folderKey: "<folderKey>" });
9160
9724
  * ```
9161
9725
  * @internal
9162
9726
  */
9163
- async deleteById(choiceSetId) {
9164
- await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.DELETE(choiceSetId), {});
9727
+ async deleteById(choiceSetId, options) {
9728
+ await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.DELETE(choiceSetId), {}, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
9165
9729
  }
9166
9730
  /**
9167
9731
  * Inserts a single value into a choice set.
9168
9732
  *
9169
9733
  * @param choiceSetId - UUID of the parent choice set
9170
9734
  * @param name - Identifier name of the new value (e.g., `"TRAVEL"`)
9171
- * @param options - Optional fields ({@link ChoiceSetValueInsertOptions})
9735
+ * @param options - Optional fields ({@link ChoiceSetValueInsertOptions}) The `folderKey` property is **experimental**.
9172
9736
  * @returns Promise resolving to the inserted value ({@link ChoiceSetValueInsertResponse})
9173
9737
  *
9174
9738
  * @example
@@ -9181,16 +9745,22 @@ class ChoiceSetService extends BaseService {
9181
9745
  * displayName: 'Travel',
9182
9746
  * });
9183
9747
  * console.log(inserted.id);
9748
+ *
9749
+ * // Folder-scoped choice set: folderKey is required on the wire
9750
+ * await choicesets.insertValueById(expenseTypes.id, 'TRAVEL', {
9751
+ * displayName: 'Travel',
9752
+ * folderKey: "<folderKey>",
9753
+ * });
9184
9754
  * ```
9185
9755
  * @internal
9186
9756
  */
9187
9757
  async insertValueById(choiceSetId, name, options) {
9188
- const choiceSetName = await this.resolveChoiceSetName(choiceSetId);
9758
+ const choiceSetName = await this.resolveChoiceSetName(choiceSetId, options?.folderKey);
9189
9759
  const payload = {
9190
9760
  Name: name,
9191
9761
  ...(options?.displayName !== undefined && { DisplayName: options.displayName }),
9192
9762
  };
9193
- const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.INSERT_BY_NAME(choiceSetName), payload);
9763
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.INSERT_BY_NAME(choiceSetName), payload, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
9194
9764
  const camelCased = pascalToCamelCaseKeys(response.data);
9195
9765
  return transformData(camelCased, EntityMap);
9196
9766
  }
@@ -9203,6 +9773,7 @@ class ChoiceSetService extends BaseService {
9203
9773
  * @param choiceSetId - UUID of the parent choice set
9204
9774
  * @param valueId - UUID of the value to update
9205
9775
  * @param displayName - New human-readable display name for the value
9776
+ * @param options - Optional {@link ChoiceSetValueUpdateOptions} — pass `folderKey` for folder-scoped choice sets; omit for tenant-level. The `folderKey` property is **experimental**.
9206
9777
  * @returns Promise resolving to the updated value ({@link ChoiceSetValueUpdateResponse})
9207
9778
  *
9208
9779
  * @example
@@ -9214,13 +9785,18 @@ class ChoiceSetService extends BaseService {
9214
9785
  * const travel = values.items.find(v => v.name === 'TRAVEL');
9215
9786
  *
9216
9787
  * await choicesets.updateValueById(expenseTypes.id, travel.id, 'Business Travel');
9788
+ *
9789
+ * // Folder-scoped choice set: folderKey is required on the wire
9790
+ * await choicesets.updateValueById(expenseTypes.id, travel.id, 'Business Travel', {
9791
+ * folderKey: "<folderKey>",
9792
+ * });
9217
9793
  * ```
9218
9794
  * @internal
9219
9795
  */
9220
- async updateValueById(choiceSetId, valueId, displayName) {
9221
- const choiceSetName = await this.resolveChoiceSetName(choiceSetId);
9796
+ async updateValueById(choiceSetId, valueId, displayName, options) {
9797
+ const choiceSetName = await this.resolveChoiceSetName(choiceSetId, options?.folderKey);
9222
9798
  const payload = { DisplayName: displayName };
9223
- const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.UPDATE_BY_NAME(choiceSetName, valueId), payload);
9799
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.UPDATE_BY_NAME(choiceSetName, valueId), payload, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
9224
9800
  const camelCased = pascalToCamelCaseKeys(response.data);
9225
9801
  return transformData(camelCased, EntityMap);
9226
9802
  }
@@ -9229,6 +9805,7 @@ class ChoiceSetService extends BaseService {
9229
9805
  *
9230
9806
  * @param choiceSetId - UUID of the parent choice set
9231
9807
  * @param valueIds - Array of value UUIDs to delete
9808
+ * @param options - Optional {@link ChoiceSetValueDeleteOptions} (e.g. `folderKey` for folder-scoped choice sets) The `folderKey` property is **experimental**.
9232
9809
  * @returns Promise resolving when the values are deleted
9233
9810
  *
9234
9811
  * @example
@@ -9238,14 +9815,20 @@ class ChoiceSetService extends BaseService {
9238
9815
  * const idsToDelete = values.items.slice(0, 2).map(v => v.id);
9239
9816
  *
9240
9817
  * await choicesets.deleteValuesById('<choiceSetId>', idsToDelete);
9818
+ *
9819
+ * // Folder-scoped choice set
9820
+ * await choicesets.deleteValuesById('<choiceSetId>', idsToDelete, { folderKey: "<folderKey>" });
9241
9821
  * ```
9242
9822
  * @internal
9243
9823
  */
9244
- async deleteValuesById(choiceSetId, valueIds) {
9245
- await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.DELETE_BY_ID(choiceSetId), valueIds);
9824
+ async deleteValuesById(choiceSetId, valueIds, options) {
9825
+ await this.post(DATA_FABRIC_ENDPOINTS.CHOICESETS.DELETE_BY_ID(choiceSetId), valueIds, { headers: createHeaders({ [FOLDER_KEY]: options?.folderKey }) });
9246
9826
  }
9247
- async resolveChoiceSetName(choiceSetId) {
9248
- const all = await this.getAll();
9827
+ async resolveChoiceSetName(choiceSetId, folderKey) {
9828
+ // Use the un-tracked helper directly so we don't fire a duplicate
9829
+ // `Choicesets.GetAll` telemetry event for every insertValueById /
9830
+ // updateValueById call.
9831
+ const all = await this.fetchAllChoiceSets(folderKey === undefined ? undefined : { folderKey });
9249
9832
  const match = all.find(cs => cs.id === choiceSetId);
9250
9833
  if (!match) {
9251
9834
  throw new NotFoundError({ message: `Choice set with id '${choiceSetId}' not found.` });
@@ -9297,6 +9880,13 @@ function createProcessMethods(processData, service) {
9297
9880
  if (!processData.folderKey)
9298
9881
  throw new Error('Folder key is undefined');
9299
9882
  return service.getIncidents(processData.processKey, processData.folderKey);
9883
+ },
9884
+ getElementStats(startTime, endTime, packageVersion) {
9885
+ if (!processData.processKey)
9886
+ throw new Error('Process key is undefined');
9887
+ if (!processData.packageId)
9888
+ throw new Error('Package ID is undefined');
9889
+ return service.getElementStats(processData.processKey, processData.packageId, startTime, endTime, packageVersion);
9300
9890
  }
9301
9891
  };
9302
9892
  }
@@ -9358,6 +9948,28 @@ async function fetchInstanceStatusTimeline(postFn, startTime, endTime, isCaseMan
9358
9948
  });
9359
9949
  return response.data ?? [];
9360
9950
  }
9951
+ /**
9952
+ * Builds the request body for the ElementCountByStatus endpoint.
9953
+ *
9954
+ * @param processKey - Process key to filter by
9955
+ * @param packageId - Package identifier
9956
+ * @param startTime - Start of the time range to query
9957
+ * @param endTime - End of the time range to query
9958
+ * @param packageVersion - Package version to filter by
9959
+ * @returns Request body for the ElementCountByStatus endpoint
9960
+ * @internal
9961
+ */
9962
+ function buildElementCountByStatusBody(processKey, packageId, startTime, endTime, packageVersion) {
9963
+ return {
9964
+ commonParams: {
9965
+ processKey,
9966
+ packageId,
9967
+ startTime: startTime.getTime(),
9968
+ endTime: endTime.getTime(),
9969
+ version: packageVersion
9970
+ }
9971
+ };
9972
+ }
9361
9973
 
9362
9974
  /**
9363
9975
  * Maps fields for Incident entities
@@ -9522,7 +10134,9 @@ function createProcessInstanceMethods(instanceData, service) {
9522
10134
  async getExecutionHistory() {
9523
10135
  if (!instanceData.instanceId)
9524
10136
  throw new Error('Process instance ID is undefined');
9525
- return service.getExecutionHistory(instanceData.instanceId);
10137
+ if (!instanceData.folderKey)
10138
+ throw new Error('Process instance folder key is undefined');
10139
+ return service.getExecutionHistory(instanceData.instanceId, instanceData.folderKey);
9526
10140
  },
9527
10141
  async getBpmn() {
9528
10142
  if (!instanceData.instanceId)
@@ -9588,6 +10202,40 @@ exports.DebugMode = void 0;
9588
10202
  DebugMode["SingleStep"] = "SingleStep";
9589
10203
  })(exports.DebugMode || (exports.DebugMode = {}));
9590
10204
 
10205
+ /**
10206
+ * Maestro Cases Models
10207
+ * Model classes for Maestro cases
10208
+ */
10209
+ /**
10210
+ * Creates methods for a case object
10211
+ *
10212
+ * @param caseData - The case data (response from API)
10213
+ * @param service - The cases service instance
10214
+ * @returns Object containing case methods
10215
+ */
10216
+ function createCaseMethods(caseData, service) {
10217
+ return {
10218
+ getElementStats(startTime, endTime, packageVersion) {
10219
+ if (!caseData.processKey)
10220
+ throw new Error('Process key is undefined');
10221
+ if (!caseData.packageId)
10222
+ throw new Error('Package ID is undefined');
10223
+ return service.getElementStats(caseData.processKey, caseData.packageId, startTime, endTime, packageVersion);
10224
+ }
10225
+ };
10226
+ }
10227
+ /**
10228
+ * Creates an actionable case by combining API case data with operational methods.
10229
+ *
10230
+ * @param caseData - The case data from API
10231
+ * @param service - The cases service instance
10232
+ * @returns A case object with added methods
10233
+ */
10234
+ function createCaseWithMethods(caseData, service) {
10235
+ const methods = createCaseMethods(caseData, service);
10236
+ return Object.assign({}, caseData, methods);
10237
+ }
10238
+
9591
10239
  /**
9592
10240
  * Case Instance Types
9593
10241
  * Types and interfaces for Maestro case instance management
@@ -9799,12 +10447,6 @@ const ProcessInstanceMap = {
9799
10447
  createdAt: 'createdTime',
9800
10448
  updatedAt: 'updatedTime'
9801
10449
  };
9802
- /**
9803
- * Maps fields for Process Instance Execution History to ensure consistent naming
9804
- */
9805
- const ProcessInstanceExecutionHistoryMap = {
9806
- startTime: 'startedTime'
9807
- };
9808
10450
 
9809
10451
  class ProcessInstancesService extends BaseService {
9810
10452
  /**
@@ -9885,11 +10527,66 @@ class ProcessInstancesService extends BaseService {
9885
10527
  /**
9886
10528
  * Get execution history (spans) for a process instance
9887
10529
  * @param instanceId The ID of the instance to get history for
9888
- * @returns Promise<ProcessInstanceExecutionHistoryResponse[]>
10530
+ * @param folderKey The folder key for authorization
10531
+ * @returns Promise resolving to execution history
10532
+ * {@link ProcessInstanceExecutionHistoryResponse}
10533
+ * @example
10534
+ * ```typescript
10535
+ * // Get execution history for a process instance
10536
+ * const history = await processInstances.getExecutionHistory(
10537
+ * <instanceId>,
10538
+ * <folderKey>
10539
+ * );
10540
+ *
10541
+ * // Analyze execution timeline
10542
+ * history.forEach(span => {
10543
+ * console.log(`Activity: ${span.name}`);
10544
+ * console.log(`Start: ${span.startedTime}`);
10545
+ * console.log(`End: ${span.endTime}`);
10546
+ * });
10547
+ * ```
9889
10548
  */
9890
- async getExecutionHistory(instanceId) {
9891
- const response = await this.get(MAESTRO_ENDPOINTS.INSTANCES.GET_EXECUTION_HISTORY(instanceId));
9892
- return response.data.map(historyItem => transformData(historyItem, ProcessInstanceExecutionHistoryMap));
10549
+ async getExecutionHistory(instanceId, folderKey) {
10550
+ const headers = createHeaders({ [FOLDER_KEY]: folderKey });
10551
+ const elementExecResponse = await this.get(MAESTRO_ENDPOINTS.INSTANCES.GET_ELEMENT_EXECUTIONS(instanceId), { headers });
10552
+ const traceId = elementExecResponse.data.traceId;
10553
+ const spansResponse = await this.get(MAESTRO_ENDPOINTS.TRACES.GET_SPANS(traceId), { headers });
10554
+ // Build span lookup keyed by elementRunId extracted from Attributes JSON
10555
+ const spanMap = new Map();
10556
+ for (const span of spansResponse.data) {
10557
+ try {
10558
+ const attrs = span.Attributes ? JSON.parse(span.Attributes) : null;
10559
+ if (attrs?.elementRunId) {
10560
+ spanMap.set(attrs.elementRunId, span);
10561
+ }
10562
+ }
10563
+ catch {
10564
+ // skip spans with unparseable Attributes — they won't match any elementRunId
10565
+ }
10566
+ }
10567
+ const results = [];
10568
+ for (const elementExec of elementExecResponse.data.elementExecutions) {
10569
+ for (const run of elementExec.elementRuns) {
10570
+ const span = spanMap.get(run.elementRunId);
10571
+ if (span) {
10572
+ results.push(this.mapSpanToHistory(span));
10573
+ }
10574
+ }
10575
+ }
10576
+ return results;
10577
+ }
10578
+ mapSpanToHistory(span) {
10579
+ return {
10580
+ id: span.Id,
10581
+ traceId: span.TraceId,
10582
+ parentId: span.ParentId,
10583
+ name: span.Name,
10584
+ startedTime: span.StartTime,
10585
+ endTime: span.EndTime,
10586
+ attributes: span.Attributes,
10587
+ updatedTime: span.UpdatedAt,
10588
+ expiredTime: span.ExpiryTimeUtc,
10589
+ };
9893
10590
  }
9894
10591
  /**
9895
10592
  * Get BPMN XML file for a process instance
@@ -10381,6 +11078,41 @@ class MaestroProcessesService extends BaseService {
10381
11078
  const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.TOP_PROCESSES_BY_DURATION, buildInsightsTopBody(startTime, endTime, false, options));
10382
11079
  return (data ?? []).map(process => ({ ...process, name: process.packageId }));
10383
11080
  }
11081
+ /**
11082
+ * Get element stats for process instances
11083
+ *
11084
+ * Returns per-element execution counts (success, fail, terminated, paused, in-progress) and
11085
+ * duration percentile metrics (min, max, avg, p50, p95, p99) for BPMN elements within a process.
11086
+ *
11087
+ * @param processKey - Process key to filter by
11088
+ * @param packageId - Package identifier
11089
+ * @param startTime - Start of the time range to query
11090
+ * @param endTime - End of the time range to query
11091
+ * @param packageVersion - Package version to filter by
11092
+ * @returns Promise resolving to an array of {@link ElementStats}
11093
+ * @example
11094
+ * ```typescript
11095
+ * // Get element metrics for a process
11096
+ * const elements = await maestroProcesses.getElementStats(
11097
+ * '<processKey>',
11098
+ * '<packageId>',
11099
+ * new Date('2026-04-01'),
11100
+ * new Date(),
11101
+ * '1.0.1'
11102
+ * );
11103
+ *
11104
+ * // Analyze element performance
11105
+ * for (const element of elements) {
11106
+ * console.log(`Element: ${element.elementId}`);
11107
+ * console.log(` Success: ${element.successCount}, Failed: ${element.failCount}`);
11108
+ * console.log(` Avg duration: ${element.avgDurationMs}ms, P95: ${element.p95DurationMs}ms`);
11109
+ * }
11110
+ * ```
11111
+ */
11112
+ async getElementStats(processKey, packageId, startTime, endTime, packageVersion) {
11113
+ const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.ELEMENT_COUNT_BY_STATUS, buildElementCountByStatusBody(processKey, packageId, startTime, endTime, packageVersion));
11114
+ return data ?? [];
11115
+ }
10384
11116
  }
10385
11117
  __decorate([
10386
11118
  track('MaestroProcesses.GetAll')
@@ -10403,6 +11135,9 @@ __decorate([
10403
11135
  __decorate([
10404
11136
  track('MaestroProcesses.GetTopExecutionDuration')
10405
11137
  ], MaestroProcessesService.prototype, "getTopExecutionDuration", null);
11138
+ __decorate([
11139
+ track('MaestroProcesses.GetElementStats')
11140
+ ], MaestroProcessesService.prototype, "getElementStats", null);
10406
11141
 
10407
11142
  /**
10408
11143
  * Service class for Maestro Process Incidents
@@ -10458,7 +11193,7 @@ var ProcessType;
10458
11193
  class CasesService extends BaseService {
10459
11194
  /**
10460
11195
  * Get all case management processes with their instance statistics
10461
- * @returns Promise resolving to array of Case objects
11196
+ * @returns Promise resolving to an array of {@link CaseGetAllWithMethodsResponse}
10462
11197
  *
10463
11198
  * @example
10464
11199
  * ```typescript
@@ -10482,10 +11217,10 @@ class CasesService extends BaseService {
10482
11217
  const response = await this.get(MAESTRO_ENDPOINTS.PROCESSES.GET_ALL, { params });
10483
11218
  // Extract processes array from response data and add name field
10484
11219
  const cases = response.data?.processes || [];
10485
- return cases.map(caseItem => ({
11220
+ return cases.map(caseItem => createCaseWithMethods({
10486
11221
  ...caseItem,
10487
11222
  name: this.extractCaseName(caseItem.packageId)
10488
- }));
11223
+ }, this));
10489
11224
  }
10490
11225
  /**
10491
11226
  * Get the top 5 case processes ranked by run count within a time range.
@@ -10704,6 +11439,40 @@ class CasesService extends BaseService {
10704
11439
  const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.TOP_PROCESSES_BY_DURATION, buildInsightsTopBody(startTime, endTime, true, options));
10705
11440
  return (data ?? []).map(process => ({ ...process, name: this.extractCaseName(process.packageId) }));
10706
11441
  }
11442
+ /**
11443
+ * Get element stats for case instances
11444
+ *
11445
+ * Returns per-element execution counts (success, fail, terminated, paused, in-progress) and
11446
+ * duration percentile metrics (min, max, avg, p50, p95, p99) for BPMN elements within a case.
11447
+ *
11448
+ * @param processKey - Process key to filter by
11449
+ * @param packageId - Package identifier
11450
+ * @param startTime - Start of the time range to query
11451
+ * @param endTime - End of the time range to query
11452
+ * @param packageVersion - Package version to filter by
11453
+ * @returns Promise resolving to an array of {@link ElementStats}
11454
+ * @example
11455
+ * ```typescript
11456
+ * // Get element metrics for a case
11457
+ * const elements = await cases.getElementStats(
11458
+ * '<processKey>',
11459
+ * '<packageId>',
11460
+ * new Date('2026-04-01'),
11461
+ * new Date(),
11462
+ * '1.0.1'
11463
+ * );
11464
+ *
11465
+ * // Find elements with failures
11466
+ * const failedElements = elements.filter(e => e.failCount > 0);
11467
+ * for (const element of failedElements) {
11468
+ * console.log(`Failed element: ${element.elementId}, failures: ${element.failCount}`);
11469
+ * }
11470
+ * ```
11471
+ */
11472
+ async getElementStats(processKey, packageId, startTime, endTime, packageVersion) {
11473
+ const { data } = await this.post(MAESTRO_ENDPOINTS.INSIGHTS.ELEMENT_COUNT_BY_STATUS, buildElementCountByStatusBody(processKey, packageId, startTime, endTime, packageVersion));
11474
+ return data ?? [];
11475
+ }
10707
11476
  /**
10708
11477
  * Extract a readable case name from the packageId
10709
11478
  * @param packageId - The full package identifier
@@ -10741,6 +11510,9 @@ __decorate([
10741
11510
  __decorate([
10742
11511
  track('Cases.GetTopExecutionDuration')
10743
11512
  ], CasesService.prototype, "getTopExecutionDuration", null);
11513
+ __decorate([
11514
+ track('Cases.GetElementStats')
11515
+ ], CasesService.prototype, "getElementStats", null);
10744
11516
 
10745
11517
  /**
10746
11518
  * Maps fields for Case Instance entities to ensure consistent naming
@@ -10825,17 +11597,19 @@ function createTaskMethods(taskData, service) {
10825
11597
  async assign(options) {
10826
11598
  if (!taskData.id)
10827
11599
  throw new Error('Task ID is undefined');
11600
+ const criteria = options.assignmentCriteria !== undefined ? { assignmentCriteria: options.assignmentCriteria } : {};
10828
11601
  const assignmentOptions = 'userId' in options && options.userId !== undefined
10829
- ? { taskId: taskData.id, userId: options.userId }
10830
- : { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
11602
+ ? { taskId: taskData.id, userId: options.userId, ...criteria }
11603
+ : { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail, ...criteria };
10831
11604
  return service.assign(assignmentOptions);
10832
11605
  },
10833
11606
  async reassign(options) {
10834
11607
  if (!taskData.id)
10835
11608
  throw new Error('Task ID is undefined');
11609
+ const criteria = options.assignmentCriteria !== undefined ? { assignmentCriteria: options.assignmentCriteria } : {};
10836
11610
  const assignmentOptions = 'userId' in options && options.userId !== undefined
10837
- ? { taskId: taskData.id, userId: options.userId }
10838
- : { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail };
11611
+ ? { taskId: taskData.id, userId: options.userId, ...criteria }
11612
+ : { taskId: taskData.id, userNameOrEmail: options.userNameOrEmail, ...criteria };
10839
11613
  return service.reassign(assignmentOptions);
10840
11614
  },
10841
11615
  async unassign() {
@@ -11148,6 +11922,26 @@ class TaskService extends BaseService {
11148
11922
  * }
11149
11923
  * ]);
11150
11924
  * ```
11925
+ *
11926
+ * @example Group assignment
11927
+ * ```typescript
11928
+ * import { TaskAssignmentCriteria } from '@uipath/uipath-typescript/tasks';
11929
+ *
11930
+ * // Assign to a directory group by userId + criteria — Action Center
11931
+ * // distributes the task across the group's members based on the criteria
11932
+ * const result = await tasks.assign({
11933
+ * taskId: 123,
11934
+ * userId: 456, // a DirectoryGroup id from tasks.getUsers()
11935
+ * assignmentCriteria: TaskAssignmentCriteria.AllUsers
11936
+ * });
11937
+ *
11938
+ * // ...or identify the group by name instead of id
11939
+ * const result2 = await tasks.assign({
11940
+ * taskId: 123,
11941
+ * userNameOrEmail: "My Group",
11942
+ * assignmentCriteria: TaskAssignmentCriteria.AllUsers
11943
+ * });
11944
+ * ```
11151
11945
  */
11152
11946
  async assign(taskAssignments) {
11153
11947
  // Normalize input to array
@@ -11199,6 +11993,25 @@ class TaskService extends BaseService {
11199
11993
  * }
11200
11994
  * ]);
11201
11995
  * ```
11996
+ *
11997
+ * @example Group reassignment
11998
+ * ```typescript
11999
+ * import { TaskAssignmentCriteria } from '@uipath/uipath-typescript/tasks';
12000
+ *
12001
+ * // Reassign to a directory group by userId + criteria
12002
+ * const result = await tasks.reassign({
12003
+ * taskId: 123,
12004
+ * userId: 456, // a DirectoryGroup id from tasks.getUsers()
12005
+ * assignmentCriteria: TaskAssignmentCriteria.AllUsers
12006
+ * });
12007
+ *
12008
+ * // ...or identify the group by name instead of id
12009
+ * const result2 = await tasks.reassign({
12010
+ * taskId: 123,
12011
+ * userNameOrEmail: "My Group",
12012
+ * assignmentCriteria: TaskAssignmentCriteria.AllUsers
12013
+ * });
12014
+ * ```
11202
12015
  */
11203
12016
  async reassign(taskAssignments) {
11204
12017
  // Normalize input to array
@@ -11949,37 +12762,6 @@ function validateName(resourceType, name) {
11949
12762
  return trimmed;
11950
12763
  }
11951
12764
 
11952
- /**
11953
- * Encodes a folder path for the `X-UIPATH-FolderPath-Encoded` header.
11954
- *
11955
- * Orchestrator decodes this header as **base64-encoded UTF-16 LE bytes**
11956
- * (see `HttpHeadersProviderExtensions.GetDecoded` + `OrganizationUnitProvider`
11957
- * in the Orchestrator repo, which call `Encoding.Unicode.GetString(...)`).
11958
- * URL-encoding is NOT what the server expects — it must be base64-of-UTF-16-LE
11959
- * bytes.
11960
- *
11961
- * @param folderPath - The folder path (e.g. 'Shared/Finance')
11962
- * @returns Base64 string suitable for the `X-UIPATH-FolderPath-Encoded` header
11963
- */
11964
- function encodeFolderPathHeader(folderPath) {
11965
- // Force little-endian regardless of host byte order. `Uint16Array` viewed
11966
- // as `Uint8Array` would use the host's native order — correct on LE hosts
11967
- // (x86/ARM-LE) but wrong on BE hosts. `DataView.setUint16(..., true)`
11968
- // pins LE.
11969
- const buf = new ArrayBuffer(folderPath.length * 2);
11970
- const view = new DataView(buf);
11971
- for (let i = 0; i < folderPath.length; i++) {
11972
- view.setUint16(i * 2, folderPath.charCodeAt(i), true);
11973
- }
11974
- const bytes = new Uint8Array(buf);
11975
- let binary = '';
11976
- for (let i = 0; i < bytes.byteLength; i++) {
11977
- binary += String.fromCharCode(bytes[i]);
11978
- }
11979
- // btoa is browser-native; Node 16+ also has it as a global
11980
- return btoa(binary);
11981
- }
11982
-
11983
12765
  /**
11984
12766
  * Resolves folder context into the appropriate Orchestrator folder headers.
11985
12767
  *
@@ -12127,6 +12909,26 @@ function describeFolderForError(folderId, folderKey, folderPath) {
12127
12909
  return '';
12128
12910
  }
12129
12911
 
12912
+ /**
12913
+ * Enum for Asset Value Scope
12914
+ */
12915
+ exports.AssetValueScope = void 0;
12916
+ (function (AssetValueScope) {
12917
+ AssetValueScope["Global"] = "Global";
12918
+ AssetValueScope["PerRobot"] = "PerRobot";
12919
+ })(exports.AssetValueScope || (exports.AssetValueScope = {}));
12920
+ /**
12921
+ * Enum for Asset Value Type
12922
+ */
12923
+ exports.AssetValueType = void 0;
12924
+ (function (AssetValueType) {
12925
+ AssetValueType["Text"] = "Text";
12926
+ AssetValueType["Bool"] = "Bool";
12927
+ AssetValueType["Integer"] = "Integer";
12928
+ AssetValueType["Credential"] = "Credential";
12929
+ AssetValueType["Secret"] = "Secret";
12930
+ })(exports.AssetValueType || (exports.AssetValueType = {}));
12931
+
12130
12932
  /**
12131
12933
  * Maps fields for Asset entities to ensure consistent naming
12132
12934
  */
@@ -12251,6 +13053,68 @@ class AssetService extends FolderScopedService {
12251
13053
  async getByName(name, options = {}) {
12252
13054
  return this.getByNameLookup('Asset', ASSET_ENDPOINTS.GET_BY_FOLDER, name, options, (raw) => transformData(pascalToCamelCaseKeys(raw), AssetMap));
12253
13055
  }
13056
+ /**
13057
+ * Updates the value of an existing asset by ID.
13058
+ *
13059
+ * Fetches the asset internally to determine its type, then updates only the value while
13060
+ * preserving the asset's name, scope, and description.
13061
+ *
13062
+ * **Supported value types:** `Text`, `Integer`, and `Bool` only. Other types
13063
+ * (`Credential`, `Secret`) throw a `ValidationError`.
13064
+ *
13065
+ * The `newValue` runtime type must match the asset's `valueType`:
13066
+ * - `Text` → `string`
13067
+ * - `Integer` → `number` (integer)
13068
+ * - `Bool` → `boolean`
13069
+ *
13070
+ * @param id - Asset ID
13071
+ * @param newValue - New value to apply (string for `Text`, number for `Integer`, boolean for `Bool`)
13072
+ * @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`)
13073
+ * @returns Promise resolving when the asset has been updated
13074
+ *
13075
+ * @example
13076
+ * ```typescript
13077
+ * import { Assets } from '@uipath/uipath-typescript/assets';
13078
+ *
13079
+ * const assets = new Assets(sdk);
13080
+ *
13081
+ * // Update a Text asset by folder ID
13082
+ * await assets.updateValueById(<assetId>, 'new-value', { folderId: <folderId> });
13083
+ *
13084
+ * // Update an Integer asset by folder key (GUID)
13085
+ * await assets.updateValueById(<assetId>, 42, { folderKey: '5f6dadf1-3677-49dc-8aca-c2999dd4b3ba' });
13086
+ *
13087
+ * // Update a Bool asset by folder path
13088
+ * await assets.updateValueById(<assetId>, true, { folderPath: 'Shared/Finance' });
13089
+ * ```
13090
+ */
13091
+ async updateValueById(id, newValue, options) {
13092
+ if (!id) {
13093
+ throw new ValidationError({ message: 'id is required for updateValueById' });
13094
+ }
13095
+ if (newValue === null || newValue === undefined) {
13096
+ throw new ValidationError({ message: 'newValue is required for updateValueById' });
13097
+ }
13098
+ const headers = resolveFolderHeaders({
13099
+ folderId: options?.folderId,
13100
+ folderKey: options?.folderKey,
13101
+ folderPath: options?.folderPath,
13102
+ resourceType: 'Assets.updateValueById',
13103
+ fallbackFolderKey: this.config.folderKey,
13104
+ });
13105
+ const existingResponse = await this.get(ASSET_ENDPOINTS.GET_BY_ID(id), { headers });
13106
+ const existing = existingResponse.data;
13107
+ const valueField = resolveValueField(id, existing.ValueType, newValue);
13108
+ const body = {
13109
+ Id: id,
13110
+ Name: existing.Name,
13111
+ ValueScope: existing.ValueScope,
13112
+ ValueType: existing.ValueType,
13113
+ Description: existing.Description,
13114
+ [valueField]: newValue,
13115
+ };
13116
+ await this.put(ASSET_ENDPOINTS.GET_BY_ID(id), body, { headers });
13117
+ }
12254
13118
  }
12255
13119
  __decorate([
12256
13120
  track('Assets.GetAll')
@@ -12261,30 +13125,42 @@ __decorate([
12261
13125
  __decorate([
12262
13126
  track('Assets.GetByName')
12263
13127
  ], AssetService.prototype, "getByName", null);
12264
-
12265
- /**
12266
- * Enum for Asset Value Scope
12267
- */
12268
- exports.AssetValueScope = void 0;
12269
- (function (AssetValueScope) {
12270
- AssetValueScope["Global"] = "Global";
12271
- AssetValueScope["PerRobot"] = "PerRobot";
12272
- })(exports.AssetValueScope || (exports.AssetValueScope = {}));
13128
+ __decorate([
13129
+ track('Assets.UpdateValueById')
13130
+ ], AssetService.prototype, "updateValueById", null);
12273
13131
  /**
12274
- * Enum for Asset Value Type
13132
+ * Maps the asset's `valueType` to the PUT body field carrying the new value, validating
13133
+ * that the new value's runtime type matches the asset type.
12275
13134
  */
12276
- exports.AssetValueType = void 0;
12277
- (function (AssetValueType) {
12278
- AssetValueType["DBConnectionString"] = "DBConnectionString";
12279
- AssetValueType["HttpConnectionString"] = "HttpConnectionString";
12280
- AssetValueType["Text"] = "Text";
12281
- AssetValueType["Bool"] = "Bool";
12282
- AssetValueType["Integer"] = "Integer";
12283
- AssetValueType["Credential"] = "Credential";
12284
- AssetValueType["WindowsCredential"] = "WindowsCredential";
12285
- AssetValueType["KeyValueList"] = "KeyValueList";
12286
- AssetValueType["Secret"] = "Secret";
12287
- })(exports.AssetValueType || (exports.AssetValueType = {}));
13135
+ function resolveValueField(id, valueType, newValue) {
13136
+ switch (valueType) {
13137
+ case exports.AssetValueType.Text:
13138
+ if (typeof newValue !== 'string') {
13139
+ throw new ValidationError({
13140
+ message: `Asset ${id} has valueType Text; newValue must be a string, got ${typeof newValue}`,
13141
+ });
13142
+ }
13143
+ return 'StringValue';
13144
+ case exports.AssetValueType.Integer:
13145
+ if (typeof newValue !== 'number' || !Number.isInteger(newValue)) {
13146
+ throw new ValidationError({
13147
+ message: `Asset ${id} has valueType Integer; newValue must be an integer number, got ${typeof newValue}`,
13148
+ });
13149
+ }
13150
+ return 'IntValue';
13151
+ case exports.AssetValueType.Bool:
13152
+ if (typeof newValue !== 'boolean') {
13153
+ throw new ValidationError({
13154
+ message: `Asset ${id} has valueType Bool; newValue must be a boolean, got ${typeof newValue}`,
13155
+ });
13156
+ }
13157
+ return 'BoolValue';
13158
+ default:
13159
+ throw new ValidationError({
13160
+ message: `updateValueById only supports Text, Integer, or Bool assets; asset ${id} has valueType ${valueType}`,
13161
+ });
13162
+ }
13163
+ }
12288
13164
 
12289
13165
  /**
12290
13166
  * Maps fields for Bucket entities to ensure consistent naming
@@ -12421,48 +13297,32 @@ class BucketService extends FolderScopedService {
12421
13297
  }
12422
13298
  }, options);
12423
13299
  }
12424
- /**
12425
- * Gets metadata for files in a bucket with optional filtering and pagination
12426
- *
12427
- * The method returns either:
12428
- * - A NonPaginatedResponse with items array (when no pagination parameters are provided)
12429
- * - A PaginatedResponse with navigation cursors (when any pagination parameter is provided)
12430
- *
12431
- * @param bucketId - The ID of the bucket to get file metadata from
12432
- * @param folderId - Required folder ID for organization unit context
12433
- * @param options - Optional parameters for filtering, pagination and access URL generation
12434
- * @returns Promise resolving to the list of file metadata in the bucket or paginated result
12435
- *
12436
- * @example
12437
- * ```typescript
12438
- * import { Buckets } from '@uipath/uipath-typescript/buckets';
12439
- *
12440
- * const buckets = new Buckets(sdk);
12441
- *
12442
- * // Get metadata for all files in a bucket
12443
- * const fileMetadata = await buckets.getFileMetaData(123, 456);
12444
- *
12445
- * // Get file metadata with a specific prefix
12446
- * const fileMetadata = await buckets.getFileMetaData(123, 456, {
12447
- * prefix: '/folder1'
12448
- * });
12449
- *
12450
- * // First page with pagination
12451
- * const page1 = await buckets.getFileMetaData(123, 456, { pageSize: 10 });
12452
- *
12453
- * // Navigate using cursor
12454
- * if (page1.hasNextPage) {
12455
- * const page2 = await buckets.getFileMetaData(123, 456, { cursor: page1.nextCursor });
12456
- * }
12457
- * ```
12458
- */
12459
- async getFileMetaData(bucketId, folderId, options) {
13300
+ async getFileMetaData(bucketId, optionsOrFolderId, legacyOptions) {
12460
13301
  if (!bucketId) {
12461
13302
  throw new ValidationError({ message: 'bucketId is required for getFileMetaData' });
12462
13303
  }
12463
- if (!folderId) {
12464
- throw new ValidationError({ message: 'folderId is required for getFileMetaData' });
13304
+ // Normalize the two overload forms into a single internal shape.
13305
+ let folderId;
13306
+ let folderKey;
13307
+ let folderPath;
13308
+ let restOptions;
13309
+ if (typeof optionsOrFolderId === 'number') {
13310
+ // Deprecated positional form: getFileMetaData(bucketId, folderId, options?)
13311
+ folderId = optionsOrFolderId;
13312
+ restOptions = (legacyOptions ?? {});
13313
+ }
13314
+ else {
13315
+ // Preferred form: getFileMetaData(bucketId, options?)
13316
+ const opts = optionsOrFolderId ?? {};
13317
+ ({ folderId, folderKey, folderPath, ...restOptions } = opts);
12465
13318
  }
13319
+ const headers = resolveFolderHeaders({
13320
+ folderId,
13321
+ folderKey,
13322
+ folderPath,
13323
+ resourceType: 'Buckets.getFileMetaData',
13324
+ fallbackFolderKey: this.config.folderKey,
13325
+ });
12466
13326
  // Transformation function for blob items
12467
13327
  const transformBlobItem = (item) => transformData(item, BucketMap);
12468
13328
  return PaginationHelpers.getAll({
@@ -12478,93 +13338,97 @@ class BucketService extends FolderScopedService {
12478
13338
  tokenParam: BUCKET_TOKEN_PARAMS.TOKEN_PARAM
12479
13339
  }
12480
13340
  },
12481
- excludeFromPrefix: ['prefix'] // Bucket-specific param, not OData
12482
- }, { ...options, folderId });
13341
+ excludeFromPrefix: ['prefix'], // Bucket-specific param, not OData
13342
+ headers,
13343
+ }, restOptions);
12483
13344
  }
12484
- /**
12485
- * Uploads a file to a bucket
12486
- *
12487
- * @param options - Options for file upload including bucket ID, folder ID, path, content, and optional parameters
12488
- * @returns Promise resolving to a response with success status and HTTP status code
12489
- *
12490
- * @example
12491
- * ```typescript
12492
- * import { Buckets } from '@uipath/uipath-typescript/buckets';
12493
- *
12494
- * const buckets = new Buckets(sdk);
12495
- *
12496
- * // Upload a file from browser
12497
- * const file = new File(['file content'], 'example.txt');
12498
- * const result = await buckets.uploadFile({
12499
- * bucketId: 123,
12500
- * folderId: 456,
12501
- * path: '/folder/example.txt',
12502
- * content: file
12503
- * });
12504
- *
12505
- * // In Node env with Buffer
12506
- * const buffer = Buffer.from('file content');
12507
- * const result = await buckets.uploadFile({
12508
- * bucketId: 123,
12509
- * folderId: 456,
12510
- * path: '/folder/example.txt',
12511
- * content: buffer
12512
- * });
12513
- * ```
12514
- */
12515
- async uploadFile(options) {
12516
- const { bucketId, folderId, path, content } = options;
13345
+ async uploadFile(bucketIdOrOptions, path, content, options) {
13346
+ // Normalize the two overload forms into a single internal shape.
13347
+ let bucketId;
13348
+ let resolvedPath;
13349
+ let resolvedContent;
13350
+ let folderId;
13351
+ let folderKey;
13352
+ let folderPath;
13353
+ if (bucketIdOrOptions !== null && typeof bucketIdOrOptions === 'object') {
13354
+ // Deprecated options-only form: uploadFile({ bucketId, path, content, ... })
13355
+ ({ bucketId, path: resolvedPath, content: resolvedContent, folderId, folderKey, folderPath } = bucketIdOrOptions);
13356
+ }
13357
+ else {
13358
+ // Preferred positional form: uploadFile(bucketId, path, content, options?)
13359
+ bucketId = bucketIdOrOptions;
13360
+ resolvedPath = path;
13361
+ resolvedContent = content;
13362
+ const opts = options ?? {};
13363
+ ({ folderId, folderKey, folderPath } = opts);
13364
+ }
12517
13365
  if (!bucketId) {
12518
13366
  throw new ValidationError({ message: 'bucketId is required for uploadFile' });
12519
13367
  }
12520
- if (!folderId) {
12521
- throw new ValidationError({ message: 'folderId is required for uploadFile' });
12522
- }
12523
- if (!path) {
13368
+ if (!resolvedPath) {
12524
13369
  throw new ValidationError({ message: 'path is required for uploadFile' });
12525
13370
  }
12526
- if (!content) {
13371
+ if (!resolvedContent) {
12527
13372
  throw new ValidationError({ message: 'content is required for uploadFile' });
12528
13373
  }
13374
+ const headers = resolveFolderHeaders({
13375
+ folderId,
13376
+ folderKey,
13377
+ folderPath,
13378
+ resourceType: 'Buckets.uploadFile',
13379
+ fallbackFolderKey: this.config.folderKey,
13380
+ });
12529
13381
  const uriResponse = await this._getWriteUri({
12530
13382
  bucketId,
12531
- folderId,
12532
- path,
13383
+ path: resolvedPath,
13384
+ headers,
12533
13385
  });
12534
13386
  // Upload file to the provided URI
12535
- const response = await this._uploadToUri(uriResponse, content);
13387
+ const response = await this._uploadToUri(uriResponse, resolvedContent);
12536
13388
  return {
12537
13389
  success: response.status >= 200 && response.status < 300,
12538
13390
  statusCode: response.status
12539
13391
  };
12540
13392
  }
12541
- /**
12542
- * Gets a direct download URL for a file in the bucket
12543
- *
12544
- * @param options - Contains bucketId, folderId, file path and optional expiry time
12545
- * @returns Promise resolving to blob file access information
12546
- *
12547
- * @example
12548
- * ```typescript
12549
- * import { Buckets } from '@uipath/uipath-typescript/buckets';
12550
- *
12551
- * const buckets = new Buckets(sdk);
12552
- *
12553
- * // Get download URL for a file
12554
- * const fileAccess = await buckets.getReadUri({
12555
- * bucketId: 123,
12556
- * folderId: 456,
12557
- * path: '/folder/file.pdf'
12558
- * });
12559
- * ```
12560
- */
12561
- async getReadUri(options) {
12562
- const { bucketId, folderId, path, expiryInMinutes, ...restOptions } = options;
13393
+ async getReadUri(bucketIdOrOptions, path, options) {
13394
+ // Normalize the two overload forms into a single internal shape.
13395
+ let bucketId;
13396
+ let resolvedPath;
13397
+ let folderId;
13398
+ let folderKey;
13399
+ let folderPath;
13400
+ let expiryInMinutes;
13401
+ let restOptions;
13402
+ if (bucketIdOrOptions !== null && typeof bucketIdOrOptions === 'object') {
13403
+ // Deprecated options-only form: getReadUri({ bucketId, path, ... })
13404
+ const { bucketId: bid, path: p, expiryInMinutes: e, folderId: fid, folderKey: fkey, folderPath: fpath, ...rest } = bucketIdOrOptions;
13405
+ bucketId = bid;
13406
+ resolvedPath = p;
13407
+ expiryInMinutes = e;
13408
+ folderId = fid;
13409
+ folderKey = fkey;
13410
+ folderPath = fpath;
13411
+ restOptions = rest;
13412
+ }
13413
+ else {
13414
+ // Preferred positional form: getReadUri(bucketId, path, options?)
13415
+ bucketId = bucketIdOrOptions;
13416
+ resolvedPath = path;
13417
+ const opts = options ?? {};
13418
+ ({ expiryInMinutes, folderId, folderKey, folderPath, ...restOptions } = opts);
13419
+ }
13420
+ const headers = resolveFolderHeaders({
13421
+ folderId,
13422
+ folderKey,
13423
+ folderPath,
13424
+ resourceType: 'Buckets.getReadUri',
13425
+ fallbackFolderKey: this.config.folderKey,
13426
+ });
12563
13427
  const queryOptions = {
12564
13428
  expiryInMinutes,
12565
13429
  ...addPrefixToKeys(restOptions, ODATA_PREFIX, Object.keys(restOptions))
12566
13430
  };
12567
- return this._getUri(BUCKET_ENDPOINTS.GET_READ_URI(bucketId), bucketId, folderId, path, queryOptions);
13431
+ return this._getUri(BUCKET_ENDPOINTS.GET_READ_URI(bucketId), bucketId, resolvedPath, headers, queryOptions);
12568
13432
  }
12569
13433
  /**
12570
13434
  * Uploads content to the provided URI
@@ -12594,23 +13458,18 @@ class BucketService extends FolderScopedService {
12594
13458
  * Private method to handle common URI request logic
12595
13459
  * @param endpoint - The API endpoint to call
12596
13460
  * @param bucketId - The bucket ID
12597
- * @param folderId - The folder ID
12598
13461
  * @param path - The file path
13462
+ * @param headers - Pre-built folder-context headers (built via `resolveFolderHeaders`)
12599
13463
  * @param queryOptions - Additional query parameters
12600
13464
  * @returns Promise resolving to blob file access information
12601
13465
  */
12602
- async _getUri(endpoint, bucketId, folderId, path, queryOptions = {}) {
13466
+ async _getUri(endpoint, bucketId, path, headers, queryOptions = {}) {
12603
13467
  if (!bucketId) {
12604
13468
  throw new ValidationError({ message: 'bucketId is required for getUri' });
12605
13469
  }
12606
- if (!folderId) {
12607
- throw new ValidationError({ message: 'folderId is required for getUri' });
12608
- }
12609
13470
  if (!path) {
12610
13471
  throw new ValidationError({ message: 'path is required for getUri' });
12611
13472
  }
12612
- // Create headers with required folder ID
12613
- const headers = createHeaders({ [FOLDER_ID]: folderId });
12614
13473
  // Filter out undefined values and build query params
12615
13474
  const queryParams = filterUndefined({
12616
13475
  path,
@@ -12745,16 +13604,16 @@ class BucketService extends FolderScopedService {
12745
13604
  /**
12746
13605
  * Gets a direct upload URL for a file in the bucket
12747
13606
  *
12748
- * @param options - Contains bucketId, folderId, file path, optional expiry time
13607
+ * @param options - Contains bucketId, file path, optional expiry time, and pre-built folder-context headers
12749
13608
  * @returns Promise resolving to blob file access information
12750
13609
  */
12751
13610
  async _getWriteUri(options) {
12752
- const { bucketId, folderId, path, expiryInMinutes, ...restOptions } = options;
13611
+ const { bucketId, path, expiryInMinutes, headers, ...restOptions } = options;
12753
13612
  const queryOptions = {
12754
13613
  expiryInMinutes,
12755
13614
  ...addPrefixToKeys(restOptions, ODATA_PREFIX, Object.keys(restOptions))
12756
13615
  };
12757
- return this._getUri(BUCKET_ENDPOINTS.GET_WRITE_URI(bucketId), bucketId, folderId, path, queryOptions);
13616
+ return this._getUri(BUCKET_ENDPOINTS.GET_WRITE_URI(bucketId), bucketId, path, headers, queryOptions);
12758
13617
  }
12759
13618
  }
12760
13619
  __decorate([
@@ -14201,6 +15060,57 @@ exports.FeedbackStatus = void 0;
14201
15060
  FeedbackStatus[FeedbackStatus["Dismissed"] = 2] = "Dismissed";
14202
15061
  })(exports.FeedbackStatus || (exports.FeedbackStatus = {}));
14203
15062
 
15063
+ /**
15064
+ * Columns available for ordering results.
15065
+ */
15066
+ exports.AgentListSortColumn = void 0;
15067
+ (function (AgentListSortColumn) {
15068
+ AgentListSortColumn["AgentName"] = "AgentName";
15069
+ AgentListSortColumn["ParentProcess"] = "ParentProcess";
15070
+ AgentListSortColumn["LastRun"] = "LastRun";
15071
+ AgentListSortColumn["HealthScore"] = "HealthScore";
15072
+ AgentListSortColumn["LastIncident"] = "LastIncident";
15073
+ AgentListSortColumn["FolderName"] = "FolderName";
15074
+ /** Quantity of AGU (Agent Units) consumed */
15075
+ AgentListSortColumn["QuantityAGU"] = "QuantityAGU";
15076
+ /** Quantity of PLTU (Platform Units) consumed */
15077
+ AgentListSortColumn["QuantityPLTU"] = "QuantityPLTU";
15078
+ AgentListSortColumn["FolderPath"] = "FolderPath";
15079
+ })(exports.AgentListSortColumn || (exports.AgentListSortColumn = {}));
15080
+ /**
15081
+ * Columns available for ordering / grouping the agent errors list.
15082
+ */
15083
+ exports.AgentErrorSortColumn = void 0;
15084
+ (function (AgentErrorSortColumn) {
15085
+ AgentErrorSortColumn["AgentId"] = "AgentId";
15086
+ AgentErrorSortColumn["AgentName"] = "AgentName";
15087
+ AgentErrorSortColumn["ParentProcessName"] = "ParentProcessName";
15088
+ AgentErrorSortColumn["ErrorTitle"] = "ErrorTitle";
15089
+ AgentErrorSortColumn["FirstSeenStartTime"] = "FirstSeenStartTime";
15090
+ AgentErrorSortColumn["ExecutionCount"] = "ExecutionCount";
15091
+ AgentErrorSortColumn["Type"] = "Type";
15092
+ AgentErrorSortColumn["FirstSeenFolderName"] = "FirstSeenFolderName";
15093
+ AgentErrorSortColumn["FirstSeenFolderPath"] = "FirstSeenFolderPath";
15094
+ AgentErrorSortColumn["LastSeenStartTime"] = "LastSeenStartTime";
15095
+ AgentErrorSortColumn["LastSeenFolderName"] = "LastSeenFolderName";
15096
+ AgentErrorSortColumn["LastSeenFolderPath"] = "LastSeenFolderPath";
15097
+ })(exports.AgentErrorSortColumn || (exports.AgentErrorSortColumn = {}));
15098
+
15099
+ /**
15100
+ * Types for the Agent Memory metrics service.
15101
+ */
15102
+ /**
15103
+ * Execution kind to filter Agent Memory queries by. Omit to include both
15104
+ * Debug and Runtime executions.
15105
+ */
15106
+ exports.AgentMemoryExecutionType = void 0;
15107
+ (function (AgentMemoryExecutionType) {
15108
+ /** Executions produced during agent debugging sessions. */
15109
+ AgentMemoryExecutionType["Debug"] = "Debug";
15110
+ /** Executions produced during production runtime. */
15111
+ AgentMemoryExecutionType["Runtime"] = "Runtime";
15112
+ })(exports.AgentMemoryExecutionType || (exports.AgentMemoryExecutionType = {}));
15113
+
14204
15114
  // Auto-generated from the OpenAPI spec — do not edit manually.
14205
15115
  var DocumentActionPriority;
14206
15116
  (function (DocumentActionPriority) {
@@ -14472,6 +15382,103 @@ var index = /*#__PURE__*/Object.freeze({
14472
15382
  get WordGroupType () { return WordGroupType; }
14473
15383
  });
14474
15384
 
15385
+ /**
15386
+ * Governance Service Types
15387
+ *
15388
+ * Public types exposed via `@uipath/uipath-typescript/governance`.
15389
+ */
15390
+ exports.PolicyEvaluationResult = void 0;
15391
+ (function (PolicyEvaluationResult) {
15392
+ /** Active policy permitted the action. */
15393
+ PolicyEvaluationResult["Allow"] = "Allow";
15394
+ /** Active policy blocked the action. */
15395
+ PolicyEvaluationResult["Deny"] = "Deny";
15396
+ /** Simulated (NoOp) policy would have permitted the action. */
15397
+ PolicyEvaluationResult["SimulatedAllow"] = "SimulatedAllow";
15398
+ /** Simulated (NoOp) policy would have blocked the action. */
15399
+ PolicyEvaluationResult["SimulatedDeny"] = "SimulatedDeny";
15400
+ })(exports.PolicyEvaluationResult || (exports.PolicyEvaluationResult = {}));
15401
+
15402
+ /** Status of a span: whether it completed successfully, with an error, or was not set. */
15403
+ exports.SpanStatus = void 0;
15404
+ (function (SpanStatus) {
15405
+ SpanStatus["Unset"] = "Unset";
15406
+ SpanStatus["Ok"] = "Ok";
15407
+ SpanStatus["Error"] = "Error";
15408
+ /** Span is still in progress. */
15409
+ SpanStatus["Running"] = "Running";
15410
+ /** Span data is hidden from the caller due to tenant/folder permission rules. */
15411
+ SpanStatus["Restricted"] = "Restricted";
15412
+ /** Span was cancelled before completion. */
15413
+ SpanStatus["Cancelled"] = "Cancelled";
15414
+ })(exports.SpanStatus || (exports.SpanStatus = {}));
15415
+ /** Platform source that produced the span. */
15416
+ exports.SpanSource = void 0;
15417
+ (function (SpanSource) {
15418
+ SpanSource["Testing"] = "Testing";
15419
+ SpanSource["Agents"] = "Agents";
15420
+ SpanSource["ProcessOrchestration"] = "ProcessOrchestration";
15421
+ SpanSource["ApiWorkflows"] = "ApiWorkflows";
15422
+ SpanSource["Robots"] = "Robots";
15423
+ SpanSource["ConversationalAgentsService"] = "ConversationalAgentsService";
15424
+ SpanSource["IntegrationServiceTrigger"] = "IntegrationServiceTrigger";
15425
+ SpanSource["Playground"] = "Playground";
15426
+ SpanSource["Governance"] = "Governance";
15427
+ /** Intelligent Experience Platform — unstructured and complex document processing source. */
15428
+ SpanSource["IXPUnstructuredAndComplexDocuments"] = "IXPUnstructuredAndComplexDocuments";
15429
+ /** Agents authored in code (as opposed to visual/no-code designers). */
15430
+ SpanSource["CodedAgents"] = "CodedAgents";
15431
+ /** Intelligent Experience Platform — communications mining source. */
15432
+ SpanSource["IXPCommunicationsMining"] = "IXPCommunicationsMining";
15433
+ /** UiPath Context Grounding — span produced by the Enterprise Context Service for RAG/knowledge-base operations. */
15434
+ SpanSource["EnterpriseContextService"] = "EnterpriseContextService";
15435
+ /** Model Context Protocol — span produced by an MCP server integration. */
15436
+ SpanSource["MCP"] = "MCP";
15437
+ /** Agent-to-Agent — span produced by an A2A protocol call between agents. */
15438
+ SpanSource["A2A"] = "A2A";
15439
+ /** Serverless — span produced by a serverless function execution. */
15440
+ SpanSource["Serverless"] = "Serverless";
15441
+ })(exports.SpanSource || (exports.SpanSource = {}));
15442
+ /** Minimum severity level of events captured in the span. */
15443
+ exports.SpanVerbosityLevel = void 0;
15444
+ (function (SpanVerbosityLevel) {
15445
+ SpanVerbosityLevel["Verbose"] = "Verbose";
15446
+ SpanVerbosityLevel["Trace"] = "Trace";
15447
+ SpanVerbosityLevel["Information"] = "Information";
15448
+ SpanVerbosityLevel["Warning"] = "Warning";
15449
+ SpanVerbosityLevel["Error"] = "Error";
15450
+ SpanVerbosityLevel["Critical"] = "Critical";
15451
+ SpanVerbosityLevel["Off"] = "Off";
15452
+ })(exports.SpanVerbosityLevel || (exports.SpanVerbosityLevel = {}));
15453
+ /** Whether the span was produced during a debug or production runtime. */
15454
+ exports.SpanExecutionType = void 0;
15455
+ (function (SpanExecutionType) {
15456
+ SpanExecutionType["Debug"] = "Debug";
15457
+ SpanExecutionType["Runtime"] = "Runtime";
15458
+ })(exports.SpanExecutionType || (exports.SpanExecutionType = {}));
15459
+ /** Whether the caller has permission to read this span's data. */
15460
+ exports.SpanPermissionStatus = void 0;
15461
+ (function (SpanPermissionStatus) {
15462
+ SpanPermissionStatus["Allow"] = "Allow";
15463
+ /** Some span fields are redacted due to permission constraints (e.g. attributes visible but payload hidden). */
15464
+ SpanPermissionStatus["PartialBlock"] = "PartialBlock";
15465
+ SpanPermissionStatus["Block"] = "Block";
15466
+ })(exports.SpanPermissionStatus || (exports.SpanPermissionStatus = {}));
15467
+ /** Storage provider that created or manages the attachment. */
15468
+ exports.SpanAttachmentProvider = void 0;
15469
+ (function (SpanAttachmentProvider) {
15470
+ SpanAttachmentProvider["Orchestrator"] = "Orchestrator";
15471
+ /** Span attachment stored by the observability platform. */
15472
+ SpanAttachmentProvider["LLMOps"] = "LLMOps";
15473
+ })(exports.SpanAttachmentProvider || (exports.SpanAttachmentProvider = {}));
15474
+ /** Whether the attachment is an input, output, or neither. */
15475
+ exports.SpanAttachmentDirection = void 0;
15476
+ (function (SpanAttachmentDirection) {
15477
+ SpanAttachmentDirection["None"] = "None";
15478
+ SpanAttachmentDirection["In"] = "In";
15479
+ SpanAttachmentDirection["Out"] = "Out";
15480
+ })(exports.SpanAttachmentDirection || (exports.SpanAttachmentDirection = {}));
15481
+
14475
15482
  /**
14476
15483
  * Asset resolution utilities for UiPath Coded Apps
14477
15484
  *
@@ -14548,6 +15555,7 @@ function getAppBase() {
14548
15555
  }
14549
15556
 
14550
15557
  exports.AgentMap = AgentMap;
15558
+ exports.AgentTraceExecutionType = exports.SpanExecutionType;
14551
15559
  exports.AuthenticationError = AuthenticationError;
14552
15560
  exports.AuthorizationError = AuthorizationError;
14553
15561
  exports.ConversationGetAllFilterMap = ConversationGetAllFilterMap;
@@ -14571,6 +15579,7 @@ exports.UserSettingsMap = UserSettingsMap;
14571
15579
  exports.ValidationError = ValidationError;
14572
15580
  exports.createAgentWithMethods = createAgentWithMethods;
14573
15581
  exports.createCaseInstanceWithMethods = createCaseInstanceWithMethods;
15582
+ exports.createCaseWithMethods = createCaseWithMethods;
14574
15583
  exports.createConversationWithMethods = createConversationWithMethods;
14575
15584
  exports.createEntityWithMethods = createEntityWithMethods;
14576
15585
  exports.createJobWithMethods = createJobWithMethods;