@uipath/auth 1.202.0-preview.159 → 1.203.0-preview.160

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.
@@ -9,3 +9,32 @@ export declare function getActiveAuthProfile(): string | undefined;
9
9
  export declare function runWithAuthProfile<T>(profile: string | undefined, fn: () => T): T;
10
10
  export declare function resolveAuthProfileFilePath(profile: string): string;
11
11
  export declare function getActiveAuthProfileFilePath(): string | undefined;
12
+ /** Absolute path to the directory holding all named profiles: `~/.uipath/profiles`. */
13
+ export declare function getAuthProfilesRootPath(): string;
14
+ /**
15
+ * Absolute path to a named profile's own directory. Unlike
16
+ * {@link resolveAuthProfileFilePath} this points at the folder, not the
17
+ * credentials file inside it — deleting a profile has to remove the whole
18
+ * folder, sidecars (`.auth.refresh-state`) included.
19
+ */
20
+ export declare function resolveAuthProfileDirPath(profile: string): string;
21
+ /**
22
+ * Names of every named profile on disk, sorted. A profile is a directory under
23
+ * `~/.uipath/profiles`; entries that are not directories, or whose names would
24
+ * fail {@link normalizeAuthProfileName}, are skipped rather than reported —
25
+ * they cannot be passed to `--profile`, so listing them would be a lie.
26
+ *
27
+ * Does not include the built-in `default` profile, which is not stored here.
28
+ */
29
+ export declare function listAuthProfileNamesAsync(): Promise<string[]>;
30
+ /** Whether a named profile has a directory on disk. */
31
+ export declare function authProfileExistsAsync(profile: string): Promise<boolean>;
32
+ /**
33
+ * Remove a named profile's directory and everything in it — credentials file
34
+ * and refresh-state sidecar alike. Returns the removed path, or `undefined`
35
+ * when the profile had no directory to begin with.
36
+ *
37
+ * Refuses the built-in `default` profile: its credentials are not stored under
38
+ * `profiles/` and are owned by `uip logout`.
39
+ */
40
+ export declare function deleteAuthProfileAsync(profile: string): Promise<string | undefined>;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Credential state read from what is on disk. Deliberately narrower than
3
+ * {@link import("./loginStatus").LoginStatusValue}: describing a profile never
4
+ * attempts a token refresh, so `"Refresh Failed"` cannot arise here.
5
+ */
6
+ export type AuthProfileStatus = "Logged in" | "Not logged in" | "Expired" | "Unreadable";
7
+ export interface AuthProfileDetails {
8
+ /** Name to pass to `--profile`. `default` is the built-in profile. */
9
+ name: string;
10
+ /** Whether this is the profile the current invocation resolves to. */
11
+ active: boolean;
12
+ organizationName?: string;
13
+ tenantName?: string;
14
+ url?: string;
15
+ status: AuthProfileStatus;
16
+ /** When the access token expires. Absent when there is no usable token. */
17
+ expiresAt?: string;
18
+ /** Absolute path to the profile's credentials file. */
19
+ path?: string;
20
+ }
21
+ /**
22
+ * Describe every profile the CLI can be pointed at, `default` first and named
23
+ * profiles after it in name order.
24
+ *
25
+ * `default` is included even though it has no directory under
26
+ * `~/.uipath/profiles` — it is a legal `--profile` value (and the value used
27
+ * when the flag is omitted), so omitting it would misreport what is available.
28
+ * Its credentials file is resolved the same way the rest of the CLI resolves
29
+ * it: a `.uipath/.auth` walked up from `cwd`, else the one under `$HOME`.
30
+ */
31
+ export declare function describeAuthProfilesAsync(): Promise<AuthProfileDetails[]>;
@@ -18277,6 +18277,63 @@ function getActiveAuthProfileFilePath() {
18277
18277
  const profile = getActiveAuthProfile();
18278
18278
  return profile ? resolveAuthProfileFilePath(profile) : undefined;
18279
18279
  }
