contribute-now 0.9.0-dev.8626d97 → 0.9.0-dev.987ca85

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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/cli.js +189 -48
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # contribute-now
2
2
 
3
- ![GitHub Repo Banner](https://ghrb.waren.build/banner?header=contribute-now+%F0%9F%94%84&subheader=Any+workflow.+Clean+commits.+Zero+friction.&bg=0D1117-21262D&color=FFFFFF&headerfont=Google+Sans+Code&subheaderfont=Sour+Gummy&support=true)
3
+ ![GitHub Repo Banner](https://ghrb.waren.build/banner?header=>_contribute-now&subheader=Ship+faster+with+clean+git+flow&bg=431586-9231A8&color=FFFFFF&headerfont=Google+Sans+Code&subheaderfont=Google+Sans+Code&support=true)
4
4
  <!-- Created with GitHub Repo Banner by Waren Gonzaga: https://ghrb.waren.build -->
5
5
 
6
6
  **contribute-now** is a developer CLI that automates git workflows — branching, syncing, staging, committing, and opening PRs — so you can focus on shipping, not on memorizing git commands.
@@ -274,6 +274,8 @@ List branches with workflow-aware labels and tracking status.
274
274
  cn branch # local branches
275
275
  cn branch --all # local + remote branches
276
276
  cn branch --remote # remote branches only
277
+ cn branch --sync # sync refs (friendly alias of --prune)
278
+ cn branch --prune # fetch remotes + prune deleted remote branches
277
279
  ```
278
280
 
279
281
  Branches are annotated with workflow labels (e.g., base, dev, feature) and tracking info (upstream, gone, no remote).
package/dist/cli.js CHANGED
@@ -2949,7 +2949,9 @@ var init_tips = __esm(() => {
2949
2949
  { command: "cn branch --help", description: "learn branch list modes and filters" },
2950
2950
  { command: "cn branch", description: "list local branches and tracking info" },
2951
2951
  { command: "cn branch --all", description: "include local and remote branches" },
2952
- { command: "cn branch --remote", description: "show only remote branches" }
2952
+ { command: "cn branch --remote", description: "show only remote branches" },
2953
+ { command: "cn branch --sync", description: "sync remote refs before listing branches" },
2954
+ { command: "cn branch --prune", description: "fetch remotes and prune deleted refs first" }
2953
2955
  ]
2954
2956
  },
2955
2957
  hook: {
@@ -9182,6 +9184,9 @@ async function runMain(cmd, opts = {}) {
9182
9184
  }
9183
9185
  }
9184
9186
 
9187
+ // src/cli.ts
9188
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
9189
+
9185
9190
  // src/commands/branch.ts
9186
9191
  init_config();
9187
9192
  var import_picocolors2 = __toESM(require_picocolors(), 1);
@@ -9308,6 +9313,9 @@ async function addRemote(name, url) {
9308
9313
  async function fetchAll() {
9309
9314
  return run(["fetch", "--all", "--quiet"]);
9310
9315
  }
9316
+ async function fetchAllPrune() {
9317
+ return run(["fetch", "--all", "--prune", "--quiet"]);
9318
+ }
9311
9319
  async function checkoutBranch(branch) {
9312
9320
  return run(["checkout", branch]);
9313
9321
  }
@@ -9765,10 +9773,16 @@ function isBranchProtected(branch, config) {
9765
9773
  }
9766
9774
 
9767
9775
  // src/commands/branch.ts
9776
+ function shouldPruneBranchRefs(args) {
9777
+ return Boolean(args.prune || args.sync);
9778
+ }
9779
+ function shouldWarnDeletedRemoteBranch(params) {
9780
+ return params.isCurrent && params.gone && (params.hasUncommitted || params.uniqueCommitsAheadOfBase > 0);
9781
+ }
9768
9782
  var branch_default = defineCommand({
9769
9783
  meta: {
9770
9784
  name: "branch",
9771
- description: "List branches with workflow-aware labels and status"
9785
+ description: "List branches with workflow-aware labels and optional remote pruning"
9772
9786
  },
9773
9787
  args: {
9774
9788
  all: {
@@ -9782,6 +9796,18 @@ var branch_default = defineCommand({
9782
9796
  alias: "r",
9783
9797
  description: "Show only remote branches",
9784
9798
  default: false
9799
+ },
9800
+ prune: {
9801
+ type: "boolean",
9802
+ alias: "p",
9803
+ description: "Fetch all remotes and prune deleted remote-tracking branches first",
9804
+ default: false
9805
+ },
9806
+ sync: {
9807
+ type: "boolean",
9808
+ alias: "s",
9809
+ description: "Sync remote branch refs before listing (alias of --prune)",
9810
+ default: false
9785
9811
  }
9786
9812
  },
9787
9813
  async run({ args }) {
@@ -9794,10 +9820,45 @@ var branch_default = defineCommand({
9794
9820
  const currentBranch = await getCurrentBranch();
9795
9821
  const showRemoteOnly = args.remote;
9796
9822
  const showAll = args.all;
9823
+ const shouldPrune = shouldPruneBranchRefs(args);
9797
9824
  await projectHeading("branch", "\uD83C\uDF3F");
9825
+ if (shouldPrune) {
9826
+ info("Fetching remotes and pruning stale remote-tracking branches...");
9827
+ const pruneResult = await fetchAllPrune();
9828
+ if (pruneResult.exitCode === 0) {
9829
+ success("Remote refs refreshed and stale branches pruned.");
9830
+ } else {
9831
+ warn(`Could not fully prune remote refs: ${pruneResult.stderr.trim() || "git fetch --all --prune failed"}`);
9832
+ }
9833
+ }
9798
9834
  console.log();
9799
9835
  if (!showRemoteOnly) {
9800
9836
  const localBranches = await getLocalBranches();
9837
+ const currentLocalBranch = localBranches.find((b2) => b2.isCurrent);
9838
+ if (currentLocalBranch?.gone) {
9839
+ const hasUncommitted = await hasUncommittedChanges();
9840
+ let uniqueCommitsAheadOfBase = 0;
9841
+ if (config) {
9842
+ const syncSource = getSyncSource(config);
9843
+ uniqueCommitsAheadOfBase = await countCommitsAhead(currentLocalBranch.name, syncSource.ref);
9844
+ }
9845
+ if (shouldWarnDeletedRemoteBranch({
9846
+ isCurrent: currentLocalBranch.isCurrent,
9847
+ gone: currentLocalBranch.gone,
9848
+ hasUncommitted,
9849
+ uniqueCommitsAheadOfBase
9850
+ })) {
9851
+ warn(`Current branch ${import_picocolors2.default.bold(currentLocalBranch.name)} was deleted remotely but still has local work.`);
9852
+ if (hasUncommitted) {
9853
+ info("You have uncommitted local changes.");
9854
+ }
9855
+ if (uniqueCommitsAheadOfBase > 0) {
9856
+ info(`You have ${uniqueCommitsAheadOfBase} local commit(s) not in the base sync branch.`);
9857
+ }
9858
+ info(`Run ${import_picocolors2.default.bold("cn update")} to move your work to a fresh branch safely.`, "");
9859
+ console.log();
9860
+ }
9861
+ }
9801
9862
  if (localBranches.length === 0) {
9802
9863
  console.log(import_picocolors2.default.dim(" No local branches found."));
9803
9864
  } else {
@@ -13705,7 +13766,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
13705
13766
  // package.json
13706
13767
  var package_default = {
13707
13768
  name: "contribute-now",
13708
- version: "0.9.0-dev.8626d97",
13769
+ version: "0.9.0-dev.987ca85",
13709
13770
  description: "Developer CLI that automates git workflows \u2014 branching, syncing, committing, and PRs \u2014 with multi-workflow and commit convention support.",
13710
13771
  type: "module",
13711
13772
  bin: {
@@ -17710,7 +17771,7 @@ function getAuthor() {
17710
17771
  function showBanner(variant = "small") {
17711
17772
  console.log(import_picocolors25.default.cyan(`
17712
17773
  ${LOGO}`));
17713
- console.log(` ${import_picocolors25.default.dim(`v${getVersion()}`)} ${import_picocolors25.default.dim("\u2014")} ${import_picocolors25.default.dim(`Built by ${getAuthor()}`)}`);
17774
+ console.log(` ${import_picocolors25.default.white(`v${getVersion()}`)} ${import_picocolors25.default.white("\u2014")} ${import_picocolors25.default.white(`Built by ${getAuthor()}`)}`);
17714
17775
  const announcements = getActiveAnnouncements();
17715
17776
  if (announcements.length > 0) {
17716
17777
  console.log();
@@ -17794,8 +17855,8 @@ ${LOGO}`));
17794
17855
  }
