mobbdev 1.1.40 → 1.1.41
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/args/commands/upload_ai_blame.mjs +339 -208
- package/dist/index.mjs +211 -80
- package/package.json +1 -1
|
@@ -1371,15 +1371,141 @@ import { withFile } from "tmp-promise";
|
|
|
1371
1371
|
import z26 from "zod";
|
|
1372
1372
|
|
|
1373
1373
|
// src/commands/handleMobbLogin.ts
|
|
1374
|
-
import crypto from "crypto";
|
|
1375
|
-
import os from "os";
|
|
1376
1374
|
import chalk2 from "chalk";
|
|
1377
1375
|
import Debug6 from "debug";
|
|
1378
|
-
import open from "open";
|
|
1379
1376
|
|
|
1380
|
-
// src/
|
|
1377
|
+
// src/utils/dirname.ts
|
|
1378
|
+
import fs from "fs";
|
|
1379
|
+
import path from "path";
|
|
1380
|
+
import { fileURLToPath } from "url";
|
|
1381
|
+
function getModuleRootDir() {
|
|
1382
|
+
let manifestDir = getDirName();
|
|
1383
|
+
for (let i = 0; i < 10; i++) {
|
|
1384
|
+
const manifestPath = path.join(manifestDir, "package.json");
|
|
1385
|
+
if (fs.existsSync(manifestPath)) {
|
|
1386
|
+
return manifestDir;
|
|
1387
|
+
}
|
|
1388
|
+
manifestDir = path.join(manifestDir, "..");
|
|
1389
|
+
}
|
|
1390
|
+
throw new Error("Cannot locate package.json file");
|
|
1391
|
+
}
|
|
1392
|
+
function getDirName() {
|
|
1393
|
+
if (typeof __filename !== "undefined") {
|
|
1394
|
+
return path.dirname(__filename);
|
|
1395
|
+
} else {
|
|
1396
|
+
try {
|
|
1397
|
+
const getImportMetaUrl = new Function("return import.meta.url");
|
|
1398
|
+
const importMetaUrl = getImportMetaUrl();
|
|
1399
|
+
return path.dirname(fileURLToPath(importMetaUrl));
|
|
1400
|
+
} catch (e) {
|
|
1401
|
+
try {
|
|
1402
|
+
const err = new Error();
|
|
1403
|
+
const stack = err.stack || "";
|
|
1404
|
+
const match = stack.match(/file:\/\/[^\s)]+/);
|
|
1405
|
+
if (match) {
|
|
1406
|
+
const fileUrl = match[0];
|
|
1407
|
+
return path.dirname(fileURLToPath(fileUrl));
|
|
1408
|
+
}
|
|
1409
|
+
} catch {
|
|
1410
|
+
}
|
|
1411
|
+
throw new Error("Unable to determine directory name in this environment");
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// src/utils/keypress.ts
|
|
1417
|
+
import readline from "readline";
|
|
1418
|
+
async function keypress() {
|
|
1419
|
+
const rl = readline.createInterface({
|
|
1420
|
+
input: process.stdin,
|
|
1421
|
+
output: process.stdout
|
|
1422
|
+
});
|
|
1423
|
+
return new Promise((resolve) => {
|
|
1424
|
+
rl.question("", (answer) => {
|
|
1425
|
+
rl.close();
|
|
1426
|
+
process.stderr.moveCursor(0, -1);
|
|
1427
|
+
process.stderr.clearLine(1);
|
|
1428
|
+
resolve(answer);
|
|
1429
|
+
});
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
// src/utils/spinner.ts
|
|
1434
|
+
import {
|
|
1435
|
+
createSpinner as _createSpinner
|
|
1436
|
+
} from "nanospinner";
|
|
1437
|
+
function printToStdError(opts) {
|
|
1438
|
+
if (opts?.text) console.error(opts.text);
|
|
1439
|
+
}
|
|
1440
|
+
var mockSpinner = {
|
|
1441
|
+
success: (opts) => {
|
|
1442
|
+
printToStdError(opts);
|
|
1443
|
+
return mockSpinner;
|
|
1444
|
+
},
|
|
1445
|
+
error: (opts) => {
|
|
1446
|
+
printToStdError(opts);
|
|
1447
|
+
return mockSpinner;
|
|
1448
|
+
},
|
|
1449
|
+
warn: (opts) => {
|
|
1450
|
+
printToStdError(opts);
|
|
1451
|
+
return mockSpinner;
|
|
1452
|
+
},
|
|
1453
|
+
stop: (opts) => {
|
|
1454
|
+
printToStdError(opts);
|
|
1455
|
+
return mockSpinner;
|
|
1456
|
+
},
|
|
1457
|
+
start: (opts) => {
|
|
1458
|
+
printToStdError(opts);
|
|
1459
|
+
return mockSpinner;
|
|
1460
|
+
},
|
|
1461
|
+
update: (opts) => {
|
|
1462
|
+
printToStdError(opts);
|
|
1463
|
+
return mockSpinner;
|
|
1464
|
+
},
|
|
1465
|
+
reset: () => mockSpinner,
|
|
1466
|
+
clear: () => mockSpinner,
|
|
1467
|
+
spin: () => mockSpinner
|
|
1468
|
+
};
|
|
1469
|
+
function Spinner({ ci = false } = {}) {
|
|
1470
|
+
return {
|
|
1471
|
+
createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/utils/check_node_version.ts
|
|
1381
1476
|
import fs2 from "fs";
|
|
1382
1477
|
import path2 from "path";
|
|
1478
|
+
import semver from "semver";
|
|
1479
|
+
function getPackageJson() {
|
|
1480
|
+
return JSON.parse(
|
|
1481
|
+
fs2.readFileSync(path2.join(getModuleRootDir(), "package.json"), "utf8")
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
var packageJson = getPackageJson();
|
|
1485
|
+
if (!semver.satisfies(process.version, packageJson.engines.node)) {
|
|
1486
|
+
console.error(
|
|
1487
|
+
`
|
|
1488
|
+
\u26A0\uFE0F ${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
|
|
1489
|
+
);
|
|
1490
|
+
process.exit(1);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// src/utils/gitUtils.ts
|
|
1494
|
+
import simpleGit from "simple-git";
|
|
1495
|
+
|
|
1496
|
+
// src/utils/index.ts
|
|
1497
|
+
var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
|
|
1498
|
+
var CliError = class extends Error {
|
|
1499
|
+
};
|
|
1500
|
+
|
|
1501
|
+
// src/commands/AuthManager.ts
|
|
1502
|
+
import crypto from "crypto";
|
|
1503
|
+
import os from "os";
|
|
1504
|
+
import open from "open";
|
|
1505
|
+
|
|
1506
|
+
// src/constants.ts
|
|
1507
|
+
import fs3 from "fs";
|
|
1508
|
+
import path3 from "path";
|
|
1383
1509
|
import chalk from "chalk";
|
|
1384
1510
|
import Debug from "debug";
|
|
1385
1511
|
import * as dotenv from "dotenv";
|
|
@@ -3481,56 +3607,17 @@ var ScmType = /* @__PURE__ */ ((ScmType2) => {
|
|
|
3481
3607
|
return ScmType2;
|
|
3482
3608
|
})(ScmType || {});
|
|
3483
3609
|
|
|
3484
|
-
// src/utils/dirname.ts
|
|
3485
|
-
import fs from "fs";
|
|
3486
|
-
import path from "path";
|
|
3487
|
-
import { fileURLToPath } from "url";
|
|
3488
|
-
function getModuleRootDir() {
|
|
3489
|
-
let manifestDir = getDirName();
|
|
3490
|
-
for (let i = 0; i < 10; i++) {
|
|
3491
|
-
const manifestPath = path.join(manifestDir, "package.json");
|
|
3492
|
-
if (fs.existsSync(manifestPath)) {
|
|
3493
|
-
return manifestDir;
|
|
3494
|
-
}
|
|
3495
|
-
manifestDir = path.join(manifestDir, "..");
|
|
3496
|
-
}
|
|
3497
|
-
throw new Error("Cannot locate package.json file");
|
|
3498
|
-
}
|
|
3499
|
-
function getDirName() {
|
|
3500
|
-
if (typeof __filename !== "undefined") {
|
|
3501
|
-
return path.dirname(__filename);
|
|
3502
|
-
} else {
|
|
3503
|
-
try {
|
|
3504
|
-
const getImportMetaUrl = new Function("return import.meta.url");
|
|
3505
|
-
const importMetaUrl = getImportMetaUrl();
|
|
3506
|
-
return path.dirname(fileURLToPath(importMetaUrl));
|
|
3507
|
-
} catch (e) {
|
|
3508
|
-
try {
|
|
3509
|
-
const err = new Error();
|
|
3510
|
-
const stack = err.stack || "";
|
|
3511
|
-
const match = stack.match(/file:\/\/[^\s)]+/);
|
|
3512
|
-
if (match) {
|
|
3513
|
-
const fileUrl = match[0];
|
|
3514
|
-
return path.dirname(fileURLToPath(fileUrl));
|
|
3515
|
-
}
|
|
3516
|
-
} catch {
|
|
3517
|
-
}
|
|
3518
|
-
throw new Error("Unable to determine directory name in this environment");
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
}
|
|
3522
|
-
|
|
3523
3610
|
// src/constants.ts
|
|
3524
3611
|
var debug = Debug("mobbdev:constants");
|
|
3525
|
-
var runtimeConfigPath =
|
|
3612
|
+
var runtimeConfigPath = path3.join(
|
|
3526
3613
|
getModuleRootDir(),
|
|
3527
3614
|
"out",
|
|
3528
3615
|
"runtime.config.json"
|
|
3529
3616
|
);
|
|
3530
|
-
if (
|
|
3617
|
+
if (fs3.existsSync(runtimeConfigPath)) {
|
|
3531
3618
|
try {
|
|
3532
3619
|
const runtimeConfig = JSON.parse(
|
|
3533
|
-
|
|
3620
|
+
fs3.readFileSync(runtimeConfigPath, "utf-8")
|
|
3534
3621
|
);
|
|
3535
3622
|
Object.assign(process.env, runtimeConfig);
|
|
3536
3623
|
debug("Loaded runtime config from %s", runtimeConfigPath);
|
|
@@ -3538,7 +3625,7 @@ if (fs2.existsSync(runtimeConfigPath)) {
|
|
|
3538
3625
|
debug("Failed to load runtime config: %o", e);
|
|
3539
3626
|
}
|
|
3540
3627
|
}
|
|
3541
|
-
dotenv.config({ path:
|
|
3628
|
+
dotenv.config({ path: path3.join(getModuleRootDir(), ".env") });
|
|
3542
3629
|
var DEFAULT_API_URL = "https://api.mobb.ai/v1/graphql";
|
|
3543
3630
|
var DEFAULT_WEB_APP_URL = "https://app.mobb.ai";
|
|
3544
3631
|
var scmFriendlyText = {
|
|
@@ -3635,91 +3722,6 @@ var ScanContext = {
|
|
|
3635
3722
|
BUGSY: "BUGSY"
|
|
3636
3723
|
};
|
|
3637
3724
|
|
|
3638
|
-
// src/utils/keypress.ts
|
|
3639
|
-
import readline from "readline";
|
|
3640
|
-
async function keypress() {
|
|
3641
|
-
const rl = readline.createInterface({
|
|
3642
|
-
input: process.stdin,
|
|
3643
|
-
output: process.stdout
|
|
3644
|
-
});
|
|
3645
|
-
return new Promise((resolve) => {
|
|
3646
|
-
rl.question("", (answer) => {
|
|
3647
|
-
rl.close();
|
|
3648
|
-
process.stderr.moveCursor(0, -1);
|
|
3649
|
-
process.stderr.clearLine(1);
|
|
3650
|
-
resolve(answer);
|
|
3651
|
-
});
|
|
3652
|
-
});
|
|
3653
|
-
}
|
|
3654
|
-
|
|
3655
|
-
// src/utils/spinner.ts
|
|
3656
|
-
import {
|
|
3657
|
-
createSpinner as _createSpinner
|
|
3658
|
-
} from "nanospinner";
|
|
3659
|
-
function printToStdError(opts) {
|
|
3660
|
-
if (opts?.text) console.error(opts.text);
|
|
3661
|
-
}
|
|
3662
|
-
var mockSpinner = {
|
|
3663
|
-
success: (opts) => {
|
|
3664
|
-
printToStdError(opts);
|
|
3665
|
-
return mockSpinner;
|
|
3666
|
-
},
|
|
3667
|
-
error: (opts) => {
|
|
3668
|
-
printToStdError(opts);
|
|
3669
|
-
return mockSpinner;
|
|
3670
|
-
},
|
|
3671
|
-
warn: (opts) => {
|
|
3672
|
-
printToStdError(opts);
|
|
3673
|
-
return mockSpinner;
|
|
3674
|
-
},
|
|
3675
|
-
stop: (opts) => {
|
|
3676
|
-
printToStdError(opts);
|
|
3677
|
-
return mockSpinner;
|
|
3678
|
-
},
|
|
3679
|
-
start: (opts) => {
|
|
3680
|
-
printToStdError(opts);
|
|
3681
|
-
return mockSpinner;
|
|
3682
|
-
},
|
|
3683
|
-
update: (opts) => {
|
|
3684
|
-
printToStdError(opts);
|
|
3685
|
-
return mockSpinner;
|
|
3686
|
-
},
|
|
3687
|
-
reset: () => mockSpinner,
|
|
3688
|
-
clear: () => mockSpinner,
|
|
3689
|
-
spin: () => mockSpinner
|
|
3690
|
-
};
|
|
3691
|
-
function Spinner({ ci = false } = {}) {
|
|
3692
|
-
return {
|
|
3693
|
-
createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
|
|
3694
|
-
};
|
|
3695
|
-
}
|
|
3696
|
-
|
|
3697
|
-
// src/utils/check_node_version.ts
|
|
3698
|
-
import fs3 from "fs";
|
|
3699
|
-
import path3 from "path";
|
|
3700
|
-
import semver from "semver";
|
|
3701
|
-
function getPackageJson() {
|
|
3702
|
-
return JSON.parse(
|
|
3703
|
-
fs3.readFileSync(path3.join(getModuleRootDir(), "package.json"), "utf8")
|
|
3704
|
-
);
|
|
3705
|
-
}
|
|
3706
|
-
var packageJson = getPackageJson();
|
|
3707
|
-
if (!semver.satisfies(process.version, packageJson.engines.node)) {
|
|
3708
|
-
console.error(
|
|
3709
|
-
`
|
|
3710
|
-
\u26A0\uFE0F ${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
|
|
3711
|
-
);
|
|
3712
|
-
process.exit(1);
|
|
3713
|
-
}
|
|
3714
|
-
|
|
3715
|
-
// src/utils/gitUtils.ts
|
|
3716
|
-
import simpleGit from "simple-git";
|
|
3717
|
-
|
|
3718
|
-
// src/utils/index.ts
|
|
3719
|
-
var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
|
|
3720
|
-
var CliError = class extends Error {
|
|
3721
|
-
};
|
|
3722
|
-
|
|
3723
3725
|
// src/utils/subscribe/subscribe.ts
|
|
3724
3726
|
import { createClient } from "graphql-ws";
|
|
3725
3727
|
import WebsocketNode from "isomorphic-ws";
|
|
@@ -6493,10 +6495,174 @@ function getConfigStore() {
|
|
|
6493
6495
|
}
|
|
6494
6496
|
var configStore = getConfigStore();
|
|
6495
6497
|
|
|
6496
|
-
// src/commands/
|
|
6497
|
-
var debug7 = Debug6("mobbdev:commands");
|
|
6498
|
+
// src/commands/AuthManager.ts
|
|
6498
6499
|
var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
|
|
6499
6500
|
var LOGIN_CHECK_DELAY = 5 * 1e3;
|
|
6501
|
+
var AuthManager = class {
|
|
6502
|
+
constructor(webAppUrl, apiUrl) {
|
|
6503
|
+
__publicField(this, "publicKey");
|
|
6504
|
+
__publicField(this, "privateKey");
|
|
6505
|
+
__publicField(this, "loginId");
|
|
6506
|
+
__publicField(this, "gqlClient");
|
|
6507
|
+
__publicField(this, "currentBrowserUrl");
|
|
6508
|
+
__publicField(this, "authenticated", null);
|
|
6509
|
+
__publicField(this, "resolvedWebAppUrl");
|
|
6510
|
+
__publicField(this, "resolvedApiUrl");
|
|
6511
|
+
this.resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
6512
|
+
this.resolvedApiUrl = apiUrl || API_URL;
|
|
6513
|
+
}
|
|
6514
|
+
openUrlInBrowser() {
|
|
6515
|
+
if (this.currentBrowserUrl) {
|
|
6516
|
+
open(this.currentBrowserUrl);
|
|
6517
|
+
return true;
|
|
6518
|
+
}
|
|
6519
|
+
return false;
|
|
6520
|
+
}
|
|
6521
|
+
async waitForAuthentication() {
|
|
6522
|
+
let newApiToken = null;
|
|
6523
|
+
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
6524
|
+
newApiToken = await this.getApiToken();
|
|
6525
|
+
if (newApiToken) {
|
|
6526
|
+
break;
|
|
6527
|
+
}
|
|
6528
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
6529
|
+
}
|
|
6530
|
+
if (!newApiToken) {
|
|
6531
|
+
return false;
|
|
6532
|
+
}
|
|
6533
|
+
this.gqlClient = new GQLClient({
|
|
6534
|
+
apiKey: newApiToken,
|
|
6535
|
+
type: "apiKey",
|
|
6536
|
+
apiUrl: this.resolvedApiUrl
|
|
6537
|
+
});
|
|
6538
|
+
const loginSuccess = await this.gqlClient.validateUserToken();
|
|
6539
|
+
if (loginSuccess) {
|
|
6540
|
+
configStore.set("apiToken", newApiToken);
|
|
6541
|
+
this.authenticated = true;
|
|
6542
|
+
return true;
|
|
6543
|
+
}
|
|
6544
|
+
return false;
|
|
6545
|
+
}
|
|
6546
|
+
/**
|
|
6547
|
+
* Checks if the user is already authenticated
|
|
6548
|
+
*/
|
|
6549
|
+
async isAuthenticated() {
|
|
6550
|
+
if (this.authenticated === null) {
|
|
6551
|
+
const result = await this.checkAuthentication();
|
|
6552
|
+
this.authenticated = result.isAuthenticated;
|
|
6553
|
+
}
|
|
6554
|
+
return this.authenticated;
|
|
6555
|
+
}
|
|
6556
|
+
/**
|
|
6557
|
+
* Private function to check if the user is authenticated with the server
|
|
6558
|
+
*/
|
|
6559
|
+
async checkAuthentication(apiKey) {
|
|
6560
|
+
try {
|
|
6561
|
+
if (!this.gqlClient) {
|
|
6562
|
+
this.gqlClient = this.getGQLClient(apiKey);
|
|
6563
|
+
}
|
|
6564
|
+
const isConnected = await this.gqlClient.verifyApiConnection();
|
|
6565
|
+
if (!isConnected) {
|
|
6566
|
+
return {
|
|
6567
|
+
isAuthenticated: false,
|
|
6568
|
+
message: "Failed to connect to Mobb server"
|
|
6569
|
+
};
|
|
6570
|
+
}
|
|
6571
|
+
const userVerify = await this.gqlClient.validateUserToken();
|
|
6572
|
+
if (!userVerify) {
|
|
6573
|
+
return {
|
|
6574
|
+
isAuthenticated: false,
|
|
6575
|
+
message: "User token validation failed"
|
|
6576
|
+
};
|
|
6577
|
+
}
|
|
6578
|
+
} catch (error) {
|
|
6579
|
+
return {
|
|
6580
|
+
isAuthenticated: false,
|
|
6581
|
+
message: error instanceof Error ? error.message : "Unknown authentication error"
|
|
6582
|
+
};
|
|
6583
|
+
}
|
|
6584
|
+
return { isAuthenticated: true, message: "Successfully authenticated" };
|
|
6585
|
+
}
|
|
6586
|
+
/**
|
|
6587
|
+
* Generates a login URL for manual authentication
|
|
6588
|
+
*/
|
|
6589
|
+
async generateLoginUrl(loginContext) {
|
|
6590
|
+
try {
|
|
6591
|
+
if (!this.gqlClient) {
|
|
6592
|
+
this.gqlClient = this.getGQLClient();
|
|
6593
|
+
}
|
|
6594
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
|
|
6595
|
+
modulusLength: 2048
|
|
6596
|
+
});
|
|
6597
|
+
this.publicKey = publicKey;
|
|
6598
|
+
this.privateKey = privateKey;
|
|
6599
|
+
this.loginId = await this.gqlClient.createCliLogin({
|
|
6600
|
+
publicKey: this.publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
6601
|
+
});
|
|
6602
|
+
const webLoginUrl = `${this.resolvedWebAppUrl}/cli-login`;
|
|
6603
|
+
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, this.loginId, os.hostname(), loginContext) : `${webLoginUrl}/${this.loginId}?hostname=${os.hostname()}`;
|
|
6604
|
+
this.currentBrowserUrl = browserUrl;
|
|
6605
|
+
return browserUrl;
|
|
6606
|
+
} catch (error) {
|
|
6607
|
+
console.error("Failed to generate login URL:", error);
|
|
6608
|
+
return null;
|
|
6609
|
+
}
|
|
6610
|
+
}
|
|
6611
|
+
/**
|
|
6612
|
+
* Retrieves and decrypts the API token after authentication
|
|
6613
|
+
*/
|
|
6614
|
+
async getApiToken() {
|
|
6615
|
+
if (!this.gqlClient || !this.loginId || !this.privateKey) {
|
|
6616
|
+
return null;
|
|
6617
|
+
}
|
|
6618
|
+
const encryptedApiToken = await this.gqlClient.getEncryptedApiToken({
|
|
6619
|
+
loginId: this.loginId
|
|
6620
|
+
});
|
|
6621
|
+
if (encryptedApiToken) {
|
|
6622
|
+
return crypto.privateDecrypt(
|
|
6623
|
+
this.privateKey,
|
|
6624
|
+
Buffer.from(encryptedApiToken, "base64")
|
|
6625
|
+
).toString("utf-8");
|
|
6626
|
+
}
|
|
6627
|
+
return null;
|
|
6628
|
+
}
|
|
6629
|
+
/**
|
|
6630
|
+
* Gets the current GQL client (if authenticated)
|
|
6631
|
+
*/
|
|
6632
|
+
getGQLClient(inputApiKey) {
|
|
6633
|
+
if (this.gqlClient === void 0) {
|
|
6634
|
+
this.gqlClient = new GQLClient({
|
|
6635
|
+
apiKey: inputApiKey || configStore.get("apiToken") || "",
|
|
6636
|
+
type: "apiKey",
|
|
6637
|
+
apiUrl: this.resolvedApiUrl
|
|
6638
|
+
});
|
|
6639
|
+
}
|
|
6640
|
+
return this.gqlClient;
|
|
6641
|
+
}
|
|
6642
|
+
/**
|
|
6643
|
+
* Assigns a GQL client instance to the AuthManager, and resets auth state
|
|
6644
|
+
* @param gqlClient The GQL client instance to set
|
|
6645
|
+
*/
|
|
6646
|
+
setGQLClient(gqlClient) {
|
|
6647
|
+
this.gqlClient = gqlClient;
|
|
6648
|
+
this.cleanup();
|
|
6649
|
+
}
|
|
6650
|
+
/**
|
|
6651
|
+
* Cleans up any active login session
|
|
6652
|
+
*/
|
|
6653
|
+
cleanup() {
|
|
6654
|
+
this.publicKey = void 0;
|
|
6655
|
+
this.privateKey = void 0;
|
|
6656
|
+
this.loginId = void 0;
|
|
6657
|
+
this.authenticated = null;
|
|
6658
|
+
this.currentBrowserUrl = null;
|
|
6659
|
+
}
|
|
6660
|
+
};
|
|
6661
|
+
|
|
6662
|
+
// src/commands/handleMobbLogin.ts
|
|
6663
|
+
var debug7 = Debug6("mobbdev:commands");
|
|
6664
|
+
var LOGIN_MAX_WAIT2 = 10 * 60 * 1e3;
|
|
6665
|
+
var LOGIN_CHECK_DELAY2 = 5 * 1e3;
|
|
6500
6666
|
var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk2.bgBlue(
|
|
6501
6667
|
"press any key to continue"
|
|
6502
6668
|
)};`;
|
|
@@ -6511,11 +6677,8 @@ async function getAuthenticatedGQLClient({
|
|
|
6511
6677
|
apiUrl || "undefined",
|
|
6512
6678
|
webAppUrl || "undefined"
|
|
6513
6679
|
);
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
type: "apiKey",
|
|
6517
|
-
apiUrl
|
|
6518
|
-
});
|
|
6680
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
6681
|
+
let gqlClient = authManager.getGQLClient(inputApiKey);
|
|
6519
6682
|
gqlClient = await handleMobbLogin({
|
|
6520
6683
|
inGqlClient: gqlClient,
|
|
6521
6684
|
skipPrompts: isSkipPrompts,
|
|
@@ -6532,35 +6695,28 @@ async function handleMobbLogin({
|
|
|
6532
6695
|
webAppUrl,
|
|
6533
6696
|
loginContext
|
|
6534
6697
|
}) {
|
|
6535
|
-
const resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
6536
|
-
const resolvedApiUrl = apiUrl || API_URL;
|
|
6537
6698
|
debug7(
|
|
6538
6699
|
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
6539
|
-
resolvedApiUrl,
|
|
6540
6700
|
apiUrl || "fallback",
|
|
6541
|
-
|
|
6701
|
+
apiUrl || "fallback",
|
|
6702
|
+
webAppUrl || "fallback",
|
|
6542
6703
|
webAppUrl || "fallback"
|
|
6543
6704
|
);
|
|
6544
6705
|
const { createSpinner } = Spinner({ ci: skipPrompts });
|
|
6545
|
-
const
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6706
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
6707
|
+
authManager.setGQLClient(inGqlClient);
|
|
6708
|
+
try {
|
|
6709
|
+
const isAuthenticated = await authManager.isAuthenticated();
|
|
6710
|
+
if (isAuthenticated) {
|
|
6711
|
+
createSpinner().start().success({
|
|
6712
|
+
text: `\u{1F513} Login to Mobb succeeded. Already authenticated`
|
|
6713
|
+
});
|
|
6714
|
+
return authManager.getGQLClient();
|
|
6715
|
+
}
|
|
6716
|
+
} catch (error) {
|
|
6717
|
+
debug7("Authentication check failed:", error);
|
|
6553
6718
|
}
|
|
6554
|
-
|
|
6555
|
-
text: `\u{1F513} Connection to Mobb: succeeded`
|
|
6556
|
-
});
|
|
6557
|
-
const userVerify = await inGqlClient.validateUserToken();
|
|
6558
|
-
if (userVerify) {
|
|
6559
|
-
createSpinner().start().success({
|
|
6560
|
-
text: `\u{1F513} Login to Mobb succeeded. ${typeof userVerify === "string" ? `Logged in as ${userVerify}` : ""}`
|
|
6561
|
-
});
|
|
6562
|
-
return inGqlClient;
|
|
6563
|
-
} else if (apiKey) {
|
|
6719
|
+
if (apiKey) {
|
|
6564
6720
|
createSpinner().start().error({
|
|
6565
6721
|
text: "\u{1F513} Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
6566
6722
|
});
|
|
@@ -6576,57 +6732,32 @@ async function handleMobbLogin({
|
|
|
6576
6732
|
loginSpinner.update({
|
|
6577
6733
|
text: "\u{1F513} Waiting for Mobb login..."
|
|
6578
6734
|
});
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
if (encryptedApiToken) {
|
|
6598
|
-
debug7("encrypted API token received %s", encryptedApiToken);
|
|
6599
|
-
newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
6600
|
-
debug7("API token decrypted");
|
|
6601
|
-
break;
|
|
6735
|
+
try {
|
|
6736
|
+
const loginUrl = await authManager.generateLoginUrl(loginContext);
|
|
6737
|
+
if (!loginUrl) {
|
|
6738
|
+
loginSpinner.error({
|
|
6739
|
+
text: "Failed to generate login URL"
|
|
6740
|
+
});
|
|
6741
|
+
throw new CliError("Failed to generate login URL");
|
|
6742
|
+
}
|
|
6743
|
+
!skipPrompts && console.log(
|
|
6744
|
+
`If the page does not open automatically, kindly access it through ${loginUrl}.`
|
|
6745
|
+
);
|
|
6746
|
+
authManager.openUrlInBrowser();
|
|
6747
|
+
const authSuccess = await authManager.waitForAuthentication();
|
|
6748
|
+
if (!authSuccess) {
|
|
6749
|
+
loginSpinner.error({
|
|
6750
|
+
text: "Login timeout error"
|
|
6751
|
+
});
|
|
6752
|
+
throw new CliError("Login timeout error");
|
|
6602
6753
|
}
|
|
6603
|
-
await sleep(LOGIN_CHECK_DELAY);
|
|
6604
|
-
}
|
|
6605
|
-
if (!newApiToken) {
|
|
6606
|
-
loginSpinner.error({
|
|
6607
|
-
text: "Login timeout error"
|
|
6608
|
-
});
|
|
6609
|
-
throw new CliError();
|
|
6610
|
-
}
|
|
6611
|
-
const newGqlClient = new GQLClient({
|
|
6612
|
-
apiKey: newApiToken,
|
|
6613
|
-
type: "apiKey",
|
|
6614
|
-
apiUrl: resolvedApiUrl
|
|
6615
|
-
});
|
|
6616
|
-
const loginSuccess = await newGqlClient.validateUserToken();
|
|
6617
|
-
if (loginSuccess) {
|
|
6618
|
-
debug7(`set api token ${newApiToken}`);
|
|
6619
|
-
configStore.set("apiToken", newApiToken);
|
|
6620
6754
|
loginSpinner.success({
|
|
6621
|
-
text: `\u{1F513} Login to Mobb successful
|
|
6622
|
-
});
|
|
6623
|
-
} else {
|
|
6624
|
-
loginSpinner.error({
|
|
6625
|
-
text: "Something went wrong, API token is invalid."
|
|
6755
|
+
text: `\u{1F513} Login to Mobb successful!`
|
|
6626
6756
|
});
|
|
6627
|
-
|
|
6757
|
+
return authManager.getGQLClient();
|
|
6758
|
+
} finally {
|
|
6759
|
+
authManager.cleanup();
|
|
6628
6760
|
}
|
|
6629
|
-
return newGqlClient;
|
|
6630
6761
|
}
|
|
6631
6762
|
|
|
6632
6763
|
// src/args/commands/upload_ai_blame.ts
|
package/dist/index.mjs
CHANGED
|
@@ -11587,10 +11587,12 @@ import tmp2 from "tmp";
|
|
|
11587
11587
|
import { z as z29 } from "zod";
|
|
11588
11588
|
|
|
11589
11589
|
// src/commands/handleMobbLogin.ts
|
|
11590
|
-
import crypto from "crypto";
|
|
11591
|
-
import os from "os";
|
|
11592
11590
|
import chalk3 from "chalk";
|
|
11593
11591
|
import Debug6 from "debug";
|
|
11592
|
+
|
|
11593
|
+
// src/commands/AuthManager.ts
|
|
11594
|
+
import crypto from "crypto";
|
|
11595
|
+
import os from "os";
|
|
11594
11596
|
import open from "open";
|
|
11595
11597
|
|
|
11596
11598
|
// src/features/analysis/graphql/gql.ts
|
|
@@ -12346,10 +12348,174 @@ function getConfigStore() {
|
|
|
12346
12348
|
}
|
|
12347
12349
|
var configStore = getConfigStore();
|
|
12348
12350
|
|
|
12349
|
-
// src/commands/
|
|
12350
|
-
var debug7 = Debug6("mobbdev:commands");
|
|
12351
|
+
// src/commands/AuthManager.ts
|
|
12351
12352
|
var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
|
|
12352
12353
|
var LOGIN_CHECK_DELAY = 5 * 1e3;
|
|
12354
|
+
var AuthManager = class {
|
|
12355
|
+
constructor(webAppUrl, apiUrl) {
|
|
12356
|
+
__publicField(this, "publicKey");
|
|
12357
|
+
__publicField(this, "privateKey");
|
|
12358
|
+
__publicField(this, "loginId");
|
|
12359
|
+
__publicField(this, "gqlClient");
|
|
12360
|
+
__publicField(this, "currentBrowserUrl");
|
|
12361
|
+
__publicField(this, "authenticated", null);
|
|
12362
|
+
__publicField(this, "resolvedWebAppUrl");
|
|
12363
|
+
__publicField(this, "resolvedApiUrl");
|
|
12364
|
+
this.resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
12365
|
+
this.resolvedApiUrl = apiUrl || API_URL;
|
|
12366
|
+
}
|
|
12367
|
+
openUrlInBrowser() {
|
|
12368
|
+
if (this.currentBrowserUrl) {
|
|
12369
|
+
open(this.currentBrowserUrl);
|
|
12370
|
+
return true;
|
|
12371
|
+
}
|
|
12372
|
+
return false;
|
|
12373
|
+
}
|
|
12374
|
+
async waitForAuthentication() {
|
|
12375
|
+
let newApiToken = null;
|
|
12376
|
+
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
12377
|
+
newApiToken = await this.getApiToken();
|
|
12378
|
+
if (newApiToken) {
|
|
12379
|
+
break;
|
|
12380
|
+
}
|
|
12381
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
12382
|
+
}
|
|
12383
|
+
if (!newApiToken) {
|
|
12384
|
+
return false;
|
|
12385
|
+
}
|
|
12386
|
+
this.gqlClient = new GQLClient({
|
|
12387
|
+
apiKey: newApiToken,
|
|
12388
|
+
type: "apiKey",
|
|
12389
|
+
apiUrl: this.resolvedApiUrl
|
|
12390
|
+
});
|
|
12391
|
+
const loginSuccess = await this.gqlClient.validateUserToken();
|
|
12392
|
+
if (loginSuccess) {
|
|
12393
|
+
configStore.set("apiToken", newApiToken);
|
|
12394
|
+
this.authenticated = true;
|
|
12395
|
+
return true;
|
|
12396
|
+
}
|
|
12397
|
+
return false;
|
|
12398
|
+
}
|
|
12399
|
+
/**
|
|
12400
|
+
* Checks if the user is already authenticated
|
|
12401
|
+
*/
|
|
12402
|
+
async isAuthenticated() {
|
|
12403
|
+
if (this.authenticated === null) {
|
|
12404
|
+
const result = await this.checkAuthentication();
|
|
12405
|
+
this.authenticated = result.isAuthenticated;
|
|
12406
|
+
}
|
|
12407
|
+
return this.authenticated;
|
|
12408
|
+
}
|
|
12409
|
+
/**
|
|
12410
|
+
* Private function to check if the user is authenticated with the server
|
|
12411
|
+
*/
|
|
12412
|
+
async checkAuthentication(apiKey) {
|
|
12413
|
+
try {
|
|
12414
|
+
if (!this.gqlClient) {
|
|
12415
|
+
this.gqlClient = this.getGQLClient(apiKey);
|
|
12416
|
+
}
|
|
12417
|
+
const isConnected = await this.gqlClient.verifyApiConnection();
|
|
12418
|
+
if (!isConnected) {
|
|
12419
|
+
return {
|
|
12420
|
+
isAuthenticated: false,
|
|
12421
|
+
message: "Failed to connect to Mobb server"
|
|
12422
|
+
};
|
|
12423
|
+
}
|
|
12424
|
+
const userVerify = await this.gqlClient.validateUserToken();
|
|
12425
|
+
if (!userVerify) {
|
|
12426
|
+
return {
|
|
12427
|
+
isAuthenticated: false,
|
|
12428
|
+
message: "User token validation failed"
|
|
12429
|
+
};
|
|
12430
|
+
}
|
|
12431
|
+
} catch (error) {
|
|
12432
|
+
return {
|
|
12433
|
+
isAuthenticated: false,
|
|
12434
|
+
message: error instanceof Error ? error.message : "Unknown authentication error"
|
|
12435
|
+
};
|
|
12436
|
+
}
|
|
12437
|
+
return { isAuthenticated: true, message: "Successfully authenticated" };
|
|
12438
|
+
}
|
|
12439
|
+
/**
|
|
12440
|
+
* Generates a login URL for manual authentication
|
|
12441
|
+
*/
|
|
12442
|
+
async generateLoginUrl(loginContext) {
|
|
12443
|
+
try {
|
|
12444
|
+
if (!this.gqlClient) {
|
|
12445
|
+
this.gqlClient = this.getGQLClient();
|
|
12446
|
+
}
|
|
12447
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
|
|
12448
|
+
modulusLength: 2048
|
|
12449
|
+
});
|
|
12450
|
+
this.publicKey = publicKey;
|
|
12451
|
+
this.privateKey = privateKey;
|
|
12452
|
+
this.loginId = await this.gqlClient.createCliLogin({
|
|
12453
|
+
publicKey: this.publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
12454
|
+
});
|
|
12455
|
+
const webLoginUrl = `${this.resolvedWebAppUrl}/cli-login`;
|
|
12456
|
+
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, this.loginId, os.hostname(), loginContext) : `${webLoginUrl}/${this.loginId}?hostname=${os.hostname()}`;
|
|
12457
|
+
this.currentBrowserUrl = browserUrl;
|
|
12458
|
+
return browserUrl;
|
|
12459
|
+
} catch (error) {
|
|
12460
|
+
console.error("Failed to generate login URL:", error);
|
|
12461
|
+
return null;
|
|
12462
|
+
}
|
|
12463
|
+
}
|
|
12464
|
+
/**
|
|
12465
|
+
* Retrieves and decrypts the API token after authentication
|
|
12466
|
+
*/
|
|
12467
|
+
async getApiToken() {
|
|
12468
|
+
if (!this.gqlClient || !this.loginId || !this.privateKey) {
|
|
12469
|
+
return null;
|
|
12470
|
+
}
|
|
12471
|
+
const encryptedApiToken = await this.gqlClient.getEncryptedApiToken({
|
|
12472
|
+
loginId: this.loginId
|
|
12473
|
+
});
|
|
12474
|
+
if (encryptedApiToken) {
|
|
12475
|
+
return crypto.privateDecrypt(
|
|
12476
|
+
this.privateKey,
|
|
12477
|
+
Buffer.from(encryptedApiToken, "base64")
|
|
12478
|
+
).toString("utf-8");
|
|
12479
|
+
}
|
|
12480
|
+
return null;
|
|
12481
|
+
}
|
|
12482
|
+
/**
|
|
12483
|
+
* Gets the current GQL client (if authenticated)
|
|
12484
|
+
*/
|
|
12485
|
+
getGQLClient(inputApiKey) {
|
|
12486
|
+
if (this.gqlClient === void 0) {
|
|
12487
|
+
this.gqlClient = new GQLClient({
|
|
12488
|
+
apiKey: inputApiKey || configStore.get("apiToken") || "",
|
|
12489
|
+
type: "apiKey",
|
|
12490
|
+
apiUrl: this.resolvedApiUrl
|
|
12491
|
+
});
|
|
12492
|
+
}
|
|
12493
|
+
return this.gqlClient;
|
|
12494
|
+
}
|
|
12495
|
+
/**
|
|
12496
|
+
* Assigns a GQL client instance to the AuthManager, and resets auth state
|
|
12497
|
+
* @param gqlClient The GQL client instance to set
|
|
12498
|
+
*/
|
|
12499
|
+
setGQLClient(gqlClient) {
|
|
12500
|
+
this.gqlClient = gqlClient;
|
|
12501
|
+
this.cleanup();
|
|
12502
|
+
}
|
|
12503
|
+
/**
|
|
12504
|
+
* Cleans up any active login session
|
|
12505
|
+
*/
|
|
12506
|
+
cleanup() {
|
|
12507
|
+
this.publicKey = void 0;
|
|
12508
|
+
this.privateKey = void 0;
|
|
12509
|
+
this.loginId = void 0;
|
|
12510
|
+
this.authenticated = null;
|
|
12511
|
+
this.currentBrowserUrl = null;
|
|
12512
|
+
}
|
|
12513
|
+
};
|
|
12514
|
+
|
|
12515
|
+
// src/commands/handleMobbLogin.ts
|
|
12516
|
+
var debug7 = Debug6("mobbdev:commands");
|
|
12517
|
+
var LOGIN_MAX_WAIT2 = 10 * 60 * 1e3;
|
|
12518
|
+
var LOGIN_CHECK_DELAY2 = 5 * 1e3;
|
|
12353
12519
|
var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk3.bgBlue(
|
|
12354
12520
|
"press any key to continue"
|
|
12355
12521
|
)};`;
|
|
@@ -12364,11 +12530,8 @@ async function getAuthenticatedGQLClient({
|
|
|
12364
12530
|
apiUrl || "undefined",
|
|
12365
12531
|
webAppUrl || "undefined"
|
|
12366
12532
|
);
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
type: "apiKey",
|
|
12370
|
-
apiUrl
|
|
12371
|
-
});
|
|
12533
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
12534
|
+
let gqlClient = authManager.getGQLClient(inputApiKey);
|
|
12372
12535
|
gqlClient = await handleMobbLogin({
|
|
12373
12536
|
inGqlClient: gqlClient,
|
|
12374
12537
|
skipPrompts: isSkipPrompts,
|
|
@@ -12385,35 +12548,28 @@ async function handleMobbLogin({
|
|
|
12385
12548
|
webAppUrl,
|
|
12386
12549
|
loginContext
|
|
12387
12550
|
}) {
|
|
12388
|
-
const resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
12389
|
-
const resolvedApiUrl = apiUrl || API_URL;
|
|
12390
12551
|
debug7(
|
|
12391
12552
|
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
12392
|
-
resolvedApiUrl,
|
|
12393
12553
|
apiUrl || "fallback",
|
|
12394
|
-
|
|
12554
|
+
apiUrl || "fallback",
|
|
12555
|
+
webAppUrl || "fallback",
|
|
12395
12556
|
webAppUrl || "fallback"
|
|
12396
12557
|
);
|
|
12397
12558
|
const { createSpinner: createSpinner5 } = Spinner({ ci: skipPrompts });
|
|
12398
|
-
const
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12559
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
12560
|
+
authManager.setGQLClient(inGqlClient);
|
|
12561
|
+
try {
|
|
12562
|
+
const isAuthenticated = await authManager.isAuthenticated();
|
|
12563
|
+
if (isAuthenticated) {
|
|
12564
|
+
createSpinner5().start().success({
|
|
12565
|
+
text: `\u{1F513} Login to Mobb succeeded. Already authenticated`
|
|
12566
|
+
});
|
|
12567
|
+
return authManager.getGQLClient();
|
|
12568
|
+
}
|
|
12569
|
+
} catch (error) {
|
|
12570
|
+
debug7("Authentication check failed:", error);
|
|
12406
12571
|
}
|
|
12407
|
-
|
|
12408
|
-
text: `\u{1F513} Connection to Mobb: succeeded`
|
|
12409
|
-
});
|
|
12410
|
-
const userVerify = await inGqlClient.validateUserToken();
|
|
12411
|
-
if (userVerify) {
|
|
12412
|
-
createSpinner5().start().success({
|
|
12413
|
-
text: `\u{1F513} Login to Mobb succeeded. ${typeof userVerify === "string" ? `Logged in as ${userVerify}` : ""}`
|
|
12414
|
-
});
|
|
12415
|
-
return inGqlClient;
|
|
12416
|
-
} else if (apiKey) {
|
|
12572
|
+
if (apiKey) {
|
|
12417
12573
|
createSpinner5().start().error({
|
|
12418
12574
|
text: "\u{1F513} Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
12419
12575
|
});
|
|
@@ -12429,57 +12585,32 @@ async function handleMobbLogin({
|
|
|
12429
12585
|
loginSpinner.update({
|
|
12430
12586
|
text: "\u{1F513} Waiting for Mobb login..."
|
|
12431
12587
|
});
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
if (encryptedApiToken) {
|
|
12451
|
-
debug7("encrypted API token received %s", encryptedApiToken);
|
|
12452
|
-
newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
12453
|
-
debug7("API token decrypted");
|
|
12454
|
-
break;
|
|
12588
|
+
try {
|
|
12589
|
+
const loginUrl = await authManager.generateLoginUrl(loginContext);
|
|
12590
|
+
if (!loginUrl) {
|
|
12591
|
+
loginSpinner.error({
|
|
12592
|
+
text: "Failed to generate login URL"
|
|
12593
|
+
});
|
|
12594
|
+
throw new CliError("Failed to generate login URL");
|
|
12595
|
+
}
|
|
12596
|
+
!skipPrompts && console.log(
|
|
12597
|
+
`If the page does not open automatically, kindly access it through ${loginUrl}.`
|
|
12598
|
+
);
|
|
12599
|
+
authManager.openUrlInBrowser();
|
|
12600
|
+
const authSuccess = await authManager.waitForAuthentication();
|
|
12601
|
+
if (!authSuccess) {
|
|
12602
|
+
loginSpinner.error({
|
|
12603
|
+
text: "Login timeout error"
|
|
12604
|
+
});
|
|
12605
|
+
throw new CliError("Login timeout error");
|
|
12455
12606
|
}
|
|
12456
|
-
await sleep(LOGIN_CHECK_DELAY);
|
|
12457
|
-
}
|
|
12458
|
-
if (!newApiToken) {
|
|
12459
|
-
loginSpinner.error({
|
|
12460
|
-
text: "Login timeout error"
|
|
12461
|
-
});
|
|
12462
|
-
throw new CliError();
|
|
12463
|
-
}
|
|
12464
|
-
const newGqlClient = new GQLClient({
|
|
12465
|
-
apiKey: newApiToken,
|
|
12466
|
-
type: "apiKey",
|
|
12467
|
-
apiUrl: resolvedApiUrl
|
|
12468
|
-
});
|
|
12469
|
-
const loginSuccess = await newGqlClient.validateUserToken();
|
|
12470
|
-
if (loginSuccess) {
|
|
12471
|
-
debug7(`set api token ${newApiToken}`);
|
|
12472
|
-
configStore.set("apiToken", newApiToken);
|
|
12473
12607
|
loginSpinner.success({
|
|
12474
|
-
text: `\u{1F513} Login to Mobb successful
|
|
12475
|
-
});
|
|
12476
|
-
} else {
|
|
12477
|
-
loginSpinner.error({
|
|
12478
|
-
text: "Something went wrong, API token is invalid."
|
|
12608
|
+
text: `\u{1F513} Login to Mobb successful!`
|
|
12479
12609
|
});
|
|
12480
|
-
|
|
12610
|
+
return authManager.getGQLClient();
|
|
12611
|
+
} finally {
|
|
12612
|
+
authManager.cleanup();
|
|
12481
12613
|
}
|
|
12482
|
-
return newGqlClient;
|
|
12483
12614
|
}
|
|
12484
12615
|
|
|
12485
12616
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
@@ -14046,7 +14177,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14046
14177
|
`If the page does not open automatically, kindly access it through ${scmAuthUrl2}.`
|
|
14047
14178
|
);
|
|
14048
14179
|
await open3(scmAuthUrl2);
|
|
14049
|
-
for (let i = 0; i <
|
|
14180
|
+
for (let i = 0; i < LOGIN_MAX_WAIT2 / LOGIN_CHECK_DELAY2; i++) {
|
|
14050
14181
|
const userInfo2 = await gqlClient.getUserInfo();
|
|
14051
14182
|
if (!userInfo2) {
|
|
14052
14183
|
throw new CliError2("User info not found");
|
|
@@ -14065,7 +14196,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14065
14196
|
return tokenInfo2.accessToken;
|
|
14066
14197
|
}
|
|
14067
14198
|
scmSpinner.spin();
|
|
14068
|
-
await sleep(
|
|
14199
|
+
await sleep(LOGIN_CHECK_DELAY2);
|
|
14069
14200
|
}
|
|
14070
14201
|
scmSpinner.error({
|
|
14071
14202
|
text: `${scmName} login timeout error`
|