better-commits 1.23.0 → 1.23.2

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/branch.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #! /usr/bin/env node
2
- import{c as q,e as j,f as U,g as W,j as m}from"./chunk-43H72S6V.js";import{a as F,e as E,j as G,k as L,l as V,m as f,o as l,r as H,s as D}from"./chunk-B7AGSPP3.js";import gt from"configstore";import{chdir as ut}from"process";import{ValiError as _t,parse as J}from"valibot";var s=class{constructor(t,e,n){this.config=t;this.branch_state=e;this.prompt_cache=n}};import*as b from"@clack/prompts";var d=class extends s{async run(){if(this.#e){let t=await b.select({message:this.#t,initialValue:this.#r,options:G});b.isCancel(t)&&process.exit(),this.#n(t)}}get#t(){return"Checkout a branch or create a worktree?"}get#e(){return this.config.worktrees.enable}get#r(){return this.branch_state.checkout||this.config.branch_action_default}#n(t){this.branch_state.checkout=t}};import*as v from"@clack/prompts";var y=class extends s{async run(){if(!this.#t)return;let t=await v.text({message:this.#r,placeholder:"",initialValue:this.#n,validate:e=>this.#i(e)});v.isCancel(t)&&process.exit(0),this.#o(t??"")}get#t(){return this.config.branch_user.enable}get#e(){return this.config.branch_user.required}get#r(){return this.#e?"Type your git username":m("Type your git username")}get#n(){return this.branch_state.user||H(this.prompt_cache,"username")}#i(t){if(this.#e&&!t)return"Please enter a username"}#o(t){this.branch_state.user=t.replace(/\s+/g,"-").toLowerCase(),D(this.prompt_cache,"username",this.branch_state.user)}};import*as g from"@clack/prompts";var k=class extends s{async run(){if(!this.#t)return;let e=await(this.config.branch_type.autocomplete?g.autocomplete:g.select)({message:this.#e,initialValue:this.#r,options:this.#n});g.isCancel(e)&&process.exit(0),this.#i(e)}get#t(){return this.config.branch_type.enable}get#e(){return"Select a branch type"}get#r(){return this.branch_state.type||this.config.commit_type.initial_value}get#n(){return this.config.commit_type.options}#i(t){this.branch_state.type=t}};import*as p from"@clack/prompts";var w=class extends s{async run(){if(!this.#t)return;let e=await(this.config.branch_scope.autocomplete?p.autocomplete:p.select)({message:this.#e,initialValue:this.#r,options:this.#n});p.isCancel(e)&&process.exit(0),await this.#o(e)}get#t(){return this.config.branch_scope.enable}get#e(){return"Select a branch scope"}get#r(){return this.branch_state.scope||this.config.commit_scope.initial_value}get#n(){return this.config.commit_scope.options}get#i(){return this.config.commit_scope.custom_scope}async#o(t){let e=t;if(e===F&&this.#i){let n=await p.text({message:"Write a custom scope",placeholder:""});p.isCancel(n)&&process.exit(0),e=n??""}this.branch_state.scope=e}};import*as C from"@clack/prompts";var x=class extends s{async run(){if(!this.#t)return;let t=await C.text({message:this.#r,placeholder:"",validate:e=>this.#n(e),initialValue:this.branch_state.ticket});C.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_ticket.enable}get#e(){return this.config.branch_ticket.required}get#r(){return this.#e?"Type ticket / issue number":m("Type ticket / issue number")}#n(t){if(this.#e&&!t)return"Please enter a ticket / issue"}#i(t){this.branch_state.ticket=t}};import*as S from"@clack/prompts";var $=class extends s{async run(){if(!this.#t)return;let t=await S.text({message:this.#r,placeholder:"",validate:e=>this.#n(e),initialValue:this.branch_state.version});S.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_version.enable}get#e(){return this.config.branch_version.required}get#r(){return this.#e?"Type version number":m("Type version number")}#n(t){if(this.#e&&!t)return"Please enter a version"}#i(t){this.branch_state.version=t}};import*as O from"@clack/prompts";var I=class extends s{async run(){let t=await O.text({message:this.#t,placeholder:"",validate:e=>this.#r(e),initialValue:this.branch_state.description});O.isCancel(t)&&process.exit(0),this.#n(t??"")}get#t(){return"Type a short description"}get#e(){return this.config.branch_description.max_length}#r(t){if(!t)return"Please enter a description";if(t.length>this.#e)return`Exceeded max length. Description max [${this.#e}]`}#n(t){this.branch_state.description=t.replace(/\s+/g,"-").toLowerCase()}};import*as u from"@clack/prompts";import{execSync as B}from"child_process";import h from"picocolors";import{chdir as at}from"process";import{parse as rt}from"@bomb.sh/args";var M=["user","type","scope","description","ticket","branch-version","checkout"],nt=["git-dir","work-tree"],it=["interactive","dry-run","help","version"],T=class{#t;constructor(t){this.#t=t}get interactive(){return!this.#t.no_interactive}get dry_run(){return this.#t.dry_run}get help(){return this.#t.help}get version(){return this.#t.version}get git_args(){return this.#t.git_args}get branch_state(){return this.#t.branch_state}},a=new T(ot(process.argv.slice(2)));function ot(r){let t=rt(r,{alias:{h:"help",v:"version"},boolean:it,string:[...M,...nt]}),e={};return M.forEach(n=>{let i=t[n];if(i){let o=n==="branch-version"?"version":n.replace("-","_");o==="checkout"?e[o]=i??"branch":e[o]=i}}),{help:t.help===!0,version:t.version===!0,git_args:st(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,branch_state:e}}function st(r,t){return`${r?`--git-dir=${r}`:""} ${t?`--work-tree=${t}`:""}`.trim()}function K(r,t){let e="";return t.branch_order.forEach(n=>{let i=`branch_${n}`;r[n]&&(e+=r[n]+t[i].separator)}),e.endsWith("-")||e.endsWith("/")||e.endsWith("_")?e.slice(0,-1).trim():e.trim()}function Y(r,t,e){let n=e.split("/").pop()||"repo",i=t.worktrees.folder_template;i=i.replace("{{repo_name}}",n).replace("{{branch_description}}",r.description).replace("{{user}}",r.user||"").replace("{{type}}",r.type||"").replace("{{scope}}",r.scope||"").replace("{{ticket}}",r.ticket||"").replace("{{version}}",r.version||""),i=i.replace(/\s/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"");let o=t.worktrees.base_path;return`${o}${o.endsWith("/")?"":"/"}${i}`}var _=class extends s{async run(){this.#i(),this.#o(),this.#a()}get#t(){return this.branch_state.checkout==="worktree"}get#e(){return this.#t?this.config.worktree_pre_commands:this.config.branch_pre_commands}get#r(){return this.#t?this.config.worktree_post_commands:this.config.branch_post_commands}get#n(){return K(this.branch_state,this.config)}#i(){this.#s(this.#e,"Something went wrong when executing pre-commands: ")}#o(){let t=this.#n,e=this.#c(t);if(!this.#t){try{B(`git ${a.git_args} checkout ${e} ${t}`,{stdio:"inherit"}),u.log.info(`Switched to a new branch '${h.bgGreen(" "+h.black(t)+" ")}'`)}catch{process.exit(0)}return}try{let n=Y(this.branch_state,this.config,f(a.git_args));B(`git ${a.git_args} worktree add ${n} ${e} ${t}`,{stdio:"inherit"}),u.log.info(`Created a new worktree ${h.bgGreen(" "+h.black(n)+" ")}, checked out branch ${h.bgGreen(" "+h.black(t)+" ")}`),u.log.info(h.bgMagenta(h.black(` cd ${n} `))+" to navigate to your new worktree"),at(n)}catch{process.exit(0)}}#a(){this.#s(this.#r,"Something went wrong when executing post-commands: ")}#s(t,e){t.forEach(n=>{try{B(n,{stdio:"inherit"})}catch(i){u.log.error(e+i),process.exit(0)}})}#c(t){let e="";try{B(`git ${a.git_args} show-ref ${t}`,{encoding:"utf-8"}),u.log.warning(h.yellow(`${t} already exists! Checking out existing branch.`))}catch{e="-b"}return e}};import{execSync as ct}from"child_process";import c from"picocolors";var pt={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print branch commands without creating a branch or worktree.","--help":"Show help information and exit."},ht={"--user":"Set branch username segment.","--type":"Set branch type (for example feat, fix, docs).","--scope":"Set branch scope segment.","--description":"Set branch description segment.","--ticket":"Set branch ticket/issue segment.","--branch-version":"Set branch version segment.","--checkout":"Choose branch or worktree checkout mode."},mt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function A(r){let n=" ";return Object.entries(r).map(([i,o])=>{let P=Math.max(2,26-i.length);return`${n}${i}${" ".repeat(P)}${o}`}).join(`
3
- `)}function z(r,t){let e=l(),n="(none)";try{n=ct(`git ${a.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let i=j(r.commit_type.options,a.git_args)||"Unknown",o=r.check_ticket.infer_ticket?U({append_hashtag:r.check_ticket.append_hashtag,prepend_hashtag:r.check_ticket.prepend_hashtag},a.git_args)||"Unknown":"Infer Disabled",P=r.commit_scope.infer_scope_from_branch?W(r.commit_scope.options,a.git_args)||"Unknown":"Infer Disabled",Q=r.commit_type.options.map(N=>N.value).join(", ").trim(),X=r.commit_scope.options.map(N=>N.value).join(", ").trim(),Z=A(pt),tt=A(mt),et=A(ht);console.log(`
2
+ import{c as q,e as j,f as U,g as W,j as g}from"./chunk-43H72S6V.js";import{a as F,e as E,j as G,k as L,l as V,m as f,o as l,r as D,s as H}from"./chunk-B7AGSPP3.js";import gt from"configstore";import{chdir as ut}from"process";import{ValiError as _t,parse as J}from"valibot";var a=class{constructor(t,e,n){this.config=t;this.branch_state=e;this.prompt_cache=n}};import*as b from"@clack/prompts";var d=class extends a{async run(){if(this.#e){let t=await b.select({message:this.#t,initialValue:this.#r,options:G});b.isCancel(t)&&process.exit(),this.#n(t)}}get#t(){return"Checkout a branch or create a worktree?"}get#e(){return this.config.worktrees.enable}get#r(){return this.branch_state.checkout||this.config.branch_action_default}#n(t){this.branch_state.checkout=t}};import*as v from"@clack/prompts";var y=class extends a{async run(){if(!this.#t)return;let t=await v.text({message:this.#r,placeholder:"",initialValue:this.#n,validate:e=>this.#i(e)});v.isCancel(t)&&process.exit(0),this.#o(t??"")}get#t(){return this.config.branch_user.enable}get#e(){return this.config.branch_user.required}get#r(){return this.#e?"Type your git username":g("Type your git username")}get#n(){return this.branch_state.user||D(this.prompt_cache,"username")}#i(t){if(this.#e&&!t)return"Please enter a username"}#o(t){this.branch_state.user=t.replace(/\s+/g,"-").toLowerCase(),H(this.prompt_cache,"username",this.branch_state.user)}};import*as u from"@clack/prompts";var k=class extends a{async run(){if(!this.#t)return;let e=await(this.config.branch_type.autocomplete?u.autocomplete:u.select)({message:this.#e,initialValue:this.#r,options:this.#n});u.isCancel(e)&&process.exit(0),this.#i(e)}get#t(){return this.config.branch_type.enable}get#e(){return"Select a branch type"}get#r(){return this.branch_state.type||this.config.commit_type.initial_value}get#n(){return this.config.commit_type.options}#i(t){this.branch_state.type=t}};import*as p from"@clack/prompts";var w=class extends a{async run(){if(!this.#t)return;let e=await(this.config.branch_scope.autocomplete?p.autocomplete:p.select)({message:this.#e,initialValue:this.#r,options:this.#n});p.isCancel(e)&&process.exit(0),await this.#o(e)}get#t(){return this.config.branch_scope.enable}get#e(){return"Select a branch scope"}get#r(){return this.branch_state.scope||this.config.commit_scope.initial_value}get#n(){return this.config.commit_scope.options}get#i(){return this.config.commit_scope.custom_scope}async#o(t){let e=t;if(e===F&&this.#i){let n=await p.text({message:"Write a custom scope",placeholder:""});p.isCancel(n)&&process.exit(0),e=n??""}this.branch_state.scope=e}};import*as C from"@clack/prompts";var x=class extends a{async run(){if(!this.#t)return;let t=await C.text({message:this.#r,placeholder:"",validate:e=>this.#n(e),initialValue:this.branch_state.ticket});C.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_ticket.enable}get#e(){return this.config.branch_ticket.required}get#r(){return this.#e?"Type ticket / issue number":g("Type ticket / issue number")}#n(t){if(this.#e&&!t)return"Please enter a ticket / issue"}#i(t){this.branch_state.ticket=t}};import*as S from"@clack/prompts";var $=class extends a{async run(){if(!this.#t)return;let t=await S.text({message:this.#r,placeholder:"",validate:e=>this.#n(e),initialValue:this.branch_state.version});S.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_version.enable}get#e(){return this.config.branch_version.required}get#r(){return this.#e?"Type version number":g("Type version number")}#n(t){if(this.#e&&!t)return"Please enter a version"}#i(t){this.branch_state.version=t}};import*as O from"@clack/prompts";var I=class extends a{async run(){let t=await O.text({message:this.#t,placeholder:"",validate:e=>this.#r(e),initialValue:this.branch_state.description});O.isCancel(t)&&process.exit(0),this.#n(t??"")}get#t(){return"Type a short description"}get#e(){return this.config.branch_description.max_length}#r(t){if(!t)return"Please enter a description";if(t.length>this.#e)return`Exceeded max length. Description max [${this.#e}]`}#n(t){this.branch_state.description=t.replace(/\s+/g,"-").toLowerCase()}};import*as m from"@clack/prompts";import{execSync as B}from"child_process";import h from"picocolors";import{chdir as at}from"process";import{parse as rt}from"@bomb.sh/args";var M=["user","type","scope","description","ticket","branch-version","checkout"],nt=["git-dir","work-tree"],it=["interactive","dry-run","help","version"],T=class{#t;constructor(t){this.#t=t}get interactive(){return!this.#t.no_interactive}get dry_run(){return this.#t.dry_run}get help(){return this.#t.help}get version(){return this.#t.version}get git_args(){return this.#t.git_args}get branch_state(){return this.#t.branch_state}},o=new T(ot(process.argv.slice(2)));function ot(r){let t=rt(r,{alias:{h:"help",v:"version"},boolean:it,string:[...M,...nt]}),e={};return M.forEach(n=>{let i=t[n];if(i){let s=n==="branch-version"?"version":n.replace("-","_");s==="checkout"?e[s]=i??"branch":e[s]=i}}),{help:t.help===!0,version:t.version===!0,git_args:st(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,branch_state:e}}function st(r,t){return`${r?`--git-dir=${r}`:""} ${t?`--work-tree=${t}`:""}`.trim()}function K(r,t){let e="";return t.branch_order.forEach(n=>{let i=`branch_${n}`;r[n]&&(e+=r[n]+t[i].separator)}),e.endsWith("-")||e.endsWith("/")||e.endsWith("_")?e.slice(0,-1).trim():e.trim()}function Y(r,t,e){let n=e.split("/").pop()||"repo",i=t.worktrees.folder_template;i=i.replace("{{repo_name}}",n).replace("{{branch_description}}",r.description).replace("{{user}}",r.user||"").replace("{{type}}",r.type||"").replace("{{scope}}",r.scope||"").replace("{{ticket}}",r.ticket||"").replace("{{version}}",r.version||""),i=i.replace(/\s/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"");let s=t.worktrees.base_path;return`${s}${s.endsWith("/")?"":"/"}${i}`}var _=class extends a{async run(){this.#i(),this.#o(),this.#c()}get#t(){return this.branch_state.checkout==="worktree"}get#e(){return this.#t?this.config.worktree_pre_commands:this.config.branch_pre_commands}get#r(){return this.#t?this.config.worktree_post_commands:this.config.branch_post_commands}get#n(){return K(this.branch_state,this.config)}#i(){this.#a(this.#e,"Something went wrong when executing pre-commands: ")}#o(){let t=this.#n,e=this.#p(t);if(!this.#t){let n=`git ${o.git_args} checkout ${e} ${t}`;if(o.dry_run){this.#s(n);return}try{B(n,{stdio:"inherit"}),m.log.info(`Switched to a new branch '${h.bgGreen(" "+h.black(t)+" ")}'`)}catch{process.exit(0)}return}try{let n=Y(this.branch_state,this.config,f(o.git_args)),i=`git ${o.git_args} worktree add ${n} ${e} ${t}`;if(o.dry_run){this.#s(i);return}B(i,{stdio:"inherit"}),m.log.info(`Created a new worktree ${h.bgGreen(" "+h.black(n)+" ")}, checked out branch ${h.bgGreen(" "+h.black(t)+" ")}`),m.log.info(h.bgMagenta(h.black(` cd ${n} `))+" to navigate to your new worktree"),at(n)}catch{process.exit(0)}}#c(){this.#a(this.#r,"Something went wrong when executing post-commands: ")}#a(t,e){t.forEach(n=>{if(o.dry_run){this.#s(n);return}try{B(n,{stdio:"inherit"})}catch(i){m.log.error(e+i),process.exit(0)}})}#s(t){m.log.info(`Dry run: ${t}`)}#p(t){let e="";try{B(`git ${o.git_args} show-ref ${t}`,{encoding:"utf-8"}),m.log.warning(h.yellow(`${t} already exists! Checking out existing branch.`))}catch{e="-b"}return e}};import{execSync as ct}from"child_process";import c from"picocolors";var pt={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print branch commands without creating a branch or worktree.","--help":"Show help information and exit."},ht={"--user":"Set branch username segment.","--type":"Set branch type (for example feat, fix, docs).","--scope":"Set branch scope segment.","--description":"Set branch description segment.","--ticket":"Set branch ticket/issue segment.","--branch-version":"Set branch version segment.","--checkout":"Choose branch or worktree checkout mode."},mt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function A(r){let n=" ";return Object.entries(r).map(([i,s])=>{let P=Math.max(2,26-i.length);return`${n}${i}${" ".repeat(P)}${s}`}).join(`
3
+ `)}function z(r,t){let e=l(),n="(none)";try{n=ct(`git ${o.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let i=j(r.commit_type.options,o.git_args)||"Unknown",s=r.check_ticket.infer_ticket?U({append_hashtag:r.check_ticket.append_hashtag,prepend_hashtag:r.check_ticket.prepend_hashtag},o.git_args)||"Unknown":"Infer Disabled",P=r.commit_scope.infer_scope_from_branch?W(r.commit_scope.options,o.git_args)||"Unknown":"Infer Disabled",Q=r.commit_type.options.map(N=>N.value).join(", ").trim(),X=r.commit_scope.options.map(N=>N.value).join(", ").trim(),Z=A(pt),tt=A(mt),et=A(ht);console.log(`
4
4
  ${c.green("\uF489 better-branch")} ${c.gray("v"+e)}
5
5
 
6
6
  ${c.gray("BRANCH")}
7
7
  ${n}
8
- ${c.gray("Type")} ${c.blue(i)} ${c.gray("\xB7")} ${c.gray("Scope")} ${c.cyan(P)} ${c.gray("\xB7")} ${c.gray("Ticket")} ${c.magenta(o)}
8
+ ${c.gray("Type")} ${c.blue(i)} ${c.gray("\xB7")} ${c.gray("Scope")} ${c.cyan(P)} ${c.gray("\xB7")} ${c.gray("Ticket")} ${c.magenta(s)}
9
9
 
10
10
  ${c.gray("CONFIGURATION")}
11
11
  ${t}
@@ -25,4 +25,4 @@ ${et}
25
25
  ${c.gray("Git Flags (Advanced)")}
26
26
  ${tt}
27
27
 
28
- `)}import*as R from"@clack/prompts";var ft=[d,y,k,x,w,$,I,_],{config:lt,config_source:dt}=V(" better-branch ",a.git_args);bt(lt,dt);async function bt(r,t){if(ut(f(a.git_args)),a.version){let o=l();R.log.step("Better Commits v"+o);return}if(a.help){z(r,t);return}let e=J(E,a.branch_state);if(!a.interactive)try{J(q(r),e)}catch(o){o instanceof _t?R.log.error(`Invalid branch input: ${o.message}`):R.log.error(`Failed to validate branch input: ${o}`),process.exit(0)}let n=r.cache_last_value?new gt("better-commits"):L,i=a.interactive?ft:[_];for(let o of i)await new o(r,e,n).run()}
28
+ `)}import*as R from"@clack/prompts";var ft=[d,y,k,x,w,$,I,_],{config:lt,config_source:dt}=V(" better-branch ",o.git_args);bt(lt,dt);async function bt(r,t){if(ut(f(o.git_args)),o.version){let s=l();R.log.step("Better Commits v"+s);return}if(o.help){z(r,t);return}let e=J(E,o.branch_state);if(!o.interactive)try{J(q(r),e)}catch(s){s instanceof _t?R.log.error(`Invalid branch input: ${s.message}`):R.log.error(`Failed to validate branch input: ${s}`),process.exit(0)}let n=r.cache_last_value?new gt("better-commits"):L,i=o.interactive?ft:[_];for(let s of i)await new s(r,e,n).run()}
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #! /usr/bin/env node
2
- import{a as dt,b as ft,d as ht,e as T,f as N,g as j,h as f,i as I,j as w,k as Z,l as bt,m as z}from"./chunk-43H72S6V.js";import{a as at,c as ct,f as n,i as mt,k as lt,l as pt,m as _t,o as R,p as ut,q as gt,r as g,s as d}from"./chunk-B7AGSPP3.js";import{chdir as qt}from"process";import*as J from"@clack/prompts";import{ValiError as Kt,parse as wt}from"valibot";import Ht from"configstore";import*as V from"@clack/prompts";var p=class{constructor(t,e,o){this.config=t;this.commit_state=e;this.prompt_cache=o}};var D=class extends p{async run(){if(this.#i){let{initial_value:t,message:e}=this.#e,s=await(this.config.commit_type.autocomplete?V.autocomplete:V.select)({message:e,initialValue:t,maxItems:this.#s,options:this.#t});V.isCancel(s)&&process.exit(0),this.#r(s)}}get#i(){return this.config.commit_type.enable}get#e(){let t=g(this.prompt_cache,"commit_type");if(t)return{initial_value:t,message:f("Commit type")};if(this.config.commit_type.infer_type_from_branch){let e=T(this.#t,n.git_args);if(e)return{message:I("Commit type"),initial_value:e}}return{initial_value:this.config.commit_type.initial_value,message:"Select a commit type"}}get#t(){return this.config.commit_type.options}get#o(){return this.#t.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??"",trailer:e.trailer??""}}),{})}get#s(){return this.config.commit_type.max_items}#r(t){d(this.prompt_cache,"commit_type",t);let e=this.#o;this.commit_state.trailer=e[t].trailer,this.commit_state.type=this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="Start"?`${e[t].emoji} ${t}`.trim():t}};import*as k from"@clack/prompts";var L=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),s=await(this.config.commit_scope.autocomplete?k.autocomplete:k.select)({message:e,initialValue:t,maxItems:this.#t,options:this.#o});k.isCancel(s)&&process.exit(0),await this.#r(s)}get#i(){return this.config.commit_scope.enable}#e(){let t=g(this.prompt_cache,"commit_scope");if(t)return{initial_value:t,message:f("Commit scope")};if(this.config.commit_scope.infer_scope_from_branch){let e=j(this.#o,n.git_args);if(e)return{initial_value:e,message:I("Commit scope")}}return{initial_value:this.config.commit_scope.initial_value,message:"Select a commit scope"}}get#t(){return this.config.commit_scope.max_items}get#o(){return this.config.commit_scope.options}get#s(){return this.config.commit_scope.custom_scope}async#r(t){d(this.prompt_cache,"commit_scope",t);let e=t;if(e===at&&this.#s){let o=await k.text({message:"Write a custom scope",placeholder:""});k.isCancel(o)&&process.exit(0),e=o??""}this.commit_state.scope=e}};import*as M from"@clack/prompts";var G=class extends p{async run(){let{initial_value:t,message:e}=this.#o();if(this.commit_state.ticket=t,this.#e){let o=await M.text({message:e,placeholder:"",initialValue:t});M.isCancel(o)&&process.exit(0),d(this.prompt_cache,"commit_ticket",o),this.commit_state.ticket=o??""}this.#t&&this.commit_state.ticket&&!this.commit_state.ticket.startsWith("#")&&(this.commit_state.ticket="#"+this.commit_state.ticket)}get#i(){return this.config.check_ticket.infer_ticket}get#e(){return this.config.check_ticket.confirm_ticket}get#t(){return this.config.check_ticket.prepend_hashtag==="Always"}#o(){let t=g(this.prompt_cache,"commit_ticket");if(t)return{initial_value:t,message:f("Ticket / issue")};if(this.#i){let e=N({append_hashtag:this.config.check_ticket.append_hashtag,prepend_hashtag:this.config.check_ticket.prepend_hashtag},n.git_args);if(e)return{initial_value:e,message:I("Ticket / issue")}}return{initial_value:this.commit_state.ticket,message:w("Add ticket / issue")}}};import*as W from"@clack/prompts";var B=class extends p{async run(){let{initial_value:t,message:e}=this.#i(),o=await W.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#e(s)});W.isCancel(o)&&process.exit(0),this.#n(o??"")}#i(){let t=g(this.prompt_cache,"commit_title");return t?{initial_value:t,message:f("Commit title")}:{initial_value:this.commit_state.title,message:"Write a brief title describing the commit"}}#e(t){if(!t)return"Please enter a title";if(this.#o(t)>this.#t)return`Exceeded max length. Title max [${this.#t}]`}get#t(){return this.config.commit_title.max_size}#o(t){return dt({type:this.commit_state.type,scope:this.commit_state.scope,ticket:this.commit_state.ticket,title:t},{include_ticket:this.config.check_ticket.add_to_title})}get#s(){return this.config.commit_type.options.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??""}}),{})}#r(t){return this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="After-Colon"?`${this.#s[this.commit_state.type]?.emoji??""} ${t}`.trim():t}#n(t){d(this.prompt_cache,"commit_title",t),this.commit_state.title=gt(this.#r(t))}};import*as K from"@clack/prompts";var q=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),o=await K.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#t(s)});K.isCancel(o)&&process.exit(0),this.#s(o??"")}get#i(){return this.config.commit_body.enable}#e(){let t=g(this.prompt_cache,"commit_body");return t?{initial_value:t,message:f("Commit body")}:{initial_value:"",message:w("Write a detailed description of the changes")}}#t(t){if(this.config.commit_body.required&&!t)return"Please enter a description"}#o(t){return this.config.commit_body.split_by_period?t.split(/\.\s+/).map(o=>o.trim()).join(`.
3
- `):t}#s(t){d(this.prompt_cache,"commit_body",t),this.commit_state.body=this.#o(t)}};import*as $ from"@clack/prompts";var H=class extends p{async run(){if(!this.#i)return;let{initial_values:t,message:e}=this.#o(),o=await $.multiselect({message:e,initialValues:t,options:this.#e,required:!1});$.isCancel(o)&&process.exit(0);let s=this.#r(o),r=await this.#n(s);this.#m(o,s,r)}get#i(){return this.config.commit_footer.enable}get#e(){let t=new Set(this.config.commit_footer.options);return mt.filter(e=>t.has(e.value))}get#t(){return this.#e.map(t=>t.value)}#o(){let t=g(this.prompt_cache,"commit_footer");return t?{initial_values:this.#s(t),message:Z(f("Commit footers"))}:{initial_values:this.config.commit_footer.initial_value.filter(o=>this.#t.includes(o)),message:Z(w("Select optional footers"))}}#s(t){return t.split(",").map(e=>e.trim()).filter(e=>this.#t.includes(e))}#r(t){return{includes_breaking_change:t.includes("breaking-change"),includes_deprecated:t.includes("deprecated"),includes_closes:t.includes("closes"),includes_custom:t.includes("custom"),includes_trailer:t.includes("trailer")}}async#n(t){let e={breaking_title:"",breaking_body:"",deprecated_title:"",deprecated_body:"",custom_footer:""};return t.includes_breaking_change&&(e.breaking_title=await this.#c("Breaking changes: Write a short title / summary"),e.breaking_body=await this.#a(w("Breaking Changes: Write a description & migration instructions"))),t.includes_deprecated&&(e.deprecated_title=await this.#c("Deprecated: Write a short title / summary"),e.deprecated_body=await this.#a(w("Deprecated: Write a description"))),t.includes_custom&&(e.custom_footer=await this.#a("Write a custom footer")),e}async#c(t){let e=await $.text({message:t,placeholder:"",validate:o=>{if(!o)return"Please enter a title / summary"}});return $.isCancel(e)&&process.exit(0),e??""}async#a(t){let e=await $.text({message:t,placeholder:""});return $.isCancel(e)&&process.exit(0),e??""}#m(t,e,o){d(this.prompt_cache,"commit_footer",t.join(",")),this.commit_state.breaking_title=o.breaking_title,this.commit_state.breaking_body=o.breaking_body,this.commit_state.deprecates_title=o.deprecated_title,this.commit_state.deprecates_body=o.deprecated_body,this.commit_state.custom_footer=o.custom_footer,this.commit_state.closes=e.includes_closes?"Closes:":"",e.includes_trailer||(this.commit_state.trailer="")}};import*as b from"@clack/prompts";import{execSync as yt}from"child_process";import u from"picocolors";function tt({commit_state:i,config:t,colorize:e=!1,escape_quotes:o=!1,include_trailer:s=!1}){let r="";if(i.type&&(r+=e?u.blue(i.type):i.type),i.scope){let m=e?u.cyan(i.scope):i.scope;r+=`(${m})`}let a=i.ticket,l=t.check_ticket.surround;if(i.ticket&&l){let m=l.charAt(0),h=l.charAt(1);a=`${m}${i.ticket}${h}`}let x=t.check_ticket.title_position==="beginning";a&&t.check_ticket.add_to_title&&x&&(r=`${e?u.magenta(a):a} ${r}`);let S=t.check_ticket.title_position==="before-colon";if(a&&t.check_ticket.add_to_title&&S){let m=i.scope||i.type&&!t.check_ticket.surround?" ":"";r+=e?u.magenta(m+a):m+a}i.breaking_title&&t.breaking_change.add_exclamation_to_title&&(r+=e?u.red("!"):"!"),(i.scope||i.type||a&&S)&&(r+=": ");let y=t.check_ticket.title_position==="start",A=t.check_ticket.title_position==="end";if(a&&t.check_ticket.add_to_title&&y&&(r+=e?u.magenta(a)+" ":a+" "),i.title&&(r+=e?u.reset(i.title):i.title),a&&t.check_ticket.add_to_title&&A&&(r+=" "+(e?u.magenta(a):a)),i.body){let h=i.body.split("\\n").map(O=>e?u.reset(O.trim()):O.trim()).join(`
2
+ import{a as ft,b as ht,d as bt,e as N,f as j,g as D,h as f,i as I,j as S,k as et,l as yt,m as it}from"./chunk-43H72S6V.js";import{a as ct,c as mt,f as n,i as lt,k as pt,l as _t,m as ut,o as T,p as gt,q as dt,r as g,s as d}from"./chunk-B7AGSPP3.js";import{chdir as Kt}from"process";import*as z from"@clack/prompts";import{ValiError as Ht,parse as Ot}from"valibot";import Ut from"configstore";import*as V from"@clack/prompts";var p=class{constructor(t,e,o){this.config=t;this.commit_state=e;this.prompt_cache=o}};var L=class extends p{async run(){if(this.#i){let{initial_value:t,message:e}=this.#e,s=await(this.config.commit_type.autocomplete?V.autocomplete:V.select)({message:e,initialValue:t,maxItems:this.#s,options:this.#t});V.isCancel(s)&&process.exit(0),this.#r(s)}}get#i(){return this.config.commit_type.enable}get#e(){let t=g(this.prompt_cache,"commit_type");if(t)return{initial_value:t,message:f("Commit type")};if(this.config.commit_type.infer_type_from_branch){let e=N(this.#t,n.git_args);if(e)return{message:I("Commit type"),initial_value:e}}return{initial_value:this.config.commit_type.initial_value,message:"Select a commit type"}}get#t(){return this.config.commit_type.options}get#o(){return this.#t.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??"",trailer:e.trailer??""}}),{})}get#s(){return this.config.commit_type.max_items}#r(t){d(this.prompt_cache,"commit_type",t);let e=this.#o;this.commit_state.trailer=e[t].trailer,this.commit_state.type=this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="Start"?`${e[t].emoji} ${t}`.trim():t}};import*as k from"@clack/prompts";var G=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),s=await(this.config.commit_scope.autocomplete?k.autocomplete:k.select)({message:e,initialValue:t,maxItems:this.#t,options:this.#o});k.isCancel(s)&&process.exit(0),await this.#r(s)}get#i(){return this.config.commit_scope.enable}#e(){let t=g(this.prompt_cache,"commit_scope");if(t)return{initial_value:t,message:f("Commit scope")};if(this.config.commit_scope.infer_scope_from_branch){let e=D(this.#o,n.git_args);if(e)return{initial_value:e,message:I("Commit scope")}}return{initial_value:this.config.commit_scope.initial_value,message:"Select a commit scope"}}get#t(){return this.config.commit_scope.max_items}get#o(){return this.config.commit_scope.options}get#s(){return this.config.commit_scope.custom_scope}async#r(t){d(this.prompt_cache,"commit_scope",t);let e=t;if(e===ct&&this.#s){let o=await k.text({message:"Write a custom scope",placeholder:""});k.isCancel(o)&&process.exit(0),e=o??""}this.commit_state.scope=e}};import*as B from"@clack/prompts";var M=class extends p{async run(){let{initial_value:t,message:e}=this.#o();if(this.commit_state.ticket=t,this.#e){let o=await B.text({message:e,placeholder:"",initialValue:t});B.isCancel(o)&&process.exit(0),d(this.prompt_cache,"commit_ticket",o),this.commit_state.ticket=o??""}this.#t&&this.commit_state.ticket&&!this.commit_state.ticket.startsWith("#")&&(this.commit_state.ticket="#"+this.commit_state.ticket)}get#i(){return this.config.check_ticket.infer_ticket}get#e(){return this.config.check_ticket.confirm_ticket}get#t(){return this.config.check_ticket.prepend_hashtag==="Always"}#o(){let t=g(this.prompt_cache,"commit_ticket");if(t)return{initial_value:t,message:f("Ticket / issue")};if(this.#i){let e=j({append_hashtag:this.config.check_ticket.append_hashtag,prepend_hashtag:this.config.check_ticket.prepend_hashtag},n.git_args);if(e)return{initial_value:e,message:I("Ticket / issue")}}return{initial_value:this.commit_state.ticket,message:S("Add ticket / issue")}}};import*as q from"@clack/prompts";var W=class extends p{async run(){let{initial_value:t,message:e}=this.#i(),o=await q.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#e(s)});q.isCancel(o)&&process.exit(0),this.#n(o??"")}#i(){let t=g(this.prompt_cache,"commit_title");return t?{initial_value:t,message:f("Commit title")}:{initial_value:this.commit_state.title,message:"Write a brief title describing the commit"}}#e(t){if(!t)return"Please enter a title";if(this.#o(t)>this.#t)return`Exceeded max length. Title max [${this.#t}]`}get#t(){return this.config.commit_title.max_size}#o(t){return ft({type:this.commit_state.type,scope:this.commit_state.scope,ticket:this.commit_state.ticket,title:t},{include_ticket:this.config.check_ticket.add_to_title})}get#s(){return this.config.commit_type.options.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??""}}),{})}#r(t){return this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="After-Colon"?`${this.#s[this.commit_state.type]?.emoji??""} ${t}`.trim():t}#n(t){d(this.prompt_cache,"commit_title",t),this.commit_state.title=dt(this.#r(t))}};import*as H from"@clack/prompts";var K=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),o=await H.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#t(s)});H.isCancel(o)&&process.exit(0),this.#o(o??"")}get#i(){return this.config.commit_body.enable}#e(){let t=g(this.prompt_cache,"commit_body");return t?{initial_value:t,message:f("Commit body")}:{initial_value:"",message:S("Write a detailed description of the changes")}}#t(t){if(this.config.commit_body.required&&!t)return"Please enter a description"}#o(t){d(this.prompt_cache,"commit_body",t),this.commit_state.body=t}};import*as $ from"@clack/prompts";var U=class extends p{async run(){if(!this.#i)return;let{initial_values:t,message:e}=this.#o(),o=await $.multiselect({message:e,initialValues:t,options:this.#e,required:!1});$.isCancel(o)&&process.exit(0);let s=this.#r(o),r=await this.#n(s);this.#m(o,s,r)}get#i(){return this.config.commit_footer.enable}get#e(){let t=new Set(this.config.commit_footer.options);return lt.filter(e=>t.has(e.value))}get#t(){return this.#e.map(t=>t.value)}#o(){let t=g(this.prompt_cache,"commit_footer");return t?{initial_values:this.#s(t),message:et(f("Commit footers"))}:{initial_values:this.config.commit_footer.initial_value.filter(o=>this.#t.includes(o)),message:et(S("Select optional footers"))}}#s(t){return t.split(",").map(e=>e.trim()).filter(e=>this.#t.includes(e))}#r(t){return{includes_breaking_change:t.includes("breaking-change"),includes_deprecated:t.includes("deprecated"),includes_closes:t.includes("closes"),includes_custom:t.includes("custom"),includes_trailer:t.includes("trailer")}}async#n(t){let e={breaking_title:"",breaking_body:"",deprecated_title:"",deprecated_body:"",custom_footer:""};return t.includes_breaking_change&&(e.breaking_title=await this.#c("Breaking changes: Write a short title / summary"),e.breaking_body=await this.#a(S("Breaking Changes: Write a description & migration instructions"))),t.includes_deprecated&&(e.deprecated_title=await this.#c("Deprecated: Write a short title / summary"),e.deprecated_body=await this.#a(S("Deprecated: Write a description"))),t.includes_custom&&(e.custom_footer=await this.#a("Write a custom footer")),e}async#c(t){let e=await $.text({message:t,placeholder:"",validate:o=>{if(!o)return"Please enter a title / summary"}});return $.isCancel(e)&&process.exit(0),e??""}async#a(t){let e=await $.text({message:t,placeholder:""});return $.isCancel(e)&&process.exit(0),e??""}#m(t,e,o){d(this.prompt_cache,"commit_footer",t.join(",")),this.commit_state.breaking_title=o.breaking_title,this.commit_state.breaking_body=o.breaking_body,this.commit_state.deprecates_title=o.deprecated_title,this.commit_state.deprecates_body=o.deprecated_body,this.commit_state.custom_footer=o.custom_footer,this.commit_state.closes=e.includes_closes?"Closes:":"",e.includes_trailer||(this.commit_state.trailer="")}};import*as h from"@clack/prompts";import{execSync as Ct}from"child_process";import u from"picocolors";function ot({commit_state:i,config:t,colorize:e=!1,escape_quotes:o=!1,include_trailer:s=!1}){let r="";if(i.type&&(r+=e?u.blue(i.type):i.type),i.scope){let c=e?u.cyan(i.scope):i.scope;r+=`(${c})`}let a=i.ticket,l=t.check_ticket.surround;if(i.ticket&&l){let c=l.charAt(0),b=l.charAt(1);a=`${c}${i.ticket}${b}`}let C=t.check_ticket.title_position==="beginning";a&&t.check_ticket.add_to_title&&C&&(r=`${e?u.magenta(a):a} ${r}`);let x=t.check_ticket.title_position==="before-colon";if(a&&t.check_ticket.add_to_title&&x){let c=i.scope||i.type&&!t.check_ticket.surround?" ":"";r+=e?u.magenta(c+a):c+a}i.breaking_title&&t.breaking_change.add_exclamation_to_title&&(r+=e?u.red("!"):"!"),(i.scope||i.type||a&&x)&&(r+=": ");let y=t.check_ticket.title_position==="start",A=t.check_ticket.title_position==="end";if(a&&t.check_ticket.add_to_title&&y&&(r+=e?u.magenta(a)+" ":a+" "),i.title&&(r+=e?u.reset(i.title):i.title),a&&t.check_ticket.add_to_title&&A&&(r+=" "+(e?u.magenta(a):a)),i.body){let c=i.body;t.commit_body.split_by_period&&(c=c.replace(/\.\s+/g,`.
3
+ `));let O=c.split("\\n").map(F=>e?u.reset(F.trim()):F.trim()).join(`
4
4
  `);r+=`
5
5
 
6
- ${h}`}if(i.breaking_title){let m=e?u.red(`BREAKING CHANGE: ${i.breaking_title}`):`BREAKING CHANGE: ${i.breaking_title}`;r+=`
6
+ ${O}`}if(i.breaking_title){let c=e?u.red(`BREAKING CHANGE: ${i.breaking_title}`):`BREAKING CHANGE: ${i.breaking_title}`;r+=`
7
7
 
8
- ${m}`}if(i.breaking_body){let m=e?u.red(i.breaking_body):i.breaking_body;r+=`
8
+ ${c}`}if(i.breaking_body){let c=e?u.red(i.breaking_body):i.breaking_body;r+=`
9
9
 
10
- ${m}`}if(i.deprecates_title){let m=e?u.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
10
+ ${c}`}if(i.deprecates_title){let c=e?u.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
11
11
 
12
- ${m}`}if(i.deprecates_body){let m=e?u.yellow(i.deprecates_body):i.deprecates_body;r+=`
12
+ ${c}`}if(i.deprecates_body){let c=e?u.yellow(i.deprecates_body):i.deprecates_body;r+=`
13
13
 
14
- ${m}`}if(i.custom_footer){let h=i.custom_footer.split("\\n").map(O=>e?u.reset(O.trim()):O.trim()).join(`
14
+ ${c}`}if(i.custom_footer){let b=i.custom_footer.split("\\n").map(O=>e?u.reset(O.trim()):O.trim()).join(`
15
15
  `);r+=`
16
16
 
17
- ${h}`}return i.closes&&i.ticket&&(r+=e?`
17
+ ${b}`}return i.closes&&i.ticket&&(r+=e?`
18
18
 
19
19
  ${u.reset(i.closes)} ${u.magenta(i.ticket)}`:`
20
20
 
@@ -22,15 +22,15 @@ ${i.closes} ${i.ticket}`),s&&i.trailer&&(r+=e?`
22
22
 
23
23
  ${u.dim(i.trailer)}`:`
24
24
 
25
- ${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}var F=class extends p{async run(){this.#i&&(yt(`${this.#n} --edit`,this.#o),process.exit(0)),this.#e&&b.note(tt({commit_state:this.commit_state,config:this.config,colorize:!0,escape_quotes:!1,include_trailer:!0}),"Commit Preview"),await this.#a()||(b.log.info("Exiting without commit"),process.exit(0));try{b.log.info(n.dry_run?z("Committing changes..."):"Committing changes..."),yt(this.#n,n.dry_run?this.#s:this.#o)}catch(e){b.log.error("Something went wrong when committing: "+e);return}this.#m()}get#i(){return n.interactive&&this.config.confirm_with_editor}get#e(){return this.config.print_commit_output}get#t(){return this.config.confirm_commit}get#o(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"inherit"}:{stdio:"inherit"}}get#s(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"pipe"}:{stdio:"pipe"}}get#r(){return this.commit_state.trailer?`--trailer="${this.commit_state.trailer}"`:""}get#n(){return`git ${n.git_args} commit -m "${tt({commit_state:this.commit_state,config:this.config,colorize:!1,escape_quotes:!0,include_trailer:!1})}" ${this.#r} ${this.#c}`.trim()}get#c(){return n.dry_run?"--dry-run --porcelain --untracked-files=no":""}async#a(){if(!n.interactive||!this.#t)return!0;let t=await b.confirm({message:n.dry_run?z("Confirm Commit?"):"Confirm Commit?"});return b.isCancel(t)&&process.exit(0),t}#m(){b.log.success("Commit Complete");let t=this.prompt_cache.get("username");this.prompt_cache.clear(),t&&this.prompt_cache.set("username",t)}};import*as C from"@clack/prompts";import E from"picocolors";import{execSync as kt}from"child_process";import*as U from"@clack/prompts";import et from"picocolors";var vt=["M","T","R","D","A","C"];function it(){let i="";try{i=kt(`git ${n.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(s){return U.log.error(et.red("Failed to git status"+s)),{index:[],work_tree:[]}}let t=i.split(`
26
- `),e=[],o=[];return t.forEach(s=>{let r=s.trimEnd();if(!r)return;let a=r.substring(2).trim(),l=r.charAt(0).trim(),x=r.charAt(1).trim();(l==="?"||x==="?")&&e.push(a),vt.includes(l)&&o.push(a),vt.includes(x)&&e.push(a)}),{index:o,work_tree:e}}function $t(i){let t=i.join(" ");if(t)try{kt(`git ${n.git_args} add ${t}`,{stdio:"pipe"}).toString(),U.log.success(et.green("Changes successfully staged"))}catch{U.log.error(et.red("Failed to stage changes"))}}import{styleText as c}from"node:util";import{AutocompletePrompt as Ft}from"@clack/core";import{S_BAR as P,S_BAR_END as Pt,S_CHECKBOX_INACTIVE as Ct,S_CHECKBOX_SELECTED as Et,limitOptions as Rt,settings as Tt,symbol as Nt}from"@clack/prompts";function jt(i,t){if(!i)return!0;let e=(t.label??String(t.value??"")).toLowerCase(),o=(t.hint??"").toLowerCase(),s=String(t.value).toLowerCase(),r=i.toLowerCase();return e.includes(r)||o.includes(r)||s.includes(r)}function Dt(i,t){return i===""||t.ctrl===!0&&t.name==="a"}var ot=class extends Ft{constructor(e){super({options:e.options,multiple:!0,filter:e.filter??((o,s)=>jt(o,s)),validate:o=>e.required&&(!Array.isArray(o)||o.length===0)?"Please select at least one item":e.validate?.(o),initialValue:e.initialValues,signal:e.signal,input:e.input,output:e.output,render(){let o=e.withGuide??Tt.withGuide,s=`${o?`${c("gray",P)}
27
- `:""}${Nt(this.state)} ${e.message}
28
- `,r=this.userInput,a=this.userInputWithCursor,l=this.options,x=this.filteredOptions.length!==l.length?c("dim",` (${this.filteredOptions.length} match${this.filteredOptions.length===1?"":"es"})`):"";switch(this.state){case"submit":return`${s}${o?`${c("gray",P)} `:""}${c("dim",`${this.selectedValues.length} items selected`)}`;case"cancel":return`${s}${o?`${c("gray",P)} `:""}${c(["strikethrough","dim"],r)}`;default:{let S=this.state==="error"?"yellow":"cyan",y=o?`${c(S,P)} `:"",A=o?c(S,Pt):"",m=[`${c("dim","\u2191/\u2193")} to navigate`,`${c("dim","Space/Tab:")} select`,`${c("dim","Ctrl+a:")} select visible`,`${c("dim","Enter:")} confirm`,`${c("dim","Type:")} to search`],h=this.filteredOptions.length===0&&r?[`${y}${c("yellow","No matches found")}`]:[],O=this.state==="error"?[`${y}${c("yellow",this.error)}`]:[],st=[...`${s}${o?c(S,P):""}`.split(`
29
- `),`${y}${c("dim","Search:")} ${a}${x}`,...h,...O],rt=[`${y}${m.join(" \u2022 ")}`,A],Ot=Rt({cursor:this.cursor,options:this.filteredOptions,style:(v,It)=>{let Vt=this.selectedValues.includes(v.value),Q=v.label??String(v.value??""),At=v.hint&&this.focusedValue!==void 0&&v.value===this.focusedValue?c("dim",` (${v.hint})`):"",nt=Vt?c("green",Et):c("dim",Ct);return v.disabled?`${c("gray",Ct)} ${c(["strikethrough","gray"],Q)}`:It?`${nt} ${Q}${At}`:`${nt} ${c("dim",Q)}`},maxItems:e.maxItems,output:e.output,rowPadding:st.length+rt.length});return[...st,...Ot.map(v=>`${y}${v}`),...rt].join(`
30
- `)}}}});this.promptOptions=e;this.on("key",(o,s)=>{if(s.name==="space"&&!this.isNavigating&&this.focusedValue!==void 0){this.toggleSelected(this.focusedValue),this.#e();return}Dt(o,s)&&(this.#i(),this.isNavigating=!0,this.#e())})}_isActionKey(e,o){return super._isActionKey(e,o)||this.multiple&&o.name==="space"&&e!==void 0&&e!==""}#i(){let e=this.filteredOptions.filter(s=>!s.disabled).map(s=>s.value);if(!e.length)return;let o=e.every(s=>this.selectedValues.includes(s));this.selectedValues=o?this.selectedValues.filter(s=>!e.includes(s)):[...this.selectedValues,...e.filter(s=>!this.selectedValues.includes(s))]}#e(){let e=this.rl;e?.write("",{ctrl:!0,name:"e"}),this._cursor=e?.cursor??this.userInput.length}};function xt(i){return new ot(i).prompt()}var X=class extends p{async run(){if(!this.#i)return;let t=it();if(this.#e(t),t.work_tree.length){let e=await this.#o(t.work_tree);e.length&&$t(e)}this.#s()}get#i(){return this.config.check_status}#e(t){C.log.step(E.black(E.bgGreen(" Checking Git Status ")));let e=this.#t(t.index,E.green);if(C.log.success(`Changes to be committed:
31
- `+e),!t.work_tree.length)return;let o=this.#t(t.work_tree,E.red);C.log.error(`Changes not staged for commit:
32
- `+o)}#t(t,e){return t.reduce((o,s,r)=>e(o+s+ut(t,r)),"")}async#o(t){let e=this.config.check_status_autocomplete?await xt({message:"Some files have not been staged, add them now?",options:t.map(o=>({value:o,label:o})),required:!1}):await C.multiselect({message:bt("Some files have not been staged, add them now?"),options:t.map(o=>({value:o,label:o})),required:!1});return C.isCancel(e)&&process.exit(0),e}#s(){it().index.length||(C.log.error(E.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}};import{execSync as Lt}from"child_process";import _ from"picocolors";var Gt={"better-branch":"Create a branch or worktree from a guided prompt flow.","better-commits-init":"Create a .better-commits.jsonc config in this repository."},Mt={"--no-interactive":"Run without tui prompts.","--dry-run":"Print the commit command without creating a commit.","--help":"Show help information and exit."},Bt={"--type":"Set commit type (can be inferred from branch).","--scope":"Set commit scope (can be inferred from branch).","--title":"Set commit title/description.","--body":"Set commit body text.","--ticket":"Set ticket / issue (can be inferred from branch).","--closes":"Set closes footer (true/false).","--trailer":"Set trailer footer value.","--breaking-title":"Set breaking-change title footer.","--breaking-body":"Set breaking-change body footer.","--deprecates-title":"Set deprecates footer title text.","--deprecates-body":"Set deprecates footer body text.","--custom-footer":"Set a custom footer line."},Wt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function Y(i){let o=" ";return Object.entries(i).map(([s,r])=>{let a=Math.max(2,26-s.length);return`${o}${s}${" ".repeat(a)}${r}`}).join(`
33
- `)}function St(i,t){let e=R(),o="(none)";try{o=Lt(`git ${n.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let s=T(i.commit_type.options,n.git_args)||"Unknown",r=i.check_ticket.infer_ticket?N({append_hashtag:i.check_ticket.append_hashtag,prepend_hashtag:i.check_ticket.prepend_hashtag},n.git_args)||"Unknown":"Infer Disabled",a=i.commit_scope.infer_scope_from_branch?j(i.commit_scope.options,n.git_args)||"Unknown":"Infer Disabled",l=i.commit_type.options.map(h=>h.value).join(", ").trim(),x=i.commit_scope.options.map(h=>h.value).join(", ").trim(),S=Y(Mt),y=Y(Wt),A=Y(Bt),m=Y(Gt);console.log(`
25
+ ${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}import{execSync as kt}from"child_process";import*as P from"@clack/prompts";import X from"picocolors";var vt=["M","T","R","D","A","C"];function st(){let i="";try{i=kt(`git ${n.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(s){return P.log.error(X.red("Failed to git status"+s)),{index:[],work_tree:[]}}let t=i.split(`
26
+ `),e=[],o=[];return t.forEach(s=>{let r=s.trimEnd();if(!r)return;let a=r.substring(2).trim(),l=r.charAt(0).trim(),C=r.charAt(1).trim();(l==="?"||C==="?")&&e.push(a),vt.includes(l)&&o.push(a),vt.includes(C)&&e.push(a)}),{index:o,work_tree:e}}function $t(i){let t=i.join(" ");if(t)try{kt(`git ${n.git_args} add ${t}`,{stdio:"pipe"}).toString(),P.log.success(X.green("Changes successfully staged"))}catch{P.log.error(X.red("Failed to stage changes"))}}function Y(){st().index.length||(P.log.error(X.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}var E=class extends p{async run(){n.interactive||Y(),this.#i&&(Ct(`${this.#n} --edit`,this.#o),process.exit(0)),this.#e&&h.note(ot({commit_state:this.commit_state,config:this.config,colorize:!0,escape_quotes:!1,include_trailer:!0}),"Commit Preview",{format:e=>e}),await this.#a()||(h.log.info("Exiting without commit"),process.exit(0));try{h.log.info(n.dry_run?it("Committing changes..."):"Committing changes..."),Ct(this.#n,n.dry_run?this.#s:this.#o)}catch(e){h.log.error("Something went wrong when committing: "+e);return}this.#m()}get#i(){return n.interactive&&this.config.confirm_with_editor}get#e(){return this.config.print_commit_output}get#t(){return this.config.confirm_commit}get#o(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"inherit"}:{stdio:"inherit"}}get#s(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"pipe"}:{stdio:"pipe"}}get#r(){return this.commit_state.trailer?`--trailer="${this.commit_state.trailer}"`:""}get#n(){return`git ${n.git_args} commit -m "${ot({commit_state:this.commit_state,config:this.config,colorize:!1,escape_quotes:!0,include_trailer:!1})}" ${this.#r} ${this.#c}`.trim()}get#c(){return n.dry_run?"--dry-run --porcelain --untracked-files=no":""}async#a(){if(!n.interactive||!this.#t)return!0;let t=await h.confirm({message:n.dry_run?it("Confirm Commit?"):"Confirm Commit?"});return h.isCancel(t)&&process.exit(0),t}#m(){h.log.success("Commit Complete");let t=this.prompt_cache.get("username");this.prompt_cache.clear(),t&&this.prompt_cache.set("username",t)}};import*as w from"@clack/prompts";import J from"picocolors";import{styleText as m}from"node:util";import{AutocompletePrompt as Pt}from"@clack/core";import{S_BAR as R,S_BAR_END as Et,S_CHECKBOX_INACTIVE as xt,S_CHECKBOX_SELECTED as Rt,limitOptions as Tt,settings as Nt,symbol as jt}from"@clack/prompts";function Dt(i,t){if(!i)return!0;let e=(t.label??String(t.value??"")).toLowerCase(),o=(t.hint??"").toLowerCase(),s=String(t.value).toLowerCase(),r=i.toLowerCase();return e.includes(r)||o.includes(r)||s.includes(r)}function Lt(i,t){return i===""||t.ctrl===!0&&t.name==="a"}var rt=class extends Pt{constructor(e){super({options:e.options,multiple:!0,filter:e.filter??((o,s)=>Dt(o,s)),validate:o=>e.required&&(!Array.isArray(o)||o.length===0)?"Please select at least one item":e.validate?.(o),initialValue:e.initialValues,signal:e.signal,input:e.input,output:e.output,render(){let o=e.withGuide??Nt.withGuide,s=`${o?`${m("gray",R)}
27
+ `:""}${jt(this.state)} ${e.message}
28
+ `,r=this.userInput,a=this.userInputWithCursor,l=this.options,C=this.filteredOptions.length!==l.length?m("dim",` (${this.filteredOptions.length} match${this.filteredOptions.length===1?"":"es"})`):"";switch(this.state){case"submit":return`${s}${o?`${m("gray",R)} `:""}${m("dim",`${this.selectedValues.length} items selected`)}`;case"cancel":return`${s}${o?`${m("gray",R)} `:""}${m(["strikethrough","dim"],r)}`;default:{let x=this.state==="error"?"yellow":"cyan",y=o?`${m(x,R)} `:"",A=o?m(x,Et):"",c=[`${m("dim","\u2191/\u2193")} to navigate`,`${m("dim","Space/Tab:")} select`,`${m("dim","Ctrl+a:")} select visible`,`${m("dim","Enter:")} confirm`,`${m("dim","Type:")} to search`],b=this.filteredOptions.length===0&&r?[`${y}${m("yellow","No matches found")}`]:[],O=this.state==="error"?[`${y}${m("yellow",this.error)}`]:[],F=[...`${s}${o?m(x,R):""}`.split(`
29
+ `),`${y}${m("dim","Search:")} ${a}${C}`,...b,...O],nt=[`${y}${c.join(" \u2022 ")}`,A],It=Tt({cursor:this.cursor,options:this.filteredOptions,style:(v,Vt)=>{let At=this.selectedValues.includes(v.value),tt=v.label??String(v.value??""),Ft=v.hint&&this.focusedValue!==void 0&&v.value===this.focusedValue?m("dim",` (${v.hint})`):"",at=At?m("green",Rt):m("dim",xt);return v.disabled?`${m("gray",xt)} ${m(["strikethrough","gray"],tt)}`:Vt?`${at} ${tt}${Ft}`:`${at} ${m("dim",tt)}`},maxItems:e.maxItems,output:e.output,rowPadding:F.length+nt.length});return[...F,...It.map(v=>`${y}${v}`),...nt].join(`
30
+ `)}}}});this.promptOptions=e;this.on("key",(o,s)=>{if(s.name==="space"&&!this.isNavigating&&this.focusedValue!==void 0){this.toggleSelected(this.focusedValue),this.#e();return}Lt(o,s)&&(this.#i(),this.isNavigating=!0,this.#e())})}_isActionKey(e,o){return super._isActionKey(e,o)||this.multiple&&o.name==="space"&&e!==void 0&&e!==""}#i(){let e=this.filteredOptions.filter(s=>!s.disabled).map(s=>s.value);if(!e.length)return;let o=e.every(s=>this.selectedValues.includes(s));this.selectedValues=o?this.selectedValues.filter(s=>!e.includes(s)):[...this.selectedValues,...e.filter(s=>!this.selectedValues.includes(s))]}#e(){let e=this.rl;e?.write("",{ctrl:!0,name:"e"}),this._cursor=e?.cursor??this.userInput.length}};function St(i){return new rt(i).prompt()}var Q=class extends p{async run(){if(!this.#i)return;let t=st();if(this.#e(t),t.work_tree.length){let e=await this.#o(t.work_tree);e.length&&$t(e)}Y()}get#i(){return this.config.check_status}#e(t){w.log.step(J.black(J.bgGreen(" Checking Git Status ")));let e=this.#t(t.index,J.green);if(w.log.success(`Changes to be committed:
31
+ `+e),!t.work_tree.length)return;let o=this.#t(t.work_tree,J.red);w.log.error(`Changes not staged for commit:
32
+ `+o)}#t(t,e){return t.reduce((o,s,r)=>e(o+s+gt(t,r)),"")}async#o(t){let e=this.config.check_status_autocomplete?await St({message:"Some files have not been staged, add them now?",options:t.map(o=>({value:o,label:o})),required:!1}):await w.multiselect({message:yt("Some files have not been staged, add them now?"),options:t.map(o=>({value:o,label:o})),required:!1});return w.isCancel(e)&&process.exit(0),e}};import{execSync as Gt}from"child_process";import _ from"picocolors";var Mt={"better-branch":"Create a branch or worktree from a guided prompt flow.","better-commits-init":"Create a .better-commits.jsonc config in this repository."},Bt={"--no-interactive":"Run without tui prompts.","--dry-run":"Print the commit command without creating a commit.","--help":"Show help information and exit."},Wt={"--type":"Set commit type (can be inferred from branch).","--scope":"Set commit scope (can be inferred from branch).","--title":"Set commit title/description.","--body":"Set commit body text.","--ticket":"Set ticket / issue (can be inferred from branch).","--closes":"Set closes footer (true/false).","--trailer":"Set trailer footer value.","--breaking-title":"Set breaking-change title footer.","--breaking-body":"Set breaking-change body footer.","--deprecates-title":"Set deprecates footer title text.","--deprecates-body":"Set deprecates footer body text.","--custom-footer":"Set a custom footer line."},qt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function Z(i){let o=" ";return Object.entries(i).map(([s,r])=>{let a=Math.max(2,26-s.length);return`${o}${s}${" ".repeat(a)}${r}`}).join(`
33
+ `)}function wt(i,t){let e=T(),o="(none)";try{o=Gt(`git ${n.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let s=N(i.commit_type.options,n.git_args)||"Unknown",r=i.check_ticket.infer_ticket?j({append_hashtag:i.check_ticket.append_hashtag,prepend_hashtag:i.check_ticket.prepend_hashtag},n.git_args)||"Unknown":"Infer Disabled",a=i.commit_scope.infer_scope_from_branch?D(i.commit_scope.options,n.git_args)||"Unknown":"Infer Disabled",l=i.commit_type.options.map(b=>b.value).join(", ").trim(),C=i.commit_scope.options.map(b=>b.value).join(", ").trim(),x=Z(Bt),y=Z(qt),A=Z(Wt),c=Z(Mt);console.log(`
34
34
  ${_.green("\uF489 better-commits")} ${_.gray("v"+e)}
35
35
 
36
36
  ${_.gray("BRANCH")}
@@ -44,10 +44,10 @@ ${_.gray("Types")}
44
44
  ${l}
45
45
 
46
46
  ${_.gray("Scopes")}
47
- ${x}
47
+ ${C}
48
48
 
49
49
  ${_.gray("CLI FLAGS")}
50
- ${S}
50
+ ${x}
51
51
 
52
52
  ${_.gray("Commit Flags")}
53
53
  ${A}
@@ -56,6 +56,6 @@ ${_.gray("Git Flags (Advanced)")}
56
56
  ${y}
57
57
 
58
58
  ${_.gray("ADDITIONAL COMMANDS")}
59
- ${m}
59
+ ${c}
60
60
 
61
- `)}var Ut=[X,D,L,G,B,q,H,F],{config:Xt,config_source:Yt}=pt();Jt(Xt,Yt);async function Jt(i,t){if(qt(_t()),n.version){let l=R();J.log.step("Better Commits v"+l);return}if(n.help){St(i,t);return}let e=ht(i),o={...n.commit_state,type:(n.commit_state.type||e?.type)??"",scope:(n.commit_state.scope||e?.scope)??"",ticket:(n.commit_state.ticket||e?.ticket)??""},s=wt(ct,o);if(!n.interactive)try{wt(ft(i),s)}catch(l){l instanceof Kt?J.log.error(`Invalid commit input: ${l.message}`):J.log.error(`Failed to validate commit input: ${l}`),process.exit(0)}let r=i.cache_last_value?new Ht("better-commits"):lt,a=n.interactive?Ut:[F];for(let l of a)await new l(i,s,r).run()}export{Jt as main};
61
+ `)}var Xt=[Q,L,G,M,W,K,U,E],{config:Yt,config_source:Jt}=_t();Qt(Yt,Jt);async function Qt(i,t){if(Kt(ut()),n.version){let l=T();z.log.step("Better Commits v"+l);return}if(n.help){wt(i,t);return}let e=bt(i),o={...n.commit_state,type:(n.commit_state.type||e?.type)??"",scope:(n.commit_state.scope||e?.scope)??"",ticket:(n.commit_state.ticket||e?.ticket)??""},s=Ot(mt,o);if(!n.interactive)try{Ot(ht(i),s)}catch(l){l instanceof Ht?z.log.error(`Invalid commit input: ${l.message}`):z.log.error(`Failed to validate commit input: ${l}`),process.exit(0)}let r=i.cache_last_value?new Ut("better-commits"):pt,a=n.interactive?Xt:[E];for(let l of a)await new l(i,s,r).run()}export{Qt as main};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-commits",
3
3
  "private": false,
4
- "version": "1.23.0",
4
+ "version": "1.23.2",
5
5
  "description": "A CLI for creating better commits following the conventional commits specification",
6
6
  "author": "Erik Verduin (https://github.com/everduin94)",
7
7
  "type": "module",
package/readme.md CHANGED
@@ -12,7 +12,7 @@
12
12
  A CLI for writing better commits, following the conventional commits specification.
13
13
  </p>
14
14
 
15
- <https://github.com/Everduin94/better-commits/assets/14320878/8fb15d46-17c4-4e5d-80d9-79abe0a2a00a>
15
+ <video src="https://github.com/Everduin94/better-commits/assets/14320878/8fb15d46-17c4-4e5d-80d9-79abe0a2a00a"></video>
16
16
 
17
17
  ## ✨ Features
18
18
 
@@ -0,0 +1,64 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const mocked = vi.hoisted(() => ({
4
+ error: vi.fn(),
5
+ execSync: vi.fn(),
6
+ }));
7
+
8
+ vi.mock("child_process", () => ({
9
+ execSync: mocked.execSync,
10
+ }));
11
+
12
+ vi.mock("@clack/prompts", () => ({
13
+ log: {
14
+ error: mocked.error,
15
+ },
16
+ }));
17
+
18
+ vi.mock("picocolors", () => ({
19
+ default: {
20
+ red: (value: string) => value,
21
+ },
22
+ }));
23
+
24
+ vi.mock("./args", () => ({
25
+ flags: {
26
+ git_args: "",
27
+ },
28
+ }));
29
+
30
+ describe("ensure_staged_changes", () => {
31
+ beforeEach(() => {
32
+ mocked.error.mockReset();
33
+ mocked.execSync.mockReset();
34
+ });
35
+
36
+ it("does not exit when staged changes exist", async () => {
37
+ const { ensure_staged_changes } = await import("./git");
38
+ const exit = vi.spyOn(process, "exit").mockImplementation(() => {
39
+ throw new Error("process.exit");
40
+ });
41
+
42
+ mocked.execSync.mockReturnValue(Buffer.from("A src/git.ts\n"));
43
+
44
+ ensure_staged_changes();
45
+
46
+ expect(exit).not.toHaveBeenCalled();
47
+ expect(mocked.error).not.toHaveBeenCalled();
48
+ });
49
+
50
+ it("exits early when no staged changes exist", async () => {
51
+ const { ensure_staged_changes } = await import("./git");
52
+ const exit = vi.spyOn(process, "exit").mockImplementation(() => {
53
+ throw new Error("process.exit");
54
+ });
55
+
56
+ mocked.execSync.mockReturnValue(Buffer.from(" M src/git.ts\n"));
57
+
58
+ expect(() => ensure_staged_changes()).toThrow("process.exit");
59
+ expect(mocked.error).toHaveBeenCalledWith(
60
+ 'no changes added to commit (use "git add" and/or "git commit -a")',
61
+ );
62
+ expect(exit).toHaveBeenCalledWith(0);
63
+ });
64
+ });
package/src/git.ts CHANGED
@@ -58,3 +58,15 @@ export function git_add(files: string[]) {
58
58
  }
59
59
  }
60
60
  }
61
+
62
+ export function ensure_staged_changes(): void {
63
+ const updated_status = git_status();
64
+ if (updated_status.index.length) return;
65
+
66
+ p.log.error(
67
+ color.red(
68
+ 'no changes added to commit (use "git add" and/or "git commit -a")',
69
+ ),
70
+ );
71
+ process.exit(0);
72
+ }
@@ -0,0 +1,89 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { parse } from "valibot";
3
+ import { BranchState, Config } from "../valibot-state";
4
+
5
+ const mocked = vi.hoisted(() => ({
6
+ dry_run: true,
7
+ execSync: vi.fn(),
8
+ info: vi.fn(),
9
+ }));
10
+
11
+ vi.mock("child_process", () => ({
12
+ execSync: mocked.execSync,
13
+ }));
14
+
15
+ vi.mock("@clack/prompts", () => ({
16
+ log: {
17
+ info: mocked.info,
18
+ warning: vi.fn(),
19
+ error: vi.fn(),
20
+ },
21
+ }));
22
+
23
+ vi.mock("picocolors", () => ({
24
+ default: {
25
+ bgGreen: (value: string) => value,
26
+ bgMagenta: (value: string) => value,
27
+ black: (value: string) => value,
28
+ yellow: (value: string) => value,
29
+ },
30
+ }));
31
+
32
+ vi.mock("../branch-args", () => ({
33
+ branch_flags: {
34
+ git_args: "",
35
+ get dry_run() {
36
+ return mocked.dry_run;
37
+ },
38
+ },
39
+ }));
40
+
41
+ vi.mock("../utils", async () => {
42
+ const actual = await vi.importActual<typeof import("../utils")>("../utils");
43
+ return {
44
+ ...actual,
45
+ get_git_root: vi.fn(() => "/tmp/repo"),
46
+ };
47
+ });
48
+
49
+ describe("BranchConfirmPrompt", () => {
50
+ beforeEach(() => {
51
+ mocked.dry_run = true;
52
+ mocked.execSync.mockReset();
53
+ mocked.info.mockReset();
54
+ });
55
+
56
+ it("does not create a worktree during dry run", async () => {
57
+ const { BranchConfirmPrompt } = await import("./branch-confirm.prompt");
58
+ const config = parse(Config, {
59
+ worktrees: {
60
+ base_path: "../worktrees",
61
+ },
62
+ });
63
+ const branch_state = parse(BranchState, {
64
+ type: "feat",
65
+ scope: "cli",
66
+ ticket: "TAC-123",
67
+ description: "add-parser",
68
+ checkout: "worktree",
69
+ });
70
+
71
+ mocked.execSync.mockImplementation((command: string) => {
72
+ if (command.includes("show-ref")) throw new Error("branch missing");
73
+ return Buffer.from("");
74
+ });
75
+
76
+ await new BranchConfirmPrompt(config, branch_state, {} as never).run();
77
+
78
+ expect(mocked.execSync).toHaveBeenCalledTimes(1);
79
+ expect(mocked.execSync).toHaveBeenCalledWith(
80
+ "git show-ref feat/TAC-123-cli-add-parser",
81
+ {
82
+ encoding: "utf-8",
83
+ },
84
+ );
85
+ expect(mocked.info).toHaveBeenCalledWith(
86
+ "Dry run: git worktree add ../worktrees/repo-TAC-123-add-parser -b feat/TAC-123-cli-add-parser",
87
+ );
88
+ });
89
+ });
@@ -46,13 +46,16 @@ export class BranchConfirmPrompt extends BranchRunnable {
46
46
  const branch_flag = this.#verify_branch_name(branch_name);
47
47
 
48
48
  if (!this.#is_worktree) {
49
+ const command = `git ${branch_flags.git_args} checkout ${branch_flag} ${branch_name}`;
50
+ if (branch_flags.dry_run) {
51
+ this.#log_dry_run_command(command);
52
+ return;
53
+ }
54
+
49
55
  try {
50
- execSync(
51
- `git ${branch_flags.git_args} checkout ${branch_flag} ${branch_name}`,
52
- {
53
- stdio: "inherit",
54
- },
55
- );
56
+ execSync(command, {
57
+ stdio: "inherit",
58
+ });
56
59
  p.log.info(
57
60
  `Switched to a new branch '${color.bgGreen(
58
61
  " " + color.black(branch_name) + " ",
@@ -71,12 +74,15 @@ export class BranchConfirmPrompt extends BranchRunnable {
71
74
  this.config,
72
75
  get_git_root(branch_flags.git_args),
73
76
  );
74
- execSync(
75
- `git ${branch_flags.git_args} worktree add ${worktree_name} ${branch_flag} ${branch_name}`,
76
- {
77
- stdio: "inherit",
78
- },
79
- );
77
+ const command = `git ${branch_flags.git_args} worktree add ${worktree_name} ${branch_flag} ${branch_name}`;
78
+ if (branch_flags.dry_run) {
79
+ this.#log_dry_run_command(command);
80
+ return;
81
+ }
82
+
83
+ execSync(command, {
84
+ stdio: "inherit",
85
+ });
80
86
  p.log.info(
81
87
  `Created a new worktree ${color.bgGreen(
82
88
  " " + color.black(worktree_name) + " ",
@@ -103,6 +109,11 @@ export class BranchConfirmPrompt extends BranchRunnable {
103
109
 
104
110
  #run_commands(commands: string[], error_message: string): void {
105
111
  commands.forEach((command) => {
112
+ if (branch_flags.dry_run) {
113
+ this.#log_dry_run_command(command);
114
+ return;
115
+ }
116
+
106
117
  try {
107
118
  execSync(command, { stdio: "inherit" });
108
119
  } catch (err) {
@@ -112,6 +123,10 @@ export class BranchConfirmPrompt extends BranchRunnable {
112
123
  });
113
124
  }
114
125
 
126
+ #log_dry_run_command(command: string): void {
127
+ p.log.info(`Dry run: ${command}`);
128
+ }
129
+
115
130
  #verify_branch_name(branch_name: string): string {
116
131
  // TODO: There has to be a better way 🤦
117
132
  let branch_flag = "";
@@ -44,14 +44,8 @@ export class CommitBodyPrompt extends Runnable {
44
44
  }
45
45
  }
46
46
 
47
- #split_by_period(value: string): string {
48
- if (!this.config.commit_body.split_by_period) return value;
49
- const sentences = value.split(/\.\s+/).map((sentence) => sentence.trim());
50
- return sentences.join(".\n");
51
- }
52
-
53
47
  #run_post_effects(prompt_result: string): void {
54
48
  set_value_cache(this.prompt_cache, "commit_body", prompt_result);
55
- this.commit_state.body = this.#split_by_period(prompt_result);
49
+ this.commit_state.body = prompt_result;
56
50
  }
57
51
  }
@@ -4,9 +4,12 @@ import { flags } from "../args";
4
4
  import { Runnable } from "./runnable";
5
5
  import { dry_run_message } from "../utils/messages";
6
6
  import { build_commit_string } from "../utils/build-commit-string";
7
+ import { ensure_staged_changes } from "../git";
7
8
 
8
9
  export class CommitConfirmPrompt extends Runnable {
9
10
  async run(): Promise<void> {
11
+ if (!flags.interactive) ensure_staged_changes();
12
+
10
13
  if (this.#confirm_with_editor) {
11
14
  execSync(`${this.#commit_command} --edit`, this.#git_command_options);
12
15
  process.exit(0);
@@ -22,6 +25,7 @@ export class CommitConfirmPrompt extends Runnable {
22
25
  include_trailer: true,
23
26
  }),
24
27
  "Commit Preview",
28
+ { format: (line) => line },
25
29
  );
26
30
  }
27
31
 
@@ -2,7 +2,7 @@ import * as p from "@clack/prompts";
2
2
  import color from "picocolors";
3
3
  import { addNewLine } from "../utils";
4
4
  import { a_for_all_message } from "../utils/messages";
5
- import { git_add, git_status } from "../git";
5
+ import { ensure_staged_changes, git_add, git_status } from "../git";
6
6
  import { autocompleteMultiselect } from "./autocomplete-multiselect";
7
7
  import { Runnable } from "./runnable";
8
8
 
@@ -22,7 +22,7 @@ export class CommitStatusPrompt extends Runnable {
22
22
  }
23
23
  }
24
24
 
25
- this.#ensure_staged_changes();
25
+ ensure_staged_changes();
26
26
  }
27
27
 
28
28
  get #is_enabled(): boolean {
@@ -63,16 +63,4 @@ export class CommitStatusPrompt extends Runnable {
63
63
  if (p.isCancel(selected_for_staging)) process.exit(0);
64
64
  return selected_for_staging;
65
65
  }
66
-
67
- #ensure_staged_changes(): void {
68
- const updated_status = git_status();
69
- if (updated_status.index.length) return;
70
-
71
- p.log.error(
72
- color.red(
73
- 'no changes added to commit (use "git add" and/or "git commit -a")',
74
- ),
75
- );
76
- process.exit(0);
77
- }
78
66
  }
@@ -148,6 +148,26 @@ describe("build_commit_string", () => {
148
148
  expect(result).toBe("feat: add cli\n\nline 1\nline 2\n\nRefs: ABC-1");
149
149
  });
150
150
 
151
+ it("splits commit body sentences by period when enabled", () => {
152
+ const result = build_commit_string({
153
+ commit_state: make_state({
154
+ type: "feat",
155
+ title: "add cli",
156
+ body: "First sentence. Second sentence. Third sentence.",
157
+ }),
158
+ config: make_config({
159
+ commit_body: {
160
+ ...make_config().commit_body,
161
+ split_by_period: true,
162
+ },
163
+ }),
164
+ });
165
+
166
+ expect(result).toBe(
167
+ "feat: add cli\n\nFirst sentence.\nSecond sentence.\nThird sentence.",
168
+ );
169
+ });
170
+
151
171
  it("includes trailer only when include_trailer is true", () => {
152
172
  const state = make_state({
153
173
  type: "feat",
@@ -95,10 +95,15 @@ export function build_commit_string({
95
95
  }
96
96
 
97
97
  if (commit_state.body) {
98
- const temp = commit_state.body.split("\\n");
98
+ let body = commit_state.body;
99
+ if (config.commit_body.split_by_period) {
100
+ body = body.replace(/\.\s+/g, ".\n");
101
+ }
102
+ const temp = body.split("\\n");
99
103
  const res = temp
100
104
  .map((value) => (colorize ? color.reset(value.trim()) : value.trim()))
101
105
  .join("\n");
106
+
102
107
  commit_string += `\n\n${res}`;
103
108
  }
104
109