17795
17856
  console.log(` ${import_picocolors25.default.dim(`\u2514${"\u2500".repeat(contentWidth + 2)}\u2518`)}`);
17796
17857
  console.log();
17797
- console.log(` ${import_picocolors25.default.dim("Star or contribute:")} ${import_picocolors25.default.dim(linkify("gh.waren.build/contribute-now", "https://gh.waren.build/contribute-now"))}`);
17798
- console.log(` ${import_picocolors25.default.dim("Sponsor:")} ${import_picocolors25.default.dim(linkify("warengonzaga.com/sponsor", "https://warengonzaga.com/sponsor"))}`);
17858
+ console.log(` \uD83E\uDD1D ${import_picocolors25.default.white("Contribute:")} ${import_picocolors25.default.dim(linkify("gh.waren.build/contribute-now", "https://gh.waren.build/contribute-now"))}`);
17859
+ console.log(` \uD83D\uDE4F ${import_picocolors25.default.white("Sponsor:")} ${import_picocolors25.default.dim(linkify("warengonzaga.com/sponsor", "https://warengonzaga.com/sponsor"))}`);
17799
17860
  }
17800
17861
  console.log();
17801
17862
  }
@@ -17882,6 +17943,112 @@ function getAnnouncementTone(kind) {
17882
17943
  }
