@uipath/solution-tool 1.202.0 → 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.
- package/dist/THIRD-PARTY-NOTICES.md +23 -1
- package/dist/deploy.js +7 -6
- package/dist/{packager-tool-bt0z25tw.js → embedded-file-reader-xxqe8vs8.js} +98 -16584
- package/dist/first-party-service-sd8yaf73.js +27 -0
- package/dist/index-dqa169gp.js +25 -0
- package/dist/index.js +19 -13
- package/dist/init.js +8 -5
- package/dist/{list-8hvfmge6.js → list-dadxggxt.js} +5 -4
- package/dist/models/pack-command-types.d.ts +33 -5
- package/dist/pack.js +12 -6
- package/dist/{packager-tool-fjjh5veg.js → packager-tool-0f0wt9vh.js} +353 -1519
- package/dist/{packager-tool-pbmpgz04.js → packager-tool-1haahq17.js} +5 -3
- package/dist/{packager-tool-rbrcxjch.js → packager-tool-2syrt51a.js} +7 -4
- package/dist/packager-tool-3jrq7smt.js +1459 -0
- package/dist/packager-tool-53w8skv5.js +262 -0
- package/dist/packager-tool-7znqtw3f.js +244 -0
- package/dist/packager-tool-bkwnetqn.js +16678 -0
- package/dist/{packager-tool-5518wy6n.js → packager-tool-cp07fhx3.js} +9 -6
- package/dist/{packager-tool-w1dzcj31.js → packager-tool-cvfbzs9p.js} +359 -95
- package/dist/packager-tool-gdtpsdn7.js +342 -0
- package/dist/{packager-tool-pyygbnp2.js → packager-tool-htag6yh5.js} +4 -4
- package/dist/{packager-tool-3bewrpq4.js → packager-tool-jz2wbfjz.js} +4 -1
- package/dist/packager-tool-k4mskzww.js +125 -0
- package/dist/{packager-tool-vfcht7hq.js → packager-tool-mj5p341c.js} +11 -12
- package/dist/{packager-tool-bme8epz8.js → packager-tool-n4nfqj99.js} +15381 -2421
- package/dist/{packager-tool-mcpzmn0v.js → packager-tool-rc5pcf2n.js} +45 -21
- package/dist/packager-tool-resolver-fmjr60x8.js +19 -0
- package/dist/{packager-tool-pw7v82j2.js → packager-tool-vas0xg5h.js} +1 -1
- package/dist/packager-tool-znakt6yw.js +188 -0
- package/dist/packager-tool.d.ts +1 -1
- package/dist/packager-tool.js +1 -1
- package/dist/prepare-solution-resources-wds3r8bq.js +22 -0
- package/dist/project-contributions-cvttys34.js +27 -0
- package/dist/publish.js +7 -6
- package/dist/resource.js +7 -4
- package/dist/services/deployment-validation.d.ts +33 -0
- package/dist/services/governance-options.d.ts +61 -1
- package/dist/services/pack-command-service.d.ts +33 -2
- package/dist/services/packager-tool-resolver.d.ts +3 -0
- package/dist/services/prepare-solution-resources.d.ts +40 -0
- package/dist/services/project-contributions.d.ts +58 -0
- package/dist/services/project-type-tools.d.ts +6 -0
- package/dist/templates/AGENTS.md +78 -8
- package/dist/tool.js +19 -13
- package/package.json +3 -2
- package/dist/services/validate-appv2-action-schemas.d.ts +0 -10
|
@@ -2609,7 +2609,7 @@ var UUID_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{1
|
|
|
2609
2609
|
var EMAIL_PATTERN = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
2610
2610
|
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
2611
2611
|
var LONG_TOKEN_PATTERN = /\b[A-Za-z0-9_-]{40,}\b/g;
|
|
2612
|
-
var PADDED_BASE64_PATTERN = /[A-Za-z0-9+/]{16,}={1,2}(?![A-Za-z0-9+/=])/g;
|
|
2612
|
+
var PADDED_BASE64_PATTERN = /(?<![A-Za-z0-9+/])[A-Za-z0-9+/]{16,}={1,2}(?![A-Za-z0-9+/=])/g;
|
|
2613
2613
|
var BASE64_WITH_PLUS_PATTERN = /[A-Za-z0-9+/]{40,}/g;
|
|
2614
2614
|
var USER_HOME_PATTERN = /(?<![A-Za-z0-9._-])([/\\])(Users|home|Profiles)([/\\])([^/\\]+)/gi;
|
|
2615
2615
|
var UNC_PATH_PATTERN = /(^|[\s"'<>|=,;([{])(\\\\[^\s"'<>|]+)/g;
|
|
@@ -2656,7 +2656,7 @@ var QUOTED_LITERAL_PATTERN = new RegExp([
|
|
|
2656
2656
|
`(?<![A-Za-z0-9])"(?:[^\\
|
|
2657
2657
|
]|\\.){2,${QUOTED_LITERAL_MAX_SPAN}}?"(?![A-Za-z0-9])`
|
|
2658
2658
|
].join("|"), "g");
|
|
2659
|
-
var JSON_BODY_PATTERN = /[{[][^{}[\]]*[:,][^{}[\]]*[\]}]/g;
|
|
2659
|
+
var JSON_BODY_PATTERN = /[{[][^{}[\]:,]*[:,][^{}[\]]*[\]}]/g;
|
|
2660
2660
|
var COLLAPSED_BODY = "{…}";
|
|
2661
2661
|
var COLLAPSED_BODY_MARKER = "\x01body\x01";
|
|
2662
2662
|
var MAX_BODY_NESTING = 8;
|
|
@@ -2671,10 +2671,13 @@ function collapseJsonBodies(text) {
|
|
|
2671
2671
|
}
|
|
2672
2672
|
return out.split(COLLAPSED_BODY_MARKER).join(COLLAPSED_BODY);
|
|
2673
2673
|
}
|
|
2674
|
-
var TRAILING_PROSE_PUNCT =
|
|
2674
|
+
var TRAILING_PROSE_PUNCT = `.,;:!?)]}>'"`;
|
|
2675
2675
|
function peelTrailingPunctuation(match) {
|
|
2676
|
-
|
|
2677
|
-
|
|
2676
|
+
let end = match.length;
|
|
2677
|
+
while (end > 0 && TRAILING_PROSE_PUNCT.includes(match[end - 1])) {
|
|
2678
|
+
end -= 1;
|
|
2679
|
+
}
|
|
2680
|
+
return [match.slice(0, end), match.slice(end)];
|
|
2678
2681
|
}
|
|
2679
2682
|
function redactUrl(raw) {
|
|
2680
2683
|
try {
|
|
@@ -2861,11 +2864,6 @@ function settlePromiseLike(thenable) {
|
|
|
2861
2864
|
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [toError(error), undefined]);
|
|
2862
2865
|
}
|
|
2863
2866
|
|
|
2864
|
-
// ../common/src/exit-code.ts
|
|
2865
|
-
function setExitCode(code) {
|
|
2866
|
-
process.exitCode = code;
|
|
2867
|
-
}
|
|
2868
|
-
|
|
2869
2867
|
// ../common/src/output-context.ts
|
|
2870
2868
|
function createStorage() {
|
|
2871
2869
|
const [error, mod] = catchError(() => __require("node:async_hooks"));
|
|
@@ -3083,6 +3081,11 @@ function getLogFilePath() {
|
|
|
3083
3081
|
return logger.getLogFilePath();
|
|
3084
3082
|
}
|
|
3085
3083
|
|
|
3084
|
+
// ../common/src/exit-code.ts
|
|
3085
|
+
function setExitCode(code) {
|
|
3086
|
+
process.exitCode = code;
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3086
3089
|
// ../common/src/output-codecs.ts
|
|
3087
3090
|
var yamlSlot = singleton("YamlCodec");
|
|
3088
3091
|
var jmespathSlot = singleton("JmespathCodec");
|
|
@@ -3351,7 +3354,8 @@ function readRegistryValue(keyPath, valueName) {
|
|
|
3351
3354
|
}
|
|
3352
3355
|
const [error, output] = catchError(() => execFileSync("reg", ["query", keyPath, "/v", valueName], {
|
|
3353
3356
|
encoding: "utf-8",
|
|
3354
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
3357
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
3358
|
+
windowsHide: true
|
|
3355
3359
|
}));
|
|
3356
3360
|
if (error) {
|
|
3357
3361
|
return "";
|
|
@@ -4002,6 +4006,12 @@ function isCliErrorCode(value) {
|
|
|
4002
4006
|
function isRetryHint(value) {
|
|
4003
4007
|
return typeof value === "string" && RETRY_HINT_VALUES.has(value);
|
|
4004
4008
|
}
|
|
4009
|
+
function carriedErrorCode(error) {
|
|
4010
|
+
if (!error || typeof error !== "object")
|
|
4011
|
+
return;
|
|
4012
|
+
const code = error.errorCode;
|
|
4013
|
+
return isCliErrorCode(code) ? code : undefined;
|
|
4014
|
+
}
|
|
4005
4015
|
var RESULTS = {
|
|
4006
4016
|
Success: "Success",
|
|
4007
4017
|
Failure: "Failure",
|
|
@@ -4066,28 +4076,32 @@ function isPlainRecord(value) {
|
|
|
4066
4076
|
const prototype = Object.getPrototypeOf(value);
|
|
4067
4077
|
return prototype === Object.prototype || prototype === null;
|
|
4068
4078
|
}
|
|
4069
|
-
function
|
|
4079
|
+
function splitPagedEnvelope(value) {
|
|
4070
4080
|
if (Array.isArray(value) || !isPlainRecord(value))
|
|
4071
4081
|
return null;
|
|
4072
|
-
const entries = Object.
|
|
4082
|
+
const entries = Object.entries(value);
|
|
4073
4083
|
if (entries.length === 0)
|
|
4074
4084
|
return null;
|
|
4075
|
-
let
|
|
4076
|
-
|
|
4077
|
-
for (const entry of entries) {
|
|
4085
|
+
let found = null;
|
|
4086
|
+
const meta = Object.create(null);
|
|
4087
|
+
for (const [key, entry] of entries) {
|
|
4078
4088
|
if (Array.isArray(entry)) {
|
|
4079
|
-
if (
|
|
4089
|
+
if (found !== null)
|
|
4080
4090
|
return null;
|
|
4081
|
-
|
|
4091
|
+
found = { key, rows: entry };
|
|
4082
4092
|
} else if (entry !== null && typeof entry === "object") {
|
|
4083
4093
|
return null;
|
|
4084
4094
|
} else {
|
|
4085
|
-
|
|
4095
|
+
meta[key] = entry;
|
|
4086
4096
|
}
|
|
4087
4097
|
}
|
|
4088
|
-
if (
|
|
4098
|
+
if (found === null || Object.keys(meta).length === 0)
|
|
4089
4099
|
return null;
|
|
4090
|
-
return
|
|
4100
|
+
return { ...found, meta };
|
|
4101
|
+
}
|
|
4102
|
+
function extractPagedRows(value) {
|
|
4103
|
+
const paged = splitPagedEnvelope(value);
|
|
4104
|
+
return paged === null ? null : paged.rows;
|
|
4091
4105
|
}
|
|
4092
4106
|
function toLowerCamelCaseKey(key) {
|
|
4093
4107
|
if (!key)
|
|
@@ -4191,6 +4205,9 @@ function printOutput(data, format = "json", logFn, asciiSafe = false, tableRowSt
|
|
|
4191
4205
|
}
|
|
4192
4206
|
break;
|
|
4193
4207
|
}
|
|
4208
|
+
case "markdown":
|
|
4209
|
+
logFn(renderMarkdown(data));
|
|
4210
|
+
break;
|
|
4194
4211
|
default: {
|
|
4195
4212
|
const hasData = "Data" in data && data.Data != null;
|
|
4196
4213
|
const pagedRows = hasData ? extractPagedRows(data.Data) : null;
|
|
@@ -4215,6 +4232,10 @@ function logOutput(data, format = "json", tableRowStyle) {
|
|
|
4215
4232
|
printOutput(data, format, (msg) => sink.writeOut(`${msg}
|
|
4216
4233
|
`), needsAsciiSafeJson(sink), styleFn);
|
|
4217
4234
|
}
|
|
4235
|
+
var PLUMBING_KEYS = new Set(["code", "log"]);
|
|
4236
|
+
function isPlumbingKey(key) {
|
|
4237
|
+
return PLUMBING_KEYS.has(key.toLowerCase());
|
|
4238
|
+
}
|
|
4218
4239
|
function cellToString(val) {
|
|
4219
4240
|
return val != null && typeof val === "object" ? JSON.stringify(val) : String(val ?? "");
|
|
4220
4241
|
}
|
|
@@ -4230,7 +4251,7 @@ function wrapText(text, width) {
|
|
|
4230
4251
|
function printTable(data, logFn, externalLogValue, tableRowStyle) {
|
|
4231
4252
|
if (data.length === 0)
|
|
4232
4253
|
return;
|
|
4233
|
-
const keys = Object.keys(data[0]).filter((key) => !
|
|
4254
|
+
const keys = Object.keys(data[0]).filter((key) => !isPlumbingKey(key));
|
|
4234
4255
|
const maxWidths = keys.map((key) => Math.max(key.length, ...data.map((item) => cellToString(item[key]).length)));
|
|
4235
4256
|
const header = keys.map((key, i) => key.padEnd(maxWidths[i])).join(" | ");
|
|
4236
4257
|
logFn(header);
|
|
@@ -4252,7 +4273,7 @@ function isNonEmptyPlainObject(value) {
|
|
|
4252
4273
|
}
|
|
4253
4274
|
var NESTED_INDENT = " ";
|
|
4254
4275
|
function printVerticalTable(data, logFn = console.log, externalLogValue) {
|
|
4255
|
-
const keys = Object.keys(data).filter((key) => !
|
|
4276
|
+
const keys = Object.keys(data).filter((key) => !isPlumbingKey(key));
|
|
4256
4277
|
if (keys.length === 0)
|
|
4257
4278
|
return;
|
|
4258
4279
|
const isBlockValue = (value) => isPlainObjectArray(value) || isNonEmptyPlainObject(value);
|
|
@@ -4283,7 +4304,7 @@ function printVerticalTable(data, logFn = console.log, externalLogValue) {
|
|
|
4283
4304
|
function printResizableTable(data, logFn = console.log, externalLogValue, availableWidth, tableRowStyle) {
|
|
4284
4305
|
if (data.length === 0)
|
|
4285
4306
|
return;
|
|
4286
|
-
const keys = Object.keys(data[0]).filter((key) => !
|
|
4307
|
+
const keys = Object.keys(data[0]).filter((key) => !isPlumbingKey(key));
|
|
4287
4308
|
if (keys.length === 0)
|
|
4288
4309
|
return;
|
|
4289
4310
|
if (!process.stdout.isTTY) {
|
|
@@ -4357,6 +4378,220 @@ function printResizableTable(data, logFn = console.log, externalLogValue, availa
|
|
|
4357
4378
|
logFn(`Log: ${externalLogValue}`);
|
|
4358
4379
|
}
|
|
4359
4380
|
}
|
|
4381
|
+
var MARKDOWN_MAX_CELL = 200;
|
|
4382
|
+
var MARKDOWN_MAX_DEPTH = 3;
|
|
4383
|
+
function markdownHeading(depth) {
|
|
4384
|
+
return "#".repeat(Math.min(3 + depth, 6));
|
|
4385
|
+
}
|
|
4386
|
+
var BACKTICK_RUN = /`+/g;
|
|
4387
|
+
function fencedBlock(text) {
|
|
4388
|
+
const first = text.trimStart()[0];
|
|
4389
|
+
const language = first === "<" ? "xml" : first === "{" || first === "[" ? "json" : "";
|
|
4390
|
+
const longestRun = Math.max(0, ...Array.from(text.matchAll(BACKTICK_RUN), (match) => match[0].length));
|
|
4391
|
+
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
4392
|
+
return `${fence}${language}
|
|
4393
|
+
${text}
|
|
4394
|
+
${fence}`;
|
|
4395
|
+
}
|
|
4396
|
+
function collapseNewlineRuns(text) {
|
|
4397
|
+
return text.split(/(\s+)/).map((part, index) => index % 2 === 1 && part.includes(`
|
|
4398
|
+
`) ? " " : part).join("");
|
|
4399
|
+
}
|
|
4400
|
+
function markdownCell(value) {
|
|
4401
|
+
const text = value instanceof Date ? value.toISOString() : cellToString(value);
|
|
4402
|
+
return collapseNewlineRuns(text).replace(/\|/g, "\\|");
|
|
4403
|
+
}
|
|
4404
|
+
function markdownLabel(key) {
|
|
4405
|
+
return collapseNewlineRuns(key).replace(/[\\`*|]/g, "\\$&");
|
|
4406
|
+
}
|
|
4407
|
+
function withoutPlumbing(record) {
|
|
4408
|
+
const kept = Object.create(null);
|
|
4409
|
+
for (const [key, value] of Object.entries(record)) {
|
|
4410
|
+
if (!isPlumbingKey(key))
|
|
4411
|
+
kept[key] = value;
|
|
4412
|
+
}
|
|
4413
|
+
return kept;
|
|
4414
|
+
}
|
|
4415
|
+
function rowsWithoutPlumbing(rows) {
|
|
4416
|
+
return rows.map((row) => isPlainRecord(row) ? withoutPlumbing(row) : row);
|
|
4417
|
+
}
|
|
4418
|
+
function markdownTable(rows) {
|
|
4419
|
+
const columns = [];
|
|
4420
|
+
const seen = new Set;
|
|
4421
|
+
for (const row of rows) {
|
|
4422
|
+
for (const key of Object.keys(row)) {
|
|
4423
|
+
if (!seen.has(key)) {
|
|
4424
|
+
seen.add(key);
|
|
4425
|
+
columns.push(key);
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
if (columns.length === 0)
|
|
4430
|
+
return null;
|
|
4431
|
+
const cells = rows.map((row) => columns.map((key) => markdownCell(row[key])));
|
|
4432
|
+
if (cells.some((row) => row.some((c) => c.length > MARKDOWN_MAX_CELL))) {
|
|
4433
|
+
return null;
|
|
4434
|
+
}
|
|
4435
|
+
return [
|
|
4436
|
+
`| ${columns.map(markdownLabel).join(" | ")} |`,
|
|
4437
|
+
`| ${columns.map(() => "---").join(" | ")} |`,
|
|
4438
|
+
...cells.map((row) => `| ${row.join(" | ")} |`)
|
|
4439
|
+
].join(`
|
|
4440
|
+
`);
|
|
4441
|
+
}
|
|
4442
|
+
function extractMessageSequence(rows) {
|
|
4443
|
+
const messages = [];
|
|
4444
|
+
for (const row of rows) {
|
|
4445
|
+
const message = extractSingleMessage(row);
|
|
4446
|
+
if (message === null)
|
|
4447
|
+
return null;
|
|
4448
|
+
messages.push(message);
|
|
4449
|
+
}
|
|
4450
|
+
return messages.join(`
|
|
4451
|
+
|
|
4452
|
+
`);
|
|
4453
|
+
}
|
|
4454
|
+
function markdownRows(rows, depth) {
|
|
4455
|
+
if (rows.length === 0)
|
|
4456
|
+
return "(none)";
|
|
4457
|
+
if (!isPlainObjectArray(rows)) {
|
|
4458
|
+
return rows.map((item) => `- ${markdownCell(item)}`).join(`
|
|
4459
|
+
`);
|
|
4460
|
+
}
|
|
4461
|
+
const prose = extractMessageSequence(rows);
|
|
4462
|
+
if (prose !== null)
|
|
4463
|
+
return prose;
|
|
4464
|
+
const table = markdownTable(rows);
|
|
4465
|
+
if (table !== null)
|
|
4466
|
+
return table;
|
|
4467
|
+
if (depth >= MARKDOWN_MAX_DEPTH) {
|
|
4468
|
+
return fencedBlock(JSON.stringify(rows, null, 2));
|
|
4469
|
+
}
|
|
4470
|
+
return rows.map((row, index) => [
|
|
4471
|
+
`${markdownHeading(depth)} ${index + 1}`,
|
|
4472
|
+
markdownObject(row, depth + 1)
|
|
4473
|
+
].join(`
|
|
4474
|
+
|
|
4475
|
+
`)).join(`
|
|
4476
|
+
|
|
4477
|
+
`);
|
|
4478
|
+
}
|
|
4479
|
+
function markdownObject(obj, depth) {
|
|
4480
|
+
const scalars = [];
|
|
4481
|
+
const blocks = [];
|
|
4482
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
4483
|
+
if (value === undefined)
|
|
4484
|
+
continue;
|
|
4485
|
+
const label = markdownLabel(key);
|
|
4486
|
+
if (Array.isArray(value)) {
|
|
4487
|
+
blocks.push(`${markdownHeading(depth)} ${label}
|
|
4488
|
+
|
|
4489
|
+
${markdownRows(value, depth + 1)}`);
|
|
4490
|
+
} else if (isNonEmptyPlainObject(value)) {
|
|
4491
|
+
const nested = depth < MARKDOWN_MAX_DEPTH ? markdownObject(value, depth + 1) : fencedBlock(JSON.stringify(value, null, 2));
|
|
4492
|
+
if (nested !== "") {
|
|
4493
|
+
blocks.push(`${markdownHeading(depth)} ${label}
|
|
4494
|
+
|
|
4495
|
+
${nested}`);
|
|
4496
|
+
}
|
|
4497
|
+
} else if (typeof value === "string" && value.includes(`
|
|
4498
|
+
`)) {
|
|
4499
|
+
blocks.push(`**${label}:**
|
|
4500
|
+
|
|
4501
|
+
${fencedBlock(value)}`);
|
|
4502
|
+
} else {
|
|
4503
|
+
scalars.push(`**${label}:** ${markdownCell(value)}`);
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
const sections = scalars.length > 0 ? [scalars.join(`
|
|
4507
|
+
`)] : [];
|
|
4508
|
+
sections.push(...blocks);
|
|
4509
|
+
return sections.join(`
|
|
4510
|
+
|
|
4511
|
+
`);
|
|
4512
|
+
}
|
|
4513
|
+
function extractSingleMessage(payload) {
|
|
4514
|
+
if (!isPlainRecord(payload))
|
|
4515
|
+
return null;
|
|
4516
|
+
const keys = Object.keys(payload);
|
|
4517
|
+
if (keys.length !== 1 || keys[0].toLowerCase() !== "message")
|
|
4518
|
+
return null;
|
|
4519
|
+
const value = payload[keys[0]];
|
|
4520
|
+
return typeof value === "string" ? value : null;
|
|
4521
|
+
}
|
|
4522
|
+
function markdownPayload(payload) {
|
|
4523
|
+
const message = extractSingleMessage(payload);
|
|
4524
|
+
if (message !== null)
|
|
4525
|
+
return message;
|
|
4526
|
+
if (Array.isArray(payload)) {
|
|
4527
|
+
return markdownRows(rowsWithoutPlumbing(payload), 0);
|
|
4528
|
+
}
|
|
4529
|
+
const visible = withoutPlumbing(payload);
|
|
4530
|
+
const paged = splitPagedEnvelope(visible);
|
|
4531
|
+
if (paged !== null) {
|
|
4532
|
+
const meta = markdownObject(paged.meta, 0);
|
|
4533
|
+
const rows = `${markdownHeading(0)} ${markdownLabel(paged.key)}
|
|
4534
|
+
|
|
4535
|
+
${markdownRows(rowsWithoutPlumbing(paged.rows), 1)}`;
|
|
4536
|
+
return meta === "" ? rows : `${meta}
|
|
4537
|
+
|
|
4538
|
+
${rows}`;
|
|
4539
|
+
}
|
|
4540
|
+
return markdownObject(visible, 0);
|
|
4541
|
+
}
|
|
4542
|
+
function isPaginationWorthShowing(value) {
|
|
4543
|
+
if (typeof value !== "object" || value === null)
|
|
4544
|
+
return false;
|
|
4545
|
+
const page = value;
|
|
4546
|
+
return page.HasMore === true || typeof page.Offset === "number" && page.Offset > 0;
|
|
4547
|
+
}
|
|
4548
|
+
function markdownEnvelopeNotes(data) {
|
|
4549
|
+
const envelope = data;
|
|
4550
|
+
const notes = [];
|
|
4551
|
+
const warning = envelope.Warning;
|
|
4552
|
+
if (typeof warning === "string" && warning !== "") {
|
|
4553
|
+
notes.push(`> **Warning:** ${warning}`);
|
|
4554
|
+
}
|
|
4555
|
+
const instructions = envelope.Instructions;
|
|
4556
|
+
if (typeof instructions === "string" && instructions !== "") {
|
|
4557
|
+
notes.push(`> ${instructions}`);
|
|
4558
|
+
}
|
|
4559
|
+
const pagination = envelope.Pagination;
|
|
4560
|
+
if (isPaginationWorthShowing(pagination)) {
|
|
4561
|
+
const body = markdownObject(pagination, 1);
|
|
4562
|
+
if (body !== "") {
|
|
4563
|
+
notes.push(`${markdownHeading(0)} Pagination
|
|
4564
|
+
|
|
4565
|
+
${body}`);
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
const log = envelope.Log;
|
|
4569
|
+
if (typeof log === "string" && log !== "") {
|
|
4570
|
+
notes.push(`**Log:** ${log}`);
|
|
4571
|
+
}
|
|
4572
|
+
return notes;
|
|
4573
|
+
}
|
|
4574
|
+
function renderMarkdown(data) {
|
|
4575
|
+
if (data.Result !== RESULTS.Success) {
|
|
4576
|
+
const failure = data;
|
|
4577
|
+
const sections = [`**Failed:** ${failure.Message}`];
|
|
4578
|
+
if (failure.Data != null) {
|
|
4579
|
+
sections.push(markdownPayload(failure.Data));
|
|
4580
|
+
}
|
|
4581
|
+
if (failure.Instructions) {
|
|
4582
|
+
sections.push(`> ${failure.Instructions}`);
|
|
4583
|
+
}
|
|
4584
|
+
return sections.filter((section) => section !== "").join(`
|
|
4585
|
+
|
|
4586
|
+
`);
|
|
4587
|
+
}
|
|
4588
|
+
if (!("Data" in data) || data.Data == null) {
|
|
4589
|
+
return markdownObject(withoutPlumbing(data), 0);
|
|
4590
|
+
}
|
|
4591
|
+
return [markdownPayload(data.Data), ...markdownEnvelopeNotes(data)].filter((section) => section !== "").join(`
|
|
4592
|
+
|
|
4593
|
+
`);
|
|
4594
|
+
}
|
|
4360
4595
|
function toYaml(data) {
|
|
4361
4596
|
const codec = getYamlCodec();
|
|
4362
4597
|
if (!codec) {
|
|
@@ -5052,6 +5287,55 @@ function parseBoundedInt(raw, optionName, bounds) {
|
|
|
5052
5287
|
return n;
|
|
5053
5288
|
}
|
|
5054
5289
|
|
|
5290
|
+
// ../common/src/solution-project-types.ts
|
|
5291
|
+
var LIBRARY_NOT_A_PROJECT = "A library cannot be a project inside a solution — it is a reusable .nupkg that other projects consume as a NuGet dependency, not a deployable unit. Build and publish it on its own ('uip rpa pack <project-dir> <output-path>', then 'uip or libraries upload --file <nupkg-path>'), and reference it from a project's dependencies. To make the published library part of this solution, add it as a resource instead: 'uip solution resources add --source remote --kind Library --name <library-name>'.";
|
|
5292
|
+
function unsupportedSolutionProjectType(projectType) {
|
|
5293
|
+
if (typeof projectType !== "string") {
|
|
5294
|
+
return null;
|
|
5295
|
+
}
|
|
5296
|
+
return projectType.toLowerCase() === "library" ? LIBRARY_NOT_A_PROJECT : null;
|
|
5297
|
+
}
|
|
5298
|
+
|
|
5299
|
+
// ../common/src/packager-tool-import.ts
|
|
5300
|
+
var REGISTER_EXPORT = "registerPackagerFactories";
|
|
5301
|
+
async function importPackagerTool(specifier) {
|
|
5302
|
+
const [importError, mod] = await catchError(import(specifier));
|
|
5303
|
+
if (importError)
|
|
5304
|
+
return importError;
|
|
5305
|
+
const register = mod?.[REGISTER_EXPORT];
|
|
5306
|
+
if (typeof register !== "function") {
|
|
5307
|
+
logger.debug(`'${specifier}' has no '${REGISTER_EXPORT}' export — treating it as a ` + "legacy entry point that registered its factories at import.");
|
|
5308
|
+
return;
|
|
5309
|
+
}
|
|
5310
|
+
const [registerError] = catchError(() => {
|
|
5311
|
+
register();
|
|
5312
|
+
});
|
|
5313
|
+
return registerError;
|
|
5314
|
+
}
|
|
5315
|
+
|
|
5316
|
+
// ../common/src/tool-provider.ts
|
|
5317
|
+
var factorySlot = singleton("PackagerFactoryProvider");
|
|
5318
|
+
async function ensurePackagerFactory(verb, packageName) {
|
|
5319
|
+
const provider = factorySlot.get();
|
|
5320
|
+
if (provider) {
|
|
5321
|
+
await provider(verb);
|
|
5322
|
+
return;
|
|
5323
|
+
}
|
|
5324
|
+
const importError = packageName ? await loadPackagerTool(`${packageName}/packager-tool`) : undefined;
|
|
5325
|
+
if (packageName && !importError)
|
|
5326
|
+
return;
|
|
5327
|
+
throw new Error(packageName ? `Packing this project type needs '${packageName}'. Install it.` : `Packing this project type needs the packager factory for '${verb}', and no package provides it.`, { cause: importError });
|
|
5328
|
+
}
|
|
5329
|
+
async function loadPackagerTool(specifier) {
|
|
5330
|
+
const error = await importPackagerTool(specifier);
|
|
5331
|
+
if (error) {
|
|
5332
|
+
logger.debug(`No packager factory provider registered; import of '${specifier}' failed: ${error.message}`);
|
|
5333
|
+
return error;
|
|
5334
|
+
}
|
|
5335
|
+
logger.debug(`No packager factory provider registered; loaded '${specifier}' directly.`);
|
|
5336
|
+
return;
|
|
5337
|
+
}
|
|
5338
|
+
|
|
5055
5339
|
// ../common/src/error-handler.ts
|
|
5056
5340
|
var DEFAULT_401 = "Unauthorized (401). Run `uip login` to authenticate.";
|
|
5057
5341
|
var DEFAULT_403 = "Forbidden (403). Ensure the account has the required permissions.";
|
|
@@ -5174,6 +5458,22 @@ function parseHttpStatusFromMessage2(message) {
|
|
|
5174
5458
|
const status = Number(match[1]);
|
|
5175
5459
|
return Number.isInteger(status) && status >= 100 && status <= 599 ? status : undefined;
|
|
5176
5460
|
}
|
|
5461
|
+
function findHttpStatusInGraph(error) {
|
|
5462
|
+
for (const node of walkErrorGraph(error)) {
|
|
5463
|
+
const response = node.response;
|
|
5464
|
+
const explicit = typeof node.status === "number" ? node.status : response?.status;
|
|
5465
|
+
if (typeof explicit === "number" && explicit >= 400 && explicit <= 599) {
|
|
5466
|
+
return explicit;
|
|
5467
|
+
}
|
|
5468
|
+
if (typeof node.message === "string") {
|
|
5469
|
+
const parsed = parseHttpStatusFromMessage2(node.message);
|
|
5470
|
+
if (parsed !== undefined && parsed >= 400) {
|
|
5471
|
+
return parsed;
|
|
5472
|
+
}
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5475
|
+
return;
|
|
5476
|
+
}
|
|
5177
5477
|
function isHtmlDocument(body) {
|
|
5178
5478
|
return /^\s*(<!doctype html|<html\b)/i.test(body);
|
|
5179
5479
|
}
|
|
@@ -5287,7 +5587,8 @@ async function extractErrorDetails(error, options) {
|
|
|
5287
5587
|
}
|
|
5288
5588
|
let message;
|
|
5289
5589
|
let result = "Failure";
|
|
5290
|
-
const
|
|
5590
|
+
const classificationStatus = status ?? findHttpStatusInGraph(error);
|
|
5591
|
+
const classification = classifyError2(classificationStatus, error);
|
|
5291
5592
|
let retry = classification.retry;
|
|
5292
5593
|
if (status === 401) {
|
|
5293
5594
|
message = DEFAULT_401;
|
|
@@ -5363,8 +5664,8 @@ async function extractErrorDetails(error, options) {
|
|
|
5363
5664
|
details = describeThrownValue(error);
|
|
5364
5665
|
}
|
|
5365
5666
|
const context = {};
|
|
5366
|
-
if (
|
|
5367
|
-
context.httpStatus =
|
|
5667
|
+
if (classificationStatus) {
|
|
5668
|
+
context.httpStatus = classificationStatus;
|
|
5368
5669
|
}
|
|
5369
5670
|
if (parsedBody?.errorCode && typeof parsedBody.errorCode === "string") {
|
|
5370
5671
|
context.errorCode = parsedBody.errorCode;
|
|
@@ -5706,6 +6007,29 @@ var BOOLEAN_FLAGS = new Set(HOST_GLOBAL_FLAGS);
|
|
|
5706
6007
|
var modeSlot = singleton("InteractivityMode");
|
|
5707
6008
|
var interactiveFlagSlot = singleton("InteractiveFlag");
|
|
5708
6009
|
// ../common/src/option-aliases.ts
|
|
6010
|
+
function resolveDeprecatedOptionAlias({
|
|
6011
|
+
preferredValue,
|
|
6012
|
+
deprecatedValue,
|
|
6013
|
+
preferredFlag,
|
|
6014
|
+
deprecatedFlag
|
|
6015
|
+
}) {
|
|
6016
|
+
const hasPreferred = preferredValue !== undefined;
|
|
6017
|
+
const hasDeprecated = deprecatedValue !== undefined;
|
|
6018
|
+
if (hasPreferred && hasDeprecated) {
|
|
6019
|
+
return {
|
|
6020
|
+
value: undefined,
|
|
6021
|
+
usedDeprecated: true,
|
|
6022
|
+
error: {
|
|
6023
|
+
message: `${deprecatedFlag} and ${preferredFlag} are aliases. Use only ${preferredFlag}.`,
|
|
6024
|
+
instructions: `Replace ${deprecatedFlag} with ${preferredFlag}.`
|
|
6025
|
+
}
|
|
6026
|
+
};
|
|
6027
|
+
}
|
|
6028
|
+
return {
|
|
6029
|
+
value: hasPreferred ? preferredValue : deprecatedValue,
|
|
6030
|
+
usedDeprecated: hasDeprecated
|
|
6031
|
+
};
|
|
6032
|
+
}
|
|
5709
6033
|
function warnDeprecatedOptionAlias(deprecatedFlag, preferredFlag) {
|
|
5710
6034
|
getOutputSink().writeErr(`[WARN] ${deprecatedFlag} is deprecated. Use ${preferredFlag} instead.
|
|
5711
6035
|
`);
|
|
@@ -5749,22 +6073,6 @@ function mapPackageMetadataOptions(opts) {
|
|
|
5749
6073
|
}
|
|
5750
6074
|
return fields;
|
|
5751
6075
|
}
|
|
5752
|
-
// ../common/src/packager-tool-import.ts
|
|
5753
|
-
var REGISTER_EXPORT = "registerPackagerFactories";
|
|
5754
|
-
async function importPackagerTool(specifier) {
|
|
5755
|
-
const [importError, mod] = await catchError(import(specifier));
|
|
5756
|
-
if (importError)
|
|
5757
|
-
return importError;
|
|
5758
|
-
const register = mod?.[REGISTER_EXPORT];
|
|
5759
|
-
if (typeof register !== "function") {
|
|
5760
|
-
logger.debug(`'${specifier}' has no '${REGISTER_EXPORT}' export — treating it as a ` + "legacy entry point that registered its factories at import.");
|
|
5761
|
-
return;
|
|
5762
|
-
}
|
|
5763
|
-
const [registerError] = catchError(() => {
|
|
5764
|
-
register();
|
|
5765
|
-
});
|
|
5766
|
-
return registerError;
|
|
5767
|
-
}
|
|
5768
6076
|
// ../common/src/polling/format-utils.ts
|
|
5769
6077
|
function msToDuration(ms) {
|
|
5770
6078
|
if (!Number.isFinite(ms) || ms < 0) {
|
|
@@ -6308,14 +6616,6 @@ function installRequestHeaderForwarding(BaseApiClass, patchKey, forward) {
|
|
|
6308
6616
|
function installSdkUserAgentHeader(BaseApiClass, userAgent) {
|
|
6309
6617
|
installRequestHeaderForwarding(BaseApiClass, userAgentPatchKey(userAgent), (headers) => addSdkUserAgentHeader(headers, userAgent));
|
|
6310
6618
|
}
|
|
6311
|
-
// ../common/src/solution-project-types.ts
|
|
6312
|
-
var LIBRARY_NOT_A_PROJECT = "A library cannot be a project inside a solution — it is a reusable .nupkg that other projects consume as a NuGet dependency, not a deployable unit. Build and publish it on its own ('uip rpa pack <project-dir> <output-path>', then 'uip or libraries upload --file <nupkg-path>'), and reference it from a project's dependencies. To make the published library part of this solution, add it as a resource instead: 'uip solution resources add --source remote --kind Library --name <library-name>'.";
|
|
6313
|
-
function unsupportedSolutionProjectType(projectType) {
|
|
6314
|
-
if (typeof projectType !== "string") {
|
|
6315
|
-
return null;
|
|
6316
|
-
}
|
|
6317
|
-
return projectType.toLowerCase() === "library" ? LIBRARY_NOT_A_PROJECT : null;
|
|
6318
|
-
}
|
|
6319
6619
|
// ../common/src/telemetry/ship-succeeded.ts
|
|
6320
6620
|
var shippedKeysSlot = singleton("ShipSucceededDedupeKeys");
|
|
6321
6621
|
function getShippedKeys() {
|
|
@@ -6357,1472 +6657,6 @@ function trackShipSucceeded(payload) {
|
|
|
6357
6657
|
telemetry.trackEvent(CommonTelemetryEvents.ShipSucceeded, redactProperties(withPseudonymizedIdentifiers(payload)));
|
|
6358
6658
|
return true;
|
|
6359
6659
|
}
|
|
6360
|
-
|
|
6361
|
-
var factorySlot = singleton("PackagerFactoryProvider");
|
|
6362
|
-
async function ensurePackagerFactory(verb, packageName) {
|
|
6363
|
-
const provider = factorySlot.get();
|
|
6364
|
-
if (provider) {
|
|
6365
|
-
await provider(verb);
|
|
6366
|
-
return;
|
|
6367
|
-
}
|
|
6368
|
-
const importError = packageName ? await loadPackagerTool(`${packageName}/packager-tool`) : undefined;
|
|
6369
|
-
if (packageName && !importError)
|
|
6370
|
-
return;
|
|
6371
|
-
throw new Error(packageName ? `Packing this project type needs '${packageName}'. Install it.` : `Packing this project type needs the packager factory for '${verb}', and no package provides it.`, { cause: importError });
|
|
6372
|
-
}
|
|
6373
|
-
async function loadPackagerTool(specifier) {
|
|
6374
|
-
const error = await importPackagerTool(specifier);
|
|
6375
|
-
if (error) {
|
|
6376
|
-
logger.debug(`No packager factory provider registered; import of '${specifier}' failed: ${error.message}`);
|
|
6377
|
-
return error;
|
|
6378
|
-
}
|
|
6379
|
-
logger.debug(`No packager factory provider registered; loaded '${specifier}' directly.`);
|
|
6380
|
-
return;
|
|
6381
|
-
}
|
|
6382
|
-
// ../auth/src/catch-error.ts
|
|
6383
|
-
function isPromiseLike2(value) {
|
|
6384
|
-
return value !== null && typeof value === "object" && typeof value.then === "function";
|
|
6385
|
-
}
|
|
6386
|
-
function catchError2(fnOrPromise) {
|
|
6387
|
-
if (isPromiseLike2(fnOrPromise)) {
|
|
6388
|
-
return settlePromiseLike2(fnOrPromise);
|
|
6389
|
-
}
|
|
6390
|
-
try {
|
|
6391
|
-
const result = fnOrPromise();
|
|
6392
|
-
if (isPromiseLike2(result)) {
|
|
6393
|
-
return settlePromiseLike2(result);
|
|
6394
|
-
}
|
|
6395
|
-
return [undefined, result];
|
|
6396
|
-
} catch (error) {
|
|
6397
|
-
return [
|
|
6398
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
6399
|
-
undefined
|
|
6400
|
-
];
|
|
6401
|
-
}
|
|
6402
|
-
}
|
|
6403
|
-
function settlePromiseLike2(thenable) {
|
|
6404
|
-
return Promise.resolve(thenable).then((data) => [undefined, data]).catch((error) => [
|
|
6405
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
6406
|
-
undefined
|
|
6407
|
-
]);
|
|
6408
|
-
}
|
|
6409
|
-
|
|
6410
|
-
// ../auth/src/constants.ts
|
|
6411
|
-
var UIPATH_HOME_DIR = ".uipath";
|
|
6412
|
-
var AUTH_FILENAME = ".auth";
|
|
6413
|
-
var DEFAULT_BASE_URL = "https://cloud.uipath.com";
|
|
6414
|
-
var DEFAULT_AUTH_TIMEOUT_MS2 = 5 * 60 * 1000;
|
|
6415
|
-
|
|
6416
|
-
// ../auth/src/authProfile.ts
|
|
6417
|
-
var DEFAULT_AUTH_PROFILE = "default";
|
|
6418
|
-
var PROFILE_DIR = "profiles";
|
|
6419
|
-
var PROFILE_NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
6420
|
-
var ACTIVE_AUTH_PROFILE_KEY = Symbol.for("@uipath/auth/ActiveAuthProfile");
|
|
6421
|
-
var AUTH_PROFILE_STORAGE_KEY = Symbol.for("@uipath/auth/ProfileStorage");
|
|
6422
|
-
var globalSlot = globalThis;
|
|
6423
|
-
function isAuthProfileStorage(value) {
|
|
6424
|
-
return value !== null && typeof value === "object" && "getStore" in value && "run" in value;
|
|
6425
|
-
}
|
|
6426
|
-
function createProfileStorage() {
|
|
6427
|
-
const [error, mod] = catchError2(() => __require("node:async_hooks"));
|
|
6428
|
-
if (error || typeof mod?.AsyncLocalStorage !== "function") {
|
|
6429
|
-
return {
|
|
6430
|
-
getStore: () => {
|
|
6431
|
-
return;
|
|
6432
|
-
},
|
|
6433
|
-
run: (_store, fn) => fn()
|
|
6434
|
-
};
|
|
6435
|
-
}
|
|
6436
|
-
return new mod.AsyncLocalStorage;
|
|
6437
|
-
}
|
|
6438
|
-
function getProfileStorage() {
|
|
6439
|
-
const existing = globalSlot[AUTH_PROFILE_STORAGE_KEY];
|
|
6440
|
-
if (isAuthProfileStorage(existing)) {
|
|
6441
|
-
return existing;
|
|
6442
|
-
}
|
|
6443
|
-
const storage2 = createProfileStorage();
|
|
6444
|
-
globalSlot[AUTH_PROFILE_STORAGE_KEY] = storage2;
|
|
6445
|
-
return storage2;
|
|
6446
|
-
}
|
|
6447
|
-
var profileStorage = getProfileStorage();
|
|
6448
|
-
|
|
6449
|
-
class AuthProfileValidationError extends Error {
|
|
6450
|
-
constructor(message) {
|
|
6451
|
-
super(message);
|
|
6452
|
-
this.name = "AuthProfileValidationError";
|
|
6453
|
-
}
|
|
6454
|
-
}
|
|
6455
|
-
function normalizeAuthProfileName(profile) {
|
|
6456
|
-
if (profile === undefined || profile === DEFAULT_AUTH_PROFILE) {
|
|
6457
|
-
return;
|
|
6458
|
-
}
|
|
6459
|
-
if (profile.length === 0 || profile === "." || profile === ".." || !PROFILE_NAME_RE.test(profile)) {
|
|
6460
|
-
throw new AuthProfileValidationError(`Invalid profile name "${profile}". Profile names may contain only letters, numbers, '.', '_', and '-'.`);
|
|
6461
|
-
}
|
|
6462
|
-
return profile;
|
|
6463
|
-
}
|
|
6464
|
-
function getActiveAuthProfile() {
|
|
6465
|
-
const scopedState = profileStorage.getStore();
|
|
6466
|
-
if (scopedState !== undefined) {
|
|
6467
|
-
return scopedState.profile;
|
|
6468
|
-
}
|
|
6469
|
-
return globalSlot[ACTIVE_AUTH_PROFILE_KEY]?.profile;
|
|
6470
|
-
}
|
|
6471
|
-
function resolveAuthProfileFilePath(profile) {
|
|
6472
|
-
const normalized = normalizeAuthProfileName(profile);
|
|
6473
|
-
if (normalized === undefined) {
|
|
6474
|
-
throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile file path.`);
|
|
6475
|
-
}
|
|
6476
|
-
const fs2 = getFileSystem();
|
|
6477
|
-
return fs2.path.join(fs2.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR, normalized, AUTH_FILENAME);
|
|
6478
|
-
}
|
|
6479
|
-
function getActiveAuthProfileFilePath() {
|
|
6480
|
-
const profile = getActiveAuthProfile();
|
|
6481
|
-
return profile ? resolveAuthProfileFilePath(profile) : undefined;
|
|
6482
|
-
}
|
|
6483
|
-
|
|
6484
|
-
// ../auth/src/config.ts
|
|
6485
|
-
var DEFAULT_CLIENT_ID = "36dea5b8-e8bb-423d-8e7b-c808df8f1c00";
|
|
6486
|
-
var AUTH_FILE_CONFIG_KEY = Symbol.for("@uipath/auth/AuthFileConfig");
|
|
6487
|
-
var globalSlot2 = globalThis;
|
|
6488
|
-
var getAuthFileConfig = () => globalSlot2[AUTH_FILE_CONFIG_KEY] ?? {};
|
|
6489
|
-
|
|
6490
|
-
class InvalidBaseUrlError extends Error {
|
|
6491
|
-
url;
|
|
6492
|
-
reason;
|
|
6493
|
-
constructor(url, reason) {
|
|
6494
|
-
super(`Invalid base URL: "${url}"
|
|
6495
|
-
` + `Reason: ${reason}
|
|
6496
|
-
|
|
6497
|
-
` + `Expected format: an https:// URL (or bare host — https:// is assumed), e.g. https://cloud.uipath.com (commercial), https://govcloud.uipath.us (Public Sector), or your Automation Suite host (https://<your-host>).
|
|
6498
|
-
` + `You can specify the URL via:
|
|
6499
|
-
` + ` • --authority flag
|
|
6500
|
-
` + ` • UIPATH_URL environment variable
|
|
6501
|
-
` + ` • auth.authority in config file`);
|
|
6502
|
-
this.url = url;
|
|
6503
|
-
this.reason = reason;
|
|
6504
|
-
this.name = "InvalidBaseUrlError";
|
|
6505
|
-
}
|
|
6506
|
-
}
|
|
6507
|
-
var DEFAULT_SCOPES = ["openid", "profile", "offline_access"];
|
|
6508
|
-
var normalizeAndValidateBaseUrl = (rawUrl) => {
|
|
6509
|
-
let baseUrl = rawUrl;
|
|
6510
|
-
if (baseUrl.endsWith("/identity_/")) {
|
|
6511
|
-
baseUrl = baseUrl.slice(0, -11);
|
|
6512
|
-
} else if (baseUrl.endsWith("/identity_")) {
|
|
6513
|
-
baseUrl = baseUrl.slice(0, -10);
|
|
6514
|
-
}
|
|
6515
|
-
while (baseUrl.endsWith("/")) {
|
|
6516
|
-
baseUrl = baseUrl.slice(0, -1);
|
|
6517
|
-
}
|
|
6518
|
-
const hasScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(baseUrl);
|
|
6519
|
-
const [hostCandidate] = baseUrl.split(/[/?#]/, 1);
|
|
6520
|
-
if (!hasScheme && hostCandidate.includes(".")) {
|
|
6521
|
-
baseUrl = `https://${baseUrl}`;
|
|
6522
|
-
}
|
|
6523
|
-
const resolvedBaseUrl = baseUrl;
|
|
6524
|
-
const [urlError, url] = catchError2(() => new URL(resolvedBaseUrl));
|
|
6525
|
-
if (urlError) {
|
|
6526
|
-
const shapeHint = !hasScheme && !hostCandidate.includes(".") ? ` "${rawUrl.trim()}" is not a URL or a host name. Pass the full authority URL — https://<host>, or just <host> (https:// is assumed).` : ` ${urlError instanceof Error ? urlError.message : "Unknown error"}`;
|
|
6527
|
-
throw new InvalidBaseUrlError(baseUrl, `Malformed URL.${shapeHint}`);
|
|
6528
|
-
}
|
|
6529
|
-
if (url.protocol !== "https:") {
|
|
6530
|
-
throw new InvalidBaseUrlError(baseUrl, `Authority must use https:// scheme, got ${url.protocol}//. OIDC token exchange requires TLS end-to-end.`);
|
|
6531
|
-
}
|
|
6532
|
-
return url.pathname.length > 1 ? url.origin : baseUrl;
|
|
6533
|
-
};
|
|
6534
|
-
var resolveScopes = (isExternalAppAuth, customScopes, fileScopes) => {
|
|
6535
|
-
const requestedScopes = customScopes?.length ? customScopes : fileScopes ?? [];
|
|
6536
|
-
if (isExternalAppAuth)
|
|
6537
|
-
return requestedScopes;
|
|
6538
|
-
return [...new Set([...DEFAULT_SCOPES, ...requestedScopes])];
|
|
6539
|
-
};
|
|
6540
|
-
var resolveConfigAsync = async ({
|
|
6541
|
-
customAuthority,
|
|
6542
|
-
customClientId,
|
|
6543
|
-
customClientSecret,
|
|
6544
|
-
customClientAssertion,
|
|
6545
|
-
customScopes
|
|
6546
|
-
} = {}) => {
|
|
6547
|
-
const fileAuth = getAuthFileConfig();
|
|
6548
|
-
let baseUrl = customAuthority;
|
|
6549
|
-
if (!baseUrl) {
|
|
6550
|
-
baseUrl = process.env.UIPATH_URL;
|
|
6551
|
-
}
|
|
6552
|
-
if (!baseUrl && fileAuth.authority) {
|
|
6553
|
-
baseUrl = fileAuth.authority;
|
|
6554
|
-
}
|
|
6555
|
-
if (!baseUrl) {
|
|
6556
|
-
baseUrl = DEFAULT_BASE_URL;
|
|
6557
|
-
}
|
|
6558
|
-
baseUrl = normalizeAndValidateBaseUrl(baseUrl);
|
|
6559
|
-
let clientId = customClientId;
|
|
6560
|
-
if (!clientId && fileAuth.clientId) {
|
|
6561
|
-
clientId = fileAuth.clientId;
|
|
6562
|
-
}
|
|
6563
|
-
if (!clientId) {
|
|
6564
|
-
clientId = DEFAULT_CLIENT_ID;
|
|
6565
|
-
}
|
|
6566
|
-
let clientSecret = customClientSecret;
|
|
6567
|
-
if (!clientSecret && fileAuth.clientSecret) {
|
|
6568
|
-
clientSecret = fileAuth.clientSecret;
|
|
6569
|
-
}
|
|
6570
|
-
const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(clientSecret) || Boolean(customClientAssertion));
|
|
6571
|
-
const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
|
|
6572
|
-
return {
|
|
6573
|
-
clientId,
|
|
6574
|
-
clientSecret,
|
|
6575
|
-
scopes,
|
|
6576
|
-
baseUrl,
|
|
6577
|
-
authorizationEndpoint: `${baseUrl}/identity_/connect/authorize`,
|
|
6578
|
-
tokenEndpoint: `${baseUrl}/identity_/connect/token`
|
|
6579
|
-
};
|
|
6580
|
-
};
|
|
6581
|
-
|
|
6582
|
-
// ../auth/src/utils/platform.ts
|
|
6583
|
-
function isBrowser() {
|
|
6584
|
-
return typeof globalThis !== "undefined" && "window" in globalThis && "document" in globalThis;
|
|
6585
|
-
}
|
|
6586
|
-
|
|
6587
|
-
// ../auth/src/utils/jwt.ts
|
|
6588
|
-
class InvalidIssuerError extends Error {
|
|
6589
|
-
expected;
|
|
6590
|
-
actual;
|
|
6591
|
-
constructor(expected, actual) {
|
|
6592
|
-
const actualText = actual ?? "<missing>";
|
|
6593
|
-
super(`Token issuer does not match the authority used to log in.
|
|
6594
|
-
` + `Expected: ${expected}
|
|
6595
|
-
` + `Actual: ${actualText}
|
|
6596
|
-
|
|
6597
|
-
` + `The identity server that issued this token is not the one ` + `you pointed --authority at. Refusing to save credentials.`);
|
|
6598
|
-
this.expected = expected;
|
|
6599
|
-
this.actual = actual;
|
|
6600
|
-
this.name = "InvalidIssuerError";
|
|
6601
|
-
}
|
|
6602
|
-
}
|
|
6603
|
-
var parseJWT = (token) => {
|
|
6604
|
-
try {
|
|
6605
|
-
const parts = token.split(".");
|
|
6606
|
-
const base64Url = parts[1];
|
|
6607
|
-
if (!base64Url) {
|
|
6608
|
-
throw new Error("Invalid JWT token format - missing payload section");
|
|
6609
|
-
}
|
|
6610
|
-
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
6611
|
-
let decodedString;
|
|
6612
|
-
if (isBrowser() && typeof atob !== "undefined") {
|
|
6613
|
-
decodedString = atob(base64);
|
|
6614
|
-
} else {
|
|
6615
|
-
decodedString = Buffer.from(base64, "base64").toString();
|
|
6616
|
-
}
|
|
6617
|
-
const jsonPayload = decodeURIComponent(decodedString.split("").map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`).join(""));
|
|
6618
|
-
const parsed = JSON.parse(jsonPayload);
|
|
6619
|
-
return parsed;
|
|
6620
|
-
} catch (error) {
|
|
6621
|
-
throw new Error(`Failed to parse JWT: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
6622
|
-
}
|
|
6623
|
-
};
|
|
6624
|
-
var assertIssuerMatchesAuthority = (token, authority) => {
|
|
6625
|
-
let payload;
|
|
6626
|
-
try {
|
|
6627
|
-
payload = parseJWT(token);
|
|
6628
|
-
} catch (error) {
|
|
6629
|
-
throw new InvalidIssuerError(`${authority.replace(/\/+$/, "")}/identity_`, `<unparseable: ${error instanceof Error ? error.message : "unknown error"}>`);
|
|
6630
|
-
}
|
|
6631
|
-
const stripTrailingSlash = (s) => s.replace(/\/+$/, "");
|
|
6632
|
-
const expected = `${stripTrailingSlash(authority)}/identity_`;
|
|
6633
|
-
const actual = typeof payload.iss === "string" ? stripTrailingSlash(payload.iss) : undefined;
|
|
6634
|
-
if (actual !== expected) {
|
|
6635
|
-
throw new InvalidIssuerError(expected, payload.iss);
|
|
6636
|
-
}
|
|
6637
|
-
};
|
|
6638
|
-
var getTokenExpiration = (accessToken) => {
|
|
6639
|
-
try {
|
|
6640
|
-
const parts = accessToken.split(".");
|
|
6641
|
-
if (parts.length !== 3) {
|
|
6642
|
-
return;
|
|
6643
|
-
}
|
|
6644
|
-
const payload = parts[1];
|
|
6645
|
-
const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
6646
|
-
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
6647
|
-
const decoded = atob(padded);
|
|
6648
|
-
const claims = JSON.parse(decoded);
|
|
6649
|
-
if (typeof claims.exp !== "number") {
|
|
6650
|
-
return;
|
|
6651
|
-
}
|
|
6652
|
-
return new Date(claims.exp * 1000);
|
|
6653
|
-
} catch {
|
|
6654
|
-
return;
|
|
6655
|
-
}
|
|
6656
|
-
};
|
|
6657
|
-
|
|
6658
|
-
// ../auth/src/sessionIdentity.ts
|
|
6659
|
-
var parseAuthFlow = (value) => value === "authorization_code" || value === "client_credentials" || value === "federated_credentials" ? value : undefined;
|
|
6660
|
-
var decodeClaims = (accessToken) => {
|
|
6661
|
-
const [error, claims] = catchError2(() => parseJWT(accessToken));
|
|
6662
|
-
return error ? undefined : claims;
|
|
6663
|
-
};
|
|
6664
|
-
var asString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
6665
|
-
var resolveIdentityType = (claims, authFlow, email) => {
|
|
6666
|
-
const subType = asString(claims?.sub_type);
|
|
6667
|
-
if (subType) {
|
|
6668
|
-
return subType.startsWith("service") ? "Application" : "User";
|
|
6669
|
-
}
|
|
6670
|
-
if (authFlow) {
|
|
6671
|
-
return authFlow === "authorization_code" ? "User" : "Application";
|
|
6672
|
-
}
|
|
6673
|
-
if (email)
|
|
6674
|
-
return "User";
|
|
6675
|
-
if (asString(claims?.client_id) && !asString(claims?.sub)) {
|
|
6676
|
-
return "Application";
|
|
6677
|
-
}
|
|
6678
|
-
return;
|
|
6679
|
-
};
|
|
6680
|
-
var looksLikeEmail = (value) => value?.includes("@") ?? false;
|
|
6681
|
-
var pickEmail = (claims) => {
|
|
6682
|
-
for (const candidate of [claims?.email, claims?.preferred_username]) {
|
|
6683
|
-
const value = asString(candidate);
|
|
6684
|
-
if (looksLikeEmail(value))
|
|
6685
|
-
return value;
|
|
6686
|
-
}
|
|
6687
|
-
return;
|
|
6688
|
-
};
|
|
6689
|
-
var pickName = (claims) => {
|
|
6690
|
-
const username = asString(claims?.preferred_username);
|
|
6691
|
-
return asString(claims?.name) ?? (looksLikeEmail(username) ? undefined : username);
|
|
6692
|
-
};
|
|
6693
|
-
var resolveSessionIdentity = (accessToken, authFlow) => {
|
|
6694
|
-
const claims = accessToken ? decodeClaims(accessToken) : undefined;
|
|
6695
|
-
const email = pickEmail(claims);
|
|
6696
|
-
const type = resolveIdentityType(claims, authFlow, email);
|
|
6697
|
-
if (!type)
|
|
6698
|
-
return;
|
|
6699
|
-
const identity = { type };
|
|
6700
|
-
if (authFlow)
|
|
6701
|
-
identity.authFlow = authFlow;
|
|
6702
|
-
if (type === "User") {
|
|
6703
|
-
const userId = asString(claims?.sub);
|
|
6704
|
-
if (userId)
|
|
6705
|
-
identity.userId = userId;
|
|
6706
|
-
if (email)
|
|
6707
|
-
identity.userEmail = email;
|
|
6708
|
-
const name = pickName(claims);
|
|
6709
|
-
if (name)
|
|
6710
|
-
identity.userName = name;
|
|
6711
|
-
return identity;
|
|
6712
|
-
}
|
|
6713
|
-
const clientId = asString(claims?.client_id);
|
|
6714
|
-
if (clientId)
|
|
6715
|
-
identity.clientId = clientId;
|
|
6716
|
-
return identity;
|
|
6717
|
-
};
|
|
6718
|
-
|
|
6719
|
-
// ../auth/src/envAuth.ts
|
|
6720
|
-
var ENV_AUTH_ENABLE_VAR = "UIPATH_CLI_ENABLE_ENV_AUTH";
|
|
6721
|
-
var ENFORCE_ROBOT_AUTH_VAR = "UIPATH_CLI_ENFORCE_ROBOT_AUTH";
|
|
6722
|
-
var ENV_AUTH_VARS = {
|
|
6723
|
-
token: "UIPATH_CLI_AUTH_TOKEN",
|
|
6724
|
-
organizationName: "UIPATH_CLI_ORGANIZATION_NAME",
|
|
6725
|
-
organizationId: "UIPATH_CLI_ORGANIZATION_ID",
|
|
6726
|
-
tenantName: "UIPATH_CLI_TENANT_NAME",
|
|
6727
|
-
tenantId: "UIPATH_CLI_TENANT_ID"
|
|
6728
|
-
};
|
|
6729
|
-
|
|
6730
|
-
class EnvAuthConfigError extends Error {
|
|
6731
|
-
constructor(message) {
|
|
6732
|
-
super(message);
|
|
6733
|
-
this.name = "EnvAuthConfigError";
|
|
6734
|
-
}
|
|
6735
|
-
}
|
|
6736
|
-
var isEnvAuthEnabled = () => process.env[ENV_AUTH_ENABLE_VAR] === "true";
|
|
6737
|
-
var isRobotAuthEnforced = () => process.env[ENFORCE_ROBOT_AUTH_VAR] === "true";
|
|
6738
|
-
var requireEnv = (name) => {
|
|
6739
|
-
const value = process.env[name];
|
|
6740
|
-
if (!value) {
|
|
6741
|
-
throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true but ${name} is not set. ` + `Set ${name} to enable env-var authentication.`);
|
|
6742
|
-
}
|
|
6743
|
-
return value;
|
|
6744
|
-
};
|
|
6745
|
-
var OPAQUE_TOKEN_BASE_URL_VAR = "UIPATH_URL";
|
|
6746
|
-
var resolveBaseUrl = (rawUrl, failureContext) => {
|
|
6747
|
-
const [baseUrlError, baseUrl] = catchError2(() => normalizeAndValidateBaseUrl(rawUrl));
|
|
6748
|
-
if (baseUrlError) {
|
|
6749
|
-
if (baseUrlError instanceof InvalidBaseUrlError) {
|
|
6750
|
-
throw baseUrlError;
|
|
6751
|
-
}
|
|
6752
|
-
throw new EnvAuthConfigError(`${failureContext}: ` + `${baseUrlError instanceof Error ? baseUrlError.message : String(baseUrlError)}`);
|
|
6753
|
-
}
|
|
6754
|
-
return baseUrl;
|
|
6755
|
-
};
|
|
6756
|
-
var readAuthFromEnv = () => {
|
|
6757
|
-
const accessToken = requireEnv(ENV_AUTH_VARS.token);
|
|
6758
|
-
const organizationName = requireEnv(ENV_AUTH_VARS.organizationName);
|
|
6759
|
-
const organizationId = requireEnv(ENV_AUTH_VARS.organizationId);
|
|
6760
|
-
const tenantName = requireEnv(ENV_AUTH_VARS.tenantName);
|
|
6761
|
-
const tenantId = requireEnv(ENV_AUTH_VARS.tenantId);
|
|
6762
|
-
const [parseError, payload] = catchError2(() => parseJWT(accessToken));
|
|
6763
|
-
if (parseError) {
|
|
6764
|
-
const parseErrorMessage = parseError instanceof Error ? parseError.message : String(parseError);
|
|
6765
|
-
const rawUrl = process.env[OPAQUE_TOKEN_BASE_URL_VAR];
|
|
6766
|
-
if (!rawUrl) {
|
|
6767
|
-
throw new EnvAuthConfigError(`${ENV_AUTH_VARS.token} is not a JWT (treating it as an opaque token, ` + `e.g. a Personal Access Token). Set ${OPAQUE_TOKEN_BASE_URL_VAR} to the ` + `UiPath base URL if this is a PAT, or fix the token if it was meant to ` + `be a JWT (parse error: ${parseErrorMessage}).`);
|
|
6768
|
-
}
|
|
6769
|
-
const baseUrl2 = resolveBaseUrl(rawUrl, `Failed to validate ${OPAQUE_TOKEN_BASE_URL_VAR}`);
|
|
6770
|
-
return {
|
|
6771
|
-
loginStatus: "Logged in",
|
|
6772
|
-
accessToken,
|
|
6773
|
-
baseUrl: baseUrl2,
|
|
6774
|
-
organizationName,
|
|
6775
|
-
organizationId,
|
|
6776
|
-
tenantName,
|
|
6777
|
-
tenantId,
|
|
6778
|
-
source: "env-vars" /* EnvironmentVariables */,
|
|
6779
|
-
hint: "Token is opaque (not a JWT) - expiration and identity cannot be " + "determined locally. Commands will fail with 401 once it is revoked or " + `expired. If this was meant to be a JWT instead of a PAT, note: ${parseErrorMessage}`
|
|
6780
|
-
};
|
|
6781
|
-
}
|
|
6782
|
-
const iss = payload.iss;
|
|
6783
|
-
if (typeof iss !== "string" || iss.length === 0) {
|
|
6784
|
-
throw new EnvAuthConfigError(`${ENV_AUTH_VARS.token} has no 'iss' claim; cannot determine ` + `the UiPath server. Ensure the token was issued by a UiPath identity server.`);
|
|
6785
|
-
}
|
|
6786
|
-
const baseUrl = resolveBaseUrl(iss, "Failed to derive server URL from token 'iss' claim");
|
|
6787
|
-
const expiration = getTokenExpiration(accessToken);
|
|
6788
|
-
const loginStatus = expiration && expiration <= new Date ? "Expired" : "Logged in";
|
|
6789
|
-
const identity = resolveSessionIdentity(accessToken);
|
|
6790
|
-
return {
|
|
6791
|
-
loginStatus,
|
|
6792
|
-
accessToken,
|
|
6793
|
-
baseUrl,
|
|
6794
|
-
organizationName,
|
|
6795
|
-
organizationId,
|
|
6796
|
-
tenantName,
|
|
6797
|
-
tenantId,
|
|
6798
|
-
expiration,
|
|
6799
|
-
source: "env-vars" /* EnvironmentVariables */,
|
|
6800
|
-
...identity ? { identity } : {}
|
|
6801
|
-
};
|
|
6802
|
-
};
|
|
6803
|
-
|
|
6804
|
-
// ../auth/src/refreshCircuitBreaker.ts
|
|
6805
|
-
var BREAKER_SUFFIX = ".refresh-state";
|
|
6806
|
-
var BACKOFF_BASE_MS = 60000;
|
|
6807
|
-
var BACKOFF_CAP_MS = 60 * 60 * 1000;
|
|
6808
|
-
var SURFACE_WINDOW_MS = 60 * 60 * 1000;
|
|
6809
|
-
async function refreshTokenFingerprint(refreshToken) {
|
|
6810
|
-
const bytes = new TextEncoder().encode(refreshToken);
|
|
6811
|
-
if (globalThis.crypto?.subtle) {
|
|
6812
|
-
const digest2 = await globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
6813
|
-
return Array.from(new Uint8Array(digest2), (b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
6814
|
-
}
|
|
6815
|
-
const { createHash } = await import("node:crypto");
|
|
6816
|
-
return createHash("sha256").update(refreshToken).digest("hex").slice(0, 16);
|
|
6817
|
-
}
|
|
6818
|
-
function breakerPathFor(authPath) {
|
|
6819
|
-
return `${authPath}${BREAKER_SUFFIX}`;
|
|
6820
|
-
}
|
|
6821
|
-
async function loadRefreshBreaker(authPath) {
|
|
6822
|
-
const fs2 = getFileSystem();
|
|
6823
|
-
try {
|
|
6824
|
-
const content = await fs2.readFile(breakerPathFor(authPath), "utf-8");
|
|
6825
|
-
if (!content)
|
|
6826
|
-
return {};
|
|
6827
|
-
const parsed = JSON.parse(content);
|
|
6828
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
6829
|
-
} catch {
|
|
6830
|
-
return {};
|
|
6831
|
-
}
|
|
6832
|
-
}
|
|
6833
|
-
async function saveRefreshBreaker(authPath, state) {
|
|
6834
|
-
try {
|
|
6835
|
-
const fs2 = getFileSystem();
|
|
6836
|
-
const path2 = breakerPathFor(authPath);
|
|
6837
|
-
await fs2.mkdir(fs2.path.dirname(path2));
|
|
6838
|
-
const tempPath = `${path2}.tmp`;
|
|
6839
|
-
await fs2.writeFile(tempPath, JSON.stringify(state));
|
|
6840
|
-
await fs2.rename(tempPath, path2);
|
|
6841
|
-
} catch {}
|
|
6842
|
-
}
|
|
6843
|
-
async function clearRefreshBreaker(authPath) {
|
|
6844
|
-
const fs2 = getFileSystem();
|
|
6845
|
-
const path2 = breakerPathFor(authPath);
|
|
6846
|
-
try {
|
|
6847
|
-
if (await fs2.exists(path2)) {
|
|
6848
|
-
await fs2.rm(path2);
|
|
6849
|
-
}
|
|
6850
|
-
} catch {}
|
|
6851
|
-
}
|
|
6852
|
-
function nextBackoffMs(attempts) {
|
|
6853
|
-
const shift = Math.max(0, attempts - 1);
|
|
6854
|
-
return Math.min(BACKOFF_BASE_MS * 2 ** shift, BACKOFF_CAP_MS);
|
|
6855
|
-
}
|
|
6856
|
-
function shouldSurface(state, nowMs) {
|
|
6857
|
-
if (state.lastSurfacedAtMs === undefined)
|
|
6858
|
-
return true;
|
|
6859
|
-
return nowMs - state.lastSurfacedAtMs >= SURFACE_WINDOW_MS;
|
|
6860
|
-
}
|
|
6861
|
-
|
|
6862
|
-
// ../auth/src/robotClientFallback.ts
|
|
6863
|
-
var DEFAULT_TIMEOUT_MS = 1000;
|
|
6864
|
-
var CLOSE_TIMEOUT_MS = 500;
|
|
6865
|
-
var ROBOT_USER_SERVICES_PIPE = "UiPathUserServices";
|
|
6866
|
-
var ROBOT_USER_SERVICES_ALTERNATE_PIPE = `${ROBOT_USER_SERVICES_PIPE}Alternate`;
|
|
6867
|
-
var PIPE_NAME_MAX_LENGTH = 103;
|
|
6868
|
-
var getRobotIpcPipeNames = async () => {
|
|
6869
|
-
const fs2 = getFileSystem();
|
|
6870
|
-
const username = fs2.env.getenv("USER") ?? fs2.env.getenv("USERNAME");
|
|
6871
|
-
if (!username) {
|
|
6872
|
-
throw new Error("Unable to determine current username");
|
|
6873
|
-
}
|
|
6874
|
-
const tempPath = fs2.env.getenv("TMPDIR") ?? "/tmp/";
|
|
6875
|
-
return [ROBOT_USER_SERVICES_PIPE, ROBOT_USER_SERVICES_ALTERNATE_PIPE].map((baseName) => fs2.path.join(tempPath, `${baseName}_${username}`).substring(0, PIPE_NAME_MAX_LENGTH));
|
|
6876
|
-
};
|
|
6877
|
-
var defaultIsRobotIpcAvailable = async () => {
|
|
6878
|
-
if (process.platform === "win32") {
|
|
6879
|
-
return true;
|
|
6880
|
-
}
|
|
6881
|
-
const [pipeNamesError, pipeNames] = await catchError2(getRobotIpcPipeNames());
|
|
6882
|
-
if (pipeNamesError || !pipeNames) {
|
|
6883
|
-
return false;
|
|
6884
|
-
}
|
|
6885
|
-
const fs2 = getFileSystem();
|
|
6886
|
-
for (const pipeName of pipeNames) {
|
|
6887
|
-
const [existsError, exists] = await catchError2(fs2.exists(pipeName));
|
|
6888
|
-
if (!existsError && exists === true) {
|
|
6889
|
-
return true;
|
|
6890
|
-
}
|
|
6891
|
-
}
|
|
6892
|
-
return false;
|
|
6893
|
-
};
|
|
6894
|
-
var withTimeout = (promise, timeoutMs) => new Promise((resolve2, reject) => {
|
|
6895
|
-
const timer = setTimeout(() => reject(new Error(`Robot IPC call timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
6896
|
-
promise.then((value) => {
|
|
6897
|
-
clearTimeout(timer);
|
|
6898
|
-
resolve2(value);
|
|
6899
|
-
}, (error) => {
|
|
6900
|
-
clearTimeout(timer);
|
|
6901
|
-
reject(error);
|
|
6902
|
-
});
|
|
6903
|
-
});
|
|
6904
|
-
var parseResourceUrl = (url) => {
|
|
6905
|
-
const [error, parsed] = catchError2(() => new URL(url));
|
|
6906
|
-
if (error || !parsed)
|
|
6907
|
-
return;
|
|
6908
|
-
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
6909
|
-
return {
|
|
6910
|
-
baseUrl: parsed.origin,
|
|
6911
|
-
organizationName: segments[0],
|
|
6912
|
-
tenantName: segments[1]
|
|
6913
|
-
};
|
|
6914
|
-
};
|
|
6915
|
-
var ROBOT_CLIENT_LOADER_KEY = Symbol.for("@uipath/auth/RobotClientLoader");
|
|
6916
|
-
var getRegisteredRobotClientLoader = () => {
|
|
6917
|
-
const loader = globalThis[ROBOT_CLIENT_LOADER_KEY];
|
|
6918
|
-
return typeof loader === "function" ? loader : undefined;
|
|
6919
|
-
};
|
|
6920
|
-
var defaultLoadModule = async () => {
|
|
6921
|
-
const hostLoader = getRegisteredRobotClientLoader();
|
|
6922
|
-
if (!hostLoader) {
|
|
6923
|
-
return;
|
|
6924
|
-
}
|
|
6925
|
-
const [error, mod] = await catchError2(() => hostLoader());
|
|
6926
|
-
if (error || !mod) {
|
|
6927
|
-
return;
|
|
6928
|
-
}
|
|
6929
|
-
return mod;
|
|
6930
|
-
};
|
|
6931
|
-
var tryRobotClientFallback = async (options = {}) => {
|
|
6932
|
-
if (isBrowser())
|
|
6933
|
-
return;
|
|
6934
|
-
if (!options.force) {
|
|
6935
|
-
if (process.env.CI || process.env.GITHUB_ACTIONS) {
|
|
6936
|
-
return;
|
|
6937
|
-
}
|
|
6938
|
-
if (process.env.UIPATH_URL) {
|
|
6939
|
-
return;
|
|
6940
|
-
}
|
|
6941
|
-
}
|
|
6942
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
6943
|
-
const isRobotIpcAvailable = options.isRobotIpcAvailable ?? defaultIsRobotIpcAvailable;
|
|
6944
|
-
const loadModule = options.loadModule ?? defaultLoadModule;
|
|
6945
|
-
if (!await isRobotIpcAvailable()) {
|
|
6946
|
-
return;
|
|
6947
|
-
}
|
|
6948
|
-
const mod = await loadModule();
|
|
6949
|
-
if (!mod)
|
|
6950
|
-
return;
|
|
6951
|
-
const [ctorError, proxy] = catchError2(() => new mod.RobotProxyConstructor);
|
|
6952
|
-
if (ctorError || !proxy) {
|
|
6953
|
-
return;
|
|
6954
|
-
}
|
|
6955
|
-
try {
|
|
6956
|
-
const enabled = await withTimeout(proxy.interactiveConnectFlow.IsEnabled(), timeoutMs);
|
|
6957
|
-
if (!enabled) {
|
|
6958
|
-
return;
|
|
6959
|
-
}
|
|
6960
|
-
const [resourceUrl, accessToken] = await Promise.all([
|
|
6961
|
-
withTimeout(proxy.accessProvider.GetResourceUrl("Orchestrator"), timeoutMs),
|
|
6962
|
-
withTimeout(proxy.accessProvider.GetAccessToken("Orchestrator", false), timeoutMs)
|
|
6963
|
-
]);
|
|
6964
|
-
if (!accessToken) {
|
|
6965
|
-
return;
|
|
6966
|
-
}
|
|
6967
|
-
const parsedUrl = parseResourceUrl(resourceUrl);
|
|
6968
|
-
if (!parsedUrl) {
|
|
6969
|
-
return;
|
|
6970
|
-
}
|
|
6971
|
-
let organizationIdFromToken;
|
|
6972
|
-
let tenantIdFromToken;
|
|
6973
|
-
let issuerFromToken;
|
|
6974
|
-
const [jwtError, claims] = catchError2(() => parseJWT(accessToken));
|
|
6975
|
-
if (!jwtError && claims) {
|
|
6976
|
-
const rawOrgId = claims.prtId ?? claims.organizationId ?? claims.prt_id;
|
|
6977
|
-
if (typeof rawOrgId === "string" && rawOrgId.length > 0) {
|
|
6978
|
-
organizationIdFromToken = rawOrgId;
|
|
6979
|
-
}
|
|
6980
|
-
const tenantClaim = claims.tenantId ?? claims.tenant_id;
|
|
6981
|
-
if (typeof tenantClaim === "string" && tenantClaim.length > 0) {
|
|
6982
|
-
tenantIdFromToken = tenantClaim;
|
|
6983
|
-
}
|
|
6984
|
-
const issClaim = claims.iss;
|
|
6985
|
-
if (typeof issClaim === "string" && issClaim.length > 0) {
|
|
6986
|
-
issuerFromToken = issClaim;
|
|
6987
|
-
}
|
|
6988
|
-
}
|
|
6989
|
-
return {
|
|
6990
|
-
accessToken,
|
|
6991
|
-
baseUrl: parsedUrl.baseUrl,
|
|
6992
|
-
organizationName: parsedUrl.organizationName,
|
|
6993
|
-
organizationId: organizationIdFromToken ?? parsedUrl.organizationName,
|
|
6994
|
-
tenantName: parsedUrl.tenantName,
|
|
6995
|
-
tenantId: tenantIdFromToken,
|
|
6996
|
-
issuer: issuerFromToken
|
|
6997
|
-
};
|
|
6998
|
-
} catch {
|
|
6999
|
-
return;
|
|
7000
|
-
} finally {
|
|
7001
|
-
await catchError2(() => withTimeout(proxy.CloseAsync(), CLOSE_TIMEOUT_MS));
|
|
7002
|
-
}
|
|
7003
|
-
};
|
|
7004
|
-
|
|
7005
|
-
// ../auth/src/tokenRefresh.ts
|
|
7006
|
-
var TOKEN_REFRESH_REAUTHENTICATE_MESSAGE = "Token refresh failed. Run 'uip login' to re-authenticate.";
|
|
7007
|
-
|
|
7008
|
-
class TokenRefreshOAuthError extends Error {
|
|
7009
|
-
__brand = "TokenRefreshOAuthError";
|
|
7010
|
-
constructor() {
|
|
7011
|
-
super(TOKEN_REFRESH_REAUTHENTICATE_MESSAGE);
|
|
7012
|
-
this.name = "TokenRefreshOAuthError";
|
|
7013
|
-
}
|
|
7014
|
-
}
|
|
7015
|
-
function isTokenRefreshOAuthFailure(error) {
|
|
7016
|
-
return error instanceof TokenRefreshOAuthError;
|
|
7017
|
-
}
|
|
7018
|
-
var refreshAccessToken = async ({
|
|
7019
|
-
refreshToken,
|
|
7020
|
-
tokenEndpoint,
|
|
7021
|
-
clientId,
|
|
7022
|
-
expectedAuthority
|
|
7023
|
-
}) => {
|
|
7024
|
-
const tokenParams = new URLSearchParams({
|
|
7025
|
-
grant_type: "refresh_token",
|
|
7026
|
-
refresh_token: refreshToken,
|
|
7027
|
-
client_id: clientId
|
|
7028
|
-
});
|
|
7029
|
-
const tokenResponse = await fetch(tokenEndpoint, {
|
|
7030
|
-
method: "POST",
|
|
7031
|
-
headers: {
|
|
7032
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
7033
|
-
},
|
|
7034
|
-
body: tokenParams
|
|
7035
|
-
});
|
|
7036
|
-
const tokenData = await tokenResponse.json();
|
|
7037
|
-
if (!tokenResponse.ok) {
|
|
7038
|
-
throw new TokenRefreshOAuthError;
|
|
7039
|
-
}
|
|
7040
|
-
const newAccessToken = tokenData.access_token;
|
|
7041
|
-
const newRefreshToken = tokenData.refresh_token;
|
|
7042
|
-
if (typeof newAccessToken !== "string" || typeof newRefreshToken !== "string") {
|
|
7043
|
-
throw new Error("Token refresh response is missing access_token or refresh_token");
|
|
7044
|
-
}
|
|
7045
|
-
if (expectedAuthority) {
|
|
7046
|
-
assertIssuerMatchesAuthority(newAccessToken, expectedAuthority);
|
|
7047
|
-
}
|
|
7048
|
-
return { accessToken: newAccessToken, refreshToken: newRefreshToken };
|
|
7049
|
-
};
|
|
7050
|
-
|
|
7051
|
-
// ../auth/src/types.ts
|
|
7052
|
-
var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
|
|
7053
|
-
|
|
7054
|
-
// ../auth/src/utils/envFile.ts
|
|
7055
|
-
var DEFAULT_ENV_FILENAME = `${UIPATH_HOME_DIR}/${AUTH_FILENAME}`;
|
|
7056
|
-
var KNOWN_ERROR_CODES = new Set([
|
|
7057
|
-
"EISDIR",
|
|
7058
|
-
"EACCES",
|
|
7059
|
-
"EPERM",
|
|
7060
|
-
"ELOOP",
|
|
7061
|
-
"ENOTDIR",
|
|
7062
|
-
"EUNKNOWN"
|
|
7063
|
-
]);
|
|
7064
|
-
var errorCode = (err) => {
|
|
7065
|
-
if (err !== null && typeof err === "object" && "code" in err && typeof err.code === "string") {
|
|
7066
|
-
const raw = err.code;
|
|
7067
|
-
return KNOWN_ERROR_CODES.has(raw) ? raw : "EUNKNOWN";
|
|
7068
|
-
}
|
|
7069
|
-
return "EUNKNOWN";
|
|
7070
|
-
};
|
|
7071
|
-
var probeAsync = async (fs2, candidate) => {
|
|
7072
|
-
try {
|
|
7073
|
-
const stats = await fs2.stat(candidate);
|
|
7074
|
-
if (stats === null) {
|
|
7075
|
-
return { exists: false };
|
|
7076
|
-
}
|
|
7077
|
-
if (!stats.isFile()) {
|
|
7078
|
-
return {
|
|
7079
|
-
exists: false,
|
|
7080
|
-
unusable: {
|
|
7081
|
-
reason: "not-a-file",
|
|
7082
|
-
code: "EISDIR",
|
|
7083
|
-
message: `Path is not a regular file: ${candidate}`
|
|
7084
|
-
}
|
|
7085
|
-
};
|
|
7086
|
-
}
|
|
7087
|
-
return { exists: true };
|
|
7088
|
-
} catch (err) {
|
|
7089
|
-
return {
|
|
7090
|
-
exists: false,
|
|
7091
|
-
unusable: {
|
|
7092
|
-
reason: "unreadable",
|
|
7093
|
-
code: errorCode(err),
|
|
7094
|
-
message: err instanceof Error ? err.message : String(err)
|
|
7095
|
-
}
|
|
7096
|
-
};
|
|
7097
|
-
}
|
|
7098
|
-
};
|
|
7099
|
-
var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) => {
|
|
7100
|
-
const fs2 = getFileSystem();
|
|
7101
|
-
if (fs2.path.isAbsolute(envFilePath)) {
|
|
7102
|
-
const probe2 = await probeAsync(fs2, envFilePath);
|
|
7103
|
-
return probe2.exists ? { exists: true, absolutePath: envFilePath, source: "absolute" } : {
|
|
7104
|
-
exists: false,
|
|
7105
|
-
absolutePath: envFilePath,
|
|
7106
|
-
source: "absolute",
|
|
7107
|
-
...probe2.unusable ? { unusable: probe2.unusable } : {}
|
|
7108
|
-
};
|
|
7109
|
-
}
|
|
7110
|
-
const cwd = opts?.cwd ?? fs2.env.cwd();
|
|
7111
|
-
let searchDir = cwd;
|
|
7112
|
-
while (true) {
|
|
7113
|
-
const candidate = fs2.path.join(searchDir, envFilePath);
|
|
7114
|
-
const probe2 = await probeAsync(fs2, candidate);
|
|
7115
|
-
if (probe2.exists) {
|
|
7116
|
-
return {
|
|
7117
|
-
exists: true,
|
|
7118
|
-
absolutePath: candidate,
|
|
7119
|
-
source: searchDir === cwd ? "cwd" : "ancestor"
|
|
7120
|
-
};
|
|
7121
|
-
}
|
|
7122
|
-
const parentDir = fs2.path.dirname(searchDir);
|
|
7123
|
-
if (parentDir === searchDir) {
|
|
7124
|
-
break;
|
|
7125
|
-
}
|
|
7126
|
-
searchDir = parentDir;
|
|
7127
|
-
}
|
|
7128
|
-
const homePath = fs2.path.join(fs2.env.homedir(), envFilePath);
|
|
7129
|
-
const probe = await probeAsync(fs2, homePath);
|
|
7130
|
-
if (probe.exists) {
|
|
7131
|
-
return { exists: true, absolutePath: homePath, source: "home" };
|
|
7132
|
-
}
|
|
7133
|
-
return {
|
|
7134
|
-
exists: false,
|
|
7135
|
-
absolutePath: homePath,
|
|
7136
|
-
source: "default",
|
|
7137
|
-
...probe.unusable ? { unusable: probe.unusable } : {}
|
|
7138
|
-
};
|
|
7139
|
-
};
|
|
7140
|
-
var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) => {
|
|
7141
|
-
const location = await resolveEnvFileLocationAsync(envFilePath, opts);
|
|
7142
|
-
if (location.exists) {
|
|
7143
|
-
return { absolutePath: location.absolutePath };
|
|
7144
|
-
}
|
|
7145
|
-
return {
|
|
7146
|
-
absolutePath: undefined,
|
|
7147
|
-
errorMessage: location.source === "absolute" ? `Environment file not found: ${envFilePath}` : `Unable to locate environment file: ${envFilePath}. Run 'uip login' to authenticate.`
|
|
7148
|
-
};
|
|
7149
|
-
};
|
|
7150
|
-
var loadEnvFileAsync = async ({ envPath }) => {
|
|
7151
|
-
const fs2 = getFileSystem();
|
|
7152
|
-
const absolutePath = fs2.path.isAbsolute(envPath) ? envPath : fs2.path.join(fs2.env.cwd(), envPath);
|
|
7153
|
-
if (!await fs2.exists(absolutePath)) {
|
|
7154
|
-
throw new Error(`Environment file not found: ${envPath}`);
|
|
7155
|
-
}
|
|
7156
|
-
const content = await fs2.readFile(absolutePath, "utf-8");
|
|
7157
|
-
if (content === null) {
|
|
7158
|
-
throw new Error(`Environment file not found: ${envPath}`);
|
|
7159
|
-
}
|
|
7160
|
-
const env = {};
|
|
7161
|
-
for (const line of content.split(`
|
|
7162
|
-
`)) {
|
|
7163
|
-
const trimmed = line.trim();
|
|
7164
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
7165
|
-
continue;
|
|
7166
|
-
}
|
|
7167
|
-
const equalIndex = trimmed.indexOf("=");
|
|
7168
|
-
if (equalIndex === -1) {
|
|
7169
|
-
continue;
|
|
7170
|
-
}
|
|
7171
|
-
const key = trimmed.slice(0, equalIndex).trim();
|
|
7172
|
-
let value = trimmed.slice(equalIndex + 1).trim();
|
|
7173
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
7174
|
-
value = value.slice(1, -1);
|
|
7175
|
-
}
|
|
7176
|
-
env[key] = value;
|
|
7177
|
-
}
|
|
7178
|
-
return env;
|
|
7179
|
-
};
|
|
7180
|
-
var saveEnvFileAsync = async ({
|
|
7181
|
-
envPath,
|
|
7182
|
-
data,
|
|
7183
|
-
merge = true
|
|
7184
|
-
}) => {
|
|
7185
|
-
const fs2 = getFileSystem();
|
|
7186
|
-
const absolutePath = fs2.path.isAbsolute(envPath) ? envPath : fs2.path.join(fs2.env.homedir(), envPath);
|
|
7187
|
-
let existingData = {};
|
|
7188
|
-
if (merge && await fs2.exists(absolutePath)) {
|
|
7189
|
-
try {
|
|
7190
|
-
existingData = await loadEnvFileAsync({ envPath: absolutePath });
|
|
7191
|
-
} catch {}
|
|
7192
|
-
}
|
|
7193
|
-
const finalData = { ...existingData, ...data };
|
|
7194
|
-
const lines = [];
|
|
7195
|
-
for (const [key, value] of Object.entries(finalData)) {
|
|
7196
|
-
if (value === undefined) {
|
|
7197
|
-
continue;
|
|
7198
|
-
}
|
|
7199
|
-
const needsQuotes = value.includes(" ") || value.includes("#");
|
|
7200
|
-
const finalValue = needsQuotes ? `"${value}"` : value;
|
|
7201
|
-
lines.push(`${key}=${finalValue}`);
|
|
7202
|
-
}
|
|
7203
|
-
const content = `${lines.join(`
|
|
7204
|
-
`)}
|
|
7205
|
-
`;
|
|
7206
|
-
const dir = fs2.path.dirname(absolutePath);
|
|
7207
|
-
await fs2.mkdir(dir);
|
|
7208
|
-
const tempPath = `${absolutePath}.tmp`;
|
|
7209
|
-
await fs2.writeFile(tempPath, content);
|
|
7210
|
-
await fs2.rename(tempPath, absolutePath);
|
|
7211
|
-
};
|
|
7212
|
-
|
|
7213
|
-
// ../auth/src/loginStatus.ts
|
|
7214
|
-
var getLoginStatusAsync = async (options = {}) => {
|
|
7215
|
-
return getLoginStatusWithDeps(options);
|
|
7216
|
-
};
|
|
7217
|
-
var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
|
|
7218
|
-
const {
|
|
7219
|
-
resolveEnvFilePath = resolveEnvFilePathAsync,
|
|
7220
|
-
loadEnvFile = loadEnvFileAsync,
|
|
7221
|
-
saveEnvFile = saveEnvFileAsync,
|
|
7222
|
-
getFs = getFileSystem,
|
|
7223
|
-
refreshToken: refreshTokenFn = refreshAccessToken,
|
|
7224
|
-
resolveConfig: resolveConfig2 = resolveConfigAsync,
|
|
7225
|
-
robotFallback = tryRobotClientFallback,
|
|
7226
|
-
loadBreaker = loadRefreshBreaker,
|
|
7227
|
-
saveBreaker = saveRefreshBreaker,
|
|
7228
|
-
clearBreaker = clearRefreshBreaker
|
|
7229
|
-
} = deps;
|
|
7230
|
-
if (isRobotAuthEnforced()) {
|
|
7231
|
-
return resolveRobotEnforcedStatus(robotFallback);
|
|
7232
|
-
}
|
|
7233
|
-
if (isEnvAuthEnabled()) {
|
|
7234
|
-
return readAuthFromEnv();
|
|
7235
|
-
}
|
|
7236
|
-
const activeProfile = getActiveAuthProfile();
|
|
7237
|
-
const activeProfileFilePath = getActiveAuthProfileFilePath();
|
|
7238
|
-
const usingActiveProfile = activeProfile !== undefined && (options.envFilePath === undefined || options.envFilePath === activeProfileFilePath);
|
|
7239
|
-
const envFilePath = options.envFilePath ?? activeProfileFilePath ?? DEFAULT_ENV_FILENAME;
|
|
7240
|
-
const { ensureTokenValidityMinutes } = options;
|
|
7241
|
-
const { absolutePath } = await resolveEnvFilePath(envFilePath);
|
|
7242
|
-
if (absolutePath === undefined) {
|
|
7243
|
-
if (usingActiveProfile) {
|
|
7244
|
-
return {
|
|
7245
|
-
loginStatus: "Not logged in",
|
|
7246
|
-
hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
|
|
7247
|
-
};
|
|
7248
|
-
}
|
|
7249
|
-
return resolveBorrowedRobotStatus(robotFallback);
|
|
7250
|
-
}
|
|
7251
|
-
const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
|
|
7252
|
-
if ("status" in loaded) {
|
|
7253
|
-
return loaded.status;
|
|
7254
|
-
}
|
|
7255
|
-
const { credentials } = loaded;
|
|
7256
|
-
const globalHint = () => usingActiveProfile ? Promise.resolve(undefined) : getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath);
|
|
7257
|
-
const expiration = getTokenExpiration(credentials.UIPATH_ACCESS_TOKEN);
|
|
7258
|
-
const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
7259
|
-
let tokens = {
|
|
7260
|
-
accessToken: credentials.UIPATH_ACCESS_TOKEN,
|
|
7261
|
-
refreshToken: credentials.UIPATH_REFRESH_TOKEN,
|
|
7262
|
-
expiration,
|
|
7263
|
-
lockReleaseFailed: false
|
|
7264
|
-
};
|
|
7265
|
-
const refreshToken = credentials.UIPATH_REFRESH_TOKEN;
|
|
7266
|
-
if (expiration && expiration <= outerThreshold && refreshToken) {
|
|
7267
|
-
const refreshed = await attemptRefresh({
|
|
7268
|
-
absolutePath,
|
|
7269
|
-
credentials,
|
|
7270
|
-
accessToken: credentials.UIPATH_ACCESS_TOKEN,
|
|
7271
|
-
refreshToken,
|
|
7272
|
-
expiration,
|
|
7273
|
-
ensureTokenValidityMinutes,
|
|
7274
|
-
getFs,
|
|
7275
|
-
loadEnvFile,
|
|
7276
|
-
saveEnvFile,
|
|
7277
|
-
refreshFn: refreshTokenFn,
|
|
7278
|
-
resolveConfig: resolveConfig2,
|
|
7279
|
-
loadBreaker,
|
|
7280
|
-
saveBreaker,
|
|
7281
|
-
clearBreaker,
|
|
7282
|
-
globalHint
|
|
7283
|
-
});
|
|
7284
|
-
if (refreshed.kind === "terminal") {
|
|
7285
|
-
return refreshed.status;
|
|
7286
|
-
}
|
|
7287
|
-
tokens = refreshed.tokens;
|
|
7288
|
-
}
|
|
7289
|
-
return buildFileStatus(tokens, credentials, globalHint);
|
|
7290
|
-
};
|
|
7291
|
-
async function resolveRobotEnforcedStatus(robotFallback) {
|
|
7292
|
-
if (isEnvAuthEnabled()) {
|
|
7293
|
-
throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
|
|
7294
|
-
}
|
|
7295
|
-
const robotCreds = await robotFallback({ force: true });
|
|
7296
|
-
if (!robotCreds) {
|
|
7297
|
-
return {
|
|
7298
|
-
loginStatus: "Not logged in",
|
|
7299
|
-
hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
|
|
7300
|
-
};
|
|
7301
|
-
}
|
|
7302
|
-
return buildRobotStatus(robotCreds);
|
|
7303
|
-
}
|
|
7304
|
-
async function resolveBorrowedRobotStatus(robotFallback) {
|
|
7305
|
-
const robotCreds = await robotFallback();
|
|
7306
|
-
return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
|
|
7307
|
-
}
|
|
7308
|
-
async function loadFileCredentials(loadEnvFile, absolutePath) {
|
|
7309
|
-
let credentials;
|
|
7310
|
-
try {
|
|
7311
|
-
credentials = await loadEnvFile({ envPath: absolutePath });
|
|
7312
|
-
} catch (error) {
|
|
7313
|
-
if (isFileNotFoundError(error)) {
|
|
7314
|
-
return { status: { loginStatus: "Not logged in" } };
|
|
7315
|
-
}
|
|
7316
|
-
throw error;
|
|
7317
|
-
}
|
|
7318
|
-
if (!credentials.UIPATH_ACCESS_TOKEN) {
|
|
7319
|
-
return { status: { loginStatus: "Not logged in" } };
|
|
7320
|
-
}
|
|
7321
|
-
return { credentials };
|
|
7322
|
-
}
|
|
7323
|
-
async function getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath) {
|
|
7324
|
-
const fs2 = getFs();
|
|
7325
|
-
const globalPath = fs2.path.join(fs2.env.homedir(), envFilePath);
|
|
7326
|
-
if (absolutePath === globalPath)
|
|
7327
|
-
return;
|
|
7328
|
-
if (!await fs2.exists(globalPath))
|
|
7329
|
-
return;
|
|
7330
|
-
try {
|
|
7331
|
-
const globalCreds = await loadEnvFile({ envPath: globalPath });
|
|
7332
|
-
if (!globalCreds.UIPATH_ACCESS_TOKEN)
|
|
7333
|
-
return;
|
|
7334
|
-
const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
|
|
7335
|
-
if (globalExp && globalExp <= new Date)
|
|
7336
|
-
return;
|
|
7337
|
-
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.`;
|
|
7338
|
-
} catch {
|
|
7339
|
-
return;
|
|
7340
|
-
}
|
|
7341
|
-
}
|
|
7342
|
-
function computeExpirationThreshold(ensureTokenValidityMinutes) {
|
|
7343
|
-
return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
|
|
7344
|
-
}
|
|
7345
|
-
async function attemptRefresh(ctx) {
|
|
7346
|
-
const shortCircuit = await circuitBreakerShortCircuit(ctx);
|
|
7347
|
-
if (shortCircuit) {
|
|
7348
|
-
return { kind: "terminal", status: shortCircuit };
|
|
7349
|
-
}
|
|
7350
|
-
let release;
|
|
7351
|
-
try {
|
|
7352
|
-
release = await ctx.getFs().acquireLock(ctx.absolutePath);
|
|
7353
|
-
} catch (error) {
|
|
7354
|
-
return {
|
|
7355
|
-
kind: "terminal",
|
|
7356
|
-
status: await lockAcquireFailureStatus(ctx, error)
|
|
7357
|
-
};
|
|
7358
|
-
}
|
|
7359
|
-
let lockedFailure;
|
|
7360
|
-
let lockReleaseFailed = false;
|
|
7361
|
-
let success;
|
|
7362
|
-
try {
|
|
7363
|
-
const outcome = await runRefreshLocked({
|
|
7364
|
-
absolutePath: ctx.absolutePath,
|
|
7365
|
-
refreshToken: ctx.refreshToken,
|
|
7366
|
-
customAuthority: ctx.credentials.UIPATH_URL,
|
|
7367
|
-
ensureTokenValidityMinutes: ctx.ensureTokenValidityMinutes,
|
|
7368
|
-
loadEnvFile: ctx.loadEnvFile,
|
|
7369
|
-
saveEnvFile: ctx.saveEnvFile,
|
|
7370
|
-
refreshFn: ctx.refreshFn,
|
|
7371
|
-
resolveConfig: ctx.resolveConfig,
|
|
7372
|
-
loadBreaker: ctx.loadBreaker,
|
|
7373
|
-
saveBreaker: ctx.saveBreaker,
|
|
7374
|
-
clearBreaker: ctx.clearBreaker
|
|
7375
|
-
});
|
|
7376
|
-
if (outcome.kind === "fail") {
|
|
7377
|
-
lockedFailure = outcome.status;
|
|
7378
|
-
} else {
|
|
7379
|
-
success = outcome;
|
|
7380
|
-
}
|
|
7381
|
-
} finally {
|
|
7382
|
-
try {
|
|
7383
|
-
await release();
|
|
7384
|
-
} catch {
|
|
7385
|
-
lockReleaseFailed = true;
|
|
7386
|
-
}
|
|
7387
|
-
}
|
|
7388
|
-
if (lockedFailure) {
|
|
7389
|
-
const globalHint = await ctx.globalHint();
|
|
7390
|
-
const base = globalHint ? { ...lockedFailure, loginStatus: "Expired", hint: globalHint } : lockedFailure;
|
|
7391
|
-
return {
|
|
7392
|
-
kind: "terminal",
|
|
7393
|
-
status: lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base
|
|
7394
|
-
};
|
|
7395
|
-
}
|
|
7396
|
-
return {
|
|
7397
|
-
kind: "refreshed",
|
|
7398
|
-
tokens: {
|
|
7399
|
-
accessToken: success?.accessToken,
|
|
7400
|
-
refreshToken: success?.refreshToken,
|
|
7401
|
-
expiration: success?.expiration,
|
|
7402
|
-
tokenRefresh: success?.tokenRefresh,
|
|
7403
|
-
persistenceWarning: success?.persistenceWarning,
|
|
7404
|
-
lockReleaseFailed
|
|
7405
|
-
}
|
|
7406
|
-
};
|
|
7407
|
-
}
|
|
7408
|
-
async function buildFileStatus(tokens, credentials, globalHint) {
|
|
7409
|
-
const result = {
|
|
7410
|
-
loginStatus: tokens.expiration && tokens.expiration <= new Date ? "Expired" : "Logged in",
|
|
7411
|
-
accessToken: tokens.accessToken,
|
|
7412
|
-
refreshToken: tokens.refreshToken,
|
|
7413
|
-
baseUrl: credentials.UIPATH_URL,
|
|
7414
|
-
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
7415
|
-
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
7416
|
-
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
7417
|
-
tenantId: credentials.UIPATH_TENANT_ID,
|
|
7418
|
-
expiration: tokens.expiration,
|
|
7419
|
-
source: "saved-login" /* SavedLogin */,
|
|
7420
|
-
...identityFields(tokens.accessToken, credentials),
|
|
7421
|
-
...tokens.persistenceWarning ? { hint: tokens.persistenceWarning, persistenceFailed: true } : {},
|
|
7422
|
-
...tokens.lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
7423
|
-
...tokens.tokenRefresh ? { tokenRefresh: tokens.tokenRefresh } : {}
|
|
7424
|
-
};
|
|
7425
|
-
if (result.loginStatus === "Expired") {
|
|
7426
|
-
const hint = await globalHint();
|
|
7427
|
-
if (hint) {
|
|
7428
|
-
result.hint = hint;
|
|
7429
|
-
}
|
|
7430
|
-
}
|
|
7431
|
-
return result;
|
|
7432
|
-
}
|
|
7433
|
-
function identityFields(accessToken, credentials) {
|
|
7434
|
-
const identity = resolveSessionIdentity(accessToken, parseAuthFlow(credentials[AUTH_FLOW_ENV_VAR]));
|
|
7435
|
-
return identity ? { identity } : {};
|
|
7436
|
-
}
|
|
7437
|
-
function buildRobotStatus(robotCreds) {
|
|
7438
|
-
const identity = resolveSessionIdentity(robotCreds.accessToken);
|
|
7439
|
-
return {
|
|
7440
|
-
loginStatus: "Logged in",
|
|
7441
|
-
accessToken: robotCreds.accessToken,
|
|
7442
|
-
baseUrl: robotCreds.baseUrl,
|
|
7443
|
-
organizationName: robotCreds.organizationName,
|
|
7444
|
-
organizationId: robotCreds.organizationId,
|
|
7445
|
-
tenantName: robotCreds.tenantName,
|
|
7446
|
-
tenantId: robotCreds.tenantId,
|
|
7447
|
-
issuer: robotCreds.issuer,
|
|
7448
|
-
expiration: getTokenExpiration(robotCreds.accessToken),
|
|
7449
|
-
source: "robot" /* Robot */,
|
|
7450
|
-
...identity ? { identity } : {}
|
|
7451
|
-
};
|
|
7452
|
-
}
|
|
7453
|
-
var isFileNotFoundError = (error) => {
|
|
7454
|
-
if (!(error instanceof Object))
|
|
7455
|
-
return false;
|
|
7456
|
-
return error.code === "ENOENT";
|
|
7457
|
-
};
|
|
7458
|
-
async function circuitBreakerShortCircuit(ctx) {
|
|
7459
|
-
const {
|
|
7460
|
-
absolutePath,
|
|
7461
|
-
refreshToken,
|
|
7462
|
-
accessToken,
|
|
7463
|
-
credentials,
|
|
7464
|
-
expiration,
|
|
7465
|
-
loadBreaker,
|
|
7466
|
-
saveBreaker,
|
|
7467
|
-
clearBreaker
|
|
7468
|
-
} = ctx;
|
|
7469
|
-
const fingerprint = await refreshTokenFingerprint(refreshToken);
|
|
7470
|
-
const breaker = await loadBreaker(absolutePath).catch(() => ({}));
|
|
7471
|
-
if (breaker.deadTokenFp && breaker.deadTokenFp !== fingerprint) {
|
|
7472
|
-
await clearBreaker(absolutePath);
|
|
7473
|
-
breaker.deadTokenFp = undefined;
|
|
7474
|
-
}
|
|
7475
|
-
const nowMs = Date.now();
|
|
7476
|
-
const tokenIsDead = breaker.deadTokenFp === fingerprint;
|
|
7477
|
-
const inBackoff = breaker.backoffUntilMs !== undefined && nowMs < breaker.backoffUntilMs;
|
|
7478
|
-
if (!tokenIsDead && !inBackoff)
|
|
7479
|
-
return;
|
|
7480
|
-
const globalHint = await ctx.globalHint();
|
|
7481
|
-
const suppressed = !shouldSurface(breaker, nowMs);
|
|
7482
|
-
if (!suppressed) {
|
|
7483
|
-
await saveBreaker(absolutePath, {
|
|
7484
|
-
...breaker,
|
|
7485
|
-
lastSurfacedAtMs: nowMs
|
|
7486
|
-
});
|
|
7487
|
-
}
|
|
7488
|
-
const deadHint = "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>.";
|
|
7489
|
-
const backoffHint = "Token refresh is temporarily backed off after a recent network error and will retry automatically once the backoff window elapses.";
|
|
7490
|
-
return {
|
|
7491
|
-
loginStatus: globalHint ? "Expired" : "Refresh Failed",
|
|
7492
|
-
...globalHint ? {
|
|
7493
|
-
accessToken,
|
|
7494
|
-
refreshToken,
|
|
7495
|
-
baseUrl: credentials.UIPATH_URL,
|
|
7496
|
-
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
7497
|
-
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
7498
|
-
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
7499
|
-
tenantId: credentials.UIPATH_TENANT_ID,
|
|
7500
|
-
expiration,
|
|
7501
|
-
source: "saved-login" /* SavedLogin */,
|
|
7502
|
-
...identityFields(accessToken, credentials)
|
|
7503
|
-
} : {},
|
|
7504
|
-
hint: globalHint ?? (tokenIsDead ? deadHint : backoffHint),
|
|
7505
|
-
refreshCircuitOpen: true,
|
|
7506
|
-
refreshTelemetrySuppressed: suppressed,
|
|
7507
|
-
tokenRefresh: { attempted: false, success: false }
|
|
7508
|
-
};
|
|
7509
|
-
}
|
|
7510
|
-
async function lockAcquireFailureStatus(ctx, error) {
|
|
7511
|
-
const msg = errorMessage(error);
|
|
7512
|
-
const globalHint = await ctx.globalHint();
|
|
7513
|
-
if (globalHint) {
|
|
7514
|
-
return {
|
|
7515
|
-
loginStatus: "Expired",
|
|
7516
|
-
accessToken: ctx.accessToken,
|
|
7517
|
-
refreshToken: ctx.refreshToken,
|
|
7518
|
-
baseUrl: ctx.credentials.UIPATH_URL,
|
|
7519
|
-
organizationName: ctx.credentials.UIPATH_ORGANIZATION_NAME,
|
|
7520
|
-
organizationId: ctx.credentials.UIPATH_ORGANIZATION_ID,
|
|
7521
|
-
tenantName: ctx.credentials.UIPATH_TENANT_NAME,
|
|
7522
|
-
tenantId: ctx.credentials.UIPATH_TENANT_ID,
|
|
7523
|
-
expiration: ctx.expiration,
|
|
7524
|
-
source: "saved-login" /* SavedLogin */,
|
|
7525
|
-
...identityFields(ctx.accessToken, ctx.credentials),
|
|
7526
|
-
hint: globalHint,
|
|
7527
|
-
tokenRefresh: {
|
|
7528
|
-
attempted: false,
|
|
7529
|
-
success: false,
|
|
7530
|
-
errorMessage: `lock acquisition failed: ${msg}`
|
|
7531
|
-
}
|
|
7532
|
-
};
|
|
7533
|
-
}
|
|
7534
|
-
return {
|
|
7535
|
-
loginStatus: "Refresh Failed",
|
|
7536
|
-
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.",
|
|
7537
|
-
tokenRefresh: {
|
|
7538
|
-
attempted: false,
|
|
7539
|
-
success: false,
|
|
7540
|
-
errorMessage: `lock acquisition failed: ${msg}`
|
|
7541
|
-
}
|
|
7542
|
-
};
|
|
7543
|
-
}
|
|
7544
|
-
async function runRefreshLocked(inputs) {
|
|
7545
|
-
const {
|
|
7546
|
-
absolutePath,
|
|
7547
|
-
refreshToken: callerRefreshToken,
|
|
7548
|
-
customAuthority,
|
|
7549
|
-
ensureTokenValidityMinutes,
|
|
7550
|
-
loadEnvFile,
|
|
7551
|
-
saveEnvFile,
|
|
7552
|
-
refreshFn,
|
|
7553
|
-
resolveConfig: resolveConfig2,
|
|
7554
|
-
loadBreaker,
|
|
7555
|
-
saveBreaker,
|
|
7556
|
-
clearBreaker
|
|
7557
|
-
} = inputs;
|
|
7558
|
-
const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
7559
|
-
let fresh;
|
|
7560
|
-
try {
|
|
7561
|
-
fresh = await loadEnvFile({ envPath: absolutePath });
|
|
7562
|
-
} catch (error) {
|
|
7563
|
-
return {
|
|
7564
|
-
kind: "fail",
|
|
7565
|
-
status: {
|
|
7566
|
-
loginStatus: "Refresh Failed",
|
|
7567
|
-
hint: "Could not read the auth file while refreshing. Retry, or run 'uip login' to re-authenticate.",
|
|
7568
|
-
tokenRefresh: {
|
|
7569
|
-
attempted: false,
|
|
7570
|
-
success: false,
|
|
7571
|
-
errorMessage: `auth file read failed: ${errorMessage(error)}`
|
|
7572
|
-
}
|
|
7573
|
-
}
|
|
7574
|
-
};
|
|
7575
|
-
}
|
|
7576
|
-
const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
|
|
7577
|
-
const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
|
|
7578
|
-
if (freshAccess && freshExp && freshExp > expirationThreshold) {
|
|
7579
|
-
await clearBreaker(absolutePath);
|
|
7580
|
-
return {
|
|
7581
|
-
kind: "ok",
|
|
7582
|
-
accessToken: freshAccess,
|
|
7583
|
-
refreshToken: fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken,
|
|
7584
|
-
expiration: freshExp,
|
|
7585
|
-
tokenRefresh: { attempted: false, success: true }
|
|
7586
|
-
};
|
|
7587
|
-
}
|
|
7588
|
-
const tokenForIdP = fresh.UIPATH_REFRESH_TOKEN ?? callerRefreshToken;
|
|
7589
|
-
let refreshedAccess;
|
|
7590
|
-
let refreshedRefresh;
|
|
7591
|
-
try {
|
|
7592
|
-
const config = await resolveConfig2({ customAuthority });
|
|
7593
|
-
const refreshed = await refreshFn({
|
|
7594
|
-
refreshToken: tokenForIdP,
|
|
7595
|
-
tokenEndpoint: config.tokenEndpoint,
|
|
7596
|
-
clientId: config.clientId,
|
|
7597
|
-
expectedAuthority: customAuthority
|
|
7598
|
-
});
|
|
7599
|
-
refreshedAccess = refreshed.accessToken;
|
|
7600
|
-
refreshedRefresh = refreshed.refreshToken;
|
|
7601
|
-
} catch (error) {
|
|
7602
|
-
const isOAuthFailure = isTokenRefreshOAuthFailure(error);
|
|
7603
|
-
const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
|
|
7604
|
-
const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
|
|
7605
|
-
const fp = await refreshTokenFingerprint(tokenForIdP);
|
|
7606
|
-
if (isOAuthFailure) {
|
|
7607
|
-
await saveBreaker(absolutePath, { deadTokenFp: fp });
|
|
7608
|
-
} else {
|
|
7609
|
-
const prior = await loadBreaker(absolutePath).catch(() => ({}));
|
|
7610
|
-
const attempts = (prior.attempts ?? 0) + 1;
|
|
7611
|
-
await saveBreaker(absolutePath, {
|
|
7612
|
-
...prior,
|
|
7613
|
-
deadTokenFp: undefined,
|
|
7614
|
-
attempts,
|
|
7615
|
-
backoffUntilMs: Date.now() + nextBackoffMs(attempts)
|
|
7616
|
-
});
|
|
7617
|
-
}
|
|
7618
|
-
return {
|
|
7619
|
-
kind: "fail",
|
|
7620
|
-
status: {
|
|
7621
|
-
loginStatus: "Refresh Failed",
|
|
7622
|
-
hint,
|
|
7623
|
-
tokenRefresh: {
|
|
7624
|
-
attempted: true,
|
|
7625
|
-
success: false,
|
|
7626
|
-
errorMessage: message
|
|
7627
|
-
}
|
|
7628
|
-
}
|
|
7629
|
-
};
|
|
7630
|
-
}
|
|
7631
|
-
const refreshedExp = getTokenExpiration(refreshedAccess);
|
|
7632
|
-
if (!refreshedExp || refreshedExp <= new Date) {
|
|
7633
|
-
return {
|
|
7634
|
-
kind: "fail",
|
|
7635
|
-
status: {
|
|
7636
|
-
loginStatus: "Refresh Failed",
|
|
7637
|
-
hint: "The identity server returned an unusable token. Run 'uip login' to re-authenticate.",
|
|
7638
|
-
tokenRefresh: {
|
|
7639
|
-
attempted: true,
|
|
7640
|
-
success: false,
|
|
7641
|
-
errorMessage: "refreshed token has no valid expiration claim"
|
|
7642
|
-
}
|
|
7643
|
-
}
|
|
7644
|
-
};
|
|
7645
|
-
}
|
|
7646
|
-
await clearBreaker(absolutePath);
|
|
7647
|
-
try {
|
|
7648
|
-
await saveEnvFile({
|
|
7649
|
-
envPath: absolutePath,
|
|
7650
|
-
data: {
|
|
7651
|
-
UIPATH_ACCESS_TOKEN: refreshedAccess,
|
|
7652
|
-
UIPATH_REFRESH_TOKEN: refreshedRefresh
|
|
7653
|
-
},
|
|
7654
|
-
merge: true
|
|
7655
|
-
});
|
|
7656
|
-
return {
|
|
7657
|
-
kind: "ok",
|
|
7658
|
-
accessToken: refreshedAccess,
|
|
7659
|
-
refreshToken: refreshedRefresh,
|
|
7660
|
-
expiration: refreshedExp,
|
|
7661
|
-
tokenRefresh: { attempted: true, success: true }
|
|
7662
|
-
};
|
|
7663
|
-
} catch (error) {
|
|
7664
|
-
const msg = errorMessage(error);
|
|
7665
|
-
return {
|
|
7666
|
-
kind: "ok",
|
|
7667
|
-
accessToken: refreshedAccess,
|
|
7668
|
-
refreshToken: refreshedRefresh,
|
|
7669
|
-
expiration: refreshedExp,
|
|
7670
|
-
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.`,
|
|
7671
|
-
tokenRefresh: {
|
|
7672
|
-
attempted: true,
|
|
7673
|
-
success: true,
|
|
7674
|
-
errorMessage: `persistence failed: ${msg}`
|
|
7675
|
-
}
|
|
7676
|
-
};
|
|
7677
|
-
}
|
|
7678
|
-
}
|
|
7679
|
-
function normalizeTokenRefreshFailure() {
|
|
7680
|
-
return "stored refresh token is invalid or expired";
|
|
7681
|
-
}
|
|
7682
|
-
function normalizeTokenRefreshUnavailableFailure() {
|
|
7683
|
-
return "token refresh failed before authentication completed";
|
|
7684
|
-
}
|
|
7685
|
-
function errorMessage(error) {
|
|
7686
|
-
return error instanceof Error ? error.message : String(error);
|
|
7687
|
-
}
|
|
7688
|
-
|
|
7689
|
-
// ../auth/src/authContext.ts
|
|
7690
|
-
var getAuthContext = async (options = {}) => {
|
|
7691
|
-
const status = await getLoginStatusAsync({
|
|
7692
|
-
ensureTokenValidityMinutes: options.ensureTokenValidityMinutes,
|
|
7693
|
-
envFilePath: options.envFilePath
|
|
7694
|
-
});
|
|
7695
|
-
if (status.loginStatus !== "Logged in" || !status.baseUrl || !status.accessToken) {
|
|
7696
|
-
throw new Error(status.hint ? `Not logged in. ${status.hint}` : "Not logged in. Run 'uip login' first.");
|
|
7697
|
-
}
|
|
7698
|
-
const tenantName = options.tenant ?? status.tenantName;
|
|
7699
|
-
if (options.requireOrganizationId && !status.organizationId) {
|
|
7700
|
-
throw new Error("Organization ID not available. Ensure you are logged in with an organization context.");
|
|
7701
|
-
}
|
|
7702
|
-
if (options.requireOrganizationName && !status.organizationName) {
|
|
7703
|
-
throw new Error("Organization name not available. Ensure you are logged in with an organization context.");
|
|
7704
|
-
}
|
|
7705
|
-
if (options.requireTenantId && !status.tenantId) {
|
|
7706
|
-
throw new Error("Tenant ID not available. Ensure UIPATH_TENANT_ID is set.");
|
|
7707
|
-
}
|
|
7708
|
-
if (options.requireTenantName && tenantName === undefined) {
|
|
7709
|
-
throw new Error("Tenant not provided and UIPATH_TENANT_NAME not set. Run 'uip login' to select a tenant, or use 'uip login tenant set <tenant>' to switch tenants.");
|
|
7710
|
-
}
|
|
7711
|
-
return {
|
|
7712
|
-
baseUrl: status.baseUrl,
|
|
7713
|
-
accessToken: status.accessToken,
|
|
7714
|
-
organizationId: status.organizationId,
|
|
7715
|
-
organizationName: status.organizationName,
|
|
7716
|
-
tenantId: status.tenantId,
|
|
7717
|
-
tenantName
|
|
7718
|
-
};
|
|
7719
|
-
};
|
|
7720
|
-
// ../auth/src/tenantSelection.ts
|
|
7721
|
-
var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
|
|
7722
|
-
|
|
7723
|
-
// ../auth/src/selectTenant.ts
|
|
7724
|
-
var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
|
|
7725
|
-
var INVALID_TENANT_CODE = "INVALID_TENANT";
|
|
7726
|
-
var TENANT_SELECTION_CODES = new Set([
|
|
7727
|
-
TENANT_SELECTION_REQUIRED_CODE,
|
|
7728
|
-
INVALID_TENANT_CODE
|
|
7729
|
-
]);
|
|
7730
|
-
// ../solution-sdk/src/solution-file.ts
|
|
7731
|
-
var STUDIO_WEB_PROJECT_TYPE_OVERRIDES = {
|
|
7732
|
-
ProcessOrchestration: "processOrchestration"
|
|
7733
|
-
};
|
|
7734
|
-
function normalizeProjectType(projectType) {
|
|
7735
|
-
return STUDIO_WEB_PROJECT_TYPE_OVERRIDES[projectType] ?? projectType;
|
|
7736
|
-
}
|
|
7737
|
-
function toPortableRelativePath(relativePath) {
|
|
7738
|
-
return relativePath.replace(/\\/g, "/");
|
|
7739
|
-
}
|
|
7740
|
-
async function readUipxFile(fs2, solutionDir) {
|
|
7741
|
-
const dirEntries = await fs2.readdir(solutionDir);
|
|
7742
|
-
const uipxFileName = dirEntries.find((f) => f.endsWith(".uipx"));
|
|
7743
|
-
if (!uipxFileName) {
|
|
7744
|
-
throw new Error(`No .uipx file found in ${solutionDir}. Run 'uip solution init' first.`);
|
|
7745
|
-
}
|
|
7746
|
-
const uipxContent = await fs2.readFile(fs2.path.join(solutionDir, uipxFileName), "utf-8");
|
|
7747
|
-
if (!uipxContent) {
|
|
7748
|
-
throw new Error(`Could not read .uipx file: ${uipxFileName} is empty or missing.`);
|
|
7749
|
-
}
|
|
7750
|
-
const [parseError, parsed] = catchError(() => JSON.parse(uipxContent));
|
|
7751
|
-
if (parseError) {
|
|
7752
|
-
throw new Error(`Invalid .uipx file: could not parse JSON in ${uipxFileName}.`);
|
|
7753
|
-
}
|
|
7754
|
-
const uipx = validateUipxFile(parsed, uipxFileName);
|
|
7755
|
-
return { uipx, uipxFileName };
|
|
7756
|
-
}
|
|
7757
|
-
function validateUipxFile(parsed, uipxFileName) {
|
|
7758
|
-
if (!isRecord2(parsed)) {
|
|
7759
|
-
throw new Error(`Invalid .uipx file: ${uipxFileName} must contain a JSON object.`);
|
|
7760
|
-
}
|
|
7761
|
-
if (typeof parsed.SolutionId !== "string" || !parsed.SolutionId.trim()) {
|
|
7762
|
-
throw new Error("Invalid .uipx file: missing SolutionId.");
|
|
7763
|
-
}
|
|
7764
|
-
if (!Array.isArray(parsed.Projects) || parsed.Projects.length === 0) {
|
|
7765
|
-
throw new Error("Invalid .uipx file: missing Projects.");
|
|
7766
|
-
}
|
|
7767
|
-
for (const [index, project] of parsed.Projects.entries()) {
|
|
7768
|
-
if (!isRecord2(project)) {
|
|
7769
|
-
throw new Error(`Invalid .uipx file: Projects[${index}] must be an object.`);
|
|
7770
|
-
}
|
|
7771
|
-
if (typeof project.ProjectRelativePath !== "string" || !project.ProjectRelativePath.trim()) {
|
|
7772
|
-
const pathHint = typeof project.Path === "string" ? " Found Path, but .uipx uses ProjectRelativePath." : "";
|
|
7773
|
-
throw new Error(`Invalid .uipx file: Projects[${index}] is missing ProjectRelativePath.${pathHint} Use 'uip solution projects add' to add projects, or set ProjectRelativePath to the project file path, for example "Foo/project.uiproj".`);
|
|
7774
|
-
}
|
|
7775
|
-
}
|
|
7776
|
-
return parsed;
|
|
7777
|
-
}
|
|
7778
|
-
function isRecord2(value) {
|
|
7779
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7780
|
-
}
|
|
7781
|
-
function resolveSolutionDir(fs2, inputPath) {
|
|
7782
|
-
const resolved = fs2.path.resolve(inputPath);
|
|
7783
|
-
if (resolved.endsWith(".uipx")) {
|
|
7784
|
-
return fs2.path.dirname(resolved);
|
|
7785
|
-
}
|
|
7786
|
-
return resolved;
|
|
7787
|
-
}
|
|
7788
|
-
async function updateUipxSolutionId(fs2, uipxPath, newSolutionId) {
|
|
7789
|
-
const [readError, content] = await catchError(fs2.readFile(uipxPath, "utf-8"));
|
|
7790
|
-
if (readError || !content) {
|
|
7791
|
-
logger.error(`Could not read .uipx file for update: ${readError?.message ?? "empty file"}`);
|
|
7792
|
-
return;
|
|
7793
|
-
}
|
|
7794
|
-
const [parseError, parsed] = catchError(() => JSON.parse(content));
|
|
7795
|
-
if (parseError) {
|
|
7796
|
-
logger.error(`Could not parse .uipx file for update: ${parseError.message}`);
|
|
7797
|
-
return;
|
|
7798
|
-
}
|
|
7799
|
-
parsed.SolutionId = newSolutionId;
|
|
7800
|
-
const [writeError] = await catchError(fs2.writeFile(uipxPath, JSON.stringify(parsed, null, 4)));
|
|
7801
|
-
if (writeError) {
|
|
7802
|
-
logger.error(`Could not update .uipx with new SolutionId: ${writeError.message}`);
|
|
7803
|
-
} else {
|
|
7804
|
-
logger.info(`Updated .uipx with Studio Web SolutionId: ${newSolutionId}`);
|
|
7805
|
-
}
|
|
7806
|
-
}
|
|
7807
|
-
async function findSolutionFileUpward(fs2, startDir) {
|
|
7808
|
-
let dir = startDir;
|
|
7809
|
-
while (true) {
|
|
7810
|
-
const entries = await fs2.readdir(dir);
|
|
7811
|
-
const files = entries.filter((f) => f.endsWith(".uipx"));
|
|
7812
|
-
if (files.length === 1) {
|
|
7813
|
-
return fs2.path.join(dir, files[0]);
|
|
7814
|
-
}
|
|
7815
|
-
if (files.length > 1) {
|
|
7816
|
-
throw new Error(`Multiple .uipx files found in ${dir}. Please specify which solution file to use.`);
|
|
7817
|
-
}
|
|
7818
|
-
const parent = fs2.path.dirname(dir);
|
|
7819
|
-
if (parent === dir) {
|
|
7820
|
-
throw new Error(`No .uipx solution file found (searched from ${startDir} to filesystem root)`);
|
|
7821
|
-
}
|
|
7822
|
-
dir = parent;
|
|
7823
|
-
}
|
|
7824
|
-
}
|
|
7825
|
-
|
|
7826
|
-
export { getFileSystem, catchError, carriedInstructions, extractErrorDetails, extractErrorMessage, logger, telemetry, RESULTS, Pagination, OutputFormatter, summarizePlatformBody, Command, Option, isPreviewBuild, processContext, withCompleter, requireConfirmation, DEFAULT_PAGE_SIZE, resolveEnvReference, isGuid, createHiddenDeprecatedTenantOption, parseLimit, parseOffset, parseBoundedInt, registerPackageMetadataOptions, mapPackageMetadataOptions, PollOutcome, mapPollFailure, pollUntil, getSdkUserAgentToken, addSdkUserAgentHeader, installSdkUserAgentHeader, unsupportedSolutionProjectType, trackShipSucceeded, ensurePackagerFactory, getLoginStatusAsync, getAuthContext, normalizeProjectType, toPortableRelativePath, readUipxFile, resolveSolutionDir, updateUipxSolutionId, findSolutionFileUpward };
|
|
6660
|
+
export { getFileSystem, catchError, carriedInstructions, extractErrorDetails, extractErrorMessage, logger, telemetry, carriedErrorCode, RESULTS, Pagination, OutputFormatter, summarizePlatformBody, Command, Option, isPreviewBuild, processContext, withCompleter, requireConfirmation, DEFAULT_PAGE_SIZE, resolveEnvReference, isGuid, resolveDeprecatedOptionAlias, warnDeprecatedOptionAlias, createHiddenDeprecatedTenantOption, parseLimit, parseOffset, parseBoundedInt, registerPackageMetadataOptions, mapPackageMetadataOptions, PollOutcome, mapPollFailure, pollUntil, getSdkUserAgentToken, addSdkUserAgentHeader, installSdkUserAgentHeader, unsupportedSolutionProjectType, trackShipSucceeded, ensurePackagerFactory };
|
|
7827
6661
|
|
|
7828
|
-
//# debugId=
|
|
6662
|
+
//# debugId=240C62B0C485594764756E2164756E21
|