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