@uipath/cli 1.202.1 → 1.203.0-preview.180

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.
@@ -568,6 +568,63 @@ function getActiveAuthProfileFilePath() {
568
568
  const profile = getActiveAuthProfile();
569
569
  return profile ? resolveAuthProfileFilePath(profile) : undefined;
570
570
  }
571
+ function getAuthProfilesRootPath() {
572
+ const fs = getFileSystem();
573
+ return fs.path.join(fs.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR);
574
+ }
575
+ function resolveAuthProfileDirPath(profile) {
576
+ const normalized = normalizeAuthProfileName(profile);
577
+ if (normalized === undefined) {
578
+ throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile directory.`);
579
+ }
580
+ const fs = getFileSystem();
581
+ return fs.path.join(getAuthProfilesRootPath(), normalized);
582
+ }
583
+ async function listAuthProfileNamesAsync() {
584
+ const fs = getFileSystem();
585
+ const root = getAuthProfilesRootPath();
586
+ if (!await fs.exists(root)) {
587
+ return [];
588
+ }
589
+ const [readError, entries] = await catchError(fs.readdir(root));
590
+ if (readError || !entries) {
591
+ return [];
592
+ }
593
+ const names = [];
594
+ for (const entry of entries) {
595
+ if (!PROFILE_NAME_RE.test(entry) || entry === DEFAULT_AUTH_PROFILE) {
596
+ continue;
597
+ }
598
+ const stats = await fs.stat(fs.path.join(root, entry));
599
+ if (stats?.isDirectory()) {
600
+ names.push(entry);
601
+ }
602
+ }
603
+ return names.sort((a, b) => a.localeCompare(b));
604
+ }
605
+ async function authProfileExistsAsync(profile) {
606
+ const fs = getFileSystem();
607
+ const [pathError, dir] = catchError(() => resolveAuthProfileDirPath(profile));
608
+ if (pathError || dir === undefined) {
609
+ return false;
610
+ }
611
+ const stats = await fs.stat(dir);
612
+ return stats?.isDirectory() === true;
613
+ }
614
+ async function deleteAuthProfileAsync(profile) {
615
+ const dir = resolveAuthProfileDirPath(profile);
616
+ const fs = getFileSystem();
617
+ const relativeToRoot = fs.path.relative(getAuthProfilesRootPath(), dir);
618
+ if (relativeToRoot === "" || relativeToRoot.startsWith("..") || fs.path.isAbsolute(relativeToRoot)) {
619
+ throw new AuthProfileValidationError(`Refusing to delete "${profile}": resolved path escapes the profiles directory.`);
620
+ }
621
+ const stats = await fs.stat(dir);
622
+ if (stats?.isDirectory() !== true) {
623
+ return;
624
+ }
625
+ await fs.rm(dir);
626
+ return dir;
627
+ }
571
628
 
572
629
  // ../auth/src/utils/jwt.ts
573
630
  class InvalidIssuerError extends Error {
@@ -1136,16 +1193,7 @@ var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) =
1136
1193
  errorMessage: location.source === "absolute" ? `Environment file not found: ${envFilePath}` : `Unable to locate environment file: ${envFilePath}. Run 'uip login' to authenticate.`
1137
1194
  };
1138
1195
  };
1139
- var loadEnvFileAsync = async ({ envPath }) => {
1140
- const fs = getFileSystem();
1141
- const absolutePath = fs.path.isAbsolute(envPath) ? envPath : fs.path.join(fs.env.cwd(), envPath);
1142
- if (!await fs.exists(absolutePath)) {
1143
- throw new Error(`Environment file not found: ${envPath}`);
1144
- }
1145
- const content = await fs.readFile(absolutePath, "utf-8");
1146
- if (content === null) {
1147
- throw new Error(`Environment file not found: ${envPath}`);
1148
- }
1196
+ var parseEnvContent = (content) => {
1149
1197
  const env = {};
1150
1198
  for (const line of content.split(`
1151
1199
  `)) {
@@ -1166,6 +1214,18 @@ var loadEnvFileAsync = async ({ envPath }) => {
1166
1214
  }
1167
1215
  return env;
1168
1216
  };
1217
+ var loadEnvFileAsync = async ({ envPath }) => {
1218
+ const fs = getFileSystem();
1219
+ const absolutePath = fs.path.isAbsolute(envPath) ? envPath : fs.path.join(fs.env.cwd(), envPath);
1220
+ if (!await fs.exists(absolutePath)) {
1221
+ throw new Error(`Environment file not found: ${envPath}`);
1222
+ }
1223
+ const content = await fs.readFile(absolutePath, "utf-8");
1224
+ if (content === null) {
1225
+ throw new Error(`Environment file not found: ${envPath}`);
1226
+ }
1227
+ return parseEnvContent(content);
1228
+ };
1169
1229
  var saveEnvFileAsync = async ({
1170
1230
  envPath,
1171
1231
  data,
@@ -1740,6 +1800,61 @@ var getAuthEnv = async (options = {}) => {
1740
1800
  }
1741
1801
  return { authEnv, loginStatus: status };
1742
1802
  };
1803
+ // ../auth/src/authProfileDetails.ts
1804
+ var ORGANIZATION_NAME_KEY = "UIPATH_ORGANIZATION_NAME";
1805
+ var TENANT_NAME_KEY = "UIPATH_TENANT_NAME";
1806
+ var URL_KEY = "UIPATH_URL";
1807
+ var ACCESS_TOKEN_KEY = "UIPATH_ACCESS_TOKEN";
1808
+ function statusFromToken(accessToken) {
1809
+ if (!accessToken) {
1810
+ return { status: "Not logged in" };
1811
+ }
1812
+ const expiration = getTokenExpiration(accessToken);
1813
+ if (expiration === undefined) {
1814
+ return { status: "Logged in" };
1815
+ }
1816
+ return {
1817
+ status: expiration.getTime() <= Date.now() ? "Expired" : "Logged in",
1818
+ expiresAt: expiration.toISOString()
1819
+ };
1820
+ }
1821
+ async function describeAuthProfileAsync(name, filePath, active) {
1822
+ const base = {
1823
+ name,
1824
+ active,
1825
+ ...filePath ? { path: filePath } : {}
1826
+ };
1827
+ if (!filePath) {
1828
+ return { ...base, status: "Not logged in" };
1829
+ }
1830
+ const fs = getFileSystem();
1831
+ const [readError, content] = await catchError(fs.readFile(filePath, "utf-8"));
1832
+ if (readError) {
1833
+ return { ...base, status: "Unreadable" };
1834
+ }
1835
+ if (content === null || content === undefined) {
1836
+ return { ...base, status: "Not logged in" };
1837
+ }
1838
+ const values = parseEnvContent(content);
1839
+ return {
1840
+ ...base,
1841
+ ...values[ORGANIZATION_NAME_KEY] ? { organizationName: values[ORGANIZATION_NAME_KEY] } : {},
1842
+ ...values[TENANT_NAME_KEY] ? { tenantName: values[TENANT_NAME_KEY] } : {},
1843
+ ...values[URL_KEY] ? { url: values[URL_KEY] } : {},
1844
+ ...statusFromToken(values[ACCESS_TOKEN_KEY])
1845
+ };
1846
+ }
1847
+ async function describeAuthProfilesAsync() {
1848
+ const activeProfile = getActiveAuthProfile();
1849
+ const [defaultPathError, defaultLocation] = await catchError(resolveEnvFilePathAsync());
1850
+ const rows = [
1851
+ await describeAuthProfileAsync(DEFAULT_AUTH_PROFILE, defaultPathError ? undefined : defaultLocation?.absolutePath, activeProfile === undefined)
1852
+ ];
1853
+ for (const name of await listAuthProfileNamesAsync()) {
1854
+ rows.push(await describeAuthProfileAsync(name, resolveAuthProfileFilePath(name), activeProfile === name));
1855
+ }
1856
+ return rows;
1857
+ }
1743
1858
  // ../auth/src/tokenGrant.ts
1744
1859
  var requestClientCredentialsToken = async ({
1745
1860
  tokenEndpoint,
@@ -2322,6 +2437,6 @@ var authenticate = async ({
2322
2437
  });
2323
2438
  };
2324
2439
 
2325
- export { setAuthFileConfig, InvalidBaseUrlError, DEFAULT_AUTH_PROFILE, AuthProfileValidationError, normalizeAuthProfileName, setActiveAuthProfile, clearActiveAuthProfile, getActiveAuthProfile, runWithAuthProfile, resolveAuthProfileFilePath, getActiveAuthProfileFilePath, parseJWT, parseAuthFlow, resolveSessionIdentity, ENV_AUTH_ENABLE_VAR, ENFORCE_ROBOT_AUTH_VAR, ENV_AUTH_VARS, EnvAuthConfigError, isEnvAuthEnabled, isRobotAuthEnforced, readAuthFromEnv, refreshTokenFingerprint, loadRefreshBreaker, saveRefreshBreaker, clearRefreshBreaker, registerRobotClientLoader, TokenRefreshOAuthError, isTokenRefreshOAuthFailure, refreshAccessToken, AUTH_FLOW_ENV_VAR, DEFAULT_AUTH_FILENAME, DEFAULT_ENV_FILENAME, resolveEnvFileLocationAsync, resolveEnvFilePathAsync, loadEnvFileAsync, saveEnvFileAsync, CredentialSource, getLoginStatusAsync, getLoginStatusWithDeps, getAuthContext, getAuthEnv, ClientCredentialsAuthenticationError, clientCredentialsLogin, JWT_BEARER_ASSERTION_TYPE, FederatedCredentialsAuthenticationError, federatedCredentialsLogin, fetchTenantsAndOrganizations, TENANT_SELECTION_REQUIRED_CODE, INVALID_TENANT_CODE, TenantSelectionError, TenantSelectionRequiredError, InvalidTenantError, isTenantSelectionError, selectTenantWithDeps, interactiveLoginWithDeps, interactiveLogin, logoutWithDeps, logout, authenticate };
2440
+ export { setAuthFileConfig, InvalidBaseUrlError, DEFAULT_AUTH_PROFILE, AuthProfileValidationError, normalizeAuthProfileName, setActiveAuthProfile, clearActiveAuthProfile, getActiveAuthProfile, runWithAuthProfile, resolveAuthProfileFilePath, getActiveAuthProfileFilePath, getAuthProfilesRootPath, resolveAuthProfileDirPath, listAuthProfileNamesAsync, authProfileExistsAsync, deleteAuthProfileAsync, parseJWT, parseAuthFlow, resolveSessionIdentity, ENV_AUTH_ENABLE_VAR, ENFORCE_ROBOT_AUTH_VAR, ENV_AUTH_VARS, EnvAuthConfigError, isEnvAuthEnabled, isRobotAuthEnforced, readAuthFromEnv, refreshTokenFingerprint, loadRefreshBreaker, saveRefreshBreaker, clearRefreshBreaker, registerRobotClientLoader, TokenRefreshOAuthError, isTokenRefreshOAuthFailure, refreshAccessToken, AUTH_FLOW_ENV_VAR, DEFAULT_AUTH_FILENAME, DEFAULT_ENV_FILENAME, resolveEnvFileLocationAsync, resolveEnvFilePathAsync, loadEnvFileAsync, saveEnvFileAsync, CredentialSource, getLoginStatusAsync, getLoginStatusWithDeps, getAuthContext, getAuthEnv, describeAuthProfilesAsync, ClientCredentialsAuthenticationError, clientCredentialsLogin, JWT_BEARER_ASSERTION_TYPE, FederatedCredentialsAuthenticationError, federatedCredentialsLogin, fetchTenantsAndOrganizations, TENANT_SELECTION_REQUIRED_CODE, INVALID_TENANT_CODE, TenantSelectionError, TenantSelectionRequiredError, InvalidTenantError, isTenantSelectionError, selectTenantWithDeps, interactiveLoginWithDeps, interactiveLogin, logoutWithDeps, logout, authenticate };
2326
2441
 
2327
- //# debugId=C423B6A3517C965364756E2164756E21
2442
+ //# debugId=05DE97FE1B9FF5A064756E2164756E21
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runNode
4
- } from "./index-9d17sa6t.js";
4
+ } from "./index-szrenqr6.js";
5
5
  import {
6
6
  registerRobotClientLoader
7
- } from "./index-v5cj0bhj.js";
8
- import"./index-vmj27s6h.js";
7
+ } from "./index-vmn69waj.js";
8
+ import"./index-mtdmza3c.js";
9
9
  import {
10
10
  TELEMETRY_DRAIN_ARGV,
11
11
  configureLogger,
@@ -18,7 +18,7 @@ import {
18
18
  setProcessContextPollSignal,
19
19
  setProxyAuthHttpsAgent,
20
20
  setTelemetrySidecarEntry
21
- } from "./index-tqczrxct.js";
21
+ } from "./index-7pvwjzsq.js";
22
22
  import"./index-g8ck9tv6.js";
23
23
  import"./index-hrt7fpkk.js";
24
24
  import"./index-d3w0wn6k.js";
@@ -192,7 +192,7 @@ var isMain = __require.main == __require.module ?? process.argv[1] === currentFi
192
192
  if (isMain) {
193
193
  setTelemetrySidecarEntry(currentFile);
194
194
  if (process.argv[2] === TELEMETRY_DRAIN_ARGV) {
195
- const { drainPendingTelemetry } = await import("./telemetry-drain-wqmnr7t7.js");
195
+ const { drainPendingTelemetry } = await import("./telemetry-drain-zkrm8xja.js");
196
196
  await drainPendingTelemetry();
197
197
  process.exit(0);
198
198
  }
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  runWithAuthProfile
3
- } from "./index-v5cj0bhj.js";
3
+ } from "./index-vmn69waj.js";
4
4
  import {
5
+ OUTPUT_FORMATS,
5
6
  catchError,
6
7
  collectCommands,
7
8
  getOutputSink,
8
9
  logger,
9
10
  runWithSink,
10
11
  setGlobalSink
11
- } from "./index-tqczrxct.js";
12
+ } from "./index-7pvwjzsq.js";
12
13
  import"./index-g8ck9tv6.js";
13
14
  import {
14
15
  exports_external
@@ -83,7 +84,7 @@ async function executeCommand(command) {
83
84
  const previousSink = getOutputSink();
84
85
  setGlobalSink(sink);
85
86
  const [error] = await catchError(async () => {
86
- const { run } = await import("./cli-p61a1vc8.js");
87
+ const { run } = await import("./cli-w7vb50ez.js");
87
88
  await runWithAuthProfile(undefined, () => runWithSink(sink, () => run(context)));
88
89
  });
89
90
  if (error) {
@@ -131,7 +132,7 @@ function introspectCommands(program) {
131
132
  }
132
133
  }
133
134
  lines.push(`
134
- Global Options (can be used with any command):`, " --output <table|json|yaml|plain>: Output format (default: json)", " --output-filter <expression>: JMESPath expression applied to the Data field of the response envelope", " --log-level <debug|info|warn|error>: Log level threshold (default: info)", " --log-file <path>: Write logs to file instead of stderr", " --profile <name>: Use a named login profile (~/.uipath/profiles/<name>/.auth)", `
135
+ Global Options (can be used with any command):`, ` --output <${OUTPUT_FORMATS.join("|")}>: Output format (default: json)`, " --output-filter <expression>: JMESPath expression applied to the Data field of the response envelope", " --log-level <debug|info|warn|error>: Log level threshold (default: info)", " --log-file <path>: Write logs to file instead of stderr", " --profile <name>: Use a named login profile (~/.uipath/profiles/<name>/.auth)", `
135
136
  Pass the command without the 'uip' prefix. Example: "login status --output json"`, `Filter example: "tools list --output-filter 'Data[].name'"`);
136
137
  return lines.join(`
137
138
  `);
@@ -191,4 +192,4 @@ export {
191
192
  startMcpServer
192
193
  };
193
194
 
194
- //# debugId=E369162B8A5BD33764756E2164756E21
195
+ //# debugId=95A6EF0EC5E5518C64756E2164756E21
@@ -7,7 +7,7 @@ import {
7
7
  logger,
8
8
  releaseClaimedSpoolFile,
9
9
  sweepTelemetrySpool
10
- } from "./index-tqczrxct.js";
10
+ } from "./index-7pvwjzsq.js";
11
11
  import"./index-xdxr3ync.js";
12
12
  import"./index-1yh8g550.js";
13
13
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  runUpdate
3
- } from "./index-vmj27s6h.js";
4
- import"./index-tqczrxct.js";
3
+ } from "./index-mtdmza3c.js";
4
+ import"./index-7pvwjzsq.js";
5
5
  import"./index-g8ck9tv6.js";
6
6
  import"./index-hrt7fpkk.js";
7
7
  import"./index-d3w0wn6k.js";
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@uipath/cli",
3
+ "author": "UiPath",
3
4
  "license": "SEE LICENSE IN LICENSE.txt",
4
- "version": "1.202.1",
5
+ "version": "1.203.0-preview.180",
5
6
  "description": "Cross platform CLI for UiPath",
6
7
  "repository": {
7
8
  "type": "git",
@@ -12,20 +13,15 @@
12
13
  "registry": "https://registry.npmjs.org/"
13
14
  },
14
15
  "type": "module",
16
+ "engines": {
17
+ "node": ">=22"
18
+ },
15
19
  "main": "./dist/index.js",
16
20
  "exports": {
17
- ".": {
18
- "browser": "./dist/index.browser.js",
19
- "default": "./dist/index.js"
20
- },
21
- "./browser": "./dist/index.browser.js",
22
- "./services/markdown-to-jira-wiki": "./dist/services.markdown.browser.js",
23
- "./services/feedback/browser": "./dist/services.feedback.browser.js"
21
+ ".": "./dist/index.js"
24
22
  },
25
23
  "files": [
26
- "dist",
27
- "!dist/uip-browser.js",
28
- "!dist/metafile.json"
24
+ "dist"
29
25
  ],
30
26
  "bin": {
31
27
  "uip": "./dist/index.js"
@@ -40,5 +36,5 @@
40
36
  "kerberos": "7.0.0",
41
37
  "node-expose-sspi": "0.1.60"
42
38
  },
43
- "gitHead": "9792d74b5ec29276123d2b3daabcae49748c1fa6"
39
+ "gitHead": "4e0a51e3ab2c9d89afd3d35a7b087a7fa58133a0"
44
40
  }
package/README.browser.md DELETED
@@ -1,128 +0,0 @@
1
- # UiPath CLI — Browser Bundle
2
-
3
- A browser-runnable bundle of the UiPath CLI. Exposes a `UiPathCLI` global that host applications can load to run CLI commands without a Node.js backend.
4
-
5
- ## What's in the bundle
6
-
7
- - **3 tools** (browser-compatible): `orchestrator-tool` (`or`), `integrationservice-tool` (`is`), `test-manager-tool` (`tm`)
8
- - **Core framework**: Commander program, `--output-filter`, output formatting, telemetry, error handling
9
-
10
- Each tool opts in by shipping a `browser.json` next to its `package.json` with `{ "compatible": true }`. At build time, `discover-browser-tools` scans `packages/*-tool/` and emits a virtual module importing each opted-in tool.
11
-
12
- Authentication is **not** included in this bundle — commands will return "Not logged in" until the browser-auth PR lands (#701).
13
-
14
- ## Bundle
15
-
16
- - **Build command**: `bun run browser:build` (from `packages/cli/`)
17
- - **Output**: `packages/cli/dist/uip-browser.js`, plus `dist/metafile.json` for build-time assertions
18
- - **Size**: ~3.3 MB unminified; ~1.4 MB / ~250 KB gzipped when `minify: true` is re-enabled in `build-browser.ts`
19
- - **Format**: IIFE, exposes `UiPathCLI` global
20
-
21
- ## Loading the bundle
22
-
23
- ```html
24
- <script src="/path/to/uip-browser.js"></script>
25
- <script>
26
- (async () => {
27
- // Wait for filesystem (LightningFS over IndexedDB) to initialize
28
- await UiPathCLI.ready;
29
-
30
- // Run a CLI command
31
- await UiPathCLI.run(['node', 'uip', '--help']);
32
- })();
33
- </script>
34
- ```
35
-
36
- ## API
37
-
38
- ### `UiPathCLI.run(args, options?)`
39
-
40
- Parses and executes a CLI invocation.
41
-
42
- ```ts
43
- UiPathCLI.run(
44
- args: string[], // e.g. ['node', 'uip', 'or', 'folders', 'list']
45
- options?: {
46
- enabledTools?: string[]; // allowlist by command prefix: ['or', 'is']
47
- }
48
- ): Promise<void>
49
- ```
50
-
51
- **`enabledTools`** — allowlist of tool command prefixes that register with Commander. Omit to register all discovered browser-compatible tools.
52
-
53
- ### `UiPathCLI.ready`
54
-
55
- A `Promise<void>` that resolves when the virtual filesystem (LightningFS over IndexedDB) has initialized. Await before the first `run()` call.
56
-
57
- ## Browser-compatible tools
58
-
59
- | Command | Tool | What it does |
60
- |---------|------|--------------|
61
- | `uip or <subcommand>` | orchestrator-tool | Jobs, processes, packages, folders, machines, licenses, users, permissions |
62
- | `uip is <subcommand>` | integrationservice-tool | Connectors, connections, triggers |
63
- | `uip tm <subcommand>` | test-manager-tool | Test cases, sets, executions, results |
64
-
65
- Use `uip or --help` (etc.) for the full subcommand tree.
66
-
67
- ## Reusing services without the CLI program
68
-
69
- `@uipath/cli/browser` exports the CLI **runner** — the whole Commander program.
70
- A host that only needs one of the CLI's services can import it directly:
71
-
72
- ```ts
73
- // Dependency-free, ~3KB, no side effects.
74
- const { markdownToJiraWiki } = await import(
75
- "@uipath/cli/services/markdown-to-jira-wiki"
76
- );
77
-
78
- // ~178KB. Browser-only — @uipath/filesystem creates an IndexedDB store on
79
- // import, so this crashes under Node. Hence the `/browser` suffix, matching
80
- // `@uipath/cli/browser`.
81
- const { createFeedbackIssue, uploadAttachment } = await import(
82
- "@uipath/cli/services/feedback/browser"
83
- );
84
- ```
85
-
86
- These exist so embedding hosts stop duplicating service logic. Autopilot's Studio
87
- Web MFE serves `uip feedback send` through a host interceptor — the command is
88
- Node-only, registered in `cli.node.ts` — and had ported the markdown converter
89
- and the issue-creation calls verbatim. Two copies of the tracker's
90
- project/component/field ids is a drift hazard.
91
-
92
- The two entries are split deliberately: the markdown converter is
93
- dependency-free, so a host that only formats descriptions should not pay for a
94
- filesystem it never touches.
95
-
96
- **These bundles are browser-safe because of the build, not the dependency graph.**
97
- `@uipath/common` resolves to its Node source and reaches `node:async_hooks`;
98
- `build-browser.ts`'s alias map rewrites that to a throwing shim and routes
99
- `@uipath/filesystem` to its browser entry. Importing the TypeScript sources
100
- directly is not browser-safe.
101
-
102
- Node-only services are deliberately absent: `send-feedback.ts`
103
- (`@inquirer/prompts`, stdin) and `environmentInfo.ts` (`node:os`).
104
- `services.browser.spec.ts` guards the surface and the exclusions.
105
-
106
- No type declarations ship with this package, so declare the surface structurally
107
- at the call site — the same way Autopilot already declares `run`/`ready`.
108
-
109
- ## Limitations
110
-
111
- - **No authentication.** Wiring for credential injection ships in a follow-up (#701). Until then, any command that calls the UiPath Cloud API returns `Not logged in`.
112
- - **No interactive prompts.** Commands that use `@inquirer/prompts` (e.g. `send-feedback`, `tools install --interactive`) are Node-only and not registered in the browser bundle.
113
- - **No file-based auth.** `uip login` / `uip logout` are Node-only and excluded from the browser entry.
114
- - **No subprocess spawning.** `child_process` is not available.
115
- - **Filesystem is virtual.** All file I/O routes through `@uipath/filesystem`'s `BrowserFileSystem`, backed by LightningFS + IndexedDB. Host-app code that reads/writes files should use `getFileSystem()` / `getFileSystemAsync()` from `@uipath/filesystem`.
116
- - **Direct `node:fs` / `node:path` imports fail at build time** for any non-commander caller — Rule 10 is enforced by the bundler.
117
-
118
- ## CORS
119
-
120
- Once auth lands in #701, the bundle will make `fetch()` requests directly to the UiPath Cloud API. The host page's origin must be allow-listed by the target environment, or the host can proxy API calls through its own server to avoid cross-origin preflight.
121
-
122
- ## Troubleshooting
123
-
124
- **`"Result": "Failure", "Instructions": "Not logged in..."`** — expected for now; auth wiring ships in #701.
125
-
126
- **`UiPathCLI is not defined`** — bundle hasn't loaded or loaded at a different scope. Confirm the `<script>` tag fires before your init code, or listen for its `load` event.
127
-
128
- **IndexedDB errors** — the bundle uses LightningFS for its virtual filesystem. Not available in headless environments without IndexedDB polyfills (e.g. `happy-dom` without `fake-indexeddb`).