@uipath/codedapp-tool 1.1.0 → 1.195.0

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 (2) hide show
  1. package/dist/tool.js +640 -238
  2. package/package.json +29 -46
package/dist/tool.js CHANGED
@@ -680,6 +680,7 @@ var init_open = __esm(() => {
680
680
  });
681
681
 
682
682
  // ../filesystem/src/node.ts
683
+ import { randomUUID } from "node:crypto";
683
684
  import { existsSync } from "node:fs";
684
685
  import * as fs6 from "node:fs/promises";
685
686
  import * as os2 from "node:os";
@@ -761,6 +762,90 @@ class NodeFileSystem {
761
762
  async mkdir(dirPath) {
762
763
  await fs6.mkdir(dirPath, { recursive: true });
763
764
  }
765
+ async acquireLock(lockPath) {
766
+ const canonicalPath = await this.canonicalizeLockTarget(lockPath);
767
+ const lockFile = `${canonicalPath}.lock`;
768
+ const ownerId = randomUUID();
769
+ const start = Date.now();
770
+ while (true) {
771
+ try {
772
+ await fs6.writeFile(lockFile, ownerId, { flag: "wx" });
773
+ return this.createLockRelease(lockFile, ownerId);
774
+ } catch (error) {
775
+ if (!this.hasErrnoCode(error, "EEXIST")) {
776
+ throw error;
777
+ }
778
+ const stats = await fs6.stat(lockFile).catch(() => null);
779
+ if (stats && Date.now() - stats.mtimeMs > LOCK_STALE_MS) {
780
+ const reclaimed = await fs6.rm(lockFile, { force: true }).then(() => true).catch(() => false);
781
+ if (reclaimed)
782
+ continue;
783
+ }
784
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
785
+ throw new Error(`ELOCKED: timed out waiting for lock on ${canonicalPath}`);
786
+ }
787
+ await new Promise((resolve2) => setTimeout(resolve2, LOCK_RETRY_MIN_MS + Math.random() * LOCK_RETRY_JITTER_MS));
788
+ }
789
+ }
790
+ }
791
+ async canonicalizeLockTarget(lockPath) {
792
+ const absolute = path2.resolve(lockPath);
793
+ const fullReal = await fs6.realpath(absolute).catch(() => null);
794
+ if (fullReal)
795
+ return fullReal;
796
+ const parent = path2.dirname(absolute);
797
+ const base = path2.basename(absolute);
798
+ const canonicalParent = await fs6.realpath(parent).catch(() => parent);
799
+ return path2.join(canonicalParent, base);
800
+ }
801
+ createLockRelease(lockFile, ownerId) {
802
+ const heartbeatStart = Date.now();
803
+ let heartbeatTimer;
804
+ let stopped = false;
805
+ const stopHeartbeat = () => {
806
+ stopped = true;
807
+ if (heartbeatTimer)
808
+ clearTimeout(heartbeatTimer);
809
+ };
810
+ const scheduleNextHeartbeat = () => {
811
+ if (stopped)
812
+ return;
813
+ if (Date.now() - heartbeatStart >= LOCK_MAX_HOLD_MS) {
814
+ stopped = true;
815
+ return;
816
+ }
817
+ heartbeatTimer = setTimeout(() => {
818
+ runHeartbeat();
819
+ }, LOCK_HEARTBEAT_MS);
820
+ heartbeatTimer.unref?.();
821
+ };
822
+ const runHeartbeat = async () => {
823
+ if (stopped)
824
+ return;
825
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
826
+ if (stopped)
827
+ return;
828
+ if (current !== ownerId) {
829
+ stopped = true;
830
+ return;
831
+ }
832
+ const now = Date.now() / 1000;
833
+ await fs6.utimes(lockFile, now, now).catch(() => {});
834
+ scheduleNextHeartbeat();
835
+ };
836
+ scheduleNextHeartbeat();
837
+ let released = false;
838
+ return async () => {
839
+ if (released)
840
+ return;
841
+ released = true;
842
+ stopHeartbeat();
843
+ const current = await fs6.readFile(lockFile, "utf-8").catch(() => null);
844
+ if (current === ownerId) {
845
+ await fs6.rm(lockFile, { force: true });
846
+ }
847
+ };
848
+ }
764
849
  async rm(filePath) {
765
850
  await fs6.rm(filePath, { recursive: true, force: true });
766
851
  }
@@ -806,9 +891,13 @@ class NodeFileSystem {
806
891
  }
807
892
  }
808
893
  isEnoent(error) {
809
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
894
+ return this.hasErrnoCode(error, "ENOENT");
895
+ }
896
+ hasErrnoCode(error, code) {
897
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
810
898
  }
811
899
  }
900
+ var LOCK_HEARTBEAT_MS = 5000, LOCK_STALE_MS = 15000, LOCK_MAX_WAIT_MS = 20000, LOCK_MAX_HOLD_MS = 60000, LOCK_RETRY_MIN_MS = 100, LOCK_RETRY_JITTER_MS = 200;
812
901
  var init_node = __esm(() => {
813
902
  init_open();
814
903
  });
@@ -38024,7 +38113,8 @@ var DEFAULT_CLIENT_ID = "36dea5b8-e8bb-423d-8e7b-c808df8f1c00", AUTH_FILE_CONFIG
38024
38113
  if (!clientSecret && fileAuth.clientSecret) {
38025
38114
  clientSecret = fileAuth.clientSecret;
38026
38115
  }
38027
- const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : DEFAULT_SCOPES;
38116
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
38117
+ const scopes = customScopes && customScopes.length > 0 ? customScopes : fileAuth.scopes && fileAuth.scopes.length > 0 ? fileAuth.scopes : isExternalAppAuth ? [] : DEFAULT_SCOPES;
38028
38118
  return {
38029
38119
  clientId,
38030
38120
  clientSecret,
@@ -38055,32 +38145,7 @@ var init_config = __esm(() => {
38055
38145
  this.name = "InvalidBaseUrlError";
38056
38146
  }
38057
38147
  };
38058
- DEFAULT_SCOPES = [
38059
- "offline_access",
38060
- "ProcessMining",
38061
- "OrchestratorApiUserAccess",
38062
- "StudioWebBackend",
38063
- "IdentityServerApi",
38064
- "ConnectionService",
38065
- "DataService",
38066
- "DataServiceApiUserAccess",
38067
- "DocumentUnderstanding",
38068
- "EnterpriseContextService",
38069
- "Directory",
38070
- "JamJamApi",
38071
- "LLMGateway",
38072
- "LLMOps",
38073
- "OMS",
38074
- "RCS.FolderAuthorization",
38075
- "RCS.TagsManagement",
38076
- "TestmanagerApiUserAccess",
38077
- "AutomationSolutions",
38078
- "StudioWebTypeCacheService",
38079
- "Docs.GPT.Search",
38080
- "Insights",
38081
- "ReferenceToken",
38082
- "Audit.Read"
38083
- ];
38148
+ DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
38084
38149
  });
38085
38150
 
38086
38151
  // ../../node_modules/oauth4webapi/build/index.js
