@dosu/cli 0.13.0 → 0.13.1
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/bin/dosu.js +129 -6
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4341,7 +4341,7 @@ function getSupabaseAnonKey() {
|
|
|
4341
4341
|
function getVersionString() {
|
|
4342
4342
|
return `v${VERSION}`;
|
|
4343
4343
|
}
|
|
4344
|
-
var VERSION = "0.13.
|
|
4344
|
+
var VERSION = "0.13.1";
|
|
4345
4345
|
|
|
4346
4346
|
// src/debug/logger.ts
|
|
4347
4347
|
import {
|
|
@@ -9473,7 +9473,85 @@ var init_github_doc_import_step = __esm(() => {
|
|
|
9473
9473
|
init_github_doc_import_prompt();
|
|
9474
9474
|
});
|
|
9475
9475
|
|
|
9476
|
+
// src/auth/errors.ts
|
|
9477
|
+
var exports_errors = {};
|
|
9478
|
+
__export(exports_errors, {
|
|
9479
|
+
OAuthCallbackError: () => OAuthCallbackError
|
|
9480
|
+
});
|
|
9481
|
+
var OAuthCallbackError;
|
|
9482
|
+
var init_errors = __esm(() => {
|
|
9483
|
+
OAuthCallbackError = class OAuthCallbackError extends Error {
|
|
9484
|
+
error;
|
|
9485
|
+
errorCode;
|
|
9486
|
+
errorDescription;
|
|
9487
|
+
constructor(message, details = {}) {
|
|
9488
|
+
super(message);
|
|
9489
|
+
this.name = "OAuthCallbackError";
|
|
9490
|
+
this.error = details.error;
|
|
9491
|
+
this.errorCode = details.errorCode;
|
|
9492
|
+
this.errorDescription = details.errorDescription;
|
|
9493
|
+
}
|
|
9494
|
+
get userMessage() {
|
|
9495
|
+
const desc = this.errorDescription ?? this.message;
|
|
9496
|
+
if (this.errorCode === "bad_oauth_state" || /state/i.test(desc)) {
|
|
9497
|
+
return `Authentication failed: ${desc}. Run \`dosu login\` again.`;
|
|
9498
|
+
}
|
|
9499
|
+
return `Authentication failed: ${desc}`;
|
|
9500
|
+
}
|
|
9501
|
+
};
|
|
9502
|
+
});
|
|
9503
|
+
|
|
9476
9504
|
// src/auth/server.ts
|
|
9505
|
+
function escapeHtml(value) {
|
|
9506
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
9507
|
+
}
|
|
9508
|
+
function buildErrorHtml(message) {
|
|
9509
|
+
const safe = escapeHtml(message);
|
|
9510
|
+
return `<!DOCTYPE html>
|
|
9511
|
+
<html lang="en">
|
|
9512
|
+
<head>
|
|
9513
|
+
<meta charset="UTF-8">
|
|
9514
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9515
|
+
<title>Dosu CLI - Authentication Failed</title>
|
|
9516
|
+
<style>
|
|
9517
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9518
|
+
body {
|
|
9519
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
9520
|
+
background: #fafafa;
|
|
9521
|
+
color: #171717;
|
|
9522
|
+
min-height: 100vh;
|
|
9523
|
+
display: flex;
|
|
9524
|
+
align-items: center;
|
|
9525
|
+
justify-content: center;
|
|
9526
|
+
padding: 20px;
|
|
9527
|
+
}
|
|
9528
|
+
.container {
|
|
9529
|
+
max-width: 480px;
|
|
9530
|
+
width: 100%;
|
|
9531
|
+
text-align: center;
|
|
9532
|
+
background: white;
|
|
9533
|
+
border: 1px solid #e5e7eb;
|
|
9534
|
+
border-radius: 12px;
|
|
9535
|
+
padding: 40px 32px;
|
|
9536
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
9537
|
+
}
|
|
9538
|
+
h1 { font-size: 20px; font-weight: 600; color: #b91c1c; margin-bottom: 12px; }
|
|
9539
|
+
p { font-size: 14px; color: #4b5563; line-height: 1.5; }
|
|
9540
|
+
.detail { margin-top: 16px; padding: 12px; background: #fef2f2; border-radius: 8px; color: #991b1b; font-size: 13px; }
|
|
9541
|
+
.next { margin-top: 20px; color: #6b7280; font-size: 13px; }
|
|
9542
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: #f3f4f6; padding: 2px 6px; border-radius: 4px; color: #111827; }
|
|
9543
|
+
</style>
|
|
9544
|
+
</head>
|
|
9545
|
+
<body>
|
|
9546
|
+
<div class="container">
|
|
9547
|
+
<h1>Authentication Failed</h1>
|
|
9548
|
+
<p>The OAuth flow could not be completed.</p>
|
|
9549
|
+
<div class="detail">${safe}</div>
|
|
9550
|
+
<p class="next">You can close this tab. In your terminal, run <code>dosu login</code> again.</p>
|
|
9551
|
+
</div>
|
|
9552
|
+
</body>
|
|
9553
|
+
</html>`;
|
|
9554
|
+
}
|
|
9477
9555
|
function buildSuccessHtml(email) {
|
|
9478
9556
|
const emailLine = email ? `<p class="email">Signed in as <strong>${email.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</strong></p>` : "";
|
|
9479
9557
|
return `<!DOCTYPE html>
|
|
@@ -9597,8 +9675,10 @@ h1 {
|
|
|
9597
9675
|
}
|
|
9598
9676
|
async function startCallbackServer() {
|
|
9599
9677
|
let resolveToken;
|
|
9600
|
-
|
|
9678
|
+
let rejectToken;
|
|
9679
|
+
const tokenPromise = new Promise((resolve, reject) => {
|
|
9601
9680
|
resolveToken = resolve;
|
|
9681
|
+
rejectToken = reject;
|
|
9602
9682
|
});
|
|
9603
9683
|
const http = __require("node:http");
|
|
9604
9684
|
const httpServer = http.createServer((req, res) => {
|
|
@@ -9612,6 +9692,22 @@ async function startCallbackServer() {
|
|
|
9612
9692
|
res.end("Not Found");
|
|
9613
9693
|
return;
|
|
9614
9694
|
}
|
|
9695
|
+
const errorParam = url.searchParams.get("error");
|
|
9696
|
+
const errorCodeParam = url.searchParams.get("error_code");
|
|
9697
|
+
const errorDescriptionParam = url.searchParams.get("error_description");
|
|
9698
|
+
if (errorParam || errorCodeParam || errorDescriptionParam) {
|
|
9699
|
+
const rawDescription = errorDescriptionParam ?? errorCodeParam ?? errorParam ?? "OAuth authentication failed";
|
|
9700
|
+
const sanitized = rawDescription.replace(/<[^>]*>/g, "");
|
|
9701
|
+
logger.warn("auth.server", `OAuth callback received error: code=${errorCodeParam ?? "n/a"} description=${sanitized}`);
|
|
9702
|
+
rejectToken?.(new OAuthCallbackError(sanitized, {
|
|
9703
|
+
error: errorParam ?? undefined,
|
|
9704
|
+
errorCode: errorCodeParam ?? undefined,
|
|
9705
|
+
errorDescription: sanitized
|
|
9706
|
+
}));
|
|
9707
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
9708
|
+
res.end(buildErrorHtml(rawDescription));
|
|
9709
|
+
return;
|
|
9710
|
+
}
|
|
9615
9711
|
const accessToken = url.searchParams.get("access_token");
|
|
9616
9712
|
const refreshToken = url.searchParams.get("refresh_token");
|
|
9617
9713
|
const expiresIn = url.searchParams.get("expires_in");
|
|
@@ -9719,6 +9815,7 @@ if (hash) {
|
|
|
9719
9815
|
</html>`;
|
|
9720
9816
|
var init_server = __esm(() => {
|
|
9721
9817
|
init_logger();
|
|
9818
|
+
init_errors();
|
|
9722
9819
|
});
|
|
9723
9820
|
|
|
9724
9821
|
// src/auth/flow.ts
|
|
@@ -9739,9 +9836,9 @@ async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}) {
|
|
|
9739
9836
|
logger.info("auth.flow", "Browser open command executed");
|
|
9740
9837
|
const timeout = new Promise((_3, reject) => {
|
|
9741
9838
|
timeoutId = setTimeout(() => {
|
|
9742
|
-
logger.warn("auth.flow", "Authentication timed out (
|
|
9743
|
-
reject(new Error("
|
|
9744
|
-
},
|
|
9839
|
+
logger.warn("auth.flow", "Authentication timed out (8min)");
|
|
9840
|
+
reject(new Error("Authentication did not complete within 8 minutes. The OAuth state may have expired — please run `dosu login` again."));
|
|
9841
|
+
}, 480000);
|
|
9745
9842
|
});
|
|
9746
9843
|
const abort = signal ? new Promise((_3, reject) => {
|
|
9747
9844
|
signal.addEventListener("abort", () => {
|
|
@@ -10106,6 +10203,16 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
10106
10203
|
} catch (err) {
|
|
10107
10204
|
const msg = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
10108
10205
|
logger.error("setup", `Auth failed: ${msg}`);
|
|
10206
|
+
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
10207
|
+
if (err instanceof OAuthCallbackError2) {
|
|
10208
|
+
M2.error(err.userMessage);
|
|
10209
|
+
if (onboardingRunID) {
|
|
10210
|
+
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_failed", {
|
|
10211
|
+
reason: err.errorCode ?? err.errorDescription ?? "oauth_callback_error"
|
|
10212
|
+
});
|
|
10213
|
+
}
|
|
10214
|
+
return null;
|
|
10215
|
+
}
|
|
10109
10216
|
M2.error(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10110
10217
|
if (onboardingRunID) {
|
|
10111
10218
|
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_failed", {
|
|
@@ -10791,6 +10898,11 @@ async function handleAuthenticate(cfg) {
|
|
|
10791
10898
|
cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
|
|
10792
10899
|
saveConfig(cfg);
|
|
10793
10900
|
} catch (err) {
|
|
10901
|
+
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
10902
|
+
if (err instanceof OAuthCallbackError2) {
|
|
10903
|
+
M2.error(err.userMessage);
|
|
10904
|
+
return;
|
|
10905
|
+
}
|
|
10794
10906
|
M2.error(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10795
10907
|
}
|
|
10796
10908
|
}
|
|
@@ -12383,7 +12495,18 @@ function createProgram() {
|
|
|
12383
12495
|
}
|
|
12384
12496
|
console.log("Opening browser for authentication...");
|
|
12385
12497
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12386
|
-
const
|
|
12498
|
+
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
12499
|
+
let token;
|
|
12500
|
+
try {
|
|
12501
|
+
token = await startOAuthFlow2();
|
|
12502
|
+
} catch (err) {
|
|
12503
|
+
if (err instanceof OAuthCallbackError2) {
|
|
12504
|
+
console.error(err.userMessage);
|
|
12505
|
+
process.exitCode = 1;
|
|
12506
|
+
return;
|
|
12507
|
+
}
|
|
12508
|
+
throw err;
|
|
12509
|
+
}
|
|
12387
12510
|
cfg.access_token = token.access_token;
|
|
12388
12511
|
cfg.refresh_token = token.refresh_token;
|
|
12389
12512
|
cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
|