@bragduck/cli 2.0.2 → 2.0.3

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.
@@ -312,11 +312,13 @@ var init_errors = __esm({
312
312
  "use strict";
313
313
  init_esm_shims();
314
314
  BragduckError = class extends Error {
315
+ code;
316
+ details;
315
317
  constructor(message, code, details) {
316
318
  super(message);
319
+ this.name = "BragduckError";
317
320
  this.code = code;
318
321
  this.details = details;
319
- this.name = "BragduckError";
320
322
  Error.captureStackTrace(this, this.constructor);
321
323
  }
322
324
  };
@@ -333,10 +335,11 @@ var init_errors = __esm({
333
335
  }
334
336
  };
335
337
  ApiError = class extends BragduckError {
338
+ statusCode;
336
339
  constructor(message, statusCode, details) {
337
340
  super(message, "API_ERROR", details);
338
- this.statusCode = statusCode;
339
341
  this.name = "ApiError";
342
+ this.statusCode = statusCode;
340
343
  }
341
344
  };
342
345
  NetworkError = class extends BragduckError {
@@ -439,7 +442,7 @@ async function findAvailablePort() {
439
442
  testServer.listen(port, "127.0.0.1");
440
443
  });
441
444
  return port;
442
- } catch (error) {
445
+ } catch {
443
446
  continue;
444
447
  }
445
448
  }