@@ -38852,7 +38917,7 @@ var init_envAuth = __esm(() => {
38852
38917
 
38853
38918
  // ../../node_modules/@uipath/coreipc/index.js
38854
38919
  var require_coreipc = __commonJS((exports, module) => {
38855
- var __dirname = "/Users/alexandru.oltean/github/cli/node_modules/@uipath/coreipc";
38920
+ var __dirname = "/home/runner/work/cli/cli/node_modules/@uipath/coreipc";
38856
38921
  /*! For license information please see index.js.LICENSE.txt */
38857
38922
  (function(e2, t2) {
38858
38923
  typeof exports == "object" && typeof module == "object" ? module.exports = t2() : typeof define == "function" && define.amd ? define([], t2) : typeof exports == "object" ? exports.ipc = t2() : e2.ipc = t2();
@@ -57390,6 +57455,129 @@ function normalizeTokenRefreshFailure() {
57390
57455
  function normalizeTokenRefreshUnavailableFailure() {
57391
57456
  return "token refresh failed before authentication completed";
57392
57457
  }
57458
+ function errorMessage(error52) {
57459
+ return error52 instanceof Error ? error52.message : String(error52);
57460
+ }
57461
+ function computeExpirationThreshold(ensureTokenValidityMinutes) {
57462
+ return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
57463
+ }
57464
+ async function runRefreshLocked(inputs) {
57465
+ const {
57466
+ absolutePath,
57467
+ refreshToken: callerRefreshToken,
57468
+ customAuthority,
57469
+ ensureTokenValidityMinutes,
57470
+ loadEnvFile,
57471
+ saveEnvFile,
57472
+ refreshFn,
57473
+ resolveConfig
57474
+ } = inputs;
57475
+ const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
57476
+ let fresh;
57477
+ try {
57478
+ fresh = await loadEnvFile({ envPath: absolutePath });
57479
+ } catch (error52) {
57480
+ return {
57481
+ kind: "fail",
57482
+ status: {
57483
+ loginStatus: "Refresh Failed",
57484
+ hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
57485
+ tokenRefresh: {
57486
+ attempted: false,
57487
+ success: false,
57488
+ errorMessage: `auth file read failed: ${errorMessage(error52)}`
57489
+ }
57490
+ }
57491
+ };
57492
+ }
57493
+ const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
57494
+ const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
57495
+ if (freshAccess && freshExp && freshExp > expirationThreshold) {
57496
+ return {
57497
+ kind: "ok",
57498
+ accessToken: freshAccess,
57499
+ refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
57500
+ expiration: freshExp,
57501
+ tokenRefresh: { attempted: false, success: true }
57502
+ };
57503
+ }
57504
+ const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
57505
+ let refreshedAccess;
57506
+ let refreshedRefresh;
57507
+ try {
57508
+ const config3 = await resolveConfig({ customAuthority });
57509
+ const refreshed = await refreshFn({
57510
+ refreshToken: tokenForIdP,
57511
+ tokenEndpoint: config3.tokenEndpoint,
57512
+ clientId: config3.clientId,
57513
+ expectedAuthority: customAuthority
57514
+ });
57515
+ refreshedAccess = refreshed.accessToken;
57516
+ refreshedRefresh = refreshed.refreshToken;
57517
+ } catch (error52) {
57518
+ const isOAuthFailure = isTokenRefreshOAuthFailure(error52);
57519
+ const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
57520
+ const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
57521
+ return {
57522
+ kind: "fail",
57523
+ status: {
57524
+ loginStatus: "Refresh Failed",
57525
+ hint,
57526
+ tokenRefresh: {
57527
+ attempted: true,
57528
+ success: false,
57529
+ errorMessage: message
57530
+ }
57531
+ }
57532
+ };
57533
+ }
57534
+ const refreshedExp = getTokenExpiration(refreshedAccess);
57535
+ if (!refreshedExp || refreshedExp <= new Date) {
57536
+ return {
57537
+ kind: "fail",
57538
+ status: {
57539
+ loginStatus: "Refresh Failed",
57540
+ hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
57541
+ tokenRefresh: {
57542
+ attempted: true,
57543
+ success: false,
57544
+ errorMessage: "refreshed token has no valid expiration claim"
57545
+ }
57546
+ }
57547
+ };
57548
+ }
57549
+ try {
57550
+ await saveEnvFile({
57551
+ envPath: absolutePath,
57552
+ data: {
57553
+ UIPATH_ACCESS_TOKEN: refreshedAccess,
57554
+ UIPATH_REFRESH_TOKEN: refreshedRefresh
57555
+ },
57556
+ merge: true
57557
+ });
57558
+ return {
57559
+ kind: "ok",
57560
+ accessToken: refreshedAccess,
57561
+ refreshToken: refreshedRefresh,
57562
+ expiration: refreshedExp,
57563
+ tokenRefresh: { attempted: true, success: true }
57564
+ };
57565
+ } catch (error52) {
57566
+ const msg = errorMessage(error52);
57567
+ return {
57568
+ kind: "ok",
57569
+ accessToken: refreshedAccess,
57570
+ refreshToken: refreshedRefresh,
57571
+ expiration: refreshedExp,
57572
+ persistenceWarning: `Access token refreshed in memory but could not be written to ${absolutePath}: ${msg}. The next CLI invocation will fail until the file can be updated — run 'uip login' to re-authenticate.`,
57573
+ tokenRefresh: {
57574
+ attempted: true,
57575
+ success: true,
57576
+ errorMessage: `persistence failed: ${msg}`
57577
+ }
57578
+ };
57579
+ }
57580
+ }
57393
57581
  var LoginStatusSource, getLoginStatusWithDeps = async (options = {}, deps = {}) => {
57394
57582
  const {
57395
57583
  resolveEnvFilePath = resolveEnvFilePathAsync,
@@ -57464,73 +57652,103 @@ var LoginStatusSource, getLoginStatusWithDeps = async (options = {}, deps = {})
57464
57652
  let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
57465
57653
  let expiration = getTokenExpiration(accessToken);
57466
57654
  let persistenceWarning;
57655
+ let lockReleaseFailed = false;
57467
57656
  let tokenRefresh;
57468
- const expirationThreshold = new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
57469
- if (expiration && expiration <= expirationThreshold && refreshToken) {
57470
- let refreshedAccess;
57471
- let refreshedRefresh;
57657
+ const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
57658
+ const tryGlobalCredsHint = async () => {
57659
+ const fs8 = getFs();
57660
+ const globalPath = fs8.path.join(fs8.env.homedir(), envFilePath);
57661
+ if (absolutePath === globalPath)
57662
+ return;
57663
+ if (!await fs8.exists(globalPath))
57664
+ return;
57472
57665
  try {
57473
- const config3 = await resolveConfig({
57474
- customAuthority: credentials.UIPATH_URL
57475
- });
57476
- const refreshed = await refreshTokenFn({
57477
- refreshToken,
57478
- tokenEndpoint: config3.tokenEndpoint,
57479
- clientId: config3.clientId,
57480
- expectedAuthority: credentials.UIPATH_URL
57481
- });
57482
- refreshedAccess = refreshed.accessToken;
57483
- refreshedRefresh = refreshed.refreshToken;
57484
- } catch (error52) {
57485
- const isOAuthFailure = isTokenRefreshOAuthFailure(error52);
57486
- const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
57487
- const errorMessage = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
57488
- return {
57489
- loginStatus: "Refresh Failed",
57490
- hint,
57491
- tokenRefresh: {
57492
- attempted: true,
57493
- success: false,
57494
- errorMessage
57495
- }
57496
- };
57666
+ const globalCreds = await loadEnvFile({ envPath: globalPath });
57667
+ if (!globalCreds.UIPATH_ACCESS_TOKEN)
57668
+ return;
57669
+ const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
57670
+ if (globalExp && globalExp <= new Date)
57671
+ return;
57672
+ return `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
57673
+ } catch {
57674
+ return;
57497
57675
  }
57498
- const refreshedExp = getTokenExpiration(refreshedAccess);
57499
- if (!refreshedExp || refreshedExp <= new Date) {
57676
+ };
57677
+ if (expiration && expiration <= outerThreshold && refreshToken) {
57678
+ let release;
57679
+ try {
57680
+ release = await getFs().acquireLock(absolutePath);
57681
+ } catch (error52) {
57682
+ const msg = errorMessage(error52);
57683
+ const globalHint = await tryGlobalCredsHint();
57684
+ if (globalHint) {
57685
+ return {
57686
+ loginStatus: "Expired",
57687
+ accessToken,
57688
+ refreshToken,
57689
+ baseUrl: credentials.UIPATH_URL,
57690
+ organizationName: credentials.UIPATH_ORGANIZATION_NAME,
57691
+ organizationId: credentials.UIPATH_ORGANIZATION_ID,
57692
+ tenantName: credentials.UIPATH_TENANT_NAME,
57693
+ tenantId: credentials.UIPATH_TENANT_ID,
57694
+ expiration,
57695
+ source: "file" /* File */,
57696
+ hint: globalHint,
57697
+ tokenRefresh: {
57698
+ attempted: false,
57699
+ success: false,
57700
+ errorMessage: `lock acquisition failed: ${msg}`
57701
+ }
57702
+ };
57703
+ }
57500
57704
  return {
57501
57705
  loginStatus: "Refresh Failed",
57502
- hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
57706
+ hint: "Could not acquire the auth-file lock — too many concurrent `uip` processes, or a permission issue on the auth directory. Retry, or run 'uip login' to re-authenticate.",
57503
57707
  tokenRefresh: {
57504
- attempted: true,
57708
+ attempted: false,
57505
57709
  success: false,
57506
- errorMessage: "refreshed token has no valid expiration claim"
57710
+ errorMessage: `lock acquisition failed: ${msg}`
57507
57711
  }
57508
57712
  };
57509
57713
  }
57510
- accessToken = refreshedAccess;
57511
- refreshToken = refreshedRefresh;
57512
- expiration = refreshedExp;
57714
+ let lockedFailure;
57513
57715
  try {
57514
- await saveEnvFile({
57515
- envPath: absolutePath,
57516
- data: {
57517
- UIPATH_ACCESS_TOKEN: accessToken,
57518
- UIPATH_REFRESH_TOKEN: refreshToken
57519
- },
57520
- merge: true
57716
+ const outcome = await runRefreshLocked({
57717
+ absolutePath,
57718
+ refreshToken,
57719
+ customAuthority: credentials.UIPATH_URL,
57720
+ ensureTokenValidityMinutes,
57721
+ loadEnvFile,
57722
+ saveEnvFile,
57723
+ refreshFn: refreshTokenFn,
57724
+ resolveConfig
57521
57725
  });
57522
- tokenRefresh = {
57523
- attempted: true,
57524
- success: true
57525
- };
57526
- } catch (error52) {
57527
- const msg = error52 instanceof Error ? error52.message : String(error52);
57528
- persistenceWarning = `Access token refreshed in memory but could not be written to ${absolutePath}: ${msg}. The next CLI invocation will fail until the file can be updated — run 'uip login' to re-authenticate.`;
57529
- tokenRefresh = {
57530
- attempted: true,
57531
- success: true,
57532
- errorMessage: `persistence failed: ${msg}`
57533
- };
57726
+ if (outcome.kind === "fail") {
57727
+ lockedFailure = outcome.status;
57728
+ } else {
57729
+ accessToken = outcome.accessToken;
57730
+ refreshToken = outcome.refreshToken;
57731
+ expiration = outcome.expiration;
57732
+ tokenRefresh = outcome.tokenRefresh;
57733
+ if (outcome.persistenceWarning) {
57734
+ persistenceWarning = outcome.persistenceWarning;
57735
+ }
57736
+ }
57737
+ } finally {
57738
+ try {
57739
+ await release();
57740
+ } catch {
57741
+ lockReleaseFailed = true;
57742
+ }
57743
+ }
57744
+ if (lockedFailure) {
57745
+ const globalHint = await tryGlobalCredsHint();
57746
+ const base = globalHint ? {
57747
+ ...lockedFailure,
57748
+ loginStatus: "Expired",
57749
+ hint: globalHint
57750
+ } : lockedFailure;
57751
+ return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
57534
57752
  }
57535
57753
  }
57536
57754
  const result = {
@@ -57545,23 +57763,13 @@ var LoginStatusSource, getLoginStatusWithDeps = async (options = {}, deps = {})
57545
57763
  expiration,
57546
57764
  source: "file" /* File */,
57547
57765
  ...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
57766
+ ...lockReleaseFailed ? { lockReleaseFailed: true } : {},
57548
57767
  ...tokenRefresh ? { tokenRefresh } : {}
57549
57768
  };
57550
57769
  if (result.loginStatus === "Expired") {
57551
- const fs8 = getFs();
57552
- const globalPath = fs8.path.join(fs8.env.homedir(), envFilePath);
57553
- if (absolutePath !== globalPath && await fs8.exists(globalPath)) {
57554
- try {
57555
- const globalCreds = await loadEnvFile({
57556
- envPath: globalPath
57557
- });
57558
- if (globalCreds.UIPATH_ACCESS_TOKEN) {
57559
- const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
57560
- if (!globalExp || globalExp > new Date) {
57561
- result.hint = `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
57562
- }
57563
- }
57564
- } catch {}
57770
+ const globalHint = await tryGlobalCredsHint();
57771
+ if (globalHint) {
57772
+ result.hint = globalHint;
57565
57773
  }
57566
57774
  }
57567
57775
  return result;
@@ -57636,9 +57844,11 @@ var clientCredentialsLogin = async ({
57636
57844
  const params = {
57637
57845
  grant_type: "client_credentials",
57638
57846
  client_id: config3.clientId,
57639
- client_secret: config3.clientSecret ?? "",
57640
- scope: config3.scopes.join(" ")
57847
+ client_secret: config3.clientSecret ?? ""
57641
57848
  };
57849
+ if (config3.scopes.length > 0) {
57850
+ params.scope = config3.scopes.join(" ");
57851
+ }
57642
57852
  const tokenResponse = await fetch(config3.tokenEndpoint, {
57643
57853
  method: "POST",
57644
57854
  headers: {
@@ -57848,11 +58058,25 @@ var interactiveLoginWithDeps = async (options, deps) => {
57848
58058
  searchDir = parentDir;
57849
58059
  }
57850
58060
  }
57851
- await saveEnvFile({
57852
- envPath: savePath,
57853
- data: credentials,
57854
- merge: true
57855
- });
58061
+ let saveRelease;
58062
+ try {
58063
+ if (typeof fs8.acquireLock === "function") {
58064
+ saveRelease = await fs8.acquireLock(savePath);
58065
+ }
58066
+ } catch {
58067
+ saveRelease = undefined;
58068
+ }
58069
+ try {
58070
+ await saveEnvFile({
58071
+ envPath: savePath,
58072
+ data: credentials,
58073
+ merge: true
58074
+ });
58075
+ } finally {
58076
+ if (saveRelease) {
58077
+ await saveRelease().catch(() => {});
58078
+ }
58079
+ }
57856
58080
  const reportedPath = fs8.path.isAbsolute(savePath) ? savePath : fs8.path.join(fs8.env.homedir(), savePath);
57857
58081
  emit({
57858
58082
  type: "saved",
@@ -57882,7 +58106,21 @@ async function logoutWithDeps(options, deps = {}) {
57882
58106
  const fs8 = getFs();
57883
58107
  const { absolutePath } = await resolveEnvFilePath(options.file);
57884
58108
  if (absolutePath && await fs8.exists(absolutePath)) {
57885
- await fs8.rm(absolutePath);
58109
+ let release;
58110
+ try {
58111
+ if (typeof fs8.acquireLock === "function") {
58112
+ release = await fs8.acquireLock(absolutePath);
58113
+ }
58114
+ } catch {
58115
+ release = undefined;
58116
+ }
58117
+ try {
58118
+ await fs8.rm(absolutePath);
58119
+ } finally {
58120
+ if (release) {
58121
+ await release().catch(() => {});
58122
+ }
58123
+ }
57886
58124
  return {
57887
58125
  success: true,
57888
58126
  message: `Logged out successfully. Removed ${absolutePath}`,
@@ -57903,81 +58141,6 @@ var init_logout = __esm(() => {
57903
58141
  init_envFile();
57904
58142
  });
57905
58143
 
57906
- // ../auth/src/strategies/browser-strategy.ts
57907
- var exports_browser_strategy = {};
57908
- __export(exports_browser_strategy, {
57909
- BrowserAuthStrategy: () => BrowserAuthStrategy
57910
- });
57911
-
57912
- class BrowserAuthStrategy {
57913
- async execute(url2, _redirectUri, expectedState) {
57914
- const global4 = getGlobalThis();
57915
- if (!global4?.window) {
57916
- throw new Error("Browser environment required for authentication");
57917
- }
57918
- const screenWidth = global4.window.screen?.width ?? 1024;
57919
- const screenHeight = global4.window.screen?.height ?? 768;
57920
- const width = 600;
57921
- const height2 = 700;
57922
- const left = screenWidth / 2 - width / 2;
57923
- const top = screenHeight / 2 - height2 / 2;
57924
- if (!global4.window.open) {
57925
- throw new Error("window.open is not available");
57926
- }
57927
- const popupResult = global4.window.open(url2, "uip_auth", `width=${width},height=${height2},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`);
57928
- const popup = popupResult;
57929
- if (!popup) {
57930
- throw new Error(`Authentication popup was blocked by your browser.
57931
-
57932
- ` + `To continue:
57933
- ` + `1. Look for a popup blocker icon in your address bar
57934
- ` + `2. Allow popups for this site
57935
- ` + `3. Try logging in again
57936
-
57937
- ` + "If using an ad blocker, you may need to temporarily disable it.");
57938
- }
57939
- return new Promise((resolve2, reject) => {
57940
- const messageHandler = (event) => {
57941
- if (event.data?.type === "UIP_AUTH_CODE" && event.data.code) {
57942
- if (event.data.state !== expectedState) {
57943
- cleanup();
57944
- reject(new Error("OAuth state mismatch — the callback state does not match the expected value. " + "This may indicate a CSRF attack. Please try signing in again."));
57945
- popup.close();
57946
- return;
57947
- }
57948
- cleanup();
57949
- resolve2(event.data.code);
57950
- popup.close();
57951
- } else if (event.data?.type === "UIP_AUTH_ERROR") {
57952
- cleanup();
57953
- const errorMsg = event.data.error || "Authentication failed";
57954
- reject(new Error(`Authentication failed: ${errorMsg}
57955
-
57956
- ` + "Please check your credentials and try again. " + "If the problem persists, verify your UiPath account is active."));
57957
- popup.close();
57958
- }
57959
- };
57960
- const cleanup = () => {
57961
- global4.window?.removeEventListener?.("message", messageHandler);
57962
- if (timer)
57963
- clearInterval(timer);
57964
- };
57965
- if (global4.window?.addEventListener) {
57966
- global4.window.addEventListener("message", messageHandler);
57967
- }
57968
- const timer = setInterval(() => {
57969
- if (popup.closed) {
57970
- cleanup();
57971
- reject(new Error(`Authentication was cancelled.
57972
-
57973
- ` + "The authentication popup was closed before completing the login process. " + "Please try again and complete the authentication flow."));
57974
- }
57975
- }, 1000);
57976
- });
57977
- }
57978
- }
57979
- var init_browser_strategy = () => {};
57980
-
57981
58144
  // ../auth/src/getBaseHtml.ts
57982
58145
  var getBaseHtml = ({ title, message, type: type2 }) => {
57983
58146
  const icon = type2 === "success" ? "✓" : "✕";
@@ -58124,7 +58287,7 @@ var getBaseHtml = ({ title, message, type: type2 }) => {
58124
58287
  };
58125
58288
 
58126
58289
  // ../auth/src/server.ts
58127
- var startServer = async ({
58290
+ var AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT", startServer = async ({
58128
58291
  redirectUri,
58129
58292
  timeoutMs = DEFAULT_AUTH_TIMEOUT_MS2,
58130
58293
  onListening
@@ -58195,7 +58358,18 @@ var startServer = async ({
58195
58358
  reject(new Error("No authorization code received"));
58196
58359
  return;
58197
58360
  });
58198
- server.listen(Number(redirectUri.port), redirectUri.hostname, () => {
58361
+ const timeoutHandle = setTimeout(() => {
58362
+ server.close();
58363
+ const err2 = new Error("Authentication timeout");
58364
+ err2.code = AUTH_TIMEOUT_ERROR_CODE;
58365
+ reject(err2);
58366
+ }, timeoutMs);
58367
+ const bindHost = redirectUri.hostname === "localhost" ? "127.0.0.1" : redirectUri.hostname;
58368
+ server.on("error", (err2) => {
58369
+ clearTimeout(timeoutHandle);
58370
+ reject(err2);
58371
+ });
58372
+ server.listen(Number(redirectUri.port), bindHost, () => {
58199
58373
  if (onListening) {
58200
58374
  Promise.resolve(onListening()).catch((err2) => {
58201
58375
  server.close();
@@ -58204,10 +58378,6 @@ var startServer = async ({
58204
58378
  });
58205
58379
  }
58206
58380
  });
58207
- const timeoutHandle = setTimeout(() => {
58208
- server.close();
58209
- reject(new Error("Authentication timeout"));
58210
- }, timeoutMs);
58211
58381
  server.on("close", () => {
58212
58382
  clearTimeout(timeoutHandle);
58213
58383
  });
@@ -58217,6 +58387,81 @@ var init_server = __esm(() => {
58217
58387
  init_constants();
58218
58388
  });
58219
58389
 
58390
+ // ../auth/src/strategies/browser-strategy.ts
58391
+ var exports_browser_strategy = {};
58392
+ __export(exports_browser_strategy, {
58393
+ BrowserAuthStrategy: () => BrowserAuthStrategy
58394
+ });
58395
+
58396
+ class BrowserAuthStrategy {
58397
+ async execute(url2, _redirectUri, expectedState) {
58398
+ const global4 = getGlobalThis();
58399
+ if (!global4?.window) {
58400
+ throw new Error("Browser environment required for authentication");
58401
+ }
58402
+ const screenWidth = global4.window.screen?.width ?? 1024;
58403
+ const screenHeight = global4.window.screen?.height ?? 768;
58404
+ const width = 600;
58405
+ const height2 = 700;
58406
+ const left = screenWidth / 2 - width / 2;
58407
+ const top = screenHeight / 2 - height2 / 2;
58408
+ if (!global4.window.open) {
58409
+ throw new Error("window.open is not available");
58410
+ }
58411
+ const popupResult = global4.window.open(url2, "uip_auth", `width=${width},height=${height2},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`);
58412
+ const popup = popupResult;
58413
+ if (!popup) {
58414
+ throw new Error(`Authentication popup was blocked by your browser.
58415
+
58416
+ ` + `To continue:
58417
+ ` + `1. Look for a popup blocker icon in your address bar
58418
+ ` + `2. Allow popups for this site
58419
+ ` + `3. Try logging in again
58420
+
58421
+ ` + "If using an ad blocker, you may need to temporarily disable it.");
58422
+ }
58423
+ return new Promise((resolve2, reject) => {
58424
+ const messageHandler = (event) => {
58425
+ if (event.data?.type === "UIP_AUTH_CODE" && event.data.code) {
58426
+ if (event.data.state !== expectedState) {
58427
+ cleanup();
58428
+ reject(new Error("OAuth state mismatch — the callback state does not match the expected value. " + "This may indicate a CSRF attack. Please try signing in again."));
58429
+ popup.close();
58430
+ return;
58431
+ }
58432
+ cleanup();
58433
+ resolve2(event.data.code);
58434
+ popup.close();
58435
+ } else if (event.data?.type === "UIP_AUTH_ERROR") {
58436
+ cleanup();
58437
+ const errorMsg = event.data.error || "Authentication failed";
58438
+ reject(new Error(`Authentication failed: ${errorMsg}
58439
+
58440
+ ` + "Please check your credentials and try again. " + "If the problem persists, verify your UiPath account is active."));
58441
+ popup.close();
58442
+ }
58443
+ };
58444
+ const cleanup = () => {
58445
+ global4.window?.removeEventListener?.("message", messageHandler);
58446
+ if (timer)
58447
+ clearInterval(timer);
58448
+ };
58449
+ if (global4.window?.addEventListener) {
58450
+ global4.window.addEventListener("message", messageHandler);
58451
+ }
58452
+ const timer = setInterval(() => {
58453
+ if (popup.closed) {
58454
+ cleanup();
58455
+ reject(new Error(`Authentication was cancelled.
58456
+
58457
+ ` + "The authentication popup was closed before completing the login process. " + "Please try again and complete the authentication flow."));
58458
+ }
58459
+ }, 1000);
58460
+ });
58461
+ }
58462
+ }
58463
+ var init_browser_strategy = () => {};
58464
+
58220
58465
  // ../auth/src/strategies/node-strategy.ts
58221
58466
  var exports_node_strategy = {};
58222
58467
  __export(exports_node_strategy, {
@@ -58303,7 +58548,8 @@ __export(exports_src, {
58303
58548
  ENV_AUTH_ENABLE_VAR: () => ENV_AUTH_ENABLE_VAR,
58304
58549
  ENFORCE_ROBOT_AUTH_VAR: () => ENFORCE_ROBOT_AUTH_VAR,
58305
58550
  DEFAULT_ENV_FILENAME: () => DEFAULT_ENV_FILENAME,
58306
- DEFAULT_AUTH_FILENAME: () => DEFAULT_AUTH_FILENAME
58551
+ DEFAULT_AUTH_FILENAME: () => DEFAULT_AUTH_FILENAME,
58552
+ AUTH_TIMEOUT_ERROR_CODE: () => AUTH_TIMEOUT_ERROR_CODE
58307
58553
  });
58308
58554
  var authenticate = async ({
58309
58555
  baseUrl,
@@ -58378,6 +58624,7 @@ var init_src2 = __esm(() => {
58378
58624
  init_config();
58379
58625
  init_envAuth();
58380
58626
  init_selectTenant();
58627
+ init_server();
58381
58628
  init_envFile();
58382
58629
  init_jwt();
58383
58630
  init_authContext();
@@ -58390,7 +58637,8 @@ var init_src2 = __esm(() => {
58390
58637
  // package.json
58391
58638
  var package_default = {
58392
58639
  name: "@uipath/codedapp-tool",
58393
- version: "1.1.0",
58640
+ license: "MIT",
58641
+ version: "1.195.0",
58394
58642
  description: "Build, pack, publish, deploy, and manage UiPath Coded Web Applications.",
58395
58643
  keywords: [
58396
58644
  "cli-tool",
@@ -63615,6 +63863,60 @@ function escapeNonAscii(jsonText) {
63615
63863
  function needsAsciiSafeJson(sink) {
63616
63864
  return process.platform === "win32" && !sink.capabilities.isInteractive;
63617
63865
  }
63866
+ function isPlainRecord(value) {
63867
+ if (value === null || typeof value !== "object")
63868
+ return false;
63869
+ const prototype = Object.getPrototypeOf(value);
63870
+ return prototype === Object.prototype || prototype === null;
63871
+ }
63872
+ function toLowerCamelCaseKey(key) {
63873
+ if (!key)
63874
+ return key;
63875
+ if (/[_\-\s]/.test(key)) {
63876
+ const [firstPart, ...restParts] = key.split(/[_\-\s]+/).filter(Boolean);
63877
+ if (!firstPart)
63878
+ return key;
63879
+ return [
63880
+ toLowerCamelCaseSimpleKey(firstPart),
63881
+ ...restParts.map((part) => {
63882
+ const normalized = toLowerCamelCaseSimpleKey(part);
63883
+ return normalized.charAt(0).toUpperCase() + normalized.slice(1);
63884
+ })
63885
+ ].join("");
63886
+ }
63887
+ return toLowerCamelCaseSimpleKey(key);
63888
+ }
63889
+ function toLowerCamelCaseSimpleKey(key) {
63890
+ if (/^[A-Z0-9]+$/.test(key))
63891
+ return key.toLowerCase();
63892
+ return key.replace(/^[A-Z]+(?=[A-Z][a-z]|\d|$)|^[A-Z]/, (match) => match.toLowerCase());
63893
+ }
63894
+ function toPascalCaseKey(key) {
63895
+ const lowerCamelKey = toLowerCamelCaseKey(key);
63896
+ return lowerCamelKey ? lowerCamelKey.charAt(0).toUpperCase() + lowerCamelKey.slice(1) : lowerCamelKey;
63897
+ }
63898
+ function toPascalCaseData(value) {
63899
+ if (Array.isArray(value))
63900
+ return value.map(toPascalCaseData);
63901
+ if (!isPlainRecord(value))
63902
+ return value;
63903
+ const result = {};
63904
+ for (const [key, nestedValue] of Object.entries(value)) {
63905
+ result[toPascalCaseKey(key)] = toPascalCaseData(nestedValue);
63906
+ }
63907
+ return result;
63908
+ }
63909
+ function normalizeDataKeys(data) {
63910
+ return toPascalCaseData(data);
63911
+ }
63912
+ function normalizeOutputKeys(data) {
63913
+ const result = {};
63914
+ for (const [key, value] of Object.entries(data)) {
63915
+ const pascalKey = toPascalCaseKey(key);
63916
+ result[pascalKey] = pascalKey === "Data" ? value : toPascalCaseData(value);
63917
+ }
63918
+ return result;
63919
+ }
63618
63920
  function printOutput(data, format = "json", logFn, asciiSafe = false) {
63619
63921
  if (!data) {
63620
63922
  logFn("Empty response object. No data to display.");
@@ -63677,7 +63979,7 @@ function wrapText(text, width) {
63677
63979
  function printTable(data, logFn, externalLogValue) {
63678
63980
  if (data.length === 0)
63679
63981
  return;
63680
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
63982
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
63681
63983
  const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
63682
63984
  const header = keys.map((key, i2) => key.padEnd(maxWidths[i2])).join(" | ");
63683
63985
  logFn(header);
@@ -63692,7 +63994,7 @@ function printTable(data, logFn, externalLogValue) {
63692
63994
  }
63693
63995
  }
63694
63996
  function printVerticalTable(data, logFn = console.log, externalLogValue) {
63695
- const keys = Object.keys(data).filter((key) => key !== "Code" && key !== "Log");
63997
+ const keys = Object.keys(data).filter((key) => !["code", "log"].includes(key.toLowerCase()));
63696
63998
  if (keys.length === 0)
63697
63999
  return;
63698
64000
  const maxKeyWidth = Math.max(...keys.map((key) => key.length));
@@ -63708,7 +64010,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
63708
64010
  function printResizableTable(data, logFn = console.log, externalLogValue) {
63709
64011
  if (data.length === 0)
63710
64012
  return;
63711
- const keys = Object.keys(data[0]).filter((key) => key !== "Code" && key !== "Log");
64013
+ const keys = Object.keys(data[0]).filter((key) => !["code", "log"].includes(key.toLowerCase()));
63712
64014
  if (keys.length === 0)
63713
64015
  return;
63714
64016
  if (!process.stdout.isTTY) {
@@ -63784,8 +64086,26 @@ function printResizableTable(data, logFn = console.log, externalLogValue) {
63784
64086
  function toYaml(data) {
63785
64087
  return dump(data);
63786
64088
  }
64089
+ class FilterEvaluationError extends Error {
64090
+ __brand = "FilterEvaluationError";
64091
+ filter;
64092
+ instructions;
64093
+ result = RESULTS.ValidationError;
64094
+ constructor(filter, cause) {
64095
+ const underlying = cause instanceof Error ? cause.message : String(cause);
64096
+ super(`Filter '${filter}' failed to evaluate: ${underlying}`);
64097
+ this.name = "FilterEvaluationError";
64098
+ this.filter = filter;
64099
+ this.instructions = `The --output-filter expression '${filter}' failed at evaluation time. ` + "Note that --output-filter operates on the 'Data' field of the envelope, not the full object. " + "For example, on a list result use 'length(@)' instead of 'Data | length(@)'.";
64100
+ }
64101
+ }
63787
64102
  function applyFilter(data, filter) {
63788
- const result = search(data, filter);
64103
+ let result;
64104
+ try {
64105
+ result = search(data, filter);
64106
+ } catch (err) {
64107
+ throw new FilterEvaluationError(filter, err);
64108
+ }
63789
64109
  if (result == null)
63790
64110
  return [];
63791
64111
  if (Array.isArray(result)) {
@@ -63802,13 +64122,18 @@ function applyFilter(data, filter) {
63802
64122
  }
63803
64123
  var OutputFormatter;
63804
64124
  ((OutputFormatter) => {
63805
- function success(data) {
64125
+ function success(data, options) {
63806
64126
  data.Log ??= getLogFilePath() || undefined;
64127
+ const normalize = !options?.preserveDataKeys;
64128
+ if (normalize) {
64129
+ data.Data = normalizeDataKeys(data.Data);
64130
+ }
63807
64131
  const filter = getOutputFilter();
63808
64132
  if (filter) {
63809
- data.Data = applyFilter(data.Data, filter);
64133
+ const filtered = applyFilter(data.Data, filter);
64134
+ data.Data = normalize ? normalizeDataKeys(filtered) : filtered;
63810
64135
  }
63811
- logOutput(data, getOutputFormat());
64136
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
63812
64137
  }
63813
64138
  OutputFormatter.success = success;
63814
64139
  function error(data) {
@@ -63818,7 +64143,7 @@ var OutputFormatter;
63818
64143
  result: data.Result,
63819
64144
  message: data.Message
63820
64145
  });
63821
- logOutput(data, getOutputFormat());
64146
+ logOutput(normalizeOutputKeys(data), getOutputFormat());
63822
64147
  }
63823
64148
  OutputFormatter.error = error;
63824
64149
  function emitList(code, items, opts) {
@@ -63839,13 +64164,14 @@ var OutputFormatter;
63839
64164
  function log(data) {
63840
64165
  const format = getOutputFormat();
63841
64166
  const sink = getOutputSink();
64167
+ const normalized = toPascalCaseData(data);
63842
64168
  if (format === "json") {
63843
- const json2 = JSON.stringify(data);
64169
+ const json2 = JSON.stringify(normalized);
63844
64170
  const safe = needsAsciiSafeJson(sink) ? escapeNonAscii(json2) : json2;
63845
64171
  sink.writeErr(`${safe}
63846
64172
  `);
63847
64173
  } else {
63848
- for (const [key, value] of Object.entries(data)) {
64174
+ for (const [key, value] of Object.entries(normalized)) {
63849
64175
  sink.writeErr(`${key}: ${value}
63850
64176
  `);
63851
64177
  }
@@ -63854,12 +64180,16 @@ var OutputFormatter;
63854
64180
  OutputFormatter.log = log;
63855
64181
  function formatToString(data) {
63856
64182
  const filter = getOutputFilter();
63857
- if (filter && "Data" in data && data.Data != null) {
63858
- data.Data = applyFilter(data.Data, filter);
64183
+ if ("Data" in data && data.Data != null) {
64184
+ data.Data = normalizeDataKeys(data.Data);
64185
+ if (filter) {
64186
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
64187
+ }
63859
64188
  }
64189
+ const output = normalizeOutputKeys(data);
63860
64190
  const lines = [];
63861
64191
  const sink = getOutputSink();
63862
- printOutput(data, getOutputFormat(), (msg) => {
64192
+ printOutput(output, getOutputFormat(), (msg) => {
63863
64193
  lines.push(msg);
63864
64194
  }, needsAsciiSafeJson(sink));
63865
64195
  return lines.join(`
@@ -65270,6 +65600,22 @@ JSONPath.prototype.safeVm = {
65270
65600
  Script: SafeScript
65271
65601
  };
65272
65602
  JSONPath.prototype.vm = vm;
65603
+ // ../common/src/polling/types.ts
65604
+ var PollOutcome = {
65605
+ Completed: "completed",
65606
+ Timeout: "timeout",
65607
+ Interrupted: "interrupted",
65608
+ Aborted: "aborted",
65609
+ Failed: "failed"
65610
+ };
65611
+
65612
+ // ../common/src/polling/poll-failure-mapping.ts
65613
+ var REASON_BY_OUTCOME = {
65614
+ [PollOutcome.Timeout]: "poll_timeout",
65615
+ [PollOutcome.Failed]: "poll_failed",
65616
+ [PollOutcome.Interrupted]: "poll_failed",
65617
+ [PollOutcome.Aborted]: "poll_aborted"
65618
+ };
65273
65619
  // ../common/src/polling/terminal-statuses.ts
65274
65620
  var TERMINAL_STATUSES = new Set([
65275
65621
  "completed",
@@ -65297,6 +65643,8 @@ var ScreenLogger;
65297
65643
  }
65298
65644
  ScreenLogger.progress = progress;
65299
65645
  })(ScreenLogger ||= {});
65646
+ // ../common/src/sdk-user-agent.ts
65647
+ var sdkUserAgentHostToken = singleton("SdkUserAgentHostToken");
65300
65648
  // ../common/src/tool-provider.ts
65301
65649
  var factorySlot = singleton("PackagerFactoryProvider");
65302
65650
  // ../common/src/telemetry/pii-redactor.ts
@@ -65479,13 +65827,17 @@ Command.prototype.trackedAction = function(context, fn, properties) {
65479
65827
  const [error] = await catchError(fn(...args));
65480
65828
  if (error) {
65481
65829
  errorMessage = error instanceof Error ? error.message : String(error);
65482
- logger.error(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
65830
+ logger.debug(`[trackedAction] ${telemetryName} failed: ${errorMessage}`);
65831
+ const typed = error;
65832
+ const customInstructions = typeof typed.instructions === "string" ? typed.instructions : undefined;
65833
+ const customResult = typeof typed.result === "string" && typed.result !== RESULTS.Success && Object.values(RESULTS).includes(typed.result) ? typed.result : undefined;
65834
+ const finalResult = customResult ?? RESULTS.Failure;
65483
65835
  OutputFormatter.error({
65484
- Result: RESULTS.Failure,
65836
+ Result: finalResult,
65485
65837
  Message: errorMessage,
65486
- Instructions: "An unexpected error occurred. Run with --log-level debug for details."
65838
+ Instructions: customInstructions ?? "An unexpected error occurred. Run with --log-level debug for details."
65487
65839
  });
65488
- context.exit(1);
65840
+ context.exit(EXIT_CODES[finalResult]);
65489
65841
  }
65490
65842
  const durationMs = performance.now() - startTime;
65491
65843
  const success = !error && (process.exitCode === undefined || process.exitCode === 0);
@@ -67541,7 +67893,7 @@ import { spawn, spawnSync } from "child_process";
67541
67893
  import { readFileSync, unlinkSync, writeFileSync } from "fs";
67542
67894
  import path3 from "node:path";
67543
67895
  import os4 from "node:os";
67544
- import { randomUUID } from "node:crypto";
67896
+ import { randomUUID as randomUUID2 } from "node:crypto";
67545
67897
 
67546
67898
  // ../../node_modules/inquirer/node_modules/@inquirer/prompts/node_modules/@inquirer/editor/node_modules/@inquirer/external-editor/dist/esm/errors/CreateFileError.js
67547
67899
  class CreateFileError extends Error {
@@ -67671,7 +68023,7 @@ class ExternalEditor {
67671
68023
  createTemporaryFile() {
67672
68024
  try {
67673
68025
  const baseDir = this.fileOptions.dir ?? os4.tmpdir();
67674
- const id = randomUUID();
68026
+ const id = randomUUID2();
67675
68027
  const prefix = sanitizeAffix(this.fileOptions.prefix);
67676
68028
  const postfix = sanitizeAffix(this.fileOptions.postfix);
67677
68029
  const filename = `${prefix}${id}${postfix}`;
@@ -73769,6 +74121,7 @@ var DEFAULT_APP_VERSION = "1.0.0";
73769
74121
  var MESSAGES = {
73770
74122
  ERRORS: {
73771
74123
  INVALID_DIST_DIRECTORY: "Invalid dist directory",
74124
+ MISSING_INDEX_HTML: "index.html not found at the root of the build directory. SSR frameworks (Next.js, Nuxt, Remix) are not supported — only static builds. Make sure you are pointing to the folder that contains index.html (e.g. for Angular: dist/<app-name>/browser/).",
73772
74125
  PACKAGE_NAME_REQUIRED: "Package name is required",
73773
74126
  ACTION_SCHEMA_REQUIRED: "❌ action-schema.json file not found in current working directory",
73774
74127
  ACTION_SCHEMA_REQUIRED_REMOTE: "❌ This project is registered as a Coded Action app but action-schema.json was not found locally. Please add an action-schema.json file to your project root before pushing.",
@@ -88740,20 +89093,26 @@ async function ensureFolderKey(logger3, explicitFolderKey) {
88740
89093
 
88741
89094
  // src/actions/deploy.ts
88742
89095
  var PUBLISHED_APP_LOOKUP_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000];
88743
- async function getDeployedApp(appName, envConfig) {
88744
- const url2 = appendQueryParams(`${envConfig.baseUrl}/${envConfig.orgId}${API_ENDPOINTS.DEPLOYED_APPS}?searchText=${encodeURIComponent(appName)}`, BASIC_ORIGIN_QUERY_PARAMS);
88745
- const response = await fetch2(url2, {
88746
- method: "GET",
88747
- headers: createHeaders({
88748
- bearerToken: envConfig.accessToken,
88749
- tenantId: envConfig.tenantId,
88750
- folderKey: envConfig.folderKey
88751
- })
88752
- });
88753
- if (!response.ok)
88754
- await handleHttpError(response, MESSAGES.ERROR_CONTEXT.APP_DEPLOYMENT);
88755
- const data = await response.json();
88756
- return data.value.find((app) => app.title === appName) ?? null;
89096
+ async function getDeployedApp(appName, displayTitle, envConfig) {
89097
+ const searchTerms = displayTitle !== appName ? [displayTitle, appName] : [appName];
89098
+ for (const searchText of searchTerms) {
89099
+ const url2 = appendQueryParams(`${envConfig.baseUrl}/${envConfig.orgId}${API_ENDPOINTS.DEPLOYED_APPS}?searchText=${encodeURIComponent(searchText)}`, BASIC_ORIGIN_QUERY_PARAMS);
89100
+ const response = await fetch2(url2, {
89101
+ method: "GET",
89102
+ headers: createHeaders({
89103
+ bearerToken: envConfig.accessToken,
89104
+ tenantId: envConfig.tenantId,
89105
+ folderKey: envConfig.folderKey
89106
+ })
89107
+ });
89108
+ if (!response.ok)
89109
+ await handleHttpError(response, MESSAGES.ERROR_CONTEXT.APP_DEPLOYMENT);
89110
+ const data = await response.json();
89111
+ const match = data.value.find((app) => app.title === appName || app.title === displayTitle);
89112
+ if (match)
89113
+ return match;
89114
+ }
89115
+ return null;
88757
89116
  }
88758
89117
  async function getPublishedApp(appName, envConfig, version2) {
88759
89118
  const endpoint = API_ENDPOINTS.PUBLISHED_APPS.replace("{tenantId}", envConfig.tenantId);
@@ -88808,9 +89167,13 @@ async function checkAppNameUniqueness(appName, envConfig) {
88808
89167
  throw new Error(MESSAGES.ERRORS.APP_NAME_ALREADY_EXISTS);
88809
89168
  }
88810
89169
  }
88811
- async function deployNewApp(appName, routingName, systemName, envConfig) {
89170
+ async function deployNewApp(appName, routingName, systemName, envConfig, tags) {
88812
89171
  const endpoint = API_ENDPOINTS.DEPLOY_APP.replace("{systemName}", systemName);
88813
89172
  const url2 = appendQueryParams(`${envConfig.baseUrl}/${envConfig.orgId}${endpoint}`, BASIC_ORIGIN_QUERY_PARAMS);
89173
+ const body = { title: appName, routingName };
89174
+ if (tags?.length) {
89175
+ body.tags = tags;
89176
+ }
88814
89177
  const response = await fetch2(url2, {
88815
89178
  method: "POST",
88816
89179
  headers: createHeaders({
@@ -88818,14 +89181,14 @@ async function deployNewApp(appName, routingName, systemName, envConfig) {
88818
89181
  tenantId: envConfig.tenantId,
88819
89182
  folderKey: envConfig.folderKey
88820
89183
  }),
88821
- body: JSON.stringify({ title: appName, routingName })
89184
+ body: JSON.stringify(body)
88822
89185
  });
88823
89186
  if (!response.ok)
88824
89187
  await handleHttpError(response, MESSAGES.ERROR_CONTEXT.APP_DEPLOYMENT);
88825
89188
  const data = await response.json();
88826
89189
  return data.id;
88827
89190
  }
88828
- async function upgradeApp(appId, title, version2, routingName, envConfig) {
89191
+ async function upgradeApp(appId, title, version2, routingName, envConfig, tags) {
88829
89192
  const url2 = appendQueryParams(`${envConfig.baseUrl}/${envConfig.orgId}${API_ENDPOINTS.EDIT_DEPLOYED_APP.replace("{appId}", appId)}`, BASIC_ORIGIN_QUERY_PARAMS);
88830
89193
  const body = {
88831
89194
  title,
@@ -88835,6 +89198,9 @@ async function upgradeApp(appId, title, version2, routingName, envConfig) {
88835
89198
  if (routingName !== undefined) {
88836
89199
  body.routingName = routingName;
88837
89200
  }
89201
+ if (tags?.length) {
89202
+ body.tags = tags;
89203
+ }
88838
89204
  const response = await fetch2(url2, {
88839
89205
  method: "PATCH",
88840
89206
  headers: createHeaders({
@@ -88882,6 +89248,7 @@ async function executeDeploy(options) {
88882
89248
  });
88883
89249
  if (!envConfig)
88884
89250
  throw new Error("Missing required configuration");
89251
+ const originalName = options.packageName;
88885
89252
  if (options.packageName) {
88886
89253
  const { sanitized, isModified } = sanitizeAppName(options.packageName);
88887
89254
  if (isModified) {
@@ -88892,6 +89259,8 @@ async function executeDeploy(options) {
88892
89259
  const appName = options.packageName ?? await getAppName(logger3);
88893
89260
  if (!appName)
88894
89261
  throw new Error(MESSAGES.VALIDATIONS.APP_NAME_REQUIRED);
89262
+ const appConfig = await loadAppConfig(logger3);
89263
+ const displayTitle = originalName || appConfig?.displayName || appName;
88895
89264
  let routingName;
88896
89265
  if (options.pathName) {
88897
89266
  const { sanitized, isModified } = sanitizeAppName(options.pathName);
@@ -88907,7 +89276,7 @@ async function executeDeploy(options) {
88907
89276
  validateAppNameLength(routingName);
88908
89277
  let spinner = ora(MESSAGES.INFO.CHECKING_DEPLOYMENT_STATUS).start();
88909
89278
  const [deployError] = await catchError((async () => {
88910
- const deployedApp = await getDeployedApp(appName, envConfig);
89279
+ const deployedApp = await getDeployedApp(appName, displayTitle, envConfig);
88911
89280
  let version2;
88912
89281
  if (deployedApp) {
88913
89282
  spinner.text = MESSAGES.INFO.UPGRADING_APP;
@@ -88923,10 +89292,10 @@ async function executeDeploy(options) {
88923
89292
  spinner.fail(source_default.red(MESSAGES.ERRORS.DEPLOY_VERSION_NOT_FOUND));
88924
89293
  throw new Error(MESSAGES.ERRORS.DEPLOY_VERSION_NOT_FOUND);
88925
89294
  }
88926
- await upgradeApp(deployedApp.id, appName, publishedApp.deployVersion, options.pathName ? routingName : undefined, envConfig);
89295
+ await upgradeApp(deployedApp.id, displayTitle, publishedApp.deployVersion, options.pathName ? routingName : undefined, envConfig, options.tags);
88927
89296
  spinner.succeed(source_default.green(MESSAGES.SUCCESS.APP_UPGRADED_SUCCESS));
88928
- const appConfig2 = await loadAppConfig(logger3);
88929
- version2 = publishedApp.appVersion ?? appConfig2?.appVersion ?? deployedApp.semVersion;
89297
+ const appConfig3 = await loadAppConfig(logger3);
89298
+ version2 = publishedApp.appVersion ?? appConfig3?.appVersion ?? deployedApp.semVersion;
88930
89299
  cliTelemetryClient.track(CodedAppTelemetryEvents.Deploy, {
88931
89300
  operation: "upgrade"
88932
89301
  });
@@ -88943,20 +89312,20 @@ async function executeDeploy(options) {
88943
89312
  spinner.fail(source_default.red(notFoundMsg));
88944
89313
  throw new Error(notFoundMsg);
88945
89314
  }
88946
- const deploymentId = await deployNewApp(appName, routingName, publishedApp.systemName, envConfig);
89315
+ const deploymentId = await deployNewApp(displayTitle, routingName, publishedApp.systemName, envConfig, options.tags);
88947
89316
  spinner.succeed(source_default.green(MESSAGES.SUCCESS.APP_DEPLOYED_SUCCESS));
88948
89317
  await updateAppConfig(deploymentId, logger3);
88949
- const appConfig2 = await loadAppConfig(logger3);
88950
- version2 = appConfig2?.appVersion ?? "1.0.0";
89318
+ const appConfig3 = await loadAppConfig(logger3);
89319
+ version2 = appConfig3?.appVersion ?? "1.0.0";
88951
89320
  cliTelemetryClient.track(CodedAppTelemetryEvents.Deploy, {
88952
89321
  operation: "fresh_deploy"
88953
89322
  });
88954
89323
  }
88955
89324
  logger3.log("");
88956
- logger3.log(` ${source_default.cyan("App Name:")} ${appName}`);
89325
+ logger3.log(` ${source_default.cyan("App Name:")} ${displayTitle}`);
88957
89326
  logger3.log(` ${source_default.cyan("Version:")} ${version2}`);
88958
- const appConfig = await loadAppConfig(logger3);
88959
- if (appConfig?.appType === "Action" /* Action */) {
89327
+ const appConfig2 = await loadAppConfig(logger3);
89328
+ if (appConfig2?.appType === "Action" /* Action */) {
88960
89329
  logger3.log(` ${source_default.yellow(MESSAGES.INFO.ACTION_APP_RUN_IN_ACTION_CENTER)}`);
88961
89330
  } else {
88962
89331
  const appUrl = buildAppUrl(envConfig.baseUrl, envConfig.orgName, routingName);
@@ -89004,14 +89373,25 @@ var DEPLOY_EXAMPLES = [
89004
89373
  message: "App deployed successfully."
89005
89374
  }
89006
89375
  }
89376
+ },
89377
+ {
89378
+ Description: "Deploy the current coded app with system tags",
89379
+ Command: 'uip codedapp deploy --name "MyApp" --tags governance',
89380
+ Output: {
89381
+ Code: "DeployCompleted",
89382
+ Data: {
89383
+ message: "App deployed successfully."
89384
+ }
89385
+ }
89007
89386
  }
89008
89387
  ];
89009
89388
  var registerDeployCommand = (program2) => {
89010
- program2.command("deploy").description("Deploy or upgrade app in UiPath").option("-n, --name <name>", "App name").option("--path-name <name>", "App pathname in the URL (https://<org>.uipath.host/<path-name>)").option("-v, --version <version>", "Target a specific published version").option("--base-url <url>", "UiPath base URL").option("--org-id <id>", "Organization ID").option("--org-name <name>", "Organization name").option("--tenant-id <id>", "Tenant ID").option("--folder-key <key>", "Folder key").option("--access-token <token>", "Access token").examples(DEPLOY_EXAMPLES).trackedAction(processContext, async (options) => {
89389
+ program2.command("deploy").description("Deploy or upgrade app in UiPath").option("-n, --name <name>", "App name").option("--path-name <name>", "App pathname in the URL (https://<org>.uipath.host/<path-name>)").option("-v, --version <version>", "Target a specific published version").option("--base-url <url>", "UiPath base URL").option("--org-id <id>", "Organization ID").option("--org-name <name>", "Organization name").option("--tenant-id <id>", "Tenant ID").option("--folder-key <key>", "Folder key").option("--access-token <token>", "Access token").option("--tags <tags>", "Comma-separated categorization labels for the deployed app (e.g. governance,insights)").examples(DEPLOY_EXAMPLES).trackedAction(processContext, async (options) => {
89011
89390
  const logger3 = {
89012
89391
  log: (msg) => getOutputSink().writeErr(msg + `
89013
89392
  `)
89014
89393
  };
89394
+ const tags = options.tags?.split(",").map((t2) => t2.trim()).filter(Boolean);
89015
89395
  const [error52] = await catchError(executeDeploy({
89016
89396
  packageName: options.name,
89017
89397
  pathName: options.pathName,
@@ -89022,6 +89402,7 @@ var registerDeployCommand = (program2) => {
89022
89402
  tenantId: options.tenantId,
89023
89403
  folderKey: options.folderKey,
89024
89404
  accessToken: options.accessToken,
89405
+ tags,
89025
89406
  logger: logger3
89026
89407
  }));
89027
89408
  if (error52) {
@@ -90809,6 +91190,7 @@ class ToolResult {
90809
91190
  errorCode;
90810
91191
  message;
90811
91192
  packages;
91193
+ details;
90812
91194
  constructor(errorCode, message, packages = []) {
90813
91195
  this.errorCode = errorCode;
90814
91196
  this.message = message;
@@ -92649,6 +93031,7 @@ async function handleMetadataJson(config2) {
92649
93031
  } else {
92650
93032
  await fs8.writeFile(targetMetadata, JSON.stringify({
92651
93033
  name: config2.name,
93034
+ displayName: config2.originalName,
92652
93035
  version: config2.version,
92653
93036
  description: config2.description,
92654
93037
  author: config2.author,
@@ -92667,6 +93050,11 @@ async function executePack(options) {
92667
93050
  if (!await validateDistDirectory(distDir)) {
92668
93051
  throw new Error(`${MESSAGES.ERRORS.INVALID_DIST_DIRECTORY}: ${distDir}`);
92669
93052
  }
93053
+ const fs8 = getFileSystem();
93054
+ const indexPath = fs8.path.join(distDir, "index.html");
93055
+ if (!await fs8.exists(indexPath)) {
93056
+ throw new Error(MESSAGES.ERRORS.MISSING_INDEX_HTML);
93057
+ }
92670
93058
  if (await hasAbsoluteAssetPaths(distDir)) {
92671
93059
  logger3.log(source_default.yellow(MESSAGES.INFO.ABSOLUTE_ASSET_PATHS_DETECTED));
92672
93060
  }
@@ -92688,6 +93076,7 @@ async function executePack(options) {
92688
93076
  }
92689
93077
  if (!packageName)
92690
93078
  throw new Error(MESSAGES.ERRORS.PACKAGE_NAME_REQUIRED);
93079
+ const originalInputName = packageName;
92691
93080
  const { sanitized: sanitizedInput, isModified } = sanitizeAppName(packageName);
92692
93081
  if (isModified) {
92693
93082
  logger3.log(source_default.yellow(MESSAGE_BUILDERS.APP_NAME_SANITIZED(packageName, sanitizedInput)));
@@ -92706,7 +93095,7 @@ async function executePack(options) {
92706
93095
  const packageConfig = {
92707
93096
  distDir,
92708
93097
  name: sanitizedName,
92709
- originalName: packageName,
93098
+ originalName: originalInputName,
92710
93099
  version: version2,
92711
93100
  author: options.author ?? "UiPath Developer",
92712
93101
  description,
@@ -93003,6 +93392,17 @@ function extractPackageMetadata(packagePath) {
93003
93392
  packageVersion: parts.slice(versionStartIndex).join(".")
93004
93393
  };
93005
93394
  }
93395
+ async function readDisplayName(uipathDir) {
93396
+ const fs8 = getFileSystem();
93397
+ const metadataPath = fs8.path.join(uipathDir, AUTH_CONSTANTS.FILES.METADATA_FILE);
93398
+ const [error52, content] = await catchError(fs8.readFile(metadataPath, "utf-8"));
93399
+ if (error52 || !content)
93400
+ return;
93401
+ const [parseError, parsed] = catchError(() => JSON.parse(content));
93402
+ if (parseError)
93403
+ return;
93404
+ return parsed.displayName;
93405
+ }
93006
93406
  async function uploadPackage(packagePath, envConfig, spinner) {
93007
93407
  const fileContent = await getFileSystem().readFile(packagePath);
93008
93408
  if (fileContent === null) {
@@ -93054,7 +93454,7 @@ async function registerCodedApp(metadata, envConfig, isActionApp, logger3) {
93054
93454
  tenantName: envConfig.tenantName,
93055
93455
  packageName: metadata.packageName,
93056
93456
  packageVersion: metadata.packageVersion,
93057
- title: metadata.packageName,
93457
+ title: metadata.displayName || metadata.packageName,
93058
93458
  schema: actionSchema
93059
93459
  };
93060
93460
  const response = await fetch(url2, {
@@ -93200,6 +93600,7 @@ async function executePublish(options) {
93200
93600
  spinner.start();
93201
93601
  }
93202
93602
  const metadata = extractPackageMetadata(selectedPackage);
93603
+ metadata.displayName = await readDisplayName(uipathDir);
93203
93604
  spinner.text = MESSAGES.INFO.UPLOADING_PACKAGE;
93204
93605
  await uploadPackage(selectedPackage, envConfig, spinner);
93205
93606
  spinner.succeed(source_default.green(MESSAGES.SUCCESS.PACKAGE_UPLOADED_SUCCESS));
@@ -93208,6 +93609,7 @@ async function executePublish(options) {
93208
93609
  spinner.succeed(source_default.green(MESSAGES.SUCCESS.CODED_APP_REGISTERED_SUCCESS));
93209
93610
  const [saveError] = await catchError(saveAppConfig({
93210
93611
  appName: metadata.packageName,
93612
+ displayName: metadata.displayName,
93211
93613
  appVersion: metadata.packageVersion,
93212
93614
  systemName: registerResponse.definition.systemName,
93213
93615
  appUrl: null,