17883
17944
 
17884
17945
  // src/cli.ts
17946
+ var CLI_SUBCOMMANDS = {
17947
+ setup: setup_default,
17948
+ config: config_default,
17949
+ sync: sync_default,
17950
+ start: start_default,
17951
+ commit: commit_default,
17952
+ update: update_default,
17953
+ submit: submit_default,
17954
+ switch: switch_default,
17955
+ discard: discard_default,
17956
+ save: save_default,
17957
+ branch: branch_default,
17958
+ clean: clean_default,
17959
+ status: status_default,
17960
+ log: log_default,
17961
+ hook: hook_default,
17962
+ validate: validate_default,
17963
+ doctor: doctor_default,
17964
+ label: label_default
17965
+ };
17966
+ function formatVersionInfo() {
17967
+ return `Contribute Now v${getVersion()} - Built by Waren Gonzaga`;
17968
+ }
17969
+ function cmd(name, desc) {
17970
+ return ` ${import_picocolors26.default.cyan(name.padEnd(12))}${import_picocolors26.default.white(desc)}`;
17971
+ }
17972
+ function showCompactRootHelp() {
17973
+ console.log(`${import_picocolors26.default.bold("USAGE")} ${import_picocolors26.default.cyan("cn <command> [options]")}`);
17974
+ console.log();
17975
+ console.log(import_picocolors26.default.bold("WORKFLOW"));
17976
+ console.log(cmd("setup", "Initialize your local environment and GitHub access"));
17977
+ console.log(cmd("start", "Create a new branch for your contribution"));
17978
+ console.log(cmd("commit", "Stage and commit changes with guided prompts"));
17979
+ console.log(cmd("update", "Sync your branch and update the PR description"));
17980
+ console.log(cmd("submit", "Push and open a pull request on GitHub"));
17981
+ console.log();
17982
+ console.log(import_picocolors26.default.bold("BRANCH & COMMITS"));
17983
+ console.log(cmd("branch", "List local/remote branches and optionally prune remotes"));
17984
+ console.log(cmd("switch", "Switch to a different branch"));
17985
+ console.log(cmd("save", "Stash uncommitted changes for later"));
17986
+ console.log(cmd("discard", "Discard uncommitted changes"));
17987
+ console.log();
17988
+ console.log(import_picocolors26.default.bold("GITHUB"));
17989
+ console.log(cmd("sync", "Sync the default branch and rebase your work"));
17990
+ console.log(cmd("label", "Suggest and apply labels on issues and PRs"));
17991
+ console.log(cmd("config", "View or update your Contribute Now config"));
17992
+ console.log();
17993
+ console.log(import_picocolors26.default.bold("UTILITIES"));
17994
+ console.log(cmd("status", "Show current branch and working tree status"));
17995
+ console.log(cmd("log", "Display a compact commit log"));
17996
+ console.log(cmd("clean", "Remove stale branches and tidy up"));
17997
+ console.log(cmd("validate", "Check branch name and commit message format"));
17998
+ console.log(cmd("hook", "Install or uninstall Git hooks"));
17999
+ console.log(cmd("doctor", "Diagnose and fix common setup issues"));
18000
+ console.log();
18001
+ console.log(`${import_picocolors26.default.bold("FLAGS")} ${import_picocolors26.default.cyan("-v, --version")} ${import_picocolors26.default.dim("Show version")}`);
18002
+ console.log();
18003
+ console.log(import_picocolors26.default.dim("Run cn <command> --help for detailed options and examples."));
18004
+ }
18005
+ function formatArgLabel(name, arg) {
18006
+ if (arg.type === "positional") {
18007
+ return arg.required ? `<${name}>` : `[${name}]`;
18008
+ }
18009
+ const flags = [];
18010
+ if (arg.alias) {
18011
+ flags.push(`-${arg.alias}`);
18012
+ }
18013
+ flags.push(`--${name}`);
18014
+ const needsValue = arg.type && arg.type !== "boolean";
18015
+ const valueHint = needsValue ? ` <${arg.type}>` : "";
18016
+ return `${flags.join(", ")}${valueHint}`;
18017
+ }
18018
+ function findRequestedSubCommand(argv2) {
18019
+ const names = Object.keys(CLI_SUBCOMMANDS);
18020
+ for (const token of argv2) {
18021
+ if (names.includes(token)) {
18022
+ return token;
18023
+ }
18024
+ }
18025
+ return null;
18026
+ }
18027
+ function showCompactSubCommandHelp(commandName) {
18028
+ const command = CLI_SUBCOMMANDS[commandName];
18029
+ const description = command.meta?.description ?? `Run ${commandName} command`;
18030
+ const args = command.args ?? {};
18031
+ const positionalArgs = Object.entries(args).filter(([, arg]) => arg.type === "positional");
18032
+ const optionArgs = Object.entries(args).filter(([, arg]) => arg.type !== "positional");
18033
+ console.log(description);
18034
+ console.log();
18035
+ const positionalUsage = positionalArgs.map(([name, arg]) => formatArgLabel(name, arg)).join(" ").trim();
18036
+ const usageSuffix = positionalUsage.length > 0 ? ` ${positionalUsage}` : " [OPTIONS]";
18037
+ console.log(`${import_picocolors26.default.bold("USAGE")} ${import_picocolors26.default.cyan(`cn ${commandName}${usageSuffix}`)}`);
18038
+ if (optionArgs.length > 0) {
18039
+ console.log();
18040
+ console.log(import_picocolors26.default.bold("OPTIONS"));
18041
+ console.log();
18042
+ const labels = optionArgs.map(([name, arg]) => formatArgLabel(name, arg));
18043
+ const maxLabel = labels.reduce((max, label) => Math.max(max, label.length), 0);
18044
+ optionArgs.forEach(([, arg], index) => {
18045
+ const label = labels[index].padEnd(maxLabel + 2);
18046
+ const desc = arg.description ?? "";
18047
+ console.log(` ${import_picocolors26.default.cyan(label)}${desc}`);
18048
+ });
18049
+ }
18050
+ console.log();
18051
+ }
17885
18052
  function normalizeCliArgs(argv2) {
17886
18053
  return argv2.map((arg, index) => {
17887
18054
  const previous = argv2[index - 1];
@@ -17897,32 +18064,23 @@ function normalizeCliArgs(argv2) {
17897
18064
  }
17898
18065
  process.argv = normalizeCliArgs(process.argv);
17899
18066
  var isVersion = process.argv.includes("--version") || process.argv.includes("-v");
18067
+ var subCommands = Object.keys(CLI_SUBCOMMANDS);
18068
+ var isHelp = process.argv.includes("--help") || process.argv.includes("-h");
18069
+ var hasSubCommand = subCommands.some((cmd2) => process.argv.includes(cmd2));
18070
+ var isRootHelp = isHelp && !hasSubCommand;
18071
+ var requestedSubCommand = isHelp ? findRequestedSubCommand(process.argv) : null;
17900
18072
  if (!isVersion) {
17901
- const subCommands = [
17902
- "setup",
17903
- "config",
17904
- "sync",
17905
- "start",
17906
- "commit",
17907
- "update",
17908
- "submit",
17909
- "switch",
17910
- "discard",
17911
- "save",
17912
- "clean",
17913
- "status",
17914
- "log",
17915
- "branch",
17916
- "hook",
17917
- "validate",
17918
- "doctor",
17919
- "label"
17920
- ];
17921
- const isHelp = process.argv.includes("--help") || process.argv.includes("-h");
17922
- const hasSubCommand = subCommands.some((cmd) => process.argv.includes(cmd));
17923
- const useBigBanner = isHelp || !hasSubCommand;
18073
+ const useBigBanner = !hasSubCommand && !isHelp;
17924
18074
  showBanner(useBigBanner ? "big" : "small");
17925
18075
  }
18076
+ if (isRootHelp) {
18077
+ showCompactRootHelp();
18078
+ process.exit(0);
18079
+ }
18080
+ if (isHelp && requestedSubCommand) {
18081
+ showCompactSubCommandHelp(requestedSubCommand);
18082
+ process.exit(0);
18083
+ }
17926
18084
  var main = defineCommand({
17927
18085
  meta: {
17928
18086
  name: "cn",
@@ -17937,28 +18095,11 @@ var main = defineCommand({
17937
18095
  }
17938
18096
  },
17939
18097
  subCommands: {
17940
- setup: setup_default,
17941
- config: config_default,
17942
- sync: sync_default,
17943
- start: start_default,
17944
- commit: commit_default,
17945
- update: update_default,
17946
- submit: submit_default,
17947
- switch: switch_default,
17948
- discard: discard_default,
17949
- save: save_default,
17950
- branch: branch_default,
17951
- clean: clean_default,
17952
- status: status_default,
17953
- log: log_default,
17954
- hook: hook_default,
17955
- validate: validate_default,
17956
- doctor: doctor_default,
17957
- label: label_default
18098
+ ...CLI_SUBCOMMANDS
17958
18099
  },
17959
18100
  run({ args }) {
17960
18101
  if (args.version) {
17961
- console.log(`cn v${getVersion()}`);
18102
+ console.log(formatVersionInfo());
17962
18103
  }
17963
18104
  }
17964
18105
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contribute-now",
3
- "version": "0.9.0-dev.8626d97",
3
+ "version": "0.9.0-dev.987ca85",
4
4
  "description": "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
5
5
  "type": "module",
6
6
  "bin": {