better-commits 1.21.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/branch.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #! /usr/bin/env node
2
- import{c as V,e as H,f as D,i as h}from"./chunk-EANV5ZZP.js";import{e as T,j as A,k as F,l as E,m as u,o as _,r as G,s as L}from"./chunk-2JVEMMKH.js";import at from"configstore";import{chdir as ct}from"process";import{ValiError as pt,parse as U}from"valibot";var a=class{constructor(t,r,n){this.config=t;this.branch_state=r;this.prompt_cache=n}};import*as l from"@clack/prompts";var f=class extends a{async run(){if(this.#e){let t=await l.select({message:this.#t,initialValue:this.#r,options:A});l.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 b from"@clack/prompts";var d=class extends a{async run(){if(!this.#t)return;let t=await b.text({message:this.#r,placeholder:"",initialValue:this.#n,validate:r=>this.#i(r)});b.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":h("Type your git username")}get#n(){return this.branch_state.user||G(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(),L(this.prompt_cache,"username",this.branch_state.user)}};import*as v from"@clack/prompts";var y=class extends a{async run(){if(!this.#t)return;let t=await v.select({message:this.#e,initialValue:this.#r,options:this.#n});v.isCancel(t)&&process.exit(0),this.#i(t)}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 w from"@clack/prompts";var k=class extends a{async run(){if(!this.#t)return;let t=await w.text({message:this.#r,placeholder:"",validate:r=>this.#n(r),initialValue:this.branch_state.ticket});w.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":h("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 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:r=>this.#n(r),initialValue:this.branch_state.version});C.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":h("Type version number")}#n(t){if(this.#e&&!t)return"Please enter a version"}#i(t){this.branch_state.version=t}};import*as I from"@clack/prompts";var $=class extends a{async run(){let t=await I.text({message:this.#t,placeholder:"",validate:r=>this.#r(r),initialValue:this.branch_state.description});I.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 S}from"child_process";import p from"picocolors";import{chdir as rt}from"process";import{parse as X}from"@bomb.sh/args";var q=["user","type","description","ticket","branch-version","checkout"],Y=["git-dir","work-tree"],Z=["interactive","dry-run","help","version"],P=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}},s=new P(tt(process.argv.slice(2)));function tt(e){let t=X(e,{alias:{h:"help",v:"version"},boolean:Z,string:[...q,...Y]}),r={};return q.forEach(n=>{let i=t[n];if(i){let o=n==="branch-version"?"version":n.replace("-","_");o==="checkout"?r[o]=i??"branch":r[o]=i}}),{help:t.help===!0,version:t.version===!0,git_args:et(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,branch_state:r}}function et(e,t){return`${e?`--git-dir=${e}`:""} ${t?`--work-tree=${t}`:""}`.trim()}function j(e,t){let r="";return t.branch_order.forEach(n=>{let i=`branch_${n}`;e[n]&&(r+=e[n]+t[i].separator)}),r.endsWith("-")||r.endsWith("/")||r.endsWith("_")?r.slice(0,-1).trim():r.trim()}function W(e,t,r){let n=r.split("/").pop()||"repo",i=t.worktrees.folder_template;i=i.replace("{{repo_name}}",n).replace("{{branch_description}}",e.description).replace("{{user}}",e.user||"").replace("{{type}}",e.type||"").replace("{{ticket}}",e.ticket||"").replace("{{version}}",e.version||""),i=i.replace(/\s/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"");let o=t.worktrees.base_path;return`${o}${o.endsWith("/")?"":"/"}${i}`}var g=class extends a{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 j(this.branch_state,this.config)}#i(){this.#s(this.#e,"Something went wrong when executing pre-commands: ")}#o(){let t=this.#n,r=this.#c(t);if(!this.#t){try{S(`git ${s.git_args} checkout ${r} ${t}`,{stdio:"inherit"}),m.log.info(`Switched to a new branch '${p.bgGreen(" "+p.black(t)+" ")}'`)}catch{process.exit(0)}return}try{let n=W(this.branch_state,this.config,u(s.git_args));S(`git ${s.git_args} worktree add ${n} ${r} ${t}`,{stdio:"inherit"}),m.log.info(`Created a new worktree ${p.bgGreen(" "+p.black(n)+" ")}, checked out branch ${p.bgGreen(" "+p.black(t)+" ")}`),m.log.info(p.bgMagenta(p.black(` cd ${n} `))+" to navigate to your new worktree"),rt(n)}catch{process.exit(0)}}#a(){this.#s(this.#r,"Something went wrong when executing post-commands: ")}#s(t,r){t.forEach(n=>{try{S(n,{stdio:"inherit"})}catch(i){m.log.error(r+i),process.exit(0)}})}#c(t){let r="";try{S(`git ${s.git_args} show-ref ${t}`,{encoding:"utf-8"}),m.log.warning(p.yellow(`${t} already exists! Checking out existing branch.`))}catch{r="-b"}return r}};import{execSync as nt}from"child_process";import c from"picocolors";var it={"--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."},ot={"--user":"Set branch username segment.","--type":"Set branch type (for example feat, fix, docs).","--description":"Set branch description segment.","--ticket":"Set branch ticket/issue segment.","--branch-version":"Set branch version segment.","--checkout":"Choose branch or worktree checkout mode."},st={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function N(e){let n=" ";return Object.entries(e).map(([i,o])=>{let B=Math.max(2,26-i.length);return`${n}${i}${" ".repeat(B)}${o}`}).join(`
3
- `)}function M(e,t){let r=_(),n="(none)";try{n=nt(`git ${s.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let i=H(e.commit_type.options,s.git_args)||"Unknown",o=e.check_ticket.infer_ticket?D({append_hashtag:e.check_ticket.append_hashtag,prepend_hashtag:e.check_ticket.prepend_hashtag},s.git_args)||"Unknown":"Infer Disabled",B=e.commit_type.options.map(R=>R.value).join(", ").trim(),z=e.commit_scope.options.map(R=>R.value).join(", ").trim(),J=N(it),K=N(st),Q=N(ot);console.log(`
4
- ${c.green("\uF489 better-branch")} ${c.gray("v"+r)}
2
+ import{c as V,e as H,f as D,i as h}from"./chunk-5EGZQSNM.js";import{e as T,j as A,k as F,l as E,m as _,o as f,r as G,s as L}from"./chunk-F4EBQBBK.js";import at from"configstore";import{chdir as ct}from"process";import{ValiError as pt,parse as U}from"valibot";var a=class{constructor(t,e,n){this.config=t;this.branch_state=e;this.prompt_cache=n}};import*as d from"@clack/prompts";var l=class extends a{async run(){if(this.#e){let t=await d.select({message:this.#t,initialValue:this.#r,options:A});d.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 y from"@clack/prompts";var b=class extends a{async run(){if(!this.#t)return;let t=await y.text({message:this.#r,placeholder:"",initialValue:this.#n,validate:e=>this.#i(e)});y.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":h("Type your git username")}get#n(){return this.branch_state.user||G(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(),L(this.prompt_cache,"username",this.branch_state.user)}};import*as m from"@clack/prompts";var v=class extends a{async run(){if(!this.#t)return;let e=await(this.config.branch_type.autocomplete?m.autocomplete:m.select)({message:this.#e,initialValue:this.#r,options:this.#n});m.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 w from"@clack/prompts";var k=class extends a{async run(){if(!this.#t)return;let t=await w.text({message:this.#r,placeholder:"",validate:e=>this.#n(e),initialValue:this.branch_state.ticket});w.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":h("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 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.version});C.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":h("Type version number")}#n(t){if(this.#e&&!t)return"Please enter a version"}#i(t){this.branch_state.version=t}};import*as I from"@clack/prompts";var $=class extends a{async run(){let t=await I.text({message:this.#t,placeholder:"",validate:e=>this.#r(e),initialValue:this.branch_state.description});I.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 g from"@clack/prompts";import{execSync as S}from"child_process";import p from"picocolors";import{chdir as rt}from"process";import{parse as X}from"@bomb.sh/args";var q=["user","type","description","ticket","branch-version","checkout"],Y=["git-dir","work-tree"],Z=["interactive","dry-run","help","version"],P=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}},s=new P(tt(process.argv.slice(2)));function tt(r){let t=X(r,{alias:{h:"help",v:"version"},boolean:Z,string:[...q,...Y]}),e={};return q.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:et(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,branch_state:e}}function et(r,t){return`${r?`--git-dir=${r}`:""} ${t?`--work-tree=${t}`:""}`.trim()}function j(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 W(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("{{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 u=class extends a{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 j(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{S(`git ${s.git_args} checkout ${e} ${t}`,{stdio:"inherit"}),g.log.info(`Switched to a new branch '${p.bgGreen(" "+p.black(t)+" ")}'`)}catch{process.exit(0)}return}try{let n=W(this.branch_state,this.config,_(s.git_args));S(`git ${s.git_args} worktree add ${n} ${e} ${t}`,{stdio:"inherit"}),g.log.info(`Created a new worktree ${p.bgGreen(" "+p.black(n)+" ")}, checked out branch ${p.bgGreen(" "+p.black(t)+" ")}`),g.log.info(p.bgMagenta(p.black(` cd ${n} `))+" to navigate to your new worktree"),rt(n)}catch{process.exit(0)}}#a(){this.#s(this.#r,"Something went wrong when executing post-commands: ")}#s(t,e){t.forEach(n=>{try{S(n,{stdio:"inherit"})}catch(i){g.log.error(e+i),process.exit(0)}})}#c(t){let e="";try{S(`git ${s.git_args} show-ref ${t}`,{encoding:"utf-8"}),g.log.warning(p.yellow(`${t} already exists! Checking out existing branch.`))}catch{e="-b"}return e}};import{execSync as nt}from"child_process";import c from"picocolors";var it={"--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."},ot={"--user":"Set branch username segment.","--type":"Set branch type (for example feat, fix, docs).","--description":"Set branch description segment.","--ticket":"Set branch ticket/issue segment.","--branch-version":"Set branch version segment.","--checkout":"Choose branch or worktree checkout mode."},st={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function N(r){let n=" ";return Object.entries(r).map(([i,o])=>{let B=Math.max(2,26-i.length);return`${n}${i}${" ".repeat(B)}${o}`}).join(`
3
+ `)}function M(r,t){let e=f(),n="(none)";try{n=nt(`git ${s.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let i=H(r.commit_type.options,s.git_args)||"Unknown",o=r.check_ticket.infer_ticket?D({append_hashtag:r.check_ticket.append_hashtag,prepend_hashtag:r.check_ticket.prepend_hashtag},s.git_args)||"Unknown":"Infer Disabled",B=r.commit_type.options.map(R=>R.value).join(", ").trim(),z=r.commit_scope.options.map(R=>R.value).join(", ").trim(),J=N(it),K=N(st),Q=N(ot);console.log(`
4
+ ${c.green("\uF489 better-branch")} ${c.gray("v"+e)}
5
5
 
6
6
  ${c.gray("BRANCH")}
7
7
  ${n}
@@ -25,4 +25,4 @@ ${Q}
25
25
  ${c.gray("Git Flags (Advanced)")}
26
26
  ${K}
27
27
 
28
- `)}import*as O from"@clack/prompts";var ht=[f,d,y,k,x,$,g],{config:mt,config_source:gt}=E(" better-branch ",s.git_args);ut(mt,gt);async function ut(e,t){if(ct(u(s.git_args)),s.version){let o=_();O.log.step("Better Commits v"+o);return}if(s.help){M(e,t);return}let r=U(T,s.branch_state);if(!s.interactive)try{U(V(e),r)}catch(o){o instanceof pt?O.log.error(`Invalid branch input: ${o.message}`):O.log.error(`Failed to validate branch input: ${o}`),process.exit(0)}let n=e.cache_last_value?new at("better-commits"):F,i=s.interactive?ht:[g];for(let o of i)await new o(e,r,n).run()}
28
+ `)}import*as O from"@clack/prompts";var ht=[l,b,v,k,x,$,u],{config:mt,config_source:gt}=E(" better-branch ",s.git_args);ut(mt,gt);async function ut(r,t){if(ct(_(s.git_args)),s.version){let o=f();O.log.step("Better Commits v"+o);return}if(s.help){M(r,t);return}let e=U(T,s.branch_state);if(!s.interactive)try{U(V(r),e)}catch(o){o instanceof pt?O.log.error(`Invalid branch input: ${o.message}`):O.log.error(`Failed to validate branch input: ${o}`),process.exit(0)}let n=r.cache_last_value?new at("better-commits"):F,i=s.interactive?ht:[u];for(let o of i)await new o(r,e,n).run()}
@@ -1 +1 @@
1
- import{b as m,d as u,f as p}from"./chunk-2JVEMMKH.js";import*as s from"valibot";function _(t,n){let i=t.scope?t.scope.length+2:0,e=t.type?.length??0,r=n.include_ticket?t.ticket?.length??0:0,c=t.title?.length??0;return i+e+r+c}function a(t){return t.map(i=>i===""?'"" (none)':`"${i}"`).join(", ")}function R(t){let n=t.commit_type.options.map(e=>e.value),i=t.commit_scope.options.map(e=>e.value);return s.pipe(s.object(m),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.type?`"${e.value.type}"`:"(empty)";e.value.type&&!n.includes(e.value.type)&&r({message:`Invalid --type ${c}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.scope?`"${e.value.scope}"`:"(empty)";e.value.scope&&!t.commit_scope.custom_scope&&!i.includes(e.value.scope)&&r({message:`Invalid --scope ${c}. Valid scopes: ${a(i)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{!e.typed||e.value.title.trim()||r({message:"Missing --title. Provide a non-empty commit title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=_(e.value,{include_ticket:t.check_ticket.add_to_title});c>t.commit_title.max_size&&r({message:`Title exceeds max width. Current size is ${c}, max is ${t.commit_title.max_size} (includes type, scope, and ticket when enabled).`})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&t.commit_body.required&&!e.value.body.trim()&&r({message:"Missing --body. commit_body.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.closes&&!e.value.ticket&&r({message:'Invalid footer values: --closes requires --ticket (for example: --ticket "ABC-123").'})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.breaking_body&&!e.value.breaking_title&&r({message:"Invalid breaking change values: --breaking-body requires --breaking-title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.deprecates_body&&!e.value.deprecates_title&&r({message:"Invalid deprecation values: --deprecates-body requires --deprecates-title."})}))}function q(t){let n=t.commit_type.options.map(i=>i.value);return s.pipe(s.object(u),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.type?`"${i.value.type}"`:"(empty)";i.value.type&&!n.includes(i.value.type)&&e({message:`Invalid --type ${r}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{!i.typed||i.value.description.trim()||e({message:"Missing --description. Provide a non-empty branch description."})}),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.description.trim();r.length>t.branch_description.max_length&&e({message:`Description exceeds max length. Current length is ${r.length}, max is ${t.branch_description.max_length}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_user.required&&!i.value.user.trim()&&e({message:"Missing --user. branch_user.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_ticket.required&&!i.value.ticket.trim()&&e({message:"Missing --ticket. branch_ticket.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_version.required&&!i.value.version.trim()&&e({message:"Missing --branch-version. branch_version.required is enabled in config."})}))}import{execSync as h}from"child_process";var f=/\/(\w+-\d+)/,v=/^(\w+-\d+)/,y=/^([A-Z]+-[\[a-zA-Z\]\d]+)_/,k=/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/,b=/\/(\d+)/,$=/^(\d+)/;function H(t){if(p.interactive)return;let n={ticket:"",type:""};if(t.check_ticket.infer_ticket){let e=w({append_hashtag:t.check_ticket.append_hashtag,prepend_hashtag:t.check_ticket.prepend_hashtag},p.git_args);n.ticket=e}let i=C(t.commit_type.options,p.git_args);return n.type=i,n}function C(t,n){let i=l(n);return i?E(i,t.map(e=>e.value)):""}function w(t,n){let i=l(n);return i?x(i,t):""}function x(t,n){let i=[t.match(y),t.match(k),t.match(f),t.match(b),t.match(v),t.match($)].filter(e=>e!=null).map(e=>e&&e.length>=2?e[1]:"");return!i.length||!i[0]?"":n.append_hashtag||n.prepend_hashtag==="Always"?`#${i[0]}`:i[0]}function E(t,n){return n.find(e=>{let r=new RegExp(`^${e}-`),c=new RegExp(`-${e}-`),g=new RegExp(`${e}/`);return[t.match(r),t.match(c),t.match(g)].filter(d=>d!=null).length>0})??""}function l(t){try{return h(`git ${t} branch --show-current`,{stdio:"pipe"}).toString().trim()}catch{return""}}import o from"picocolors";function X(t){return`${t} ${o.dim("\xB7 restored from cache")}`}function U(t){return`${t} ${o.dim("\xB7 inferred from branch")}`}function Z(t){return`${t} ${o.dim("\xB7 optional")}`}function j(t){return`${t} ${o.dim("\xB7 <space> to select")}`}function D(t){return`${t} ${o.dim("\xB7 dry run - changes will not be committed")}`}export{_ as a,R as b,q as c,H as d,C as e,w as f,X as g,U as h,Z as i,j,D as k};
1
+ import{b as m,d as u,f as p}from"./chunk-F4EBQBBK.js";import*as s from"valibot";function _(t,n){let i=t.scope?t.scope.length+2:0,e=t.type?.length??0,r=n.include_ticket?t.ticket?.length??0:0,c=t.title?.length??0;return i+e+r+c}function a(t){return t.map(i=>i===""?'"" (none)':`"${i}"`).join(", ")}function R(t){let n=t.commit_type.options.map(e=>e.value),i=t.commit_scope.options.map(e=>e.value);return s.pipe(s.object(m),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.type?`"${e.value.type}"`:"(empty)";e.value.type&&!n.includes(e.value.type)&&r({message:`Invalid --type ${c}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.scope?`"${e.value.scope}"`:"(empty)";e.value.scope&&!t.commit_scope.custom_scope&&!i.includes(e.value.scope)&&r({message:`Invalid --scope ${c}. Valid scopes: ${a(i)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{!e.typed||e.value.title.trim()||r({message:"Missing --title. Provide a non-empty commit title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=_(e.value,{include_ticket:t.check_ticket.add_to_title});c>t.commit_title.max_size&&r({message:`Title exceeds max width. Current size is ${c}, max is ${t.commit_title.max_size} (includes type, scope, and ticket when enabled).`})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&t.commit_body.required&&!e.value.body.trim()&&r({message:"Missing --body. commit_body.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.closes&&!e.value.ticket&&r({message:'Invalid footer values: --closes requires --ticket (for example: --ticket "ABC-123").'})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.breaking_body&&!e.value.breaking_title&&r({message:"Invalid breaking change values: --breaking-body requires --breaking-title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.deprecates_body&&!e.value.deprecates_title&&r({message:"Invalid deprecation values: --deprecates-body requires --deprecates-title."})}))}function q(t){let n=t.commit_type.options.map(i=>i.value);return s.pipe(s.object(u),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.type?`"${i.value.type}"`:"(empty)";i.value.type&&!n.includes(i.value.type)&&e({message:`Invalid --type ${r}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{!i.typed||i.value.description.trim()||e({message:"Missing --description. Provide a non-empty branch description."})}),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.description.trim();r.length>t.branch_description.max_length&&e({message:`Description exceeds max length. Current length is ${r.length}, max is ${t.branch_description.max_length}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_user.required&&!i.value.user.trim()&&e({message:"Missing --user. branch_user.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_ticket.required&&!i.value.ticket.trim()&&e({message:"Missing --ticket. branch_ticket.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_version.required&&!i.value.version.trim()&&e({message:"Missing --branch-version. branch_version.required is enabled in config."})}))}import{execSync as h}from"child_process";var f=/\/(\w+-\d+)/,v=/^(\w+-\d+)/,y=/^([A-Z]+-[\[a-zA-Z\]\d]+)_/,k=/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/,b=/\/(\d+)/,$=/^(\d+)/;function H(t){if(p.interactive)return;let n={ticket:"",type:""};if(t.check_ticket.infer_ticket){let e=w({append_hashtag:t.check_ticket.append_hashtag,prepend_hashtag:t.check_ticket.prepend_hashtag},p.git_args);n.ticket=e}let i=C(t.commit_type.options,p.git_args);return n.type=i,n}function C(t,n){let i=l(n);return i?E(i,t.map(e=>e.value)):""}function w(t,n){let i=l(n);return i?x(i,t):""}function x(t,n){let i=[t.match(y),t.match(k),t.match(f),t.match(b),t.match(v),t.match($)].filter(e=>e!=null).map(e=>e&&e.length>=2?e[1]:"");return!i.length||!i[0]?"":n.append_hashtag||n.prepend_hashtag==="Always"?`#${i[0]}`:i[0]}function E(t,n){return n.find(e=>{let r=new RegExp(`^${e}-`),c=new RegExp(`-${e}-`),g=new RegExp(`${e}/`);return[t.match(r),t.match(c),t.match(g)].filter(d=>d!=null).length>0})??""}function l(t){try{return h(`git ${t} branch --show-current`,{stdio:"pipe"}).toString().trim()}catch{return""}}import o from"picocolors";function X(t){return`${t} ${o.dim("\xB7 restored from cache")}`}function U(t){return`${t} ${o.dim("\xB7 inferred from branch")}`}function Z(t){return`${t} ${o.dim("\xB7 optional")}`}function j(t){return`${t} ${o.dim("\xB7 <space> to select")}`}function D(t){return`${t} ${o.dim("\xB7 <space> to select \xB7 <a> to select all")}`}function L(t){return`${t} ${o.dim("\xB7 dry run - changes will not be committed")}`}export{_ as a,R as b,q as c,H as d,C as e,w as f,X as g,U as h,Z as i,j,D as k,L as l};
@@ -1,6 +1,7 @@
1
- import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","trailer","breaking-change","deprecated","custom"],u=l.picklist(["branch","worktree"]),m=l.picklist(["closes","trailer","breaking-change","deprecated","custom"]),d=l.picklist(["user","version","type","ticket","description"]),K=l.picklist(["branch_user","branch_version","branch_type","branch_ticket","branch_description"]),C=["user","version","type","ticket","description"],y=[{value:"app",label:"app"},{value:"shared",label:"shared"},{value:"server",label:"server"},{value:"tools",label:"tools"},{value:"",label:"none"}],k=[{value:"feat",label:"feat",hint:"A new feature",emoji:"\u{1F31F}",trailer:"Changelog: feature"},{value:"fix",label:"fix",hint:"A bug fix",emoji:"\u{1F41B}",trailer:"Changelog: fix"},{value:"docs",label:"docs",hint:"Documentation only changes",emoji:"\u{1F4DA}",trailer:"Changelog: documentation"},{value:"refactor",label:"refactor",hint:"A code change that neither fixes a bug nor adds a feature",emoji:"\u{1F528}",trailer:"Changelog: refactor"},{value:"perf",label:"perf",hint:"A code change that improves performance",emoji:"\u{1F680}",trailer:"Changelog: performance"},{value:"test",label:"test",hint:"Adding missing tests or correcting existing tests",emoji:"\u{1F6A8}",trailer:"Changelog: test"},{value:"build",label:"build",hint:"Changes that affect the build system or external dependencies",emoji:"\u{1F6A7}",trailer:"Changelog: build"},{value:"ci",label:"ci",hint:"Changes to our CI configuration files and scripts",emoji:"\u{1F916}",trailer:"Changelog: ci"},{value:"chore",label:"chore",hint:"Other changes that do not modify src or test files",emoji:"\u{1F9F9}",trailer:"Changelog: chore"},{value:"",label:"none"}];var N=e.pipe(e.optional(e.object({enable:e.optional(e.boolean(),!0),initial_value:e.optional(e.string(),"feat"),max_items:e.optional(e.pipe(e.number(),e.minValue(1)),20),infer_type_from_branch:e.optional(e.boolean(),!0),append_emoji_to_label:e.optional(e.boolean(),!1),append_emoji_to_commit:e.optional(e.boolean(),!1),emoji_commit_position:e.optional(e.picklist(["Start","After-Colon"]),"Start"),options:e.optional(e.array(e.object({value:e.string(),label:e.optional(e.string()),hint:e.optional(e.string()),emoji:e.optional(e.pipe(e.string(),e.emoji())),trailer:e.optional(e.string())})),k)}),{}),e.rawCheck(({dataset:o,addIssue:t})=>{o.typed&&!o.value.options.some(r=>r.value===o.value.initial_value)&&t({message:`Type: initial_value "${o.value.initial_value}" must exist in options`})}),e.transform(o=>({...o,options:o.options.map(t=>({...t,label:t.emoji&&o.append_emoji_to_label?`${t.emoji} ${t.label}`:t.label}))}))),R=e.pipe(e.optional(e.object({enable:e.optional(e.boolean(),!0),custom_scope:e.optional(e.boolean(),!1),max_items:e.optional(e.pipe(e.number(),e.minValue(1)),20),initial_value:e.optional(e.string(),"app"),options:e.optional(e.array(e.object({value:e.string(),label:e.optional(e.string()),hint:e.optional(e.string())})),y)}),{}),e.rawCheck(({dataset:o,addIssue:t})=>{if(!o.typed)return;let r=o.value.options.map(i=>i.value);o.value.custom_scope&&r.push(s),r.includes(o.value.initial_value)||t({message:`Scope: initial_value "${o.value.initial_value}" must exist in options`})}),e.transform(o=>{let t=o.options.map(r=>r.value);return o.custom_scope&&!t.includes(s)?{...o,options:[...o.options,{label:s,value:s,hint:"Write a custom scope"}]}:o})),_=e.object({check_status:e.optional(e.boolean(),!0),commit_type:N,commit_scope:R,check_ticket:e.optional(e.object({infer_ticket:e.optional(e.boolean(),!0),confirm_ticket:e.optional(e.boolean(),!0),add_to_title:e.optional(e.boolean(),!0),append_hashtag:e.optional(e.boolean(),!1),prepend_hashtag:e.optional(e.picklist(["Never","Always","Prompt"]),"Never"),surround:e.optional(e.picklist(["","()","[]","{}"]),""),title_position:e.optional(e.picklist(["start","end","before-colon","beginning"]),"start")}),{}),commit_title:e.optional(e.object({max_size:e.optional(e.pipe(e.number(),e.minValue(1)),70)}),{}),commit_body:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),split_by_period:e.optional(e.boolean(),!1)}),{}),commit_footer:e.optional(e.object({enable:e.optional(e.boolean(),!0),initial_value:e.optional(e.array(m),[]),options:e.optional(e.array(m),h)}),{}),breaking_change:e.optional(e.object({add_exclamation_to_title:e.optional(e.boolean(),!0)}),{}),cache_last_value:e.optional(e.boolean(),!0),confirm_with_editor:e.optional(e.boolean(),!1),confirm_commit:e.optional(e.boolean(),!0),print_commit_output:e.optional(e.boolean(),!0),branch_pre_commands:e.optional(e.array(e.string()),[]),branch_post_commands:e.optional(e.array(e.string()),[]),worktree_pre_commands:e.optional(e.array(e.string()),[]),worktree_post_commands:e.optional(e.array(e.string()),[]),branch_user:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"/")}),{}),branch_type:e.optional(e.object({enable:e.optional(e.boolean(),!0),separator:e.optional(e.picklist(["/","-","_"]),"/")}),{}),branch_version:e.optional(e.object({enable:e.optional(e.boolean(),!1),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"/")}),{}),branch_ticket:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"-")}),{}),branch_description:e.optional(e.object({max_length:e.optional(e.pipe(e.number(),e.minValue(1)),70),separator:e.optional(e.picklist(["","/","-","_"]),"")}),{}),branch_action_default:e.optional(u,"branch"),branch_order:e.optional(e.array(d),C),enable_worktrees:e.optional(e.boolean(),!0),worktrees:e.optional(e.object({enable:e.optional(e.boolean(),!0),base_path:e.optional(e.string(),".."),folder_template:e.optional(e.string(),"{{repo_name}}-{{ticket}}-{{branch_description}}")}),{}),overrides:e.optional(e.object({shell:e.optional(e.string())}),{})}),P={type:e.optional(e.string(),""),scope:e.optional(e.string(),""),title:e.optional(e.string(),""),body:e.optional(e.string(),""),closes:e.optional(e.string(),""),ticket:e.optional(e.string(),""),breaking_title:e.optional(e.string(),""),breaking_body:e.optional(e.string(),""),deprecates:e.optional(e.string(),""),deprecates_title:e.optional(e.string(),""),deprecates_body:e.optional(e.string(),""),custom_footer:e.optional(e.string(),""),trailer:e.optional(e.string(),"")},Q=e.optional(e.object(P),{}),F={user:e.optional(e.string(),""),type:e.optional(e.string(),""),ticket:e.optional(e.string(),""),description:e.optional(e.string(),""),version:e.optional(e.string(),""),checkout:e.optional(u,"branch")},X=e.optional(e.object(F),{});import{parse as L}from"@bomb.sh/args";var O=["type","scope","title","body","closes","ticket","trailer","deprecates","breaking-title","breaking-body","deprecates-title","deprecates-body","custom-footer"],D=["git-dir","work-tree"],$=["interactive","dry-run","help","version"],g=class{#e;constructor(t){this.#e=t}get git_args(){return this.#e.git_args}get interactive(){return!this.#e.no_interactive}get dry_run(){return this.#e.dry_run}get help(){return this.#e.help}get version(){return this.#e.version}get commit_state(){return this.#e.commit_state}},f=new g(V(process.argv.slice(2)));function V(o){let t=L(o,{alias:{h:"help",v:"version"},boolean:$,string:[...O,...D]}),r={};return O.forEach(i=>{let a=t[i];if(a){let p=i.replace("-","_");r[p]=a}}),{help:t.help===!0,version:t.version===!0,git_args:M(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,commit_state:r}}function M(o,t){return`${o?`--git-dir=${o}`:""} ${t?`--work-tree=${t}`:""}`.trim()}var x=`{
1
+ import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","trailer","breaking-change","deprecated","custom"],u=l.picklist(["branch","worktree"]),m=l.picklist(["closes","trailer","breaking-change","deprecated","custom"]),d=l.picklist(["user","version","type","ticket","description"]),K=l.picklist(["branch_user","branch_version","branch_type","branch_ticket","branch_description"]),C=["user","version","type","ticket","description"],y=[{value:"app",label:"app"},{value:"shared",label:"shared"},{value:"server",label:"server"},{value:"tools",label:"tools"},{value:"",label:"none"}],k=[{value:"feat",label:"feat",hint:"A new feature",emoji:"\u{1F31F}",trailer:"Changelog: feature"},{value:"fix",label:"fix",hint:"A bug fix",emoji:"\u{1F41B}",trailer:"Changelog: fix"},{value:"docs",label:"docs",hint:"Documentation only changes",emoji:"\u{1F4DA}",trailer:"Changelog: documentation"},{value:"refactor",label:"refactor",hint:"A code change that neither fixes a bug nor adds a feature",emoji:"\u{1F528}",trailer:"Changelog: refactor"},{value:"perf",label:"perf",hint:"A code change that improves performance",emoji:"\u{1F680}",trailer:"Changelog: performance"},{value:"test",label:"test",hint:"Adding missing tests or correcting existing tests",emoji:"\u{1F6A8}",trailer:"Changelog: test"},{value:"build",label:"build",hint:"Changes that affect the build system or external dependencies",emoji:"\u{1F6A7}",trailer:"Changelog: build"},{value:"ci",label:"ci",hint:"Changes to our CI configuration files and scripts",emoji:"\u{1F916}",trailer:"Changelog: ci"},{value:"chore",label:"chore",hint:"Other changes that do not modify src or test files",emoji:"\u{1F9F9}",trailer:"Changelog: chore"},{value:"",label:"none"}];var N=e.pipe(e.optional(e.object({enable:e.optional(e.boolean(),!0),initial_value:e.optional(e.string(),"feat"),max_items:e.optional(e.pipe(e.number(),e.minValue(1)),20),infer_type_from_branch:e.optional(e.boolean(),!0),append_emoji_to_label:e.optional(e.boolean(),!1),append_emoji_to_commit:e.optional(e.boolean(),!1),emoji_commit_position:e.optional(e.picklist(["Start","After-Colon"]),"Start"),autocomplete:e.optional(e.boolean(),!0),options:e.optional(e.array(e.object({value:e.string(),label:e.optional(e.string()),hint:e.optional(e.string()),emoji:e.optional(e.pipe(e.string(),e.emoji())),trailer:e.optional(e.string())})),k)}),{}),e.rawCheck(({dataset:o,addIssue:t})=>{o.typed&&!o.value.options.some(r=>r.value===o.value.initial_value)&&t({message:`Type: initial_value "${o.value.initial_value}" must exist in options`})}),e.transform(o=>({...o,options:o.options.map(t=>({...t,label:t.emoji&&o.append_emoji_to_label?`${t.emoji} ${t.label}`:t.label}))}))),R=e.pipe(e.optional(e.object({enable:e.optional(e.boolean(),!0),custom_scope:e.optional(e.boolean(),!1),max_items:e.optional(e.pipe(e.number(),e.minValue(1)),20),initial_value:e.optional(e.string(),"app"),autocomplete:e.optional(e.boolean(),!0),options:e.optional(e.array(e.object({value:e.string(),label:e.optional(e.string()),hint:e.optional(e.string())})),y)}),{}),e.rawCheck(({dataset:o,addIssue:t})=>{if(!o.typed)return;let r=o.value.options.map(i=>i.value);o.value.custom_scope&&r.push(s),r.includes(o.value.initial_value)||t({message:`Scope: initial_value "${o.value.initial_value}" must exist in options`})}),e.transform(o=>{let t=o.options.map(r=>r.value);return o.custom_scope&&!t.includes(s)?{...o,options:[...o.options,{label:s,value:s,hint:"Write a custom scope"}]}:o})),_=e.object({check_status:e.optional(e.boolean(),!0),check_status_autocomplete:e.optional(e.boolean(),!0),commit_type:N,commit_scope:R,check_ticket:e.optional(e.object({infer_ticket:e.optional(e.boolean(),!0),confirm_ticket:e.optional(e.boolean(),!0),add_to_title:e.optional(e.boolean(),!0),append_hashtag:e.optional(e.boolean(),!1),prepend_hashtag:e.optional(e.picklist(["Never","Always","Prompt"]),"Never"),surround:e.optional(e.picklist(["","()","[]","{}"]),""),title_position:e.optional(e.picklist(["start","end","before-colon","beginning"]),"start")}),{}),commit_title:e.optional(e.object({max_size:e.optional(e.pipe(e.number(),e.minValue(1)),70)}),{}),commit_body:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),split_by_period:e.optional(e.boolean(),!1)}),{}),commit_footer:e.optional(e.object({enable:e.optional(e.boolean(),!0),initial_value:e.optional(e.array(m),[]),options:e.optional(e.array(m),h)}),{}),breaking_change:e.optional(e.object({add_exclamation_to_title:e.optional(e.boolean(),!0)}),{}),cache_last_value:e.optional(e.boolean(),!0),confirm_with_editor:e.optional(e.boolean(),!1),confirm_commit:e.optional(e.boolean(),!0),print_commit_output:e.optional(e.boolean(),!0),branch_pre_commands:e.optional(e.array(e.string()),[]),branch_post_commands:e.optional(e.array(e.string()),[]),worktree_pre_commands:e.optional(e.array(e.string()),[]),worktree_post_commands:e.optional(e.array(e.string()),[]),branch_user:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"/")}),{}),branch_type:e.optional(e.object({enable:e.optional(e.boolean(),!0),separator:e.optional(e.picklist(["/","-","_"]),"/"),autocomplete:e.optional(e.boolean(),!0)}),{}),branch_version:e.optional(e.object({enable:e.optional(e.boolean(),!1),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"/")}),{}),branch_ticket:e.optional(e.object({enable:e.optional(e.boolean(),!0),required:e.optional(e.boolean(),!1),separator:e.optional(e.picklist(["/","-","_"]),"-")}),{}),branch_description:e.optional(e.object({max_length:e.optional(e.pipe(e.number(),e.minValue(1)),70),separator:e.optional(e.picklist(["","/","-","_"]),"")}),{}),branch_action_default:e.optional(u,"branch"),branch_order:e.optional(e.array(d),C),enable_worktrees:e.optional(e.boolean(),!0),worktrees:e.optional(e.object({enable:e.optional(e.boolean(),!0),base_path:e.optional(e.string(),".."),folder_template:e.optional(e.string(),"{{repo_name}}-{{ticket}}-{{branch_description}}")}),{}),overrides:e.optional(e.object({shell:e.optional(e.string())}),{})}),P={type:e.optional(e.string(),""),scope:e.optional(e.string(),""),title:e.optional(e.string(),""),body:e.optional(e.string(),""),closes:e.optional(e.string(),""),ticket:e.optional(e.string(),""),breaking_title:e.optional(e.string(),""),breaking_body:e.optional(e.string(),""),deprecates:e.optional(e.string(),""),deprecates_title:e.optional(e.string(),""),deprecates_body:e.optional(e.string(),""),custom_footer:e.optional(e.string(),""),trailer:e.optional(e.string(),"")},Q=e.optional(e.object(P),{}),F={user:e.optional(e.string(),""),type:e.optional(e.string(),""),ticket:e.optional(e.string(),""),description:e.optional(e.string(),""),version:e.optional(e.string(),""),checkout:e.optional(u,"branch")},X=e.optional(e.object(F),{});import{parse as L}from"@bomb.sh/args";var O=["type","scope","title","body","closes","ticket","trailer","deprecates","breaking-title","breaking-body","deprecates-title","deprecates-body","custom-footer"],D=["git-dir","work-tree"],$=["interactive","dry-run","help","version"],g=class{#e;constructor(t){this.#e=t}get git_args(){return this.#e.git_args}get interactive(){return!this.#e.no_interactive}get dry_run(){return this.#e.dry_run}get help(){return this.#e.help}get version(){return this.#e.version}get commit_state(){return this.#e.commit_state}},f=new g(V(process.argv.slice(2)));function V(o){let t=L(o,{alias:{h:"help",v:"version"},boolean:$,string:[...O,...D]}),r={};return O.forEach(i=>{let a=t[i];if(a){let p=i.replace("-","_");r[p]=a}}),{help:t.help===!0,version:t.version===!0,git_args:M(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,commit_state:r}}function M(o,t){return`${o?`--git-dir=${o}`:""} ${t?`--work-tree=${t}`:""}`.trim()}var x=`{
2
2
  // Run interactive \`git status\` before composing a commit
3
3
  "check_status": true,
4
+ "check_status_autocomplete": true,
4
5
 
5
6
  /* COMMIT FIELDS */
6
7
  "commit_type": {
@@ -9,6 +10,8 @@ import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","
9
10
  // Default selected type from options
10
11
  "initial_value": "feat",
11
12
 
13
+ "max_items": 20,
14
+
12
15
  // Infer type from the current branch name: user/TYPE/my-branch
13
16
  "infer_type_from_branch": true,
14
17
 
@@ -21,6 +24,8 @@ import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","
21
24
  // "Start" | "After-Colon"
22
25
  "emoji_commit_position": "Start",
23
26
 
27
+ "autocomplete": true,
28
+
24
29
  "options": [
25
30
  {
26
31
  "value": "feat",
@@ -102,6 +107,7 @@ import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","
102
107
  "initial_value": "app",
103
108
 
104
109
  "max_items": 20,
110
+ "autocomplete": true,
105
111
  "options": [
106
112
  { "value": "app", "label": "app" },
107
113
  { "value": "shared", "label": "shared" },
@@ -189,7 +195,8 @@ import*as e from"valibot";import*as l from"valibot";var s="custom",h=["closes","
189
195
 
190
196
  "branch_type": {
191
197
  "enable": true,
192
- "separator": "/"
198
+ "separator": "/",
199
+ "autocomplete": true,
193
200
  },
194
201
 
195
202
  "branch_ticket": {
package/dist/index.js CHANGED
@@ -1,57 +1,61 @@
1
1
  #! /usr/bin/env node
2
- import{a as nt,b as at,d as ct,e as F,f as P,g as f,h as A,i as y,j as $,k as Y}from"./chunk-EANV5ZZP.js";import{a as Z,c as z,f as s,i as tt,k as et,l as it,m as ot,o as I,p as rt,q as st,r as g,s as u}from"./chunk-2JVEMMKH.js";import{chdir as kt}from"process";import*as H from"@clack/prompts";import{ValiError as vt,parse as ut}from"valibot";import Ct from"configstore";import*as T from"@clack/prompts";var m=class{constructor(t,e,o){this.config=t;this.commit_state=e;this.prompt_cache=o}};var R=class extends m{async run(){if(this.#o){let{initial_value:t,message:e}=this.#e,o=await T.select({message:e,initialValue:t,maxItems:this.#r,options:this.#t});T.isCancel(o)&&process.exit(0),this.#s(o)}}get#o(){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=F(this.#t,s.git_args);if(e)return{message:A("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#i(){return this.#t.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??"",trailer:e.trailer??""}}),{})}get#r(){return this.config.commit_type.max_items}#s(t){u(this.prompt_cache,"commit_type",t);let e=this.#i;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 j=class extends m{async run(){if(!this.#o)return;let{initial_value:t,message:e}=this.#e(),o=await k.select({message:e,initialValue:t,maxItems:this.#t,options:this.#i});k.isCancel(o)&&process.exit(0),await this.#s(o)}get#o(){return this.config.commit_scope.enable}#e(){let t=g(this.prompt_cache,"commit_scope");return t?{initial_value:t,message:f("Commit scope")}:{initial_value:this.config.commit_scope.initial_value,message:"Select a commit scope"}}get#t(){return this.config.commit_scope.max_items}get#i(){return this.config.commit_scope.options}get#r(){return this.config.commit_scope.custom_scope}async#s(t){u(this.prompt_cache,"commit_scope",t);let e=t;if(e===Z&&this.#r){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 N from"@clack/prompts";var E=class extends m{async run(){let{initial_value:t,message:e}=this.#i();if(this.commit_state.ticket=t,this.#e){let o=await N.text({message:e,placeholder:"",initialValue:t});N.isCancel(o)&&process.exit(0),u(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#o(){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"}#i(){let t=g(this.prompt_cache,"commit_ticket");if(t)return{initial_value:t,message:f("Ticket / issue")};if(this.#o){let e=P({append_hashtag:this.config.check_ticket.append_hashtag,prepend_hashtag:this.config.check_ticket.prepend_hashtag},s.git_args);if(e)return{initial_value:e,message:A("Ticket / issue")}}return{initial_value:this.commit_state.ticket,message:y("Add ticket / issue")}}};import*as G from"@clack/prompts";var D=class extends m{async run(){let{initial_value:t,message:e}=this.#o(),o=await G.text({message:e,initialValue:t,placeholder:"",validate:a=>this.#e(a)});G.isCancel(o)&&process.exit(0),this.#n(o??"")}#o(){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.#i(t)>this.#t)return`Exceeded max length. Title max [${this.#t}]`}get#t(){return this.config.commit_title.max_size}#i(t){return nt({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#r(){return this.config.commit_type.options.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??""}}),{})}#s(t){return this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="After-Colon"?`${this.#r[this.commit_state.type]?.emoji??""} ${t}`.trim():t}#n(t){u(this.prompt_cache,"commit_title",t),this.commit_state.title=st(this.#s(t))}};import*as L from"@clack/prompts";var M=class extends m{async run(){if(!this.#o)return;let{initial_value:t,message:e}=this.#e(),o=await L.text({message:e,initialValue:t,placeholder:"",validate:a=>this.#t(a)});L.isCancel(o)&&process.exit(0),this.#r(o??"")}get#o(){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:y("Write a detailed description of the changes")}}#t(t){if(this.config.commit_body.required&&!t)return"Please enter a description"}#i(t){return this.config.commit_body.split_by_period?t.split(/\.\s+/).map(o=>o.trim()).join(`.
3
- `):t}#r(t){u(this.prompt_cache,"commit_body",t),this.commit_state.body=this.#i(t)}};import*as h from"@clack/prompts";var V=class extends m{async run(){if(!this.#o)return;let{initial_values:t,message:e}=this.#i(),o=await h.multiselect({message:e,initialValues:t,options:this.#e,required:!1});h.isCancel(o)&&process.exit(0);let a=this.#s(o),r=await this.#n(a);this.#m(o,a,r)}get#o(){return this.config.commit_footer.enable}get#e(){let t=new Set(this.config.commit_footer.options);return tt.filter(e=>t.has(e.value))}get#t(){return this.#e.map(t=>t.value)}#i(){let t=g(this.prompt_cache,"commit_footer");return t?{initial_values:this.#r(t),message:$(f("Commit footers"))}:{initial_values:this.config.commit_footer.initial_value.filter(o=>this.#t.includes(o)),message:$(y("Select optional footers"))}}#r(t){return t.split(",").map(e=>e.trim()).filter(e=>this.#t.includes(e))}#s(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(y("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(y("Deprecated: Write a description"))),t.includes_custom&&(e.custom_footer=await this.#a("Write a custom footer")),e}async#c(t){let e=await h.text({message:t,placeholder:"",validate:o=>{if(!o)return"Please enter a title / summary"}});return h.isCancel(e)&&process.exit(0),e??""}async#a(t){let e=await h.text({message:t,placeholder:""});return h.isCancel(e)&&process.exit(0),e??""}#m(t,e,o){u(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 d from"@clack/prompts";import{execSync as mt}from"child_process";import p from"picocolors";function J({commit_state:i,config:t,colorize:e=!1,escape_quotes:o=!1,include_trailer:a=!1}){let r="";if(i.type&&(r+=e?p.blue(i.type):i.type),i.scope){let c=e?p.cyan(i.scope):i.scope;r+=`(${c})`}let n=i.ticket,l=t.check_ticket.surround;if(i.ticket&&l){let c=l.charAt(0),C=l.charAt(1);n=`${c}${i.ticket}${C}`}let v=t.check_ticket.title_position==="beginning";n&&t.check_ticket.add_to_title&&v&&(r=`${e?p.magenta(n):n} ${r}`);let w=t.check_ticket.title_position==="before-colon";if(n&&t.check_ticket.add_to_title&&w){let c=i.scope||i.type&&!t.check_ticket.surround?" ":"";r+=e?p.magenta(c+n):c+n}i.breaking_title&&t.breaking_change.add_exclamation_to_title&&(r+=e?p.red("!"):"!"),(i.scope||i.type||n&&w)&&(r+=": ");let U=t.check_ticket.title_position==="start",K=t.check_ticket.title_position==="end";if(n&&t.check_ticket.add_to_title&&U&&(r+=e?p.magenta(n)+" ":n+" "),i.title&&(r+=e?p.reset(i.title):i.title),n&&t.check_ticket.add_to_title&&K&&(r+=" "+(e?p.magenta(n):n)),i.body){let C=i.body.split("\\n").map(x=>e?p.reset(x.trim()):x.trim()).join(`
2
+ import{a as gt,b as dt,d as ft,e as R,f as T,g as f,h as N,i as S,j as Q,k as ht,l as Z}from"./chunk-5EGZQSNM.js";import{a as nt,c as at,f as n,i as ct,k as lt,l as mt,m as pt,o as E,p as ut,q as _t,r as g,s as d}from"./chunk-F4EBQBBK.js";import{chdir as Wt}from"process";import*as Y from"@clack/prompts";import{ValiError as qt,parse as St}from"valibot";import Kt from"configstore";import*as I from"@clack/prompts";var p=class{constructor(t,e,o){this.config=t;this.commit_state=e;this.prompt_cache=o}};var j=class extends p{async run(){if(this.#i){let{initial_value:t,message:e}=this.#e,s=await(this.config.commit_type.autocomplete?I.autocomplete:I.select)({message:e,initialValue:t,maxItems:this.#s,options:this.#t});I.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=R(this.#t,n.git_args);if(e)return{message:N("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 v from"@clack/prompts";var D=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),s=await(this.config.commit_scope.autocomplete?v.autocomplete:v.select)({message:e,initialValue:t,maxItems:this.#t,options:this.#o});v.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");return t?{initial_value:t,message:f("Commit scope")}:{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===nt&&this.#s){let o=await v.text({message:"Write a custom scope",placeholder:""});v.isCancel(o)&&process.exit(0),e=o??""}this.commit_state.scope=e}};import*as G from"@clack/prompts";var L=class extends p{async run(){let{initial_value:t,message:e}=this.#o();if(this.commit_state.ticket=t,this.#e){let o=await G.text({message:e,placeholder:"",initialValue:t});G.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=T({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:N("Ticket / issue")}}return{initial_value:this.commit_state.ticket,message:S("Add ticket / issue")}}};import*as B from"@clack/prompts";var M=class extends p{async run(){let{initial_value:t,message:e}=this.#i(),o=await B.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#e(s)});B.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 gt({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=_t(this.#r(t))}};import*as q from"@clack/prompts";var W=class extends p{async run(){if(!this.#i)return;let{initial_value:t,message:e}=this.#e(),o=await q.text({message:e,initialValue:t,placeholder:"",validate:s=>this.#t(s)});q.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:S("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 k from"@clack/prompts";var K=class extends p{async run(){if(!this.#i)return;let{initial_values:t,message:e}=this.#o(),o=await k.multiselect({message:e,initialValues:t,options:this.#e,required:!1});k.isCancel(o)&&process.exit(0);let s=this.#r(o),r=await this.#n(s);this.#l(o,s,r)}get#i(){return this.config.commit_footer.enable}get#e(){let t=new Set(this.config.commit_footer.options);return ct.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:Q(f("Commit footers"))}:{initial_values:this.config.commit_footer.initial_value.filter(o=>this.#t.includes(o)),message:Q(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 k.text({message:t,placeholder:"",validate:o=>{if(!o)return"Please enter a title / summary"}});return k.isCancel(e)&&process.exit(0),e??""}async#a(t){let e=await k.text({message:t,placeholder:""});return k.isCancel(e)&&process.exit(0),e??""}#l(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 bt}from"child_process";import u from"picocolors";function z({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 l=e?u.cyan(i.scope):i.scope;r+=`(${l})`}let a=i.ticket,m=t.check_ticket.surround;if(i.ticket&&m){let l=m.charAt(0),O=m.charAt(1);a=`${l}${i.ticket}${O}`}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 l=i.scope||i.type&&!t.check_ticket.surround?" ":"";r+=e?u.magenta(l+a):l+a}i.breaking_title&&t.breaking_change.add_exclamation_to_title&&(r+=e?u.red("!"):"!"),(i.scope||i.type||a&&x)&&(r+=": ");let b=t.check_ticket.title_position==="start",V=t.check_ticket.title_position==="end";if(a&&t.check_ticket.add_to_title&&b&&(r+=e?u.magenta(a)+" ":a+" "),i.title&&(r+=e?u.reset(i.title):i.title),a&&t.check_ticket.add_to_title&&V&&(r+=" "+(e?u.magenta(a):a)),i.body){let O=i.body.split("\\n").map(w=>e?u.reset(w.trim()):w.trim()).join(`
4
4
  `);r+=`
5
5
 
6
- ${C}`}if(i.breaking_title){let c=e?p.red(`BREAKING CHANGE: ${i.breaking_title}`):`BREAKING CHANGE: ${i.breaking_title}`;r+=`
6
+ ${O}`}if(i.breaking_title){let l=e?u.red(`BREAKING CHANGE: ${i.breaking_title}`):`BREAKING CHANGE: ${i.breaking_title}`;r+=`
7
7
 
8
- ${c}`}if(i.breaking_body){let c=e?p.red(i.breaking_body):i.breaking_body;r+=`
8
+ ${l}`}if(i.breaking_body){let l=e?u.red(i.breaking_body):i.breaking_body;r+=`
9
9
 
10
- ${c}`}if(i.deprecates_title){let c=e?p.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
10
+ ${l}`}if(i.deprecates_title){let l=e?u.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
11
11
 
12
- ${c}`}if(i.deprecates_body){let c=e?p.yellow(i.deprecates_body):i.deprecates_body;r+=`
12
+ ${l}`}if(i.deprecates_body){let l=e?u.yellow(i.deprecates_body):i.deprecates_body;r+=`
13
13
 
14
- ${c}`}if(i.custom_footer){let C=i.custom_footer.split("\\n").map(x=>e?p.reset(x.trim()):x.trim()).join(`
14
+ ${l}`}if(i.custom_footer){let O=i.custom_footer.split("\\n").map(w=>e?u.reset(w.trim()):w.trim()).join(`
15
15
  `);r+=`
16
16
 
17
- ${C}`}return i.closes&&i.ticket&&(r+=e?`
17
+ ${O}`}return i.closes&&i.ticket&&(r+=e?`
18
18
 
19
- ${p.reset(i.closes)} ${p.magenta(i.ticket)}`:`
19
+ ${u.reset(i.closes)} ${u.magenta(i.ticket)}`:`
20
20
 
21
- ${i.closes} ${i.ticket}`),a&&i.trailer&&(r+=e?`
21
+ ${i.closes} ${i.ticket}`),s&&i.trailer&&(r+=e?`
22
22
 
23
- ${p.dim(i.trailer)}`:`
23
+ ${u.dim(i.trailer)}`:`
24
24
 
25
- ${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}var O=class extends m{async run(){this.#o&&(mt(`${this.#n} --edit`,this.#i),process.exit(0)),this.#e&&d.note(J({commit_state:this.commit_state,config:this.config,colorize:!0,escape_quotes:!1,include_trailer:!0}),"Commit Preview"),await this.#a()||(d.log.info("Exiting without commit"),process.exit(0));try{d.log.info(s.dry_run?Y("Committing changes..."):"Committing changes..."),mt(this.#n,s.dry_run?this.#r:this.#i)}catch(e){d.log.error("Something went wrong when committing: "+e);return}this.#m()}get#o(){return s.interactive&&this.config.confirm_with_editor}get#e(){return this.config.print_commit_output}get#t(){return this.config.confirm_commit}get#i(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"inherit"}:{stdio:"inherit"}}get#r(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"pipe"}:{stdio:"pipe"}}get#s(){return this.commit_state.trailer?`--trailer="${this.commit_state.trailer}"`:""}get#n(){return`git ${s.git_args} commit -m "${J({commit_state:this.commit_state,config:this.config,colorize:!1,escape_quotes:!0,include_trailer:!1})}" ${this.#s} ${this.#c}`.trim()}get#c(){return s.dry_run?"--dry-run --porcelain --untracked-files=no":""}async#a(){if(!s.interactive||!this.#t)return!0;let t=await d.confirm({message:s.dry_run?Y("Confirm Commit?"):"Confirm Commit?"});return d.isCancel(t)&&process.exit(0),t}#m(){d.log.success("Commit Complete");let t=this.prompt_cache.get("username");this.prompt_cache.clear(),t&&this.prompt_cache.set("username",t)}};import*as b from"@clack/prompts";import S from"picocolors";import{execSync as lt}from"child_process";import*as W from"@clack/prompts";import Q from"picocolors";var pt=["M","T","R","D","A","C"];function X(){let i="";try{i=lt(`git ${s.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(a){return W.log.error(Q.red("Failed to git status"+a)),{index:[],work_tree:[]}}let t=i.split(`
26
- `),e=[],o=[];return t.forEach(a=>{let r=a.trimEnd();if(!r)return;let n=r.substring(2).trim(),l=r.charAt(0).trim(),v=r.charAt(1).trim();(l==="?"||v==="?")&&e.push(n),pt.includes(l)&&o.push(n),pt.includes(v)&&e.push(n)}),{index:o,work_tree:e}}function _t(i){let t=i.join(" ");if(t)try{lt(`git ${s.git_args} add ${t}`,{stdio:"pipe"}).toString(),W.log.success(Q.green("Changes successfully staged"))}catch{W.log.error(Q.red("Failed to stage changes"))}}var q=class extends m{async run(){if(!this.#o)return;let t=X();if(this.#e(t),t.work_tree.length){let e=await this.#i(t.work_tree);e.length&&_t(e)}this.#r()}get#o(){return this.config.check_status}#e(t){b.log.step(S.black(S.bgGreen(" Checking Git Status ")));let e=this.#t(t.index,S.green);if(b.log.success(`Changes to be committed:
27
- `+e),!t.work_tree.length)return;let o=this.#t(t.work_tree,S.red);b.log.error(`Changes not staged for commit:
28
- `+o)}#t(t,e){return t.reduce((o,a,r)=>e(o+a+rt(t,r)),"")}async#i(t){let e=await b.multiselect({message:$("Some files have not been staged, would you like to add them now?"),options:[{value:".",label:"."},...t.map(o=>({value:o,label:o}))],required:!1});return b.isCancel(e)&&process.exit(0),e}#r(){X().index.length||(b.log.error(S.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}};import{execSync as ft}from"child_process";import _ from"picocolors";var dt={"better-branch":"Create a branch or worktree from a guided prompt flow.","better-commits-init":"Create a .better-commits.json config in this repository."},ht={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print the commit command without creating a commit.","--help":"Show help information and exit."},bt={"--type":"Set commit type (for example feat, fix, docs).","--scope":"Set commit scope.","--title":"Set commit title/description.","--body":"Set commit body text.","--closes":"Set issue/ticket id for a closes footer.","--ticket":"Set ticket value used in the title.","--trailer":"Set trailer footer value.","--deprecates":"Set issue/ticket id for a deprecates footer.","--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."},yt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function B(i){let o=" ";return Object.entries(i).map(([a,r])=>{let n=Math.max(2,26-a.length);return`${o}${a}${" ".repeat(n)}${r}`}).join(`
29
- `)}function gt(i,t){let e=I(),o="(none)";try{o=ft(`git ${s.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let a=F(i.commit_type.options,s.git_args)||"Unknown",r=i.check_ticket.infer_ticket?P({append_hashtag:i.check_ticket.append_hashtag,prepend_hashtag:i.check_ticket.prepend_hashtag},s.git_args)||"Unknown":"Infer Disabled",n=i.commit_type.options.map(c=>c.value).join(", ").trim(),l=i.commit_scope.options.map(c=>c.value).join(", ").trim(),v=B(ht),w=B(yt),U=B(bt),K=B(dt);console.log(`
25
+ ${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}var F=class extends p{async run(){this.#i&&(bt(`${this.#n} --edit`,this.#o),process.exit(0)),this.#e&&h.note(z({commit_state:this.commit_state,config:this.config,colorize:!0,escape_quotes:!1,include_trailer:!0}),"Commit Preview"),await this.#a()||(h.log.info("Exiting without commit"),process.exit(0));try{h.log.info(n.dry_run?Z("Committing changes..."):"Committing changes..."),bt(this.#n,n.dry_run?this.#s:this.#o)}catch(e){h.log.error("Something went wrong when committing: "+e);return}this.#l()}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 "${z({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?Z("Confirm Commit?"):"Confirm Commit?"});return h.isCancel(t)&&process.exit(0),t}#l(){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 $ from"@clack/prompts";import A from"picocolors";import{execSync as vt}from"child_process";import*as H from"@clack/prompts";import tt from"picocolors";var yt=["M","T","R","D","A","C"];function et(){let i="";try{i=vt(`git ${n.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(s){return H.log.error(tt.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(),m=r.charAt(0).trim(),C=r.charAt(1).trim();(m==="?"||C==="?")&&e.push(a),yt.includes(m)&&o.push(a),yt.includes(C)&&e.push(a)}),{index:o,work_tree:e}}function kt(i){let t=i.join(" ");if(t)try{vt(`git ${n.git_args} add ${t}`,{stdio:"pipe"}).toString(),H.log.success(tt.green("Changes successfully staged"))}catch{H.log.error(tt.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 $t,S_CHECKBOX_SELECTED as At,limitOptions as Et,settings as Rt,symbol as Tt}from"@clack/prompts";function Nt(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 jt(i,t){return i===""||t.ctrl===!0&&t.name==="a"}var it=class extends Ft{constructor(e){super({options:e.options,multiple:!0,filter:e.filter??((o,s)=>Nt(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??Rt.withGuide,s=`${o?`${c("gray",P)}
27
+ `:""}${Tt(this.state)} ${e.message}
28
+ `,r=this.userInput,a=this.userInputWithCursor,m=this.options,C=this.filteredOptions.length!==m.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 x=this.state==="error"?"yellow":"cyan",b=o?`${c(x,P)} `:"",V=o?c(x,Pt):"",l=[`${c("dim","\u2191/\u2193")} to navigate`,`${c("dim",this.isNavigating?"Space/Tab:":"Tab:")} select`,`${c("dim","Ctrl+a:")} select visible`,`${c("dim","Enter:")} confirm`,`${c("dim","Type:")} to search`],O=this.filteredOptions.length===0&&r?[`${b}${c("yellow","No matches found")}`]:[],w=this.state==="error"?[`${b}${c("yellow",this.error)}`]:[],ot=[...`${s}${o?c(x,P):""}`.split(`
29
+ `),`${b}${c("dim","Search:")} ${a}${C}`,...O,...w],st=[`${b}${l.join(" \u2022 ")}`,V],Ot=Et({cursor:this.cursor,options:this.filteredOptions,style:(y,wt)=>{let It=this.selectedValues.includes(y.value),J=y.label??String(y.value??""),Vt=y.hint&&this.focusedValue!==void 0&&y.value===this.focusedValue?c("dim",` (${y.hint})`):"",rt=It?c("green",At):c("dim",$t);return y.disabled?`${c("gray",$t)} ${c(["strikethrough","gray"],J)}`:wt?`${rt} ${J}${Vt}`:`${rt} ${c("dim",J)}`},maxItems:e.maxItems,output:e.output,rowPadding:ot.length+st.length});return[...ot,...Ot.map(y=>`${b}${y}`),...st].join(`
30
+ `)}}}});this.promptOptions=e;this.on("key",(o,s)=>{jt(o,s)&&(this.#i(),this.isNavigating=!0,this.#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 Ct(i){return new it(i).prompt()}var U=class extends p{async run(){if(!this.#i)return;let t=et();if(this.#e(t),t.work_tree.length){let e=await this.#o(t.work_tree);e.length&&kt(e)}this.#s()}get#i(){return this.config.check_status}#e(t){$.log.step(A.black(A.bgGreen(" Checking Git Status ")));let e=this.#t(t.index,A.green);if($.log.success(`Changes to be committed:
31
+ `+e),!t.work_tree.length)return;let o=this.#t(t.work_tree,A.red);$.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 Ct({message:"Some files have not been staged, add them now?",options:t.map(o=>({value:o,label:o})),required:!1}):await $.multiselect({message:ht("Some files have not been staged, add them now?"),options:t.map(o=>({value:o,label:o})),required:!1});return $.isCancel(e)&&process.exit(0),e}#s(){et().index.length||($.log.error(A.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}};import{execSync as Dt}from"child_process";import _ from"picocolors";var Lt={"better-branch":"Create a branch or worktree from a guided prompt flow.","better-commits-init":"Create a .better-commits.json config in this repository."},Gt={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print the commit command without creating a commit.","--help":"Show help information and exit."},Mt={"--type":"Set commit type (for example feat, fix, docs).","--scope":"Set commit scope.","--title":"Set commit title/description.","--body":"Set commit body text.","--closes":"Set issue/ticket id for a closes footer.","--ticket":"Set ticket value used in the title.","--trailer":"Set trailer footer value.","--deprecates":"Set issue/ticket id for a deprecates footer.","--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."},Bt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function X(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 xt(i,t){let e=E(),o="(none)";try{o=Dt(`git ${n.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let s=R(i.commit_type.options,n.git_args)||"Unknown",r=i.check_ticket.infer_ticket?T({append_hashtag:i.check_ticket.append_hashtag,prepend_hashtag:i.check_ticket.prepend_hashtag},n.git_args)||"Unknown":"Infer Disabled",a=i.commit_type.options.map(l=>l.value).join(", ").trim(),m=i.commit_scope.options.map(l=>l.value).join(", ").trim(),C=X(Gt),x=X(Bt),b=X(Mt),V=X(Lt);console.log(`
30
34
  ${_.green("\uF489 better-commits")} ${_.gray("v"+e)}
31
35
 
32
36
  ${_.gray("BRANCH")}
33
37
  ${o}
34
- ${_.gray("Type")} ${_.blue(a)} ${_.gray("\xB7")} ${_.gray("Ticket")} ${_.magenta(r)}
38
+ ${_.gray("Type")} ${_.blue(s)} ${_.gray("\xB7")} ${_.gray("Ticket")} ${_.magenta(r)}
35
39
 
36
40
  ${_.gray("CONFIGURATION")}
37
41
  ${t}
38
42
 
39
43
  ${_.gray("Types")}
40
- ${n}
44
+ ${a}
41
45
 
42
46
  ${_.gray("Scopes")}
43
- ${l}
47
+ ${m}
44
48
 
45
49
  ${_.gray("CLI FLAGS")}
46
- ${v}
50
+ ${C}
47
51
 
48
52
  ${_.gray("Commit Flags")}
49
- ${U}
53
+ ${b}
50
54
 
51
55
  ${_.gray("Git Flags (Advanced)")}
52
- ${w}
56
+ ${x}
53
57
 
54
58
  ${_.gray("ADDITIONAL COMMANDS")}
55
- ${K}
59
+ ${V}
56
60
 
57
- `)}var xt=[q,R,j,E,D,M,V,O],{config:$t,config_source:Ot}=it();St($t,Ot);async function St(i,t){if(kt(ot()),s.version){let l=I();H.log.step("Better Commits v"+l);return}if(s.help){gt(i,t);return}let e=ct(i),o={...s.commit_state,type:(s.commit_state.type||e?.type)??"",ticket:(s.commit_state.ticket||e?.ticket)??""},a=ut(z,o);if(!s.interactive)try{ut(at(i),a)}catch(l){l instanceof vt?H.log.error(`Invalid commit input: ${l.message}`):H.log.error(`Failed to validate commit input: ${l}`),process.exit(0)}let r=i.cache_last_value?new Ct("better-commits"):et,n=s.interactive?xt:[O];for(let l of n)await new l(i,a,r).run()}export{St as main};
61
+ `)}var Ht=[U,j,D,L,M,W,K,F],{config:Ut,config_source:Xt}=mt();Yt(Ut,Xt);async function Yt(i,t){if(Wt(pt()),n.version){let m=E();Y.log.step("Better Commits v"+m);return}if(n.help){xt(i,t);return}let e=ft(i),o={...n.commit_state,type:(n.commit_state.type||e?.type)??"",ticket:(n.commit_state.ticket||e?.ticket)??""},s=St(at,o);if(!n.interactive)try{St(dt(i),s)}catch(m){m instanceof qt?Y.log.error(`Invalid commit input: ${m.message}`):Y.log.error(`Failed to validate commit input: ${m}`),process.exit(0)}let r=i.cache_last_value?new Kt("better-commits"):lt,a=n.interactive?Ht:[F];for(let m of a)await new m(i,s,r).run()}export{Yt as main};
package/dist/init.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #! /usr/bin/env node
2
- import{g as c,h as e,m as a,n as p}from"./chunk-2JVEMMKH.js";import*as t from"@clack/prompts";import l from"fs";import o from"picocolors";await m();async function m(){console.clear(),t.intro(`${o.bgCyan(o.black(" better-commits-init "))}`);let r=a(),i=p(r),s=`${r}/${e}`;if(i){let n=await t.confirm({message:`${i.split("/").pop()} already exists. Replace with default ${e}?`});if(t.isCancel(n)||!n){t.outro("Cancelled");return}}try{l.writeFileSync(s,c)}catch{t.log.error(`${o.red("Could not determine git root folder. better-commits-init must be used in a git repository")}`)}t.log.success(`${o.green(`Successfully created ${s.split("/").pop()}`)}`),t.outro(`Run ${o.bgBlack(o.white("better-commits"))} to start the CLI`)}export{m as create_init_config};
2
+ import{g as c,h as e,m as a,n as p}from"./chunk-F4EBQBBK.js";import*as t from"@clack/prompts";import l from"fs";import o from"picocolors";await m();async function m(){console.clear(),t.intro(`${o.bgCyan(o.black(" better-commits-init "))}`);let r=a(),i=p(r),s=`${r}/${e}`;if(i){let n=await t.confirm({message:`${i.split("/").pop()} already exists. Replace with default ${e}?`});if(t.isCancel(n)||!n){t.outro("Cancelled");return}}try{l.writeFileSync(s,c)}catch{t.log.error(`${o.red("Could not determine git root folder. better-commits-init must be used in a git repository")}`)}t.log.success(`${o.green(`Successfully created ${s.split("/").pop()}`)}`),t.outro(`Run ${o.bgBlack(o.white("better-commits"))} to start the CLI`)}export{m as create_init_config};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-commits",
3
3
  "private": false,
4
- "version": "1.21.0",
4
+ "version": "1.22.0",
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",
@@ -46,7 +46,7 @@
46
46
  "@semantic-release/git": "^10.0.1",
47
47
  "@semantic-release/npm": "^13.1.3",
48
48
  "@types/configstore": "^6.0.0",
49
- "@types/node": "^18.14.5",
49
+ "@types/node": "^24.10.1",
50
50
  "jiti": "^1.17.0",
51
51
  "prettier": "3.2.5",
52
52
  "semantic-release": "^25.0.2",
package/readme.md CHANGED
@@ -87,6 +87,7 @@ To create a **repository-specific config**, navigate to the root of your project
87
87
  {
88
88
  // Run interactive `git status` before composing a commit
89
89
  "check_status": true,
90
+ "check_status_autocomplete": true,
90
91
 
91
92
  /* COMMIT FIELDS */
92
93
  "commit_type": {
@@ -109,6 +110,8 @@ To create a **repository-specific config**, navigate to the root of your project
109
110
  // "Start" | "After-Colon"
110
111
  "emoji_commit_position": "Start",
111
112
 
113
+ "autocomplete": true,
114
+
112
115
  "options": [
113
116
  {
114
117
  "value": "feat",
@@ -190,6 +193,7 @@ To create a **repository-specific config**, navigate to the root of your project
190
193
  "initial_value": "app",
191
194
 
192
195
  "max_items": 20,
196
+ "autocomplete": true,
193
197
  "options": [
194
198
  { "value": "app", "label": "app" },
195
199
  { "value": "shared", "label": "shared" },
@@ -278,6 +282,7 @@ To create a **repository-specific config**, navigate to the root of your project
278
282
  "branch_type": {
279
283
  "enable": true,
280
284
  "separator": "/",
285
+ "autocomplete": true,
281
286
  },
282
287
 
283
288
  "branch_ticket": {
@@ -1,6 +1,7 @@
1
1
  export const DEFAULT_CONFIG_TEMPLATE = `{
2
2
  // Run interactive \`git status\` before composing a commit
3
3
  "check_status": true,
4
+ "check_status_autocomplete": true,
4
5
 
5
6
  /* COMMIT FIELDS */
6
7
  "commit_type": {
@@ -9,6 +10,8 @@ export const DEFAULT_CONFIG_TEMPLATE = `{
9
10
  // Default selected type from options
10
11
  "initial_value": "feat",
11
12
 
13
+ "max_items": 20,
14
+
12
15
  // Infer type from the current branch name: user/TYPE/my-branch
13
16
  "infer_type_from_branch": true,
14
17
 
@@ -21,6 +24,8 @@ export const DEFAULT_CONFIG_TEMPLATE = `{
21
24
  // "Start" | "After-Colon"
22
25
  "emoji_commit_position": "Start",
23
26
 
27
+ "autocomplete": true,
28
+
24
29
  "options": [
25
30
  {
26
31
  "value": "feat",
@@ -102,6 +107,7 @@ export const DEFAULT_CONFIG_TEMPLATE = `{
102
107
  "initial_value": "app",
103
108
 
104
109
  "max_items": 20,
110
+ "autocomplete": true,
105
111
  "options": [
106
112
  { "value": "app", "label": "app" },
107
113
  { "value": "shared", "label": "shared" },
@@ -189,7 +195,8 @@ export const DEFAULT_CONFIG_TEMPLATE = `{
189
195
 
190
196
  "branch_type": {
191
197
  "enable": true,
192
- "separator": "/"
198
+ "separator": "/",
199
+ "autocomplete": true,
193
200
  },
194
201
 
195
202
  "branch_ticket": {
@@ -0,0 +1,232 @@
1
+ import type { Key, ReadLine } from "node:readline";
2
+ import type { Readable, Writable } from "node:stream";
3
+ import { styleText } from "node:util";
4
+ import { AutocompletePrompt } from "@clack/core";
5
+ import {
6
+ S_BAR,
7
+ S_BAR_END,
8
+ S_CHECKBOX_INACTIVE,
9
+ S_CHECKBOX_SELECTED,
10
+ limitOptions,
11
+ settings,
12
+ symbol,
13
+ } from "@clack/prompts";
14
+
15
+ type Option<Value> = {
16
+ value: Value;
17
+ label?: string;
18
+ hint?: string;
19
+ disabled?: boolean;
20
+ };
21
+
22
+ type Filter<Value> = (search: string, option: Option<Value>) => boolean;
23
+
24
+ type AutocompleteMultiselectOptions<Value> = {
25
+ message: string;
26
+ options:
27
+ | Option<Value>[]
28
+ | ((this: AutocompletePrompt<Option<Value>>) => Option<Value>[]);
29
+ maxItems?: number;
30
+ validate?: (value: Value[] | undefined) => string | Error | undefined;
31
+ filter?: Filter<Value>;
32
+ initialValues?: Value[];
33
+ required?: boolean;
34
+ input?: Readable;
35
+ output?: Writable;
36
+ signal?: AbortSignal;
37
+ withGuide?: boolean;
38
+ };
39
+
40
+ function getFilteredOption<Value>(
41
+ searchText: string,
42
+ option: Option<Value>,
43
+ ): boolean {
44
+ if (!searchText) return true;
45
+
46
+ const label = (option.label ?? String(option.value ?? "")).toLowerCase();
47
+ const hint = (option.hint ?? "").toLowerCase();
48
+ const value = String(option.value).toLowerCase();
49
+ const term = searchText.toLowerCase();
50
+
51
+ return label.includes(term) || hint.includes(term) || value.includes(term);
52
+ }
53
+
54
+ function is_ctrl_a(char: string | undefined, key: Key): boolean {
55
+ return char === "\u0001" || (key.ctrl === true && key.name === "a");
56
+ }
57
+
58
+ /**
59
+ * Generated by 🤖. Mostly copying and extending from Clack AutocompletePrompt.
60
+ *
61
+ * This is to support ctrl+a to select all visible
62
+ */
63
+ class AutocompleteMultiselectPrompt<Value> extends AutocompletePrompt<
64
+ Option<Value>
65
+ > {
66
+ constructor(
67
+ private readonly promptOptions: AutocompleteMultiselectOptions<Value>,
68
+ ) {
69
+ super({
70
+ options: promptOptions.options,
71
+ multiple: true,
72
+ filter:
73
+ promptOptions.filter ??
74
+ ((search, opt) => getFilteredOption(search, opt)),
75
+ validate: (value) => {
76
+ if (
77
+ promptOptions.required &&
78
+ (!Array.isArray(value) || value.length === 0)
79
+ ) {
80
+ return "Please select at least one item";
81
+ }
82
+
83
+ return promptOptions.validate?.(value as Value[] | undefined);
84
+ },
85
+ initialValue: promptOptions.initialValues,
86
+ signal: promptOptions.signal,
87
+ input: promptOptions.input,
88
+ output: promptOptions.output,
89
+ render() {
90
+ const hasGuide = promptOptions.withGuide ?? settings.withGuide;
91
+ const title = `${hasGuide ? `${styleText("gray", S_BAR)}\n` : ""}${symbol(this.state)} ${promptOptions.message}\n`;
92
+ const userInput = this.userInput;
93
+ const searchText = this.userInputWithCursor;
94
+
95
+ const options = this.options;
96
+ const matches =
97
+ this.filteredOptions.length !== options.length
98
+ ? styleText(
99
+ "dim",
100
+ ` (${this.filteredOptions.length} match${this.filteredOptions.length === 1 ? "" : "es"})`,
101
+ )
102
+ : "";
103
+
104
+ switch (this.state) {
105
+ case "submit": {
106
+ return `${title}${hasGuide ? `${styleText("gray", S_BAR)} ` : ""}${styleText("dim", `${this.selectedValues.length} items selected`)}`;
107
+ }
108
+
109
+ case "cancel": {
110
+ return `${title}${hasGuide ? `${styleText("gray", S_BAR)} ` : ""}${styleText(["strikethrough", "dim"], userInput)}`;
111
+ }
112
+
113
+ default: {
114
+ const barStyle = this.state === "error" ? "yellow" : "cyan";
115
+ const guidePrefix = hasGuide
116
+ ? `${styleText(barStyle, S_BAR)} `
117
+ : "";
118
+ const guidePrefixEnd = hasGuide
119
+ ? styleText(barStyle, S_BAR_END)
120
+ : "";
121
+ const instructions = [
122
+ `${styleText("dim", "↑/↓")} to navigate`,
123
+ `${styleText("dim", this.isNavigating ? "Space/Tab:" : "Tab:")} select`,
124
+ `${styleText("dim", "Ctrl+a:")} select visible`,
125
+ `${styleText("dim", "Enter:")} confirm`,
126
+ `${styleText("dim", "Type:")} to search`,
127
+ ];
128
+ const noResults =
129
+ this.filteredOptions.length === 0 && userInput
130
+ ? [`${guidePrefix}${styleText("yellow", "No matches found")}`]
131
+ : [];
132
+ const errorMessage =
133
+ this.state === "error"
134
+ ? [`${guidePrefix}${styleText("yellow", this.error)}`]
135
+ : [];
136
+ const headerLines = [
137
+ ...`${title}${hasGuide ? styleText(barStyle, S_BAR) : ""}`.split(
138
+ "\n",
139
+ ),
140
+ `${guidePrefix}${styleText("dim", "Search:")} ${searchText}${matches}`,
141
+ ...noResults,
142
+ ...errorMessage,
143
+ ];
144
+ const footerLines = [
145
+ `${guidePrefix}${instructions.join(" • ")}`,
146
+ guidePrefixEnd,
147
+ ];
148
+ const displayOptions = limitOptions({
149
+ cursor: this.cursor,
150
+ options: this.filteredOptions,
151
+ style: (option, active) => {
152
+ const isSelected = this.selectedValues.includes(option.value);
153
+ const label = option.label ?? String(option.value ?? "");
154
+ const hint =
155
+ option.hint &&
156
+ this.focusedValue !== undefined &&
157
+ option.value === this.focusedValue
158
+ ? styleText("dim", ` (${option.hint})`)
159
+ : "";
160
+ const checkbox = isSelected
161
+ ? styleText("green", S_CHECKBOX_SELECTED)
162
+ : styleText("dim", S_CHECKBOX_INACTIVE);
163
+
164
+ if (option.disabled) {
165
+ return `${styleText("gray", S_CHECKBOX_INACTIVE)} ${styleText(["strikethrough", "gray"], label)}`;
166
+ }
167
+
168
+ if (active) {
169
+ return `${checkbox} ${label}${hint}`;
170
+ }
171
+
172
+ return `${checkbox} ${styleText("dim", label)}`;
173
+ },
174
+ maxItems: promptOptions.maxItems,
175
+ output: promptOptions.output,
176
+ rowPadding: headerLines.length + footerLines.length,
177
+ });
178
+
179
+ return [
180
+ ...headerLines,
181
+ ...displayOptions.map((option) => `${guidePrefix}${option}`),
182
+ ...footerLines,
183
+ ].join("\n");
184
+ }
185
+ }
186
+ },
187
+ });
188
+
189
+ this.on("key", (char, key) => {
190
+ if (!is_ctrl_a(char, key)) return;
191
+
192
+ this.#toggle_all_visible();
193
+ this.isNavigating = true;
194
+ this.#restore_cursor_to_end();
195
+ });
196
+ }
197
+
198
+ #toggle_all_visible(): void {
199
+ const visible_values = this.filteredOptions
200
+ .filter((option) => !option.disabled)
201
+ .map((option) => option.value);
202
+
203
+ if (!visible_values.length) return;
204
+
205
+ const every_visible_selected = visible_values.every((value) =>
206
+ this.selectedValues.includes(value),
207
+ );
208
+
209
+ this.selectedValues = every_visible_selected
210
+ ? this.selectedValues.filter((value) => !visible_values.includes(value))
211
+ : [
212
+ ...this.selectedValues,
213
+ ...visible_values.filter(
214
+ (value) => !this.selectedValues.includes(value),
215
+ ),
216
+ ];
217
+ }
218
+
219
+ #restore_cursor_to_end(): void {
220
+ const rl = (this as unknown as { rl?: ReadLine }).rl;
221
+ rl?.write("", { ctrl: true, name: "e" });
222
+ this._cursor = rl?.cursor ?? this.userInput.length;
223
+ }
224
+ }
225
+
226
+ export function autocompleteMultiselect<Value>(
227
+ opts: AutocompleteMultiselectOptions<Value>,
228
+ ): Promise<Value[] | symbol> {
229
+ return new AutocompleteMultiselectPrompt(opts).prompt() as Promise<
230
+ Value[] | symbol
231
+ >;
232
+ }
@@ -5,7 +5,10 @@ export class BranchTypePrompt extends BranchRunnable {
5
5
  async run(): Promise<void> {
6
6
  if (!this.#is_enabled) return;
7
7
 
8
- const branch_type = await p.select({
8
+ const prompt_type = this.config.branch_type.autocomplete
9
+ ? p.autocomplete
10
+ : p.select;
11
+ const branch_type = await prompt_type({
9
12
  message: this.#message,
10
13
  initialValue: this.#initial_value,
11
14
  options: this.#options,
@@ -9,7 +9,10 @@ export class CommitScopePrompt extends Runnable {
9
9
  if (!this.#is_enabled) return;
10
10
  const { initial_value, message } = this.#get_initial_value();
11
11
 
12
- let commit_scope = await p.select({
12
+ const prompt_type = this.config.commit_scope.autocomplete
13
+ ? p.autocomplete
14
+ : p.select;
15
+ let commit_scope = await prompt_type({
13
16
  message,
14
17
  initialValue: initial_value,
15
18
  maxItems: this.#max_items,
@@ -1,8 +1,9 @@
1
1
  import * as p from "@clack/prompts";
2
2
  import color from "picocolors";
3
3
  import { addNewLine } from "../utils";
4
- import { space_to_select_message } from "../utils/messages";
4
+ import { a_for_all_message } from "../utils/messages";
5
5
  import { git_add, git_status } from "../git";
6
+ import { autocompleteMultiselect } from "./autocomplete-multiselect";
6
7
  import { Runnable } from "./runnable";
7
8
 
8
9
  export class CommitStatusPrompt extends Runnable {
@@ -47,16 +48,18 @@ export class CommitStatusPrompt extends Runnable {
47
48
  }
48
49
 
49
50
  async #select_for_staging(work_tree: string[]): Promise<string[]> {
50
- const selected_for_staging = (await p.multiselect({
51
- message: space_to_select_message(
52
- "Some files have not been staged, would you like to add them now?",
53
- ),
54
- options: [
55
- { value: ".", label: "." },
56
- ...work_tree.map((v) => ({ value: v, label: v })),
57
- ],
58
- required: false,
59
- })) as string[];
51
+ const selected_for_staging = (this.config.check_status_autocomplete
52
+ ? await autocompleteMultiselect({
53
+ message: "Some files have not been staged, add them now?",
54
+ options: work_tree.map((v) => ({ value: v, label: v })),
55
+ required: false,
56
+ })
57
+ : await p.multiselect({
58
+ message: a_for_all_message("Some files have not been staged, add them now?"),
59
+ options: work_tree.map((v) => ({ value: v, label: v })),
60
+ required: false,
61
+ })) as string[];
62
+
60
63
  if (p.isCancel(selected_for_staging)) process.exit(0);
61
64
  return selected_for_staging;
62
65
  }
@@ -9,7 +9,10 @@ export class CommitTypePrompt extends Runnable {
9
9
  async run() {
10
10
  if (this.#is_enabled) {
11
11
  const { initial_value, message } = this.#initial_value;
12
- const commit_type = await p.select({
12
+ const prompt_type = this.config.commit_type.autocomplete
13
+ ? p.autocomplete
14
+ : p.select;
15
+ const commit_type = await prompt_type({
13
16
  message,
14
17
  initialValue: initial_value,
15
18
  maxItems: this.#max_items,
@@ -17,7 +17,7 @@ export function space_to_select_message(message: string): string {
17
17
  }
18
18
 
19
19
  export function a_for_all_message(message: string): string {
20
- return `${message} ${color.dim("· <space> to select | <a> to select all")}`;
20
+ return `${message} ${color.dim("· <space> to select · <a> to select all")}`;
21
21
  }
22
22
 
23
23
  export function dry_run_message(message: string): string {
@@ -23,6 +23,7 @@ const CommitTypeConfig = v.pipe(
23
23
  v.picklist(["Start", "After-Colon"]),
24
24
  "Start",
25
25
  ),
26
+ autocomplete: v.optional(v.boolean(), true),
26
27
  options: v.optional(
27
28
  v.array(
28
29
  v.object({
@@ -69,6 +70,7 @@ const CommitScopeConfig = v.pipe(
69
70
  custom_scope: v.optional(v.boolean(), false),
70
71
  max_items: v.optional(v.pipe(v.number(), v.minValue(1)), 20),
71
72
  initial_value: v.optional(v.string(), "app"),
73
+ autocomplete: v.optional(v.boolean(), true),
72
74
  options: v.optional(
73
75
  v.array(
74
76
  v.object({
@@ -116,6 +118,7 @@ const CommitScopeConfig = v.pipe(
116
118
 
117
119
  export const Config = v.object({
118
120
  check_status: v.optional(v.boolean(), true),
121
+ check_status_autocomplete: v.optional(v.boolean(), true),
119
122
  commit_type: CommitTypeConfig,
120
123
  commit_scope: CommitScopeConfig,
121
124
  check_ticket: v.optional(
@@ -184,6 +187,7 @@ export const Config = v.object({
184
187
  v.object({
185
188
  enable: v.optional(v.boolean(), true),
186
189
  separator: v.optional(v.picklist(["/", "-", "_"]), "/"),
190
+ autocomplete: v.optional(v.boolean(), true),
187
191
  }),
188
192
  {},
189
193
  ),
@@ -259,7 +263,4 @@ export const BRANCH_STATE_ENTRIES = {
259
263
  checkout: v.optional(V_BRANCH_ACTIONS, "branch"),
260
264
  };
261
265
 
262
- export const BranchState = v.optional(
263
- v.object(BRANCH_STATE_ENTRIES),
264
- {},
265
- );
266
+ export const BranchState = v.optional(v.object(BRANCH_STATE_ENTRIES), {});