18280
+ function getAuthProfilesRootPath() {
18281
+ const fs = getFileSystem();
18282
+ return fs.path.join(fs.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR);
18283
+ }
18284
+ function resolveAuthProfileDirPath(profile) {
18285
+ const normalized = normalizeAuthProfileName(profile);
18286
+ if (normalized === undefined) {
18287
+ throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile directory.`);
18288
+ }
18289
+ const fs = getFileSystem();
18290
+ return fs.path.join(getAuthProfilesRootPath(), normalized);
18291
+ }
18292
+ async function listAuthProfileNamesAsync() {
18293
+ const fs = getFileSystem();
18294
+ const root = getAuthProfilesRootPath();
18295
+ if (!await fs.exists(root)) {
18296
+ return [];
18297
+ }
18298
+ const [readError, entries] = await catchError(fs.readdir(root));
18299
+ if (readError || !entries) {
18300
+ return [];
18301
+ }
18302
+ const names = [];
18303
+ for (const entry of entries) {
18304
+ if (!PROFILE_NAME_RE.test(entry) || entry === DEFAULT_AUTH_PROFILE) {
18305
+ continue;
18306
+ }
18307
+ const stats = await fs.stat(fs.path.join(root, entry));
18308
+ if (stats?.isDirectory()) {
18309
+ names.push(entry);
18310
+ }
18311
+ }
18312
+ return names.sort((a, b) => a.localeCompare(b));
18313
+ }
18314
+ async function authProfileExistsAsync(profile) {
18315
+ const fs = getFileSystem();
18316
+ const [pathError, dir] = catchError(() => resolveAuthProfileDirPath(profile));
18317
+ if (pathError || dir === undefined) {
18318
+ return false;
18319
+ }
18320
+ const stats = await fs.stat(dir);
18321
+ return stats?.isDirectory() === true;
18322
+ }
18323
+ async function deleteAuthProfileAsync(profile) {
18324
+ const dir = resolveAuthProfileDirPath(profile);
18325
+ const fs = getFileSystem();
18326
+ const relativeToRoot = fs.path.relative(getAuthProfilesRootPath(), dir);
18327
+ if (relativeToRoot === "" || relativeToRoot.startsWith("..") || fs.path.isAbsolute(relativeToRoot)) {
18328
+ throw new AuthProfileValidationError(`Refusing to delete "${profile}": resolved path escapes the profiles directory.`);
18329
+ }
18330
+ const stats = await fs.stat(dir);
18331
+ if (stats?.isDirectory() !== true) {
18332
+ return;
18333
+ }
18334
+ await fs.rm(dir);
18335
+ return dir;
18336
+ }
18280
18337
 
18281
18338
  // src/config.ts
18282
18339
  var DEFAULT_CLIENT_ID = "36dea5b8-e8bb-423d-8e7b-c808df8f1c00";
@@ -18954,16 +19011,7 @@ var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) =
18954
19011
  errorMessage: location.source === "absolute" ? `Environment file not found: ${envFilePath}` : `Unable to locate environment file: ${envFilePath}. Run 'uip login' to authenticate.`
18955
19012
  };
18956
19013
  };
18957
- var loadEnvFileAsync = async ({ envPath }) => {
18958
- const fs = getFileSystem4();
18959
- const absolutePath = fs.path.isAbsolute(envPath) ? envPath : fs.path.join(fs.env.cwd(), envPath);
18960
- if (!await fs.exists(absolutePath)) {
18961
- throw new Error(`Environment file not found: ${envPath}`);
18962
- }
18963
- const content = await fs.readFile(absolutePath, "utf-8");
18964
- if (content === null) {
18965
- throw new Error(`Environment file not found: ${envPath}`);
18966
- }
19014
+ var parseEnvContent = (content) => {
18967
19015
  const env = {};
18968
19016
  for (const line of content.split(`
18969
19017
  `)) {
@@ -18984,6 +19032,18 @@ var loadEnvFileAsync = async ({ envPath }) => {
18984
19032
  }
18985
19033
  return env;
18986
19034
  };
19035
+ var loadEnvFileAsync = async ({ envPath }) => {
19036
+ const fs = getFileSystem4();
19037
+ const absolutePath = fs.path.isAbsolute(envPath) ? envPath : fs.path.join(fs.env.cwd(), envPath);
19038
+ if (!await fs.exists(absolutePath)) {
19039
+ throw new Error(`Environment file not found: ${envPath}`);
19040
+ }
19041
+ const content = await fs.readFile(absolutePath, "utf-8");
19042
+ if (content === null) {
19043
+ throw new Error(`Environment file not found: ${envPath}`);
19044
+ }
19045
+ return parseEnvContent(content);
19046
+ };
18987
19047
  var saveEnvFileAsync = async ({
18988
19048
  envPath,
18989
19049
  data,
@@ -19747,18 +19807,22 @@ export {
19747
19807
  DEFAULT_ENV_FILENAME,
19748
19808
  InvalidBaseUrlError,
19749
19809
  TokenRefreshOAuthError,
19810
+ authProfileExistsAsync,
19750
19811
  clearActiveAuthProfile,
19751
19812
  clientCredentialsLogin,
19813
+ deleteAuthProfileAsync,
19752
19814
  fetchTenantsAndOrganizations,
19753
19815
  getActiveAuthProfile,
19754
19816
  getActiveAuthProfileFilePath,
19755
19817
  getAuthContext,
19756
19818
  getAuthEnv,
19819
+ getAuthProfilesRootPath,
19757
19820
  getLoginStatusAsync,
19758
19821
  getLoginStatusWithDeps,
19759
19822
  isBrowser,
19760
19823
  isNode,
19761
19824
  isTokenRefreshOAuthFailure,
19825
+ listAuthProfileNamesAsync,
19762
19826
  loadEnvFileAsync,
19763
19827
  logout,
19764
19828
  logoutWithDeps,
@@ -19766,6 +19830,7 @@ export {
19766
19830
  parseAuthFlow,
19767
19831
  parseJWT,
19768
19832
  refreshAccessToken,
19833
+ resolveAuthProfileDirPath,
19769
19834
  resolveAuthProfileFilePath,
19770
19835
  resolveEnvFileLocationAsync,
19771
19836
  resolveEnvFilePathAsync,
@@ -19776,4 +19841,4 @@ export {
19776
19841
  setAuthFileConfig
19777
19842
  };
19778
19843
 
19779
- //# debugId=2C66658C2F43E99364756E2164756E21
19844
+ //# debugId=BA72FB3851B49E2164756E2164756E21
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./authContext";
2
2
  export * from "./authProfile";
3
+ export * from "./authProfileDetails";
3
4
  export * from "./clientCredentials";
4
5
  export { type AuthFileConfig, InvalidBaseUrlError, setAuthFileConfig, } from "./config";
5
6
  export { AUTH_CANCELLED_ERROR_CODE, AUTH_RECLAIMED_ERROR_CODE, AUTH_TIMEOUT_ERROR_CODE, DEFAULT_AUTH_TIMEOUT_MS, } from "./constants";
package/dist/index.js CHANGED
@@ -2050,6 +2050,63 @@ function getActiveAuthProfileFilePath() {
2050
2050
  const profile = getActiveAuthProfile();
2051
2051
  return profile ? resolveAuthProfileFilePath(profile) : undefined;
2052
2052
  }
2053
+ function getAuthProfilesRootPath() {
2054
+ const fs7 = getFileSystem();
2055
+ return fs7.path.join(fs7.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR);
2056
+ }
2057
+ function resolveAuthProfileDirPath(profile) {
2058
+ const normalized = normalizeAuthProfileName(profile);
2059
+ if (normalized === undefined) {
2060
+ throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile directory.`);
2061
+ }
2062
+ const fs7 = getFileSystem();
2063
+ return fs7.path.join(getAuthProfilesRootPath(), normalized);
2064
+ }
2065
+ async function listAuthProfileNamesAsync() {
2066
+ const fs7 = getFileSystem();
2067
+ const root = getAuthProfilesRootPath();
2068
+ if (!await fs7.exists(root)) {
2069
+ return [];
2070
+ }
2071
+ const [readError, entries] = await catchError(fs7.readdir(root));
2072
+ if (readError || !entries) {
2073
+ return [];
2074
+ }
2075
+ const names = [];
2076
+ for (const entry of entries) {
2077
+ if (!PROFILE_NAME_RE.test(entry) || entry === DEFAULT_AUTH_PROFILE) {
2078
+ continue;
2079
+ }
2080
+ const stats = await fs7.stat(fs7.path.join(root, entry));
2081
+ if (stats?.isDirectory()) {
2082
+ names.push(entry);
2083
+ }
2084
+ }
2085
+ return names.sort((a, b) => a.localeCompare(b));
2086
+ }
2087
+ async function authProfileExistsAsync(profile) {
2088
+ const fs7 = getFileSystem();
2089
+ const [pathError, dir] = catchError(() => resolveAuthProfileDirPath(profile));
2090
+ if (pathError || dir === undefined) {
2091
+ return false;
2092
+ }
2093
+ const stats = await fs7.stat(dir);
2094
+ return stats?.isDirectory() === true;
2095
+ }
2096
+ async function deleteAuthProfileAsync(profile) {
2097
+ const dir = resolveAuthProfileDirPath(profile);
2098
+ const fs7 = getFileSystem();
2099
+ const relativeToRoot = fs7.path.relative(getAuthProfilesRootPath(), dir);
2100
+ if (relativeToRoot === "" || relativeToRoot.startsWith("..") || fs7.path.isAbsolute(relativeToRoot)) {
2101
+ throw new AuthProfileValidationError(`Refusing to delete "${profile}": resolved path escapes the profiles directory.`);
2102
+ }
2103
+ const stats = await fs7.stat(dir);
2104
+ if (stats?.isDirectory() !== true) {
2105
+ return;
2106
+ }
2107
+ await fs7.rm(dir);
2108
+ return dir;
2109
+ }
2053
2110
  // src/utils/jwt.ts
