@bragduck/cli 1.0.3 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,12 +32,10 @@ var init_constants = __esm({
32
32
  config({ path: join(__dirname, "..", "..", ".env") });
33
33
  APP_NAME = "bragduck";
34
34
  CONFIG_KEYS = {
35
- API_BASE_URL: "apiBaseUrl",
36
35
  DEFAULT_COMMIT_DAYS: "defaultCommitDays",
37
36
  AUTO_VERSION_CHECK: "autoVersionCheck"
38
37
  };
39
38
  DEFAULT_CONFIG = {
40
- apiBaseUrl: process.env.API_BASE_URL || "https://api.bragduck.com",
41
39
  defaultCommitDays: 30,
42
40
  autoVersionCheck: true
43
41
  };
@@ -308,7 +306,7 @@ var init_storage_service = __esm({
308
306
  });
309
307
 
310
308
  // src/utils/errors.ts
311
- var BragduckError, AuthenticationError, GitError, ApiError, NetworkError, ValidationError, OAuthError, TokenExpiredError;
309
+ var BragduckError, AuthenticationError, GitError, ApiError, NetworkError, ValidationError, OAuthError, TokenExpiredError, GitHubError;
312
310
  var init_errors = __esm({
313
311
  "src/utils/errors.ts"() {
314
312
  "use strict";
@@ -366,6 +364,12 @@ var init_errors = __esm({
366
364
  this.code = "TOKEN_EXPIRED";
367
365
  }
368
366
  };
367
+ GitHubError = class extends BragduckError {
368
+ constructor(message, details) {
369
+ super(message, "GITHUB_ERROR", details);
370
+ this.name = "GitHubError";
371
+ }
372
+ };
369
373
  }
370
374
  });
371
375
 
@@ -694,8 +698,24 @@ var init_browser = __esm({
694
698
 
695
699
  // src/services/auth.service.ts
696
700
  import { randomBytes as randomBytes2 } from "crypto";
701
+ import { readFileSync as readFileSync2 } from "fs";
702
+ import { fileURLToPath as fileURLToPath3 } from "url";
703
+ import { dirname as dirname2, join as join3 } from "path";
697
704
  import { ofetch } from "ofetch";
698
- var AuthService, authService;
705
+ function getUserAgent() {
706
+ try {
707
+ const packageJsonPath2 = join3(__dirname3, "../../package.json");
708
+ const packageJson2 = JSON.parse(readFileSync2(packageJsonPath2, "utf-8"));
709
+ const version2 = packageJson2.version;
710
+ const platform = process.platform;
711
+ const arch = process.arch;
712
+ return `BragDuck-CLI/${version2} (${platform}-${arch})`;
713
+ } catch (error) {
714
+ logger.debug("Failed to read package.json version");
715
+ return "BragDuck-CLI/2.0.0";
716
+ }
717
+ }
718
+ var __filename3, __dirname3, AuthService, authService;
699
719
  var init_auth_service = __esm({
700
720
  "src/services/auth.service.ts"() {
701
721
  "use strict";
@@ -706,10 +726,12 @@ var init_auth_service = __esm({
706
726
  init_browser();
707
727
  init_errors();
708
728
  init_logger();
729
+ __filename3 = fileURLToPath3(import.meta.url);
730
+ __dirname3 = dirname2(__filename3);
709
731
  AuthService = class {
710
732
  apiBaseUrl;
711
733
  constructor() {
712
- this.apiBaseUrl = process.env.API_BASE_URL || storageService.getConfig("apiBaseUrl") || "https://api.bragduck.com";
734
+ this.apiBaseUrl = process.env.API_BASE_URL || "https://api.bragduck.com";
713
735
  }
714
736
  /**
715
737
  * Generate a random state string for CSRF protection
@@ -745,7 +767,8 @@ var init_auth_service = __esm({
745
767
  grant_type: "authorization_code"
746
768
  },
747
769
  headers: {
748
- "Content-Type": "application/json"
770
+ "Content-Type": "application/json",
771
+ "User-Agent": getUserAgent()
749
772
  }
750
773
  }
751
774
  );
@@ -861,7 +884,8 @@ var init_auth_service = __esm({
861
884
  grant_type: "refresh_token"
862
885
  },
863
886
  headers: {
864
- "Content-Type": "application/json"
887
+ "Content-Type": "application/json",
888
+ "User-Agent": getUserAgent()
865
889
  }
866
890
  }
867
891
  );
@@ -893,15 +917,15 @@ __export(version_exports, {
893
917
  getCurrentVersion: () => getCurrentVersion,
894
918
  version: () => version
895
919
  });
896
- import { readFileSync as readFileSync2 } from "fs";
897
- import { fileURLToPath as fileURLToPath3 } from "url";
898
- import { dirname as dirname2, join as join4 } from "path";
920
+ import { readFileSync as readFileSync3 } from "fs";
921
+ import { fileURLToPath as fileURLToPath4 } from "url";
922
+ import { dirname as dirname3, join as join5 } from "path";
899
923
  import chalk4 from "chalk";
900
924
  import boxen3 from "boxen";
901
925
  function getCurrentVersion() {
902
926
  try {
903
- const packageJsonPath2 = join4(__dirname3, "../../package.json");
904
- const packageJson2 = JSON.parse(readFileSync2(packageJsonPath2, "utf-8"));
927
+ const packageJsonPath2 = join5(__dirname4, "../../package.json");
928
+ const packageJson2 = JSON.parse(readFileSync3(packageJsonPath2, "utf-8"));
905
929
  return packageJson2.version;
906
930
  } catch (error) {
907
931
  logger.debug("Failed to read package.json version");
@@ -983,7 +1007,7 @@ function formatVersion(includePrefix = true) {
983
1007
  const prefix = includePrefix ? "v" : "";
984
1008
  return `${prefix}${version}`;
985
1009
  }
986
- var __filename3, __dirname3, version;
1010
+ var __filename4, __dirname4, version;
987
1011
  var init_version = __esm({
988
1012
  "src/utils/version.ts"() {
989
1013
  "use strict";
@@ -991,40 +1015,68 @@ var init_version = __esm({
991
1015
  init_api_service();
992
1016
  init_storage_service();
993
1017
  init_logger();
994
- __filename3 = fileURLToPath3(import.meta.url);
995
- __dirname3 = dirname2(__filename3);
1018
+ __filename4 = fileURLToPath4(import.meta.url);
1019
+ __dirname4 = dirname3(__filename4);
996
1020
  version = getCurrentVersion();
997
1021
  }
998
1022
  });
999
1023
 
1000
1024
  // src/services/api.service.ts
1001
1025
  import { ofetch as ofetch2 } from "ofetch";
1002
- var ApiService, apiService;
1026
+ import { readFileSync as readFileSync4 } from "fs";
1027
+ import { fileURLToPath as fileURLToPath5 } from "url";
1028
+ import { dirname as dirname4, join as join6 } from "path";
1029
+ function getCliVersion() {
1030
+ try {
1031
+ const packageJsonPath2 = join6(__dirname5, "../../package.json");
1032
+ const packageJson2 = JSON.parse(readFileSync4(packageJsonPath2, "utf-8"));
1033
+ return packageJson2.version;
1034
+ } catch (error) {
1035
+ logger.debug("Failed to read package.json version");
1036
+ return "2.0.0";
1037
+ }
1038
+ }
1039
+ function getPlatformInfo() {
1040
+ const platform = process.platform;
1041
+ const arch = process.arch;
1042
+ return `${platform}-${arch}`;
1043
+ }
1044
+ var __filename5, __dirname5, ApiService, apiService;
1003
1045
  var init_api_service = __esm({
1004
1046
  "src/services/api.service.ts"() {
1005
1047
  "use strict";
1006
1048
  init_esm_shims();
1007
- init_storage_service();
1008
1049
  init_auth_service();
1009
1050
  init_constants();
1010
1051
  init_errors();
1011
1052
  init_logger();
1053
+ __filename5 = fileURLToPath5(import.meta.url);
1054
+ __dirname5 = dirname4(__filename5);
1012
1055
  ApiService = class {
1013
1056
  baseURL;
1014
1057
  client;
1015
1058
  constructor() {
1016
- this.baseURL = process.env.API_BASE_URL || storageService.getConfig("apiBaseUrl");
1059
+ this.baseURL = process.env.API_BASE_URL || "https://api.bragduck.com";
1017
1060
  this.client = ofetch2.create({
1018
1061
  baseURL: this.baseURL,
1019
1062
  // Request interceptor
1020
1063
  onRequest: async ({ options }) => {
1021
1064
  logger.debug(`API Request: ${options.method} ${options.baseURL}${options.url}`);
1065
+ const cliVersion = getCliVersion();
1066
+ const platform = getPlatformInfo();
1067
+ const userAgent = `BragDuck-CLI/${cliVersion} (${platform})`;
1022
1068
  const token = await authService.getAccessToken();
1023
1069
  if (token) {
1024
1070
  options.headers = {
1025
1071
  ...options.headers,
1072
+ "User-Agent": userAgent,
1026
1073
  Authorization: `Bearer ${token}`
1027
1074
  };
1075
+ } else {
1076
+ options.headers = {
1077
+ ...options.headers,
1078
+ "User-Agent": userAgent
1079
+ };
1028
1080
  }
1029
1081
  if (options.method && ["POST", "PUT", "PATCH"].includes(options.method)) {
1030
1082
  options.headers = {
@@ -1204,7 +1256,6 @@ var init_api_service = __esm({
1204
1256
  */
1205
1257
  setBaseURL(url) {
1206
1258
  this.baseURL = url;
1207
- storageService.setConfig("apiBaseUrl", url);
1208
1259
  this.client = ofetch2.create({
1209
1260
  baseURL: url
1210
1261
  });
@@ -1223,9 +1274,9 @@ var init_api_service = __esm({
1223
1274
  // src/cli.ts
1224
1275
  init_esm_shims();
1225
1276
  import { Command } from "commander";
1226
- import { readFileSync as readFileSync3 } from "fs";
1227
- import { fileURLToPath as fileURLToPath4 } from "url";
1228
- import { dirname as dirname3, join as join5 } from "path";
1277
+ import { readFileSync as readFileSync5 } from "fs";
1278
+ import { fileURLToPath as fileURLToPath6 } from "url";
1279
+ import { dirname as dirname5, join as join7 } from "path";
1229
1280
 
1230
1281
  // src/commands/init.ts
1231
1282
  init_esm_shims();
@@ -1399,6 +1450,13 @@ init_esm_shims();
1399
1450
  import boxen4 from "boxen";
1400
1451
  import chalk7 from "chalk";
1401
1452
 
1453
+ // src/services/github.service.ts
1454
+ init_esm_shims();
1455
+ init_errors();
1456
+ init_logger();
1457
+ import { exec as exec2 } from "child_process";
1458
+ import { promisify as promisify2 } from "util";
1459
+
1402
1460
  // src/services/git.service.ts
1403
1461
  init_esm_shims();
1404
1462
  import simpleGit from "simple-git";
@@ -1407,9 +1465,9 @@ import simpleGit from "simple-git";
1407
1465
  init_esm_shims();
1408
1466
  init_errors();
1409
1467
  import { existsSync as existsSync2 } from "fs";
1410
- import { join as join3 } from "path";
1468
+ import { join as join4 } from "path";
1411
1469
  function validateGitRepository(path2) {
1412
- const gitDir = join3(path2, ".git");
1470
+ const gitDir = join4(path2, ".git");
1413
1471
  if (!existsSync2(gitDir)) {
1414
1472
  throw new GitError(
1415
1473
  "Not a git repository. Please run this command from within a git repository.",
@@ -1481,7 +1539,7 @@ var GitService = class {
1481
1539
  * Fetch recent commits
1482
1540
  */
1483
1541
  async getRecentCommits(options = {}) {
1484
- const { days = 30, limit, author, branch } = options;
1542
+ const { days = 30, limit, author } = options;
1485
1543
  try {
1486
1544
  await this.validateRepository();
1487
1545
  logger.debug(`Fetching commits from last ${days} days`);
@@ -1619,6 +1677,203 @@ var GitService = class {
1619
1677
  };
1620
1678
  var gitService = new GitService();
1621
1679
 
1680
+ // src/services/github.service.ts
1681
+ var execAsync2 = promisify2(exec2);
1682
+ var GitHubService = class {
1683
+ MAX_BODY_LENGTH = 5e3;
1684
+ PR_SEARCH_FIELDS = "number,title,body,author,mergedAt,additions,deletions,changedFiles,url,labels";
1685
+ /**
1686
+ * Check if GitHub CLI is installed and available
1687
+ */
1688
+ async checkGitHubCLI() {
1689
+ try {
1690
+ await execAsync2("command gh --version");
1691
+ return true;
1692
+ } catch (_error) {
1693
+ return false;
1694
+ }
1695
+ }
1696
+ /**
1697
+ * Validate that GitHub CLI is installed
1698
+ */
1699
+ async ensureGitHubCLI() {
1700
+ const isInstalled = await this.checkGitHubCLI();
1701
+ if (!isInstalled) {
1702
+ throw new GitHubError("GitHub CLI (gh) is not installed", {
1703
+ hint: "Install from https://cli.github.com/"
1704
+ });
1705
+ }
1706
+ }
1707
+ /**
1708
+ * Check if user is authenticated with GitHub CLI
1709
+ */
1710
+ async checkAuthentication() {
1711
+ try {
1712
+ await execAsync2("command gh auth status");
1713
+ return true;
1714
+ } catch (_error) {
1715
+ return false;
1716
+ }
1717
+ }
1718
+ /**
1719
+ * Ensure user is authenticated with GitHub CLI
1720
+ */
1721
+ async ensureAuthentication() {
1722
+ const isAuthenticated = await this.checkAuthentication();
1723
+ if (!isAuthenticated) {
1724
+ throw new GitHubError("Not authenticated with GitHub", {
1725
+ hint: 'Run "gh auth login" to authenticate'
1726
+ });
1727
+ }
1728
+ }
1729
+ /**
1730
+ * Validate that the current repository is hosted on GitHub
1731
+ */
1732
+ async validateGitHubRepository() {
1733
+ try {
1734
+ await this.ensureGitHubCLI();
1735
+ await this.ensureAuthentication();
1736
+ await gitService.validateRepository();
1737
+ const { stdout } = await execAsync2("command gh repo view --json url");
1738
+ const data = JSON.parse(stdout);
1739
+ if (!data.url) {
1740
+ throw new GitHubError("This repository is not hosted on GitHub", {
1741
+ hint: "Only GitHub repositories are currently supported for PR scanning"
1742
+ });
1743
+ }
1744
+ } catch (error) {
1745
+ if (error instanceof GitHubError || error instanceof GitError) {
1746
+ throw error;
1747
+ }
1748
+ if (error.message?.includes("not a git repository")) {
1749
+ throw new GitHubError("Not a git repository", {
1750
+ hint: "Navigate to a git repository directory"
1751
+ });
1752
+ }
1753
+ if (error.message?.includes("Could not resolve to a Repository")) {
1754
+ throw new GitHubError("This repository is not hosted on GitHub", {
1755
+ hint: "Only GitHub repositories are currently supported for PR scanning"
1756
+ });
1757
+ }
1758
+ throw new GitHubError("Failed to validate GitHub repository", {
1759
+ originalError: error.message
1760
+ });
1761
+ }
1762
+ }
1763
+ /**
1764
+ * Get GitHub repository information
1765
+ */
1766
+ async getRepositoryInfo() {
1767
+ try {
1768
+ await this.ensureGitHubCLI();
1769
+ const { stdout } = await execAsync2(
1770
+ "command gh repo view --json owner,name,url,nameWithOwner"
1771
+ );
1772
+ const data = JSON.parse(stdout);
1773
+ return {
1774
+ owner: data.owner.login,
1775
+ name: data.name,
1776
+ fullName: data.nameWithOwner,
1777
+ url: data.url,
1778
+ isGitHub: true
1779
+ };
1780
+ } catch (error) {
1781
+ if (error instanceof GitHubError || error instanceof GitError) {
1782
+ throw error;
1783
+ }
1784
+ throw new GitHubError("Failed to get GitHub repository information", {
1785
+ originalError: error.message
1786
+ });
1787
+ }
1788
+ }
1789
+ /**
1790
+ * Get the current authenticated GitHub user
1791
+ */
1792
+ async getCurrentGitHubUser() {
1793
+ try {
1794
+ const { stdout } = await execAsync2("command gh api user --jq .login");
1795
+ return stdout.trim() || null;
1796
+ } catch (_error) {
1797
+ logger.debug("Failed to get GitHub user");
1798
+ return null;
1799
+ }
1800
+ }
1801
+ /**
1802
+ * Fetch merged PRs from GitHub
1803
+ */
1804
+ async getMergedPRs(options = {}) {
1805
+ const { days = 30, limit, author } = options;
1806
+ try {
1807
+ await this.ensureGitHubCLI();
1808
+ await this.ensureAuthentication();
1809
+ logger.debug(`Fetching merged PRs from the last ${days} days`);
1810
+ const since = /* @__PURE__ */ new Date();
1811
+ since.setDate(since.getDate() - days);
1812
+ const sinceDate = since.toISOString().split("T")[0];
1813
+ let searchQuery = `merged:>=${sinceDate}`;
1814
+ if (author) {
1815
+ searchQuery += ` author:${author}`;
1816
+ }
1817
+ const limitArg = limit ? `--limit ${limit}` : "";
1818
+ const command = `command gh pr list --state merged --json ${this.PR_SEARCH_FIELDS} --search "${searchQuery}" ${limitArg}`;
1819
+ logger.debug(`Running: ${command}`);
1820
+ const { stdout } = await execAsync2(command);
1821
+ const prs = JSON.parse(stdout);
1822
+ logger.debug(`Found ${prs.length} merged PRs`);
1823
+ return prs;
1824
+ } catch (error) {
1825
+ if (error instanceof GitHubError || error instanceof GitError) {
1826
+ throw error;
1827
+ }
1828
+ throw new GitHubError("Failed to fetch PRs from GitHub", {
1829
+ originalError: error.message,
1830
+ days
1831
+ });
1832
+ }
1833
+ }
1834
+ /**
1835
+ * Get merged PRs by current user (PRs authored by the current user)
1836
+ */
1837
+ async getPRsByCurrentUser(options = {}) {
1838
+ const currentUser = await this.getCurrentGitHubUser();
1839
+ if (!currentUser) {
1840
+ logger.warning("Could not determine GitHub user, returning all PRs");
1841
+ return this.getMergedPRs(options);
1842
+ }
1843
+ logger.debug(`Filtering PRs by author: ${currentUser}`);
1844
+ return this.getMergedPRs({
1845
+ ...options,
1846
+ author: currentUser
1847
+ });
1848
+ }
1849
+ /**
1850
+ * Transform a GitHub PR into a GitCommit structure
1851
+ * This allows PR data to work with existing commit-based UI and API
1852
+ */
1853
+ transformPRToCommit(pr) {
1854
+ const title = pr.title;
1855
+ const body = pr.body || "";
1856
+ const truncatedBody = body.length > this.MAX_BODY_LENGTH ? body.substring(0, this.MAX_BODY_LENGTH) + "...[truncated]" : body;
1857
+ const message = truncatedBody ? `${title}
1858
+
1859
+ ${truncatedBody}` : title;
1860
+ return {
1861
+ sha: `pr-${pr.number}`,
1862
+ message,
1863
+ author: pr.author.login,
1864
+ authorEmail: "",
1865
+ // Not available from gh PR API
1866
+ date: pr.mergedAt,
1867
+ diffStats: {
1868
+ filesChanged: pr.changedFiles,
1869
+ insertions: pr.additions,
1870
+ deletions: pr.deletions
1871
+ }
1872
+ };
1873
+ }
1874
+ };
1875
+ var githubService = new GitHubService();
1876
+
1622
1877
  // src/commands/scan.ts
1623
1878
  init_api_service();
1624
1879
  init_auth_service();
@@ -1635,7 +1890,13 @@ import chalk5 from "chalk";
1635
1890
  import Table from "cli-table3";
1636
1891
  import terminalLink from "terminal-link";
1637
1892
  function formatCommitChoice(commit) {
1638
- const sha = chalk5.yellow(commit.sha.substring(0, 7));
1893
+ let displaySha;
1894
+ if (commit.sha.startsWith("pr-")) {
1895
+ const prNumber = commit.sha.replace("pr-", "#");
1896
+ displaySha = chalk5.yellow(prNumber);
1897
+ } else {
1898
+ displaySha = chalk5.yellow(commit.sha.substring(0, 7));
1899
+ }
1639
1900
  const message = commit.message.split("\n")[0];
1640
1901
  const author = chalk5.gray(`by ${commit.author}`);
1641
1902
  const date = chalk5.gray(new Date(commit.date).toLocaleDateString());
@@ -1646,7 +1907,7 @@ function formatCommitChoice(commit) {
1646
1907
  ` [${filesChanged} files, ${chalk5.green(`+${insertions}`)} ${chalk5.red(`-${deletions}`)}]`
1647
1908
  );
1648
1909
  }
1649
- return `${sha} ${message}${stats}
1910
+ return `${displaySha} ${message}${stats}
1650
1911
  ${author} \u2022 ${date}`;
1651
1912
  }
1652
1913
  function formatRefinedCommitsTable(commits) {
@@ -1721,7 +1982,7 @@ async function promptSelectCommits(commits) {
1721
1982
  checked: false
1722
1983
  }));
1723
1984
  const selected = await checkbox({
1724
- message: "Select commits to brag about (use space to select, enter to confirm):",
1985
+ message: "Select PRs to brag about (use space to select, enter to confirm):",
1725
1986
  choices,
1726
1987
  pageSize: 10,
1727
1988
  loop: false
@@ -1743,7 +2004,7 @@ async function promptDaysToScan(defaultDays = 30) {
1743
2004
  { name: "Custom", value: "custom", description: "Enter custom number of days" }
1744
2005
  ];
1745
2006
  const selected = await select({
1746
- message: "How many days back should we scan for commits?",
2007
+ message: "How many days back should we scan for PRs?",
1747
2008
  choices,
1748
2009
  default: "30"
1749
2010
  });
@@ -1775,8 +2036,8 @@ function createSpinner(text) {
1775
2036
  spinner: "dots"
1776
2037
  });
1777
2038
  }
1778
- function fetchingCommitsSpinner(days) {
1779
- return createSpinner(`Fetching commits from the last ${days} days...`);
2039
+ function fetchingPRsSpinner(days) {
2040
+ return createSpinner(`Fetching merged PRs from the last ${days} days...`);
1780
2041
  }
1781
2042
  function refiningCommitsSpinner(count) {
1782
2043
  return createSpinner(`Refining ${count} commit${count > 1 ? "s" : ""} with AI...`);
@@ -1823,9 +2084,9 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1823
2084
  );
1824
2085
  process.exit(1);
1825
2086
  }
1826
- await gitService.validateRepository();
1827
- const repoInfo = await gitService.getRepositoryInfo();
1828
- logger.info(`Repository: ${chalk7.cyan(repoInfo.currentBranch)} branch`);
2087
+ await githubService.validateGitHubRepository();
2088
+ const repoInfo = await githubService.getRepositoryInfo();
2089
+ logger.info(`Repository: ${chalk7.cyan(repoInfo.fullName)} on GitHub`);
1829
2090
  logger.log("");
1830
2091
  let days = options.days;
1831
2092
  if (!days) {
@@ -1833,21 +2094,22 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1833
2094
  days = await promptDaysToScan(defaultDays);
1834
2095
  logger.log("");
1835
2096
  }
1836
- const spinner = fetchingCommitsSpinner(days);
2097
+ const spinner = fetchingPRsSpinner(days);
1837
2098
  spinner.start();
1838
- let commits;
2099
+ let prs;
1839
2100
  if (options.all) {
1840
- commits = await gitService.getCommitsWithStats({ days });
2101
+ prs = await githubService.getMergedPRs({ days });
1841
2102
  } else {
1842
- commits = await gitService.getCommitsByCurrentUser({ days });
2103
+ prs = await githubService.getPRsByCurrentUser({ days });
1843
2104
  }
2105
+ const commits = prs.map((pr) => githubService.transformPRToCommit(pr));
1844
2106
  if (commits.length === 0) {
1845
- failSpinner(spinner, `No commits found in the last ${days} days`);
2107
+ failSpinner(spinner, `No merged PRs found in the last ${days} days`);
1846
2108
  logger.log("");
1847
- logger.info("Try increasing the number of days or check your git configuration");
2109
+ logger.info("Try increasing the number of days or check your GitHub activity");
1848
2110
  return;
1849
2111
  }
1850
- succeedSpinner(spinner, `Found ${commits.length} commit${commits.length > 1 ? "s" : ""}`);
2112
+ succeedSpinner(spinner, `Found ${commits.length} PR${commits.length > 1 ? "s" : ""}`);
1851
2113
  logger.log("");
1852
2114
  logger.log(formatCommitStats(commits));
1853
2115
  logger.log("");
@@ -1858,9 +2120,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1858
2120
  }
1859
2121
  const selectedCommits = commits.filter((c) => selectedShas.includes(c.sha));
1860
2122
  logger.log("");
1861
- logger.success(
1862
- `Selected ${selectedCommits.length} commit${selectedCommits.length > 1 ? "s" : ""}`
1863
- );
2123
+ logger.success(`Selected ${selectedCommits.length} PR${selectedCommits.length > 1 ? "s" : ""}`);
1864
2124
  logger.log("");
1865
2125
  const refineSpinner = refiningCommitsSpinner(selectedCommits.length);
1866
2126
  refineSpinner.start();
@@ -1879,7 +2139,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1879
2139
  };
1880
2140
  const refineResponse = await apiService.refineCommits(refineRequest);
1881
2141
  const refinedCommits = refineResponse.refined_commits;
1882
- succeedSpinner(refineSpinner, "Commits refined successfully");
2142
+ succeedSpinner(refineSpinner, "PRs refined successfully");
1883
2143
  logger.log("");
1884
2144
  logger.info("Preview of refined brags:");
1885
2145
  logger.log("");
@@ -1901,7 +2161,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1901
2161
  title: refined.refined_title,
1902
2162
  description: refined.refined_description,
1903
2163
  tags: refined.suggested_tags,
1904
- repository: repoInfo.remoteUrl,
2164
+ repository: repoInfo.url,
1905
2165
  date: originalCommit?.date || (/* @__PURE__ */ new Date()).toISOString(),
1906
2166
  commit_url: refined.commit_url,
1907
2167
  impact_score: refined.impact_score,
@@ -1935,8 +2195,11 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
1935
2195
  }
1936
2196
  }
1937
2197
  function getErrorHint2(error) {
2198
+ if (error.name === "GitHubError") {
2199
+ return 'Make sure you are in a GitHub repository and have authenticated with "gh auth login"';
2200
+ }
1938
2201
  if (error.name === "GitError") {
1939
- return "Make sure you are in a git repository with commits";
2202
+ return "Make sure you are in a git repository. Note: Only GitHub repositories are supported for PR scanning.";
1940
2203
  }
1941
2204
  if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
1942
2205
  return 'Run "bragduck init" to login again';
@@ -2102,7 +2365,6 @@ function getErrorHint3(error) {
2102
2365
  // src/commands/config.ts
2103
2366
  init_esm_shims();
2104
2367
  init_storage_service();
2105
- init_api_service();
2106
2368
  init_logger();
2107
2369
  init_constants();
2108
2370
  import boxen6 from "boxen";
@@ -2152,7 +2414,6 @@ async function configCommand(subcommand, key, value) {
2152
2414
  }
2153
2415
  async function handleListConfig() {
2154
2416
  const config2 = {
2155
- apiBaseUrl: storageService.getConfig("apiBaseUrl"),
2156
2417
  defaultCommitDays: storageService.getConfig("defaultCommitDays"),
2157
2418
  autoVersionCheck: storageService.getConfig("autoVersionCheck")
2158
2419
  };
@@ -2165,11 +2426,6 @@ async function handleListConfig() {
2165
2426
  border: ["gray"]
2166
2427
  }
2167
2428
  });
2168
- table.push([
2169
- chalk9.white("apiBaseUrl"),
2170
- chalk9.yellow(config2.apiBaseUrl),
2171
- chalk9.dim(DEFAULT_CONFIG.apiBaseUrl)
2172
- ]);
2173
2429
  table.push([
2174
2430
  chalk9.white("defaultCommitDays"),
2175
2431
  chalk9.yellow(String(config2.defaultCommitDays)),
@@ -2209,9 +2465,6 @@ async function handleSetConfig(key, value) {
2209
2465
  validateConfigKey(key);
2210
2466
  const typedValue = validateAndConvertValue(key, value);
2211
2467
  storageService.setConfig(key, typedValue);
2212
- if (key === CONFIG_KEYS.API_BASE_URL) {
2213
- apiService.setBaseURL(typedValue);
2214
- }
2215
2468
  logger.log(
2216
2469
  boxen6(
2217
2470
  `${chalk9.green.bold("\u2713 Configuration updated")}
@@ -2238,15 +2491,6 @@ ${VALID_CONFIG_KEYS.map((k) => ` - ${k}`).join("\n")}`
2238
2491
  }
2239
2492
  function validateAndConvertValue(key, value) {
2240
2493
  switch (key) {
2241
- case CONFIG_KEYS.API_BASE_URL:
2242
- if (!isValidUrl(value)) {
2243
- throw new ValidationError(
2244
- `Invalid URL format: "${value}"
2245
-
2246
- Example: https://api.bragduck.com`
2247
- );
2248
- }
2249
- return value;
2250
2494
  case CONFIG_KEYS.DEFAULT_COMMIT_DAYS:
2251
2495
  const days = parseInt(value, 10);
2252
2496
  if (isNaN(days) || days < 1 || days > 365) {
@@ -2270,15 +2514,7 @@ Must be a number between 1 and 365`
2270
2514
  Must be one of: true, false, yes, no, 1, 0`
2271
2515
  );
2272
2516
  default:
2273
- return value;
2274
- }
2275
- }
2276
- function isValidUrl(url) {
2277
- try {
2278
- const parsed = new URL(url);
2279
- return parsed.protocol === "http:" || parsed.protocol === "https:";
2280
- } catch {
2281
- return false;
2517
+ throw new ValidationError(`Unknown config key: "${key}"`);
2282
2518
  }
2283
2519
  }
2284
2520
  function getConfigHint(error) {
@@ -2291,10 +2527,10 @@ function getConfigHint(error) {
2291
2527
  // src/cli.ts
2292
2528
  init_version();
2293
2529
  init_logger();
2294
- var __filename4 = fileURLToPath4(import.meta.url);
2295
- var __dirname4 = dirname3(__filename4);
2296
- var packageJsonPath = join5(__dirname4, "../../package.json");
2297
- var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
2530
+ var __filename6 = fileURLToPath6(import.meta.url);
2531
+ var __dirname6 = dirname5(__filename6);
2532
+ var packageJsonPath = join7(__dirname6, "../../package.json");
2533
+ var packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
2298
2534
  var program = new Command();
2299
2535
  program.name("bragduck").description("CLI tool for managing developer achievements and brags").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)");
2300
2536
  program.command("init").description("Authenticate with Bragduck").action(async () => {