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 +4 -4
- package/dist/{chunk-EANV5ZZP.js → chunk-5EGZQSNM.js} +1 -1
- package/dist/{chunk-2JVEMMKH.js → chunk-F4EBQBBK.js} +9 -2
- package/dist/index.js +28 -24
- package/dist/init.js +1 -1
- package/package.json +2 -2
- package/readme.md +5 -0
- package/src/default-config-template.ts +8 -1
- package/src/prompts/autocomplete-multiselect.ts +232 -0
- package/src/prompts/branch-type.prompt.ts +4 -1
- package/src/prompts/commit-scope.prompt.ts +4 -1
- package/src/prompts/commit-status.prompt.ts +14 -11
- package/src/prompts/commit-type.prompt.ts +4 -1
- package/src/utils/messages.ts +1 -1
- package/src/valibot-state.ts +5 -4
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-
|
|
3
|
-
`)}function M(
|
|
4
|
-
${c.green("\uF489 better-branch")} ${c.gray("v"+
|
|
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=[
|
|
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-
|
|
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
|
|
3
|
-
`):t}#
|
|
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
|
-
${
|
|
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
|
-
${
|
|
8
|
+
${l}`}if(i.breaking_body){let l=e?u.red(i.breaking_body):i.breaking_body;r+=`
|
|
9
9
|
|
|
10
|
-
${
|
|
10
|
+
${l}`}if(i.deprecates_title){let l=e?u.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
|
|
11
11
|
|
|
12
|
-
${
|
|
12
|
+
${l}`}if(i.deprecates_body){let l=e?u.yellow(i.deprecates_body):i.deprecates_body;r+=`
|
|
13
13
|
|
|
14
|
-
${
|
|
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
|
-
${
|
|
17
|
+
${O}`}return i.closes&&i.ticket&&(r+=e?`
|
|
18
18
|
|
|
19
|
-
${
|
|
19
|
+
${u.reset(i.closes)} ${u.magenta(i.ticket)}`:`
|
|
20
20
|
|
|
21
|
-
${i.closes} ${i.ticket}`),
|
|
21
|
+
${i.closes} ${i.ticket}`),s&&i.trailer&&(r+=e?`
|
|
22
22
|
|
|
23
|
-
${
|
|
23
|
+
${u.dim(i.trailer)}`:`
|
|
24
24
|
|
|
25
|
-
${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}var
|
|
26
|
-
`),e=[],o=[];return t.forEach(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`)}
|
|
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(
|
|
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
|
-
${
|
|
44
|
+
${a}
|
|
41
45
|
|
|
42
46
|
${_.gray("Scopes")}
|
|
43
|
-
${
|
|
47
|
+
${m}
|
|
44
48
|
|
|
45
49
|
${_.gray("CLI FLAGS")}
|
|
46
|
-
${
|
|
50
|
+
${C}
|
|
47
51
|
|
|
48
52
|
${_.gray("Commit Flags")}
|
|
49
|
-
${
|
|
53
|
+
${b}
|
|
50
54
|
|
|
51
55
|
${_.gray("Git Flags (Advanced)")}
|
|
52
|
-
${
|
|
56
|
+
${x}
|
|
53
57
|
|
|
54
58
|
${_.gray("ADDITIONAL COMMANDS")}
|
|
55
|
-
${
|
|
59
|
+
${V}
|
|
56
60
|
|
|
57
|
-
`)}var
|
|
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-
|
|
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.
|
|
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": "^
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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 = (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
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,
|
package/src/utils/messages.ts
CHANGED
|
@@ -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
|
|
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 {
|
package/src/valibot-state.ts
CHANGED
|
@@ -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), {});
|