@uipath/uipath-typescript 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -3883,6 +3883,7 @@ class ExecutionContext {
3883
3883
  * Checks if code is running in a browser environment
3884
3884
  */
3885
3885
  const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
3886
+ const isInActionCenter = isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
3886
3887
 
3887
3888
  /**
3888
3889
  * Session storage keys used by the auth module
@@ -4199,6 +4200,102 @@ function getErrorDetails(error) {
4199
4200
  };
4200
4201
  }
4201
4202
 
4203
+ var ActionCenterEventNames;
4204
+ (function (ActionCenterEventNames) {
4205
+ ActionCenterEventNames["TOKENREFRESHED"] = "AC.tokenRefreshed";
4206
+ ActionCenterEventNames["REFRESHTOKEN"] = "AC.refreshToken";
4207
+ })(ActionCenterEventNames || (ActionCenterEventNames = {}));
4208
+
4209
+ const AUTHENTICATION_TIMEOUT = 8000;
4210
+ class ActionCenterTokenManager {
4211
+ constructor(config, onTokenRefreshed) {
4212
+ this.config = config;
4213
+ this.onTokenRefreshed = onTokenRefreshed;
4214
+ this.parentOrigin = new URLSearchParams(window.location.search).get('basedomain');
4215
+ this.refreshPromise = null;
4216
+ }
4217
+ async refreshAccessToken(tokenInfo) {
4218
+ if (!this.isTokenExpired(tokenInfo)) {
4219
+ return tokenInfo.token;
4220
+ }
4221
+ if (this.refreshPromise) {
4222
+ return this.refreshPromise;
4223
+ }
4224
+ this.refreshPromise = new Promise((resolve, reject) => {
4225
+ const content = {
4226
+ clientId: this.config.clientId,
4227
+ scope: this.config.scope,
4228
+ };
4229
+ this.sendMessageToParent(ActionCenterEventNames.REFRESHTOKEN, content);
4230
+ const messageListener = (event) => {
4231
+ if (event.origin !== this.parentOrigin)
4232
+ return;
4233
+ if (event.data?.eventType !== ActionCenterEventNames.TOKENREFRESHED)
4234
+ return;
4235
+ clearTimeout(timer);
4236
+ if (event.data?.content?.token) {
4237
+ const { accessToken, expiresAt } = event.data.content.token;
4238
+ this.onTokenRefreshed({ token: accessToken, type: 'secret', expiresAt });
4239
+ resolve(accessToken);
4240
+ }
4241
+ else {
4242
+ reject(new AuthenticationError({
4243
+ message: 'Failed to fetch access token',
4244
+ statusCode: HttpStatus.UNAUTHORIZED,
4245
+ }));
4246
+ }
4247
+ this.refreshPromise = null;
4248
+ this.cleanup(messageListener);
4249
+ };
4250
+ const timer = setTimeout(() => {
4251
+ reject(new AuthenticationError({
4252
+ message: 'Failed to fetch access token',
4253
+ statusCode: HttpStatus.UNAUTHORIZED,
4254
+ }));
4255
+ this.refreshPromise = null;
4256
+ this.cleanup(messageListener);
4257
+ }, AUTHENTICATION_TIMEOUT);
4258
+ window.addEventListener('message', messageListener);
4259
+ });
4260
+ return this.refreshPromise;
4261
+ }
4262
+ isTokenExpired(tokenInfo) {
4263
+ if (!tokenInfo?.expiresAt) {
4264
+ return true;
4265
+ }
4266
+ return new Date() >= tokenInfo.expiresAt;
4267
+ }
4268
+ sendMessageToParent(eventType, content) {
4269
+ if (window.parent && this.isValidOrigin(this.parentOrigin)) {
4270
+ try {
4271
+ window.parent.postMessage({ eventType, content }, this.parentOrigin);
4272
+ }
4273
+ catch (error) {
4274
+ console.warn('Failed to send message to Action Center', JSON.stringify(error));
4275
+ }
4276
+ }
4277
+ }
4278
+ cleanup(messageListener) {
4279
+ window.removeEventListener('message', messageListener);
4280
+ }
4281
+ isValidOrigin(origin) {
4282
+ const ALLOWED_ORIGINS = ['https://alpha.uipath.com', 'https://staging.uipath.com', 'https://cloud.uipath.com'];
4283
+ if (!origin) {
4284
+ return false;
4285
+ }
4286
+ if (ALLOWED_ORIGINS.includes(origin)) {
4287
+ return true;
4288
+ }
4289
+ try {
4290
+ const url = new URL(origin);
4291
+ return url.hostname === 'localhost';
4292
+ }
4293
+ catch {
4294
+ return false;
4295
+ }
4296
+ }
4297
+ }
4298
+
4202
4299
  /**
4203
4300
  * TokenManager is responsible for managing authentication tokens.
4204
4301
  * It provides token operations for a specific client ID.
@@ -4217,6 +4314,11 @@ class TokenManager {
4217
4314
  this.config = config;
4218
4315
  this.isOAuth = isOAuth;
4219
4316
  this.refreshPromise = null;
4317
+ this.actionCenterTokenManager = null;
4318
+ if (isInActionCenter) {
4319
+ this.actionCenterTokenManager = new ActionCenterTokenManager(config, (tokenInfo) => this.setToken(tokenInfo));
4320
+ this.isOAuth = false;
4321
+ }
4220
4322
  }
4221
4323
  /**
4222
4324
  * Checks if a token is expired
@@ -4244,6 +4346,9 @@ class TokenManager {
4244
4346
  message: 'No authentication token available. Make sure to initialize the SDK first.'
4245
4347
  });
4246
4348
  }
4349
+ if (this.actionCenterTokenManager) {
4350
+ return await this.actionCenterTokenManager.refreshAccessToken(tokenInfo);
4351
+ }
4247
4352
  // For secret-based tokens, they never expire
4248
4353
  if (tokenInfo.type === 'secret') {
4249
4354
  return tokenInfo.token;
@@ -4388,9 +4493,6 @@ class TokenManager {
4388
4493
  clearToken() {
4389
4494
  this.currentToken = undefined;
4390
4495
  this.executionContext.set('tokenInfo', undefined);
4391
- const headers = this.executionContext.getHeaders();
4392
- delete headers['Authorization'];
4393
- this.executionContext.setHeaders(headers);
4394
4496
  // Remove from session storage if this is an OAuth token
4395
4497
  if (isBrowser && this.isOAuth) {
4396
4498
  try {
@@ -4406,10 +4508,6 @@ class TokenManager {
4406
4508
  */
4407
4509
  _updateExecutionContext(tokenInfo) {
4408
4510
  this.executionContext.set('tokenInfo', tokenInfo);
4409
- // Update authorization header
4410
- this.executionContext.setHeaders({
4411
- 'Authorization': `Bearer ${tokenInfo.token}`
4412
- });
4413
4511
  }
4414
4512
  /**
4415
4513
  * Refreshes the access token using the stored refresh token.
@@ -4593,6 +4691,7 @@ const DATA_FABRIC_ENDPOINTS = {
4593
4691
  UPDATE_BY_ID: (entityId) => `${DATAFABRIC_BASE}/api/EntityService/entity/${entityId}/update-batch`,
4594
4692
  DELETE_BY_ID: (entityId) => `${DATAFABRIC_BASE}/api/EntityService/entity/${entityId}/delete-batch`,
4595
4693
  DOWNLOAD_ATTACHMENT: (entityName, recordId, fieldName) => `${DATAFABRIC_BASE}/api/Attachment/${entityName}/${recordId}/${fieldName}`,
4694
+ UPLOAD_ATTACHMENT: (entityName, recordId, fieldName) => `${DATAFABRIC_BASE}/api/Attachment/${entityName}/${recordId}/${fieldName}`,
4596
4695
  },
4597
4696
  CHOICESETS: {
4598
4697
  GET_ALL: `${DATAFABRIC_BASE}/api/Entity/choiceset`,
@@ -4613,8 +4712,15 @@ const IDENTITY_ENDPOINTS = {
4613
4712
 
4614
4713
  class AuthService {
4615
4714
  constructor(config, executionContext) {
4616
- // Check if we should use stored OAuth context instead of provided config
4617
- const storedContext = AuthService.getStoredOAuthContext();
4715
+ // Only use stored OAuth context when completing an active callback (URL has ?code=).
4716
+ // If stored context exists but we're NOT in a callback, it's stale from a
4717
+ // failed/abandoned flow (e.g. scope mismatch, invalid redirect URI) and must
4718
+ // be cleared so the fresh config takes effect.
4719
+ const isCallback = AuthService.isInOAuthCallback();
4720
+ const storedContext = isCallback ? AuthService.getStoredOAuthContext() : null;
4721
+ if (!isCallback) {
4722
+ AuthService._clearStoredOAuthContext();
4723
+ }
4618
4724
  const effectiveConfig = storedContext ? AuthService._mergeConfigWithContext(config, storedContext) : config;
4619
4725
  this.config = effectiveConfig;
4620
4726
  const isOAuth = hasOAuthConfig(effectiveConfig);
@@ -4661,6 +4767,22 @@ class AuthService {
4661
4767
  return null;
4662
4768
  }
4663
4769
  }
4770
+ /**
4771
+ * Clear stale OAuth context from session storage.
4772
+ * Called when there is no active OAuth callback, meaning any stored context
4773
+ * is left over from a failed or abandoned flow.
4774
+ */
4775
+ static _clearStoredOAuthContext() {
4776
+ if (!isBrowser)
4777
+ return;
4778
+ try {
4779
+ sessionStorage.removeItem(AUTH_STORAGE_KEYS.OAUTH_CONTEXT);
4780
+ sessionStorage.removeItem(AUTH_STORAGE_KEYS.CODE_VERIFIER);
4781
+ }
4782
+ catch {
4783
+ // Ignore storage errors
4784
+ }
4785
+ }
4664
4786
  /**
4665
4787
  * Merges provided config with stored OAuth context, prioritizing stored values
4666
4788
  */
@@ -4969,13 +5091,41 @@ class AuthService {
4969
5091
  }
4970
5092
  }
