@bragduck/cli 2.20.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/bragduck.js +81 -44
- package/dist/bin/bragduck.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/bragduck.js
CHANGED
|
@@ -4485,6 +4485,22 @@ import boxen4 from "boxen";
|
|
|
4485
4485
|
init_esm_shims();
|
|
4486
4486
|
import Table from "cli-table3";
|
|
4487
4487
|
import terminalLink from "terminal-link";
|
|
4488
|
+
|
|
4489
|
+
// src/utils/date-formatter.ts
|
|
4490
|
+
init_esm_shims();
|
|
4491
|
+
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
4492
|
+
function formatDate(dateString) {
|
|
4493
|
+
const date = typeof dateString === "string" ? new Date(dateString) : dateString;
|
|
4494
|
+
if (isNaN(date.getTime())) {
|
|
4495
|
+
return "Invalid date";
|
|
4496
|
+
}
|
|
4497
|
+
const day = date.getDate().toString().padStart(2, "0");
|
|
4498
|
+
const month = MONTHS[date.getMonth()];
|
|
4499
|
+
const year = date.getFullYear();
|
|
4500
|
+
return `${day} ${month} ${year}`;
|
|
4501
|
+
}
|
|
4502
|
+
|
|
4503
|
+
// src/ui/formatters.ts
|
|
4488
4504
|
function formatCommitChoice(commit) {
|
|
4489
4505
|
let displaySha;
|
|
4490
4506
|
if (commit.sha.startsWith("pr-")) {
|
|
@@ -4505,7 +4521,7 @@ function formatCommitChoice(commit) {
|
|
|
4505
4521
|
}
|
|
4506
4522
|
}
|
|
4507
4523
|
const author = colors.info(`by ${commit.author}`);
|
|
4508
|
-
const date = colors.info(
|
|
4524
|
+
const date = colors.info(formatDate(commit.date));
|
|
4509
4525
|
let stats = "";
|
|
4510
4526
|
let sizeIndicator = "";
|
|
4511
4527
|
if (commit.diffStats) {
|
|
@@ -4579,19 +4595,29 @@ function formatSelectionSummary(count, commits) {
|
|
|
4579
4595
|
return `
|
|
4580
4596
|
${selectedText}: ${stats}`;
|
|
4581
4597
|
}
|
|
4582
|
-
function formatSuccessMessage(count) {
|
|
4598
|
+
function formatSuccessMessage(count, brags) {
|
|
4583
4599
|
const emoji = "\u{1F389}";
|
|
4584
4600
|
const title = colors.successBold(
|
|
4585
4601
|
`${emoji} Successfully created ${count} brag${count > 1 ? "s" : ""}!`
|
|
4586
4602
|
);
|
|
4587
4603
|
const message = colors.white("\nYour achievements are now saved and ready to showcase.");
|
|
4588
|
-
|
|
4604
|
+
let bragsList = "";
|
|
4605
|
+
if (brags && brags.length > 0) {
|
|
4606
|
+
bragsList = "\n\n" + theme.secondary("Created brags:");
|
|
4607
|
+
for (const brag of brags) {
|
|
4608
|
+
const sourceLabel = brag.source.charAt(0).toUpperCase() + brag.source.slice(1).toLowerCase();
|
|
4609
|
+
const dateFormatted = formatDate(brag.date);
|
|
4610
|
+
bragsList += `
|
|
4611
|
+
${colors.dim("\u2022")} ${colors.white(brag.title)} ${theme.secondary(`(${dateFormatted} \xB7 ${sourceLabel})`)}`;
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
const hint = theme.secondary("\n\nRun ") + theme.command("bragduck list") + theme.secondary(" to see all your brags");
|
|
4589
4615
|
const url = "https://bragduck.com/app/brags";
|
|
4590
4616
|
const clickableUrl = terminalLink(url, url, {
|
|
4591
4617
|
fallback: () => colors.primary(url)
|
|
4592
4618
|
});
|
|
4593
4619
|
const webUrl = theme.secondary("\n\nOr, check ") + clickableUrl + theme.secondary(" to see all your brags");
|
|
4594
|
-
return `${title}${message}${hint}${webUrl}`;
|
|
4620
|
+
return `${title}${message}${bragsList}${hint}${webUrl}`;
|
|
4595
4621
|
}
|
|
4596
4622
|
function formatErrorMessage(message, hint) {
|
|
4597
4623
|
const title = colors.errorBold("\u2717 Error");
|
|
@@ -4993,8 +5019,30 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
4993
5019
|
logger.log("");
|
|
4994
5020
|
logger.log(formatCommitStats(workItems));
|
|
4995
5021
|
logger.log("");
|
|
4996
|
-
|
|
4997
|
-
|
|
5022
|
+
const existingBrags = await apiService.listBrags({ limit: 100 });
|
|
5023
|
+
logger.debug(`Fetched ${existingBrags.brags.length} existing brags`);
|
|
5024
|
+
const existingUrls = new Set(existingBrags.brags.flatMap((b) => b.attachments || []));
|
|
5025
|
+
logger.debug(`Existing URLs in attachments: ${existingUrls.size}`);
|
|
5026
|
+
const duplicates = workItems.filter((c) => c.url && existingUrls.has(c.url));
|
|
5027
|
+
const newWorkItems = workItems.filter((c) => !c.url || !existingUrls.has(c.url));
|
|
5028
|
+
logger.debug(`Found ${duplicates.length} duplicates, ${newWorkItems.length} new items`);
|
|
5029
|
+
if (duplicates.length > 0) {
|
|
5030
|
+
logger.log("");
|
|
5031
|
+
logger.info(
|
|
5032
|
+
colors.dim(
|
|
5033
|
+
`\u2139 ${duplicates.length} work item${duplicates.length > 1 ? "s" : ""} already exist in Bragduck (will be skipped)`
|
|
5034
|
+
)
|
|
5035
|
+
);
|
|
5036
|
+
logger.log("");
|
|
5037
|
+
}
|
|
5038
|
+
if (newWorkItems.length === 0) {
|
|
5039
|
+
logger.log("");
|
|
5040
|
+
logger.info(theme.secondary("All work items already exist in Bragduck. Nothing to sync."));
|
|
5041
|
+
logger.log("");
|
|
5042
|
+
return { created: 0, skipped: duplicates.length };
|
|
5043
|
+
}
|
|
5044
|
+
let sortedCommits = [...newWorkItems];
|
|
5045
|
+
if (newWorkItems.length > 1 && !options.turbo) {
|
|
4998
5046
|
const sortOption = await promptSortOption();
|
|
4999
5047
|
logger.log("");
|
|
5000
5048
|
if (sortOption === "date") {
|
|
@@ -5012,58 +5060,34 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
5012
5060
|
return filesB - filesA;
|
|
5013
5061
|
});
|
|
5014
5062
|
}
|
|
5015
|
-
} else if (
|
|
5063
|
+
} else if (newWorkItems.length > 1 && options.turbo) {
|
|
5016
5064
|
sortedCommits.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
5017
5065
|
logger.debug("Turbo mode: sorted by date (most recent first)");
|
|
5018
5066
|
}
|
|
5019
5067
|
let selectedShas;
|
|
5020
5068
|
if (options.turbo) {
|
|
5021
5069
|
selectedShas = sortedCommits.map((c) => c.sha);
|
|
5022
|
-
logger.debug(`Turbo mode: auto-selected all ${selectedShas.length} items`);
|
|
5070
|
+
logger.debug(`Turbo mode: auto-selected all ${selectedShas.length} new items`);
|
|
5023
5071
|
} else {
|
|
5024
5072
|
selectedShas = await promptSelectCommits(sortedCommits);
|
|
5025
5073
|
if (selectedShas.length === 0) {
|
|
5026
5074
|
logger.log("");
|
|
5027
5075
|
logger.info(theme.secondary("No work items selected. Sync cancelled."));
|
|
5028
5076
|
logger.log("");
|
|
5029
|
-
return { created: 0, skipped:
|
|
5077
|
+
return { created: 0, skipped: duplicates.length };
|
|
5030
5078
|
}
|
|
5031
5079
|
}
|
|
5032
5080
|
const selectedCommits = sortedCommits.filter((c) => selectedShas.includes(c.sha));
|
|
5033
5081
|
logger.log(formatSelectionSummary(selectedCommits.length, selectedCommits));
|
|
5034
5082
|
logger.log("");
|
|
5035
|
-
const existingBrags = await apiService.listBrags({ limit: 100 });
|
|
5036
|
-
logger.debug(`Fetched ${existingBrags.brags.length} existing brags`);
|
|
5037
|
-
const existingUrls = new Set(existingBrags.brags.flatMap((b) => b.attachments || []));
|
|
5038
|
-
logger.debug(`Existing URLs in attachments: ${existingUrls.size}`);
|
|
5039
|
-
const duplicates = selectedCommits.filter((c) => c.url && existingUrls.has(c.url));
|
|
5040
|
-
const newCommits = selectedCommits.filter((c) => !c.url || !existingUrls.has(c.url));
|
|
5041
|
-
logger.debug(`Duplicates: ${duplicates.length}, New: ${newCommits.length}`);
|
|
5042
|
-
if (duplicates.length > 0) {
|
|
5043
|
-
logger.log("");
|
|
5044
|
-
logger.info(
|
|
5045
|
-
colors.warning(
|
|
5046
|
-
`${duplicates.length} work item${duplicates.length > 1 ? "s" : ""} already added to Bragduck - skipping`
|
|
5047
|
-
)
|
|
5048
|
-
);
|
|
5049
|
-
logger.log("");
|
|
5050
|
-
}
|
|
5051
|
-
if (newCommits.length === 0) {
|
|
5052
|
-
logger.log("");
|
|
5053
|
-
logger.info(
|
|
5054
|
-
theme.secondary("All selected work items already exist in Bragduck. Nothing to refine.")
|
|
5055
|
-
);
|
|
5056
|
-
logger.log("");
|
|
5057
|
-
return { created: 0, skipped: duplicates.length };
|
|
5058
|
-
}
|
|
5059
5083
|
const refineSpinner = createStepSpinner(
|
|
5060
5084
|
4,
|
|
5061
5085
|
TOTAL_STEPS,
|
|
5062
|
-
`Refining ${theme.count(
|
|
5086
|
+
`Refining ${theme.count(selectedCommits.length)} work item${selectedCommits.length > 1 ? "s" : ""} with AI`
|
|
5063
5087
|
);
|
|
5064
5088
|
refineSpinner.start();
|
|
5065
5089
|
const refineRequest = {
|
|
5066
|
-
brags:
|
|
5090
|
+
brags: selectedCommits.map((c) => ({
|
|
5067
5091
|
text: c.message,
|
|
5068
5092
|
date: c.date,
|
|
5069
5093
|
title: c.message.split("\n")[0]
|
|
@@ -5081,9 +5105,9 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
5081
5105
|
} else {
|
|
5082
5106
|
logger.info("Preview of refined brags:");
|
|
5083
5107
|
logger.log("");
|
|
5084
|
-
logger.log(formatRefinedCommitsTable(refinedBrags,
|
|
5108
|
+
logger.log(formatRefinedCommitsTable(refinedBrags, selectedCommits));
|
|
5085
5109
|
logger.log("");
|
|
5086
|
-
acceptedBrags = await promptReviewBrags(refinedBrags,
|
|
5110
|
+
acceptedBrags = await promptReviewBrags(refinedBrags, selectedCommits);
|
|
5087
5111
|
}
|
|
5088
5112
|
if (acceptedBrags.length === 0) {
|
|
5089
5113
|
logger.log("");
|
|
@@ -5115,7 +5139,7 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
5115
5139
|
createSpinner2.start();
|
|
5116
5140
|
const createRequest = {
|
|
5117
5141
|
brags: acceptedBrags.map((refined, index) => {
|
|
5118
|
-
const originalCommit =
|
|
5142
|
+
const originalCommit = selectedCommits[index];
|
|
5119
5143
|
return {
|
|
5120
5144
|
commit_sha: originalCommit?.sha || `brag-${index}`,
|
|
5121
5145
|
title: refined.refined_title,
|
|
@@ -5162,7 +5186,12 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
5162
5186
|
logger.log("");
|
|
5163
5187
|
throw error;
|
|
5164
5188
|
}
|
|
5165
|
-
|
|
5189
|
+
const createdBrags = createResponse.brags.map((brag) => ({
|
|
5190
|
+
title: brag.title,
|
|
5191
|
+
date: brag.created_at,
|
|
5192
|
+
source: sourceType
|
|
5193
|
+
}));
|
|
5194
|
+
return { created: createResponse.created, skipped: duplicates.length, createdBrags };
|
|
5166
5195
|
}
|
|
5167
5196
|
async function syncAllAuthenticatedServices(options) {
|
|
5168
5197
|
const TOTAL_STEPS = 5;
|
|
@@ -5268,7 +5297,12 @@ async function syncAllAuthenticatedServices(options) {
|
|
|
5268
5297
|
sharedDays,
|
|
5269
5298
|
sharedOrgId
|
|
5270
5299
|
);
|
|
5271
|
-
results.push({
|
|
5300
|
+
results.push({
|
|
5301
|
+
service,
|
|
5302
|
+
created: result.created,
|
|
5303
|
+
skipped: result.skipped,
|
|
5304
|
+
createdBrags: result.createdBrags
|
|
5305
|
+
});
|
|
5272
5306
|
logger.log("");
|
|
5273
5307
|
} catch (error) {
|
|
5274
5308
|
const err = error;
|
|
@@ -5309,7 +5343,8 @@ async function syncAllAuthenticatedServices(options) {
|
|
|
5309
5343
|
logger.log("");
|
|
5310
5344
|
}
|
|
5311
5345
|
if (totalCreated > 0) {
|
|
5312
|
-
|
|
5346
|
+
const allCreatedBrags = results.filter((r) => r.createdBrags).flatMap((r) => r.createdBrags);
|
|
5347
|
+
logger.log(boxen6(formatSuccessMessage(totalCreated, allCreatedBrags), boxStyles.success));
|
|
5313
5348
|
} else if (successful.length > 0) {
|
|
5314
5349
|
logger.log(
|
|
5315
5350
|
boxen6(
|
|
@@ -5397,7 +5432,9 @@ async function syncCommand(options = {}) {
|
|
|
5397
5432
|
logger.log("");
|
|
5398
5433
|
const result = await syncSingleService(sourceType, options, TOTAL_STEPS);
|
|
5399
5434
|
if (result.created > 0) {
|
|
5400
|
-
logger.log(
|
|
5435
|
+
logger.log(
|
|
5436
|
+
boxen6(formatSuccessMessage(result.created, result.createdBrags), boxStyles.success)
|
|
5437
|
+
);
|
|
5401
5438
|
} else if (result.skipped > 0) {
|
|
5402
5439
|
logger.log("");
|
|
5403
5440
|
logger.info(
|
|
@@ -5883,7 +5920,7 @@ function formatBragsTable(brags) {
|
|
|
5883
5920
|
style: tableStyles.default.style
|
|
5884
5921
|
});
|
|
5885
5922
|
brags.forEach((brag) => {
|
|
5886
|
-
const date =
|
|
5923
|
+
const date = formatDate(brag.date);
|
|
5887
5924
|
const title = brag.title;
|
|
5888
5925
|
const description = truncateText(brag.description, 100);
|
|
5889
5926
|
const tags = brag.tags.length > 0 ? brag.tags.join(", ") : colors.dim("none");
|
|
@@ -5900,7 +5937,7 @@ function formatBragsTable(brags) {
|
|
|
5900
5937
|
}
|
|
5901
5938
|
function formatBragsOneline(brags) {
|
|
5902
5939
|
return brags.map((brag) => {
|
|
5903
|
-
const date =
|
|
5940
|
+
const date = formatDate(brag.date);
|
|
5904
5941
|
return `${colors.highlight(date)} ${colors.white(brag.title)}`;
|
|
5905
5942
|
}).join("\n");
|
|
5906
5943
|
}
|