@uipath/solution-sdk 1.202.0-preview.137 → 1.202.0-preview.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8544,7 +8544,7 @@ class TextApiResponse {
8544
8544
  var package_default = {
8545
8545
  name: "@uipath/solution-sdk",
8546
8546
  license: "MIT",
8547
- version: "1.202.0-preview.137",
8547
+ version: "1.202.0-preview.139",
8548
8548
  repository: {
8549
8549
  type: "git",
8550
8550
  url: "https://github.com/UiPath/cli.git",
@@ -17363,9 +17363,11 @@ async function listStudioWebSolutions(config, organizationName, options = {}) {
17363
17363
  // src/upload-service.ts
17364
17364
  class HttpError extends Error {
17365
17365
  status;
17366
- constructor(status, message) {
17366
+ authChallenge;
17367
+ constructor(status, message, authChallenge) {
17367
17368
  super(message);
17368
17369
  this.status = status;
17370
+ this.authChallenge = authChallenge;
17369
17371
  }
17370
17372
  }
17371
17373
 
@@ -17379,6 +17381,7 @@ class SolutionUploadHttpError extends Error {
17379
17381
  solutionId;
17380
17382
  parsedErrorCode;
17381
17383
  parsedErrorMessage;
17384
+ authChallenge;
17382
17385
  constructor(details) {
17383
17386
  super(details.message);
17384
17387
  this.name = "SolutionUploadHttpError";
@@ -17391,6 +17394,7 @@ class SolutionUploadHttpError extends Error {
17391
17394
  if (details.operation === "overwrite") {
17392
17395
  this.solutionId = details.solutionId;
17393
17396
  }
17397
+ this.authChallenge = details.authChallenge;
17394
17398
  const parsed = parseUploadErrorBody(details.body);
17395
17399
  this.parsedErrorCode = parsed.code;
17396
17400
  this.parsedErrorMessage = parsed.message;
@@ -17414,16 +17418,71 @@ function requestPath(url) {
17414
17418
  const [, parsed] = catchError(() => new URL(url));
17415
17419
  return parsed ? `${parsed.pathname}${parsed.search}` : url;
17416
17420
  }
17421
+ var TOKEN_SHAPED = /\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]*)?|\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/gi;
17422
+ function redactTokens(text) {
17423
+ return text.replace(TOKEN_SHAPED, "[REDACTED]");
17424
+ }
17425
+ var MAX_CHALLENGE_DESCRIPTION = 200;
17426
+ function parseAuthChallenge(header) {
17427
+ if (!header)
17428
+ return {};
17429
+ const code = /\berror="([^"]*)"/.exec(header)?.[1]?.trim();
17430
+ const raw = /\berror_description="([^"]*)"/.exec(header)?.[1]?.trim();
17431
+ const description = raw ? redactTokens(raw).slice(0, MAX_CHALLENGE_DESCRIPTION) : undefined;
17432
+ return {
17433
+ error: code || undefined,
17434
+ description: description || undefined
17435
+ };
17436
+ }
17437
+ function summarizeAuthRefusalBody(body) {
17438
+ return summarizePlatformBody(redactTokens(body));
17439
+ }
17440
+ function isAuthRefusal(status) {
17441
+ return status === 401 || status === 403;
17442
+ }
17443
+ function buildAuthRefusalInstructions({
17444
+ err: err2,
17445
+ subject,
17446
+ target,
17447
+ bodySuffix,
17448
+ identityType,
17449
+ clientId
17450
+ }) {
17451
+ const refusal = err2.status === 401 ? "rejected the call as unauthorized (401)" : "forbade the call (403)";
17452
+ const what = err2.operation === "overwrite" ? `replacing the contents of solution ${target}` : "importing the solution package";
17453
+ const actor = identityType === "Application" ? `This session acts as external application ${clientId ?? "(client id unknown)"}, so ` + `check what that application is allowed to do: it needs the Studio ` + `Web scopes that cover writing a solution (the StudioWebS2S grants ` + `on the external application), not just the Orchestrator or ` + `Solutions ones. ` : identityType === "User" ? `This session acts as a user, so check that your account has ` + `Studio Web access in this tenant. ` : `Check what this session is allowed to do in Studio Web — an ` + `external application needs the StudioWebS2S grants that cover ` + `writing a solution, a user needs Studio Web access in the tenant. `;
17454
+ const tenant = err2.operation === "overwrite" ? `Also confirm that ${target} is the solution this project should ` + `publish to, and that it lives in the organization and tenant ` + `this session logged into — the id comes from the SolutionId ` + `recorded in the enclosing solution file. An id this session ` + `cannot see at all is reported separately, as nothing to ` + `overwrite, so a refusal here points at the grants first. ` : `Also confirm you are logged into the organization and tenant the ` + `solution should land in. `;
17455
+ const challenge = parseAuthChallenge(err2.authChallenge);
17456
+ const quoted = challenge.description ? ` ("${challenge.description}")` : "";
17457
+ if (challenge.error === "invalid_token") {
17458
+ return `Studio Web ${refusal} while ${what}, and rejected the credential ` + `itself with the reason \`invalid_token\`${quoted}. That is the ` + `platform refusing this token rather than the permissions behind ` + `it, so unlike a grants refusal this one is worth a fresh ` + `\`uip login\` — or, in a pipeline, a newly minted ` + `client-credentials token. Check too that the token was issued for ` + `the organization being called: one minted against a different ` + `environment or audience is refused this way. Nothing was uploaded ` + `and nothing ran, so the ${subject} is not the cause.${bodySuffix}`;
17459
+ }
17460
+ const authenticated = `The session is authenticated — the token was issued and had not ` + `expired when the call went out — so re-running \`uip login\` mints ` + `the same token and fails the same way. `;
17461
+ const diagnosis = challenge.error === "insufficient_scope" ? `Studio Web reported \`insufficient_scope\`${quoted}, so the ` + `token is valid and simply not allowed to do this: logging in ` + `again will not change it. ` : challenge.error ? `${authenticated}Studio Web gave the reason ` + `\`${challenge.error}\`${quoted}. ` : authenticated;
17462
+ const closing = bodySuffix ? `If the grants and the tenant are already right, report the platform ` + `response, including its traceId.${bodySuffix}` : challenge.error ? `If the grants and the tenant are already right, report that reason ` + `together with the request path and status above.` : `If the grants and the tenant are already right, report the request ` + `path and status above — Studio Web returned no response body and ` + `no authentication challenge, so there is nothing further to quote.`;
17463
+ return `Studio Web ${refusal} while ${what}. ${diagnosis}${actor}${tenant}` + `Nothing was uploaded and nothing ran, so the ${subject} is not the ` + `cause. ${closing}`;
17464
+ }
17417
17465
  function buildSolutionUploadFailureOutput(err2, options = {}) {
17418
17466
  const stage = err2.operation === "overwrite" ? "overwrite-solution" : "import-solution";
17419
- const detail = err2.parsedErrorMessage ? ` — ${err2.parsedErrorMessage}` : "";
17467
+ const authRefusal = isAuthRefusal(err2.status);
17468
+ const parsedMessage = authRefusal && err2.parsedErrorMessage ? redactTokens(err2.parsedErrorMessage) : err2.parsedErrorMessage;
17469
+ const detail = parsedMessage ? ` — ${parsedMessage}` : "";
17420
17470
  const Message = `Failed during ${stage}: HTTP ${err2.status} on ${err2.method} ` + `${err2.endpoint}${detail}`;
17421
- const body = err2.parsedErrorMessage ? "" : summarizePlatformBody(err2.body);
17471
+ const quote = authRefusal ? summarizeAuthRefusalBody : summarizePlatformBody;
17472
+ const body = err2.parsedErrorMessage ? "" : quote(err2.body);
17422
17473
  const bodySuffix = body ? ` Platform response: "${body}".` : "";
17423
17474
  const importHint = options.importCheckHint ? ` ${options.importCheckHint}` : "";
17424
17475
  const subject = options.subject ?? "project";
17425
17476
  const target = err2.solutionId ?? `the solution at ${err2.endpoint}`;
17426
- const Instructions = err2.operation === "overwrite" ? `Studio Web refused to replace the contents of solution ` + `${target}. Nothing was uploaded and nothing ran, so the ` + `${subject} is not the cause: do not re-author it, and do not ` + `copy the project into another solution. Confirm that ${target} ` + `is a solution you can still write to, and that it is the one ` + `this project should publish to — it comes from the SolutionId ` + `recorded in the enclosing solution file. If it is right, report ` + `the platform response.${bodySuffix}` : `Studio Web refused to import the solution package. Nothing was ` + `uploaded and nothing ran, so no part of the ${subject} executed ` + `— but the package itself may be what was rejected.${importHint} ` + `Report the platform response if the ${subject} is ` + `well-formed.${bodySuffix}`;
17477
+ const authInstructions = isAuthRefusal(err2.status) ? buildAuthRefusalInstructions({
17478
+ err: err2,
17479
+ subject,
17480
+ target,
17481
+ bodySuffix,
17482
+ identityType: options.identityType,
17483
+ clientId: options.clientId
17484
+ }) : undefined;
17485
+ const Instructions = authInstructions ?? (err2.operation === "overwrite" ? `Studio Web refused to replace the contents of solution ` + `${target}. Nothing was uploaded and nothing ran, so the ` + `${subject} is not the cause: do not re-author it, and do not ` + `copy the project into another solution. Confirm that ${target} ` + `is a solution you can still write to, and that it is the one ` + `this project should publish to — it comes from the SolutionId ` + `recorded in the enclosing solution file. If it is right, report ` + `the platform response.${bodySuffix}` : `Studio Web refused to import the solution package. Nothing was ` + `uploaded and nothing ran, so no part of the ${subject} executed ` + `— but the package itself may be what was rejected.${importHint} ` + `Report the platform response if the ${subject} is ` + `well-formed.${bodySuffix}`);
17427
17486
  const Context = {
17428
17487
  httpStatus: err2.status,
17429
17488
  stage,
@@ -17439,6 +17498,9 @@ function buildSolutionUploadFailureOutput(err2, options = {}) {
17439
17498
  Instructions,
17440
17499
  Context
17441
17500
  };
17501
+ if (err2.status === 401 && options.identityType === "Application") {
17502
+ output.ErrorCode = "permission_denied";
17503
+ }
17442
17504
  if (err2.operation === "overwrite" && err2.status >= 500 && err2.status < 600) {
17443
17505
  output.Retry = "RetryAfter30Seconds";
17444
17506
  }
@@ -17489,8 +17551,10 @@ async function solutionExistsOnStudioWeb(config, organizationName, solutionId) {
17489
17551
  if (error.response.status === 404) {
17490
17552
  return false;
17491
17553
  }
17554
+ const status = error.response.status;
17492
17555
  const text = await error.response.text().catch(() => "");
17493
- throw new HttpError(error.response.status, `Studio Web solution existence probe failed (${error.response.status}): ${text}`);
17556
+ const body = isAuthRefusal(status) ? summarizeAuthRefusalBody(text) : text;
17557
+ throw new HttpError(status, `Studio Web solution existence probe failed (${status}): ${body}`, parseAuthChallenge(error.response.headers?.get("www-authenticate") ?? undefined));
17494
17558
  }
17495
17559
  throw error;
17496
17560
  }
@@ -17519,6 +17583,7 @@ async function importSolution(config, organizationName, fileBuffer, fileName) {
17519
17583
  endpoint: requestPath(importUrl),
17520
17584
  url: importUrl,
17521
17585
  body: text,
17586
+ authChallenge: response.headers?.get("www-authenticate") ?? undefined,
17522
17587
  message: `Import failed (${response.status}): ${text}`
17523
17588
  });
17524
17589
  }
@@ -17550,6 +17615,7 @@ async function overwriteSolution(config, organizationName, fileBuffer, fileName,
17550
17615
  endpoint: requestPath(overwriteUrl),
17551
17616
  url: overwriteUrl,
17552
17617
  body: text,
17618
+ authChallenge: response.headers?.get("www-authenticate") ?? undefined,
17553
17619
  message: `Overwrite failed (${response.status}): ${text}`,
17554
17620
  solutionId
17555
17621
  });