@@ -450,10 +453,10 @@ async function startOAuthCallbackServer(expectedState) {
450
453
  const timeout = OAUTH_CONFIG.TIMEOUT_MS;
451
454
  return new Promise((resolve, reject) => {
452
455
  let server = null;
453
- let timeoutId;
456
+ let timeoutId = null;
454
457
  const cleanup = () => {
455
458
  if (timeoutId) {
456
- clearTimeout(timeoutId);
459
+ globalThis.clearTimeout(timeoutId);
457
460
  }
458
461
  if (server) {
459
462
  if (typeof server.closeAllConnections === "function") {
@@ -499,7 +502,7 @@ async function startOAuthCallbackServer(expectedState) {
499
502
  }
500
503
  res.writeHead(200, { "Content-Type": "text/html" });
501
504
  res.end(SUCCESS_HTML);
502
- setTimeout(() => {
505
+ globalThis.setTimeout(() => {
503
506
  cleanup();
504
507
  resolve({
505
508
  code: String(code),
@@ -521,7 +524,7 @@ async function startOAuthCallbackServer(expectedState) {
521
524
  server.listen(port, "127.0.0.1", () => {
522
525
  logger.debug(`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`);
523
526
  });
524
- timeoutId = setTimeout(() => {
527
+ timeoutId = globalThis.setTimeout(() => {
525
528
  logger.debug("OAuth callback timeout");
526
529
  cleanup();
527
530
  reject(new OAuthError("Authentication timeout - no callback received within 2 minutes"));
@@ -699,7 +702,7 @@ var init_browser = __esm({
699
702
  // src/services/auth.service.ts
700
703
  import { randomBytes as randomBytes2 } from "crypto";
701
704
  import { readFileSync as readFileSync2 } from "fs";
702
- import { fileURLToPath as fileURLToPath3 } from "url";
705
+ import { fileURLToPath as fileURLToPath3, URLSearchParams } from "url";
703
706
  import { dirname as dirname2, join as join3 } from "path";
704
707
  import { ofetch } from "ofetch";
705
708
  function getUserAgent() {
@@ -710,7 +713,7 @@ function getUserAgent() {
710
713
  const platform = process.platform;
711
714
  const arch = process.arch;
712
715
  return `BragDuck-CLI/${version2} (${platform}-${arch})`;
713
- } catch (error) {
716
+ } catch {
714
717
  logger.debug("Failed to read package.json version");
715
718
  return "BragDuck-CLI/2.0.0";
716
719
  }
@@ -808,7 +811,7 @@ var init_auth_service = __esm({
808
811
  const serverPromise = startOAuthCallbackServer(state);
809
812
  try {
810
813
  await openBrowser(authUrl);
811
- } catch (error) {
814
+ } catch {
812
815
  logger.warning("Could not open browser automatically");
813
816
  logger.info(`Please open this URL in your browser:`);
814
817
  logger.log(authUrl);
@@ -927,7 +930,7 @@ function getCurrentVersion() {
927
930
  const packageJsonPath2 = join5(__dirname4, "../../package.json");
928
931
  const packageJson2 = JSON.parse(readFileSync3(packageJsonPath2, "utf-8"));
929
932
  return packageJson2.version;
930
- } catch (error) {
933
+ } catch {
931
934
  logger.debug("Failed to read package.json version");
932
935
  return "1.0.0";
933
936
  }
@@ -1025,13 +1028,14 @@ var init_version = __esm({
1025
1028
  import { ofetch as ofetch2 } from "ofetch";
1026
1029
  import { readFileSync as readFileSync4 } from "fs";
1027
1030
  import { fileURLToPath as fileURLToPath5 } from "url";
1031
+ import { URLSearchParams as URLSearchParams2 } from "url";
1028
1032
  import { dirname as dirname4, join as join6 } from "path";
1029
1033
  function getCliVersion() {
1030
1034
  try {
1031
1035
  const packageJsonPath2 = join6(__dirname5, "../../package.json");
1032
1036
  const packageJson2 = JSON.parse(readFileSync4(packageJsonPath2, "utf-8"));
1033
1037
  return packageJson2.version;
1034
- } catch (error) {
1038
+ } catch {
1035
1039
  logger.debug("Failed to read package.json version");
1036
1040
  return "2.0.0";
1037
1041
  }
@@ -1061,29 +1065,23 @@ var init_api_service = __esm({
1061
1065
  baseURL: this.baseURL,
1062
1066
  // Request interceptor
1063
1067
  onRequest: async ({ options }) => {
1064
- logger.debug(`API Request: ${options.method} ${options.baseURL}${options.url}`);
1068
+ const extendedOptions = options;
1069
+ logger.debug(`API Request: ${options.method} ${extendedOptions.baseURL}${extendedOptions.url}`);
1065
1070
  const cliVersion = getCliVersion();
1066
1071
  const platform = getPlatformInfo();
1067
1072
  const userAgent = `BragDuck-CLI/${cliVersion} (${platform})`;
1068
1073
  const token = await authService.getAccessToken();
1074
+ const headers = {
1075
+ ...options.headers,
1076
+ "User-Agent": userAgent
1077
+ };
1069
1078
  if (token) {
1070
- options.headers = {
1071
- ...options.headers,
1072
- "User-Agent": userAgent,
1073
- Authorization: `Bearer ${token}`
1074
- };
1075
- } else {
1076
- options.headers = {
1077
- ...options.headers,
1078
- "User-Agent": userAgent
1079
- };
1079
+ headers.Authorization = `Bearer ${token}`;
1080
1080
  }
1081
1081
  if (options.method && ["POST", "PUT", "PATCH"].includes(options.method)) {
1082
- options.headers = {
1083
- ...options.headers,
1084
- "Content-Type": "application/json"
1085
- };
1082
+ headers["Content-Type"] = "application/json";
1086
1083
  }
1084
+ options.headers = headers;
1087
1085
  },
1088
1086
  // Response interceptor for success
1089
1087
  onResponse: ({ response }) => {
@@ -1092,7 +1090,8 @@ var init_api_service = __esm({
1092
1090
  // Response interceptor for errors
1093
1091
  onResponseError: async ({ response, options }) => {
1094
1092
  const status = response.status;
1095
- const url = `${options.baseURL}${options.url}`;
1093
+ const extendedOptions = options;
1094
+ const url = `${extendedOptions.baseURL}${extendedOptions.url}`;
1096
1095
  logger.debug(`API Error: ${status} ${response.statusText} - ${url}`);
1097
1096
  if (status === HTTP_STATUS.UNAUTHORIZED) {
1098
1097
  logger.debug("Token expired, attempting refresh");
@@ -1164,9 +1163,9 @@ var init_api_service = __esm({
1164
1163
  );
1165
1164
  logger.debug(`Successfully refined ${response.refined_commits.length} commits`);
1166
1165
  return response;
1167
- } catch (error) {
1166
+ } catch (_error) {
1168
1167
  logger.debug("Failed to refine commits");
1169
- throw error;
1168
+ throw _error;
1170
1169
  }
1171
1170
  }
1172
1171
  /**
@@ -1184,9 +1183,9 @@ var init_api_service = __esm({
1184
1183
  );
1185
1184
  logger.debug(`Successfully created ${response.created} brags`);
1186
1185
  return response;
1187
- } catch (error) {
1186
+ } catch (_error) {
1188
1187
  logger.debug("Failed to create brags");
1189
- throw error;
1188
+ throw _error;
1190
1189
  }
1191
1190
  }
1192
1191
  /**
@@ -1196,7 +1195,7 @@ var init_api_service = __esm({
1196
1195
  const { limit = 50, offset = 0, tags, search } = params;
1197
1196
  logger.debug(`Listing brags: limit=${limit}, offset=${offset}`);
1198
1197
  try {
1199
- const queryParams = new URLSearchParams({
1198
+ const queryParams = new URLSearchParams2({
1200
1199
  limit: limit.toString(),
1201
1200
  offset: offset.toString()
1202
1201
  });
@@ -1212,9 +1211,9 @@ var init_api_service = __esm({
1212
1211
  });
1213
1212
  logger.debug(`Successfully fetched ${response.brags.length} brags (total: ${response.total})`);
1214
1213
  return response;
1215
- } catch (error) {
1214
+ } catch (_error) {
1216
1215
  logger.debug("Failed to list brags");
1217
- throw error;
1216
+ throw _error;
1218
1217
  }
1219
1218
  }
1220
1219
  /**
@@ -1231,7 +1230,7 @@ var init_api_service = __esm({
1231
1230
  );
1232
1231
  logger.debug(`Latest version: ${response.latest_version}`);
1233
1232
  return response;
1234
- } catch (error) {
1233
+ } catch {
1235
1234
  logger.debug("Failed to check version");
1236
1235
  const { version: version2 } = await Promise.resolve().then(() => (init_version(), version_exports));
1237
1236
  return {
@@ -1247,7 +1246,7 @@ var init_api_service = __esm({
1247
1246
  try {
1248
1247
  await this.checkVersion();
1249
1248
  return true;
1250
- } catch (error) {
1249
+ } catch {
1251
1250
  return false;
1252
1251
  }
1253
1252
  }
@@ -1310,7 +1309,7 @@ ${chalk2.dim("Run")} ${chalk2.cyan("bragduck logout")} ${chalk2.dim("to sign out
1310
1309
  )
1311
1310
  );
1312
1311
  logger.log("");
1313
- setTimeout(() => {
1312
+ globalThis.setTimeout(() => {
1314
1313
  process.exit(0);
1315
1314
  }, 100);
1316
1315
  return;
@@ -1339,7 +1338,7 @@ ${chalk2.dim("You can now use")} ${chalk2.cyan("bragduck scan")} ${chalk2.dim("t
1339
1338
  )
1340
1339
  );
1341
1340
  logger.log("");
1342
- setTimeout(() => {
1341
+ globalThis.setTimeout(() => {
1343
1342
  process.exit(0);
1344
1343
  }, 100);
1345
1344
  return;
@@ -1438,7 +1437,7 @@ ${chalk3.dim("Run")} ${chalk3.cyan("bragduck init")} ${chalk3.dim("to login agai
1438
1437
  }
1439
1438
  )
1440
1439
  );
1441
- } catch (error) {
1440
+ } catch {
1442
1441
  spinner.fail("Logout failed");
1443
1442
  logger.error("Failed to logout. Please try again.");
1444
1443
  process.exit(1);
@@ -1447,8 +1446,7 @@ ${chalk3.dim("Run")} ${chalk3.cyan("bragduck init")} ${chalk3.dim("to login agai
1447
1446
 
1448
1447
  // src/commands/scan.ts
1449
1448
  init_esm_shims();
1450
- import boxen4 from "boxen";
1451
- import chalk7 from "chalk";
1449
+ import boxen6 from "boxen";
1452
1450
 
1453
1451
  // src/services/github.service.ts
1454
1452
  init_esm_shims();
@@ -1627,7 +1625,7 @@ var GitService = class {
1627
1625
  ...commit,
1628
1626
  diffStats: stats
1629
1627
  };
1630
- } catch (error) {
1628
+ } catch {
1631
1629
  logger.debug(`Failed to get stats for commit ${commit.sha}, continuing without stats`);
1632
1630
  return commit;
1633
1631
  }
@@ -1642,7 +1640,7 @@ var GitService = class {
1642
1640
  try {
1643
1641
  const email = await this.git.raw(["config", "user.email"]);
1644
1642
  return email.trim() || null;
1645
- } catch (error) {
1643
+ } catch {
1646
1644
  logger.debug("Failed to get git user email");
1647
1645
  return null;
1648
1646
  }
@@ -1654,7 +1652,7 @@ var GitService = class {
1654
1652
  try {
1655
1653
  const name = await this.git.raw(["config", "user.name"]);
1656
1654
  return name.trim() || null;
1657
- } catch (error) {
1655
+ } catch {
1658
1656
  logger.debug("Failed to get git user name");
1659
1657
  return null;
1660
1658
  }
@@ -1689,7 +1687,7 @@ var GitHubService = class {
1689
1687
  try {
1690
1688
  await execAsync2("command gh --version");
1691
1689
  return true;
1692
- } catch (_error) {
1690
+ } catch {
1693
1691
  return false;
1694
1692
  }
1695
1693
  }
@@ -1711,7 +1709,7 @@ var GitHubService = class {
1711
1709
  try {
1712
1710
  await execAsync2("command gh auth status");
1713
1711
  return true;
1714
- } catch (_error) {
1712
+ } catch {
1715
1713
  return false;
1716
1714
  }
1717
1715
  }
@@ -1793,7 +1791,7 @@ var GitHubService = class {
1793
1791
  try {
1794
1792
  const { stdout } = await execAsync2("command gh api user --jq .login");
1795
1793
  return stdout.trim() || null;
1796
- } catch (_error) {
1794
+ } catch {
1797
1795
  logger.debug("Failed to get GitHub user");
1798
1796
  return null;
1799
1797
  }
@@ -1876,68 +1874,248 @@ var githubService = new GitHubService();
1876
1874
 
1877
1875
  // src/commands/scan.ts
1878
1876
  init_api_service();
1879
- init_auth_service();
1880
1877
  init_storage_service();
1881
1878
  init_logger();
1882
1879
 
1880
+ // src/utils/auth-helper.ts
1881
+ init_esm_shims();
1882
+ init_auth_service();
1883
+ import boxen5 from "boxen";
1884
+ init_logger();
1885
+
1883
1886
  // src/ui/prompts.ts
1884
1887
  init_esm_shims();
1885
- import { checkbox, confirm as confirm2, input, select } from "@inquirer/prompts";
1888
+ import { checkbox, confirm as confirm2, input, select, editor } from "@inquirer/prompts";
1889
+ import boxen4 from "boxen";
1886
1890
 
1887
1891
  // src/ui/formatters.ts
1888
1892
  init_esm_shims();
1889
- import chalk5 from "chalk";
1890
1893
  import Table from "cli-table3";
1891
1894
  import terminalLink from "terminal-link";
1895
+
1896
+ // src/ui/theme.ts
1897
+ init_esm_shims();
1898
+ import chalk5 from "chalk";
1899
+ var colors = {
1900
+ // Primary colors for main actions and interactive elements
1901
+ primary: chalk5.cyan,
1902
+ // Success states
1903
+ success: chalk5.green,
1904
+ successBold: chalk5.green.bold,
1905
+ // Warning states
1906
+ warning: chalk5.yellow,
1907
+ warningBold: chalk5.yellow.bold,
1908
+ // Error states
1909
+ error: chalk5.red,
1910
+ errorBold: chalk5.red.bold,
1911
+ // Info and metadata
1912
+ info: chalk5.gray,
1913
+ infoDim: chalk5.dim,
1914
+ // Highlighted/important data
1915
+ highlight: chalk5.yellow.bold,
1916
+ highlightCyan: chalk5.cyan.bold,
1917
+ // Text emphasis
1918
+ bold: chalk5.bold,
1919
+ dim: chalk5.dim,
1920
+ // Special purpose
1921
+ white: chalk5.white,
1922
+ gray: chalk5.gray
1923
+ };
1924
+ var theme = {
1925
+ /**
1926
+ * Format command names and CLI actions
1927
+ */
1928
+ command: (text) => colors.primary(text),
1929
+ /**
1930
+ * Format success messages
1931
+ */
1932
+ success: (text) => colors.success(`\u2713 ${text}`),
1933
+ successBold: (text) => colors.successBold(`\u2713 ${text}`),
1934
+ /**
1935
+ * Format error messages
1936
+ */
1937
+ error: (text) => colors.error(`\u2717 ${text}`),
1938
+ errorBold: (text) => colors.errorBold(`\u2717 ${text}`),
1939
+ /**
1940
+ * Format warning messages
1941
+ */
1942
+ warning: (text) => colors.warning(`\u26A0 ${text}`),
1943
+ /**
1944
+ * Format info messages
1945
+ */
1946
+ info: (text) => colors.info(text),
1947
+ /**
1948
+ * Format labels (e.g., "User:", "Email:")
1949
+ */
1950
+ label: (text) => colors.gray(`${text}:`),
1951
+ /**
1952
+ * Format values
1953
+ */
1954
+ value: (text) => colors.highlight(text),
1955
+ /**
1956
+ * Format counts and numbers
1957
+ */
1958
+ count: (num) => colors.highlightCyan(num.toString()),
1959
+ /**
1960
+ * Format file paths
1961
+ */
1962
+ path: (text) => colors.info(text),
1963
+ /**
1964
+ * Format step indicators (e.g., "Step 1/5:")
1965
+ */
1966
+ step: (current, total) => colors.primary(`[${current}/${total}]`),
1967
+ /**
1968
+ * Format progress text
1969
+ */
1970
+ progress: (text) => colors.infoDim(text),
1971
+ /**
1972
+ * Format emphasized text
1973
+ */
1974
+ emphasis: (text) => colors.bold(text),
1975
+ /**
1976
+ * Format de-emphasized/secondary text
1977
+ */
1978
+ secondary: (text) => colors.dim(text),
1979
+ /**
1980
+ * Format interactive elements (prompts, selections)
1981
+ */
1982
+ interactive: (text) => colors.primary(text),
1983
+ /**
1984
+ * Format keys in key-value pairs
1985
+ */
1986
+ key: (text) => colors.white(text)
1987
+ };
1988
+ var boxStyles = {
1989
+ success: {
1990
+ borderColor: "green",
1991
+ borderStyle: "round",
1992
+ padding: 1,
1993
+ margin: 1
1994
+ },
1995
+ error: {
1996
+ borderColor: "red",
1997
+ borderStyle: "round",
1998
+ padding: 1,
1999
+ margin: 1
2000
+ },
2001
+ warning: {
2002
+ borderColor: "yellow",
2003
+ borderStyle: "round",
2004
+ padding: 1,
2005
+ margin: 1
2006
+ },
2007
+ info: {
2008
+ borderColor: "cyan",
2009
+ borderStyle: "round",
2010
+ padding: 1,
2011
+ margin: 1
2012
+ },
2013
+ plain: {
2014
+ borderColor: "gray",
2015
+ borderStyle: "round",
2016
+ padding: 1,
2017
+ margin: 1
2018
+ }
2019
+ };
2020
+ var tableStyles = {
2021
+ default: {
2022
+ style: {
2023
+ head: [],
2024
+ border: ["gray"]
2025
+ }
2026
+ },
2027
+ compact: {
2028
+ style: {
2029
+ head: [],
2030
+ border: ["dim"],
2031
+ compact: true
2032
+ }
2033
+ }
2034
+ };
2035
+ var sizeIndicators = {
2036
+ small: colors.success("\u25CF"),
2037
+ medium: colors.warning("\u25CF"),
2038
+ large: colors.error("\u25CF")
2039
+ };
2040
+ function getSizeIndicator(insertions, deletions) {
2041
+ const total = insertions + deletions;
2042
+ if (total < 50) {
2043
+ return `${sizeIndicators.small} Small`;
2044
+ } else if (total < 200) {
2045
+ return `${sizeIndicators.medium} Medium`;
2046
+ } else {
2047
+ return `${sizeIndicators.large} Large`;
2048
+ }
2049
+ }
2050
+ function formatDiffStats(insertions, deletions) {
2051
+ return `${colors.success(`+${insertions}`)} ${colors.error(`-${deletions}`)}`;
2052
+ }
2053
+
2054
+ // src/ui/formatters.ts
1892
2055
  function formatCommitChoice(commit) {
1893
2056
  let displaySha;
1894
2057
  if (commit.sha.startsWith("pr-")) {
1895
2058
  const prNumber = commit.sha.replace("pr-", "#");
1896
- displaySha = chalk5.yellow(prNumber);
2059
+ displaySha = colors.highlight(prNumber);
1897
2060
  } else {
1898
- displaySha = chalk5.yellow(commit.sha.substring(0, 7));
2061
+ displaySha = colors.highlight(commit.sha.substring(0, 7));
2062
+ }
2063
+ const lines = commit.message.split("\n");
2064
+ const title = lines[0];
2065
+ let bodyPreview = "";
2066
+ if (lines.length > 1) {
2067
+ const body = lines.slice(1).join(" ").trim();
2068
+ if (body.length > 0) {
2069
+ const preview = body.length > 80 ? body.substring(0, 80) + "..." : body;
2070
+ bodyPreview = `
2071
+ ${colors.infoDim(preview)}`;
2072
+ }
1899
2073
  }
1900
- const message = commit.message.split("\n")[0];
1901
- const author = chalk5.gray(`by ${commit.author}`);
1902
- const date = chalk5.gray(new Date(commit.date).toLocaleDateString());
2074
+ const author = colors.info(`by ${commit.author}`);
2075
+ const date = colors.info(new Date(commit.date).toLocaleDateString());
1903
2076
  let stats = "";
2077
+ let sizeIndicator = "";
1904
2078
  if (commit.diffStats) {
1905
2079
  const { filesChanged, insertions, deletions } = commit.diffStats;
1906
- stats = chalk5.gray(
1907
- ` [${filesChanged} files, ${chalk5.green(`+${insertions}`)} ${chalk5.red(`-${deletions}`)}]`
2080
+ sizeIndicator = ` ${getSizeIndicator(insertions, deletions)}`;
2081
+ stats = colors.info(
2082
+ ` [${filesChanged} files, ${formatDiffStats(insertions, deletions)}]`
1908
2083
  );
1909
2084
  }
1910
- return `${displaySha} ${message}${stats}
1911
- ${author} \u2022 ${date}`;
2085
+ return `${displaySha} ${title}${sizeIndicator}${stats}
2086
+ ${author} \u2022 ${date}${bodyPreview}`;
1912
2087
  }
1913
2088
  function formatRefinedCommitsTable(commits) {
1914
2089
  const table = new Table({
1915
2090
  head: [
1916
- chalk5.cyan("SHA"),
1917
- chalk5.cyan("Original"),
1918
- chalk5.cyan("Refined Title"),
1919
- chalk5.cyan("Description"),
1920
- chalk5.cyan("Tags")
2091
+ colors.primary("SHA"),
2092
+ colors.primary("Original"),
2093
+ colors.primary("Refined Title"),
2094
+ colors.primary("Description"),
2095
+ colors.primary("Tags")
1921
2096
  ],
1922
- colWidths: [10, 30, 30, 40, 20],
2097
+ colWidths: [12, 28, 30, 40, 20],
1923
2098
  wordWrap: true,
1924
- style: {
1925
- head: [],
1926
- border: ["gray"]
1927
- }
2099
+ style: tableStyles.default.style
1928
2100
  });
1929
- commits.forEach((commit) => {
1930
- const sha = commit.sha.substring(0, 7);
2101
+ commits.forEach((commit, index) => {
2102
+ let displaySha;
2103
+ if (commit.sha.startsWith("pr-")) {
2104
+ displaySha = commit.sha.replace("pr-", "#");
2105
+ } else {
2106
+ displaySha = commit.sha.substring(0, 7);
2107
+ }
1931
2108
  const original = commit.original_message.split("\n")[0] || "";
1932
2109
  const title = commit.refined_title;
1933
- const description = commit.refined_description.substring(0, 100) + "...";
2110
+ const description = commit.refined_description.length > 100 ? commit.refined_description.substring(0, 97) + "..." : commit.refined_description;
1934
2111
  const tags = (commit.suggested_tags || []).join(", ") || "none";
2112
+ const rowNum = colors.infoDim(`${index + 1}.`);
1935
2113
  table.push([
1936
- chalk5.yellow(sha),
1937
- chalk5.gray(original),
1938
- chalk5.white(title),
1939
- chalk5.dim(description),
1940
- chalk5.blue(tags)
2114
+ `${rowNum} ${colors.highlight(displaySha)}`,
2115
+ colors.info(original),
2116
+ colors.white(title),
2117
+ colors.dim(description),
2118
+ colors.primary(tags)
1941
2119
  ]);
1942
2120
  });
1943
2121
  return table.toString();
@@ -1946,26 +2124,35 @@ function formatCommitStats(commits) {
1946
2124
  const totalFiles = commits.reduce((sum, c) => sum + (c.diffStats?.filesChanged || 0), 0);
1947
2125
  const totalInsertions = commits.reduce((sum, c) => sum + (c.diffStats?.insertions || 0), 0);
1948
2126
  const totalDeletions = commits.reduce((sum, c) => sum + (c.diffStats?.deletions || 0), 0);
1949
- return chalk5.gray("Total changes: ") + chalk5.white(`${totalFiles} files`) + chalk5.gray(", ") + chalk5.green(`+${totalInsertions}`) + chalk5.gray(" ") + chalk5.red(`-${totalDeletions}`);
2127
+ return colors.info("Total changes: ") + colors.white(`${totalFiles} files`) + colors.info(", ") + formatDiffStats(totalInsertions, totalDeletions);
2128
+ }
2129
+ function formatSelectionSummary(count, commits) {
2130
+ const totalFiles = commits.reduce((sum, c) => sum + (c.diffStats?.filesChanged || 0), 0);
2131
+ const totalInsertions = commits.reduce((sum, c) => sum + (c.diffStats?.insertions || 0), 0);
2132
+ const totalDeletions = commits.reduce((sum, c) => sum + (c.diffStats?.deletions || 0), 0);
2133
+ const selectedText = theme.success(`Selected ${theme.count(count)} PR${count > 1 ? "s" : ""}`);
2134
+ const stats = `${theme.count(totalFiles)} files changed, ${formatDiffStats(totalInsertions, totalDeletions)}`;
2135
+ return `
2136
+ ${selectedText}: ${stats}`;
1950
2137
  }
1951
2138
  function formatSuccessMessage(count) {
1952
2139
  const emoji = "\u{1F389}";
1953
- const title = chalk5.green.bold(
2140
+ const title = colors.successBold(
1954
2141
  `${emoji} Successfully created ${count} brag${count > 1 ? "s" : ""}!`
1955
2142
  );
1956
- const message = chalk5.white("\nYour achievements are now saved and ready to showcase.");
1957
- const hint = chalk5.dim("\nRun ") + chalk5.cyan("bragduck list") + chalk5.dim(" to see all your brags");
2143
+ const message = colors.white("\nYour achievements are now saved and ready to showcase.");
2144
+ const hint = theme.secondary("\nRun ") + theme.command("bragduck list") + theme.secondary(" to see all your brags");
1958
2145
  const url = "https://bragduck.com/app/brags";
1959
2146
  const clickableUrl = terminalLink(url, url, {
1960
- fallback: () => chalk5.blue.underline(url)
2147
+ fallback: () => colors.primary(url)
1961
2148
  });
1962
- const webUrl = chalk5.dim("\n\nOr, check ") + clickableUrl + chalk5.dim(" to see all your brags");
2149
+ const webUrl = theme.secondary("\n\nOr, check ") + clickableUrl + theme.secondary(" to see all your brags");
1963
2150
  return `${title}${message}${hint}${webUrl}`;
1964
2151
  }
1965
2152
  function formatErrorMessage(message, hint) {
1966
- const title = chalk5.red.bold("\u2717 Error");
1967
- const error = chalk5.white(message);
1968
- const hintText = hint ? chalk5.dim("\n\nHint: ") + chalk5.cyan(hint) : "";
2153
+ const title = colors.errorBold("\u2717 Error");
2154
+ const error = colors.white(message);
2155
+ const hintText = hint ? theme.secondary("\n\nHint: ") + theme.command(hint) : "";
1969
2156
  return `${title}
1970
2157
 
1971
2158
  ${error}${hintText}`;
@@ -2024,11 +2211,118 @@ async function promptDaysToScan(defaultDays = 30) {
2024
2211
  }
2025
2212
  return parseInt(selected, 10);
2026
2213
  }
2214
+ async function promptSortOption() {
2215
+ const choices = [
2216
+ { name: "By date (newest first)", value: "date", description: "Most recent PRs first" },
2217
+ { name: "By size (largest first)", value: "size", description: "Most lines changed" },
2218
+ { name: "By files (most files)", value: "files", description: "Most files changed" },
2219
+ { name: "No sorting", value: "none", description: "Keep original order" }
2220
+ ];
2221
+ return await select({
2222
+ message: "How would you like to sort the PRs?",
2223
+ choices,
2224
+ default: "date"
2225
+ });
2226
+ }
2227
+ async function promptReviewBrags(refinedCommits) {
2228
+ const acceptedBrags = [];
2229
+ console.log("\n" + theme.info("Review each brag before creation:") + "\n");
2230
+ for (let i = 0; i < refinedCommits.length; i++) {
2231
+ const commit = refinedCommits[i];
2232
+ const current = i + 1;
2233
+ const total = refinedCommits.length;
2234
+ const displaySha = commit.sha.startsWith("pr-") ? commit.sha.replace("pr-", "#") : commit.sha.substring(0, 7);
2235
+ const bragDetails = `${theme.step(current, total)} ${colors.highlight(displaySha)}
2236
+
2237
+ ${theme.label("Title")} ${colors.white(commit.refined_title)}
2238
+
2239
+ ${theme.label("Description")}
2240
+ ${colors.white(commit.refined_description)}
2241
+
2242
+ ${theme.label("Tags")} ${colors.primary((commit.suggested_tags || []).join(", ") || "none")}
2243
+
2244
+ ${theme.label("Impact Score")} ${colors.highlight(commit.impact_score?.toString() || "N/A")}`;
2245
+ console.log(boxen4(bragDetails, boxStyles.info));
2246
+ console.log("");
2247
+ const action = await select({
2248
+ message: `What would you like to do with this brag?`,
2249
+ choices: [
2250
+ { name: "\u2713 Accept", value: "accept", description: "Add this brag as-is" },
2251
+ { name: "\u270E Edit title", value: "edit-title", description: "Modify the title" },
2252
+ { name: "\u270E Edit description", value: "edit-desc", description: "Modify the description" },
2253
+ { name: "\u270E Edit both", value: "edit-both", description: "Modify title and description" },
2254
+ { name: "\u2717 Skip", value: "skip", description: "Skip this brag" },
2255
+ ...current < total ? [{ name: "\u2713 Accept all remaining", value: "accept-all", description: "Accept this and all remaining brags" }] : [],
2256
+ { name: "\u2717 Cancel", value: "cancel", description: "Cancel and discard all brags" }
2257
+ ]
2258
+ });
2259
+ if (action === "cancel") {
2260
+ return [];
2261
+ }
2262
+ if (action === "accept-all") {
2263
+ acceptedBrags.push(commit);
2264
+ for (let j = i + 1; j < refinedCommits.length; j++) {
2265
+ acceptedBrags.push(refinedCommits[j]);
2266
+ }
2267
+ break;
2268
+ }
2269
+ if (action === "skip") {
2270
+ continue;
2271
+ }
2272
+ let editedCommit = { ...commit };
2273
+ if (action === "edit-title" || action === "edit-both") {
2274
+ const newTitle = await input({
2275
+ message: "Enter new title:",
2276
+ default: commit.refined_title
2277
+ });
2278
+ editedCommit.refined_title = newTitle;
2279
+ }
2280
+ if (action === "edit-desc" || action === "edit-both") {
2281
+ const newDesc = await editor({
2282
+ message: "Edit description (will open your default editor):",
2283
+ default: commit.refined_description
2284
+ });
2285
+ editedCommit.refined_description = newDesc;
2286
+ }
2287
+ acceptedBrags.push(editedCommit);
2288
+ }
2289
+ return acceptedBrags;
2290
+ }
2291
+
2292
+ // src/utils/auth-helper.ts
2293
+ async function ensureAuthenticated() {
2294
+ const isAuthenticated = await authService.isAuthenticated();
2295
+ if (isAuthenticated) {
2296
+ return true;
2297
+ }
2298
+ logger.log("");
2299
+ logger.log(
2300
+ boxen5(
2301
+ theme.warning("Not authenticated") + "\n\nYou need to be logged in to use this command.\n\nWould you like to authenticate now?",
2302
+ boxStyles.warning
2303
+ )
2304
+ );
2305
+ logger.log("");
2306
+ const shouldAuth = await promptConfirm("Authenticate now?", true);
2307
+ if (!shouldAuth) {
2308
+ logger.log("");
2309
+ logger.info(
2310
+ theme.secondary("Authentication skipped. Run ") + theme.command("bragduck init") + theme.secondary(" when you're ready to authenticate.")
2311
+ );
2312
+ logger.log("");
2313
+ return false;
2314
+ }
2315
+ try {
2316
+ await initCommand();
2317
+ return true;
2318
+ } catch {
2319
+ return false;
2320
+ }
2321
+ }
2027
2322
 
2028
2323
  // src/ui/spinners.ts
2029
2324
  init_esm_shims();
2030
2325
  import ora3 from "ora";
2031
- import chalk6 from "chalk";
2032
2326
  function createSpinner(text) {
2033
2327
  return ora3({
2034
2328
  text,
@@ -2036,57 +2330,59 @@ function createSpinner(text) {
2036
2330
  spinner: "dots"
2037
2331
  });
2038
2332
  }
2039
- function fetchingPRsSpinner(days) {
2040
- return createSpinner(`Fetching merged PRs from the last ${days} days...`);
2041
- }
2042
- function refiningCommitsSpinner(count) {
2043
- return createSpinner(`Refining ${count} commit${count > 1 ? "s" : ""} with AI...`);
2044
- }
2045
- function creatingBragsSpinner(count) {
2046
- return createSpinner(`Creating ${count} brag${count > 1 ? "s" : ""}...`);
2333
+ function createStepSpinner(currentStep, totalSteps, text) {
2334
+ const stepIndicator = theme.step(currentStep, totalSteps);
2335
+ return ora3({
2336
+ text: `${stepIndicator} ${text}`,
2337
+ color: "cyan",
2338
+ spinner: "dots"
2339
+ });
2047
2340
  }
2048
2341
  function fetchingBragsSpinner() {
2049
2342
  return createSpinner("Fetching your brags...");
2050
2343
  }
2051
2344
  function succeedSpinner(spinner, text) {
2052
2345
  if (text) {
2053
- spinner.succeed(chalk6.green(text));
2346
+ spinner.succeed(colors.success(text));
2054
2347
  } else {
2055
2348
  spinner.succeed();
2056
2349
  }
2057
2350
  }
2058
2351
  function failSpinner(spinner, text) {
2059
2352
  if (text) {
2060
- spinner.fail(chalk6.red(text));
2353
+ spinner.fail(colors.error(text));
2061
2354
  } else {
2062
2355
  spinner.fail();
2063
2356
  }
2064
2357
  }
2358
+ function succeedStepSpinner(spinner, currentStep, totalSteps, text) {
2359
+ const stepIndicator = theme.step(currentStep, totalSteps);
2360
+ spinner.succeed(`${stepIndicator} ${colors.success(text)}`);
2361
+ }
2362
+ function failStepSpinner(spinner, currentStep, totalSteps, text) {
2363
+ const stepIndicator = theme.step(currentStep, totalSteps);
2364
+ spinner.fail(`${stepIndicator} ${colors.error(text)}`);
2365
+ }
2065
2366
 
2066
2367
  // src/commands/scan.ts
2067
2368
  async function scanCommand(options = {}) {
2068
2369
  logger.log("");
2370
+ const TOTAL_STEPS = 5;
2069
2371
  try {
2070
- const isAuthenticated = await authService.isAuthenticated();
2372
+ const isAuthenticated = await ensureAuthenticated();
2071
2373
  if (!isAuthenticated) {
2072
- logger.log(
2073
- boxen4(
2074
- `${chalk7.yellow.bold("\u26A0 Not authenticated")}
2075
-
2076
- Please run ${chalk7.cyan("bragduck init")} to login first.`,
2077
- {
2078
- padding: 1,
2079
- margin: 1,
2080
- borderStyle: "round",
2081
- borderColor: "yellow"
2082
- }
2083
- )
2084
- );
2085
2374
  process.exit(1);
2086
2375
  }
2376
+ const repoSpinner = createStepSpinner(1, TOTAL_STEPS, "Validating GitHub repository");
2377
+ repoSpinner.start();
2087
2378
  await githubService.validateGitHubRepository();
2088
2379
  const repoInfo = await githubService.getRepositoryInfo();
2089
- logger.info(`Repository: ${chalk7.cyan(repoInfo.fullName)} on GitHub`);
2380
+ succeedStepSpinner(
2381
+ repoSpinner,
2382
+ 1,
2383
+ TOTAL_STEPS,
2384
+ `Repository: ${theme.value(repoInfo.fullName)}`
2385
+ );
2090
2386
  logger.log("");
2091
2387
  let days = options.days;
2092
2388
  if (!days) {
@@ -2094,8 +2390,8 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
2094
2390
  days = await promptDaysToScan(defaultDays);
2095
2391
  logger.log("");
2096
2392
  }
2097
- const spinner = fetchingPRsSpinner(days);
2098
- spinner.start();
2393
+ const prSpinner = createStepSpinner(2, TOTAL_STEPS, `Fetching merged PRs from the last ${days} days`);
2394
+ prSpinner.start();
2099
2395
  let prs;
2100
2396
  if (options.all) {
2101
2397
  prs = await githubService.getMergedPRs({ days });
@@ -2104,25 +2400,46 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
2104
2400
  }
2105
2401
  const commits = prs.map((pr) => githubService.transformPRToCommit(pr));
2106
2402
  if (commits.length === 0) {
2107
- failSpinner(spinner, `No merged PRs found in the last ${days} days`);
2403
+ failStepSpinner(prSpinner, 2, TOTAL_STEPS, `No merged PRs found in the last ${days} days`);
2108
2404
  logger.log("");
2109
2405
  logger.info("Try increasing the number of days or check your GitHub activity");
2110
2406
  return;
2111
2407
  }
2112
- succeedSpinner(spinner, `Found ${commits.length} PR${commits.length > 1 ? "s" : ""}`);
2408
+ succeedStepSpinner(prSpinner, 2, TOTAL_STEPS, `Found ${theme.count(commits.length)} PR${commits.length > 1 ? "s" : ""}`);
2113
2409
  logger.log("");
2114
2410
  logger.log(formatCommitStats(commits));
2115
2411
  logger.log("");
2116
- const selectedShas = await promptSelectCommits(commits);
2412
+ const sortOption = await promptSortOption();
2413
+ logger.log("");
2414
+ let sortedCommits = [...commits];
2415
+ if (sortOption === "date") {
2416
+ sortedCommits.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
2417
+ } else if (sortOption === "size") {
2418
+ sortedCommits.sort((a, b) => {
2419
+ const sizeA = (a.diffStats?.insertions || 0) + (a.diffStats?.deletions || 0);
2420
+ const sizeB = (b.diffStats?.insertions || 0) + (b.diffStats?.deletions || 0);
2421
+ return sizeB - sizeA;
2422
+ });
2423
+ } else if (sortOption === "files") {
2424
+ sortedCommits.sort((a, b) => {
2425
+ const filesA = a.diffStats?.filesChanged || 0;
2426
+ const filesB = b.diffStats?.filesChanged || 0;
2427
+ return filesB - filesA;
2428
+ });
2429
+ }
2430
+ const selectedShas = await promptSelectCommits(sortedCommits);
2117
2431
  if (selectedShas.length === 0) {
2118
- logger.warning("No commits selected");
2432
+ logger.warning("No PRs selected");
2119
2433
  return;
2120
2434
  }
2121
- const selectedCommits = commits.filter((c) => selectedShas.includes(c.sha));
2122
- logger.log("");
2123
- logger.success(`Selected ${selectedCommits.length} PR${selectedCommits.length > 1 ? "s" : ""}`);
2435
+ const selectedCommits = sortedCommits.filter((c) => selectedShas.includes(c.sha));
2436
+ logger.log(formatSelectionSummary(selectedCommits.length, selectedCommits));
2124
2437
  logger.log("");
2125
- const refineSpinner = refiningCommitsSpinner(selectedCommits.length);
2438
+ const refineSpinner = createStepSpinner(
2439
+ 3,
2440
+ TOTAL_STEPS,
2441
+ `Refining ${theme.count(selectedCommits.length)} PR${selectedCommits.length > 1 ? "s" : ""} with AI`
2442
+ );
2126
2443
  refineSpinner.start();
2127
2444
  const refineRequest = {
2128
2445
  commits: selectedCommits.map((c) => ({
@@ -2138,23 +2455,27 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
2138
2455
  }))
2139
2456
  };
2140
2457
  const refineResponse = await apiService.refineCommits(refineRequest);
2141
- const refinedCommits = refineResponse.refined_commits;
2142
- succeedSpinner(refineSpinner, "PRs refined successfully");
2458
+ let refinedCommits = refineResponse.refined_commits;
2459
+ succeedStepSpinner(refineSpinner, 3, TOTAL_STEPS, "PRs refined successfully");
2143
2460
  logger.log("");
2144
2461
  logger.info("Preview of refined brags:");
2145
2462
  logger.log("");
2146
2463
  logger.log(formatRefinedCommitsTable(refinedCommits));
2147
2464
  logger.log("");
2148
- const shouldCreate = await promptConfirm("Create these brags?", true);
2149
- if (!shouldCreate) {
2150
- logger.warning("Cancelled");
2465
+ const acceptedBrags = await promptReviewBrags(refinedCommits);
2466
+ if (acceptedBrags.length === 0) {
2467
+ logger.warning("No brags selected for creation");
2151
2468
  return;
2152
2469
  }
2153
2470
  logger.log("");
2154
- const createSpinner2 = creatingBragsSpinner(refinedCommits.length);
2471
+ const createSpinner2 = createStepSpinner(
2472
+ 4,
2473
+ TOTAL_STEPS,
2474
+ `Creating ${theme.count(acceptedBrags.length)} brag${acceptedBrags.length > 1 ? "s" : ""}`
2475
+ );
2155
2476
  createSpinner2.start();
2156
2477
  const createRequest = {
2157
- brags: refinedCommits.map((refined) => {
2478
+ brags: acceptedBrags.map((refined) => {
2158
2479
  const originalCommit = selectedCommits.find((c) => c.sha === refined.sha);
2159
2480
  return {
2160
2481
  commit_sha: refined.sha,
@@ -2170,27 +2491,13 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
2170
2491
  })
2171
2492
  };
2172
2493
  const createResponse = await apiService.createBrags(createRequest);
2173
- succeedSpinner(createSpinner2, `Created ${createResponse.created} brags`);
2494
+ succeedStepSpinner(createSpinner2, 4, TOTAL_STEPS, `Created ${theme.count(createResponse.created)} brag${createResponse.created > 1 ? "s" : ""}`);
2174
2495
  logger.log("");
2175
- logger.log(
2176
- boxen4(formatSuccessMessage(createResponse.created), {
2177
- padding: 1,
2178
- margin: 1,
2179
- borderStyle: "round",
2180
- borderColor: "green"
2181
- })
2182
- );
2496
+ logger.log(boxen6(formatSuccessMessage(createResponse.created), boxStyles.success));
2183
2497
  } catch (error) {
2184
2498
  const err = error;
2185
2499
  logger.log("");
2186
- logger.log(
2187
- boxen4(formatErrorMessage(err.message, getErrorHint2(err)), {
2188
- padding: 1,
2189
- margin: 1,
2190
- borderStyle: "round",
2191
- borderColor: "red"
2192
- })
2193
- );
2500
+ logger.log(boxen6(formatErrorMessage(err.message, getErrorHint2(err)), boxStyles.error));
2194
2501
  process.exit(1);
2195
2502
  }
2196
2503
  }
@@ -2216,29 +2523,14 @@ function getErrorHint2(error) {
2216
2523
  // src/commands/list.ts
2217
2524
  init_esm_shims();
2218
2525
  init_api_service();
2219
- init_auth_service();
2220
- init_logger();
2221
- import boxen5 from "boxen";
2222
- import chalk8 from "chalk";
2526
+ import boxen7 from "boxen";
2223
2527
  import Table2 from "cli-table3";
2528
+ init_logger();
2224
2529
  async function listCommand(options = {}) {
2225
2530
  logger.log("");
2226
2531
  try {
2227
- const isAuthenticated = await authService.isAuthenticated();
2532
+ const isAuthenticated = await ensureAuthenticated();
2228
2533
  if (!isAuthenticated) {
2229
- logger.log(
2230
- boxen5(
2231
- `${chalk8.yellow.bold("\u26A0 Not authenticated")}
2232
-
2233
- Please run ${chalk8.cyan("bragduck init")} to login first.`,
2234
- {
2235
- padding: 1,
2236
- margin: 1,
2237
- borderStyle: "round",
2238
- borderColor: "yellow"
2239
- }
2240
- )
2241
- );
2242
2534
  process.exit(1);
2243
2535
  }
2244
2536
  const limit = options.limit || 50;
@@ -2259,7 +2551,7 @@ Please run ${chalk8.cyan("bragduck init")} to login first.`,
2259
2551
  if (search || tags) {
2260
2552
  logger.info("Try adjusting your filters or run without filters to see all brags");
2261
2553
  } else {
2262
- logger.info(`Run ${chalk8.cyan("bragduck scan")} to create your first brag!`);
2554
+ logger.info(theme.secondary("Run ") + theme.command("bragduck scan") + theme.secondary(" to create your first brag!"));
2263
2555
  }
2264
2556
  return;
2265
2557
  }
@@ -2273,7 +2565,7 @@ Please run ${chalk8.cyan("bragduck init")} to login first.`,
2273
2565
  `Showing ${offset + 1}-${offset + response.brags.length} of ${response.total} total brags`
2274
2566
  );
2275
2567
  logger.info(
2276
- chalk8.dim(`Run `) + chalk8.cyan(`bragduck list --offset ${nextOffset}`) + chalk8.dim(` to see more`)
2568
+ theme.secondary("Run ") + theme.command(`bragduck list --offset ${nextOffset}`) + theme.secondary(" to see more")
2277
2569
  );
2278
2570
  logger.log("");
2279
2571
  } else if (offset > 0) {
@@ -2286,51 +2578,41 @@ Please run ${chalk8.cyan("bragduck init")} to login first.`,
2286
2578
  const filterInfo = [];
2287
2579
  if (search) filterInfo.push(`search: "${search}"`);
2288
2580
  if (tags) filterInfo.push(`tags: ${tags.join(", ")}`);
2289
- logger.info(chalk8.dim(`Filters applied: ${filterInfo.join(", ")}`));
2581
+ logger.info(theme.info(`Filters applied: ${filterInfo.join(", ")}`));
2290
2582
  logger.log("");
2291
2583
  }
2292
2584
  } catch (error) {
2293
2585
  const err = error;
2294
2586
  logger.log("");
2295
- logger.log(
2296
- boxen5(formatErrorMessage(err.message, getErrorHint3(err)), {
2297
- padding: 1,
2298
- margin: 1,
2299
- borderStyle: "round",
2300
- borderColor: "red"
2301
- })
2302
- );
2587
+ logger.log(boxen7(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
2303
2588
  process.exit(1);
2304
2589
  }
2305
2590
  }
2306
2591
  function formatBragsTable(brags) {
2307
2592
  const table = new Table2({
2308
2593
  head: [
2309
- chalk8.cyan("Date"),
2310
- chalk8.cyan("Title"),
2311
- chalk8.cyan("Description"),
2312
- chalk8.cyan("Tags"),
2313
- chalk8.cyan("Repository")
2594
+ colors.primary("Date"),
2595
+ colors.primary("Title"),
2596
+ colors.primary("Description"),
2597
+ colors.primary("Tags"),
2598
+ colors.primary("Repository")
2314
2599
  ],
2315
2600
  colWidths: [12, 30, 40, 20, 30],
2316
2601
  wordWrap: true,
2317
- style: {
2318
- head: [],
2319
- border: ["gray"]
2320
- }
2602
+ style: tableStyles.default.style
2321
2603
  });
2322
2604
  brags.forEach((brag) => {
2323
2605
  const date = new Date(brag.date).toLocaleDateString();
2324
2606
  const title = brag.title;
2325
2607
  const description = truncateText(brag.description, 100);
2326
- const tags = brag.tags.length > 0 ? brag.tags.join(", ") : chalk8.dim("none");
2327
- const repository = brag.repository ? truncateText(extractRepoName(brag.repository), 25) : chalk8.dim("none");
2608
+ const tags = brag.tags.length > 0 ? brag.tags.join(", ") : colors.dim("none");
2609
+ const repository = brag.repository ? truncateText(extractRepoName(brag.repository), 25) : colors.dim("none");
2328
2610
  table.push([
2329
- chalk8.yellow(date),
2330
- chalk8.white(title),
2331
- chalk8.dim(description),
2332
- chalk8.blue(tags),
2333
- chalk8.gray(repository)
2611
+ colors.highlight(date),
2612
+ colors.white(title),
2613
+ colors.dim(description),
2614
+ colors.primary(tags),
2615
+ colors.info(repository)
2334
2616
  ]);
2335
2617
  });
2336
2618
  return table.toString();
@@ -2367,8 +2649,8 @@ init_esm_shims();
2367
2649
  init_storage_service();
2368
2650
  init_logger();
2369
2651
  init_constants();
2370
- import boxen6 from "boxen";
2371
- import chalk9 from "chalk";
2652
+ import boxen8 from "boxen";
2653
+ import chalk6 from "chalk";
2372
2654
  import Table3 from "cli-table3";
2373
2655
  init_errors();
2374
2656
  var VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);
@@ -2400,9 +2682,10 @@ async function configCommand(subcommand, key, value) {
2400
2682
  );
2401
2683
  }
2402
2684
  } catch (error) {
2685
+ const err = error;
2403
2686
  logger.log("");
2404
2687
  logger.log(
2405
- boxen6(formatErrorMessage(error.message, getConfigHint(error)), {
2688
+ boxen8(formatErrorMessage(err.message, getConfigHint(err)), {
2406
2689
  padding: 1,
2407
2690
  margin: 1,
2408
2691
  borderStyle: "round",
@@ -2418,7 +2701,7 @@ async function handleListConfig() {
2418
2701
  autoVersionCheck: storageService.getConfig("autoVersionCheck")
2419
2702
  };
2420
2703
  const table = new Table3({
2421
- head: [chalk9.cyan("Key"), chalk9.cyan("Value"), chalk9.cyan("Default")],
2704
+ head: [chalk6.cyan("Key"), chalk6.cyan("Value"), chalk6.cyan("Default")],
2422
2705
  colWidths: [25, 40, 40],
2423
2706
  wordWrap: true,
2424
2707
  style: {
@@ -2427,36 +2710,36 @@ async function handleListConfig() {
2427
2710
  }
2428
2711
  });
2429
2712
  table.push([
2430
- chalk9.white("defaultCommitDays"),
2431
- chalk9.yellow(String(config2.defaultCommitDays)),
2432
- chalk9.dim(String(DEFAULT_CONFIG.defaultCommitDays))
2713
+ chalk6.white("defaultCommitDays"),
2714
+ chalk6.yellow(String(config2.defaultCommitDays)),
2715
+ chalk6.dim(String(DEFAULT_CONFIG.defaultCommitDays))
2433
2716
  ]);
2434
2717
  table.push([
2435
- chalk9.white("autoVersionCheck"),
2436
- chalk9.yellow(String(config2.autoVersionCheck)),
2437
- chalk9.dim(String(DEFAULT_CONFIG.autoVersionCheck))
2718
+ chalk6.white("autoVersionCheck"),
2719
+ chalk6.yellow(String(config2.autoVersionCheck)),
2720
+ chalk6.dim(String(DEFAULT_CONFIG.autoVersionCheck))
2438
2721
  ]);
2439
2722
  logger.info("Current configuration:");
2440
2723
  logger.log("");
2441
2724
  logger.log(table.toString());
2442
2725
  logger.log("");
2443
- logger.info(chalk9.dim("To change a value: ") + chalk9.cyan("bragduck config set <key> <value>"));
2726
+ logger.info(chalk6.dim("To change a value: ") + chalk6.cyan("bragduck config set <key> <value>"));
2444
2727
  logger.log("");
2445
2728
  }
2446
2729
  async function handleGetConfig(key) {
2447
2730
  validateConfigKey(key);
2448
2731
  const value = storageService.getConfig(key);
2449
2732
  const defaultValue = DEFAULT_CONFIG[key];
2450
- logger.info(`Configuration for ${chalk9.cyan(key)}:`);
2733
+ logger.info(`Configuration for ${chalk6.cyan(key)}:`);
2451
2734
  logger.log("");
2452
- logger.log(` ${chalk9.white("Current:")} ${chalk9.yellow(String(value))}`);
2453
- logger.log(` ${chalk9.white("Default:")} ${chalk9.dim(String(defaultValue))}`);
2735
+ logger.log(` ${chalk6.white("Current:")} ${chalk6.yellow(String(value))}`);
2736
+ logger.log(` ${chalk6.white("Default:")} ${chalk6.dim(String(defaultValue))}`);
2454
2737
  logger.log("");
2455
2738
  if (value === defaultValue) {
2456
- logger.info(chalk9.dim("Using default value"));
2739
+ logger.info(chalk6.dim("Using default value"));
2457
2740
  } else {
2458
2741
  logger.info(
2459
- chalk9.dim("Custom value set. Reset with: ") + chalk9.cyan(`bragduck config set ${key} ${defaultValue}`)
2742
+ chalk6.dim("Custom value set. Reset with: ") + chalk6.cyan(`bragduck config set ${key} ${defaultValue}`)
2460
2743
  );
2461
2744
  }
2462
2745
  logger.log("");
@@ -2466,10 +2749,10 @@ async function handleSetConfig(key, value) {
2466
2749
  const typedValue = validateAndConvertValue(key, value);
2467
2750
  storageService.setConfig(key, typedValue);
2468
2751
  logger.log(
2469
- boxen6(
2470
- `${chalk9.green.bold("\u2713 Configuration updated")}
2752
+ boxen8(
2753
+ `${chalk6.green.bold("\u2713 Configuration updated")}
2471
2754
 
2472
- ${chalk9.white(key)}: ${chalk9.yellow(String(typedValue))}`,
2755
+ ${chalk6.white(key)}: ${chalk6.yellow(String(typedValue))}`,
2473
2756
  {
2474
2757
  padding: 1,
2475
2758
  margin: 1,
@@ -2491,7 +2774,7 @@ ${VALID_CONFIG_KEYS.map((k) => ` - ${k}`).join("\n")}`
2491
2774
  }
2492
2775
  function validateAndConvertValue(key, value) {
2493
2776
  switch (key) {
2494
- case CONFIG_KEYS.DEFAULT_COMMIT_DAYS:
2777
+ case CONFIG_KEYS.DEFAULT_COMMIT_DAYS: {
2495
2778
  const days = parseInt(value, 10);
2496
2779
  if (isNaN(days) || days < 1 || days > 365) {
2497
2780
  throw new ValidationError(
@@ -2501,7 +2784,8 @@ Must be a number between 1 and 365`
2501
2784
  );
2502
2785
  }
2503
2786
  return days;
2504
- case CONFIG_KEYS.AUTO_VERSION_CHECK:
2787
+ }
2788
+ case CONFIG_KEYS.AUTO_VERSION_CHECK: {
2505
2789
  const lowerValue = value.toLowerCase();
2506
2790
  if (lowerValue === "true" || lowerValue === "1" || lowerValue === "yes") {
2507
2791
  return true;
@@ -2513,6 +2797,7 @@ Must be a number between 1 and 365`
2513
2797
 
2514
2798
  Must be one of: true, false, yes, no, 1, 0`
2515
2799
  );
2800
+ }
2516
2801
  default:
2517
2802
  throw new ValidationError(`Unknown config key: "${key}"`);
2518
2803
  }
@@ -2573,7 +2858,7 @@ program.command("config [subcommand] [key] [value]").description("Manage CLI con
2573
2858
  process.exit(1);
2574
2859
  }
2575
2860
  });
2576
- program.hook("preAction", async (_thisCommand) => {
2861
+ program.hook("preAction", async () => {
2577
2862
  const options = program.opts();
2578
2863
  if (options.debug) {
2579
2864
  process.env.DEBUG = "true";
@@ -2583,7 +2868,7 @@ program.hook("preAction", async (_thisCommand) => {
2583
2868
  if (!options.skipVersionCheck && !isVersionOrHelp) {
2584
2869
  try {
2585
2870
  await checkForUpdates({ silent: false });
2586
- } catch (error) {
2871
+ } catch {
2587
2872
  logger.debug("Version check failed, continuing...");
2588
2873
  }
2589
2874
  }