2054
2111
  class InvalidIssuerError extends Error {
2055
2112
  expected;
@@ -2621,16 +2678,7 @@ var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) =
2621
2678
  errorMessage: location.source === "absolute" ? `Environment file not found: ${envFilePath}` : `Unable to locate environment file: ${envFilePath}. Run 'uip login' to authenticate.`
2622
2679
  };
2623
2680
  };
2624
- var loadEnvFileAsync = async ({ envPath }) => {
2625
- const fs7 = getFileSystem();
2626
- const absolutePath = fs7.path.isAbsolute(envPath) ? envPath : fs7.path.join(fs7.env.cwd(), envPath);
2627
- if (!await fs7.exists(absolutePath)) {
2628
- throw new Error(`Environment file not found: ${envPath}`);
2629
- }
2630
- const content = await fs7.readFile(absolutePath, "utf-8");
2631
- if (content === null) {
2632
- throw new Error(`Environment file not found: ${envPath}`);
2633
- }
2681
+ var parseEnvContent = (content) => {
2634
2682
  const env = {};
2635
2683
  for (const line of content.split(`
2636
2684
  `)) {
@@ -2651,6 +2699,18 @@ var loadEnvFileAsync = async ({ envPath }) => {
2651
2699
  }
2652
2700
  return env;
2653
2701
  };
2702
+ var loadEnvFileAsync = async ({ envPath }) => {
2703
+ const fs7 = getFileSystem();
2704
+ const absolutePath = fs7.path.isAbsolute(envPath) ? envPath : fs7.path.join(fs7.env.cwd(), envPath);
2705
+ if (!await fs7.exists(absolutePath)) {
2706
+ throw new Error(`Environment file not found: ${envPath}`);
2707
+ }
2708
+ const content = await fs7.readFile(absolutePath, "utf-8");
2709
+ if (content === null) {
2710
+ throw new Error(`Environment file not found: ${envPath}`);
2711
+ }
2712
+ return parseEnvContent(content);
2713
+ };
2654
2714
  var saveEnvFileAsync = async ({
2655
2715
  envPath,
2656
2716
  data,
@@ -3225,6 +3285,62 @@ var getAuthEnv = async (options = {}) => {
3225
3285
  }
3226
3286
  return { authEnv, loginStatus: status };
3227
3287
  };
3288
+ // src/authProfileDetails.ts
3289
+ init_src();
3290
+ var ORGANIZATION_NAME_KEY = "UIPATH_ORGANIZATION_NAME";
3291
+ var TENANT_NAME_KEY = "UIPATH_TENANT_NAME";
3292
+ var URL_KEY = "UIPATH_URL";
3293
+ var ACCESS_TOKEN_KEY = "UIPATH_ACCESS_TOKEN";
3294
+ function statusFromToken(accessToken) {
3295
+ if (!accessToken) {
3296
+ return { status: "Not logged in" };
3297
+ }
3298
+ const expiration = getTokenExpiration(accessToken);
3299
+ if (expiration === undefined) {
3300
+ return { status: "Logged in" };
3301
+ }
3302
+ return {
3303
+ status: expiration.getTime() <= Date.now() ? "Expired" : "Logged in",
3304
+ expiresAt: expiration.toISOString()
3305
+ };
3306
+ }
3307
+ async function describeAuthProfileAsync(name, filePath, active) {
3308
+ const base = {
3309
+ name,
3310
+ active,
3311
+ ...filePath ? { path: filePath } : {}
3312
+ };
3313
+ if (!filePath) {
3314
+ return { ...base, status: "Not logged in" };
3315
+ }
3316
+ const fs7 = getFileSystem();
3317
+ const [readError, content] = await catchError(fs7.readFile(filePath, "utf-8"));
3318
+ if (readError) {
3319
+ return { ...base, status: "Unreadable" };
3320
+ }
3321
+ if (content === null || content === undefined) {
3322
+ return { ...base, status: "Not logged in" };
3323
+ }
3324
+ const values = parseEnvContent(content);
3325
+ return {
3326
+ ...base,
3327
+ ...values[ORGANIZATION_NAME_KEY] ? { organizationName: values[ORGANIZATION_NAME_KEY] } : {},
3328
+ ...values[TENANT_NAME_KEY] ? { tenantName: values[TENANT_NAME_KEY] } : {},
3329
+ ...values[URL_KEY] ? { url: values[URL_KEY] } : {},
3330
+ ...statusFromToken(values[ACCESS_TOKEN_KEY])
3331
+ };
3332
+ }
3333
+ async function describeAuthProfilesAsync() {
3334
+ const activeProfile = getActiveAuthProfile();
3335
+ const [defaultPathError, defaultLocation] = await catchError(resolveEnvFilePathAsync());
3336
+ const rows = [
3337
+ await describeAuthProfileAsync(DEFAULT_AUTH_PROFILE, defaultPathError ? undefined : defaultLocation?.absolutePath, activeProfile === undefined)
3338
+ ];
3339
+ for (const name of await listAuthProfileNamesAsync()) {
3340
+ rows.push(await describeAuthProfileAsync(name, resolveAuthProfileFilePath(name), activeProfile === name));
3341
+ }
3342
+ return rows;
3343
+ }
3228
3344
  // src/tokenGrant.ts
3229
3345
  var requestClientCredentialsToken = async ({
3230
3346
  tokenEndpoint,
@@ -3840,16 +3956,20 @@ export {
3840
3956
  TenantSelectionError,
3841
3957
  TenantSelectionRequiredError,
3842
3958
  TokenRefreshOAuthError,
3959
+ authProfileExistsAsync,
3843
3960
  authenticate,
3844
3961
  clearActiveAuthProfile,
3845
3962
  clearRefreshBreaker,
3846
3963
  clientCredentialsLogin,
3964
+ deleteAuthProfileAsync,
3965
+ describeAuthProfilesAsync,
3847
3966
  federatedCredentialsLogin,
3848
3967
  fetchTenantsAndOrganizations,
3849
3968
  getActiveAuthProfile,
3850
3969
  getActiveAuthProfileFilePath,
3851
3970
  getAuthContext,
3852
3971
  getAuthEnv,
3972
+ getAuthProfilesRootPath,
3853
3973
  getLoginStatusAsync,
3854
3974
  getLoginStatusWithDeps,
3855
3975
  interactiveLogin,
@@ -3860,6 +3980,7 @@ export {
3860
3980
  isRobotAuthEnforced,
3861
3981
  isTenantSelectionError,
3862
3982
  isTokenRefreshOAuthFailure,
3983
+ listAuthProfileNamesAsync,
3863
3984
  loadEnvFileAsync,
3864
3985
  loadRefreshBreaker,
3865
3986
  logout,
@@ -3871,6 +3992,7 @@ export {
3871
3992
  refreshAccessToken,
3872
3993
  refreshTokenFingerprint,
3873
3994
  registerRobotClientLoader,
3995
+ resolveAuthProfileDirPath,
3874
3996
  resolveAuthProfileFilePath,
3875
3997
  resolveEnvFileLocationAsync,
3876
3998
  resolveEnvFilePathAsync,
@@ -3883,4 +4005,4 @@ export {
3883
4005
  setAuthFileConfig
3884
4006
  };
3885
4007
 
3886
- //# debugId=8ECD0F0A4A5E19F264756E2164756E21
4008
+ //# debugId=07EEA08E9106212A64756E2164756E21
@@ -90,6 +90,16 @@ export declare const resolveEnvFileLocationAsync: (envFilePath?: string, opts?:
90
90
  export declare const resolveEnvFilePathAsync: (envFilePath?: string, opts?: {
91
91
  cwd?: string;
92
92
  }) => Promise<ResolveEnvFilePathResult>;
93
+ /**
94
+ * Parse dotenv-style content into key/value pairs.
95
+ *
96
+ * Split out from {@link loadEnvFileAsync} so a caller that already holds the
97
+ * file's text can parse it the same way, without a second copy of these rules
98
+ * drifting on quoting or comments. Blank lines and `#` comments are skipped, as
99
+ * is any line with no `=`; a value wrapped in matching single or double quotes
100
+ * is unwrapped.
101
+ */
102
+ export declare const parseEnvContent: (content: string) => Record<string, string>;
93
103
  /**
94
104
  * Load environment variables from a credentials file
95
105
  * @param envPath - Path to the credentials file (relative to cwd or absolute)
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@uipath/auth",
3
+ "author": "UiPath",
3
4
  "license": "SEE LICENSE IN LICENSE.txt",
4
- "version": "1.202.0-preview.159",
5
+ "version": "1.203.0-preview.160",
5
6
  "repository": {
6
7
  "type": "git",
7
8
  "url": "https://github.com/UiPath/cli.git",
@@ -37,5 +38,5 @@
37
38
  "mihaigirleanu",
38
39
  "vlad-uipath"
39
40
  ],
40
- "gitHead": "a3f23209784c6cec7155e735fa051b48ca49e8d7"
41
+ "gitHead": "3a42062ba731afca4595ba9aa8a80afc9667528d"
41
42
  }