@@ -17901,4 +17967,4 @@ export {
17901
17967
  uploadOrOverwriteSolution
17902
17968
  };
17903
17969
 
17904
- //# debugId=0922D7C9641F03E864756E2164756E21
17970
+ //# debugId=C66D5C6F8D87285E64756E2164756E21
@@ -16788,8 +16788,7 @@ class ToolsFactoryRepository {
16788
16788
  getProjectToolFactory(projectType) {
16789
16789
  const factory = this.projectFactoryMap.get(projectType);
16790
16790
  if (!factory) {
16791
- const known = [...this.projectFactoryMap.keys()].join(", ");
16792
- throw new Error(`Cannot pack project type '${projectType}': no packager is installed for it. ` + `Project types that can be packed: ${known || "none"}.`);
16791
+ throw new Error(`Cannot pack project type '${projectType}': no packager is installed for it.`);
16793
16792
  }
16794
16793
  return factory;
16795
16794
  }
@@ -30516,6 +30515,59 @@ class FileSystemFileStorageProviderFactory {
30516
30515
  }
30517
30516
  }
30518
30517
 
30518
+ // src/resources/providers/resource-builder-logger.ts
30519
+ var PLACEHOLDER = /\{(\w+)\}|%[sdifoOj]/g;
30520
+ function render(value) {
30521
+ if (typeof value === "string")
30522
+ return value;
30523
+ if (value === null || value === undefined)
30524
+ return String(value);
30525
+ if (typeof value !== "object")
30526
+ return String(value);
30527
+ try {
30528
+ return JSON.stringify(value) ?? String(value);
30529
+ } catch {
30530
+ return String(value);
30531
+ }
30532
+ }
30533
+ function interpolate(message, args) {
30534
+ const fields = args[0] !== null && typeof args[0] === "object" && !Array.isArray(args[0]) ? args[0] : undefined;
30535
+ const consumed = new Set;
30536
+ let positional = 0;
30537
+ const filled = message.replace(PLACEHOLDER, (match, name) => {
30538
+ if (name !== undefined) {
30539
+ if (fields && name in fields) {
30540
+ consumed.add(0);
30541
+ return render(fields[name]);
30542
+ }
30543
+ return match;
30544
+ }
30545
+ const index = positional;
30546
+ positional += 1;
30547
+ if (index >= args.length)
30548
+ return match;
30549
+ consumed.add(index);
30550
+ return render(args[index]);
30551
+ });
30552
+ const extra = args.filter((_, index) => !consumed.has(index)).map(render).filter((text) => text.length > 0);
30553
+ return extra.length > 0 ? `${filled} ${extra.join(" ")}` : filled;
30554
+ }
30555
+
30556
+ class CliResourceBuilderLoggerFactory {
30557
+ create(target) {
30558
+ const name = typeof target === "string" ? target : target.name;
30559
+ const line = (message, args) => `[${name}] ${interpolate(message, args)}`;
30560
+ return {
30561
+ trace: (message, ...args) => logger.debug(line(message, args)),
30562
+ debug: (message, ...args) => logger.debug(line(message, args)),
30563
+ info: (message, ...args) => logger.info(line(message, args)),
30564
+ warn: (message, ...args) => logger.warn(line(message, args)),
30565
+ error: (message, error, ...args) => logger.error(error ? `${line(message, args)}: ${error.message}` : line(message, args)),
30566
+ fatal: (message, ...args) => logger.error(line(message, args))
30567
+ };
30568
+ }
30569
+ }
30570
+
30519
30571
  // ../orchestrator-sdk/generated/src/runtime.ts
