@bragduck/cli 2.29.2 → 2.30.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/README.md +138 -300
- package/dist/bin/bragduck.js +168 -579
- package/dist/bin/bragduck.js.map +1 -1
- package/dist/index.js +85 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -12
package/dist/bin/bragduck.js
CHANGED
|
@@ -9,11 +9,11 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// node_modules/tsup/assets/esm_shims.js
|
|
12
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js
|
|
13
13
|
import path from "path";
|
|
14
14
|
import { fileURLToPath } from "url";
|
|
15
15
|
var init_esm_shims = __esm({
|
|
16
|
-
"node_modules/tsup/assets/esm_shims.js"() {
|
|
16
|
+
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
|
|
17
17
|
"use strict";
|
|
18
18
|
}
|
|
19
19
|
});
|
|
@@ -55,7 +55,7 @@ var init_constants = __esm({
|
|
|
55
55
|
TIMEOUT_MS: 12e4,
|
|
56
56
|
// 2 minutes
|
|
57
57
|
MIN_PORT: 8e3,
|
|
58
|
-
MAX_PORT:
|
|
58
|
+
MAX_PORT: 8004
|
|
59
59
|
};
|
|
60
60
|
ATLASSIAN_OAUTH_CONFIG = {
|
|
61
61
|
CLIENT_ID: "kJlsd66DLTnENE8p7Ru2JwqZg1Sie4yZ",
|
|
@@ -788,92 +788,95 @@ async function findAvailablePort() {
|
|
|
788
788
|
async function startOAuthCallbackServer(expectedState) {
|
|
789
789
|
const port = await findAvailablePort();
|
|
790
790
|
const timeout = OAUTH_CONFIG.TIMEOUT_MS;
|
|
791
|
-
|
|
791
|
+
const callbackUrl = `http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`;
|
|
792
|
+
return new Promise((resolveHandle, rejectHandle) => {
|
|
792
793
|
let server = null;
|
|
793
794
|
let timeoutId = null;
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (server) {
|
|
799
|
-
if (typeof server.closeAllConnections === "function") {
|
|
800
|
-
server.closeAllConnections();
|
|
801
|
-
}
|
|
802
|
-
server.close(() => {
|
|
803
|
-
logger.debug("OAuth server closed");
|
|
804
|
-
});
|
|
805
|
-
server.unref();
|
|
806
|
-
}
|
|
807
|
-
};
|
|
808
|
-
const handleRequest = (req, res) => {
|
|
809
|
-
const parsedUrl = parse(req.url || "", true);
|
|
810
|
-
logger.debug(`OAuth callback received: ${req.url}`);
|
|
811
|
-
if (parsedUrl.pathname === OAUTH_CONFIG.CALLBACK_PATH) {
|
|
812
|
-
const { code, state, error, error_description } = parsedUrl.query;
|
|
813
|
-
if (error) {
|
|
814
|
-
const errorMsg = error_description || error;
|
|
815
|
-
logger.debug(`OAuth error: ${errorMsg}`);
|
|
816
|
-
res.writeHead(400, { "Content-Type": "text/html" });
|
|
817
|
-
res.end(ERROR_HTML(String(errorMsg)));
|
|
818
|
-
cleanup();
|
|
819
|
-
reject(new OAuthError(`OAuth error: ${errorMsg}`));
|
|
820
|
-
return;
|
|
795
|
+
const resultPromise = new Promise((resolveResult, rejectResult) => {
|
|
796
|
+
const cleanup = () => {
|
|
797
|
+
if (timeoutId) {
|
|
798
|
+
globalThis.clearTimeout(timeoutId);
|
|
821
799
|
}
|
|
822
|
-
if (
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
800
|
+
if (server) {
|
|
801
|
+
if (typeof server.closeAllConnections === "function") {
|
|
802
|
+
server.closeAllConnections();
|
|
803
|
+
}
|
|
804
|
+
server.close(() => {
|
|
805
|
+
logger.debug("OAuth server closed");
|
|
806
|
+
});
|
|
807
|
+
server.unref();
|
|
830
808
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
809
|
+
};
|
|
810
|
+
const handleRequest = (req, res) => {
|
|
811
|
+
const parsedUrl = parse(req.url || "", true);
|
|
812
|
+
logger.debug(`OAuth callback received: ${req.url}`);
|
|
813
|
+
if (parsedUrl.pathname === OAUTH_CONFIG.CALLBACK_PATH) {
|
|
814
|
+
const { code, state, error, error_description } = parsedUrl.query;
|
|
815
|
+
if (error) {
|
|
816
|
+
const errorMsg = error_description || error;
|
|
817
|
+
logger.debug(`OAuth error: ${errorMsg}`);
|
|
818
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
819
|
+
res.end(ERROR_HTML(String(errorMsg)));
|
|
820
|
+
cleanup();
|
|
821
|
+
rejectResult(new OAuthError(`OAuth error: ${errorMsg}`));
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (!code || !state) {
|
|
825
|
+
const errorMsg = "Missing code or state parameter";
|
|
826
|
+
logger.debug(errorMsg);
|
|
827
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
828
|
+
res.end(ERROR_HTML(errorMsg));
|
|
829
|
+
cleanup();
|
|
830
|
+
rejectResult(new OAuthError(errorMsg));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
if (state !== expectedState) {
|
|
834
|
+
const errorMsg = "Invalid state parameter (possible CSRF attack)";
|
|
835
|
+
logger.debug(errorMsg);
|
|
836
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
837
|
+
res.end(ERROR_HTML(errorMsg));
|
|
838
|
+
cleanup();
|
|
839
|
+
rejectResult(new OAuthError(errorMsg));
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
843
|
+
res.end(SUCCESS_HTML);
|
|
844
|
+
globalThis.setTimeout(() => {
|
|
845
|
+
cleanup();
|
|
846
|
+
resolveResult({
|
|
847
|
+
code: String(code),
|
|
848
|
+
state: String(state),
|
|
849
|
+
port
|
|
850
|
+
});
|
|
851
|
+
}, 100);
|
|
838
852
|
return;
|
|
839
853
|
}
|
|
840
|
-
res.writeHead(
|
|
841
|
-
res.end(
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`
|
|
864
|
-
);
|
|
854
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
855
|
+
res.end("Not Found");
|
|
856
|
+
};
|
|
857
|
+
server = createServer(handleRequest);
|
|
858
|
+
server.on("error", (error) => {
|
|
859
|
+
logger.debug(`OAuth server error: ${error.message}`);
|
|
860
|
+
cleanup();
|
|
861
|
+
rejectResult(new OAuthError(`OAuth server error: ${error.message}`));
|
|
862
|
+
rejectHandle(new OAuthError(`OAuth server error: ${error.message}`));
|
|
863
|
+
});
|
|
864
|
+
server.listen(port, "127.0.0.1", () => {
|
|
865
|
+
logger.debug(
|
|
866
|
+
`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`
|
|
867
|
+
);
|
|
868
|
+
resolveHandle({ callbackUrl, resultPromise });
|
|
869
|
+
});
|
|
870
|
+
timeoutId = globalThis.setTimeout(() => {
|
|
871
|
+
logger.debug("OAuth callback timeout");
|
|
872
|
+
cleanup();
|
|
873
|
+
rejectResult(
|
|
874
|
+
new OAuthError("Authentication timeout - no callback received within 2 minutes")
|
|
875
|
+
);
|
|
876
|
+
}, timeout);
|
|
865
877
|
});
|
|
866
|
-
timeoutId = globalThis.setTimeout(() => {
|
|
867
|
-
logger.debug("OAuth callback timeout");
|
|
868
|
-
cleanup();
|
|
869
|
-
reject(new OAuthError("Authentication timeout - no callback received within 2 minutes"));
|
|
870
|
-
}, timeout);
|
|
871
878
|
});
|
|
872
879
|
}
|
|
873
|
-
async function getCallbackUrl() {
|
|
874
|
-
const port = await findAvailablePort();
|
|
875
|
-
return `http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`;
|
|
876
|
-
}
|
|
877
880
|
var SUCCESS_HTML, ERROR_HTML;
|
|
878
881
|
var init_oauth_server = __esm({
|
|
879
882
|
"src/utils/oauth-server.ts"() {
|
|
@@ -1136,7 +1139,7 @@ var init_auth_service = __esm({
|
|
|
1136
1139
|
async login() {
|
|
1137
1140
|
logger.debug("Starting OAuth login flow");
|
|
1138
1141
|
const state = this.generateState();
|
|
1139
|
-
const callbackUrl = await
|
|
1142
|
+
const { callbackUrl, resultPromise } = await startOAuthCallbackServer(state);
|
|
1140
1143
|
storageService.setOAuthState({
|
|
1141
1144
|
state,
|
|
1142
1145
|
createdAt: Date.now()
|
|
@@ -1145,7 +1148,6 @@ var init_auth_service = __esm({
|
|
|
1145
1148
|
logger.debug(`Callback URL: ${callbackUrl}`);
|
|
1146
1149
|
const authUrl = await this.buildAuthUrl(state, callbackUrl);
|
|
1147
1150
|
logger.debug(`Authorization URL: ${authUrl}`);
|
|
1148
|
-
const serverPromise = startOAuthCallbackServer(state);
|
|
1149
1151
|
try {
|
|
1150
1152
|
await openBrowser(authUrl);
|
|
1151
1153
|
} catch {
|
|
@@ -1155,7 +1157,7 @@ var init_auth_service = __esm({
|
|
|
1155
1157
|
}
|
|
1156
1158
|
let callbackResult;
|
|
1157
1159
|
try {
|
|
1158
|
-
callbackResult = await
|
|
1160
|
+
callbackResult = await resultPromise;
|
|
1159
1161
|
} catch (error) {
|
|
1160
1162
|
storageService.deleteOAuthState();
|
|
1161
1163
|
throw error;
|
|
@@ -1833,7 +1835,7 @@ var AtlassianAuthService = class {
|
|
|
1833
1835
|
async login() {
|
|
1834
1836
|
logger.debug("Starting Atlassian OAuth login flow");
|
|
1835
1837
|
const state = this.generateState();
|
|
1836
|
-
const callbackUrl = await
|
|
1838
|
+
const { callbackUrl, resultPromise } = await startOAuthCallbackServer(state);
|
|
1837
1839
|
storageService.setOAuthState({
|
|
1838
1840
|
state,
|
|
1839
1841
|
createdAt: Date.now()
|
|
@@ -1842,7 +1844,6 @@ var AtlassianAuthService = class {
|
|
|
1842
1844
|
logger.debug(`Callback URL: ${callbackUrl}`);
|
|
1843
1845
|
const authUrl = this.buildAuthUrl(state, callbackUrl);
|
|
1844
1846
|
logger.debug(`Authorization URL: ${authUrl}`);
|
|
1845
|
-
const serverPromise = startOAuthCallbackServer(state);
|
|
1846
1847
|
try {
|
|
1847
1848
|
await openBrowser(authUrl);
|
|
1848
1849
|
} catch {
|
|
@@ -1852,7 +1853,7 @@ var AtlassianAuthService = class {
|
|
|
1852
1853
|
}
|
|
1853
1854
|
let callbackResult;
|
|
1854
1855
|
try {
|
|
1855
|
-
callbackResult = await
|
|
1856
|
+
callbackResult = await resultPromise;
|
|
1856
1857
|
} catch (error) {
|
|
1857
1858
|
storageService.deleteOAuthState();
|
|
1858
1859
|
throw error;
|
|
@@ -2866,7 +2867,7 @@ Services configured:
|
|
|
2866
2867
|
// src/commands/sync.ts
|
|
2867
2868
|
init_esm_shims();
|
|
2868
2869
|
|
|
2869
|
-
// node_modules/@inquirer/core/dist/esm/lib/errors.mjs
|
|
2870
|
+
// ../../node_modules/.pnpm/@inquirer+core@9.2.1/node_modules/@inquirer/core/dist/esm/lib/errors.mjs
|
|
2870
2871
|
init_esm_shims();
|
|
2871
2872
|
var CancelPromptError = class extends Error {
|
|
2872
2873
|
name = "CancelPromptError";
|
|
@@ -2878,7 +2879,7 @@ init_api_service();
|
|
|
2878
2879
|
init_storage_service();
|
|
2879
2880
|
init_auth_service();
|
|
2880
2881
|
import { select as select4 } from "@inquirer/prompts";
|
|
2881
|
-
import
|
|
2882
|
+
import boxen5 from "boxen";
|
|
2882
2883
|
|
|
2883
2884
|
// src/utils/source-detector.ts
|
|
2884
2885
|
init_esm_shims();
|
|
@@ -4758,138 +4759,13 @@ init_logger();
|
|
|
4758
4759
|
// src/utils/auth-helper.ts
|
|
4759
4760
|
init_esm_shims();
|
|
4760
4761
|
init_auth_service();
|
|
4761
|
-
import
|
|
4762
|
-
|
|
4763
|
-
// src/commands/init.ts
|
|
4764
|
-
init_esm_shims();
|
|
4765
|
-
init_auth_service();
|
|
4766
|
-
init_logger();
|
|
4767
|
-
import ora from "ora";
|
|
4768
|
-
import boxen3 from "boxen";
|
|
4769
|
-
import chalk5 from "chalk";
|
|
4770
|
-
async function initCommand() {
|
|
4771
|
-
logger.log("");
|
|
4772
|
-
logger.log(
|
|
4773
|
-
boxen3(
|
|
4774
|
-
chalk5.yellow.bold("\u26A0 Deprecation Notice") + `
|
|
4775
|
-
|
|
4776
|
-
The ${chalk5.cyan("init")} command is deprecated.
|
|
4777
|
-
Please use ${chalk5.cyan("bragduck auth login")} instead.
|
|
4778
|
-
|
|
4779
|
-
` + chalk5.dim("This command will be removed in v3.0.0"),
|
|
4780
|
-
{
|
|
4781
|
-
padding: 1,
|
|
4782
|
-
borderStyle: "round",
|
|
4783
|
-
borderColor: "yellow",
|
|
4784
|
-
dimBorder: true
|
|
4785
|
-
}
|
|
4786
|
-
)
|
|
4787
|
-
);
|
|
4788
|
-
logger.log("");
|
|
4789
|
-
logger.info("Starting authentication flow...");
|
|
4790
|
-
logger.log("");
|
|
4791
|
-
const isAuthenticated = await authService.isAuthenticated();
|
|
4792
|
-
if (isAuthenticated) {
|
|
4793
|
-
const userInfo = authService.getUserInfo();
|
|
4794
|
-
if (userInfo) {
|
|
4795
|
-
logger.log(
|
|
4796
|
-
boxen3(
|
|
4797
|
-
`${chalk5.yellow("Already authenticated!")}
|
|
4798
|
-
|
|
4799
|
-
${chalk5.gray("User:")} ${userInfo.name}
|
|
4800
|
-
${chalk5.gray("Email:")} ${userInfo.email}
|
|
4801
|
-
|
|
4802
|
-
${chalk5.dim("Run")} ${chalk5.cyan("bragduck logout")} ${chalk5.dim("to sign out")}`,
|
|
4803
|
-
{
|
|
4804
|
-
padding: 1,
|
|
4805
|
-
margin: 1,
|
|
4806
|
-
borderStyle: "round",
|
|
4807
|
-
borderColor: "yellow"
|
|
4808
|
-
}
|
|
4809
|
-
)
|
|
4810
|
-
);
|
|
4811
|
-
logger.log("");
|
|
4812
|
-
globalThis.setTimeout(() => {
|
|
4813
|
-
process.exit(0);
|
|
4814
|
-
}, 100);
|
|
4815
|
-
return;
|
|
4816
|
-
}
|
|
4817
|
-
}
|
|
4818
|
-
const spinner = ora("Opening browser for authentication...").start();
|
|
4819
|
-
try {
|
|
4820
|
-
spinner.text = "Waiting for authentication...";
|
|
4821
|
-
const userInfo = await authService.login();
|
|
4822
|
-
spinner.succeed("Authentication successful!");
|
|
4823
|
-
logger.log("");
|
|
4824
|
-
logger.log(
|
|
4825
|
-
boxen3(
|
|
4826
|
-
`${chalk5.green.bold("\u2713 Successfully authenticated!")}
|
|
4827
|
-
|
|
4828
|
-
${chalk5.gray("Welcome,")} ${chalk5.cyan(userInfo.name)}
|
|
4829
|
-
${chalk5.gray("Email:")} ${userInfo.email}
|
|
4830
|
-
|
|
4831
|
-
${chalk5.dim("You can now use")} ${chalk5.cyan("bragduck scan")} ${chalk5.dim("to create brags!")}`,
|
|
4832
|
-
{
|
|
4833
|
-
padding: 1,
|
|
4834
|
-
margin: 1,
|
|
4835
|
-
borderStyle: "round",
|
|
4836
|
-
borderColor: "green"
|
|
4837
|
-
}
|
|
4838
|
-
)
|
|
4839
|
-
);
|
|
4840
|
-
logger.log("");
|
|
4841
|
-
globalThis.setTimeout(() => {
|
|
4842
|
-
process.exit(0);
|
|
4843
|
-
}, 100);
|
|
4844
|
-
return;
|
|
4845
|
-
} catch (error) {
|
|
4846
|
-
spinner.fail("Authentication failed");
|
|
4847
|
-
logger.log("");
|
|
4848
|
-
const err = error;
|
|
4849
|
-
logger.log(
|
|
4850
|
-
boxen3(
|
|
4851
|
-
`${chalk5.red.bold("\u2717 Authentication Failed")}
|
|
4852
|
-
|
|
4853
|
-
${err.message}
|
|
4854
|
-
|
|
4855
|
-
${chalk5.dim("Hint:")} ${getErrorHint(err)}`,
|
|
4856
|
-
{
|
|
4857
|
-
padding: 1,
|
|
4858
|
-
margin: 1,
|
|
4859
|
-
borderStyle: "round",
|
|
4860
|
-
borderColor: "red"
|
|
4861
|
-
}
|
|
4862
|
-
)
|
|
4863
|
-
);
|
|
4864
|
-
process.exit(1);
|
|
4865
|
-
}
|
|
4866
|
-
}
|
|
4867
|
-
function getErrorHint(error) {
|
|
4868
|
-
if (error.name === "OAuthError") {
|
|
4869
|
-
if (error.message.includes("timeout")) {
|
|
4870
|
-
return "Try again and complete the authentication within 2 minutes";
|
|
4871
|
-
}
|
|
4872
|
-
if (error.message.includes("CSRF")) {
|
|
4873
|
-
return "This might be a security issue. Try running the command again";
|
|
4874
|
-
}
|
|
4875
|
-
return "Check your internet connection and try again";
|
|
4876
|
-
}
|
|
4877
|
-
if (error.name === "NetworkError") {
|
|
4878
|
-
return "Check your internet connection and firewall settings";
|
|
4879
|
-
}
|
|
4880
|
-
if (error.name === "AuthenticationError") {
|
|
4881
|
-
return "Verify your credentials and try again";
|
|
4882
|
-
}
|
|
4883
|
-
return "Try running the command again or check the logs with DEBUG=* bragduck init";
|
|
4884
|
-
}
|
|
4885
|
-
|
|
4886
|
-
// src/utils/auth-helper.ts
|
|
4762
|
+
import boxen4 from "boxen";
|
|
4887
4763
|
init_logger();
|
|
4888
4764
|
|
|
4889
4765
|
// src/ui/prompts.ts
|
|
4890
4766
|
init_esm_shims();
|
|
4891
4767
|
import { checkbox, confirm, input as input2, select as select3, editor } from "@inquirer/prompts";
|
|
4892
|
-
import
|
|
4768
|
+
import boxen3 from "boxen";
|
|
4893
4769
|
|
|
4894
4770
|
// src/ui/formatters.ts
|
|
4895
4771
|
init_esm_shims();
|
|
@@ -4978,7 +4854,13 @@ function formatRefinedCommitsTable(brags, selectedCommits) {
|
|
|
4978
4854
|
} else {
|
|
4979
4855
|
displaySha = `#${index + 1}`;
|
|
4980
4856
|
}
|
|
4981
|
-
|
|
4857
|
+
let original;
|
|
4858
|
+
if (isNewBragType) {
|
|
4859
|
+
const input3 = brag.original_input;
|
|
4860
|
+
original = typeof input3 === "string" ? input3.split("\n")[0] || "" : "Raw input";
|
|
4861
|
+
} else {
|
|
4862
|
+
original = brag.original_message.split("\n")[0] || "";
|
|
4863
|
+
}
|
|
4982
4864
|
const title = brag.refined_title;
|
|
4983
4865
|
const description = brag.refined_description.length > 100 ? brag.refined_description.substring(0, 97) + "..." : brag.refined_description;
|
|
4984
4866
|
const tags = (brag.suggested_tags || []).join(", ") || "none";
|
|
@@ -5231,7 +5113,7 @@ ${theme.label("Impact Score")} ${colors.highlight(impactScore)}`;
|
|
|
5231
5113
|
|
|
5232
5114
|
${theme.label("PR Link")} ${colors.link(prUrl)}`;
|
|
5233
5115
|
}
|
|
5234
|
-
console.log(
|
|
5116
|
+
console.log(boxen3(bragDetails, boxStyles.info));
|
|
5235
5117
|
console.log("");
|
|
5236
5118
|
const action = await select3({
|
|
5237
5119
|
message: `What would you like to do with this brag?`,
|
|
@@ -5308,7 +5190,7 @@ async function ensureAuthenticated() {
|
|
|
5308
5190
|
}
|
|
5309
5191
|
logger.log("");
|
|
5310
5192
|
logger.log(
|
|
5311
|
-
|
|
5193
|
+
boxen4(
|
|
5312
5194
|
theme.warning("Not authenticated") + "\n\nYou need to be logged in to use this command.\n\nWould you like to authenticate now?",
|
|
5313
5195
|
boxStyles.warning
|
|
5314
5196
|
)
|
|
@@ -5324,7 +5206,7 @@ async function ensureAuthenticated() {
|
|
|
5324
5206
|
return false;
|
|
5325
5207
|
}
|
|
5326
5208
|
try {
|
|
5327
|
-
await
|
|
5209
|
+
await authCommand("login");
|
|
5328
5210
|
return true;
|
|
5329
5211
|
} catch {
|
|
5330
5212
|
return false;
|
|
@@ -5333,9 +5215,9 @@ async function ensureAuthenticated() {
|
|
|
5333
5215
|
|
|
5334
5216
|
// src/ui/spinners.ts
|
|
5335
5217
|
init_esm_shims();
|
|
5336
|
-
import
|
|
5218
|
+
import ora from "ora";
|
|
5337
5219
|
function createSpinner(text) {
|
|
5338
|
-
return
|
|
5220
|
+
return ora({
|
|
5339
5221
|
text,
|
|
5340
5222
|
color: "cyan",
|
|
5341
5223
|
spinner: "dots"
|
|
@@ -5343,7 +5225,7 @@ function createSpinner(text) {
|
|
|
5343
5225
|
}
|
|
5344
5226
|
function createStepSpinner(currentStep, totalSteps, text) {
|
|
5345
5227
|
const stepIndicator = theme.step(currentStep, totalSteps);
|
|
5346
|
-
return
|
|
5228
|
+
return ora({
|
|
5347
5229
|
text: `${stepIndicator} ${text}`,
|
|
5348
5230
|
color: "cyan",
|
|
5349
5231
|
spinner: "dots"
|
|
@@ -5646,7 +5528,10 @@ async function syncSingleRepository(repo, days, sortOption, scanMode, orgId, opt
|
|
|
5646
5528
|
repository: repoInfo.url,
|
|
5647
5529
|
date: originalCommit?.date || (/* @__PURE__ */ new Date()).toISOString(),
|
|
5648
5530
|
commit_url: originalCommit?.url || "",
|
|
5531
|
+
impactLevel: refined.suggested_impactLevel,
|
|
5532
|
+
typeId: refined.suggested_typeId,
|
|
5649
5533
|
impact_score: refined.suggested_impactLevel,
|
|
5534
|
+
impactDescription: refined.impact_description,
|
|
5650
5535
|
impact_description: refined.impact_description,
|
|
5651
5536
|
attachments: originalCommit?.url ? [originalCommit.url] : [],
|
|
5652
5537
|
orgId: orgId || void 0,
|
|
@@ -6056,7 +5941,10 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
6056
5941
|
repository: repoInfo.url,
|
|
6057
5942
|
date: originalCommit?.date || (/* @__PURE__ */ new Date()).toISOString(),
|
|
6058
5943
|
commit_url: originalCommit?.url || "",
|
|
5944
|
+
impactLevel: refined.suggested_impactLevel,
|
|
5945
|
+
typeId: refined.suggested_typeId,
|
|
6059
5946
|
impact_score: refined.suggested_impactLevel,
|
|
5947
|
+
impactDescription: refined.impact_description,
|
|
6060
5948
|
impact_description: refined.impact_description,
|
|
6061
5949
|
attachments: originalCommit?.url ? [originalCommit.url] : [],
|
|
6062
5950
|
orgId: selectedOrgId || void 0,
|
|
@@ -6260,10 +6148,10 @@ async function syncAllAuthenticatedServices(options) {
|
|
|
6260
6148
|
}
|
|
6261
6149
|
if (totalCreated > 0) {
|
|
6262
6150
|
const allCreatedBrags = results.filter((r) => r.createdBrags).flatMap((r) => r.createdBrags);
|
|
6263
|
-
logger.log(
|
|
6151
|
+
logger.log(boxen5(formatSuccessMessage(totalCreated, allCreatedBrags), boxStyles.success));
|
|
6264
6152
|
} else if (successful.length > 0) {
|
|
6265
6153
|
logger.log(
|
|
6266
|
-
|
|
6154
|
+
boxen5(
|
|
6267
6155
|
theme.secondary("No new brags created (all items already exist or were skipped)"),
|
|
6268
6156
|
boxStyles.info
|
|
6269
6157
|
)
|
|
@@ -6287,7 +6175,7 @@ async function syncCommand(options = {}) {
|
|
|
6287
6175
|
logger.debug("FREE tier detected - blocking sync command");
|
|
6288
6176
|
logger.log("");
|
|
6289
6177
|
logger.log(
|
|
6290
|
-
|
|
6178
|
+
boxen5(
|
|
6291
6179
|
theme.warning("CLI Access Requires Subscription") + "\n\nThe Bragduck CLI is available for Plus and Pro subscribers.\nUpgrade now to unlock:\n\n \u2022 Automatic work item scanning\n \u2022 AI-powered brag generation\n \u2022 Unlimited brags\n\n" + colors.highlight("Start your free trial today"),
|
|
6292
6180
|
{
|
|
6293
6181
|
...boxStyles.warning,
|
|
@@ -6346,7 +6234,7 @@ async function syncCommand(options = {}) {
|
|
|
6346
6234
|
const result2 = await syncMultipleRepositories(repos, options);
|
|
6347
6235
|
if (result2.totalCreated > 0 || result2.totalSkipped > 0) {
|
|
6348
6236
|
logger.log("");
|
|
6349
|
-
logger.log(
|
|
6237
|
+
logger.log(boxen5(formatMultiRepoSummary(result2), boxStyles.success));
|
|
6350
6238
|
} else {
|
|
6351
6239
|
logger.log("");
|
|
6352
6240
|
logger.info("No brags created.");
|
|
@@ -6379,7 +6267,7 @@ async function syncCommand(options = {}) {
|
|
|
6379
6267
|
const result = await syncSingleService(sourceType, options, TOTAL_STEPS);
|
|
6380
6268
|
if (result.created > 0) {
|
|
6381
6269
|
logger.log(
|
|
6382
|
-
|
|
6270
|
+
boxen5(formatSuccessMessage(result.created, result.createdBrags), boxStyles.success)
|
|
6383
6271
|
);
|
|
6384
6272
|
} else if (result.skipped > 0) {
|
|
6385
6273
|
logger.log("");
|
|
@@ -6406,12 +6294,12 @@ async function syncCommand(options = {}) {
|
|
|
6406
6294
|
const err = error;
|
|
6407
6295
|
logger.log("");
|
|
6408
6296
|
logger.log(
|
|
6409
|
-
|
|
6297
|
+
boxen5(formatErrorMessage(err.message, getErrorHint(err, sourceType)), boxStyles.error)
|
|
6410
6298
|
);
|
|
6411
6299
|
process.exit(1);
|
|
6412
6300
|
}
|
|
6413
6301
|
}
|
|
6414
|
-
function
|
|
6302
|
+
function getErrorHint(error, sourceType) {
|
|
6415
6303
|
if (error.name === "GitHubError") {
|
|
6416
6304
|
return 'Make sure you are in a GitHub repository and have authenticated with "gh auth login"';
|
|
6417
6305
|
}
|
|
@@ -6438,17 +6326,17 @@ init_esm_shims();
|
|
|
6438
6326
|
init_auth_service();
|
|
6439
6327
|
init_logger();
|
|
6440
6328
|
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
6441
|
-
import
|
|
6442
|
-
import
|
|
6443
|
-
import
|
|
6329
|
+
import boxen6 from "boxen";
|
|
6330
|
+
import chalk5 from "chalk";
|
|
6331
|
+
import ora2 from "ora";
|
|
6444
6332
|
async function logoutCommand() {
|
|
6445
6333
|
const isAuthenticated = await authService.isAuthenticated();
|
|
6446
6334
|
if (!isAuthenticated) {
|
|
6447
6335
|
logger.log(
|
|
6448
|
-
|
|
6449
|
-
`${
|
|
6336
|
+
boxen6(
|
|
6337
|
+
`${chalk5.yellow("Not currently authenticated")}
|
|
6450
6338
|
|
|
6451
|
-
${
|
|
6339
|
+
${chalk5.dim("Nothing to logout from")}`,
|
|
6452
6340
|
{
|
|
6453
6341
|
padding: 1,
|
|
6454
6342
|
margin: 1,
|
|
@@ -6463,25 +6351,25 @@ ${chalk6.dim("Nothing to logout from")}`,
|
|
|
6463
6351
|
const userName = userInfo?.name || "Unknown User";
|
|
6464
6352
|
logger.log("");
|
|
6465
6353
|
const shouldLogout = await confirm2({
|
|
6466
|
-
message: `Are you sure you want to logout? (${
|
|
6354
|
+
message: `Are you sure you want to logout? (${chalk5.cyan(userName)})`,
|
|
6467
6355
|
default: false
|
|
6468
6356
|
});
|
|
6469
6357
|
if (!shouldLogout) {
|
|
6470
6358
|
logger.info("Logout cancelled");
|
|
6471
6359
|
return;
|
|
6472
6360
|
}
|
|
6473
|
-
const spinner =
|
|
6361
|
+
const spinner = ora2("Logging out...").start();
|
|
6474
6362
|
try {
|
|
6475
6363
|
await authService.logout();
|
|
6476
6364
|
spinner.succeed("Logged out successfully");
|
|
6477
6365
|
logger.log("");
|
|
6478
6366
|
logger.log(
|
|
6479
|
-
|
|
6480
|
-
`${
|
|
6367
|
+
boxen6(
|
|
6368
|
+
`${chalk5.green.bold("\u2713 Logged out successfully")}
|
|
6481
6369
|
|
|
6482
|
-
${
|
|
6370
|
+
${chalk5.dim("Your credentials have been cleared")}
|
|
6483
6371
|
|
|
6484
|
-
${
|
|
6372
|
+
${chalk5.dim("Run")} ${chalk5.cyan("bragduck init")} ${chalk5.dim("to login again")}`,
|
|
6485
6373
|
{
|
|
6486
6374
|
padding: 1,
|
|
6487
6375
|
margin: 1,
|
|
@@ -6497,293 +6385,10 @@ ${chalk6.dim("Run")} ${chalk6.cyan("bragduck init")} ${chalk6.dim("to login agai
|
|
|
6497
6385
|
}
|
|
6498
6386
|
}
|
|
6499
6387
|
|
|
6500
|
-
// src/commands/scan.ts
|
|
6501
|
-
init_esm_shims();
|
|
6502
|
-
import boxen8 from "boxen";
|
|
6503
|
-
import chalk7 from "chalk";
|
|
6504
|
-
init_api_service();
|
|
6505
|
-
init_storage_service();
|
|
6506
|
-
init_logger();
|
|
6507
|
-
init_browser();
|
|
6508
|
-
init_auth_service();
|
|
6509
|
-
async function scanCommand(options = {}) {
|
|
6510
|
-
logger.log("");
|
|
6511
|
-
logger.log(
|
|
6512
|
-
boxen8(
|
|
6513
|
-
chalk7.yellow.bold("\u26A0 Deprecation Notice") + `
|
|
6514
|
-
|
|
6515
|
-
The ${chalk7.cyan("scan")} command is deprecated.
|
|
6516
|
-
Please use ${chalk7.cyan("bragduck sync")} instead.
|
|
6517
|
-
|
|
6518
|
-
` + chalk7.dim("This command will be removed in v3.0.0"),
|
|
6519
|
-
{
|
|
6520
|
-
padding: 1,
|
|
6521
|
-
borderStyle: "round",
|
|
6522
|
-
borderColor: "yellow",
|
|
6523
|
-
dimBorder: true
|
|
6524
|
-
}
|
|
6525
|
-
)
|
|
6526
|
-
);
|
|
6527
|
-
logger.log("");
|
|
6528
|
-
const TOTAL_STEPS = 5;
|
|
6529
|
-
try {
|
|
6530
|
-
const isAuthenticated = await ensureAuthenticated();
|
|
6531
|
-
if (!isAuthenticated) {
|
|
6532
|
-
process.exit(1);
|
|
6533
|
-
}
|
|
6534
|
-
logger.debug("Fetching subscription status...");
|
|
6535
|
-
const subscriptionStatus = await apiService.getSubscriptionStatus();
|
|
6536
|
-
logger.debug("Subscription status response:", JSON.stringify(subscriptionStatus, null, 2));
|
|
6537
|
-
logger.debug(
|
|
6538
|
-
`Checking tier: "${subscriptionStatus.tier}" (type: ${typeof subscriptionStatus.tier})`
|
|
6539
|
-
);
|
|
6540
|
-
logger.debug(`Tier === 'FREE': ${subscriptionStatus.tier === "FREE"}`);
|
|
6541
|
-
if (subscriptionStatus.tier === "FREE") {
|
|
6542
|
-
logger.debug("FREE tier detected - blocking scan command");
|
|
6543
|
-
logger.log("");
|
|
6544
|
-
logger.log(
|
|
6545
|
-
boxen8(
|
|
6546
|
-
theme.warning("CLI Access Requires Subscription") + "\n\nThe Bragduck CLI is available for Plus and Pro subscribers.\nUpgrade now to unlock:\n\n \u2022 Automatic PR scanning\n \u2022 AI-powered brag generation\n \u2022 Unlimited brags\n\n" + colors.highlight("Start your free trial today!"),
|
|
6547
|
-
{
|
|
6548
|
-
...boxStyles.warning,
|
|
6549
|
-
padding: 1,
|
|
6550
|
-
margin: 1
|
|
6551
|
-
}
|
|
6552
|
-
)
|
|
6553
|
-
);
|
|
6554
|
-
logger.log("");
|
|
6555
|
-
const shouldOpenBrowser = await promptConfirm(
|
|
6556
|
-
"Open subscription plans in your browser?",
|
|
6557
|
-
true
|
|
6558
|
-
);
|
|
6559
|
-
if (shouldOpenBrowser) {
|
|
6560
|
-
logger.log("");
|
|
6561
|
-
const plansUrl = "https://bragduck.com/app/settings/plans";
|
|
6562
|
-
try {
|
|
6563
|
-
await openBrowser(plansUrl);
|
|
6564
|
-
logger.info(theme.secondary("Opening browser..."));
|
|
6565
|
-
} catch {
|
|
6566
|
-
logger.warning("Could not open browser automatically");
|
|
6567
|
-
logger.info(`Please visit: ${theme.value(plansUrl)}`);
|
|
6568
|
-
}
|
|
6569
|
-
}
|
|
6570
|
-
logger.log("");
|
|
6571
|
-
return;
|
|
6572
|
-
}
|
|
6573
|
-
logger.debug(`Subscription tier "${subscriptionStatus.tier}" - proceeding with scan`);
|
|
6574
|
-
const repoSpinner = createStepSpinner(1, TOTAL_STEPS, "Validating GitHub repository");
|
|
6575
|
-
repoSpinner.start();
|
|
6576
|
-
await githubService.validateGitHubRepository();
|
|
6577
|
-
const repoInfo = await githubService.getRepositoryInfo();
|
|
6578
|
-
succeedStepSpinner(
|
|
6579
|
-
repoSpinner,
|
|
6580
|
-
1,
|
|
6581
|
-
TOTAL_STEPS,
|
|
6582
|
-
`Repository: ${theme.value(repoInfo.fullName)}`
|
|
6583
|
-
);
|
|
6584
|
-
logger.log("");
|
|
6585
|
-
let days = options.days;
|
|
6586
|
-
if (!days) {
|
|
6587
|
-
const defaultDays = storageService.getConfig("defaultCommitDays");
|
|
6588
|
-
days = await promptDaysToScan(defaultDays);
|
|
6589
|
-
logger.log("");
|
|
6590
|
-
}
|
|
6591
|
-
const prSpinner = createStepSpinner(
|
|
6592
|
-
2,
|
|
6593
|
-
TOTAL_STEPS,
|
|
6594
|
-
`Fetching merged PRs from the last ${days} days`
|
|
6595
|
-
);
|
|
6596
|
-
prSpinner.start();
|
|
6597
|
-
let prs;
|
|
6598
|
-
if (options.all) {
|
|
6599
|
-
prs = await githubService.getMergedPRs({ days });
|
|
6600
|
-
} else {
|
|
6601
|
-
prs = await githubService.getPRsByCurrentUser({ days });
|
|
6602
|
-
}
|
|
6603
|
-
const commits = prs.map((pr) => githubService.transformPRToCommit(pr));
|
|
6604
|
-
if (commits.length === 0) {
|
|
6605
|
-
failStepSpinner(prSpinner, 2, TOTAL_STEPS, `No merged PRs found in the last ${days} days`);
|
|
6606
|
-
logger.log("");
|
|
6607
|
-
logger.info("Try increasing the number of days or check your GitHub activity");
|
|
6608
|
-
return;
|
|
6609
|
-
}
|
|
6610
|
-
succeedStepSpinner(
|
|
6611
|
-
prSpinner,
|
|
6612
|
-
2,
|
|
6613
|
-
TOTAL_STEPS,
|
|
6614
|
-
`Found ${theme.count(commits.length)} PR${commits.length > 1 ? "s" : ""}`
|
|
6615
|
-
);
|
|
6616
|
-
logger.log("");
|
|
6617
|
-
logger.log(formatCommitStats(commits));
|
|
6618
|
-
logger.log("");
|
|
6619
|
-
let sortedCommits = [...commits];
|
|
6620
|
-
if (commits.length > 1) {
|
|
6621
|
-
const sortOption = await promptSortOption();
|
|
6622
|
-
logger.log("");
|
|
6623
|
-
if (sortOption === "date") {
|
|
6624
|
-
sortedCommits.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
6625
|
-
} else if (sortOption === "size") {
|
|
6626
|
-
sortedCommits.sort((a, b) => {
|
|
6627
|
-
const sizeA = (a.diffStats?.insertions || 0) + (a.diffStats?.deletions || 0);
|
|
6628
|
-
const sizeB = (b.diffStats?.insertions || 0) + (b.diffStats?.deletions || 0);
|
|
6629
|
-
return sizeB - sizeA;
|
|
6630
|
-
});
|
|
6631
|
-
} else if (sortOption === "files") {
|
|
6632
|
-
sortedCommits.sort((a, b) => {
|
|
6633
|
-
const filesA = a.diffStats?.filesChanged || 0;
|
|
6634
|
-
const filesB = b.diffStats?.filesChanged || 0;
|
|
6635
|
-
return filesB - filesA;
|
|
6636
|
-
});
|
|
6637
|
-
}
|
|
6638
|
-
}
|
|
6639
|
-
const selectedShas = await promptSelectCommits(sortedCommits);
|
|
6640
|
-
if (selectedShas.length === 0) {
|
|
6641
|
-
logger.log("");
|
|
6642
|
-
logger.info(theme.secondary("No PRs selected. Scan cancelled."));
|
|
6643
|
-
logger.log("");
|
|
6644
|
-
return;
|
|
6645
|
-
}
|
|
6646
|
-
const selectedCommits = sortedCommits.filter((c) => selectedShas.includes(c.sha));
|
|
6647
|
-
logger.log(formatSelectionSummary(selectedCommits.length, selectedCommits));
|
|
6648
|
-
logger.log("");
|
|
6649
|
-
const existingBrags = await apiService.listBrags({ limit: 100 });
|
|
6650
|
-
logger.debug(`Fetched ${existingBrags.brags.length} existing brags`);
|
|
6651
|
-
const existingUrls = new Set(existingBrags.brags.flatMap((b) => b.attachments || []));
|
|
6652
|
-
logger.debug(`Existing PR URLs in attachments: ${existingUrls.size}`);
|
|
6653
|
-
const duplicates = selectedCommits.filter((c) => c.url && existingUrls.has(c.url));
|
|
6654
|
-
const newCommits = selectedCommits.filter((c) => !c.url || !existingUrls.has(c.url));
|
|
6655
|
-
logger.debug(`Duplicates: ${duplicates.length}, New: ${newCommits.length}`);
|
|
6656
|
-
if (duplicates.length > 0) {
|
|
6657
|
-
logger.log("");
|
|
6658
|
-
logger.info(
|
|
6659
|
-
colors.warning(
|
|
6660
|
-
`${duplicates.length} PR${duplicates.length > 1 ? "s" : ""} already added to Bragduck - skipping`
|
|
6661
|
-
)
|
|
6662
|
-
);
|
|
6663
|
-
logger.log("");
|
|
6664
|
-
}
|
|
6665
|
-
if (newCommits.length === 0) {
|
|
6666
|
-
logger.log("");
|
|
6667
|
-
logger.info(
|
|
6668
|
-
theme.secondary("All selected PRs already exist in Bragduck. Nothing to refine.")
|
|
6669
|
-
);
|
|
6670
|
-
logger.log("");
|
|
6671
|
-
return;
|
|
6672
|
-
}
|
|
6673
|
-
const refineSpinner = createStepSpinner(
|
|
6674
|
-
3,
|
|
6675
|
-
TOTAL_STEPS,
|
|
6676
|
-
`Refining ${theme.count(newCommits.length)} PR${newCommits.length > 1 ? "s" : ""} with AI`
|
|
6677
|
-
);
|
|
6678
|
-
refineSpinner.start();
|
|
6679
|
-
const refineRequest = {
|
|
6680
|
-
brags: newCommits.map((c) => ({
|
|
6681
|
-
text: c.message,
|
|
6682
|
-
date: c.date,
|
|
6683
|
-
title: c.message.split("\n")[0]
|
|
6684
|
-
// First line as initial title
|
|
6685
|
-
}))
|
|
6686
|
-
};
|
|
6687
|
-
const refineResponse = await apiService.refineBrags(refineRequest);
|
|
6688
|
-
let refinedBrags = refineResponse.refined_brags;
|
|
6689
|
-
succeedStepSpinner(refineSpinner, 3, TOTAL_STEPS, "PRs refined successfully");
|
|
6690
|
-
logger.log("");
|
|
6691
|
-
logger.info("Preview of refined brags:");
|
|
6692
|
-
logger.log("");
|
|
6693
|
-
logger.log(formatRefinedCommitsTable(refinedBrags, newCommits));
|
|
6694
|
-
logger.log("");
|
|
6695
|
-
const acceptedBrags = await promptReviewBrags(refinedBrags, newCommits);
|
|
6696
|
-
if (acceptedBrags.length === 0) {
|
|
6697
|
-
logger.log("");
|
|
6698
|
-
logger.info(theme.secondary("No brags selected for creation. Scan cancelled."));
|
|
6699
|
-
logger.log("");
|
|
6700
|
-
return;
|
|
6701
|
-
}
|
|
6702
|
-
logger.log("");
|
|
6703
|
-
let selectedOrgId = null;
|
|
6704
|
-
const userInfo = authService.getUserInfo();
|
|
6705
|
-
if (userInfo?.id) {
|
|
6706
|
-
try {
|
|
6707
|
-
const orgsResponse = await apiService.listUserOrganisations(userInfo.id);
|
|
6708
|
-
if (orgsResponse.items.length > 0) {
|
|
6709
|
-
selectedOrgId = await promptSelectOrganisation(orgsResponse.items);
|
|
6710
|
-
logger.log("");
|
|
6711
|
-
}
|
|
6712
|
-
} catch {
|
|
6713
|
-
logger.debug("Failed to fetch organisations, skipping org selection");
|
|
6714
|
-
}
|
|
6715
|
-
}
|
|
6716
|
-
const createSpinner2 = createStepSpinner(
|
|
6717
|
-
4,
|
|
6718
|
-
TOTAL_STEPS,
|
|
6719
|
-
`Creating ${theme.count(acceptedBrags.length)} brag${acceptedBrags.length > 1 ? "s" : ""}`
|
|
6720
|
-
);
|
|
6721
|
-
createSpinner2.start();
|
|
6722
|
-
const createRequest = {
|
|
6723
|
-
brags: acceptedBrags.map((refined, index) => {
|
|
6724
|
-
const originalCommit = newCommits[index];
|
|
6725
|
-
const repoTag = repoInfo.name;
|
|
6726
|
-
const tagsWithRepo = refined.suggested_tags.includes(repoTag) ? refined.suggested_tags : [repoTag, ...refined.suggested_tags];
|
|
6727
|
-
return {
|
|
6728
|
-
commit_sha: originalCommit?.sha || `brag-${index}`,
|
|
6729
|
-
title: refined.refined_title,
|
|
6730
|
-
description: refined.refined_description,
|
|
6731
|
-
tags: tagsWithRepo,
|
|
6732
|
-
repository: repoInfo.url,
|
|
6733
|
-
date: originalCommit?.date || "",
|
|
6734
|
-
commit_url: originalCommit?.url || "",
|
|
6735
|
-
impact_score: refined.suggested_impactLevel,
|
|
6736
|
-
impact_description: refined.impact_description,
|
|
6737
|
-
attachments: originalCommit?.url ? [originalCommit.url] : [],
|
|
6738
|
-
orgId: selectedOrgId || void 0
|
|
6739
|
-
};
|
|
6740
|
-
})
|
|
6741
|
-
};
|
|
6742
|
-
const createResponse = await apiService.createBrags(createRequest);
|
|
6743
|
-
succeedStepSpinner(
|
|
6744
|
-
createSpinner2,
|
|
6745
|
-
4,
|
|
6746
|
-
TOTAL_STEPS,
|
|
6747
|
-
`Created ${theme.count(createResponse.created)} brag${createResponse.created > 1 ? "s" : ""}`
|
|
6748
|
-
);
|
|
6749
|
-
logger.log("");
|
|
6750
|
-
logger.log(boxen8(formatSuccessMessage(createResponse.created), boxStyles.success));
|
|
6751
|
-
} catch (error) {
|
|
6752
|
-
if (error instanceof CancelPromptError) {
|
|
6753
|
-
logger.log("");
|
|
6754
|
-
logger.info(theme.secondary("Scan cancelled."));
|
|
6755
|
-
logger.log("");
|
|
6756
|
-
return;
|
|
6757
|
-
}
|
|
6758
|
-
const err = error;
|
|
6759
|
-
logger.log("");
|
|
6760
|
-
logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
|
|
6761
|
-
process.exit(1);
|
|
6762
|
-
}
|
|
6763
|
-
}
|
|
6764
|
-
function getErrorHint3(error) {
|
|
6765
|
-
if (error.name === "GitHubError") {
|
|
6766
|
-
return 'Make sure you are in a GitHub repository and have authenticated with "gh auth login"';
|
|
6767
|
-
}
|
|
6768
|
-
if (error.name === "GitError") {
|
|
6769
|
-
return "Make sure you are in a git repository. Note: Only GitHub repositories are supported for PR scanning.";
|
|
6770
|
-
}
|
|
6771
|
-
if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
|
|
6772
|
-
return 'Run "bragduck init" to login again';
|
|
6773
|
-
}
|
|
6774
|
-
if (error.name === "NetworkError") {
|
|
6775
|
-
return "Check your internet connection and try again";
|
|
6776
|
-
}
|
|
6777
|
-
if (error.name === "ApiError") {
|
|
6778
|
-
return "The server might be experiencing issues. Try again later";
|
|
6779
|
-
}
|
|
6780
|
-
return "Try running with DEBUG=* for more information";
|
|
6781
|
-
}
|
|
6782
|
-
|
|
6783
6388
|
// src/commands/list.ts
|
|
6784
6389
|
init_esm_shims();
|
|
6785
6390
|
init_api_service();
|
|
6786
|
-
import
|
|
6391
|
+
import boxen7 from "boxen";
|
|
6787
6392
|
import Table2 from "cli-table3";
|
|
6788
6393
|
init_logger();
|
|
6789
6394
|
async function listCommand(options = {}) {
|
|
@@ -6850,7 +6455,7 @@ async function listCommand(options = {}) {
|
|
|
6850
6455
|
} catch (error) {
|
|
6851
6456
|
const err = error;
|
|
6852
6457
|
logger.log("");
|
|
6853
|
-
logger.log(
|
|
6458
|
+
logger.log(boxen7(formatErrorMessage(err.message, getErrorHint2(err)), boxStyles.error));
|
|
6854
6459
|
process.exit(1);
|
|
6855
6460
|
}
|
|
6856
6461
|
}
|
|
@@ -6872,7 +6477,7 @@ function formatBragsTable(brags) {
|
|
|
6872
6477
|
const title = brag.title;
|
|
6873
6478
|
const description = truncateText(brag.description, 100);
|
|
6874
6479
|
const tags = brag.tags.length > 0 ? brag.tags.join(", ") : colors.dim("none");
|
|
6875
|
-
const repository = brag.
|
|
6480
|
+
const repository = brag.externalUrl ? truncateText(extractRepoName(brag.externalUrl), 25) : colors.dim("none");
|
|
6876
6481
|
table.push([
|
|
6877
6482
|
colors.highlight(date),
|
|
6878
6483
|
colors.white(title),
|
|
@@ -6903,7 +6508,7 @@ function extractRepoName(url) {
|
|
|
6903
6508
|
return url;
|
|
6904
6509
|
}
|
|
6905
6510
|
}
|
|
6906
|
-
function
|
|
6511
|
+
function getErrorHint2(error) {
|
|
6907
6512
|
if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
|
|
6908
6513
|
return 'Run "bragduck init" to login again';
|
|
6909
6514
|
}
|
|
@@ -6921,8 +6526,8 @@ init_esm_shims();
|
|
|
6921
6526
|
init_storage_service();
|
|
6922
6527
|
init_logger();
|
|
6923
6528
|
init_constants();
|
|
6924
|
-
import
|
|
6925
|
-
import
|
|
6529
|
+
import boxen8 from "boxen";
|
|
6530
|
+
import chalk6 from "chalk";
|
|
6926
6531
|
import Table3 from "cli-table3";
|
|
6927
6532
|
init_errors();
|
|
6928
6533
|
var VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);
|
|
@@ -6957,7 +6562,7 @@ async function configCommand(subcommand, key, value) {
|
|
|
6957
6562
|
const err = error;
|
|
6958
6563
|
logger.log("");
|
|
6959
6564
|
logger.log(
|
|
6960
|
-
|
|
6565
|
+
boxen8(formatErrorMessage(err.message, getConfigHint(err)), {
|
|
6961
6566
|
padding: 1,
|
|
6962
6567
|
margin: 1,
|
|
6963
6568
|
borderStyle: "round",
|
|
@@ -6978,7 +6583,7 @@ async function handleListConfig() {
|
|
|
6978
6583
|
gitlabInstance: storageService.getConfig("gitlabInstance")
|
|
6979
6584
|
};
|
|
6980
6585
|
const table = new Table3({
|
|
6981
|
-
head: [
|
|
6586
|
+
head: [chalk6.cyan("Key"), chalk6.cyan("Value"), chalk6.cyan("Default")],
|
|
6982
6587
|
colWidths: [25, 40, 40],
|
|
6983
6588
|
wordWrap: true,
|
|
6984
6589
|
style: {
|
|
@@ -6987,61 +6592,61 @@ async function handleListConfig() {
|
|
|
6987
6592
|
}
|
|
6988
6593
|
});
|
|
6989
6594
|
table.push([
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6595
|
+
chalk6.white("defaultCommitDays"),
|
|
6596
|
+
chalk6.yellow(String(config2.defaultCommitDays)),
|
|
6597
|
+
chalk6.dim(String(DEFAULT_CONFIG.defaultCommitDays))
|
|
6993
6598
|
]);
|
|
6994
6599
|
table.push([
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6600
|
+
chalk6.white("autoVersionCheck"),
|
|
6601
|
+
chalk6.yellow(String(config2.autoVersionCheck)),
|
|
6602
|
+
chalk6.dim(String(DEFAULT_CONFIG.autoVersionCheck))
|
|
6998
6603
|
]);
|
|
6999
6604
|
table.push([
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
6605
|
+
chalk6.white("defaultSource"),
|
|
6606
|
+
chalk6.yellow(config2.defaultSource || "not set"),
|
|
6607
|
+
chalk6.dim("not set")
|
|
7003
6608
|
]);
|
|
7004
6609
|
table.push([
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
6610
|
+
chalk6.white("sourcePriority"),
|
|
6611
|
+
chalk6.yellow(config2.sourcePriority ? config2.sourcePriority.join(", ") : "not set"),
|
|
6612
|
+
chalk6.dim("not set")
|
|
7008
6613
|
]);
|
|
7009
6614
|
table.push([
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
6615
|
+
chalk6.white("jiraInstance"),
|
|
6616
|
+
chalk6.yellow(config2.jiraInstance || "not set"),
|
|
6617
|
+
chalk6.dim("not set")
|
|
7013
6618
|
]);
|
|
7014
6619
|
table.push([
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
6620
|
+
chalk6.white("confluenceInstance"),
|
|
6621
|
+
chalk6.yellow(config2.confluenceInstance || "not set"),
|
|
6622
|
+
chalk6.dim("not set")
|
|
7018
6623
|
]);
|
|
7019
6624
|
table.push([
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
6625
|
+
chalk6.white("gitlabInstance"),
|
|
6626
|
+
chalk6.yellow(config2.gitlabInstance || "not set"),
|
|
6627
|
+
chalk6.dim("not set")
|
|
7023
6628
|
]);
|
|
7024
6629
|
logger.info("Current configuration:");
|
|
7025
6630
|
logger.log("");
|
|
7026
6631
|
logger.log(table.toString());
|
|
7027
6632
|
logger.log("");
|
|
7028
|
-
logger.info(
|
|
6633
|
+
logger.info(chalk6.dim("To change a value: ") + chalk6.cyan("bragduck config set <key> <value>"));
|
|
7029
6634
|
logger.log("");
|
|
7030
6635
|
}
|
|
7031
6636
|
async function handleGetConfig(key) {
|
|
7032
6637
|
validateConfigKey(key);
|
|
7033
6638
|
const value = storageService.getConfig(key);
|
|
7034
6639
|
const defaultValue = DEFAULT_CONFIG[key];
|
|
7035
|
-
logger.info(`Configuration for ${
|
|
6640
|
+
logger.info(`Configuration for ${chalk6.cyan(key)}:`);
|
|
7036
6641
|
logger.log("");
|
|
7037
|
-
logger.log(` ${
|
|
7038
|
-
logger.log(` ${
|
|
6642
|
+
logger.log(` ${chalk6.white("Current:")} ${chalk6.yellow(String(value))}`);
|
|
6643
|
+
logger.log(` ${chalk6.white("Default:")} ${chalk6.dim(String(defaultValue))}`);
|
|
7039
6644
|
logger.log("");
|
|
7040
6645
|
if (value === defaultValue) {
|
|
7041
|
-
logger.info(
|
|
6646
|
+
logger.info(chalk6.dim("Using default value"));
|
|
7042
6647
|
} else {
|
|
7043
6648
|
logger.info(
|
|
7044
|
-
|
|
6649
|
+
chalk6.dim("Custom value set. Reset with: ") + chalk6.cyan(`bragduck config set ${key} ${defaultValue}`)
|
|
7045
6650
|
);
|
|
7046
6651
|
}
|
|
7047
6652
|
logger.log("");
|
|
@@ -7051,10 +6656,10 @@ async function handleSetConfig(key, value) {
|
|
|
7051
6656
|
const typedValue = validateAndConvertValue(key, value);
|
|
7052
6657
|
storageService.setConfig(key, typedValue);
|
|
7053
6658
|
logger.log(
|
|
7054
|
-
|
|
7055
|
-
`${
|
|
6659
|
+
boxen8(
|
|
6660
|
+
`${chalk6.green.bold("\u2713 Configuration updated")}
|
|
7056
6661
|
|
|
7057
|
-
${
|
|
6662
|
+
${chalk6.white(key)}: ${chalk6.yellow(String(typedValue))}`,
|
|
7058
6663
|
{
|
|
7059
6664
|
padding: 1,
|
|
7060
6665
|
margin: 1,
|
|
@@ -7156,7 +6761,7 @@ var __dirname7 = dirname6(__filename7);
|
|
|
7156
6761
|
var packageJsonPath = join8(__dirname7, "../../package.json");
|
|
7157
6762
|
var packageJson = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
|
|
7158
6763
|
var program = new Command();
|
|
7159
|
-
program.name("bragduck").description("CLI tool for managing developer achievements and brags\nAliases:
|
|
6764
|
+
program.name("bragduck").description("CLI tool for managing developer achievements and brags\nAliases: duck, brag").version(packageJson.version, "-v, --version", "Display version number").helpOption("-h, --help", "Display help information").option("--skip-version-check", "Skip automatic version check on startup").option("--debug", "Enable debug mode (shows detailed logs)");
|
|
7160
6765
|
program.command("auth [subcommand]").description("Manage authentication (subcommands: login, status, bitbucket, gitlab)").action(async (subcommand) => {
|
|
7161
6766
|
try {
|
|
7162
6767
|
await authCommand(subcommand);
|
|
@@ -7173,22 +6778,6 @@ program.command("sync").description("Sync work items and create brags").option("
|
|
|
7173
6778
|
process.exit(1);
|
|
7174
6779
|
}
|
|
7175
6780
|
});
|
|
7176
|
-
program.command("init").description("Authenticate with Bragduck").action(async () => {
|
|
7177
|
-
try {
|
|
7178
|
-
await initCommand();
|
|
7179
|
-
} catch (error) {
|
|
7180
|
-
console.error(error);
|
|
7181
|
-
process.exit(1);
|
|
7182
|
-
}
|
|
7183
|
-
});
|
|
7184
|
-
program.command("scan").description("Scan git commits and create brags (deprecated, use sync)").option("-d, --days <number>", "Number of days to scan", (val) => parseInt(val, 10)).option("-a, --all", "Include all commits (not just current user)").action(async (options) => {
|
|
7185
|
-
try {
|
|
7186
|
-
await scanCommand(options);
|
|
7187
|
-
} catch (error) {
|
|
7188
|
-
console.error(error);
|
|
7189
|
-
process.exit(1);
|
|
7190
|
-
}
|
|
7191
|
-
});
|
|
7192
6781
|
program.command("list").description("List your existing brags").option("-l, --limit <number>", "Number of brags to display", (val) => parseInt(val, 10), 50).option("-o, --offset <number>", "Number of brags to skip", (val) => parseInt(val, 10), 0).option("-t, --tags <tags>", "Filter by tags (comma-separated)").option("-s, --search <query>", "Search brags by keyword").option("--oneline", "Show only date and title for each brag").action(async (options) => {
|
|
7193
6782
|
try {
|
|
7194
6783
|
await listCommand(options);
|