@bragduck/cli 2.38.2 → 2.39.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 +442 -11
- package/dist/bin/bragduck.js.map +1 -1
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/bragduck.js
CHANGED
|
@@ -104,6 +104,11 @@ var init_constants = __esm({
|
|
|
104
104
|
ORGANISATIONS: {
|
|
105
105
|
LIST: "/v1/users/{userId}/organisations"
|
|
106
106
|
},
|
|
107
|
+
STORIES: {
|
|
108
|
+
LIST: "/v1/users/{userId}/stories",
|
|
109
|
+
CREATE: "/v1/users/{userId}/stories",
|
|
110
|
+
DELETE: "/v1/users/{userId}/stories/{storyId}"
|
|
111
|
+
},
|
|
107
112
|
VERSION: "/v1/cli/version",
|
|
108
113
|
/**
|
|
109
114
|
* @deprecated Use BRAGS.REFINE instead
|
|
@@ -1622,6 +1627,70 @@ var init_api_service = __esm({
|
|
|
1622
1627
|
throw _error;
|
|
1623
1628
|
}
|
|
1624
1629
|
}
|
|
1630
|
+
/**
|
|
1631
|
+
* List user's stories
|
|
1632
|
+
*/
|
|
1633
|
+
async listStories(userId, params = {}) {
|
|
1634
|
+
const { page = 1, perPage = 20, search, competency, orgId } = params;
|
|
1635
|
+
logger.debug(`Listing stories: page=${page}, perPage=${perPage}`);
|
|
1636
|
+
try {
|
|
1637
|
+
const queryParams = new URLSearchParams6({
|
|
1638
|
+
page: page.toString(),
|
|
1639
|
+
perPage: perPage.toString()
|
|
1640
|
+
});
|
|
1641
|
+
if (search) queryParams.append("search", search);
|
|
1642
|
+
if (competency) queryParams.append("competency", competency);
|
|
1643
|
+
if (orgId) queryParams.append("orgId", orgId);
|
|
1644
|
+
const url = `${API_ENDPOINTS.STORIES.LIST.replace("{userId}", userId)}?${queryParams.toString()}`;
|
|
1645
|
+
const response = await this.makeRequest(url, {
|
|
1646
|
+
method: "GET"
|
|
1647
|
+
});
|
|
1648
|
+
logger.debug(
|
|
1649
|
+
`Successfully fetched ${response.items.length} stories (total: ${response.total})`
|
|
1650
|
+
);
|
|
1651
|
+
return response;
|
|
1652
|
+
} catch (_error) {
|
|
1653
|
+
logger.debug("Failed to list stories");
|
|
1654
|
+
throw _error;
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* Create a story
|
|
1659
|
+
*/
|
|
1660
|
+
async createStory(userId, body) {
|
|
1661
|
+
logger.debug(`Creating story: ${body.title}`);
|
|
1662
|
+
try {
|
|
1663
|
+
const url = API_ENDPOINTS.STORIES.CREATE.replace("{userId}", userId);
|
|
1664
|
+
const response = await this.makeRequest(url, {
|
|
1665
|
+
method: "POST",
|
|
1666
|
+
body
|
|
1667
|
+
});
|
|
1668
|
+
logger.debug(`Successfully created story: ${response.id}`);
|
|
1669
|
+
return response;
|
|
1670
|
+
} catch (_error) {
|
|
1671
|
+
logger.debug("Failed to create story");
|
|
1672
|
+
throw _error;
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Delete a story (soft delete)
|
|
1677
|
+
*/
|
|
1678
|
+
async deleteStory(userId, storyId) {
|
|
1679
|
+
logger.debug(`Deleting story: ${storyId}`);
|
|
1680
|
+
try {
|
|
1681
|
+
const url = API_ENDPOINTS.STORIES.DELETE.replace("{userId}", userId).replace(
|
|
1682
|
+
"{storyId}",
|
|
1683
|
+
storyId
|
|
1684
|
+
);
|
|
1685
|
+
await this.makeRequest(url, {
|
|
1686
|
+
method: "DELETE"
|
|
1687
|
+
});
|
|
1688
|
+
logger.debug(`Successfully deleted story: ${storyId}`);
|
|
1689
|
+
} catch (_error) {
|
|
1690
|
+
logger.debug("Failed to delete story");
|
|
1691
|
+
throw _error;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1625
1694
|
/**
|
|
1626
1695
|
* List user's organisations
|
|
1627
1696
|
*/
|
|
@@ -5970,6 +6039,12 @@ async function promptConfirm(message, defaultValue = true) {
|
|
|
5970
6039
|
default: defaultValue
|
|
5971
6040
|
});
|
|
5972
6041
|
}
|
|
6042
|
+
async function promptInput(message, defaultValue) {
|
|
6043
|
+
return await input2({
|
|
6044
|
+
message,
|
|
6045
|
+
default: defaultValue
|
|
6046
|
+
});
|
|
6047
|
+
}
|
|
5973
6048
|
async function promptDaysToScan(defaultDays = 30) {
|
|
5974
6049
|
const choices = [
|
|
5975
6050
|
{ name: "1 day", value: "1", description: "Last 24 hours" },
|
|
@@ -6217,6 +6292,13 @@ function createFetchSpinner(text) {
|
|
|
6217
6292
|
spinner: "bouncingBar"
|
|
6218
6293
|
});
|
|
6219
6294
|
}
|
|
6295
|
+
function createWriteSpinner(text) {
|
|
6296
|
+
return ora({
|
|
6297
|
+
text,
|
|
6298
|
+
color: "cyan",
|
|
6299
|
+
spinner: "dots"
|
|
6300
|
+
});
|
|
6301
|
+
}
|
|
6220
6302
|
function createValidateSpinner(text) {
|
|
6221
6303
|
return ora({
|
|
6222
6304
|
text,
|
|
@@ -6239,6 +6321,15 @@ function updateStepSpinner(spinner, currentStep, totalSteps, text) {
|
|
|
6239
6321
|
function fetchingBragsSpinner() {
|
|
6240
6322
|
return createFetchSpinner("Fetching your brags...");
|
|
6241
6323
|
}
|
|
6324
|
+
function fetchingStoriesSpinner() {
|
|
6325
|
+
return createFetchSpinner("Fetching your stories...");
|
|
6326
|
+
}
|
|
6327
|
+
function creatingStorySpinner() {
|
|
6328
|
+
return createWriteSpinner("Creating story...");
|
|
6329
|
+
}
|
|
6330
|
+
function deletingStorySpinner() {
|
|
6331
|
+
return createWriteSpinner("Deleting story...");
|
|
6332
|
+
}
|
|
6242
6333
|
function succeedSpinner(spinner, text) {
|
|
6243
6334
|
if (text) {
|
|
6244
6335
|
spinner.succeed(colors.success(text));
|
|
@@ -6535,6 +6626,7 @@ async function syncSingleRepository(repo, days, sortOption, scanMode, orgId, opt
|
|
|
6535
6626
|
);
|
|
6536
6627
|
createSpinner.start();
|
|
6537
6628
|
const createRequest = {
|
|
6629
|
+
mode: options.turbo ? "turbo" : "manual",
|
|
6538
6630
|
brags: acceptedBrags.map((refined, index) => {
|
|
6539
6631
|
const originalCommit = selectedCommits[index];
|
|
6540
6632
|
const repoTag = repo.name;
|
|
@@ -6963,6 +7055,7 @@ async function syncSingleService(sourceType, options, TOTAL_STEPS, sharedDays, s
|
|
|
6963
7055
|
);
|
|
6964
7056
|
createSpinner.start();
|
|
6965
7057
|
const createRequest = {
|
|
7058
|
+
mode: options.turbo ? "turbo" : "manual",
|
|
6966
7059
|
brags: acceptedBrags.map((refined, index) => {
|
|
6967
7060
|
const originalCommit = selectedCommits[index];
|
|
6968
7061
|
const isGitSource = sourceType === "github" || sourceType === "gitlab" || sourceType === "bitbucket" || sourceType === "atlassian";
|
|
@@ -7680,13 +7773,15 @@ function formatBragsTable(brags) {
|
|
|
7680
7773
|
return table.toString() + (links ? "\n\n" + links : "");
|
|
7681
7774
|
}
|
|
7682
7775
|
function formatBragLinks(brags) {
|
|
7683
|
-
const lines = brags.filter((brag) => brag.url || brag.
|
|
7776
|
+
const lines = brags.filter((brag) => brag.url || brag.keyResultIds && brag.keyResultIds.length > 0).map((brag) => {
|
|
7684
7777
|
const parts = [` ${colors.white(brag.title)}`];
|
|
7685
7778
|
if (brag.url) {
|
|
7686
7779
|
parts.push(` ${colors.info(brag.url)}`);
|
|
7687
7780
|
}
|
|
7688
|
-
if (brag.
|
|
7689
|
-
parts.push(
|
|
7781
|
+
if (brag.keyResultIds && brag.keyResultIds.length > 0) {
|
|
7782
|
+
parts.push(
|
|
7783
|
+
` ${colors.dim("Linked to key result:")} ${colors.primary(brag.keyResultIds[0])}`
|
|
7784
|
+
);
|
|
7690
7785
|
}
|
|
7691
7786
|
return parts.join("\n");
|
|
7692
7787
|
});
|
|
@@ -7698,9 +7793,9 @@ function formatBragsOneline(brags) {
|
|
|
7698
7793
|
const date = formatDate(brag.date);
|
|
7699
7794
|
const urlLine = brag.url ? `
|
|
7700
7795
|
${colors.info(brag.url)}` : "";
|
|
7701
|
-
const
|
|
7702
|
-
${colors.dim("Linked to key result:")} ${colors.primary(brag.
|
|
7703
|
-
return `${colors.highlight(date)} ${colors.white(brag.title)}${urlLine}${
|
|
7796
|
+
const keyResultLine = brag.keyResultIds && brag.keyResultIds.length > 0 ? `
|
|
7797
|
+
${colors.dim("Linked to key result:")} ${colors.primary(brag.keyResultIds[0])}` : "";
|
|
7798
|
+
return `${colors.highlight(date)} ${colors.white(brag.title)}${urlLine}${keyResultLine}`;
|
|
7704
7799
|
}).join("\n");
|
|
7705
7800
|
}
|
|
7706
7801
|
function truncateText(text, maxLength) {
|
|
@@ -7730,14 +7825,338 @@ function getErrorHint2(error) {
|
|
|
7730
7825
|
return "Try running with DEBUG=* for more information";
|
|
7731
7826
|
}
|
|
7732
7827
|
|
|
7828
|
+
// src/commands/story.ts
|
|
7829
|
+
init_esm_shims();
|
|
7830
|
+
init_api_service();
|
|
7831
|
+
init_auth_service();
|
|
7832
|
+
import boxen8 from "boxen";
|
|
7833
|
+
import Table3 from "cli-table3";
|
|
7834
|
+
init_logger();
|
|
7835
|
+
async function storyCommand(subcommand, idOrOptions, _options) {
|
|
7836
|
+
switch (subcommand) {
|
|
7837
|
+
case "list":
|
|
7838
|
+
case "ls":
|
|
7839
|
+
await storyListCommand(idOrOptions || {});
|
|
7840
|
+
break;
|
|
7841
|
+
case "create":
|
|
7842
|
+
case "add":
|
|
7843
|
+
await storyCreateCommand(idOrOptions || {});
|
|
7844
|
+
break;
|
|
7845
|
+
case "delete":
|
|
7846
|
+
case "rm":
|
|
7847
|
+
if (typeof idOrOptions === "string") {
|
|
7848
|
+
await storyDeleteCommand(idOrOptions);
|
|
7849
|
+
} else {
|
|
7850
|
+
logger.log("");
|
|
7851
|
+
logger.log(
|
|
7852
|
+
boxen8(
|
|
7853
|
+
formatErrorMessage("Missing story ID", "Usage: bragduck story delete <id>"),
|
|
7854
|
+
boxStyles.error
|
|
7855
|
+
)
|
|
7856
|
+
);
|
|
7857
|
+
process.exit(1);
|
|
7858
|
+
}
|
|
7859
|
+
break;
|
|
7860
|
+
default:
|
|
7861
|
+
logger.log("");
|
|
7862
|
+
logger.log(
|
|
7863
|
+
boxen8(
|
|
7864
|
+
colors.primary("Story Commands") + `
|
|
7865
|
+
|
|
7866
|
+
${theme.command("bragduck story list")} List your interview stories
|
|
7867
|
+
${theme.command("bragduck story create")} Create a new STAR story
|
|
7868
|
+
${theme.command("bragduck story delete")} Delete a story by ID
|
|
7869
|
+
|
|
7870
|
+
` + colors.dim("Aliases: ls, add, rm"),
|
|
7871
|
+
{ ...boxStyles.info, padding: 1 }
|
|
7872
|
+
)
|
|
7873
|
+
);
|
|
7874
|
+
break;
|
|
7875
|
+
}
|
|
7876
|
+
}
|
|
7877
|
+
async function storyListCommand(options) {
|
|
7878
|
+
logger.log("");
|
|
7879
|
+
try {
|
|
7880
|
+
const isAuthenticated = await ensureAuthenticated();
|
|
7881
|
+
if (!isAuthenticated) {
|
|
7882
|
+
process.exit(1);
|
|
7883
|
+
}
|
|
7884
|
+
const subSpinner = createValidateSpinner("Checking subscription...");
|
|
7885
|
+
subSpinner.start();
|
|
7886
|
+
let subscriptionStatus;
|
|
7887
|
+
try {
|
|
7888
|
+
subscriptionStatus = await apiService.getSubscriptionStatus();
|
|
7889
|
+
} catch (error) {
|
|
7890
|
+
failSpinner(subSpinner, "Failed to check subscription");
|
|
7891
|
+
throw error;
|
|
7892
|
+
}
|
|
7893
|
+
if (subscriptionStatus.tier === "FREE") {
|
|
7894
|
+
failSpinner(subSpinner, "Free plan \u2014 upgrade to use the CLI");
|
|
7895
|
+
showUpgradeMessage();
|
|
7896
|
+
return;
|
|
7897
|
+
}
|
|
7898
|
+
subSpinner.stop();
|
|
7899
|
+
const userInfo = authService.getUserInfo();
|
|
7900
|
+
if (!userInfo) {
|
|
7901
|
+
logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
|
|
7902
|
+
process.exit(1);
|
|
7903
|
+
}
|
|
7904
|
+
const perPage = options.limit || 20;
|
|
7905
|
+
const spinner = fetchingStoriesSpinner();
|
|
7906
|
+
spinner.start();
|
|
7907
|
+
const response = await apiService.listStories(userInfo.id, {
|
|
7908
|
+
perPage,
|
|
7909
|
+
search: options.search,
|
|
7910
|
+
competency: options.competency
|
|
7911
|
+
});
|
|
7912
|
+
if (response.items.length === 0) {
|
|
7913
|
+
failSpinner(spinner, "No stories found");
|
|
7914
|
+
logger.log("");
|
|
7915
|
+
if (options.search || options.competency) {
|
|
7916
|
+
logger.info("Try adjusting your filters or run without filters to see all stories");
|
|
7917
|
+
} else {
|
|
7918
|
+
logger.info(
|
|
7919
|
+
theme.secondary("Run ") + theme.command("bragduck story create") + theme.secondary(" to create your first interview story")
|
|
7920
|
+
);
|
|
7921
|
+
}
|
|
7922
|
+
return;
|
|
7923
|
+
}
|
|
7924
|
+
succeedSpinner(spinner, `Found ${response.total} stor${response.total > 1 ? "ies" : "y"}`);
|
|
7925
|
+
showCommandHeader(userInfo);
|
|
7926
|
+
logger.log("");
|
|
7927
|
+
logger.log(formatStoriesTable(response.items));
|
|
7928
|
+
logger.log("");
|
|
7929
|
+
if (response.total > response.items.length) {
|
|
7930
|
+
logger.info(`Showing ${response.items.length} of ${response.total} total stories`);
|
|
7931
|
+
logger.log("");
|
|
7932
|
+
}
|
|
7933
|
+
if (options.search || options.competency) {
|
|
7934
|
+
const filterInfo = [];
|
|
7935
|
+
if (options.search) filterInfo.push(`search: "${options.search}"`);
|
|
7936
|
+
if (options.competency) filterInfo.push(`competency: ${options.competency}`);
|
|
7937
|
+
logger.info(theme.info(`Filters applied: ${filterInfo.join(", ")}`));
|
|
7938
|
+
logger.log("");
|
|
7939
|
+
}
|
|
7940
|
+
} catch (error) {
|
|
7941
|
+
const err = error;
|
|
7942
|
+
logger.log("");
|
|
7943
|
+
logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
|
|
7944
|
+
process.exit(1);
|
|
7945
|
+
}
|
|
7946
|
+
}
|
|
7947
|
+
async function storyCreateCommand(options) {
|
|
7948
|
+
logger.log("");
|
|
7949
|
+
try {
|
|
7950
|
+
const isAuthenticated = await ensureAuthenticated();
|
|
7951
|
+
if (!isAuthenticated) {
|
|
7952
|
+
process.exit(1);
|
|
7953
|
+
}
|
|
7954
|
+
const subSpinner = createValidateSpinner("Checking subscription...");
|
|
7955
|
+
subSpinner.start();
|
|
7956
|
+
let subscriptionStatus;
|
|
7957
|
+
try {
|
|
7958
|
+
subscriptionStatus = await apiService.getSubscriptionStatus();
|
|
7959
|
+
} catch (error) {
|
|
7960
|
+
failSpinner(subSpinner, "Failed to check subscription");
|
|
7961
|
+
throw error;
|
|
7962
|
+
}
|
|
7963
|
+
if (subscriptionStatus.tier === "FREE") {
|
|
7964
|
+
failSpinner(subSpinner, "Free plan \u2014 upgrade to use the CLI");
|
|
7965
|
+
showUpgradeMessage();
|
|
7966
|
+
return;
|
|
7967
|
+
}
|
|
7968
|
+
subSpinner.stop();
|
|
7969
|
+
const userInfo = authService.getUserInfo();
|
|
7970
|
+
if (!userInfo) {
|
|
7971
|
+
logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
|
|
7972
|
+
process.exit(1);
|
|
7973
|
+
}
|
|
7974
|
+
logger.log(
|
|
7975
|
+
boxen8(
|
|
7976
|
+
colors.primary("Create Interview Story") + "\n\n" + colors.dim("Use the STAR format to structure your story:\n") + colors.dim("Situation, Task, Action, Result"),
|
|
7977
|
+
{ ...boxStyles.info, padding: 1 }
|
|
7978
|
+
)
|
|
7979
|
+
);
|
|
7980
|
+
logger.log("");
|
|
7981
|
+
const title = options.title || await promptInput("Story title (short summary):");
|
|
7982
|
+
if (!title.trim()) {
|
|
7983
|
+
logger.log(theme.error("Title is required"));
|
|
7984
|
+
process.exit(1);
|
|
7985
|
+
}
|
|
7986
|
+
const situation = await promptInput("Situation (context and background):");
|
|
7987
|
+
if (!situation.trim()) {
|
|
7988
|
+
logger.log(theme.error("Situation is required"));
|
|
7989
|
+
process.exit(1);
|
|
7990
|
+
}
|
|
7991
|
+
const task = await promptInput("Task (your responsibility or challenge):");
|
|
7992
|
+
if (!task.trim()) {
|
|
7993
|
+
logger.log(theme.error("Task is required"));
|
|
7994
|
+
process.exit(1);
|
|
7995
|
+
}
|
|
7996
|
+
const action = await promptInput("Action (what you did):");
|
|
7997
|
+
if (!action.trim()) {
|
|
7998
|
+
logger.log(theme.error("Action is required"));
|
|
7999
|
+
process.exit(1);
|
|
8000
|
+
}
|
|
8001
|
+
const result = await promptInput("Result (outcome and impact):");
|
|
8002
|
+
if (!result.trim()) {
|
|
8003
|
+
logger.log(theme.error("Result is required"));
|
|
8004
|
+
process.exit(1);
|
|
8005
|
+
}
|
|
8006
|
+
const competenciesInput = await promptInput(
|
|
8007
|
+
"Competencies (comma-separated, e.g. leadership, system design):",
|
|
8008
|
+
""
|
|
8009
|
+
);
|
|
8010
|
+
const competencies = competenciesInput ? competenciesInput.split(",").map((c) => c.trim()).filter(Boolean) : [];
|
|
8011
|
+
let orgId;
|
|
8012
|
+
try {
|
|
8013
|
+
const orgsResponse = await apiService.listUserOrganisations(userInfo.id);
|
|
8014
|
+
if (orgsResponse.items.length > 0) {
|
|
8015
|
+
const selectedOrg = await promptSelectOrganisationWithDefault(orgsResponse.items);
|
|
8016
|
+
if (selectedOrg) {
|
|
8017
|
+
orgId = selectedOrg;
|
|
8018
|
+
}
|
|
8019
|
+
}
|
|
8020
|
+
} catch {
|
|
8021
|
+
logger.debug("Failed to fetch organisations, skipping org selection");
|
|
8022
|
+
}
|
|
8023
|
+
logger.log("");
|
|
8024
|
+
logger.log(
|
|
8025
|
+
boxen8(
|
|
8026
|
+
colors.primary("Preview") + `
|
|
8027
|
+
|
|
8028
|
+
${theme.label("Title")} ${colors.white(title)}
|
|
8029
|
+
|
|
8030
|
+
${theme.label("Situation")} ${colors.white(situation)}
|
|
8031
|
+
|
|
8032
|
+
${theme.label("Task")} ${colors.white(task)}
|
|
8033
|
+
|
|
8034
|
+
${theme.label("Action")} ${colors.white(action)}
|
|
8035
|
+
|
|
8036
|
+
${theme.label("Result")} ${colors.white(result)}
|
|
8037
|
+
|
|
8038
|
+
${theme.label("Competencies")} ${competencies.length > 0 ? colors.primary(competencies.join(", ")) : colors.dim("none")}`,
|
|
8039
|
+
{ ...boxStyles.info, padding: 1 }
|
|
8040
|
+
)
|
|
8041
|
+
);
|
|
8042
|
+
logger.log("");
|
|
8043
|
+
const shouldCreate = await promptConfirm("Create this story?", true);
|
|
8044
|
+
if (!shouldCreate) {
|
|
8045
|
+
logger.log(theme.secondary("Story creation cancelled"));
|
|
8046
|
+
return;
|
|
8047
|
+
}
|
|
8048
|
+
const spinner = creatingStorySpinner();
|
|
8049
|
+
spinner.start();
|
|
8050
|
+
const body = {
|
|
8051
|
+
title,
|
|
8052
|
+
situation,
|
|
8053
|
+
task,
|
|
8054
|
+
action,
|
|
8055
|
+
result,
|
|
8056
|
+
competencies,
|
|
8057
|
+
source: "cli"
|
|
8058
|
+
};
|
|
8059
|
+
if (orgId) {
|
|
8060
|
+
body.orgId = orgId;
|
|
8061
|
+
}
|
|
8062
|
+
const story = await apiService.createStory(userInfo.id, body);
|
|
8063
|
+
succeedSpinner(spinner, `Story created: "${story.title}"`);
|
|
8064
|
+
logger.log("");
|
|
8065
|
+
} catch (error) {
|
|
8066
|
+
const err = error;
|
|
8067
|
+
logger.log("");
|
|
8068
|
+
logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
|
|
8069
|
+
process.exit(1);
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
8072
|
+
async function storyDeleteCommand(storyId) {
|
|
8073
|
+
logger.log("");
|
|
8074
|
+
try {
|
|
8075
|
+
const isAuthenticated = await ensureAuthenticated();
|
|
8076
|
+
if (!isAuthenticated) {
|
|
8077
|
+
process.exit(1);
|
|
8078
|
+
}
|
|
8079
|
+
const userInfo = authService.getUserInfo();
|
|
8080
|
+
if (!userInfo) {
|
|
8081
|
+
logger.log(boxen8(formatErrorMessage("Could not retrieve user info"), boxStyles.error));
|
|
8082
|
+
process.exit(1);
|
|
8083
|
+
}
|
|
8084
|
+
const shouldDelete = await promptConfirm(`Delete story ${storyId}?`, false);
|
|
8085
|
+
if (!shouldDelete) {
|
|
8086
|
+
logger.log(theme.secondary("Deletion cancelled"));
|
|
8087
|
+
return;
|
|
8088
|
+
}
|
|
8089
|
+
const spinner = deletingStorySpinner();
|
|
8090
|
+
spinner.start();
|
|
8091
|
+
await apiService.deleteStory(userInfo.id, storyId);
|
|
8092
|
+
succeedSpinner(spinner, "Story deleted");
|
|
8093
|
+
logger.log("");
|
|
8094
|
+
} catch (error) {
|
|
8095
|
+
const err = error;
|
|
8096
|
+
logger.log("");
|
|
8097
|
+
logger.log(boxen8(formatErrorMessage(err.message, getErrorHint3(err)), boxStyles.error));
|
|
8098
|
+
process.exit(1);
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
8101
|
+
function formatStoriesTable(stories) {
|
|
8102
|
+
const table = new Table3({
|
|
8103
|
+
head: [
|
|
8104
|
+
colors.primary("ID"),
|
|
8105
|
+
colors.primary("Title"),
|
|
8106
|
+
colors.primary("Competencies"),
|
|
8107
|
+
colors.primary("Updated")
|
|
8108
|
+
],
|
|
8109
|
+
colWidths: [12, 35, 30, 14],
|
|
8110
|
+
wordWrap: true,
|
|
8111
|
+
style: tableStyles.default.style
|
|
8112
|
+
});
|
|
8113
|
+
stories.forEach((story) => {
|
|
8114
|
+
const competencies = story.competencies.length > 0 ? story.competencies.join(", ") : colors.dim("none");
|
|
8115
|
+
const updated = formatDate(story.updatedAt);
|
|
8116
|
+
table.push([
|
|
8117
|
+
colors.dim(story.id),
|
|
8118
|
+
colors.white(story.title),
|
|
8119
|
+
colors.primary(competencies),
|
|
8120
|
+
colors.highlight(updated)
|
|
8121
|
+
]);
|
|
8122
|
+
});
|
|
8123
|
+
return table.toString();
|
|
8124
|
+
}
|
|
8125
|
+
function showUpgradeMessage() {
|
|
8126
|
+
logger.log("");
|
|
8127
|
+
logger.log(
|
|
8128
|
+
boxen8(
|
|
8129
|
+
theme.warning("CLI Access Requires Subscription") + "\n\nThe BragDuck CLI is available for Plus and Pro subscribers.\nUpgrade now to unlock:\n\n \u2022 List and manage your interview stories\n \u2022 Create STAR-format stories from the terminal\n \u2022 Automatic work item scanning\n\n" + colors.highlight("Upgrade at: https://bragduck.com/app/settings/plans"),
|
|
8130
|
+
{
|
|
8131
|
+
...boxStyles.warning,
|
|
8132
|
+
padding: 1,
|
|
8133
|
+
margin: 1
|
|
8134
|
+
}
|
|
8135
|
+
)
|
|
8136
|
+
);
|
|
8137
|
+
logger.log("");
|
|
8138
|
+
}
|
|
8139
|
+
function getErrorHint3(error) {
|
|
8140
|
+
if (error.name === "TokenExpiredError" || error.name === "AuthenticationError") {
|
|
8141
|
+
return 'Run "bragduck auth login" to login again';
|
|
8142
|
+
}
|
|
8143
|
+
if (error.name === "NetworkError") {
|
|
8144
|
+
return "Check your internet connection and try again";
|
|
8145
|
+
}
|
|
8146
|
+
if (error.name === "ApiError") {
|
|
8147
|
+
return "The server might be experiencing issues. Try again later";
|
|
8148
|
+
}
|
|
8149
|
+
return "Try running with DEBUG=* for more information";
|
|
8150
|
+
}
|
|
8151
|
+
|
|
7733
8152
|
// src/commands/config.ts
|
|
7734
8153
|
init_esm_shims();
|
|
7735
8154
|
init_storage_service();
|
|
7736
8155
|
init_logger();
|
|
7737
8156
|
init_constants();
|
|
7738
|
-
import
|
|
8157
|
+
import boxen9 from "boxen";
|
|
7739
8158
|
import chalk6 from "chalk";
|
|
7740
|
-
import
|
|
8159
|
+
import Table4 from "cli-table3";
|
|
7741
8160
|
init_errors();
|
|
7742
8161
|
var VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);
|
|
7743
8162
|
async function configCommand(subcommand, key, value) {
|
|
@@ -7771,7 +8190,7 @@ async function configCommand(subcommand, key, value) {
|
|
|
7771
8190
|
const err = error;
|
|
7772
8191
|
logger.log("");
|
|
7773
8192
|
logger.log(
|
|
7774
|
-
|
|
8193
|
+
boxen9(formatErrorMessage(err.message, getConfigHint(err)), {
|
|
7775
8194
|
padding: 1,
|
|
7776
8195
|
margin: 1,
|
|
7777
8196
|
borderStyle: "round",
|
|
@@ -7791,7 +8210,7 @@ async function handleListConfig() {
|
|
|
7791
8210
|
confluenceInstance: storageService.getConfig("confluenceInstance"),
|
|
7792
8211
|
gitlabInstance: storageService.getConfig("gitlabInstance")
|
|
7793
8212
|
};
|
|
7794
|
-
const table = new
|
|
8213
|
+
const table = new Table4({
|
|
7795
8214
|
head: [chalk6.cyan("Key"), chalk6.cyan("Value"), chalk6.cyan("Default")],
|
|
7796
8215
|
colWidths: [25, 40, 40],
|
|
7797
8216
|
wordWrap: true,
|
|
@@ -7865,7 +8284,7 @@ async function handleSetConfig(key, value) {
|
|
|
7865
8284
|
const typedValue = validateAndConvertValue(key, value);
|
|
7866
8285
|
storageService.setConfig(key, typedValue);
|
|
7867
8286
|
logger.log(
|
|
7868
|
-
|
|
8287
|
+
boxen9(
|
|
7869
8288
|
`${chalk6.green.bold("\u2713 Configuration updated")}
|
|
7870
8289
|
|
|
7871
8290
|
${chalk6.white(key)}: ${chalk6.yellow(String(typedValue))}`,
|
|
@@ -7997,6 +8416,18 @@ program.command("list").description("List your existing brags").option("-l, --li
|
|
|
7997
8416
|
process.exit(1);
|
|
7998
8417
|
}
|
|
7999
8418
|
});
|
|
8419
|
+
program.command("story [subcommand] [id]").description("Manage interview stories (subcommands: list, create, delete)").option("-l, --limit <number>", "Number of stories to display", (val) => parseInt(val, 10), 20).option("-s, --search <query>", "Search stories by keyword").option("-c, --competency <competency>", "Filter by competency").option("-t, --title <title>", "Story title (for create)").action(async (subcommand, id, options) => {
|
|
8420
|
+
try {
|
|
8421
|
+
if (subcommand === "delete" || subcommand === "rm") {
|
|
8422
|
+
await storyCommand(subcommand, id, options);
|
|
8423
|
+
} else {
|
|
8424
|
+
await storyCommand(subcommand, options);
|
|
8425
|
+
}
|
|
8426
|
+
} catch (error) {
|
|
8427
|
+
console.error(error);
|
|
8428
|
+
process.exit(1);
|
|
8429
|
+
}
|
|
8430
|
+
});
|
|
8000
8431
|
program.command("logout").description("Clear stored credentials").action(async () => {
|
|
8001
8432
|
try {
|
|
8002
8433
|
await logoutCommand();
|