30520
30572
  var BASE_PATH = "https://alpha.uipath.com/uipattycyrhx/abizon_1/orchestrator_".replace(/\/+$/, "");
30521
30573
 
@@ -32389,7 +32441,7 @@ class SolutionAccessProvider {
32389
32441
 
32390
32442
  // src/resources/providers/resource-builder-init.ts
32391
32443
  async function createResourceBuilderServices() {
32392
- return await createResourceBuilderConfiguration().addAccessProvider(new SolutionAccessProvider).addFileStorageProviderFactory(new FileSystemFileStorageProviderFactory).addArtifactResourceSpecEnhancer(new EntryPointSpecEnhancer).build();
32444
+ return await createResourceBuilderConfiguration().addAccessProvider(new SolutionAccessProvider).addFileStorageProviderFactory(new FileSystemFileStorageProviderFactory).addArtifactResourceSpecEnhancer(new EntryPointSpecEnhancer).addLoggerFactory(new CliResourceBuilderLoggerFactory).build();
32393
32445
  }
32394
32446
 
32395
32447
  // src/resources/commands/project-utils.ts
@@ -32433,6 +32485,26 @@ async function findProjectFile2(projectDir) {
32433
32485
  null
32434
32486
  ];
32435
32487
  }
32488
+
32489
+ class ProjectManifestError extends Error {
32490
+ __projectManifestError = true;
32491
+ reason;
32492
+ constructor(message, reason) {
32493
+ super(message);
32494
+ this.name = "ProjectManifestError";
32495
+ this.reason = reason;
32496
+ }
32497
+ }
32498
+ function isProjectManifestError(error) {
32499
+ return !!error && typeof error === "object" && error.__projectManifestError === true;
32500
+ }
32501
+ function isMissingProjectTypeError(error) {
32502
+ return isProjectManifestError(error) && error.reason === "no-project-type";
32503
+ }
32504
+ function lastPathSegment(filePath) {
32505
+ const parts = filePath.split(/[/\\]/);
32506
+ return parts[parts.length - 1] ?? filePath;
32507
+ }
32436
32508
  async function readProjectFile(filePath, useProjectJson) {
32437
32509
  const fs7 = getFileSystem();
32438
32510
  const [readError, rawContent] = await catchError2(fs7.readFile(filePath, "utf-8"));
@@ -32442,7 +32514,7 @@ async function readProjectFile(filePath, useProjectJson) {
32442
32514
  const [parseError, content] = catchError2(() => JSON.parse(rawContent));
32443
32515
  if (parseError) {
32444
32516
  return [
32445
- new Error(`Invalid JSON in project file: ${parseError.message}`),
32517
+ new ProjectManifestError(`Invalid JSON in project file: ${parseError.message}`, "invalid-json"),
32446
32518
  null
32447
32519
  ];
32448
32520
  }
@@ -32457,7 +32529,16 @@ async function readProjectFile(filePath, useProjectJson) {
32457
32529
  }
32458
32530
  ];
32459
32531
  }
