better-commits 1.17.1 → 1.18.1

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,2 +1,2 @@
1
1
  #! /usr/bin/env node
2
- import{d as u,e as d,h,i as f,q as b,s as g}from"./chunk-7K2QIDID.js";import*as t from"@clack/prompts";import{execSync as m}from"child_process";import w from"configstore";import a from"picocolors";import{chdir as y}from"process";import{parse as C}from"valibot";x(g(" better-branch "));async function x(e){let i=C(u,{}),o="branch";if(e.enable_worktrees){let r=await t.select({message:"Checkout a branch or create a worktree?",initialValue:e.branch_action_default,options:b});t.isCancel(r)&&process.exit(),o=r}if(e.branch_user.enable){let r=O(),n=e.branch_user.required,c=await t.text({message:`Type your git username ${n?"":h} ${f}`.trim(),placeholder:"",initialValue:r,validate:k=>{if(n&&!k)return"Please enter a username"}});t.isCancel(c)&&process.exit(0),i.user=c?.replace(/\s+/g,"-")?.toLowerCase()??"",S(i.user)}if(e.branch_type.enable){let r=e.commit_type.initial_value,n=await t.select({message:"Select a branch type",initialValue:r,options:e.commit_type.options});t.isCancel(n)&&process.exit(0),i.type=n}if(e.branch_ticket.enable){let r=e.branch_ticket.required,n=await t.text({message:`Type ticket / issue number ${r?"":h}`.trim(),placeholder:"",validate:c=>{if(r&&!c)return"Please enter a ticket / issue"}});t.isCancel(n)&&process.exit(0),i.ticket=n}if(e.branch_version.enable){let r=e.branch_version.required,n=await t.text({message:`Type version number ${r?"":h}`.trim(),placeholder:"",validate:c=>{if(r&&!c)return"Please enter a version"}});t.isCancel(n)&&process.exit(0),i.version=n}let s=e.branch_description.max_length,_=await t.text({message:"Type a short description",placeholder:"",validate:r=>{if(!r)return"Please enter a description";if(r.length>s)return`Exceeded max length. Description max [${s}]`}});t.isCancel(_)&&process.exit(0),i.description=_?.replace(/\s+/g,"-")?.toLowerCase()??"",(o==="worktree"?e.worktree_pre_commands:e.branch_pre_commands).forEach(r=>{try{m(r,{stdio:"inherit"})}catch(n){t.log.error("Something went wrong when executing pre-commands: "+n),process.exit(0)}});let p=$(i,e),l=v(p);if(o==="branch")try{m(`git ${d.git_args} checkout ${l} ${p}`,{stdio:"inherit"}),t.log.info(`Switched to a new branch '${a.bgGreen(" "+a.black(p)+" ")}'`)}catch{process.exit(0)}else try{let n=`${i.ticket?`${i.ticket}-`:""}${i.description}`;m(`git worktree add ${n} ${l} ${p}`,{stdio:"inherit"}),t.log.info(`Created a new worktree ${a.bgGreen(+" "+a.black(n)+" ")}, checked out branch ${a.bgGreen(" "+a.black(p)+" ")}`),t.log.info(a.bgMagenta(a.black(` cd ${n} `))+" to navigate to your new worktree"),y(n)}catch{process.exit(0)}(o==="worktree"?e.worktree_post_commands:e.branch_post_commands).forEach(r=>{try{m(r,{stdio:"inherit"})}catch(n){t.log.error("Something went wrong when executing post-commands: "+n),process.exit(0)}})}function $(e,i){let o="";return i.branch_order.forEach(s=>{let _=`branch_${s}`;e[s]&&(o+=e[s]+i[_].separator)}),o.endsWith("-")||o.endsWith("/")||o.endsWith("_")?o.slice(0,-1).trim():o.trim()}function O(){try{return new w("better-commits").get("username")??""}catch{t.log.warn('There was an issue accessing username from cache. Check that the folder "~/.config" exists')}return""}function v(e){let i="";try{m(`git show-ref ${e}`,{encoding:"utf-8"}),t.log.warning(a.yellow(`${e} already exists! Checking out existing branch.`))}catch{i="-b"}return i}function S(e){try{new w("better-commits").set("username",e)}catch{}}
2
+ import{d as f,e as g,h as _,i as b,q as w,s as y,u as h}from"./chunk-ELYOZGPM.js";import*as r from"@clack/prompts";import{execSync as l}from"child_process";import C from"configstore";import s from"picocolors";import{chdir as k}from"process";import{parse as $}from"valibot";O(y(" better-branch "));async function O(e){let o=$(f,{});k(h());let a="branch";if(e.worktrees.enable){let t=await r.select({message:"Checkout a branch or create a worktree?",initialValue:e.branch_action_default,options:w});r.isCancel(t)&&process.exit(),a=t}if(e.branch_user.enable){let t=N(),n=e.branch_user.required,p=await r.text({message:`Type your git username ${n?"":_} ${b}`.trim(),placeholder:"",initialValue:t,validate:x=>{if(n&&!x)return"Please enter a username"}});r.isCancel(p)&&process.exit(0),o.user=p?.replace(/\s+/g,"-")?.toLowerCase()??"",T(o.user)}if(e.branch_type.enable){let t=e.commit_type.initial_value,n=await r.select({message:"Select a branch type",initialValue:t,options:e.commit_type.options});r.isCancel(n)&&process.exit(0),o.type=n}if(e.branch_ticket.enable){let t=e.branch_ticket.required,n=await r.text({message:`Type ticket / issue number ${t?"":_}`.trim(),placeholder:"",validate:p=>{if(t&&!p)return"Please enter a ticket / issue"}});r.isCancel(n)&&process.exit(0),o.ticket=n}if(e.branch_version.enable){let t=e.branch_version.required,n=await r.text({message:`Type version number ${t?"":_}`.trim(),placeholder:"",validate:p=>{if(t&&!p)return"Please enter a version"}});r.isCancel(n)&&process.exit(0),o.version=n}let c=e.branch_description.max_length,i=await r.text({message:"Type a short description",placeholder:"",validate:t=>{if(!t)return"Please enter a description";if(t.length>c)return`Exceeded max length. Description max [${c}]`}});r.isCancel(i)&&process.exit(0),o.description=i?.replace(/\s+/g,"-")?.toLowerCase()??"",(a==="worktree"?e.worktree_pre_commands:e.branch_pre_commands).forEach(t=>{try{l(t,{stdio:"inherit"})}catch(n){r.log.error("Something went wrong when executing pre-commands: "+n),process.exit(0)}});let m=v(o,e),d=A(m);if(a==="branch")try{l(`git ${g.git_args} checkout ${d} ${m}`,{stdio:"inherit"}),r.log.info(`Switched to a new branch '${s.bgGreen(" "+s.black(m)+" ")}'`)}catch{process.exit(0)}else try{let t=S(o,e);l(`git worktree add ${t} ${d} ${m}`,{stdio:"inherit"}),r.log.info(`Created a new worktree ${s.bgGreen(+" "+s.black(t)+" ")}, checked out branch ${s.bgGreen(" "+s.black(m)+" ")}`),r.log.info(s.bgMagenta(s.black(` cd ${t} `))+" to navigate to your new worktree"),k(t)}catch{process.exit(0)}(a==="worktree"?e.worktree_post_commands:e.branch_post_commands).forEach(t=>{try{l(t,{stdio:"inherit"})}catch(n){r.log.error("Something went wrong when executing post-commands: "+n),process.exit(0)}})}function v(e,o){let a="";return o.branch_order.forEach(c=>{let i=`branch_${c}`;e[c]&&(a+=e[c]+o[i].separator)}),a.endsWith("-")||a.endsWith("/")||a.endsWith("_")?a.slice(0,-1).trim():a.trim()}function S(e,o){let c=h().split("/").pop()||"repo",i=o.worktrees.folder_template;i=i.replace("{{repo_name}}",c).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 u=o.worktrees.base_path;return`${u}${u.endsWith("/")?"":"/"}${i}`}function N(){try{return new C("better-commits").get("username")??""}catch{r.log.warn('There was an issue accessing username from cache. Check that the folder "~/.config" exists')}return""}function A(e){let o="";try{l(`git show-ref ${e}`,{encoding:"utf-8"}),r.log.warning(s.yellow(`${e} already exists! Checking out existing branch.`))}catch{o="-b"}return o}function T(e){try{new C("better-commits").set("username",e)}catch{}}
@@ -1,4 +1,4 @@
1
- import*as p from"valibot";var c="custom",f=["closes","trailer","breaking-change","deprecated","custom"],h=p.picklist(["branch","worktree"]),g=p.picklist(["closes","trailer","breaking-change","deprecated","custom"]),d=p.picklist(["user","version","type","ticket","description"]),$=p.picklist(["branch_user","branch_version","branch_type","branch_ticket","branch_description"]),O=["user","version","type","ticket","description"],x=[{value:"app",label:"app"},{value:"shared",label:"shared"},{value:"server",label:"server"},{value:"tools",label:"tools"},{value:"",label:"none"}],C=[{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"}];import*as t from"valibot";var m=t.object({check_status:t.optional(t.boolean(),!0),commit_type:t.transform(t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.string(),"feat"),max_items:t.optional(t.number([t.minValue(1)]),20),infer_type_from_branch:t.optional(t.boolean(),!0),append_emoji_to_label:t.optional(t.boolean(),!1),append_emoji_to_commit:t.optional(t.boolean(),!1),emoji_commit_position:t.optional(t.picklist(["Start","After-Colon"]),"Start"),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string()),emoji:t.optional(t.string([t.emoji()]),void 0),trailer:t.optional(t.string())})),C)},[t.custom(e=>e.options.map(o=>o.value).includes(e.initial_value),e=>`Type: initial_value "${e.input.initial_value}" must exist in options`)]),{}),e=>{let o=e.options.map(n=>({...n,label:n.emoji&&e.append_emoji_to_label?`${n.emoji} ${n.label}`:n.label}))??[];return{...e,options:o}}),commit_scope:t.transform(t.optional(t.object({enable:t.optional(t.boolean(),!0),custom_scope:t.optional(t.boolean(),!1),max_items:t.optional(t.number([t.minValue(1)]),20),initial_value:t.optional(t.string(),"app"),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string())})),x)},[t.custom(e=>{let o=e.options.map(n=>n.value);return e.custom_scope&&o.push(c),o.includes(e.initial_value)},e=>`Scope: initial_value "${e.input.initial_value}" must exist in options`)]),{}),e=>{let o=e.options.map(n=>n.value);return e.custom_scope&&!o.includes(c)?{...e,options:[...e.options,{label:c,value:c,hint:"Write a custom scope"}]}:e}),check_ticket:t.optional(t.object({infer_ticket:t.optional(t.boolean(),!0),confirm_ticket:t.optional(t.boolean(),!0),add_to_title:t.optional(t.boolean(),!0),append_hashtag:t.optional(t.boolean(),!1),prepend_hashtag:t.optional(t.picklist(["Never","Always","Prompt"]),"Never"),surround:t.optional(t.picklist(["","()","[]","{}"]),""),title_position:t.optional(t.picklist(["start","end","before-colon","beginning"]),"start")}),{}),commit_title:t.optional(t.object({max_size:t.optional(t.number([t.minValue(1)]),70)}),{}),commit_body:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1)}),{}),commit_footer:t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.array(g),[]),options:t.optional(t.array(g),f)}),{}),breaking_change:t.optional(t.object({add_exclamation_to_title:t.optional(t.boolean(),!1)}),{}),cache_last_value:t.optional(t.boolean(),!0),confirm_with_editor:t.optional(t.boolean(),!1),confirm_commit:t.optional(t.boolean(),!0),print_commit_output:t.optional(t.boolean(),!0),branch_pre_commands:t.optional(t.array(t.string()),[]),branch_post_commands:t.optional(t.array(t.string()),[]),worktree_pre_commands:t.optional(t.array(t.string()),[]),worktree_post_commands:t.optional(t.array(t.string()),[]),branch_user:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_type:t.optional(t.object({enable:t.optional(t.boolean(),!0),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_version:t.optional(t.object({enable:t.optional(t.boolean(),!1),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_ticket:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"-")}),{}),branch_description:t.optional(t.object({max_length:t.optional(t.number([t.minValue(1)]),70),separator:t.optional(t.picklist(["","/","-","_"]),"")}),{}),branch_action_default:t.optional(h,"branch"),branch_order:t.optional(t.array(d),O),enable_worktrees:t.optional(t.boolean(),!0),overrides:t.optional(t.object({shell:t.optional(t.string())}),{})}),H=t.optional(t.object({type:t.optional(t.string(),""),scope:t.optional(t.string(),""),title:t.optional(t.string(),""),body:t.optional(t.string(),""),closes:t.optional(t.string(),""),ticket:t.optional(t.string(),""),breaking_title:t.optional(t.string(),""),breaking_body:t.optional(t.string(),""),deprecates:t.optional(t.string(),""),deprecates_title:t.optional(t.string(),""),deprecates_body:t.optional(t.string(),""),custom_footer:t.optional(t.string(),""),trailer:t.optional(t.string(),"")}),{}),D=t.optional(t.object({user:t.optional(t.string(),""),type:t.optional(t.string(),""),ticket:t.optional(t.string(),""),description:t.optional(t.string(),""),version:t.optional(t.string(),"")}),{});var b=class{#t="";constructor(){}get git_args(){return this.#t}set git_args(o){this.#t=o}},_=new b;import*as i from"@clack/prompts";import{execSync as S}from"child_process";import u from"fs";import{homedir as R}from"os";import a from"picocolors";import{ValiError as N,parse as y}from"valibot";import{argv as E}from"process";var T=".better-commits.json",K=`${a.dim("(<space> to select)")}`,Q=`${a.dim("(<space> to select, <a> to select all)")}`,tt=`${a.dim("(optional)")}`,ot=`${a.dim("(value will be saved)")}`,et=new RegExp(/\/(\w+-\d+)/),nt=new RegExp(/^(\w+-\d+)/),it=new RegExp(/^([A-Z]+-[\[a-zA-Z\]\d]+)_/),rt=new RegExp(/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/),at=new RegExp(/\/(\d+)/),lt=new RegExp(/^(\d+)/),st=[{value:"closes",label:"closes <issue/ticket>",hint:"Attempts to infer ticket from branch"},{value:"trailer",label:"trailer",hint:"Appends trailer based on commit type"},{value:"breaking-change",label:"breaking change",hint:"Add breaking change"},{value:"deprecated",label:"deprecated",hint:"Add deprecated change"},{value:"custom",label:"custom",hint:"Add a custom footer"}],pt=[{value:"branch",label:"Branch"},{value:"worktree",label:"Worktree"}],ct={get:()=>"",set:(e,o)=>{},clear:()=>{}};function vt(e=" better-commits "){console.clear(),i.intro(`${a.bgCyan(a.black(e))}`),P();let o=null,n=I();u.existsSync(n)&&(i.log.step("Found global config"),o=A(n));let l=`${w()}/${T}`;if(u.existsSync(l)){i.log.step("Found repository config");let s=A(l);return o?{...s,overrides:o.overrides.shell?o.overrides:s.overrides,confirm_with_editor:o.confirm_with_editor,cache_last_value:o.cache_last_value}:s}if(o)return o;let v=y(m,{});return i.log.step("Config not found. Generating default .better-commit.json at $HOME"),u.writeFileSync(n,JSON.stringify(v,null,4)),v}function A(e){let o=null;try{o=JSON.parse(u.readFileSync(e,"utf8"))}catch(n){i.log.error(`Invalid JSON file. Exiting.
1
+ import*as p from"valibot";var c="custom",f=["closes","trailer","breaking-change","deprecated","custom"],h=p.picklist(["branch","worktree"]),g=p.picklist(["closes","trailer","breaking-change","deprecated","custom"]),d=p.picklist(["user","version","type","ticket","description"]),$=p.picklist(["branch_user","branch_version","branch_type","branch_ticket","branch_description"]),O=["user","version","type","ticket","description"],x=[{value:"app",label:"app"},{value:"shared",label:"shared"},{value:"server",label:"server"},{value:"tools",label:"tools"},{value:"",label:"none"}],C=[{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"}];import*as t from"valibot";var m=t.object({check_status:t.optional(t.boolean(),!0),commit_type:t.transform(t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.string(),"feat"),max_items:t.optional(t.number([t.minValue(1)]),20),infer_type_from_branch:t.optional(t.boolean(),!0),append_emoji_to_label:t.optional(t.boolean(),!1),append_emoji_to_commit:t.optional(t.boolean(),!1),emoji_commit_position:t.optional(t.picklist(["Start","After-Colon"]),"Start"),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string()),emoji:t.optional(t.string([t.emoji()]),void 0),trailer:t.optional(t.string())})),C)},[t.custom(e=>e.options.map(o=>o.value).includes(e.initial_value),e=>`Type: initial_value "${e.input.initial_value}" must exist in options`)]),{}),e=>{let o=e.options.map(n=>({...n,label:n.emoji&&e.append_emoji_to_label?`${n.emoji} ${n.label}`:n.label}))??[];return{...e,options:o}}),commit_scope:t.transform(t.optional(t.object({enable:t.optional(t.boolean(),!0),custom_scope:t.optional(t.boolean(),!1),max_items:t.optional(t.number([t.minValue(1)]),20),initial_value:t.optional(t.string(),"app"),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string())})),x)},[t.custom(e=>{let o=e.options.map(n=>n.value);return e.custom_scope&&o.push(c),o.includes(e.initial_value)},e=>`Scope: initial_value "${e.input.initial_value}" must exist in options`)]),{}),e=>{let o=e.options.map(n=>n.value);return e.custom_scope&&!o.includes(c)?{...e,options:[...e.options,{label:c,value:c,hint:"Write a custom scope"}]}:e}),check_ticket:t.optional(t.object({infer_ticket:t.optional(t.boolean(),!0),confirm_ticket:t.optional(t.boolean(),!0),add_to_title:t.optional(t.boolean(),!0),append_hashtag:t.optional(t.boolean(),!1),prepend_hashtag:t.optional(t.picklist(["Never","Always","Prompt"]),"Never"),surround:t.optional(t.picklist(["","()","[]","{}"]),""),title_position:t.optional(t.picklist(["start","end","before-colon","beginning"]),"start")}),{}),commit_title:t.optional(t.object({max_size:t.optional(t.number([t.minValue(1)]),70)}),{}),commit_body:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1)}),{}),commit_footer:t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.array(g),[]),options:t.optional(t.array(g),f)}),{}),breaking_change:t.optional(t.object({add_exclamation_to_title:t.optional(t.boolean(),!1)}),{}),cache_last_value:t.optional(t.boolean(),!0),confirm_with_editor:t.optional(t.boolean(),!1),confirm_commit:t.optional(t.boolean(),!0),print_commit_output:t.optional(t.boolean(),!0),branch_pre_commands:t.optional(t.array(t.string()),[]),branch_post_commands:t.optional(t.array(t.string()),[]),worktree_pre_commands:t.optional(t.array(t.string()),[]),worktree_post_commands:t.optional(t.array(t.string()),[]),branch_user:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_type:t.optional(t.object({enable:t.optional(t.boolean(),!0),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_version:t.optional(t.object({enable:t.optional(t.boolean(),!1),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"/")}),{}),branch_ticket:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1),separator:t.optional(t.picklist(["/","-","_"]),"-")}),{}),branch_description:t.optional(t.object({max_length:t.optional(t.number([t.minValue(1)]),70),separator:t.optional(t.picklist(["","/","-","_"]),"")}),{}),branch_action_default:t.optional(h,"branch"),branch_order:t.optional(t.array(d),O),enable_worktrees:t.optional(t.boolean(),!0),worktrees:t.optional(t.object({enable:t.optional(t.boolean(),!0),base_path:t.optional(t.string(),".."),folder_template:t.optional(t.string(),"{{repo_name}}-{{ticket}}-{{branch_description}}")}),{}),overrides:t.optional(t.object({shell:t.optional(t.string())}),{})}),H=t.optional(t.object({type:t.optional(t.string(),""),scope:t.optional(t.string(),""),title:t.optional(t.string(),""),body:t.optional(t.string(),""),closes:t.optional(t.string(),""),ticket:t.optional(t.string(),""),breaking_title:t.optional(t.string(),""),breaking_body:t.optional(t.string(),""),deprecates:t.optional(t.string(),""),deprecates_title:t.optional(t.string(),""),deprecates_body:t.optional(t.string(),""),custom_footer:t.optional(t.string(),""),trailer:t.optional(t.string(),"")}),{}),D=t.optional(t.object({user:t.optional(t.string(),""),type:t.optional(t.string(),""),ticket:t.optional(t.string(),""),description:t.optional(t.string(),""),version:t.optional(t.string(),"")}),{});var b=class{#t="";constructor(){}get git_args(){return this.#t}set git_args(o){this.#t=o}},_=new b;import*as i from"@clack/prompts";import{execSync as S}from"child_process";import u from"fs";import{homedir as R}from"os";import a from"picocolors";import{ValiError as N,parse as y}from"valibot";import{argv as E}from"process";var T=".better-commits.json",K=`${a.dim("(<space> to select)")}`,Q=`${a.dim("(<space> to select, <a> to select all)")}`,tt=`${a.dim("(optional)")}`,ot=`${a.dim("(value will be saved)")}`,et=new RegExp(/\/(\w+-\d+)/),nt=new RegExp(/^(\w+-\d+)/),it=new RegExp(/^([A-Z]+-[\[a-zA-Z\]\d]+)_/),rt=new RegExp(/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/),at=new RegExp(/\/(\d+)/),lt=new RegExp(/^(\d+)/),st=[{value:"closes",label:"closes <issue/ticket>",hint:"Attempts to infer ticket from branch"},{value:"trailer",label:"trailer",hint:"Appends trailer based on commit type"},{value:"breaking-change",label:"breaking change",hint:"Add breaking change"},{value:"deprecated",label:"deprecated",hint:"Add deprecated change"},{value:"custom",label:"custom",hint:"Add a custom footer"}],pt=[{value:"branch",label:"Branch"},{value:"worktree",label:"Worktree"}],ct={get:()=>"",set:(e,o)=>{},clear:()=>{}};function vt(e=" better-commits "){console.clear(),i.intro(`${a.bgCyan(a.black(e))}`),P();let o=null,n=I();u.existsSync(n)&&(i.log.step("Found global config"),o=A(n));let l=`${w()}/${T}`;if(u.existsSync(l)){i.log.step("Found repository config");let s=A(l);return o?{...s,overrides:o.overrides.shell?o.overrides:s.overrides,confirm_with_editor:o.confirm_with_editor,cache_last_value:o.cache_last_value}:s}if(o)return o;let v=y(m,{});return i.log.step("Config not found. Generating default .better-commit.json at $HOME"),u.writeFileSync(n,JSON.stringify(v,null,4)),v}function A(e){let o=null;try{o=JSON.parse(u.readFileSync(e,"utf8"))}catch(n){i.log.error(`Invalid JSON file. Exiting.
2
2
  `+n),process.exit(0)}return j(o)}function j(e){try{return y(m,e)}catch(o){if(o instanceof N){let r=(o.issues[0].path??[]).map(l=>l.key).join(".");i.log.error(`Invalid Configuration: ${a.red(r)}
3
3
  `+o.message)}process.exit(0)}}function _t(e){let o="";try{o=S(`git ${_.git_args} branch --show-current`,{stdio:"pipe"}).toString()}catch{return""}return e.find(r=>{let l=new RegExp(`^${r}-`),v=new RegExp(`-${r}-`),s=new RegExp(`${r}/`);return[o.match(l),o.match(v),o.match(s)].filter(k=>k!=null)?.length})??""}function w(){let e=".";try{e=S(`git ${_.git_args} rev-parse --show-toplevel`).toString().trim()}catch{i.log.warn("Could not find git root. If in a --bare repository, ignore this warning.")}return e}function I(){return R()+"/"+T}function ut(e,o){return o===e.length-1?"":`
4
4
  `}function gt(e){let o=e.trim();return o.endsWith(".")?o.substring(0,o.length-1).trim():e.trim()}function P(){_.git_args=`${E[2]??""} ${E[3]??""}`.trim()}function mt(e,o){try{return e.get(o)??""}catch{i.log.warn(`Could not access ${o} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}return""}function bt(e,o,n){try{e.set(o,n)}catch{i.log.warn(`Could not access ${o} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}}export{c as a,m as b,H as c,D as d,_ as e,T as f,K as g,tt as h,ot as i,et as j,nt as k,it as l,rt as m,at as n,lt as o,st as p,pt as q,ct as r,vt as s,_t as t,w as u,ut as v,gt as w,mt as x,bt as y};
package/dist/index.js CHANGED
@@ -1,31 +1,31 @@
1
1
  #! /usr/bin/env node
2
- import{a as A,c as T,e as g,g as x,h as b,j as R,k as v,l as P,m as j,n as G,o as N,p as D,r as I,s as W,t as M,u as V,v as C,w as H,x as k,y}from"./chunk-7K2QIDID.js";import*as s from"@clack/prompts";import c from"picocolors";import{execSync as w}from"child_process";import{chdir as B}from"process";import{parse as q}from"valibot";import{execSync as X}from"child_process";import*as $ from"@clack/prompts";import E from"picocolors";var L=["M","T","R","D","A","C"];function S(){let e="";try{e=X(`git ${g.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(u){return $.log.error(E.red("Failed to git status"+u)),{index:[],work_tree:[]}}let t=e.split(`
3
- `),o=[],h=[];return t.forEach(u=>{let a=u.trimEnd();if(!a)return;let p=a.substring(2).trim(),i=a.charAt(0).trim(),r=a.charAt(1).trim();(i==="?"||r==="?")&&o.push(p),L.includes(i)&&h.push(p),L.includes(r)&&o.push(p)}),{index:h,work_tree:o}}function F(e){let t=e.join(" ");if(t)try{X(`git ${g.git_args} add ${t}`,{stdio:"pipe"}).toString(),$.log.success(E.green("Changes successfully staged"))}catch{$.log.error(E.red("Failed to stage changes"))}}import K from"configstore";Y(W());async function Y(e){let t=q(T,{});B(V());let o=e.cache_last_value?new K("better-commits"):I;if(e.check_status){let{index:i,work_tree:r}=S();s.log.step(c.black(c.bgGreen(" Checking Git Status ")));let n=i.reduce((d,l,m)=>c.green(d+l+C(i,m)),"");if(s.log.success(`Changes to be committed:
4
- `+n),r.length){let d=r.reduce((m,f,U)=>c.red(m+f+C(r,U)),"");s.log.error(`Changes not staged for commit:
5
- `+d);let l=await s.multiselect({message:`Some files have not been staged, would you like to add them now? ${x}`,options:[{value:".",label:"."},...r.map(m=>({value:m,label:m}))],required:!1});s.isCancel(l)&&process.exit(0),F(l)}S().index.length||(s.log.error(c.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}let h=e.commit_type.options.reduce((i,r)=>({...i,[r.value]:{emoji:r.emoji??"",trailer:r.trailer??""}}),{});if(e.commit_type.enable){let i="Select a commit type",r=e.commit_type.initial_value;if(e.commit_type.infer_type_from_branch){let _=e.commit_type.options.map(l=>l.value),d=M(_);d&&(i=`Commit type inferred from branch ${c.dim("(confirm / edit)")}`,r=d)}let n=await s.select({message:i,initialValue:k(o,"commit_type")||r,maxItems:e.commit_type.max_items,options:e.commit_type.options});s.isCancel(n)&&process.exit(0),y(o,"commit_type",n),t.trailer=h[n].trailer,t.type=e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="Start"?`${h[n].emoji} ${n}`.trim():n}if(e.commit_scope.enable){let i=await s.select({message:"Select a commit scope",initialValue:k(o,"commit_scope")||e.commit_scope.initial_value,maxItems:e.commit_scope.max_items,options:e.commit_scope.options});s.isCancel(i)&&process.exit(0),y(o,"commit_scope",i),i===A&&e.commit_scope.custom_scope&&(i=await s.text({message:"Write a custom scope",placeholder:""}),s.isCancel(i)&&process.exit(0)),t.scope=i}if(e.check_ticket.infer_ticket)try{let i=w(`git ${g.git_args} branch --show-current`,{stdio:"pipe"}).toString(),r=[i.match(P),i.match(j),i.match(R),i.match(G),i.match(v),i.match(N)].filter(n=>n!=null).map(n=>n&&n.length>=2?n[1]:"");r.length&&r[0]&&(t.ticket=e.check_ticket.append_hashtag||e.check_ticket.prepend_hashtag==="Prompt"?"#"+r[0]:r[0])}catch{}if(e.check_ticket.confirm_ticket){let i=await s.text({message:t.ticket?`Ticket / issue inferred from branch ${c.dim("(confirm / edit)")}`:`Add ticket / issue ${b}`,placeholder:"",initialValue:k(o,"commit_ticket")||t.ticket});s.isCancel(i)&&process.exit(0),y(o,"commit_ticket",i),t.ticket=i??""}e.check_ticket.prepend_hashtag==="Always"&&t.ticket&&!t.ticket.startsWith("#")&&(t.ticket="#"+t.ticket);let u=await s.text({message:"Write a brief title describing the commit",initialValue:k(o,"commit_title")||"",placeholder:"",validate:i=>{if(!i)return"Please enter a title";let r=t.scope?t.scope.length+2:0,n=t.type.length,_=e.check_ticket.add_to_title?t.ticket.length:0;if(r+n+_+i.length>e.commit_title.max_size)return`Exceeded max length. Title max [${e.commit_title.max_size}]`}});s.isCancel(u)&&process.exit(0),y(o,"commit_title",u);let a=u;if(e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="After-Colon"&&(a=`${h[t.type].emoji} ${u}`),t.title=H(a),e.commit_body.enable){let i=await s.text({message:`Write a detailed description of the changes ${b}`,initialValue:k(o,"commit_body")||"",placeholder:"",validate:r=>{if(e.commit_body.required&&!r)return"Please enter a description"}});s.isCancel(i)&&process.exit(0),y(o,"commit_body",i),t.body=i??""}if(e.commit_footer.enable){let i=k(o,"commit_footer").split(","),r=await s.multiselect({message:`Select optional footers ${x}`,initialValues:i||e.commit_footer.initial_value,options:D,required:!1});if(s.isCancel(r)&&process.exit(0),y(o,"commit_footer",r.join(",")),r.includes("breaking-change")){let n=await s.text({message:"Breaking changes: Write a short title / summary",placeholder:"",validate:d=>{if(!d)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Breaking Changes: Write a description & migration instructions ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.breaking_title=n,t.breaking_body=_}if(r.includes("deprecated")){let n=await s.text({message:"Deprecated: Write a short title / summary",placeholder:"",validate:d=>{if(!d)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Deprecated: Write a description ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.deprecates_body=_,t.deprecates_title=n}if(r.includes("closes")&&(t.closes="Closes:"),r.includes("custom")){let n=await s.text({message:"Write a custom footer",placeholder:""});s.isCancel(n)&&process.exit(0),t.custom_footer=n}r.includes("trailer")||(t.trailer="")}if(e.confirm_with_editor){let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r} --edit`,i),process.exit(0)}let p=!0;e.print_commit_output&&s.note(O(t,e,!0,!1,!0),"Commit Preview"),e.confirm_commit&&(p=await s.confirm({message:"Confirm Commit?"}),s.isCancel(p)&&process.exit(0)),p||(s.log.info("Exiting without commit"),process.exit(0));try{s.log.info("Committing changes...");let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r}`,i)}catch(i){s.log.error("Something went wrong when committing: "+i)}s.log.success("Commit Complete"),o.clear()}function O(e,t,o=!1,h=!1,u=!1){let a="";if(e.type&&(a+=o?c.blue(e.type):e.type),e.scope){let l=o?c.cyan(e.scope):e.scope;a+=`(${l})`}let p=e.ticket,i=t.check_ticket.surround;if(e.ticket&&i){let l=i.charAt(0),m=i.charAt(1);p=`${l}${e.ticket}${m}`}let r=t.check_ticket.title_position==="beginning";p&&t.check_ticket.add_to_title&&r&&(a=`${o?c.magenta(p):p} ${a}`);let n=t.check_ticket.title_position==="before-colon";if(p&&t.check_ticket.add_to_title&&n){let l=e.scope||e.type&&!t.check_ticket.surround?" ":"";a+=o?c.magenta(l+p):l+p}e.breaking_title&&t.breaking_change.add_exclamation_to_title&&(a+=o?c.red("!"):"!"),(e.scope||e.type||p&&n)&&(a+=": ");let _=t.check_ticket.title_position==="start",d=t.check_ticket.title_position==="end";if(p&&t.check_ticket.add_to_title&&_&&(a+=o?c.magenta(p)+" ":p+" "),e.title&&(a+=o?c.reset(e.title):e.title),p&&t.check_ticket.add_to_title&&d&&(a+=" "+(o?c.magenta(p):p)),e.body){let m=e.body.split("\\n").map(f=>o?c.reset(f.trim()):f.trim()).join(`
2
+ import{a as A,c as T,e as g,g as x,h as b,j as R,k as v,l as P,m as j,n as G,o as N,p as D,r as I,s as W,t as M,u as V,v as C,w as H,x as k,y}from"./chunk-ELYOZGPM.js";import*as s from"@clack/prompts";import l from"picocolors";import{execSync as w}from"child_process";import{chdir as q}from"process";import{parse as K}from"valibot";import{execSync as X}from"child_process";import*as $ from"@clack/prompts";import E from"picocolors";var L=["M","T","R","D","A","C"];function S(){let e="";try{e=X(`git ${g.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(u){return $.log.error(E.red("Failed to git status"+u)),{index:[],work_tree:[]}}let t=e.split(`
3
+ `),o=[],f=[];return t.forEach(u=>{let a=u.trimEnd();if(!a)return;let p=a.substring(2).trim(),h=a.charAt(0).trim(),i=a.charAt(1).trim();(h==="?"||i==="?")&&o.push(p),L.includes(h)&&f.push(p),L.includes(i)&&o.push(p)}),{index:f,work_tree:o}}function F(e){let t=e.join(" ");if(t)try{X(`git ${g.git_args} add ${t}`,{stdio:"pipe"}).toString(),$.log.success(E.green("Changes successfully staged"))}catch{$.log.error(E.red("Failed to stage changes"))}}import Y from"configstore";J(W());async function J(e){let t=K(T,{});q(V());let o=e.cache_last_value?new Y("better-commits"):I;if(e.check_status){let{index:i,work_tree:r}=S();s.log.step(l.black(l.bgGreen(" Checking Git Status ")));let n=i.reduce((c,m,d)=>l.green(c+m+C(i,d)),"");if(s.log.success(`Changes to be committed:
4
+ `+n),r.length){let c=r.reduce((d,U,B)=>l.red(d+U+C(r,B)),"");s.log.error(`Changes not staged for commit:
5
+ `+c);let m=await s.multiselect({message:`Some files have not been staged, would you like to add them now? ${x}`,options:[{value:".",label:"."},...r.map(d=>({value:d,label:d}))],required:!1});s.isCancel(m)&&process.exit(0),F(m)}S().index.length||(s.log.error(l.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}let f=e.commit_type.options.reduce((i,r)=>({...i,[r.value]:{emoji:r.emoji??"",trailer:r.trailer??""}}),{});if(e.commit_type.enable){let i="Select a commit type",r=e.commit_type.initial_value;if(e.commit_type.infer_type_from_branch){let _=e.commit_type.options.map(m=>m.value),c=M(_);c&&(i=`Commit type inferred from branch ${l.dim("(confirm / edit)")}`,r=c)}let n=await s.select({message:i,initialValue:k(o,"commit_type")||r,maxItems:e.commit_type.max_items,options:e.commit_type.options});s.isCancel(n)&&process.exit(0),y(o,"commit_type",n),t.trailer=f[n].trailer,t.type=e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="Start"?`${f[n].emoji} ${n}`.trim():n}if(e.commit_scope.enable){let i=await s.select({message:"Select a commit scope",initialValue:k(o,"commit_scope")||e.commit_scope.initial_value,maxItems:e.commit_scope.max_items,options:e.commit_scope.options});s.isCancel(i)&&process.exit(0),y(o,"commit_scope",i),i===A&&e.commit_scope.custom_scope&&(i=await s.text({message:"Write a custom scope",placeholder:""}),s.isCancel(i)&&process.exit(0)),t.scope=i}if(e.check_ticket.infer_ticket)try{let i=w(`git ${g.git_args} branch --show-current`,{stdio:"pipe"}).toString(),r=[i.match(P),i.match(j),i.match(R),i.match(G),i.match(v),i.match(N)].filter(n=>n!=null).map(n=>n&&n.length>=2?n[1]:"");r.length&&r[0]&&(t.ticket=e.check_ticket.append_hashtag||e.check_ticket.prepend_hashtag==="Prompt"?"#"+r[0]:r[0])}catch{}if(e.check_ticket.confirm_ticket){let i=await s.text({message:t.ticket?`Ticket / issue inferred from branch ${l.dim("(confirm / edit)")}`:`Add ticket / issue ${b}`,placeholder:"",initialValue:k(o,"commit_ticket")||t.ticket});s.isCancel(i)&&process.exit(0),y(o,"commit_ticket",i),t.ticket=i??""}e.check_ticket.prepend_hashtag==="Always"&&t.ticket&&!t.ticket.startsWith("#")&&(t.ticket="#"+t.ticket);let u=await s.text({message:"Write a brief title describing the commit",initialValue:k(o,"commit_title")||"",placeholder:"",validate:i=>{if(!i)return"Please enter a title";let r=t.scope?t.scope.length+2:0,n=t.type.length,_=e.check_ticket.add_to_title?t.ticket.length:0;if(r+n+_+i.length>e.commit_title.max_size)return`Exceeded max length. Title max [${e.commit_title.max_size}]`}});s.isCancel(u)&&process.exit(0),y(o,"commit_title",u);let a=u;if(e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="After-Colon"&&(a=`${f[t.type].emoji} ${u}`),t.title=H(a),e.commit_body.enable){let i=await s.text({message:`Write a detailed description of the changes ${b}`,initialValue:k(o,"commit_body")||"",placeholder:"",validate:r=>{if(e.commit_body.required&&!r)return"Please enter a description"}});s.isCancel(i)&&process.exit(0),y(o,"commit_body",i),t.body=i??""}if(e.commit_footer.enable){let i=k(o,"commit_footer").split(","),r=await s.multiselect({message:`Select optional footers ${x}`,initialValues:i||e.commit_footer.initial_value,options:D,required:!1});if(s.isCancel(r)&&process.exit(0),y(o,"commit_footer",r.join(",")),r.includes("breaking-change")){let n=await s.text({message:"Breaking changes: Write a short title / summary",placeholder:"",validate:c=>{if(!c)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Breaking Changes: Write a description & migration instructions ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.breaking_title=n,t.breaking_body=_}if(r.includes("deprecated")){let n=await s.text({message:"Deprecated: Write a short title / summary",placeholder:"",validate:c=>{if(!c)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Deprecated: Write a description ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.deprecates_body=_,t.deprecates_title=n}if(r.includes("closes")&&(t.closes="Closes:"),r.includes("custom")){let n=await s.text({message:"Write a custom footer",placeholder:""});s.isCancel(n)&&process.exit(0),t.custom_footer=n}r.includes("trailer")||(t.trailer="")}if(e.confirm_with_editor){let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r} --edit`,i),process.exit(0)}let p=!0;e.print_commit_output&&s.note(O(t,e,!0,!1,!0),"Commit Preview"),e.confirm_commit&&(p=await s.confirm({message:"Confirm Commit?"}),s.isCancel(p)&&process.exit(0)),p||(s.log.info("Exiting without commit"),process.exit(0));try{s.log.info("Committing changes...");let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r}`,i)}catch(i){s.log.error("Something went wrong when committing: "+i)}s.log.success("Commit Complete");let h=o.get("username");o.clear(),h&&o.set("username",h)}function O(e,t,o=!1,f=!1,u=!1){let a="";if(e.type&&(a+=o?l.blue(e.type):e.type),e.scope){let c=o?l.cyan(e.scope):e.scope;a+=`(${c})`}let p=e.ticket,h=t.check_ticket.surround;if(e.ticket&&h){let c=h.charAt(0),m=h.charAt(1);p=`${c}${e.ticket}${m}`}let i=t.check_ticket.title_position==="beginning";p&&t.check_ticket.add_to_title&&i&&(a=`${o?l.magenta(p):p} ${a}`);let r=t.check_ticket.title_position==="before-colon";if(p&&t.check_ticket.add_to_title&&r){let c=e.scope||e.type&&!t.check_ticket.surround?" ":"";a+=o?l.magenta(c+p):c+p}e.breaking_title&&t.breaking_change.add_exclamation_to_title&&(a+=o?l.red("!"):"!"),(e.scope||e.type||p&&r)&&(a+=": ");let n=t.check_ticket.title_position==="start",_=t.check_ticket.title_position==="end";if(p&&t.check_ticket.add_to_title&&n&&(a+=o?l.magenta(p)+" ":p+" "),e.title&&(a+=o?l.reset(e.title):e.title),p&&t.check_ticket.add_to_title&&_&&(a+=" "+(o?l.magenta(p):p)),e.body){let m=e.body.split("\\n").map(d=>o?l.reset(d.trim()):d.trim()).join(`
6
6
  `);a+=o?`
7
7
 
8
8
  ${m}`:`
9
9
 
10
- ${m}`}if(e.breaking_title){let l=o?c.red(`BREAKING CHANGE: ${e.breaking_title}`):`BREAKING CHANGE: ${e.breaking_title}`;a+=`
10
+ ${m}`}if(e.breaking_title){let c=o?l.red(`BREAKING CHANGE: ${e.breaking_title}`):`BREAKING CHANGE: ${e.breaking_title}`;a+=`
11
11
 
12
- ${l}`}if(e.breaking_body){let l=o?c.red(e.breaking_body):e.breaking_body;a+=`
12
+ ${c}`}if(e.breaking_body){let c=o?l.red(e.breaking_body):e.breaking_body;a+=`
13
13
 
14
- ${l}`}if(e.deprecates_title){let l=o?c.yellow(`DEPRECATED: ${e.deprecates_title}`):`DEPRECATED: ${e.deprecates_title}`;a+=`
14
+ ${c}`}if(e.deprecates_title){let c=o?l.yellow(`DEPRECATED: ${e.deprecates_title}`):`DEPRECATED: ${e.deprecates_title}`;a+=`
15
15
 
16
- ${l}`}if(e.deprecates_body){let l=o?c.yellow(e.deprecates_body):e.deprecates_body;a+=`
16
+ ${c}`}if(e.deprecates_body){let c=o?l.yellow(e.deprecates_body):e.deprecates_body;a+=`
17
17
 
18
- ${l}`}if(e.custom_footer){let m=e.custom_footer.split("\\n").map(f=>o?c.reset(f.trim()):f.trim()).join(`
18
+ ${c}`}if(e.custom_footer){let m=e.custom_footer.split("\\n").map(d=>o?l.reset(d.trim()):d.trim()).join(`
19
19
  `);a+=o?`
20
20
 
21
21
  ${m}`:`
22
22
 
23
23
  ${m}`}return e.closes&&e.ticket&&(a+=o?`
24
24
 
25
- ${c.reset(e.closes)} ${c.magenta(e.ticket)}`:`
25
+ ${l.reset(e.closes)} ${l.magenta(e.ticket)}`:`
26
26
 
27
27
  ${e.closes} ${e.ticket}`),u&&e.trailer&&(a+=o?`
28
28
 
29
- ${c.dim(e.trailer)}`:`
29
+ ${l.dim(e.trailer)}`:`
30
30
 
31
- ${e.trailer}`),h&&(a=a.replaceAll('"','\\"').replaceAll("`","\\`")),a}export{Y as main};
31
+ ${e.trailer}`),f&&(a=a.replaceAll('"','\\"').replaceAll("`","\\`")),a}export{J as main};
package/dist/init.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #! /usr/bin/env node
2
- import{b as r,f as e,u as i}from"./chunk-7K2QIDID.js";import*as t from"@clack/prompts";import c from"fs";import o from"picocolors";import{parse as l}from"valibot";try{console.clear(),t.intro(`${o.bgCyan(o.black(" better-commits-init "))}`);let s=`${i()}/${e}`,m=l(r,{});c.writeFileSync(s,JSON.stringify(m,null,4)),t.log.success(`${o.green("Successfully created .better-commits.json")}`),t.outro(`Run ${o.bgBlack(o.white("better-commits"))} to start the CLI`)}catch{t.log.error(`${o.red("Could not determine git root folder. better-commits-init must be used in a git repository")}`)}
2
+ import{b as r,f as e,u as i}from"./chunk-ELYOZGPM.js";import*as t from"@clack/prompts";import c from"fs";import o from"picocolors";import{parse as l}from"valibot";try{console.clear(),t.intro(`${o.bgCyan(o.black(" better-commits-init "))}`);let s=`${i()}/${e}`,m=l(r,{});c.writeFileSync(s,JSON.stringify(m,null,4)),t.log.success(`${o.green("Successfully created .better-commits.json")}`),t.outro(`Run ${o.bgBlack(o.white("better-commits"))} to start the CLI`)}catch{t.log.error(`${o.red("Could not determine git root folder. better-commits-init must be used in a git repository")}`)}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-commits",
3
3
  "private": false,
4
- "version": "1.17.1",
4
+ "version": "1.18.1",
5
5
  "description": "A CLI for creating better commits following the conventional commits specification",
6
6
  "author": "Erik Verduin (https://github.com/everduin94)",
7
7
  "type": "module",
package/readme.md CHANGED
@@ -42,16 +42,15 @@ npm install -g better-commits
42
42
 
43
43
  ## 🚀 Usage
44
44
 
45
- When you're ready to commit. To run the CLI in your terminal:
45
+ To run the CLI in your terminal:
46
46
 
47
47
  ```sh
48
- better-commits
49
- # or
50
- npx better-commits
48
+ better-commits # Create a new commit
49
+ better-branch # Create a new branch
51
50
  ```
52
51
 
53
- It will prompt a series of questions. These prompts will build a commit message, which you can preview, before confirming the commit.
54
- Some of the values in these prompts will be infered by your branch name and auto populated. You can adjust this in your `.better-commits.json` configuration file.
52
+ `better-commits` will prompt a series of questions. These prompts will build a commit message, which you can preview, before confirming the commit.
53
+ Some of the values in these prompts will be inferred by your branch name and auto populated. You can adjust this in your `.better-commits.json` configuration file.
55
54
 
56
55
  To better understand these prompts and their intention, read [Conventional Commits Summary](https://www.conventionalcommits.org/en/v1.0.0-beta.4/#summary)
57
56
 
@@ -73,8 +72,6 @@ To create a **repository-specific config**, navigate to the root of your project
73
72
 
74
73
  ### Options
75
74
 
76
- Better-commits (& better-branch) are highly flexible with sane defaults. These options allow you specify whats best for your workflow.
77
-
78
75
  > [!NOTE]<br>
79
76
  > All properties are optional and can be removed from the config. It will be replaced by the default at run-time.
80
77
  >
@@ -170,7 +167,7 @@ Better-commits (& better-branch) are highly flexible with sane defaults. These o
170
167
  "enable": true,
171
168
  "custom_scope": false,
172
169
  "initial_value": "app",
173
- "max_items": 20
170
+ "max_items": 20,
174
171
  "options": [
175
172
  {
176
173
  "value": "app",
@@ -251,7 +248,11 @@ Better-commits (& better-branch) are highly flexible with sane defaults. These o
251
248
  },
252
249
  "branch_action_default": "branch",
253
250
  "branch_order": ["user", "version", "type", "ticket", "description"],
254
- "enable_worktrees": true,
251
+ "worktrees": {
252
+ "enable": true,
253
+ "base_path": "..",
254
+ "folder_template": "{{repo_name}}-{{ticket}}-{{branch_description}}"
255
+ },
255
256
  "overrides": {
256
257
  "shell": "/bin/sh"
257
258
  }
@@ -323,28 +324,31 @@ Expand to see explanations and possible values
323
324
 
324
325
  Branch configuration (same config file, split for readability)
325
326
 
326
- | Property | Description |
327
- | ------------------------------- | --------------------------------------------------------- |
328
- | `branch_pre_commands` | Array of shell commands to run before branching |
329
- | `branch_post_commands` | Array of shell commands to run after branching |
330
- | `worktree_pre_commands` | Array of shell commands to run before creating worktree |
331
- | `worktree_post_commands` | Array of shell commands to run after creating worktree |
332
- | `branch_user.enable` | If enabled include user name |
333
- | `branch_user.required` | If enabled require user name |
334
- | `branch_user.separator` | Branch delimeter - "/" (default), "-", "\_" |
335
- | `branch_type.enable` | If enabled include type |
336
- | `branch_type.separator` | Branch delimeter - "/" (default), "-", "\_" |
337
- | `branch_ticket.enable` | If enabled include ticket |
338
- | `branch_ticket.required` | If enabled require ticket |
339
- | `branch_ticket.separator` | Branch delimeter - "/", "-" (default), "\_" |
340
- | `branch_description.max_length` | Max length branch name |
341
- | `branch_description.separator` | Branch delimeter - "" (default), "/", "-", "\_" |
342
- | `branch_version.enable` | If enabled include version |
343
- | `branch_version.required` | If enabled require version |
344
- | `branch_version.separator` | Branch delimeter - "", "/" (default), "-", "\_" |
345
- | `branch_order` | Order of branch name values (doesn't effect prompt order) |
346
- | `branch_action_default` | "branch" or "worktree" |
347
- | `enable_worktrees` | If false, always default to branch action |
327
+ | Property | Description |
328
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
329
+ | `branch_pre_commands` | Array of shell commands to run before branching |
330
+ | `branch_post_commands` | Array of shell commands to run after branching |
331
+ | `worktree_pre_commands` | Array of shell commands to run before creating worktree |
332
+ | `worktree_post_commands` | Array of shell commands to run after creating worktree |
333
+ | `branch_user.enable` | If enabled include user name |
334
+ | `branch_user.required` | If enabled require user name |
335
+ | `branch_user.separator` | Branch delimeter - "/" (default), "-", "\_" |
336
+ | `branch_type.enable` | If enabled include type |
337
+ | `branch_type.separator` | Branch delimeter - "/" (default), "-", "\_" |
338
+ | `branch_ticket.enable` | If enabled include ticket |
339
+ | `branch_ticket.required` | If enabled require ticket |
340
+ | `branch_ticket.separator` | Branch delimeter - "/", "-" (default), "\_" |
341
+ | `branch_description.max_length` | Max length branch name |
342
+ | `branch_description.separator` | Branch delimeter - "" (default), "/", "-", "\_" |
343
+ | `branch_version.enable` | If enabled include version |
344
+ | `branch_version.required` | If enabled require version |
345
+ | `branch_version.separator` | Branch delimeter - "", "/" (default), "-", "\_" |
346
+ | `branch_order` | Order of branch name values (doesn't effect prompt order) |
347
+ | `branch_action_default` | "branch" or "worktree" |
348
+ | `enable_worktrees` | `Deprecated` see `worktrees.enable` |
349
+ | `worktrees.enable` | If false, always default to branch action |
350
+ | `worktrees.base_path` | Directory where worktrees are created (default: "..") |
351
+ | `worktrees.folder_template` | Template for worktree folder names with variables like {{repo_name}}, {{branch_description}}, {{user}}, {{type}}, {{ticket}}, {{version}} |
348
352
 
349
353
  </details>
350
354
 
@@ -362,16 +366,13 @@ Branch configuration (same config file, split for readability)
362
366
 
363
367
  ## 🌳 Better Branch
364
368
 
365
- > [!NOTE]<br>
366
- > Using `better-branch` with `better-commits` can supercharge your git workflow.
367
- > Make sure to try it out!
368
-
369
369
  Better branch is a secondary feature that works with better commits
370
370
 
371
371
  - Supports consistent branch naming conventions
372
372
  - Uses same type-list/prompt from your config
373
373
  - Enables better-commits to infer type & ticket
374
374
  - Caches your username for speedy branching
375
+ - Convenient worktree creation
375
376
 
376
377
  To run the CLI in your terminal:
377
378
 
@@ -381,13 +382,14 @@ better-branch
381
382
 
382
383
  ### Worktree Support
383
384
 
384
- `better-branch` will prompt for **Branch** or **Worktree**. Creating a **Worktree** with `better-branch` is a great way to create worktrees while maintaining consistent branch naming conventions.
385
-
386
- The worktree flow creates a folder/worktree with your **branch description** and a git branch inside with your **full branch name**.
385
+ `better-branch` will prompt for **Branch** or **Worktree**. The Worktree flow creates a folder/worktree from your **branch description** and a git branch inside with your **full branch name**.
387
386
 
388
387
  > [!NOTE]<br>
389
388
  > Creating a worktree named `everduin94/feat/TAC-123-add-worktrees` with the native git command would create a nested folder for each `/`. `better-branch` removes the hassle by creating 1 folder while still using the full name for the branch.
390
389
 
390
+ > [!TIP]
391
+ > By default, `better-branch` will create **worktrees** as a sibling folder. To change this, see `worktrees.base_path`.
392
+
391
393
  ### Pre/Post Branch Checkout Hooks
392
394
 
393
395
  Optionally configure pre and post checkout commands, for example:
@@ -419,7 +421,7 @@ If you're using Github issues to track your work, and select the `closes` footer
419
421
 
420
422
  `better-commits` can append a commit trailer per commit type. This allows you to [automate change logs](https://docs.gitlab.com/ee/user/project/changelogs.html) with tools like Gitlab.
421
423
 
422
- ### Fun Facts
424
+ ### Misc
423
425
 
424
426
  `better-commits` uses native `git` commands under the hood. So any hooks, tools, or staging should work as if it was a normal commit.
425
427
 
@@ -428,9 +430,6 @@ Setting `confirm_with_editor=true` will allow you to edit/confirm a commit with
428
430
  - For example, to edit with Neovim: `git config --global core.editor "nvim"`
429
431
  - For VS Code, `git config --global core.editor "code -n --wait"`
430
432
 
431
- > [!NOTE]<br>
432
- > Enjoy learning, open source technology, and note-taking? [Join our Discord!](https://discord.gg/grHVnZwYup)
433
-
434
433
  You can add this badge to your repository to display that you're using a better-commits repository config
435
434
 
436
435
  | Markdown | Result |
package/src/branch.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  CACHE_PROMPT,
18
18
  OPTIONAL_PROMPT,
19
19
  load_setup,
20
+ get_git_root,
20
21
  } from "./utils";
21
22
  import { flags } from "./args";
22
23
 
@@ -24,9 +25,10 @@ main(load_setup(" better-branch "));
24
25
 
25
26
  async function main(config: Output<typeof Config>) {
26
27
  const branch_state = parse(BranchState, {});
28
+ chdir(get_git_root());
27
29
 
28
30
  let checkout_type: Output<typeof V_BRANCH_ACTIONS> = "branch";
29
- if (config.enable_worktrees) {
31
+ if (config.worktrees.enable) {
30
32
  const branch_or_worktree = await p.select({
31
33
  message: `Checkout a branch or create a worktree?`,
32
34
  initialValue: config.branch_action_default,
@@ -140,8 +142,7 @@ async function main(config: Output<typeof Config>) {
140
142
  }
141
143
  } else {
142
144
  try {
143
- const ticket = branch_state.ticket ? `${branch_state.ticket}-` : "";
144
- const worktree_name = `${ticket}${branch_state.description}`;
145
+ const worktree_name = build_worktree_path(branch_state, config);
145
146
  execSync(
146
147
  `git worktree add ${worktree_name} ${branch_flag} ${branch_name}`,
147
148
  {
@@ -194,6 +195,32 @@ function build_branch(
194
195
  return res.trim();
195
196
  }
196
197
 
198
+ function build_worktree_path(
199
+ branch_state: Output<typeof BranchState>,
200
+ config: Output<typeof Config>,
201
+ ): string {
202
+ const gitRoot = get_git_root();
203
+ const repo_name = gitRoot.split("/").pop() || "repo";
204
+
205
+ let worktree_name = config.worktrees.folder_template;
206
+
207
+ worktree_name = worktree_name
208
+ .replace("{{repo_name}}", repo_name)
209
+ .replace("{{branch_description}}", branch_state.description)
210
+ .replace("{{user}}", branch_state.user || "")
211
+ .replace("{{type}}", branch_state.type || "")
212
+ .replace("{{ticket}}", branch_state.ticket || "")
213
+ .replace("{{version}}", branch_state.version || "");
214
+
215
+ worktree_name = worktree_name
216
+ .replace(/\s/g, "")
217
+ .replace(/--+/g, "-")
218
+ .replace(/^-+|-+$/g, "");
219
+
220
+ const base_path = config.worktrees.base_path;
221
+ return `${base_path}${base_path.endsWith("/") ? "" : "/"}${worktree_name}`;
222
+ }
223
+
197
224
  function get_user_from_cache(): string {
198
225
  try {
199
226
  const config_store = new Configstore("better-commits");
package/src/index.ts CHANGED
@@ -358,7 +358,11 @@ export async function main(config: Output<typeof Config>) {
358
358
  p.log.error("Something went wrong when committing: " + err);
359
359
  }
360
360
  p.log.success("Commit Complete");
361
+
362
+ // Instead of deleting individual keys, just get what we need and clear.
363
+ const user_name = prompt_cache.get("username");
361
364
  prompt_cache.clear();
365
+ if (user_name) prompt_cache.set("username", user_name);
362
366
  }
363
367
 
364
368
  function build_commit_string(
@@ -211,6 +211,17 @@ export const Config = v.object({
211
211
  branch_action_default: v.optional(V_BRANCH_ACTIONS, "branch"),
212
212
  branch_order: v.optional(v.array(V_BRANCH_FIELDS), BRANCH_ORDER_DEFAULTS),
213
213
  enable_worktrees: v.optional(v.boolean(), true),
214
+ worktrees: v.optional(
215
+ v.object({
216
+ enable: v.optional(v.boolean(), true),
217
+ base_path: v.optional(v.string(), ".."),
218
+ folder_template: v.optional(
219
+ v.string(),
220
+ "{{repo_name}}-{{ticket}}-{{branch_description}}",
221
+ ),
222
+ }),
223
+ {},
224
+ ),
214
225
  overrides: v.optional(
215
226
  v.object({
216
227
  shell: v.optional(v.string()),