4971
5093
 
5094
+ /**
5095
+ * Check if config has all required base fields
5096
+ */
5097
+ function hasRequiredBaseFields(config) {
5098
+ return Boolean(config.baseUrl && config.orgName && config.tenantName);
5099
+ }
5100
+ /**
5101
+ * Check if config has exactly one authentication method (secret XOR oauth)
5102
+ * Returns true if exactly one auth method is present, false otherwise
5103
+ */
5104
+ function hasValidAuthConfig(config) {
5105
+ const hasSecret = hasSecretConfig(config);
5106
+ const hasOAuth = hasOAuthConfig(config);
5107
+ // XOR: exactly one auth method, not both, not neither
5108
+ return hasSecret !== hasOAuth;
5109
+ }
4972
5110
  function validateConfig(config) {
4973
- if (!config.baseUrl || !config.orgName || !config.tenantName) {
5111
+ if (!hasRequiredBaseFields(config)) {
4974
5112
  throw new Error('Missing required configuration: baseUrl, orgName, and tenantName are required');
4975
5113
  }
4976
- if (!hasSecretConfig(config) && !hasOAuthConfig(config)) {
4977
- throw new Error('Invalid configuration: must provide either secret or (clientId, redirectUri, and scope)');
5114
+ const hasSecret = hasSecretConfig(config);
5115
+ const hasOAuth = hasOAuthConfig(config);
5116
+ if (hasSecret && hasOAuth) {
5117
+ throw new Error('Invalid configuration: cannot provide both secret and OAuth credentials. Choose one authentication method.');
4978
5118
  }
5119
+ if (!hasSecret && !hasOAuth) {
5120
+ throw new Error('Invalid configuration: must provide either secret or OAuth credentials (clientId, redirectUri, and scope)');
5121
+ }
5122
+ }
5123
+ /**
5124
+ * Check if partial config has all required fields for a complete SDK config
5125
+ * Requires base fields and exactly one authentication method (secret XOR oauth)
5126
+ */
5127
+ function isCompleteConfig(config) {
5128
+ return hasRequiredBaseFields(config) && hasValidAuthConfig(config);
4979
5129
  }
4980
5130
  function normalizeBaseUrl(url) {
4981
5131
  return url.endsWith('/') ? url.slice(0, -1) : url;
@@ -4987,7 +5137,7 @@ function normalizeBaseUrl(url) {
4987
5137
  // Connection string placeholder that will be replaced during build
4988
5138
  const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
4989
5139
  // SDK Version placeholder
4990
- const SDK_VERSION = "1.1.1";
5140
+ const SDK_VERSION = "1.1.3";
4991
5141
  const VERSION = "Version";
4992
5142
  const SERVICE = "Service";
4993
5143
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
@@ -5316,19 +5466,71 @@ class SDKInternalsRegistry {
5316
5466
  }
5317
5467
  }
5318
5468
 
5319
- var _UiPath_config, _UiPath_authService, _UiPath_initialized;
5469
+ /**
5470
+ * UiPath meta tag names for runtime configuration.
5471
+ *
5472
+ * These meta tags are injected at deployment time by the Apps Service
5473
+ * to configure SDK authentication and asset resolution in production.
5474
+ */
5475
+ var UiPathMetaTags;
5476
+ (function (UiPathMetaTags) {
5477
+ // SDK/OAuth configuration
5478
+ UiPathMetaTags["CLIENT_ID"] = "uipath:client-id";
5479
+ UiPathMetaTags["SCOPE"] = "uipath:scope";
5480
+ UiPathMetaTags["ORG_NAME"] = "uipath:org-name";
5481
+ UiPathMetaTags["TENANT_NAME"] = "uipath:tenant-name";
5482
+ UiPathMetaTags["BASE_URL"] = "uipath:base-url";
5483
+ UiPathMetaTags["REDIRECT_URI"] = "uipath:redirect-uri";
5484
+ // Asset resolution and routing
5485
+ UiPathMetaTags["CDN_BASE"] = "uipath:cdn-base";
5486
+ UiPathMetaTags["APP_BASE"] = "uipath:app-base";
5487
+ })(UiPathMetaTags || (UiPathMetaTags = {}));
5488
+
5489
+ /**
5490
+ * Get the content of a meta tag by name.
5491
+ * Returns undefined if not in browser environment or meta tag is not found.
5492
+ */
5493
+ function getMetaTagContent(name) {
5494
+ if (!isBrowser)
5495
+ return undefined;
5496
+ return document.querySelector(`meta[name="${name}"]`)?.content;
5497
+ }
5498
+ /**
5499
+ * Load configuration from HTML meta tags injected at runtime.
5500
+ * These meta tags are injected by @uipath/coded-apps during build
5501
+ * or by the Apps service during deployment.
5502
+ *
5503
+ * Returns partial config with values found, or null if no meta tags present.
5504
+ */
5505
+ function loadFromMetaTags() {
5506
+ if (!isBrowser)
5507
+ return null;
5508
+ const config = {
5509
+ clientId: getMetaTagContent(UiPathMetaTags.CLIENT_ID),
5510
+ scope: getMetaTagContent(UiPathMetaTags.SCOPE),
5511
+ orgName: getMetaTagContent(UiPathMetaTags.ORG_NAME),
5512
+ tenantName: getMetaTagContent(UiPathMetaTags.TENANT_NAME),
5513
+ baseUrl: getMetaTagContent(UiPathMetaTags.BASE_URL),
5514
+ redirectUri: getMetaTagContent(UiPathMetaTags.REDIRECT_URI),
5515
+ };
5516
+ const hasAnyValue = Object.values(config).some(Boolean);
5517
+ return hasAnyValue ? config : null;
5518
+ }
5519
+
5520
+ var _UiPath_instances, _UiPath_config, _UiPath_authService, _UiPath_initialized, _UiPath_partialConfig, _UiPath_initializeWithConfig, _UiPath_loadConfig;
5320
5521
  /**
5321
5522
  * UiPath - Core SDK class for authentication and configuration management.
5322
5523
  *
5323
5524
  * Handles authentication, configuration, and provides access to SDK internals
5324
5525
  * for service instantiation in the modular pattern.
5325
5526
  *
5527
+ * Supports two usage patterns:
5528
+ * 1. Full config in constructor — for server-side or explicit configuration
5529
+ * 2. No config / partial config — loads from meta tags injected by @uipath/coded-apps plugin
5530
+ *
5326
5531
  * @example
5327
5532
  * ```typescript
5328
- * // Modular pattern
5329
- * import { UiPath } from '@uipath/uipath-typescript/core';
5330
- * import { Entities } from '@uipath/uipath-typescript/entities';
5331
- *
5533
+ * // Explicit config
5332
5534
  * const sdk = new UiPath({
5333
5535
  * baseUrl: 'https://cloud.uipath.com',
5334
5536
  * orgName: 'myorg',
@@ -5337,70 +5539,47 @@ var _UiPath_config, _UiPath_authService, _UiPath_initialized;
5337
5539
  * redirectUri: 'http://localhost:3000/callback',
5338
5540
  * scope: 'OR.Users OR.Robots'
5339
5541
  * });
5340
- *
5341
5542
  * await sdk.initialize();
5543
+ * ```
5342
5544
  *
5343
- * const entitiesService = new Entities(sdk);
5344
- * const allEntities = await entitiesService.getAll();
5545
+ * @example
5546
+ * ```typescript
5547
+ * // Auto-load from meta tags (coded apps)
5548
+ * const sdk = new UiPath();
5549
+ * await sdk.initialize();
5345
5550
  * ```
5346
5551
  */
5347
5552
  let UiPath$1 = class UiPath {
5348
5553
  constructor(config) {
5554
+ _UiPath_instances.add(this);
5349
5555
  // Private fields - true runtime privacy, not visible via Object.keys()
5350
5556
  _UiPath_config.set(this, void 0);
5351
5557
  _UiPath_authService.set(this, void 0);
5352
5558
  _UiPath_initialized.set(this, false);
5353
- // Validate and normalize the configuration
5354
- validateConfig(config);
5355
- const hasSecretAuth = hasSecretConfig(config);
5356
- const hasOAuthAuth = hasOAuthConfig(config);
5357
- // Initialize core components
5358
- const internalConfig = new UiPathConfig({
5359
- baseUrl: normalizeBaseUrl(config.baseUrl),
5360
- orgName: config.orgName,
5361
- tenantName: config.tenantName,
5362
- secret: hasSecretAuth ? config.secret : undefined,
5363
- clientId: hasOAuthAuth ? config.clientId : undefined,
5364
- redirectUri: hasOAuthAuth ? config.redirectUri : undefined,
5365
- scope: hasOAuthAuth ? config.scope : undefined
5366
- });
5367
- const executionContext = new ExecutionContext();
5368
- __classPrivateFieldSet(this, _UiPath_authService, new AuthService(internalConfig, executionContext), "f");
5369
- __classPrivateFieldSet(this, _UiPath_config, internalConfig, "f");
5370
- // Store internals in SDKInternalsRegistry (not visible on instance)
5371
- SDKInternalsRegistry.set(this, {
5372
- config: internalConfig,
5373
- context: executionContext,
5374
- tokenManager: __classPrivateFieldGet(this, _UiPath_authService, "f").getTokenManager()
5375
- });
5376
- // Expose read-only config for user convenience
5377
- this.config = {
5378
- baseUrl: internalConfig.baseUrl,
5379
- orgName: internalConfig.orgName,
5380
- tenantName: internalConfig.tenantName
5381
- };
5382
- // Initialize telemetry with SDK configuration
5383
- telemetryClient.initialize({
5384
- baseUrl: config.baseUrl,
5385
- orgName: config.orgName,
5386
- tenantName: config.tenantName,
5387
- clientId: hasOAuthAuth ? config.clientId : undefined,
5388
- redirectUri: hasOAuthAuth ? config.redirectUri : undefined
5389
- });
5390
- // Track SDK initialization
5391
- trackEvent('Sdk.Auth');
5392
- // Auto-initialize for secret-based auth
5393
- if (hasSecretAuth) {
5394
- __classPrivateFieldGet(this, _UiPath_authService, "f").authenticateWithSecret(config.secret);
5395
- __classPrivateFieldSet(this, _UiPath_initialized, true, "f");
5559
+ _UiPath_partialConfig.set(this, void 0);
5560
+ // Load configuration from meta tags
5561
+ const configFromMetaTags = loadFromMetaTags();
5562
+ // Merge configuration: constructor config overrides meta tags
5563
+ const mergedConfig = config ? { ...configFromMetaTags, ...config } : configFromMetaTags;
5564
+ if (mergedConfig && isCompleteConfig(mergedConfig)) {
5565
+ __classPrivateFieldGet(this, _UiPath_instances, "m", _UiPath_initializeWithConfig).call(this, mergedConfig);
5566
+ }
5567
+ else if (config) {
5568
+ __classPrivateFieldSet(this, _UiPath_partialConfig, config, "f");
5396
5569
  }
5397
5570
  }
5398
5571
  /**
5399
5572
  * Initialize the SDK based on the provided configuration.
5400
5573
  * This method handles both OAuth flow initiation and completion automatically.
5401
5574
  * For secret-based authentication, initialization is automatic and this returns immediately.
5575
+ * If no config was provided in constructor, loads from meta tags.
5402
5576
  */
5403
5577
  async initialize() {
5578
+ // Load config from meta tags if not provided in constructor
5579
+ if (!__classPrivateFieldGet(this, _UiPath_config, "f")) {
5580
+ const loadedConfig = __classPrivateFieldGet(this, _UiPath_instances, "m", _UiPath_loadConfig).call(this);
5581
+ __classPrivateFieldGet(this, _UiPath_instances, "m", _UiPath_initializeWithConfig).call(this, loadedConfig);
5582
+ }
5404
5583
  // For secret-based auth, it's already initialized in constructor
5405
5584
  if (hasSecretConfig(__classPrivateFieldGet(this, _UiPath_config, "f"))) {
5406
5585
  return;
@@ -5447,6 +5626,11 @@ let UiPath$1 = class UiPath {
5447
5626
  if (!AuthService.isInOAuthCallback()) {
5448
5627
  throw new Error('Not in OAuth callback state. Call initialize() first to start OAuth flow.');
5449
5628
  }
5629
+ // Load config if not yet initialized
5630
+ if (!__classPrivateFieldGet(this, _UiPath_config, "f")) {
5631
+ const loadedConfig = __classPrivateFieldGet(this, _UiPath_instances, "m", _UiPath_loadConfig).call(this);
5632
+ __classPrivateFieldGet(this, _UiPath_instances, "m", _UiPath_initializeWithConfig).call(this, loadedConfig);
5633
+ }
5450
5634
  try {
5451
5635
  const success = await __classPrivateFieldGet(this, _UiPath_authService, "f").authenticate(__classPrivateFieldGet(this, _UiPath_config, "f"));
5452
5636
  if (success && this.isAuthenticated()) {
@@ -5464,13 +5648,13 @@ let UiPath$1 = class UiPath {
5464
5648
  * Check if the user is authenticated (has valid token)
5465
5649
  */
5466
5650
  isAuthenticated() {
5467
- return __classPrivateFieldGet(this, _UiPath_authService, "f").hasValidToken();
5651
+ return __classPrivateFieldGet(this, _UiPath_authService, "f")?.hasValidToken() ?? false;
5468
5652
  }
5469
5653
  /**
5470
5654
  * Get the current authentication token
5471
5655
  */
5472
5656
  getToken() {
5473
- return __classPrivateFieldGet(this, _UiPath_authService, "f").getToken();
5657
+ return __classPrivateFieldGet(this, _UiPath_authService, "f")?.getToken();
5474
5658
  }
5475
5659
  /**
5476
5660
  * Logout from the SDK, clearing all authentication state.
@@ -5478,14 +5662,71 @@ let UiPath$1 = class UiPath {
5478
5662
  */
5479
5663
  logout() {
5480
5664
  // Secret-based auth has no session to end — skip silently
5481
- if (hasSecretConfig(__classPrivateFieldGet(this, _UiPath_config, "f"))) {
5665
+ if (__classPrivateFieldGet(this, _UiPath_config, "f") && hasSecretConfig(__classPrivateFieldGet(this, _UiPath_config, "f"))) {
5482
5666
  return;
5483
5667
  }
5484
- __classPrivateFieldGet(this, _UiPath_authService, "f").logout();
5668
+ __classPrivateFieldGet(this, _UiPath_authService, "f")?.logout();
5485
5669
  __classPrivateFieldSet(this, _UiPath_initialized, false, "f");
5486
5670
  }
5487
5671
  };
5488
- _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap();
5672
+ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap(), _UiPath_partialConfig = new WeakMap(), _UiPath_instances = new WeakSet(), _UiPath_initializeWithConfig = function _UiPath_initializeWithConfig(config) {
5673
+ // Validate and normalize the configuration
5674
+ validateConfig(config);
5675
+ const hasSecretAuth = hasSecretConfig(config);
5676
+ const hasOAuthAuth = hasOAuthConfig(config);
5677
+ // Initialize core components
5678
+ const internalConfig = new UiPathConfig({
5679
+ baseUrl: normalizeBaseUrl(config.baseUrl),
5680
+ orgName: config.orgName,
5681
+ tenantName: config.tenantName,
5682
+ secret: hasSecretAuth ? config.secret : undefined,
5683
+ clientId: hasOAuthAuth ? config.clientId : undefined,
5684
+ redirectUri: hasOAuthAuth ? config.redirectUri : undefined,
5685
+ scope: hasOAuthAuth ? config.scope : undefined
5686
+ });
5687
+ const executionContext = new ExecutionContext();
5688
+ __classPrivateFieldSet(this, _UiPath_authService, new AuthService(internalConfig, executionContext), "f");
5689
+ __classPrivateFieldSet(this, _UiPath_config, internalConfig, "f");
5690
+ // Store internals in SDKInternalsRegistry (not visible on instance)
5691
+ SDKInternalsRegistry.set(this, {
5692
+ config: internalConfig,
5693
+ context: executionContext,
5694
+ tokenManager: __classPrivateFieldGet(this, _UiPath_authService, "f").getTokenManager()
5695
+ });
5696
+ // Expose read-only config for user convenience
5697
+ this.config = {
5698
+ baseUrl: internalConfig.baseUrl,
5699
+ orgName: internalConfig.orgName,
5700
+ tenantName: internalConfig.tenantName
5701
+ };
5702
+ // Initialize telemetry with SDK configuration
5703
+ telemetryClient.initialize({
5704
+ baseUrl: config.baseUrl,
5705
+ orgName: config.orgName,
5706
+ tenantName: config.tenantName,
5707
+ clientId: hasOAuthAuth ? config.clientId : undefined,
5708
+ redirectUri: hasOAuthAuth ? config.redirectUri : undefined
5709
+ });
5710
+ // Track SDK initialization
5711
+ trackEvent('Sdk.Auth');
5712
+ /** Auto-initialize for secret-based auth
5713
+ * When viewed in Action Center, initialize tokenInfo with empty token. When an sdk call is made Action Center passes the token to sdk.
5714
+ */
5715
+ if (hasSecretAuth || isInActionCenter) {
5716
+ __classPrivateFieldGet(this, _UiPath_authService, "f").authenticateWithSecret(config.secret ?? '');
5717
+ __classPrivateFieldSet(this, _UiPath_initialized, true, "f");
5718
+ }
5719
+ }, _UiPath_loadConfig = function _UiPath_loadConfig() {
5720
+ // Load from meta tags
5721
+ const metaConfig = loadFromMetaTags();
5722
+ // Merge with any partial config from constructor (constructor overrides meta tags)
5723
+ const merged = { ...metaConfig, ...__classPrivateFieldGet(this, _UiPath_partialConfig, "f") };
5724
+ if (!isCompleteConfig(merged)) {
5725
+ throw new Error('UiPath SDK configuration not found. ' +
5726
+ 'Ensure @uipath/coded-apps plugin is set up in your bundler to inject configuration during development and build.');
5727
+ }
5728
+ return merged;
5729
+ };
5489
5730
 
5490
5731
  /**
5491
5732
  * Type guards for error response types
@@ -5764,15 +6005,6 @@ class ApiClient {
5764
6005
  async getDefaultHeaders() {
5765
6006
  // Get headers from execution context first
5766
6007
  const contextHeaders = this.executionContext.getHeaders();
5767
- // If Authorization header is already set in context, use that
5768
- if (contextHeaders['Authorization']) {
5769
- return {
5770
- ...contextHeaders,
5771
- 'Content-Type': CONTENT_TYPES.JSON,
5772
- ...this.defaultHeaders,
5773
- ...this.clientConfig.headers
5774
- };
5775
- }
5776
6008
  const token = await this.getValidToken();
5777
6009
  return {
5778
6010
  ...contextHeaders,
@@ -5787,8 +6019,13 @@ class ApiClient {
5787
6019
  const normalizedPath = path.startsWith('/') ? path.substring(1) : path;
5788
6020
  // Construct URL with org and tenant names
5789
6021
  const url = new URL(`${this.config.orgName}/${this.config.tenantName}/${normalizedPath}`, this.config.baseUrl).toString();
6022
+ const isFormData = options.body instanceof FormData;
6023
+ const defaultHeaders = await this.getDefaultHeaders();
6024
+ if (isFormData) {
6025
+ delete defaultHeaders['Content-Type'];
6026
+ }
5790
6027
  const headers = {
5791
- ...await this.getDefaultHeaders(),
6028
+ ...defaultHeaders,
5792
6029
  ...options.headers
5793
6030
  };
5794
6031
  // Convert params to URLSearchParams
@@ -5799,11 +6036,15 @@ class ApiClient {
5799
6036
  });
5800
6037
  }
5801
6038
  const fullUrl = searchParams.toString() ? `${url}?${searchParams.toString()}` : url;
6039
+ let body = undefined;
6040
+ if (options.body) {
6041
+ body = isFormData ? options.body : JSON.stringify(options.body);
6042
+ }
5802
6043
  try {
5803
6044
  const response = await fetch(fullUrl, {
5804
6045
  method,
5805
6046
  headers,
5806
- body: options.body ? JSON.stringify(options.body) : undefined,
6047
+ body,
5807
6048
  signal: options.signal
5808
6049
  });
5809
6050
  if (!response.ok) {
@@ -7094,6 +7335,17 @@ function createEntityMethods(entityData, service) {
7094
7335
  fieldName
7095
7336
  });
7096
7337
  },
7338
+ async uploadAttachment(recordId, fieldName, file, expansionLevel) {
7339
+ if (!entityData.name)
7340
+ throw new Error('Entity name is undefined');
7341
+ return service.uploadAttachment({
7342
+ entityName: entityData.name,
7343
+ recordId,
7344
+ fieldName,
7345
+ file,
7346
+ expansionLevel
7347
+ });
7348
+ },
7097
7349
  async insert(data, options) {
7098
7350
  return this.insertRecord(data, options);
7099
7351
  },
@@ -7597,6 +7849,42 @@ class EntityService extends BaseService {
7597
7849
  });
7598
7850
  return response.data;
7599
7851
  }
7852
+ /**
7853
+ * Uploads an attachment to a File-type field of an entity record
7854
+ *
7855
+ * @param options - Options containing entityName, recordId, fieldName, file, and optional expansionLevel
7856
+ * @returns Promise resolving to the upload response
7857
+ *
7858
+ * @example
7859
+ * ```typescript
7860
+ * import { Entities } from '@uipath/uipath-typescript/entities';
7861
+ *
7862
+ * const entities = new Entities(sdk);
7863
+ *
7864
+ * // Upload a file attachment
7865
+ * const response = await entities.uploadAttachment({
7866
+ * entityName: 'Invoice',
7867
+ * recordId: '<record-uuid>',
7868
+ * fieldName: 'Documents',
7869
+ * file: file
7870
+ * });
7871
+ * ```
7872
+ */
7873
+ async uploadAttachment(options) {
7874
+ const { entityName, recordId, fieldName, file, expansionLevel } = options;
7875
+ const formData = new FormData();
7876
+ if (file instanceof Uint8Array) {
7877
+ formData.append('file', new Blob([file.buffer]));
7878
+ }
7879
+ else {
7880
+ formData.append('file', file);
7881
+ }
7882
+ const params = createParams({ expansionLevel });
7883
+ const response = await this.post(DATA_FABRIC_ENDPOINTS.ENTITY.UPLOAD_ATTACHMENT(entityName, recordId, fieldName), formData, { params });
7884
+ // Convert PascalCase response to camelCase
7885
+ const camelResponse = pascalToCamelCaseKeys(response.data);
7886
+ return camelResponse;
7887
+ }
7600
7888
  /**
7601
7889
  * @hidden
7602
7890
  * @deprecated Use {@link getAllRecords} instead.
@@ -7730,6 +8018,9 @@ __decorate([
7730
8018
  __decorate([
7731
8019
  track('Entities.DownloadAttachment')
7732
8020
  ], EntityService.prototype, "downloadAttachment", null);
8021
+ __decorate([
8022
+ track('Entities.UploadAttachment')
8023
+ ], EntityService.prototype, "uploadAttachment", null);
7733
8024
 
7734
8025
  class ChoiceSetService extends BaseService {
7735
8026
  /**
@@ -11116,4 +11407,79 @@ const UserSettingsMap = {
11116
11407
  ...CommonFieldMap
11117
11408
  };
11118
11409
 
11119
- export { APP_NAME, AgentMap, AssetValueScope, AssetValueType, AuthenticationError, AuthorizationError, BucketOptions, CLOUD_CLIENT_ID, CLOUD_ORGANIZATION_NAME, CLOUD_REDIRECT_URI, CLOUD_ROLE_NAME, CLOUD_TENANT_NAME, CLOUD_URL, CONNECTION_STRING, CitationErrorType, ConversationMap, DEFAULT_ITEMS_FIELD, DEFAULT_PAGE_SIZE, DEFAULT_TOTAL_COUNT_FIELD, DataDirectionType, DebugMode, EntityFieldDataType, EntityType, ErrorType, EscalationActionType, EscalationRecipientScope, EscalationTriggerType, ExchangeMap, FeedbackRating, FieldDisplayType, HttpStatus, InputStreamSpeechSensitivity, InterruptType, JobPriority, JobState, JobType, JoinType, MAX_PAGE_SIZE, MessageMap, MessageRole, NetworkError, NotFoundError, PackageSourceType, PackageType, ProcessIncidentSeverity, ProcessIncidentStatus, ProcessIncidentType, RateLimitError, ReferenceType, RemoteControlAccess, RobotSize, SDK_LOGGER_NAME, SDK_RUN_EVENT, SDK_SERVICE_NAME, SDK_VERSION, SERVICE, SLADurationUnit, ServerError, SortOrder, StageTaskType, StartStrategy, StopStrategy, TargetFramework, TaskActivityType, TaskPriority, TaskSlaCriteria, TaskSlaStatus, TaskSourceName, TaskStatus, TaskType, UNKNOWN$1 as UNKNOWN, UiPath, UiPathError, UserSettingsMap, VERSION, ValidationError, createAgentWithMethods, createCaseInstanceWithMethods, createConversationWithMethods, createEntityWithMethods, createProcessInstanceWithMethods, createProcessWithMethods, createTaskWithMethods, getErrorDetails, getLimitedPageSize, isAuthenticationError, isAuthorizationError, isNetworkError, isNotFoundError, isRateLimitError, isServerError, isUiPathError, isValidationError, telemetryClient, track, trackEvent };
11410
+ /**
11411
+ * Asset resolution utilities for UiPath Coded Apps
11412
+ *
11413
+ * These helpers enable developers to write code that works identically
11414
+ * in local development and production environments.
11415
+ *
11416
+ * Values are read from meta tags injected at deployment:
11417
+ * - <meta name="uipath:cdn-base" content="https://cdn.example.com/appId/folder">
11418
+ * - <meta name="uipath:app-base" content="/org/apps_/.../public">
11419
+ */
11420
+ /**
11421
+ * Resolves an asset path to the CDN URL (if available)
11422
+ *
11423
+ * In local development: returns path as-is (loads from local dev server)
11424
+ * In production: prepends CDN base URL from meta tag
11425
+ *
11426
+ * @param path - The asset path (e.g., './assets/logo.png' or '/assets/logo.png')
11427
+ * @returns The resolved asset URL
11428
+ *
11429
+ * @example
11430
+ * ```tsx
11431
+ * import { getAsset } from '@uipath/uipath-typescript';
11432
+ * import logoPath from './assets/logo.png';
11433
+ *
11434
+ * function MyComponent() {
11435
+ * return <img src={getAsset(logoPath)} alt="Logo" />;
11436
+ * }
11437
+ * ```
11438
+ */
11439
+ function getAsset(path) {
11440
+ // If path is already an absolute URL, return as-is
11441
+ if (path.startsWith('http://') || path.startsWith('https://')) {
11442
+ return path;
11443
+ }
11444
+ const cdnBase = getMetaTagContent(UiPathMetaTags.CDN_BASE);
11445
+ if (!cdnBase)
11446
+ return path;
11447
+ // Normalize CDN base URL to remove trailing slash
11448
+ const normalizedCdnBase = normalizeBaseUrl(cdnBase);
11449
+ // Normalize path to ensure it starts with /
11450
+ let normalizedPath = path;
11451
+ if (normalizedPath.startsWith('./')) {
11452
+ normalizedPath = normalizedPath.substring(1); // ./assets -> /assets
11453
+ }
11454
+ else if (!normalizedPath.startsWith('/')) {
11455
+ normalizedPath = '/' + normalizedPath; // assets -> /assets
11456
+ }
11457
+ return normalizedCdnBase + normalizedPath;
11458
+ }
11459
+ /**
11460
+ * Returns the app base path for router configuration
11461
+ *
11462
+ * In local development: returns '/'
11463
+ * In production: returns the deployed app path from meta tag
11464
+ *
11465
+ * @returns The app base path
11466
+ *
11467
+ * @example
11468
+ * ```tsx
11469
+ * import { getAppBase } from '@uipath/uipath-typescript';
11470
+ * import { BrowserRouter } from 'react-router-dom';
11471
+ *
11472
+ * function App() {
11473
+ * return (
11474
+ * <BrowserRouter basename={getAppBase()}>
11475
+ * {/* routes *\/}
11476
+ * </BrowserRouter>
11477
+ * );
11478
+ * }
11479
+ * ```
11480
+ */
11481
+ function getAppBase() {
11482
+ return getMetaTagContent(UiPathMetaTags.APP_BASE) || '/';
11483
+ }
11484
+
11485
+ export { APP_NAME, AgentMap, AssetValueScope, AssetValueType, AuthenticationError, AuthorizationError, BucketOptions, CLOUD_CLIENT_ID, CLOUD_ORGANIZATION_NAME, CLOUD_REDIRECT_URI, CLOUD_ROLE_NAME, CLOUD_TENANT_NAME, CLOUD_URL, CONNECTION_STRING, CitationErrorType, ConversationMap, DEFAULT_ITEMS_FIELD, DEFAULT_PAGE_SIZE, DEFAULT_TOTAL_COUNT_FIELD, DataDirectionType, DebugMode, EntityFieldDataType, EntityType, ErrorType, EscalationActionType, EscalationRecipientScope, EscalationTriggerType, ExchangeMap, FeedbackRating, FieldDisplayType, HttpStatus, InputStreamSpeechSensitivity, InterruptType, JobPriority, JobState, JobType, JoinType, MAX_PAGE_SIZE, MessageMap, MessageRole, NetworkError, NotFoundError, PackageSourceType, PackageType, ProcessIncidentSeverity, ProcessIncidentStatus, ProcessIncidentType, RateLimitError, ReferenceType, RemoteControlAccess, RobotSize, SDK_LOGGER_NAME, SDK_RUN_EVENT, SDK_SERVICE_NAME, SDK_VERSION, SERVICE, SLADurationUnit, ServerError, SortOrder, StageTaskType, StartStrategy, StopStrategy, TargetFramework, TaskActivityType, TaskPriority, TaskSlaCriteria, TaskSlaStatus, TaskSourceName, TaskStatus, TaskType, UNKNOWN$1 as UNKNOWN, UiPath, UiPathError, UiPathMetaTags, UserSettingsMap, VERSION, ValidationError, createAgentWithMethods, createCaseInstanceWithMethods, createConversationWithMethods, createEntityWithMethods, createProcessInstanceWithMethods, createProcessWithMethods, createTaskWithMethods, getAppBase, getAsset, getErrorDetails, getLimitedPageSize, isAuthenticationError, isAuthorizationError, isNetworkError, isNotFoundError, isRateLimitError, isServerError, isUiPathError, isValidationError, loadFromMetaTags, telemetryClient, track, trackEvent };