32460
- return [new Error(`ProjectType not found in ${filePath}`), null];
32532
+ if (lastPathSegment(filePath) === "uipath.json") {
32533
+ return [
32534
+ new ProjectManifestError(`${filePath} has no 'ProjectType'. A uipath.json is only read as a code-first Functions project, which also needs a 'functions' entry. Other project types are registered from project.uiproj or project.json, not from uipath.json.`, "no-project-type"),
32535
+ null
32536
+ ];
32537
+ }
32538
+ return [
32539
+ new ProjectManifestError(`ProjectType not found in ${filePath}`, "no-project-type"),
32540
+ null
32541
+ ];
32461
32542
  }
32462
32543
  return [null, { content, projectType: normalizeProjectType(projectType) }];
32463
32544
  }
@@ -33280,6 +33361,7 @@ async function resourceRefreshAsync(solutionPath = ".", options = {}) {
33280
33361
  }
33281
33362
  export {
33282
33363
  EntryPointSpecEnhancer,
33364
+ ProjectManifestError,
33283
33365
  addProjectArtifactsToSolutionAsync,
33284
33366
  applyEntryPointEnhancementAsync,
33285
33367
  assertSolutionManifest,
@@ -33293,6 +33375,8 @@ export {
33293
33375
  findProjectFile2 as findProjectFile,
33294
33376
  findResourceByKeyInRcs,
33295
33377
  findResourceInRcs,
33378
+ isMissingProjectTypeError,
33379
+ isProjectManifestError,
33296
33380
  normalizeFolderPath,
33297
33381
  readProjectFile,
33298
33382
  readSolutionFile,
@@ -33308,4 +33392,4 @@ export {
33308
33392
  writeSolutionFile
33309
33393
  };
33310
33394
 
33311
- //# debugId=A122757AB33BF19D64756E2164756E21
33395
+ //# debugId=E988507D1077967864756E2164756E21
@@ -32,6 +32,35 @@ export interface ParsedSolutionFile {
32
32
  * project.uiproj, project.json, then uipath.json (code-first JS/TS Functions).
33
33
  */
34
34
  export declare function findProjectFile(projectDir: string): Promise<[Error, null] | [null, ProjectFileInfo]>;
35
+ /**
36
+ * Which way the manifest was unusable. `invalid-json` is a syntax error in the
37
+ * file; `no-project-type` is a file that parsed but declares no type. Callers
38
+ * that add guidance need the difference — advice about the wrong manifest
39
+ * makes no sense for a file that is merely mistyped.
40
+ */
41
+ export type ProjectManifestErrorReason = "invalid-json" | "no-project-type";
42
+ /**
43
+ * The manifest was read but is not usable: bad JSON, or no `ProjectType` to
44
+ * act on. Distinct from the raw `fs.readFile` failure `readProjectFile` also
45
+ * returns (EACCES on a file that exists, say) — that one is a local
46
+ * filesystem problem, not bad input, and callers must not classify the two
47
+ * the same way. `__projectManifestError` lets callers duck-type across bundle
48
+ * boundaries where `instanceof` fails.
49
+ */
50
+ export declare class ProjectManifestError extends Error {
51
+ readonly __projectManifestError = true;
52
+ readonly reason: ProjectManifestErrorReason;
53
+ constructor(message: string, reason: ProjectManifestErrorReason);
54
+ }
55
+ /** True when `error` is a {@link ProjectManifestError}, duck-typed. */
56
+ export declare function isProjectManifestError(error: unknown): boolean;
57
+ /**
58
+ * True when the manifest parsed but names no `ProjectType`. Callers gate
59
+ * "this may be the wrong manifest" guidance on this rather than on the file
60
+ * name alone: a `uipath.json` with a JSON typo is a different problem and
61
+ * must keep the parse error as its only advice.
62
+ */
63
+ export declare function isMissingProjectTypeError(error: unknown): boolean;
35
64
  /**
36
65
  * Reads and parses a project manifest, extracting the project type.
37
66
  */
@@ -8,5 +8,9 @@ import { type IResourceBuilderServices } from "@uipath/resource-builder-sdk";
8
8
  * `EntryPointSpecEnhancer` is registered so artefact resources (resources
9
9
  * with a `projectKey`) reflect the latest `entry-points.json` from disk at
10
10
  * read time, instead of the snapshot captured at `solution projects add`.
11
+ *
12
+ * `CliResourceBuilderLoggerFactory` replaces the SDK's default logger, which
13
+ * prints its message templates unfilled (`{solutionKey}`, `%s`) and bypasses
14
+ * `--log-level` / `--log-file` — see that file for why both matter.
11
15
  */
12
16
  export declare function createResourceBuilderServices(): Promise<IResourceBuilderServices>;
@@ -0,0 +1,25 @@
1
+ import type { ILogger, ILoggerFactory } from "@uipath/resource-builder-sdk";
2
+ /**
3
+ * Fill a message template from the arguments the SDK passed alongside it.
4
+ *
5
+ * `{name}` is looked up on the first argument when that is a plain object —
6
+ * the shape the SDK uses. `%s` and friends consume arguments in order. A
7
+ * placeholder with nothing to fill it is left as written rather than replaced
8
+ * with "undefined", so a template the SDK logs with no arguments at all still
9
+ * reads as a template.
10
+ *
11
+ * Arguments no placeholder consumed are appended, so nothing the SDK meant to
12
+ * report is dropped.
13
+ */
14
+ export declare function interpolate(message: string, args: unknown[]): string;
15
+ /**
16
+ * The CLI's `ILoggerFactory` for the resource engine.
17
+ *
18
+ * The SDK's own factory prefixes each line with a timestamp and its component
19
+ * name; `logger` already stamps its own lines, so only the component name is
20
+ * carried over — it is what tells a `solution resource refresh` line apart
21
+ * from a `solution upload` one in a `--log-file`.
22
+ */
23
+ export declare class CliResourceBuilderLoggerFactory implements ILoggerFactory {
24
+ create(target: (new (...args: never[]) => unknown) | string): ILogger;
25
+ }
@@ -17,6 +17,9 @@ type SolutionUploadFailureDetails = {
17
17
  /** Full request URL, for diagnostics. */
18
18
  url: string;
19
19
  body: string;
20
+ /** Raw `WWW-Authenticate` when the response carried one. Parsed, never
21
+ * echoed whole — see {@link parseAuthChallenge}. */
22
+ authChallenge?: string;
20
23
  message: string;
21
24
  } & ({
22
25
  operation: "import";
@@ -47,11 +50,44 @@ export declare class SolutionUploadHttpError extends Error {
47
50
  /** From a `{"code":…,"message":…}` body; undefined for any other shape. */
48
51
  readonly parsedErrorCode?: string;
49
52
  readonly parsedErrorMessage?: string;
53
+ /** Raw `WWW-Authenticate`, when the response had one. On a real 401 from
54
+ * Studio Web this is often the *only* diagnostic: the body is empty
55
+ * (`content-length: 0`) and the reason is in this header. */
56
+ readonly authChallenge?: string;
50
57
  constructor(details: SolutionUploadFailureDetails);
51
58
  }
52
59
  /** Matched by shape, not `instanceof`: tools bundle their own copy of this
53
60
  * package, so a cross-bundle `instanceof` is not reliable. */
54
61
  export declare function isSolutionUploadHttpError(error: unknown): error is SolutionUploadHttpError;
62
+ /** Replace anything token-shaped in `text`. Exported for the auth-refusal
63
+ * paths and their tests; not re-exported from the package barrel. */
64
+ export declare function redactTokens(text: string): string;
65
+ /**
66
+ * Pull the reason out of a `WWW-Authenticate` challenge.
67
+ *
68
+ * Measured against alpha: a real Studio Web 401 comes back with
69
+ * `content-length: 0` and puts the whole diagnostic in this header —
70
+ * `Bearer realm="…", error="invalid_token", error_description="The audience
71
+ * 'empty' is invalid"`. Without this the CLI has nothing to tell the user, and
72
+ * the envelope ends up asking them to report a platform response that does not
73
+ * exist.
74
+ *
75
+ * Only the two RFC 6750 fields are taken. `realm` is deliberately dropped: it
76
+ * is an internal endpoint URL, it says nothing about why the call failed, and
77
+ * echoing routing metadata into user-facing errors is the pattern the security
78
+ * checklist warns about. `error` is a small fixed vocabulary; `error_description`
79
+ * is free text, so it goes through {@link redactTokens} and a length cap in
80
+ * case Identity ever quotes the presented credential back.
81
+ */
82
+ export declare function parseAuthChallenge(header?: string): {
83
+ error?: string;
84
+ description?: string;
85
+ };
86
+ /** Quote a platform body for an auth refusal, minus anything token-shaped.
87
+ * Redaction runs before `summarizePlatformBody`'s length cap, so a token
88
+ * cannot survive by being truncated mid-string into something the pattern no
89
+ * longer matches. */
90
+ export declare function summarizeAuthRefusalBody(body: string): string;
55
91
  /**
56
92
  * Build the CLI failure envelope for a Studio Web upload refusal.
57
93
  *
@@ -66,11 +102,20 @@ export declare function isSolutionUploadHttpError(error: unknown): error is Solu
66
102
  * the caller has a command for checking it; an overwrite refusal is about the
67
103
  * target solution, not the package.
68
104
  *
69
- * `Context.httpStatus` is what gives the envelope its `ErrorCode`.
105
+ * `identityType` (with `clientId` when it is known) only changes the wording
106
+ * of a 401/403: who the session acts as decides whether "check your Studio Web
107
+ * access" or "check the external application's scopes" is the useful sentence.
108
+ * It is read from unverified token claims, so it must never be used for
109
+ * anything but text — see `SessionIdentity` in `@uipath/auth`.
110
+ *
111
+ * `Context.httpStatus` is what gives the envelope its `ErrorCode`, except on an
112
+ * application 401 — see {@link buildAuthRefusalInstructions}.
70
113
  */
71
114
  export declare function buildSolutionUploadFailureOutput(err: SolutionUploadHttpError, options?: {
72
115
  subject?: string;
73
116
  importCheckHint?: string;
117
+ identityType?: "User" | "Application";
118
+ clientId?: string;
74
119
  }): FailureOutput;
75
120
  /**
76
121
  * Escape hatch for very large solutions or unusually slow links:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/solution-sdk",
3
3
  "license": "MIT",
4
- "version": "1.202.0-preview.137",
4
+ "version": "1.202.0-preview.139",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/UiPath/cli.git",
@@ -39,5 +39,5 @@
39
39
  "dist"
40
40
  ],
41
41
  "private": false,
42
- "gitHead": "bbb20a6d3501afc3435a92af9ae2e9f7ab2e34f6"
42
+ "gitHead": "fd9f8b8a05749404743763d22187b1b012c44274"
43
43
  }