better-commits 1.23.2 โ 1.24.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 +19 -19
- package/dist/index.js +31 -53
- package/dist/init.js +1 -1
- package/dist/messages-ZJeoTfy2.js +1 -0
- package/dist/utils-CeUs4BjU.js +259 -0
- package/package.json +18 -12
- package/readme.md +4 -2
- package/.better-commits.json +0 -52
- package/.github/workflows/publish.yml +0 -34
- package/.github/workflows/test.yml +0 -27
- package/.prettierignore +0 -5
- package/.prettierrc +0 -1
- package/dist/chunk-43H72S6V.js +0 -1
- package/dist/chunk-B7AGSPP3.js +0 -261
- package/src/args.test.ts +0 -128
- package/src/args.ts +0 -125
- package/src/branch-args.test.ts +0 -75
- package/src/branch-args.ts +0 -107
- package/src/branch-help.ts +0 -125
- package/src/branch.ts +0 -97
- package/src/default-config-template.ts +0 -258
- package/src/git.test.ts +0 -64
- package/src/git.ts +0 -72
- package/src/help.ts +0 -138
- package/src/index.test.ts +0 -7
- package/src/index.ts +0 -101
- package/src/init.test.ts +0 -123
- package/src/init.ts +0 -46
- package/src/prompts/autocomplete-multiselect.test.ts +0 -129
- package/src/prompts/autocomplete-multiselect.ts +0 -249
- package/src/prompts/branch-checkout.prompt.ts +0 -36
- package/src/prompts/branch-confirm.prompt.test.ts +0 -89
- package/src/prompts/branch-confirm.prompt.ts +0 -149
- package/src/prompts/branch-description.prompt.ts +0 -37
- package/src/prompts/branch-runnable.ts +0 -13
- package/src/prompts/branch-scope.prompt.ts +0 -59
- package/src/prompts/branch-ticket.prompt.ts +0 -41
- package/src/prompts/branch-type.prompt.ts +0 -46
- package/src/prompts/branch-user.prompt.ts +0 -50
- package/src/prompts/branch-version.prompt.ts +0 -41
- package/src/prompts/commit-body.prompt.ts +0 -51
- package/src/prompts/commit-confirm.prompt.ts +0 -123
- package/src/prompts/commit-footer.prompt.ts +0 -195
- package/src/prompts/commit-scope.prompt.ts +0 -91
- package/src/prompts/commit-status.prompt.ts +0 -66
- package/src/prompts/commit-ticket.prompt.ts +0 -82
- package/src/prompts/commit-title.prompt.ts +0 -98
- package/src/prompts/commit-type.prompt.ts +0 -96
- package/src/prompts/runnable.ts +0 -13
- package/src/utils/build-branch.test.ts +0 -159
- package/src/utils/build-branch.ts +0 -48
- package/src/utils/build-commit-string.test.ts +0 -273
- package/src/utils/build-commit-string.ts +0 -163
- package/src/utils/commit-title-size.ts +0 -24
- package/src/utils/infer.test.ts +0 -174
- package/src/utils/infer.ts +0 -160
- package/src/utils/messages.ts +0 -25
- package/src/utils/no-interactive-branch-validation.test.ts +0 -193
- package/src/utils/no-interactive-validation.test.ts +0 -174
- package/src/utils/no-interactive-validation.ts +0 -213
- package/src/utils.test.ts +0 -164
- package/src/utils.ts +0 -235
- package/src/valibot-consts.ts +0 -117
- package/src/valibot-state.test.ts +0 -57
- package/src/valibot-state.ts +0 -276
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -12
- package/vitest.config.ts +0 -8
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import*as e from"@clack/prompts";import*as t from"valibot";import{ValiError as n,parse as r}from"valibot";import{execSync as i}from"child_process";import a from"fs";import{homedir as o}from"os";import{parse as s}from"jsonc-parser";import c from"picocolors";import{parse as l}from"@bomb.sh/args";const u=`custom`,d=[`closes`,`trailer`,`breaking-change`,`deprecated`,`custom`],f=t.picklist([`branch`,`worktree`]),p=t.picklist([`closes`,`trailer`,`breaking-change`,`deprecated`,`custom`]),m=t.picklist([`user`,`version`,`type`,`scope`,`ticket`,`description`]);t.picklist([`branch_user`,`branch_version`,`branch_type`,`branch_scope`,`branch_ticket`,`branch_description`]);const h=[`user`,`version`,`type`,`ticket`,`scope`,`description`],g=[{value:`app`,label:`app`},{value:`shared`,label:`shared`},{value:`server`,label:`server`},{value:`tools`,label:`tools`},{value:``,label:`none`}],_=t.pipe(t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.string(),`feat`),max_items:t.optional(t.pipe(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`),autocomplete:t.optional(t.boolean(),!0),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string()),emoji:t.optional(t.pipe(t.string(),t.emoji())),trailer:t.optional(t.string())})),[{value:`feat`,label:`feat`,hint:`A new feature`,emoji:`๐`,trailer:`Changelog: feature`},{value:`fix`,label:`fix`,hint:`A bug fix`,emoji:`๐`,trailer:`Changelog: fix`},{value:`docs`,label:`docs`,hint:`Documentation only changes`,emoji:`๐`,trailer:`Changelog: documentation`},{value:`refactor`,label:`refactor`,hint:`A code change that neither fixes a bug nor adds a feature`,emoji:`๐จ`,trailer:`Changelog: refactor`},{value:`perf`,label:`perf`,hint:`A code change that improves performance`,emoji:`๐`,trailer:`Changelog: performance`},{value:`test`,label:`test`,hint:`Adding missing tests or correcting existing tests`,emoji:`๐จ`,trailer:`Changelog: test`},{value:`build`,label:`build`,hint:`Changes that affect the build system or external dependencies`,emoji:`๐ง`,trailer:`Changelog: build`},{value:`ci`,label:`ci`,hint:`Changes to our CI configuration files and scripts`,emoji:`๐ค`,trailer:`Changelog: ci`},{value:`chore`,label:`chore`,hint:`Other changes that do not modify src or test files`,emoji:`๐งน`,trailer:`Changelog: chore`},{value:``,label:`none`}])}),{}),t.rawCheck(({dataset:e,addIssue:t})=>{e.typed&&!e.value.options.some(t=>t.value===e.value.initial_value)&&t({message:`Type: initial_value "${e.value.initial_value}" must exist in options`})}),t.transform(e=>({...e,options:e.options.map(t=>({...t,label:t.emoji&&e.append_emoji_to_label?`${t.emoji} ${t.label}`:t.label}))}))),v=t.pipe(t.optional(t.object({enable:t.optional(t.boolean(),!0),custom_scope:t.optional(t.boolean(),!1),max_items:t.optional(t.pipe(t.number(),t.minValue(1)),20),initial_value:t.optional(t.string(),`app`),infer_scope_from_branch:t.optional(t.boolean(),!0),autocomplete:t.optional(t.boolean(),!0),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string())})),g)}),{}),t.rawCheck(({dataset:e,addIssue:t})=>{if(!e.typed)return;let n=e.value.options.map(e=>e.value);e.value.custom_scope&&n.push(u),n.includes(e.value.initial_value)||t({message:`Scope: initial_value "${e.value.initial_value}" must exist in options`})}),t.transform(e=>{let t=e.options.map(e=>e.value);return e.custom_scope&&!t.includes(`custom`)?{...e,options:[...e.options,{label:u,value:u,hint:`Write a custom scope`}]}:e})),y=t.object({check_status:t.optional(t.boolean(),!0),check_status_autocomplete:t.optional(t.boolean(),!0),commit_type:_,commit_scope:v,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.pipe(t.number(),t.minValue(1)),70)}),{}),commit_body:t.optional(t.object({enable:t.optional(t.boolean(),!0),required:t.optional(t.boolean(),!1),split_by_period:t.optional(t.boolean(),!1)}),{}),commit_footer:t.optional(t.object({enable:t.optional(t.boolean(),!0),initial_value:t.optional(t.array(p),[]),options:t.optional(t.array(p),d)}),{}),breaking_change:t.optional(t.object({add_exclamation_to_title:t.optional(t.boolean(),!0)}),{}),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([`/`,`-`,`_`]),`/`),autocomplete:t.optional(t.boolean(),!0)}),{}),branch_scope:t.optional(t.object({enable:t.optional(t.boolean(),!0),separator:t.optional(t.picklist([`/`,`-`,`_`]),`-`),autocomplete:t.optional(t.boolean(),!0)}),{}),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.pipe(t.number(),t.minValue(1)),70),separator:t.optional(t.picklist([``,`/`,`-`,`_`]),``)}),{}),branch_action_default:t.optional(f,`branch`),branch_order:t.optional(t.array(m),h),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())}),{})}),b={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(),``)},x=t.optional(t.object(b),{}),S={user:t.optional(t.string(),``),type:t.optional(t.string(),``),scope:t.optional(t.string(),``),ticket:t.optional(t.string(),``),description:t.optional(t.string(),``),version:t.optional(t.string(),``),checkout:t.optional(f,`branch`)},C=t.optional(t.object(S),{}),w=[`type`,`scope`,`title`,`body`,`ticket`,`closes`,`trailer`,`breaking-title`,`breaking-body`,`deprecates-title`,`deprecates-body`,`custom-footer`],T=[`git-dir`,`work-tree`],E=[`interactive`,`dry-run`,`help`,`version`],D=new class{#e;constructor(e){this.#e=e}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}}(O(process.argv.slice(2)));function O(e){let t=l(e,{alias:{h:`help`,v:`version`},boolean:E,string:[...w,...T]}),n={};return w.forEach(e=>{let r=t[e],i=k(e,r);if(i!==void 0){let t=e.replace(`-`,`_`);n[t]=i}}),{help:t.help===!0,version:t.version===!0,git_args:A(t[`git-dir`],t[`work-tree`]),no_interactive:t.interactive===!1,dry_run:t[`dry-run`]===!0,commit_state:n}}function k(e,t){if(t===void 0)return;if(e!==`closes`)return t;let n=t.trim().toLowerCase();if(n!==`false`&&(t===``||n))return`Closes:`}function A(e,t){return`${e?`--git-dir=${e}`:``} ${t?`--work-tree=${t}`:``}`.trim()}const j=`{
|
|
2
|
+
// Run interactive \`git status\` before composing a commit
|
|
3
|
+
"check_status": true,
|
|
4
|
+
"check_status_autocomplete": true,
|
|
5
|
+
|
|
6
|
+
/* COMMIT FIELDS */
|
|
7
|
+
"commit_type": {
|
|
8
|
+
"enable": true,
|
|
9
|
+
|
|
10
|
+
// Default selected type from options
|
|
11
|
+
"initial_value": "feat",
|
|
12
|
+
|
|
13
|
+
"max_items": 20,
|
|
14
|
+
|
|
15
|
+
// Infer type from the current branch name: user/TYPE/my-branch
|
|
16
|
+
"infer_type_from_branch": true,
|
|
17
|
+
|
|
18
|
+
// Include emoji in prompt label
|
|
19
|
+
"append_emoji_to_label": false,
|
|
20
|
+
|
|
21
|
+
// Include emoji from prompt label in commit message
|
|
22
|
+
"append_emoji_to_commit": false,
|
|
23
|
+
|
|
24
|
+
// "Start" | "After-Colon"
|
|
25
|
+
"emoji_commit_position": "Start",
|
|
26
|
+
|
|
27
|
+
"autocomplete": true,
|
|
28
|
+
|
|
29
|
+
"options": [
|
|
30
|
+
{
|
|
31
|
+
"value": "feat",
|
|
32
|
+
"label": "feat",
|
|
33
|
+
"hint": "A new feature",
|
|
34
|
+
"emoji": "๐",
|
|
35
|
+
"trailer": "Changelog: feature"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"value": "fix",
|
|
39
|
+
"label": "fix",
|
|
40
|
+
"hint": "A bug fix",
|
|
41
|
+
"emoji": "๐",
|
|
42
|
+
"trailer": "Changelog: fix"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"value": "docs",
|
|
46
|
+
"label": "docs",
|
|
47
|
+
"hint": "Documentation only changes",
|
|
48
|
+
"emoji": "๐",
|
|
49
|
+
"trailer": "Changelog: documentation"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"value": "refactor",
|
|
53
|
+
"label": "refactor",
|
|
54
|
+
"hint": "A code change that neither fixes a bug nor adds a feature",
|
|
55
|
+
"emoji": "๐จ",
|
|
56
|
+
"trailer": "Changelog: refactor"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"value": "perf",
|
|
60
|
+
"label": "perf",
|
|
61
|
+
"hint": "A code change that improves performance",
|
|
62
|
+
"emoji": "๐",
|
|
63
|
+
"trailer": "Changelog: performance"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"value": "test",
|
|
67
|
+
"label": "test",
|
|
68
|
+
"hint": "Adding missing tests or correcting existing tests",
|
|
69
|
+
"emoji": "๐จ",
|
|
70
|
+
"trailer": "Changelog: test"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"value": "build",
|
|
74
|
+
"label": "build",
|
|
75
|
+
"hint": "Changes that affect the build system or external dependencies",
|
|
76
|
+
"emoji": "๐ง",
|
|
77
|
+
"trailer": "Changelog: build"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"value": "ci",
|
|
81
|
+
"label": "ci",
|
|
82
|
+
"hint": "Changes to our CI configuration files and scripts",
|
|
83
|
+
"emoji": "๐ค",
|
|
84
|
+
"trailer": "Changelog: ci"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"value": "chore",
|
|
88
|
+
"label": "chore",
|
|
89
|
+
"hint": "Other changes that do not modify src or test files",
|
|
90
|
+
"emoji": "๐งน",
|
|
91
|
+
"trailer": "Changelog: chore"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"value": "",
|
|
95
|
+
"label": "none"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
"commit_scope": {
|
|
101
|
+
"enable": true,
|
|
102
|
+
|
|
103
|
+
// If true, users can type a scope not listed in options
|
|
104
|
+
"custom_scope": false,
|
|
105
|
+
|
|
106
|
+
// Default selected scope from options
|
|
107
|
+
"initial_value": "app",
|
|
108
|
+
|
|
109
|
+
// Infer scope from the current branch name: user/type/ticket-SCOPE-my-branch
|
|
110
|
+
"infer_scope_from_branch": true,
|
|
111
|
+
|
|
112
|
+
"max_items": 20,
|
|
113
|
+
"autocomplete": true,
|
|
114
|
+
"options": [
|
|
115
|
+
{ "value": "app", "label": "app" },
|
|
116
|
+
{ "value": "shared", "label": "shared" },
|
|
117
|
+
{ "value": "server", "label": "server" },
|
|
118
|
+
{ "value": "tools", "label": "tools" },
|
|
119
|
+
{ "value": "", "label": "none" }
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
"check_ticket": {
|
|
124
|
+
// Infer ticket / issue from the branch name - user/type/TICKET-my-branch
|
|
125
|
+
"infer_ticket": true,
|
|
126
|
+
|
|
127
|
+
// Prompt for confirmation / edit before using an inferred ticket
|
|
128
|
+
"confirm_ticket": true,
|
|
129
|
+
|
|
130
|
+
// Add the ticket to the commit title - feat(app): TICKET my commit title
|
|
131
|
+
"add_to_title": true,
|
|
132
|
+
|
|
133
|
+
// Deprecated, prefer \`prepend_hashtag\`
|
|
134
|
+
"append_hashtag": false,
|
|
135
|
+
|
|
136
|
+
// "Never" | "Prompt" | "Always" - 12345 --> #12345
|
|
137
|
+
"prepend_hashtag": "Never",
|
|
138
|
+
|
|
139
|
+
// Wrap the ticket in the commit title: "" | "[]" | "()" | "{}"
|
|
140
|
+
"surround": "",
|
|
141
|
+
|
|
142
|
+
// "start" | "end" | "before-colon" | "beginning"
|
|
143
|
+
"title_position": "start"
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
"commit_title": {
|
|
147
|
+
// Includes total size of title + type + scope + ticket
|
|
148
|
+
"max_size": 70
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
"commit_body": {
|
|
152
|
+
"enable": true,
|
|
153
|
+
"required": false,
|
|
154
|
+
|
|
155
|
+
// Split sentences into multiple lines automatically
|
|
156
|
+
"split_by_period": false
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
"commit_footer": {
|
|
160
|
+
"enable": true,
|
|
161
|
+
"initial_value": [],
|
|
162
|
+
|
|
163
|
+
// "closes", "trailer", "breaking-change", "deprecated", "custom"
|
|
164
|
+
"options": ["closes", "trailer", "breaking-change", "deprecated", "custom"]
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
"breaking_change": {
|
|
168
|
+
// Adds \`!\` to the commit title when a breaking change is selected
|
|
169
|
+
"add_exclamation_to_title": true
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
// Confirm / edit with $GIT_EDITOR or $EDITOR
|
|
173
|
+
"confirm_with_editor": false,
|
|
174
|
+
|
|
175
|
+
// Show a final confirmation prompt before running git commit
|
|
176
|
+
"confirm_commit": true,
|
|
177
|
+
|
|
178
|
+
// Reuse the last known value from a previous canceled or failed commit
|
|
179
|
+
"cache_last_value": true,
|
|
180
|
+
|
|
181
|
+
// Pretty-print the final commit preview before execution
|
|
182
|
+
"print_commit_output": true,
|
|
183
|
+
|
|
184
|
+
/* BRANCH FIELDS */
|
|
185
|
+
// Optional shell commands to run before / after creating branches or worktrees
|
|
186
|
+
"branch_pre_commands": [],
|
|
187
|
+
"branch_post_commands": [],
|
|
188
|
+
"worktree_pre_commands": [],
|
|
189
|
+
"worktree_post_commands": [],
|
|
190
|
+
|
|
191
|
+
"branch_user": {
|
|
192
|
+
"enable": true,
|
|
193
|
+
"required": false,
|
|
194
|
+
|
|
195
|
+
// "/" | "-" | "_" - user/feat/my-branch
|
|
196
|
+
"separator": "/"
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
"branch_type": {
|
|
200
|
+
"enable": true,
|
|
201
|
+
"separator": "/",
|
|
202
|
+
"autocomplete": true,
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
"branch_scope": {
|
|
206
|
+
"enable": true,
|
|
207
|
+
"separator": "-",
|
|
208
|
+
"autocomplete": true,
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
"branch_ticket": {
|
|
212
|
+
"enable": true,
|
|
213
|
+
"required": false,
|
|
214
|
+
"separator": "-"
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
"branch_version": {
|
|
218
|
+
"enable": false,
|
|
219
|
+
"required": false,
|
|
220
|
+
"separator": "/"
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
"branch_description": {
|
|
224
|
+
// Maximum length for the description segment of the branch name
|
|
225
|
+
"max_length": 70,
|
|
226
|
+
|
|
227
|
+
// Allowed values: "" | "/" | "-" | "_"
|
|
228
|
+
"separator": ""
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
// "branch" | "worktree"
|
|
232
|
+
"branch_action_default": "branch",
|
|
233
|
+
|
|
234
|
+
// Order of values in the final branch name
|
|
235
|
+
"branch_order": ["user", "version", "type", "ticket", "scope", "description"],
|
|
236
|
+
|
|
237
|
+
// Deprecated, prefer \`worktrees.enable\`
|
|
238
|
+
"enable_worktrees": true,
|
|
239
|
+
|
|
240
|
+
"worktrees": {
|
|
241
|
+
// If false, always create a branch instead of prompting for a worktree
|
|
242
|
+
"enable": true,
|
|
243
|
+
|
|
244
|
+
// Directory where worktrees are created
|
|
245
|
+
"base_path": "..",
|
|
246
|
+
|
|
247
|
+
// Available template variables include:
|
|
248
|
+
// {{repo_name}}, {{branch_description}}, {{user}}, {{type}}, {{scope}}, {{ticket}}, {{version}}
|
|
249
|
+
"folder_template": "{{repo_name}}-{{ticket}}-{{branch_description}}"
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
/* OTHER FIELDS */
|
|
253
|
+
"overrides": {
|
|
254
|
+
// Useful on Windows or for shells with different multiline behavior
|
|
255
|
+
"shell": "/bin/sh"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
`,M=[`.better-commits.jsonc`,`.better-commits.json`],N=M[0],P=[{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`}],F=[{value:`branch`,label:`Branch`},{value:`worktree`,label:`Worktree`}],I={get:()=>``,set:(e,t)=>{},clear:()=>{}};function L(t=` better-commits `,n=D.git_args){console.clear(),e.intro(`${c.bgCyan(c.black(t))}`);let i=null,o=V();a.existsSync(o)&&(i=R(o));let s=H(B(n));if(s){e.log.step(`Reading from Repository Config`);let t=R(s);return{config:i?{...t,overrides:i.overrides.shell?i.overrides:t.overrides,confirm_with_editor:i.confirm_with_editor,cache_last_value:i.cache_last_value}:t,config_source:`repository`}}if(i)return e.log.step(`Reading from Global Config`),{config:i,config_source:`global`};let l=r(y,{});return e.log.step(`Config not found. Generating default ${N} at $HOME`),a.writeFileSync(o,j),{config:l,config_source:`none`}}function R(t){let n=null;try{n=s(a.readFileSync(t,`utf8`))}catch(n){e.log.error(`Invalid JSON/JSONC config file at ${t}. Exiting.\n`+n),process.exit(0)}return z(n)}function z(t){try{return r(y,t)}catch(t){if(t instanceof n){let n=(t.issues[0].path??[]).map(e=>e.key).filter(e=>typeof e==`string`||typeof e==`number`).join(`.`);e.log.error(`Invalid Configuration: ${c.red(n)}\n`+t.message)}process.exit(0)}}function B(t=D.git_args){let n=`.`;try{n=i(`git ${t} rev-parse --show-toplevel`).toString().trim()}catch{e.log.warn(`Could not find git root. If in a --bare repository, ignore this warning.`)}return n}function V(){return U(o())??o()+`/`+N}function H(e){return U(e)}function U(e){for(let t of M){let n=`${e}/${t}`;if(a.existsSync(n))return n}return null}function W(){try{return JSON.parse(a.readFileSync(new URL(`../package.json`,import.meta.url),`utf8`)).version??`unknown`}catch{return`unknown`}}function G(e,t){return t===e.length-1?``:`
|
|
259
|
+
`}function K(e){let t=e.trim();return t.endsWith(`.`)?t.substring(0,t.length-1).trim():e.trim()}function q(t,n){try{return t.get(n)??``}catch{e.log.warn(`Could not access ${n} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}return``}function J(t,n,r){try{t.set(n,r)}catch{e.log.warn(`Could not access ${n} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}}export{b as _,G as a,W as c,L as d,J as f,C as g,S as h,I as i,H as l,D as m,P as n,K as o,j as p,N as r,B as s,F as t,q as u,x as v,u as y};
|
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.24.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",
|
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
"commit"
|
|
14
14
|
],
|
|
15
15
|
"main": "dist/index.js",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20.19.0"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"readme.md"
|
|
23
|
+
],
|
|
16
24
|
"bin": {
|
|
17
25
|
"better-commits-init": "./dist/init.js",
|
|
18
26
|
"better-commits": "./dist/index.js",
|
|
@@ -29,7 +37,7 @@
|
|
|
29
37
|
"@bomb.sh/args": "^0.3.1",
|
|
30
38
|
"@clack/core": "^1.2.0",
|
|
31
39
|
"@clack/prompts": "^1.2.0",
|
|
32
|
-
"configstore": "^
|
|
40
|
+
"configstore": "^8.0.0",
|
|
33
41
|
"jsonc-parser": "^3.3.1",
|
|
34
42
|
"picocolors": "^1.0.0",
|
|
35
43
|
"valibot": "^1.3.1"
|
|
@@ -38,21 +46,19 @@
|
|
|
38
46
|
"start": "tsx ./src/index.ts",
|
|
39
47
|
"branch": "tsx ./src/branch.ts",
|
|
40
48
|
"init": "tsx ./src/init.ts",
|
|
41
|
-
"build": "
|
|
49
|
+
"build": "tsdown",
|
|
42
50
|
"commit": "tsx ./src/index.ts",
|
|
43
|
-
"test": "vitest run"
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"knip": "knip"
|
|
44
53
|
},
|
|
45
54
|
"devDependencies": {
|
|
46
55
|
"@semantic-release/git": "^10.0.1",
|
|
47
|
-
"@
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"prettier": "3.2.5",
|
|
52
|
-
"semantic-release": "^25.0.2",
|
|
53
|
-
"tsup": "^8.0.2",
|
|
56
|
+
"@types/node": "^24.12.4",
|
|
57
|
+
"knip": "^6.15.0",
|
|
58
|
+
"semantic-release": "^25.0.3",
|
|
59
|
+
"tsdown": "^0.21.10",
|
|
54
60
|
"tsx": "^3.12.3",
|
|
55
|
-
"typescript": "^5.
|
|
61
|
+
"typescript": "^5.9.3",
|
|
56
62
|
"vitest": "^3.2.4"
|
|
57
63
|
},
|
|
58
64
|
"release": {
|
package/readme.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|

|
|
4
4
|
|
|
5
5
|
[](https://github.com/Everduin94/better-commits)
|
|
6
|
-
[](https://
|
|
6
|
+
[](https://npmx.dev/package/better-commits)
|
|
7
7
|
[](https://discord.gg/grHVnZwYup)
|
|
8
8
|
|
|
9
9
|
</h3>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
A CLI for writing better commits, following the conventional commits specification.
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
<video src="https://github.com/Everduin94/better-commits/assets/14320878/8fb15d46-17c4-4e5d-80d9-79abe0a2a00a"></video>
|
|
15
|
+
<video src="https://github.com/Everduin94/better-commits/assets/14320878/8fb15d46-17c4-4e5d-80d9-79abe0a2a00a"></video>
|
|
16
16
|
|
|
17
17
|
## โจ Features
|
|
18
18
|
|
|
@@ -36,6 +36,8 @@ As a side-effect of formatting messages
|
|
|
36
36
|
|
|
37
37
|
## ๐ฆ Installation
|
|
38
38
|
|
|
39
|
+
> Requires Node.js 20 or newer.
|
|
40
|
+
|
|
39
41
|
```sh
|
|
40
42
|
npm install -g better-commits
|
|
41
43
|
```
|
package/.better-commits.json
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"commit_type": {
|
|
3
|
-
"append_emoji_to_label": true,
|
|
4
|
-
"append_emoji_to_commit": false
|
|
5
|
-
},
|
|
6
|
-
"commit_body": {
|
|
7
|
-
"split_by_period": true
|
|
8
|
-
},
|
|
9
|
-
"commit_scope": {
|
|
10
|
-
"enable": true,
|
|
11
|
-
"initial_value": "commit",
|
|
12
|
-
"options": [
|
|
13
|
-
{
|
|
14
|
-
"value": "commit",
|
|
15
|
-
"label": "commit"
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"value": "branch",
|
|
19
|
-
"label": "branch"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"value": "init",
|
|
23
|
-
"label": "init"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"value": "util",
|
|
27
|
-
"label": "util"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"value": "build",
|
|
31
|
-
"label": "build"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"value": "help",
|
|
35
|
-
"label": "help"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"value": "",
|
|
39
|
-
"label": "none"
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
},
|
|
43
|
-
"check_ticket": {
|
|
44
|
-
"prepend_hashtag": "Always"
|
|
45
|
-
},
|
|
46
|
-
"branch_pre_commands": [
|
|
47
|
-
"git stash",
|
|
48
|
-
"git checkout main",
|
|
49
|
-
"git pull -r origin main",
|
|
50
|
-
"npm install"
|
|
51
|
-
]
|
|
52
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
name: Publish to NPM
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
name: Publish
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
permissions:
|
|
13
|
-
contents: write
|
|
14
|
-
issues: write
|
|
15
|
-
pull-requests: write
|
|
16
|
-
id-token: write
|
|
17
|
-
steps:
|
|
18
|
-
- name: Checkout
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
with:
|
|
21
|
-
fetch-depth: 0
|
|
22
|
-
- name: Setup Node.js
|
|
23
|
-
uses: actions/setup-node@v4
|
|
24
|
-
with:
|
|
25
|
-
node-version: "lts/*"
|
|
26
|
-
registry-url: "https://registry.npmjs.org"
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
run: npm ci
|
|
29
|
-
- name: Build package
|
|
30
|
-
run: npm run build
|
|
31
|
-
- name: Release
|
|
32
|
-
env:
|
|
33
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
-
run: npx semantic-release
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
name: Test
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
push:
|
|
6
|
-
branches:
|
|
7
|
-
- main
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
name: npm test
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- name: Checkout
|
|
15
|
-
uses: actions/checkout@v4
|
|
16
|
-
|
|
17
|
-
- name: Setup Node.js
|
|
18
|
-
uses: actions/setup-node@v4
|
|
19
|
-
with:
|
|
20
|
-
node-version: "lts/*"
|
|
21
|
-
cache: npm
|
|
22
|
-
|
|
23
|
-
- name: Install dependencies
|
|
24
|
-
run: npm ci
|
|
25
|
-
|
|
26
|
-
- name: Run tests
|
|
27
|
-
run: npm run test
|
package/.prettierignore
DELETED
package/.prettierrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
package/dist/chunk-43H72S6V.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as _,b as u,d as l,f as p}from"./chunk-B7AGSPP3.js";import*as s from"valibot";function g(t,n){let r=t.scope?t.scope.length+2:0,e=t.type?.length??0,i=n.include_ticket?t.ticket?.length??0:0,o=t.title?.length??0;return r+e+i+o}function a(t){return t.map(r=>r===""?'"" (none)':`"${r}"`).join(", ")}function G(t){let n=t.commit_type.options.map(e=>e.value),r=t.commit_scope.options.map(e=>e.value);return s.pipe(s.object(u),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=e.value.type?`"${e.value.type}"`:"(empty)";e.value.type&&!n.includes(e.value.type)&&i({message:`Invalid --type ${o}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=e.value.scope?`"${e.value.scope}"`:"(empty)";e.value.scope&&!t.commit_scope.custom_scope&&!r.includes(e.value.scope)&&i({message:`Invalid --scope ${o}. Valid scopes: ${a(r)}.`})}),s.rawCheck(({dataset:e,addIssue:i})=>{!e.typed||e.value.title.trim()||i({message:"Missing --title. Provide a non-empty commit title."})}),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=g(e.value,{include_ticket:t.check_ticket.add_to_title});o>t.commit_title.max_size&&i({message:`Title exceeds max width. Current size is ${o}, max is ${t.commit_title.max_size} (includes type, scope, and ticket when enabled).`})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&t.commit_body.required&&!e.value.body.trim()&&i({message:"Missing --body. commit_body.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&e.value.closes&&!e.value.ticket&&i({message:'Invalid footer values: --closes requires --ticket (for example: --ticket "ABC-123").'})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&e.value.breaking_body&&!e.value.breaking_title&&i({message:"Invalid breaking change values: --breaking-body requires --breaking-title."})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&e.value.deprecates_body&&!e.value.deprecates_title&&i({message:"Invalid deprecation values: --deprecates-body requires --deprecates-title."})}))}function N(t){let n=t.commit_type.options.map(e=>e.value),r=t.commit_scope.options.map(e=>e.value);return s.pipe(s.object(l),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=e.value.type?`"${e.value.type}"`:"(empty)";e.value.type&&!n.includes(e.value.type)&&i({message:`Invalid --type ${o}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=e.value.scope?`"${e.value.scope}"`:"(empty)";e.value.scope&&!t.commit_scope.custom_scope&&!r.includes(e.value.scope)&&i({message:`Invalid --scope ${o}. Valid scopes: ${a(r)}.`})}),s.rawCheck(({dataset:e,addIssue:i})=>{!e.typed||e.value.description.trim()||i({message:"Missing --description. Provide a non-empty branch description."})}),s.rawCheck(({dataset:e,addIssue:i})=>{if(!e.typed)return;let o=e.value.description.trim();o.length>t.branch_description.max_length&&i({message:`Description exceeds max length. Current length is ${o.length}, max is ${t.branch_description.max_length}.`})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&t.branch_user.required&&!e.value.user.trim()&&i({message:"Missing --user. branch_user.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&t.branch_ticket.required&&!e.value.ticket.trim()&&i({message:"Missing --ticket. branch_ticket.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:i})=>{e.typed&&t.branch_version.required&&!e.value.version.trim()&&i({message:"Missing --branch-version. branch_version.required is enabled in config."})}))}import{execSync as h}from"child_process";var v=/\/(\w+-\d+)/,y=/^(\w+-\d+)/,k=/^([A-Z]+-[\[a-zA-Z\]\d]+)_/,b=/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/,$=/\/(\d+)/,C=/^(\d+)/;function V(t){if(p.interactive)return;let n={ticket:"",type:"",scope:""};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 r=x(t.commit_type.options,p.git_args);if(n.type=r,t.commit_scope.enable&&t.commit_scope.infer_scope_from_branch){let e=E(t.commit_scope.options,p.git_args);n.scope=e}return n}function x(t,n){let r=m(n);return r?T(r,t.map(e=>e.value)):""}function w(t,n){let r=m(n);return r?S(r,t):""}function E(t,n){let r=m(n);return r?z(r,t):""}function S(t,n){let r=[t.match(k),t.match(b),t.match(v),t.match($),t.match(y),t.match(C)].filter(e=>e!=null).map(e=>e&&e.length>=2?e[1]:"");return!r.length||!r[0]?"":n.append_hashtag||n.prepend_hashtag==="Always"?`#${r[0]}`:r[0]}function T(t,n){return n.find(e=>{let i=new RegExp(`^${e}-`),o=new RegExp(`-${e}-`),d=new RegExp(`${e}/`);return[t.match(i),t.match(o),t.match(d)].filter(f=>f!=null).length>0})??""}function A(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function z(t,n){return n.map(i=>i.value).filter(i=>i&&i!==_).sort((i,o)=>o.length-i.length).find(i=>new RegExp(`(?:^|[/_-])${A(i)}(?=$|[/_-])`).test(t))??""}function m(t){try{return h(`git ${t} branch --show-current`,{stdio:"pipe"}).toString().trim()}catch{return""}}import c from"picocolors";function D(t){return`${t} ${c.dim("\xB7 restored from cache")}`}function L(t){return`${t} ${c.dim("\xB7 inferred from branch")}`}function B(t){return`${t} ${c.dim("\xB7 optional")}`}function K(t){return`${t} ${c.dim("\xB7 <space> to select")}`}function Y(t){return`${t} ${c.dim("\xB7 <space> to select \xB7 <a> to select all")}`}function F(t){return`${t} ${c.dim("\xB7 dry run - changes will not be committed")}`}export{g as a,G as b,N as c,V as d,x as e,w as f,E as g,D as h,L as i,B as j,K as k,Y as l,F as m};
|