@freecodecamp/universe-cli 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +305 -164
- package/dist/index.js +270 -204
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8421,6 +8421,27 @@ function w(r, t2) {
|
|
|
8421
8421
|
const e = r;
|
|
8422
8422
|
e.isTTY && e.setRawMode(t2);
|
|
8423
8423
|
}
|
|
8424
|
+
function z({ input: r = import_node_process.stdin, output: t2 = import_node_process.stdout, overwrite: e = true, hideCursor: s = true } = {}) {
|
|
8425
|
+
const i = _.createInterface({ input: r, output: t2, prompt: "", tabSize: 1 });
|
|
8426
|
+
_.emitKeypressEvents(r, i), r instanceof import_node_tty.ReadStream && r.isTTY && r.setRawMode(true);
|
|
8427
|
+
const n = (o, { name: a, sequence: h }) => {
|
|
8428
|
+
const l = String(o);
|
|
8429
|
+
if (V([l, a, h], "cancel")) {
|
|
8430
|
+
s && t2.write(import_sisteransi.cursor.show), process.exit(0);
|
|
8431
|
+
return;
|
|
8432
|
+
}
|
|
8433
|
+
if (!e) return;
|
|
8434
|
+
const f = a === "return" ? 0 : -1, v = a === "return" ? -1 : 0;
|
|
8435
|
+
_.moveCursor(t2, f, v, () => {
|
|
8436
|
+
_.clearLine(t2, 1, () => {
|
|
8437
|
+
r.once("keypress", n);
|
|
8438
|
+
});
|
|
8439
|
+
});
|
|
8440
|
+
};
|
|
8441
|
+
return s && t2.write(import_sisteransi.cursor.hide), r.once("keypress", n), () => {
|
|
8442
|
+
r.off("keypress", n), s && t2.write(import_sisteransi.cursor.show), r instanceof import_node_tty.ReadStream && r.isTTY && !Y && r.setRawMode(false), i.terminal = false, i.close();
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8424
8445
|
var O = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80;
|
|
8425
8446
|
var A = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
|
|
8426
8447
|
function R(r, t2, e, s = e) {
|
|
@@ -8579,6 +8600,7 @@ function Ze() {
|
|
|
8579
8600
|
return import_node_process2.default.platform !== "win32" ? import_node_process2.default.env.TERM !== "linux" : !!import_node_process2.default.env.CI || !!import_node_process2.default.env.WT_SESSION || !!import_node_process2.default.env.TERMINUS_SUBLIME || import_node_process2.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process2.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process2.default.env.TERM_PROGRAM === "vscode" || import_node_process2.default.env.TERM === "xterm-256color" || import_node_process2.default.env.TERM === "alacritty" || import_node_process2.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
8580
8601
|
}
|
|
8581
8602
|
var ee = Ze();
|
|
8603
|
+
var ae = () => process.env.CI === "true";
|
|
8582
8604
|
var w2 = (e, i) => ee ? e : i;
|
|
8583
8605
|
var _e = w2("\u25C6", "*");
|
|
8584
8606
|
var oe = w2("\u25A0", "x");
|
|
@@ -8671,6 +8693,59 @@ var O2 = { message: (e = [], { symbol: i = (0, import_node_util2.styleText)("gra
|
|
|
8671
8693
|
}, error: (e, i) => {
|
|
8672
8694
|
O2.message(e, { ...i, symbol: (0, import_node_util2.styleText)("red", ge) });
|
|
8673
8695
|
} };
|
|
8696
|
+
var Ct = (e) => (0, import_node_util2.styleText)("magenta", e);
|
|
8697
|
+
var fe = ({ indicator: e = "dots", onCancel: i, output: s = process.stdout, cancelMessage: r, errorMessage: u2, frames: n = ee ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: o = ee ? 80 : 120, signal: c2, ...a } = {}) => {
|
|
8698
|
+
const l = ae();
|
|
8699
|
+
let $2, y2, p2 = false, m = false, g = "", S2, h = performance.now();
|
|
8700
|
+
const f = O(s), v = a?.styleFrame ?? Ct, T = (_2) => {
|
|
8701
|
+
const A2 = _2 > 1 ? u2 ?? u.messages.error : r ?? u.messages.cancel;
|
|
8702
|
+
m = _2 === 1, p2 && (W(A2, _2), m && typeof i == "function" && i());
|
|
8703
|
+
}, C2 = () => T(2), b = () => T(1), x = () => {
|
|
8704
|
+
process.on("uncaughtExceptionMonitor", C2), process.on("unhandledRejection", C2), process.on("SIGINT", b), process.on("SIGTERM", b), process.on("exit", T), c2 && c2.addEventListener("abort", b);
|
|
8705
|
+
}, G2 = () => {
|
|
8706
|
+
process.removeListener("uncaughtExceptionMonitor", C2), process.removeListener("unhandledRejection", C2), process.removeListener("SIGINT", b), process.removeListener("SIGTERM", b), process.removeListener("exit", T), c2 && c2.removeEventListener("abort", b);
|
|
8707
|
+
}, M2 = () => {
|
|
8708
|
+
if (S2 === void 0) return;
|
|
8709
|
+
l && s.write(`
|
|
8710
|
+
`);
|
|
8711
|
+
const _2 = wrapAnsi(S2, f, { hard: true, trim: false }).split(`
|
|
8712
|
+
`);
|
|
8713
|
+
_2.length > 1 && s.write(import_sisteransi2.cursor.up(_2.length - 1)), s.write(import_sisteransi2.cursor.to(0)), s.write(import_sisteransi2.erase.down());
|
|
8714
|
+
}, R2 = (_2) => _2.replace(/\.+$/, ""), j2 = (_2) => {
|
|
8715
|
+
const A2 = (performance.now() - _2) / 1e3, k = Math.floor(A2 / 60), L = Math.floor(A2 % 60);
|
|
8716
|
+
return k > 0 ? `[${k}m ${L}s]` : `[${L}s]`;
|
|
8717
|
+
}, D2 = a.withGuide ?? u.withGuide, ie = (_2 = "") => {
|
|
8718
|
+
p2 = true, $2 = z({ output: s }), g = R2(_2), h = performance.now(), D2 && s.write(`${(0, import_node_util2.styleText)("gray", d)}
|
|
8719
|
+
`);
|
|
8720
|
+
let A2 = 0, k = 0;
|
|
8721
|
+
x(), y2 = setInterval(() => {
|
|
8722
|
+
if (l && g === S2) return;
|
|
8723
|
+
M2(), S2 = g;
|
|
8724
|
+
const L = v(n[A2]);
|
|
8725
|
+
let Z;
|
|
8726
|
+
if (l) Z = `${L} ${g}...`;
|
|
8727
|
+
else if (e === "timer") Z = `${L} ${g} ${j2(h)}`;
|
|
8728
|
+
else {
|
|
8729
|
+
const Be = ".".repeat(Math.floor(k)).slice(0, 3);
|
|
8730
|
+
Z = `${L} ${g}${Be}`;
|
|
8731
|
+
}
|
|
8732
|
+
const Ne = wrapAnsi(Z, f, { hard: true, trim: false });
|
|
8733
|
+
s.write(Ne), A2 = A2 + 1 < n.length ? A2 + 1 : 0, k = k < 4 ? k + 0.125 : 0;
|
|
8734
|
+
}, o);
|
|
8735
|
+
}, W = (_2 = "", A2 = 0, k = false) => {
|
|
8736
|
+
if (!p2) return;
|
|
8737
|
+
p2 = false, clearInterval(y2), M2();
|
|
8738
|
+
const L = A2 === 0 ? (0, import_node_util2.styleText)("green", F) : A2 === 1 ? (0, import_node_util2.styleText)("red", oe) : (0, import_node_util2.styleText)("red", ue);
|
|
8739
|
+
g = _2 ?? g, k || (e === "timer" ? s.write(`${L} ${g} ${j2(h)}
|
|
8740
|
+
`) : s.write(`${L} ${g}
|
|
8741
|
+
`)), G2(), $2();
|
|
8742
|
+
};
|
|
8743
|
+
return { start: ie, stop: (_2 = "") => W(_2, 0), message: (_2 = "") => {
|
|
8744
|
+
g = R2(_2 ?? g);
|
|
8745
|
+
}, cancel: (_2 = "") => W(_2, 1), error: (_2 = "") => W(_2, 2), clear: () => W("", 0, true), get isCancelled() {
|
|
8746
|
+
return m;
|
|
8747
|
+
} };
|
|
8748
|
+
};
|
|
8674
8749
|
var Ve = { light: w2("\u2500", "-"), heavy: w2("\u2501", "="), block: w2("\u2588", "#") };
|
|
8675
8750
|
var je = `${(0, import_node_util2.styleText)("gray", d)} `;
|
|
8676
8751
|
|
|
@@ -22862,6 +22937,14 @@ function suggest(target, candidates, threshold = 2) {
|
|
|
22862
22937
|
}
|
|
22863
22938
|
|
|
22864
22939
|
// src/lib/proxy-client.ts
|
|
22940
|
+
var DEFAULT_FETCH_TIMEOUT_MS = 3e4;
|
|
22941
|
+
function parseFetchTimeoutMs(env) {
|
|
22942
|
+
const raw = env["UNIVERSE_FETCH_TIMEOUT_MS"];
|
|
22943
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
22944
|
+
const n = Number(raw);
|
|
22945
|
+
if (!Number.isFinite(n) || n < 0) return void 0;
|
|
22946
|
+
return Math.floor(n);
|
|
22947
|
+
}
|
|
22865
22948
|
var ProxyError = class extends CliError {
|
|
22866
22949
|
exitCode;
|
|
22867
22950
|
status;
|
|
@@ -22939,6 +23022,24 @@ function stripTrailingSlash(url2) {
|
|
|
22939
23022
|
function createProxyClient(cfg) {
|
|
22940
23023
|
const base = stripTrailingSlash(cfg.baseUrl);
|
|
22941
23024
|
const fetchImpl = cfg.fetch ?? globalThis.fetch.bind(globalThis);
|
|
23025
|
+
const timeoutMs = cfg.timeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
|
|
23026
|
+
function withTimeoutSignal(init) {
|
|
23027
|
+
if (timeoutMs <= 0) return init;
|
|
23028
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
23029
|
+
const merged = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;
|
|
23030
|
+
return { ...init, signal: merged };
|
|
23031
|
+
}
|
|
23032
|
+
function translateFetchError(err) {
|
|
23033
|
+
if (err instanceof DOMException && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
23034
|
+
throw new ProxyError(
|
|
23035
|
+
0,
|
|
23036
|
+
"timeout",
|
|
23037
|
+
`proxy timed out after ${timeoutMs}ms`
|
|
23038
|
+
);
|
|
23039
|
+
}
|
|
23040
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23041
|
+
throw new ProxyError(0, "network_error", `proxy unreachable: ${message}`);
|
|
23042
|
+
}
|
|
22942
23043
|
async function userBearer() {
|
|
22943
23044
|
const tok = await cfg.getAuthToken();
|
|
22944
23045
|
return `Bearer ${tok}`;
|
|
@@ -22946,10 +23047,9 @@ function createProxyClient(cfg) {
|
|
|
22946
23047
|
async function call(url2, init) {
|
|
22947
23048
|
let response;
|
|
22948
23049
|
try {
|
|
22949
|
-
response = await fetchImpl(url2, init);
|
|
23050
|
+
response = await fetchImpl(url2, withTimeoutSignal(init));
|
|
22950
23051
|
} catch (err) {
|
|
22951
|
-
|
|
22952
|
-
throw new ProxyError(0, "network_error", `proxy unreachable: ${message}`);
|
|
23052
|
+
translateFetchError(err);
|
|
22953
23053
|
}
|
|
22954
23054
|
if (!response.ok) {
|
|
22955
23055
|
const env = await readErrorEnvelope(response);
|
|
@@ -23021,20 +23121,18 @@ function createProxyClient(cfg) {
|
|
|
23021
23121
|
const url2 = `${base}/api/site/${encodeURIComponent(req.site)}/alias/${encodeURIComponent(req.mode)}`;
|
|
23022
23122
|
let response;
|
|
23023
23123
|
try {
|
|
23024
|
-
response = await fetchImpl(
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
|
|
23028
|
-
|
|
23029
|
-
|
|
23030
|
-
|
|
23031
|
-
|
|
23032
|
-
|
|
23033
|
-
throw new ProxyError(
|
|
23034
|
-
0,
|
|
23035
|
-
"network_error",
|
|
23036
|
-
`proxy unreachable: ${message}`
|
|
23124
|
+
response = await fetchImpl(
|
|
23125
|
+
url2,
|
|
23126
|
+
withTimeoutSignal({
|
|
23127
|
+
method: "GET",
|
|
23128
|
+
headers: {
|
|
23129
|
+
Authorization: await userBearer(),
|
|
23130
|
+
Accept: "application/json"
|
|
23131
|
+
}
|
|
23132
|
+
})
|
|
23037
23133
|
);
|
|
23134
|
+
} catch (err) {
|
|
23135
|
+
translateFetchError(err);
|
|
23038
23136
|
}
|
|
23039
23137
|
if (response.status === 404) return null;
|
|
23040
23138
|
if (!response.ok) {
|
|
@@ -23278,6 +23376,103 @@ function buildErrorEnvelope(command, code, message, issues) {
|
|
|
23278
23376
|
};
|
|
23279
23377
|
}
|
|
23280
23378
|
|
|
23379
|
+
// src/output/redact.ts
|
|
23380
|
+
var AWS_KEY_PREFIX_PATTERN = /(?:AKIA|ASIA|AROA|AIDA|ACCA|ANPA|ABIA|AGPA)[A-Z0-9]{12,}/g;
|
|
23381
|
+
var URL_CREDS_PATTERN = /https?:\/\/[^@\s]+@/g;
|
|
23382
|
+
var CREDENTIAL_CONTEXT_PATTERN = /(?:access_key_id|secret_access_key|accessKeyId|secretAccessKey|secret|password|token|key|credential|auth)\s*[=:]\s*([A-Za-z0-9/+=]{21,})/gi;
|
|
23383
|
+
var HEX_CREDENTIAL_CONTEXT_PATTERN = /(?:secret|password|token|key|credential|auth|access_key_id|secret_access_key)\s*[=:]\s*([a-f0-9]{32,})/gi;
|
|
23384
|
+
var JSON_CREDENTIAL_PATTERN = /"(?:secret|password|token|key|credential|auth|access_key_id|secret_access_key|accessKeyId|secretAccessKey)"\s*:\s*"[^"]+"/gi;
|
|
23385
|
+
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/gi;
|
|
23386
|
+
var CREDENTIAL_KEY_PATTERN = /(?:secret|password|token|key|credential|auth)/i;
|
|
23387
|
+
var EXACT_CREDENTIAL_KEYS = /* @__PURE__ */ new Set([
|
|
23388
|
+
"accesskeyid",
|
|
23389
|
+
"secretaccesskey",
|
|
23390
|
+
"access_key_id",
|
|
23391
|
+
"secret_access_key"
|
|
23392
|
+
]);
|
|
23393
|
+
var STANDALONE_LONG_SECRET = /^[A-Za-z0-9/+=]{21,}$/;
|
|
23394
|
+
function maskAwsKey(match) {
|
|
23395
|
+
return match.slice(0, 4) + "****" + match.slice(-4);
|
|
23396
|
+
}
|
|
23397
|
+
function maskUrlCreds(match) {
|
|
23398
|
+
const atIndex = match.lastIndexOf("@");
|
|
23399
|
+
const protocolEnd = match.indexOf("://") + 3;
|
|
23400
|
+
return match.slice(0, protocolEnd) + "****:****@" + match.slice(atIndex + 1);
|
|
23401
|
+
}
|
|
23402
|
+
function redact(value) {
|
|
23403
|
+
let result = value;
|
|
23404
|
+
result = result.replace(URL_CREDS_PATTERN, maskUrlCreds);
|
|
23405
|
+
result = result.replace(AWS_KEY_PREFIX_PATTERN, maskAwsKey);
|
|
23406
|
+
result = result.replace(BEARER_PATTERN, "Bearer ****");
|
|
23407
|
+
result = result.replace(JSON_CREDENTIAL_PATTERN, (match) => {
|
|
23408
|
+
const colonIndex = match.indexOf(":");
|
|
23409
|
+
return match.slice(0, colonIndex + 1) + '"****"';
|
|
23410
|
+
});
|
|
23411
|
+
result = result.replace(
|
|
23412
|
+
CREDENTIAL_CONTEXT_PATTERN,
|
|
23413
|
+
(_match, _secret, _offset, _full) => {
|
|
23414
|
+
const eqIndex = _match.indexOf("=");
|
|
23415
|
+
const colonIndex = _match.indexOf(":");
|
|
23416
|
+
const sepIndex = eqIndex >= 0 && colonIndex >= 0 ? Math.min(eqIndex, colonIndex) : eqIndex >= 0 ? eqIndex : colonIndex;
|
|
23417
|
+
const prefix = _match.slice(0, sepIndex + 1);
|
|
23418
|
+
return prefix + "****";
|
|
23419
|
+
}
|
|
23420
|
+
);
|
|
23421
|
+
result = result.replace(HEX_CREDENTIAL_CONTEXT_PATTERN, (_match, _secret) => {
|
|
23422
|
+
const eqIndex = _match.indexOf("=");
|
|
23423
|
+
const colonIndex = _match.indexOf(":");
|
|
23424
|
+
const sepIndex = eqIndex >= 0 && colonIndex >= 0 ? Math.min(eqIndex, colonIndex) : eqIndex >= 0 ? eqIndex : colonIndex;
|
|
23425
|
+
const prefix = _match.slice(0, sepIndex + 1);
|
|
23426
|
+
return prefix + "****";
|
|
23427
|
+
});
|
|
23428
|
+
return result;
|
|
23429
|
+
}
|
|
23430
|
+
function redactValue(value, keyName) {
|
|
23431
|
+
if (typeof value === "string") {
|
|
23432
|
+
if (keyName && EXACT_CREDENTIAL_KEYS.has(keyName.toLowerCase())) {
|
|
23433
|
+
return "****";
|
|
23434
|
+
}
|
|
23435
|
+
const redacted = redact(value);
|
|
23436
|
+
if (redacted === value && keyName && CREDENTIAL_KEY_PATTERN.test(keyName) && STANDALONE_LONG_SECRET.test(value)) {
|
|
23437
|
+
return "****";
|
|
23438
|
+
}
|
|
23439
|
+
return redacted;
|
|
23440
|
+
}
|
|
23441
|
+
if (Array.isArray(value)) {
|
|
23442
|
+
return value.map((v) => redactValue(v, keyName));
|
|
23443
|
+
}
|
|
23444
|
+
if (value !== null && typeof value === "object") {
|
|
23445
|
+
return redactObject(value);
|
|
23446
|
+
}
|
|
23447
|
+
return value;
|
|
23448
|
+
}
|
|
23449
|
+
function redactObject(obj) {
|
|
23450
|
+
const result = {};
|
|
23451
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
23452
|
+
result[key] = redactValue(value, key);
|
|
23453
|
+
}
|
|
23454
|
+
return result;
|
|
23455
|
+
}
|
|
23456
|
+
|
|
23457
|
+
// src/output/format.ts
|
|
23458
|
+
function outputError(ctx, code, message, optsOrIssues) {
|
|
23459
|
+
const opts = Array.isArray(optsOrIssues) ? { issues: optsOrIssues } : optsOrIssues ?? {};
|
|
23460
|
+
const redactedMessage = redact(message);
|
|
23461
|
+
const redactedIssues = opts.issues?.map(redact);
|
|
23462
|
+
if (ctx.json) {
|
|
23463
|
+
const envelope = buildErrorEnvelope(
|
|
23464
|
+
ctx.command,
|
|
23465
|
+
code,
|
|
23466
|
+
redactedMessage,
|
|
23467
|
+
redactedIssues
|
|
23468
|
+
);
|
|
23469
|
+
const payload = opts.extras ? { ...envelope, ...redactObject(opts.extras) } : envelope;
|
|
23470
|
+
process.stdout.write(JSON.stringify(payload) + "\n");
|
|
23471
|
+
} else {
|
|
23472
|
+
(opts.logError ?? ((m) => O2.error(m)))(redactedMessage);
|
|
23473
|
+
}
|
|
23474
|
+
}
|
|
23475
|
+
|
|
23281
23476
|
// src/commands/deploy.ts
|
|
23282
23477
|
var defaultReadPlatformYaml = async (cwd) => {
|
|
23283
23478
|
return (0, import_promises4.readFile)((0, import_node_path5.resolve)(cwd, "platform.yaml"), "utf-8");
|
|
@@ -23371,6 +23566,7 @@ async function deploy(options, deps = {}) {
|
|
|
23371
23566
|
const build = deps.runBuild ?? runBuild;
|
|
23372
23567
|
const walk = deps.walkFiles ?? walkFiles;
|
|
23373
23568
|
const upload = deps.uploadFiles ?? uploadFiles;
|
|
23569
|
+
const mkSpinner = deps.createSpinner ?? (() => fe());
|
|
23374
23570
|
const success2 = deps.logSuccess ?? ((s) => O2.success(s));
|
|
23375
23571
|
const info = deps.logInfo ?? ((s) => O2.info(s));
|
|
23376
23572
|
const warn = deps.logWarn ?? ((s) => O2.warn(s));
|
|
@@ -23387,7 +23583,8 @@ async function deploy(options, deps = {}) {
|
|
|
23387
23583
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL;
|
|
23388
23584
|
const client = mkClient({
|
|
23389
23585
|
baseUrl,
|
|
23390
|
-
getAuthToken: () => identity.token
|
|
23586
|
+
getAuthToken: () => identity.token,
|
|
23587
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
23391
23588
|
});
|
|
23392
23589
|
let me2;
|
|
23393
23590
|
try {
|
|
@@ -23438,17 +23635,22 @@ async function deploy(options, deps = {}) {
|
|
|
23438
23635
|
} catch (err) {
|
|
23439
23636
|
rethrowProxy("deploy init failed", err);
|
|
23440
23637
|
}
|
|
23638
|
+
const spin = options.json ? null : mkSpinner();
|
|
23639
|
+
spin?.start(`Uploading 0/${filtered.length} files`);
|
|
23441
23640
|
const uploadResult = await upload({
|
|
23442
23641
|
client,
|
|
23443
23642
|
deployId: initResult.deployId,
|
|
23444
23643
|
jwt: initResult.jwt,
|
|
23445
|
-
files: filtered
|
|
23644
|
+
files: filtered,
|
|
23645
|
+
onProgress: spin ? (p2) => spin.message(`Uploading ${p2.uploaded}/${p2.total} \u2014 ${p2.current}`) : void 0
|
|
23446
23646
|
});
|
|
23447
23647
|
if (uploadResult.errors.length > 0) {
|
|
23648
|
+
spin?.error(`Upload failed: ${uploadResult.errors.length} file(s)`);
|
|
23448
23649
|
const message = `Upload partially failed: ${uploadResult.errors.length} file(s) failed:
|
|
23449
23650
|
- ${uploadResult.errors.join("\n - ")}`;
|
|
23450
23651
|
throw new PartialUploadError(message);
|
|
23451
23652
|
}
|
|
23653
|
+
spin?.stop(`Uploaded ${uploadResult.fileCount} files`);
|
|
23452
23654
|
const mode = options.promote ? "production" : "preview";
|
|
23453
23655
|
let finalizeResult;
|
|
23454
23656
|
try {
|
|
@@ -23461,6 +23663,25 @@ async function deploy(options, deps = {}) {
|
|
|
23461
23663
|
} catch (err) {
|
|
23462
23664
|
rethrowProxy("deploy finalize failed", err);
|
|
23463
23665
|
}
|
|
23666
|
+
if (options.promote && !options.json) {
|
|
23667
|
+
try {
|
|
23668
|
+
const preview = await client.getAlias({
|
|
23669
|
+
site: config2.site,
|
|
23670
|
+
mode: "preview"
|
|
23671
|
+
});
|
|
23672
|
+
if (preview && preview.deployId !== finalizeResult.deployId) {
|
|
23673
|
+
warn(
|
|
23674
|
+
`Preview alias still points to ${preview.deployId}; it will not auto-update. Run \`universe static deploy\` (without --promote) to refresh preview.`
|
|
23675
|
+
);
|
|
23676
|
+
}
|
|
23677
|
+
} catch (err) {
|
|
23678
|
+
if (err instanceof ProxyError && (err.status === 401 || err.status === 403)) {
|
|
23679
|
+
warn(
|
|
23680
|
+
`Preview alias probe got ${err.status} (${err.code}) \u2014 token may need rotation: ${err.message}`
|
|
23681
|
+
);
|
|
23682
|
+
}
|
|
23683
|
+
}
|
|
23684
|
+
}
|
|
23464
23685
|
if (options.json) {
|
|
23465
23686
|
emitJson(
|
|
23466
23687
|
buildEnvelope("deploy", true, {
|
|
@@ -23507,11 +23728,9 @@ async function deploy(options, deps = {}) {
|
|
|
23507
23728
|
code = EXIT_USAGE;
|
|
23508
23729
|
message = String(err);
|
|
23509
23730
|
}
|
|
23510
|
-
|
|
23511
|
-
|
|
23512
|
-
}
|
|
23513
|
-
error48(message);
|
|
23514
|
-
}
|
|
23731
|
+
outputError({ json: options.json, command: "deploy" }, code, message, {
|
|
23732
|
+
logError: error48
|
|
23733
|
+
});
|
|
23515
23734
|
exit(code);
|
|
23516
23735
|
}
|
|
23517
23736
|
}
|
|
@@ -23652,17 +23871,12 @@ async function login(options, deps = {}) {
|
|
|
23652
23871
|
});
|
|
23653
23872
|
} catch (err) {
|
|
23654
23873
|
const message = err instanceof Error ? err.message : String(err);
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
|
|
23658
|
-
|
|
23659
|
-
|
|
23660
|
-
|
|
23661
|
-
error: { code: EXIT_CREDENTIALS, message }
|
|
23662
|
-
});
|
|
23663
|
-
} else {
|
|
23664
|
-
error48(message);
|
|
23665
|
-
}
|
|
23874
|
+
outputError(
|
|
23875
|
+
{ json: options.json, command: "login" },
|
|
23876
|
+
EXIT_CREDENTIALS,
|
|
23877
|
+
message,
|
|
23878
|
+
{ logError: error48 }
|
|
23879
|
+
);
|
|
23666
23880
|
exit(EXIT_CREDENTIALS);
|
|
23667
23881
|
return;
|
|
23668
23882
|
}
|
|
@@ -23771,7 +23985,8 @@ async function ls(options, deps = {}) {
|
|
|
23771
23985
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL;
|
|
23772
23986
|
const client = mkClient({
|
|
23773
23987
|
baseUrl,
|
|
23774
|
-
getAuthToken: () => identity.token
|
|
23988
|
+
getAuthToken: () => identity.token,
|
|
23989
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
23775
23990
|
});
|
|
23776
23991
|
const raw = await client.siteDeploys({ site });
|
|
23777
23992
|
const sorted = [...raw].sort(
|
|
@@ -23795,11 +24010,9 @@ async function ls(options, deps = {}) {
|
|
|
23795
24010
|
success2(formatTable(deploys));
|
|
23796
24011
|
} catch (err) {
|
|
23797
24012
|
const { code, message } = wrapProxyError("ls", err);
|
|
23798
|
-
|
|
23799
|
-
|
|
23800
|
-
}
|
|
23801
|
-
error48(message);
|
|
23802
|
-
}
|
|
24013
|
+
outputError({ json: options.json, command: "ls" }, code, message, {
|
|
24014
|
+
logError: error48
|
|
24015
|
+
});
|
|
23803
24016
|
exit(code);
|
|
23804
24017
|
}
|
|
23805
24018
|
}
|
|
@@ -23855,7 +24068,8 @@ async function promote(options, deps = {}) {
|
|
|
23855
24068
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL;
|
|
23856
24069
|
const client = mkClient({
|
|
23857
24070
|
baseUrl,
|
|
23858
|
-
getAuthToken: () => identity.token
|
|
24071
|
+
getAuthToken: () => identity.token,
|
|
24072
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
23859
24073
|
});
|
|
23860
24074
|
let result;
|
|
23861
24075
|
if (options.from) {
|
|
@@ -23953,16 +24167,11 @@ async function promote(options, deps = {}) {
|
|
|
23953
24167
|
}
|
|
23954
24168
|
} catch (err) {
|
|
23955
24169
|
const { code, message } = wrapProxyError("promote", err);
|
|
23956
|
-
|
|
23957
|
-
|
|
23958
|
-
|
|
23959
|
-
|
|
23960
|
-
|
|
23961
|
-
emitJson5(envelope);
|
|
23962
|
-
}
|
|
23963
|
-
} else {
|
|
23964
|
-
error48(message);
|
|
23965
|
-
}
|
|
24170
|
+
const extras = err instanceof AliasDriftError ? { current: err.current } : void 0;
|
|
24171
|
+
outputError({ json: options.json, command: "promote" }, code, message, {
|
|
24172
|
+
logError: error48,
|
|
24173
|
+
extras
|
|
24174
|
+
});
|
|
23966
24175
|
exit(code);
|
|
23967
24176
|
}
|
|
23968
24177
|
}
|
|
@@ -24023,7 +24232,8 @@ async function rollback(options, deps = {}) {
|
|
|
24023
24232
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL;
|
|
24024
24233
|
const client = mkClient({
|
|
24025
24234
|
baseUrl,
|
|
24026
|
-
getAuthToken: () => identity.token
|
|
24235
|
+
getAuthToken: () => identity.token,
|
|
24236
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
24027
24237
|
});
|
|
24028
24238
|
const to = options.to.trim();
|
|
24029
24239
|
const prod = await client.getAlias({
|
|
@@ -24076,16 +24286,11 @@ async function rollback(options, deps = {}) {
|
|
|
24076
24286
|
}
|
|
24077
24287
|
} catch (err) {
|
|
24078
24288
|
const { code, message } = wrapProxyError("rollback", err);
|
|
24079
|
-
|
|
24080
|
-
|
|
24081
|
-
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
emitJson6(envelope);
|
|
24085
|
-
}
|
|
24086
|
-
} else {
|
|
24087
|
-
error48(message);
|
|
24088
|
-
}
|
|
24289
|
+
const extras = err instanceof AliasDriftError ? { current: err.current } : void 0;
|
|
24290
|
+
outputError({ json: options.json, command: "rollback" }, code, message, {
|
|
24291
|
+
logError: error48,
|
|
24292
|
+
extras
|
|
24293
|
+
});
|
|
24089
24294
|
exit(code);
|
|
24090
24295
|
}
|
|
24091
24296
|
}
|
|
@@ -24105,18 +24310,20 @@ async function whoami(options, deps = {}) {
|
|
|
24105
24310
|
const identity = await resolve6({ env });
|
|
24106
24311
|
if (!identity) {
|
|
24107
24312
|
const msg = "No GitHub identity available. Run `universe login`, set $GITHUB_TOKEN, or install the gh CLI.";
|
|
24108
|
-
|
|
24109
|
-
|
|
24110
|
-
|
|
24111
|
-
|
|
24112
|
-
|
|
24313
|
+
outputError(
|
|
24314
|
+
{ json: options.json, command: "whoami" },
|
|
24315
|
+
EXIT_CREDENTIALS,
|
|
24316
|
+
msg,
|
|
24317
|
+
{ logError: error48 }
|
|
24318
|
+
);
|
|
24113
24319
|
exit(EXIT_CREDENTIALS);
|
|
24114
24320
|
return;
|
|
24115
24321
|
}
|
|
24116
24322
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL2;
|
|
24117
24323
|
const client = mkClient({
|
|
24118
24324
|
baseUrl,
|
|
24119
|
-
getAuthToken: () => identity.token
|
|
24325
|
+
getAuthToken: () => identity.token,
|
|
24326
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
24120
24327
|
});
|
|
24121
24328
|
try {
|
|
24122
24329
|
const result = await client.whoami();
|
|
@@ -24142,11 +24349,9 @@ async function whoami(options, deps = {}) {
|
|
|
24142
24349
|
} catch (err) {
|
|
24143
24350
|
const exitCode = err instanceof CliError ? err.exitCode : EXIT_CREDENTIALS;
|
|
24144
24351
|
const message = err instanceof ProxyError ? `whoami failed (${err.code}): ${err.message}` : err instanceof Error ? err.message : String(err);
|
|
24145
|
-
|
|
24146
|
-
|
|
24147
|
-
}
|
|
24148
|
-
error48(message);
|
|
24149
|
-
}
|
|
24352
|
+
outputError({ json: options.json, command: "whoami" }, exitCode, message, {
|
|
24353
|
+
logError: error48
|
|
24354
|
+
});
|
|
24150
24355
|
exit(exitCode);
|
|
24151
24356
|
}
|
|
24152
24357
|
}
|
|
@@ -24173,7 +24378,8 @@ async function setupClient(deps) {
|
|
|
24173
24378
|
const baseUrl = env["UNIVERSE_PROXY_URL"] ?? DEFAULT_PROXY_URL;
|
|
24174
24379
|
const client = mkClient({
|
|
24175
24380
|
baseUrl,
|
|
24176
|
-
getAuthToken: () => identity.token
|
|
24381
|
+
getAuthToken: () => identity.token,
|
|
24382
|
+
timeoutMs: parseFetchTimeoutMs(env)
|
|
24177
24383
|
});
|
|
24178
24384
|
return { client, identitySource: identity.source };
|
|
24179
24385
|
}
|
|
@@ -24200,7 +24406,7 @@ async function ls2(options, deps = {}) {
|
|
|
24200
24406
|
const error48 = deps.logError ?? ((s) => O2.error(s));
|
|
24201
24407
|
const exit = deps.exit ?? exitWithCode;
|
|
24202
24408
|
try {
|
|
24203
|
-
const { client } = await setupClient(deps);
|
|
24409
|
+
const { client, identitySource } = await setupClient(deps);
|
|
24204
24410
|
let rows = await client.listSites();
|
|
24205
24411
|
let scope = "all";
|
|
24206
24412
|
if (options.mine) {
|
|
@@ -24214,7 +24420,8 @@ async function ls2(options, deps = {}) {
|
|
|
24214
24420
|
buildEnvelope(command, true, {
|
|
24215
24421
|
count: rows.length,
|
|
24216
24422
|
scope,
|
|
24217
|
-
sites: rows
|
|
24423
|
+
sites: rows,
|
|
24424
|
+
identitySource
|
|
24218
24425
|
})
|
|
24219
24426
|
);
|
|
24220
24427
|
} else {
|
|
@@ -24222,11 +24429,9 @@ async function ls2(options, deps = {}) {
|
|
|
24222
24429
|
}
|
|
24223
24430
|
} catch (err) {
|
|
24224
24431
|
const { code, message } = wrapProxyError(command, err);
|
|
24225
|
-
|
|
24226
|
-
|
|
24227
|
-
}
|
|
24228
|
-
error48(message);
|
|
24229
|
-
}
|
|
24432
|
+
outputError({ json: options.json, command }, code, message, {
|
|
24433
|
+
logError: error48
|
|
24434
|
+
});
|
|
24230
24435
|
exit(code);
|
|
24231
24436
|
}
|
|
24232
24437
|
}
|
|
@@ -24242,7 +24447,7 @@ async function register(options, deps = {}) {
|
|
|
24242
24447
|
throw new UsageError("slug is required (positional argument)");
|
|
24243
24448
|
}
|
|
24244
24449
|
const teams = parseTeamsFlag(options.team);
|
|
24245
|
-
const { client } = await setupClient(deps);
|
|
24450
|
+
const { client, identitySource } = await setupClient(deps);
|
|
24246
24451
|
const row = await client.registerSite({
|
|
24247
24452
|
slug: options.slug,
|
|
24248
24453
|
teams: teams.length > 0 ? teams : void 0
|
|
@@ -24253,7 +24458,8 @@ async function register(options, deps = {}) {
|
|
|
24253
24458
|
slug: row.slug,
|
|
24254
24459
|
teams: row.teams,
|
|
24255
24460
|
createdAt: row.createdAt,
|
|
24256
|
-
createdBy: row.createdBy
|
|
24461
|
+
createdBy: row.createdBy,
|
|
24462
|
+
identitySource
|
|
24257
24463
|
})
|
|
24258
24464
|
);
|
|
24259
24465
|
} else {
|
|
@@ -24270,11 +24476,9 @@ async function register(options, deps = {}) {
|
|
|
24270
24476
|
}
|
|
24271
24477
|
} catch (err) {
|
|
24272
24478
|
const { code, message } = wrapProxyError(command, err);
|
|
24273
|
-
|
|
24274
|
-
|
|
24275
|
-
}
|
|
24276
|
-
error48(message);
|
|
24277
|
-
}
|
|
24479
|
+
outputError({ json: options.json, command }, code, message, {
|
|
24480
|
+
logError: error48
|
|
24481
|
+
});
|
|
24278
24482
|
exit(code);
|
|
24279
24483
|
}
|
|
24280
24484
|
}
|
|
@@ -24289,13 +24493,14 @@ async function rm2(options, deps = {}) {
|
|
|
24289
24493
|
if (!options.slug || options.slug.trim().length === 0) {
|
|
24290
24494
|
throw new UsageError("slug is required (positional argument)");
|
|
24291
24495
|
}
|
|
24292
|
-
const { client } = await setupClient(deps);
|
|
24496
|
+
const { client, identitySource } = await setupClient(deps);
|
|
24293
24497
|
await client.deleteSite({ slug: options.slug });
|
|
24294
24498
|
if (options.json) {
|
|
24295
24499
|
emitJson8(
|
|
24296
24500
|
buildEnvelope(command, true, {
|
|
24297
24501
|
slug: options.slug,
|
|
24298
|
-
deleted: true
|
|
24502
|
+
deleted: true,
|
|
24503
|
+
identitySource
|
|
24299
24504
|
})
|
|
24300
24505
|
);
|
|
24301
24506
|
} else {
|
|
@@ -24310,11 +24515,9 @@ async function rm2(options, deps = {}) {
|
|
|
24310
24515
|
}
|
|
24311
24516
|
} catch (err) {
|
|
24312
24517
|
const { code, message } = wrapProxyError(command, err);
|
|
24313
|
-
|
|
24314
|
-
|
|
24315
|
-
}
|
|
24316
|
-
error48(message);
|
|
24317
|
-
}
|
|
24518
|
+
outputError({ json: options.json, command }, code, message, {
|
|
24519
|
+
logError: error48
|
|
24520
|
+
});
|
|
24318
24521
|
exit(code);
|
|
24319
24522
|
}
|
|
24320
24523
|
}
|
|
@@ -24335,7 +24538,7 @@ async function update(options, deps = {}) {
|
|
|
24335
24538
|
"--team is required with at least one slug; use `sites rm` to remove a site"
|
|
24336
24539
|
);
|
|
24337
24540
|
}
|
|
24338
|
-
const { client } = await setupClient(deps);
|
|
24541
|
+
const { client, identitySource } = await setupClient(deps);
|
|
24339
24542
|
const row = await client.updateSite({
|
|
24340
24543
|
slug: options.slug,
|
|
24341
24544
|
teams
|
|
@@ -24345,7 +24548,8 @@ async function update(options, deps = {}) {
|
|
|
24345
24548
|
buildEnvelope(command, true, {
|
|
24346
24549
|
slug: row.slug,
|
|
24347
24550
|
teams: row.teams,
|
|
24348
|
-
updatedAt: row.updatedAt
|
|
24551
|
+
updatedAt: row.updatedAt,
|
|
24552
|
+
identitySource
|
|
24349
24553
|
})
|
|
24350
24554
|
);
|
|
24351
24555
|
} else {
|
|
@@ -24361,78 +24565,15 @@ async function update(options, deps = {}) {
|
|
|
24361
24565
|
}
|
|
24362
24566
|
} catch (err) {
|
|
24363
24567
|
const { code, message } = wrapProxyError(command, err);
|
|
24364
|
-
|
|
24365
|
-
|
|
24366
|
-
}
|
|
24367
|
-
error48(message);
|
|
24368
|
-
}
|
|
24568
|
+
outputError({ json: options.json, command }, code, message, {
|
|
24569
|
+
logError: error48
|
|
24570
|
+
});
|
|
24369
24571
|
exit(code);
|
|
24370
24572
|
}
|
|
24371
24573
|
}
|
|
24372
24574
|
|
|
24373
|
-
// src/output/redact.ts
|
|
24374
|
-
var AWS_KEY_PREFIX_PATTERN = /(?:AKIA|ASIA|AROA|AIDA|ACCA|ANPA|ABIA|AGPA)[A-Z0-9]{12,}/g;
|
|
24375
|
-
var URL_CREDS_PATTERN = /https?:\/\/[^@\s]+@/g;
|
|
24376
|
-
var CREDENTIAL_CONTEXT_PATTERN = /(?:access_key_id|secret_access_key|accessKeyId|secretAccessKey|secret|password|token|key|credential|auth)\s*[=:]\s*([A-Za-z0-9/+=]{21,})/gi;
|
|
24377
|
-
var HEX_CREDENTIAL_CONTEXT_PATTERN = /(?:secret|password|token|key|credential|auth|access_key_id|secret_access_key)\s*[=:]\s*([a-f0-9]{32,})/gi;
|
|
24378
|
-
var JSON_CREDENTIAL_PATTERN = /"(?:secret|password|token|key|credential|auth|access_key_id|secret_access_key|accessKeyId|secretAccessKey)"\s*:\s*"[^"]+"/gi;
|
|
24379
|
-
var BEARER_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]+/gi;
|
|
24380
|
-
function maskAwsKey(match) {
|
|
24381
|
-
return match.slice(0, 4) + "****" + match.slice(-4);
|
|
24382
|
-
}
|
|
24383
|
-
function maskUrlCreds(match) {
|
|
24384
|
-
const atIndex = match.lastIndexOf("@");
|
|
24385
|
-
const protocolEnd = match.indexOf("://") + 3;
|
|
24386
|
-
return match.slice(0, protocolEnd) + "****:****@" + match.slice(atIndex + 1);
|
|
24387
|
-
}
|
|
24388
|
-
function redact(value) {
|
|
24389
|
-
let result = value;
|
|
24390
|
-
result = result.replace(URL_CREDS_PATTERN, maskUrlCreds);
|
|
24391
|
-
result = result.replace(AWS_KEY_PREFIX_PATTERN, maskAwsKey);
|
|
24392
|
-
result = result.replace(BEARER_PATTERN, "Bearer ****");
|
|
24393
|
-
result = result.replace(JSON_CREDENTIAL_PATTERN, (match) => {
|
|
24394
|
-
const colonIndex = match.indexOf(":");
|
|
24395
|
-
return match.slice(0, colonIndex + 1) + '"****"';
|
|
24396
|
-
});
|
|
24397
|
-
result = result.replace(
|
|
24398
|
-
CREDENTIAL_CONTEXT_PATTERN,
|
|
24399
|
-
(_match, _secret, _offset, _full) => {
|
|
24400
|
-
const eqIndex = _match.indexOf("=");
|
|
24401
|
-
const colonIndex = _match.indexOf(":");
|
|
24402
|
-
const sepIndex = eqIndex >= 0 && colonIndex >= 0 ? Math.min(eqIndex, colonIndex) : eqIndex >= 0 ? eqIndex : colonIndex;
|
|
24403
|
-
const prefix = _match.slice(0, sepIndex + 1);
|
|
24404
|
-
return prefix + "****";
|
|
24405
|
-
}
|
|
24406
|
-
);
|
|
24407
|
-
result = result.replace(HEX_CREDENTIAL_CONTEXT_PATTERN, (_match, _secret) => {
|
|
24408
|
-
const eqIndex = _match.indexOf("=");
|
|
24409
|
-
const colonIndex = _match.indexOf(":");
|
|
24410
|
-
const sepIndex = eqIndex >= 0 && colonIndex >= 0 ? Math.min(eqIndex, colonIndex) : eqIndex >= 0 ? eqIndex : colonIndex;
|
|
24411
|
-
const prefix = _match.slice(0, sepIndex + 1);
|
|
24412
|
-
return prefix + "****";
|
|
24413
|
-
});
|
|
24414
|
-
return result;
|
|
24415
|
-
}
|
|
24416
|
-
|
|
24417
|
-
// src/output/format.ts
|
|
24418
|
-
function outputError(ctx, code, message, issues) {
|
|
24419
|
-
const redactedMessage = redact(message);
|
|
24420
|
-
const redactedIssues = issues?.map(redact);
|
|
24421
|
-
if (ctx.json) {
|
|
24422
|
-
const envelope = buildErrorEnvelope(
|
|
24423
|
-
ctx.command,
|
|
24424
|
-
code,
|
|
24425
|
-
redactedMessage,
|
|
24426
|
-
redactedIssues
|
|
24427
|
-
);
|
|
24428
|
-
process.stdout.write(JSON.stringify(envelope) + "\n");
|
|
24429
|
-
} else {
|
|
24430
|
-
O2.error(redactedMessage);
|
|
24431
|
-
}
|
|
24432
|
-
}
|
|
24433
|
-
|
|
24434
24575
|
// src/cli.ts
|
|
24435
|
-
var version2 = true ? "0.
|
|
24576
|
+
var version2 = true ? "0.7.0" : "0.0.0";
|
|
24436
24577
|
function handleActionError(command, json2, err) {
|
|
24437
24578
|
const ctx = { json: json2, command };
|
|
24438
24579
|
const message = err instanceof Error ? err.message : "unknown error";
|