better-commits 1.19.1 → 1.20.0-cli-flags

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.
Files changed (65) hide show
  1. package/.better-commits.json +4 -0
  2. package/.github/workflows/test.yml +27 -0
  3. package/.opencode/package-lock.json +115 -0
  4. package/.opencode/plans/cli-args.md +182 -0
  5. package/.svelte-kit/ambient.d.ts +289 -0
  6. package/.svelte-kit/generated/client/app.js +28 -0
  7. package/.svelte-kit/generated/client/matchers.js +1 -0
  8. package/.svelte-kit/generated/client/nodes/0.js +1 -0
  9. package/.svelte-kit/generated/client/nodes/1.js +1 -0
  10. package/.svelte-kit/tsconfig.json +49 -0
  11. package/0001-feat-branch-124-update-worktrees-feature.patch +316 -0
  12. package/dist/branch.js +27 -1
  13. package/dist/chunk-OFJCRS3N.js +4 -0
  14. package/dist/chunk-SIF4LZUS.js +1 -0
  15. package/dist/index.js +44 -19
  16. package/dist/init.js +1 -1
  17. package/docs/ai-skills.yaml +48 -0
  18. package/docs/clack.md +143 -0
  19. package/docs/valibot.md +228 -0
  20. package/package.json +12 -9
  21. package/readme.md +18 -2
  22. package/src/args.test.ts +102 -0
  23. package/src/args.ts +101 -7
  24. package/src/branch-args.test.ts +72 -0
  25. package/src/branch-args.ts +106 -0
  26. package/src/branch-help.ts +114 -0
  27. package/src/branch.ts +67 -238
  28. package/src/help.ts +131 -0
  29. package/src/index.test.ts +7 -0
  30. package/src/index.ts +73 -495
  31. package/src/prompts/branch-checkout.prompt.ts +36 -0
  32. package/src/prompts/branch-confirm.prompt.ts +134 -0
  33. package/src/prompts/branch-description.prompt.ts +37 -0
  34. package/src/prompts/branch-runnable.ts +13 -0
  35. package/src/prompts/branch-ticket.prompt.ts +41 -0
  36. package/src/prompts/branch-type.prompt.ts +43 -0
  37. package/src/prompts/branch-user.prompt.ts +50 -0
  38. package/src/prompts/branch-version.prompt.ts +41 -0
  39. package/src/prompts/commit-body.prompt.ts +57 -0
  40. package/src/prompts/commit-confirm.prompt.ts +119 -0
  41. package/src/prompts/commit-footer.prompt.ts +195 -0
  42. package/src/prompts/commit-scope.prompt.ts +73 -0
  43. package/src/prompts/commit-status.prompt.ts +75 -0
  44. package/src/prompts/commit-ticket.prompt.ts +82 -0
  45. package/src/prompts/commit-title.prompt.ts +98 -0
  46. package/src/prompts/commit-type.prompt.ts +93 -0
  47. package/src/prompts/runnable.ts +13 -0
  48. package/src/utils/build-branch.test.ts +141 -0
  49. package/src/utils/build-branch.ts +46 -0
  50. package/src/utils/build-commit-string.test.ts +253 -0
  51. package/src/utils/build-commit-string.ts +158 -0
  52. package/src/utils/commit-title-size.ts +24 -0
  53. package/src/utils/infer.test.ts +83 -0
  54. package/src/utils/infer.ts +114 -0
  55. package/src/utils/messages.ts +25 -0
  56. package/src/utils/no-interactive-branch-validation.test.ts +170 -0
  57. package/src/utils/no-interactive-validation.test.ts +174 -0
  58. package/src/utils/no-interactive-validation.ts +190 -0
  59. package/src/utils.ts +59 -66
  60. package/src/valibot-consts.ts +2 -2
  61. package/src/valibot-state.test.ts +48 -0
  62. package/src/valibot-state.ts +133 -130
  63. package/tsconfig.json +3 -2
  64. package/vitest.config.ts +8 -0
  65. package/dist/chunk-K2RPF2JY.js +0 -4
@@ -0,0 +1,49 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "$app/types": [
5
+ "./types/index.d.ts"
6
+ ]
7
+ },
8
+ "rootDirs": [
9
+ "..",
10
+ "./types"
11
+ ],
12
+ "verbatimModuleSyntax": true,
13
+ "isolatedModules": true,
14
+ "lib": [
15
+ "esnext",
16
+ "DOM",
17
+ "DOM.Iterable"
18
+ ],
19
+ "moduleResolution": "bundler",
20
+ "module": "esnext",
21
+ "noEmit": true,
22
+ "target": "esnext"
23
+ },
24
+ "include": [
25
+ "ambient.d.ts",
26
+ "non-ambient.d.ts",
27
+ "./types/**/$types.d.ts",
28
+ "../vite.config.js",
29
+ "../vite.config.ts",
30
+ "../src/**/*.js",
31
+ "../src/**/*.ts",
32
+ "../src/**/*.svelte",
33
+ "../test/**/*.js",
34
+ "../test/**/*.ts",
35
+ "../test/**/*.svelte",
36
+ "../tests/**/*.js",
37
+ "../tests/**/*.ts",
38
+ "../tests/**/*.svelte"
39
+ ],
40
+ "exclude": [
41
+ "../node_modules/**",
42
+ "../src/service-worker.js",
43
+ "../src/service-worker/**/*.js",
44
+ "../src/service-worker.ts",
45
+ "../src/service-worker/**/*.ts",
46
+ "../src/service-worker.d.ts",
47
+ "../src/service-worker/**/*.d.ts"
48
+ ]
49
+ }
@@ -0,0 +1,316 @@
1
+ From 8f6f28a9e249988ac00350defdb852c0bcdea615 Mon Sep 17 00:00:00 2001
2
+ From: everduin94 <everduin94@gmail.com>
3
+ Date: Thu, 4 Sep 2025 08:53:43 -0500
4
+ Subject: [PATCH] feat(branch): #124 update worktrees feature
5
+
6
+ DEPRECATED: replaced enable_worktrees in favor of worktrees.enable
7
+
8
+ Closes: #124
9
+ ---
10
+ .better-commits.json | 6 +---
11
+ readme.md | 85 +++++++++++++++++++++-----------------------
12
+ src/branch.ts | 37 +++++++++----------
13
+ src/utils.ts | 26 --------------
14
+ src/valibot-state.ts | 15 ++++----
15
+ 5 files changed, 68 insertions(+), 101 deletions(-)
16
+
17
+ diff --git a/.better-commits.json b/.better-commits.json
18
+ index a2a964b..3dce2fc 100644
19
+ --- a/.better-commits.json
20
+ +++ b/.better-commits.json
21
+ @@ -41,9 +41,5 @@
22
+ "git checkout main",
23
+ "git pull -r origin main",
24
+ "npm install"
25
+ - ],
26
+ - "worktree_config": {
27
+ - "base_path": "../",
28
+ - "folder_template": "{{repo_name}}-{{user}}-{{type}}-{{branch_description}}"
29
+ - }
30
+ + ]
31
+ }
32
+ diff --git a/readme.md b/readme.md
33
+ index 7376317..cf46fb1 100644
34
+ --- a/readme.md
35
+ +++ b/readme.md
36
+ @@ -42,16 +42,15 @@ npm install -g better-commits
37
+
38
+ ## 🚀 Usage
39
+
40
+ -When you're ready to commit. To run the CLI in your terminal:
41
+ +To run the CLI in your terminal:
42
+
43
+ ```sh
44
+ -better-commits
45
+ -# or
46
+ -npx better-commits
47
+ +better-commits # Create a new commit
48
+ +better-branch # Create a new branch
49
+ ```
50
+
51
+ -It will prompt a series of questions. These prompts will build a commit message, which you can preview, before confirming the commit.
52
+ -Some of the values in these prompts will be infered by your branch name and auto populated. You can adjust this in your `.better-commits.json` configuration file.
53
+ +`better-commits` will prompt a series of questions. These prompts will build a commit message, which you can preview, before confirming the commit.
54
+ +Some of the values in these prompts will be inferred by your branch name and auto populated. You can adjust this in your `.better-commits.json` configuration file.
55
+
56
+ To better understand these prompts and their intention, read [Conventional Commits Summary](https://www.conventionalcommits.org/en/v1.0.0-beta.4/#summary)
57
+
58
+ @@ -251,10 +250,10 @@ Better-commits (& better-branch) are highly flexible with sane defaults. These o
59
+ },
60
+ "branch_action_default": "branch",
61
+ "branch_order": ["user", "version", "type", "ticket", "description"],
62
+ - "enable_worktrees": true,
63
+ - "worktree_config": {
64
+ - "base_path": "../",
65
+ - "folder_template": "{{repo_name}}-{{branch_description}}"
66
+ + "worktrees": {
67
+ + "enable": true,
68
+ + "base_path": "..",
69
+ + "folder_template": "{{repo_name}}-{{ticket}}-{{branch_description}}"
70
+ },
71
+ "overrides": {
72
+ "shell": "/bin/sh"
73
+ @@ -327,30 +326,31 @@ Expand to see explanations and possible values
74
+
75
+ Branch configuration (same config file, split for readability)
76
+
77
+ -| Property | Description |
78
+ -| ------------------------------- | --------------------------------------------------------- |
79
+ -| `branch_pre_commands` | Array of shell commands to run before branching |
80
+ -| `branch_post_commands` | Array of shell commands to run after branching |
81
+ -| `worktree_pre_commands` | Array of shell commands to run before creating worktree |
82
+ -| `worktree_post_commands` | Array of shell commands to run after creating worktree |
83
+ -| `branch_user.enable` | If enabled include user name |
84
+ -| `branch_user.required` | If enabled require user name |
85
+ -| `branch_user.separator` | Branch delimeter - "/" (default), "-", "\_" |
86
+ -| `branch_type.enable` | If enabled include type |
87
+ -| `branch_type.separator` | Branch delimeter - "/" (default), "-", "\_" |
88
+ -| `branch_ticket.enable` | If enabled include ticket |
89
+ -| `branch_ticket.required` | If enabled require ticket |
90
+ -| `branch_ticket.separator` | Branch delimeter - "/", "-" (default), "\_" |
91
+ -| `branch_description.max_length` | Max length branch name |
92
+ -| `branch_description.separator` | Branch delimeter - "" (default), "/", "-", "\_" |
93
+ -| `branch_version.enable` | If enabled include version |
94
+ -| `branch_version.required` | If enabled require version |
95
+ -| `branch_version.separator` | Branch delimeter - "", "/" (default), "-", "\_" |
96
+ -| `branch_order` | Order of branch name values (doesn't effect prompt order) |
97
+ -| `branch_action_default` | "branch" or "worktree" |
98
+ -| `enable_worktrees` | If false, always default to branch action |
99
+ -| `worktree_config.base_path` | Directory where worktrees are created (default: "../") |
100
+ -| `worktree_config.folder_template` | Template for worktree folder names with variables like {{repo_name}}, {{branch_description}}, {{user}}, {{type}}, {{ticket}}, {{version}} |
101
+ +| Property | Description |
102
+ +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
103
+ +| `branch_pre_commands` | Array of shell commands to run before branching |
104
+ +| `branch_post_commands` | Array of shell commands to run after branching |
105
+ +| `worktree_pre_commands` | Array of shell commands to run before creating worktree |
106
+ +| `worktree_post_commands` | Array of shell commands to run after creating worktree |
107
+ +| `branch_user.enable` | If enabled include user name |
108
+ +| `branch_user.required` | If enabled require user name |
109
+ +| `branch_user.separator` | Branch delimeter - "/" (default), "-", "\_" |
110
+ +| `branch_type.enable` | If enabled include type |
111
+ +| `branch_type.separator` | Branch delimeter - "/" (default), "-", "\_" |
112
+ +| `branch_ticket.enable` | If enabled include ticket |
113
+ +| `branch_ticket.required` | If enabled require ticket |
114
+ +| `branch_ticket.separator` | Branch delimeter - "/", "-" (default), "\_" |
115
+ +| `branch_description.max_length` | Max length branch name |
116
+ +| `branch_description.separator` | Branch delimeter - "" (default), "/", "-", "\_" |
117
+ +| `branch_version.enable` | If enabled include version |
118
+ +| `branch_version.required` | If enabled require version |
119
+ +| `branch_version.separator` | Branch delimeter - "", "/" (default), "-", "\_" |
120
+ +| `branch_order` | Order of branch name values (doesn't effect prompt order) |
121
+ +| `branch_action_default` | "branch" or "worktree" |
122
+ +| `enable_worktrees` | `Deprecated` see `worktrees.enable` |
123
+ +| `worktrees.enable` | If false, always default to branch action |
124
+ +| `worktrees.base_path` | Directory where worktrees are created (default: "..") |
125
+ +| `worktrees.folder_template` | Template for worktree folder names with variables like {{repo_name}}, {{branch_description}}, {{user}}, {{type}}, {{ticket}}, {{version}} |
126
+
127
+ </details>
128
+
129
+ @@ -368,16 +368,13 @@ Branch configuration (same config file, split for readability)
130
+
131
+ ## 🌳 Better Branch
132
+
133
+ -> [!NOTE]<br>
134
+ -> Using `better-branch` with `better-commits` can supercharge your git workflow.
135
+ -> Make sure to try it out!
136
+ -
137
+ Better branch is a secondary feature that works with better commits
138
+
139
+ - Supports consistent branch naming conventions
140
+ - Uses same type-list/prompt from your config
141
+ - Enables better-commits to infer type & ticket
142
+ - Caches your username for speedy branching
143
+ +- Convenient worktree creation
144
+
145
+ To run the CLI in your terminal:
146
+
147
+ @@ -387,13 +384,14 @@ better-branch
148
+
149
+ ### Worktree Support
150
+
151
+ -`better-branch` will prompt for **Branch** or **Worktree**. Creating a **Worktree** with `better-branch` is a great way to create worktrees while maintaining consistent branch naming conventions.
152
+ -
153
+ -The worktree flow creates a folder/worktree with your **branch description** and a git branch inside with your **full branch name**.
154
+ +`better-branch` will prompt for **Branch** or **Worktree**. The Worktree flow creates a folder/worktree from your **branch description** and a git branch inside with your **full branch name**.
155
+
156
+ > [!NOTE]<br>
157
+ > Creating a worktree named `everduin94/feat/TAC-123-add-worktrees` with the native git command would create a nested folder for each `/`. `better-branch` removes the hassle by creating 1 folder while still using the full name for the branch.
158
+
159
+ +> [!TIP]
160
+ +> By default, `better-branch` will create **worktrees** as a sibling folder. To change this, see `worktrees.base_path`.
161
+ +
162
+ ### Pre/Post Branch Checkout Hooks
163
+
164
+ Optionally configure pre and post checkout commands, for example:
165
+ @@ -425,7 +423,7 @@ If you're using Github issues to track your work, and select the `closes` footer
166
+
167
+ `better-commits` can append a commit trailer per commit type. This allows you to [automate change logs](https://docs.gitlab.com/ee/user/project/changelogs.html) with tools like Gitlab.
168
+
169
+ -### Fun Facts
170
+ +### Misc
171
+
172
+ `better-commits` uses native `git` commands under the hood. So any hooks, tools, or staging should work as if it was a normal commit.
173
+
174
+ @@ -434,9 +432,6 @@ Setting `confirm_with_editor=true` will allow you to edit/confirm a commit with
175
+ - For example, to edit with Neovim: `git config --global core.editor "nvim"`
176
+ - For VS Code, `git config --global core.editor "code -n --wait"`
177
+
178
+ -> [!NOTE]<br>
179
+ -> Enjoy learning, open source technology, and note-taking? [Join our Discord!](https://discord.gg/grHVnZwYup)
180
+ -
181
+ You can add this badge to your repository to display that you're using a better-commits repository config
182
+
183
+ | Markdown | Result |
184
+ diff --git a/src/branch.ts b/src/branch.ts
185
+ index 14b3f0f..bd70311 100644
186
+ --- a/src/branch.ts
187
+ +++ b/src/branch.ts
188
+ @@ -17,7 +17,7 @@ import {
189
+ CACHE_PROMPT,
190
+ OPTIONAL_PROMPT,
191
+ load_setup,
192
+ - get_repo_name,
193
+ + get_git_root,
194
+ } from "./utils";
195
+ import { flags } from "./args";
196
+
197
+ @@ -25,9 +25,10 @@ main(load_setup(" better-branch "));
198
+
199
+ async function main(config: Output<typeof Config>) {
200
+ const branch_state = parse(BranchState, {});
201
+ + chdir(get_git_root());
202
+
203
+ let checkout_type: Output<typeof V_BRANCH_ACTIONS> = "branch";
204
+ - if (config.enable_worktrees) {
205
+ + if (config.worktrees.enable) {
206
+ const branch_or_worktree = await p.select({
207
+ message: `Checkout a branch or create a worktree?`,
208
+ initialValue: config.branch_action_default,
209
+ @@ -198,26 +199,26 @@ function build_worktree_path(
210
+ branch_state: Output<typeof BranchState>,
211
+ config: Output<typeof Config>,
212
+ ): string {
213
+ - const repo_name = get_repo_name();
214
+ - let worktree_name = config.worktree_config.folder_template;
215
+ -
216
+ - // Replace template variables
217
+ + const gitRoot = get_git_root();
218
+ + const repo_name = gitRoot.split("/").pop() || "repo";
219
+ +
220
+ + let worktree_name = config.worktrees.folder_template;
221
+ +
222
+ worktree_name = worktree_name
223
+ - .replace(/\{\{repo_name\}\}/g, repo_name)
224
+ - .replace(/\{\{branch_description\}\}/g, branch_state.description)
225
+ - .replace(/\{\{user\}\}/g, branch_state.user || "")
226
+ - .replace(/\{\{type\}\}/g, branch_state.type || "")
227
+ - .replace(/\{\{ticket\}\}/g, branch_state.ticket || "")
228
+ - .replace(/\{\{version\}\}/g, branch_state.version || "");
229
+ -
230
+ - // Clean up any double hyphens or leading/trailing hyphens
231
+ + .replace("{{repo_name}}", repo_name)
232
+ + .replace("{{branch_description}}", branch_state.description)
233
+ + .replace("{{user}}", branch_state.user || "")
234
+ + .replace("{{type}}", branch_state.type || "")
235
+ + .replace("{{ticket}}", branch_state.ticket || "")
236
+ + .replace("{{version}}", branch_state.version || "");
237
+ +
238
+ worktree_name = worktree_name
239
+ + .replace(/\s/g, "")
240
+ .replace(/--+/g, "-")
241
+ .replace(/^-+|-+$/g, "");
242
+ -
243
+ - // Combine with base path
244
+ - const base_path = config.worktree_config.base_path;
245
+ - return `${base_path}${base_path.endsWith('/') ? '' : '/'}${worktree_name}`;
246
+ +
247
+ + const base_path = config.worktrees.base_path;
248
+ + return `${base_path}${base_path.endsWith("/") ? "" : "/"}${worktree_name}`;
249
+ }
250
+
251
+ function get_user_from_cache(): string {
252
+ diff --git a/src/utils.ts b/src/utils.ts
253
+ index 7166c2a..0c0403d 100644
254
+ --- a/src/utils.ts
255
+ +++ b/src/utils.ts
256
+ @@ -224,29 +224,3 @@ export function set_value_cache(
257
+ );
258
+ }
259
+ }
260
+ -
261
+ -export function get_repo_name(): string {
262
+ - try {
263
+ - // First try to get repo name from git remote
264
+ - const remote = execSync(`git ${flags.git_args} remote get-url origin`, {
265
+ - stdio: "pipe",
266
+ - }).toString().trim();
267
+ -
268
+ - // Extract repo name from remote URL
269
+ - const match = remote.match(/\/([^\/]+?)(\.git)?$/);
270
+ - if (match && match[1]) {
271
+ - return match[1];
272
+ - }
273
+ - } catch (err) {
274
+ - // If git remote fails, fall back to directory name
275
+ - }
276
+ -
277
+ - try {
278
+ - // Fall back to git root directory name
279
+ - const gitRoot = get_git_root();
280
+ - const repoName = gitRoot.split('/').pop() || 'repo';
281
+ - return repoName;
282
+ - } catch (err) {
283
+ - return 'repo';
284
+ - }
285
+ -}
286
+ diff --git a/src/valibot-state.ts b/src/valibot-state.ts
287
+ index 7256ca3..de943a3 100644
288
+ --- a/src/valibot-state.ts
289
+ +++ b/src/valibot-state.ts
290
+ @@ -211,15 +211,16 @@ export const Config = v.object({
291
+ branch_action_default: v.optional(V_BRANCH_ACTIONS, "branch"),
292
+ branch_order: v.optional(v.array(V_BRANCH_FIELDS), BRANCH_ORDER_DEFAULTS),
293
+ enable_worktrees: v.optional(v.boolean(), true),
294
+ - worktree_config: v.optional(
295
+ + worktrees: v.optional(
296
+ v.object({
297
+ - base_path: v.optional(v.string(), "../"),
298
+ - folder_template: v.optional(v.string(), "{{repo_name}}-{{branch_description}}"),
299
+ + enable: v.optional(v.boolean(), true),
300
+ + base_path: v.optional(v.string(), ".."),
301
+ + folder_template: v.optional(
302
+ + v.string(),
303
+ + "{{repo_name}}-{{ticket}}-{{branch_description}}",
304
+ + ),
305
+ }),
306
+ - {
307
+ - base_path: "../",
308
+ - folder_template: "{{repo_name}}-{{branch_description}}",
309
+ - },
310
+ + {},
311
+ ),
312
+ overrides: v.optional(
313
+ v.object({
314
+ --
315
+ 2.39.5 (Apple Git-154)
316
+
package/dist/branch.js CHANGED
@@ -1,2 +1,28 @@
1
1
  #! /usr/bin/env node
2
- import{d as f,e as g,h as _,i as b,q as w,s as y,u as h}from"./chunk-K2RPF2JY.js";import*as r from"@clack/prompts";import{execSync as l}from"child_process";import C from"configstore";import s from"picocolors";import{chdir as k}from"process";import{parse as $}from"valibot";O(y(" better-branch "));async function O(e){let o=$(f,{});k(h());let a="branch";if(e.worktrees.enable){let t=await r.select({message:"Checkout a branch or create a worktree?",initialValue:e.branch_action_default,options:w});r.isCancel(t)&&process.exit(),a=t}if(e.branch_user.enable){let t=N(),n=e.branch_user.required,p=await r.text({message:`Type your git username ${n?"":_} ${b}`.trim(),placeholder:"",initialValue:t,validate:x=>{if(n&&!x)return"Please enter a username"}});r.isCancel(p)&&process.exit(0),o.user=p?.replace(/\s+/g,"-")?.toLowerCase()??"",T(o.user)}if(e.branch_type.enable){let t=e.commit_type.initial_value,n=await r.select({message:"Select a branch type",initialValue:t,options:e.commit_type.options});r.isCancel(n)&&process.exit(0),o.type=n}if(e.branch_ticket.enable){let t=e.branch_ticket.required,n=await r.text({message:`Type ticket / issue number ${t?"":_}`.trim(),placeholder:"",validate:p=>{if(t&&!p)return"Please enter a ticket / issue"}});r.isCancel(n)&&process.exit(0),o.ticket=n}if(e.branch_version.enable){let t=e.branch_version.required,n=await r.text({message:`Type version number ${t?"":_}`.trim(),placeholder:"",validate:p=>{if(t&&!p)return"Please enter a version"}});r.isCancel(n)&&process.exit(0),o.version=n}let c=e.branch_description.max_length,i=await r.text({message:"Type a short description",placeholder:"",validate:t=>{if(!t)return"Please enter a description";if(t.length>c)return`Exceeded max length. Description max [${c}]`}});r.isCancel(i)&&process.exit(0),o.description=i?.replace(/\s+/g,"-")?.toLowerCase()??"",(a==="worktree"?e.worktree_pre_commands:e.branch_pre_commands).forEach(t=>{try{l(t,{stdio:"inherit"})}catch(n){r.log.error("Something went wrong when executing pre-commands: "+n),process.exit(0)}});let m=v(o,e),d=A(m);if(a==="branch")try{l(`git ${g.git_args} checkout ${d} ${m}`,{stdio:"inherit"}),r.log.info(`Switched to a new branch '${s.bgGreen(" "+s.black(m)+" ")}'`)}catch{process.exit(0)}else try{let t=S(o,e);l(`git worktree add ${t} ${d} ${m}`,{stdio:"inherit"}),r.log.info(`Created a new worktree ${s.bgGreen(+" "+s.black(t)+" ")}, checked out branch ${s.bgGreen(" "+s.black(m)+" ")}`),r.log.info(s.bgMagenta(s.black(` cd ${t} `))+" to navigate to your new worktree"),k(t)}catch{process.exit(0)}(a==="worktree"?e.worktree_post_commands:e.branch_post_commands).forEach(t=>{try{l(t,{stdio:"inherit"})}catch(n){r.log.error("Something went wrong when executing post-commands: "+n),process.exit(0)}})}function v(e,o){let a="";return o.branch_order.forEach(c=>{let i=`branch_${c}`;e[c]&&(a+=e[c]+o[i].separator)}),a.endsWith("-")||a.endsWith("/")||a.endsWith("_")?a.slice(0,-1).trim():a.trim()}function S(e,o){let c=h().split("/").pop()||"repo",i=o.worktrees.folder_template;i=i.replace("{{repo_name}}",c).replace("{{branch_description}}",e.description).replace("{{user}}",e.user||"").replace("{{type}}",e.type||"").replace("{{ticket}}",e.ticket||"").replace("{{version}}",e.version||""),i=i.replace(/\s/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"");let u=o.worktrees.base_path;return`${u}${u.endsWith("/")?"":"/"}${i}`}function N(){try{return new C("better-commits").get("username")??""}catch{r.log.warn('There was an issue accessing username from cache. Check that the folder "~/.config" exists')}return""}function A(e){let o="";try{l(`git show-ref ${e}`,{encoding:"utf-8"}),r.log.warning(s.yellow(`${e} already exists! Checking out existing branch.`))}catch{o="-b"}return o}function T(e){try{new C("better-commits").set("username",e)}catch{}}
2
+ import{c as V,e as H,f as D,i as h}from"./chunk-SIF4LZUS.js";import{f as T,j as A,k as F,l as E,m as u,n as _,q as G,r as L}from"./chunk-OFJCRS3N.js";import at from"configstore";import{chdir as ct}from"process";import{ValiError as pt,parse as U}from"valibot";var a=class{constructor(t,r,n){this.config=t;this.branch_state=r;this.prompt_cache=n}};import*as l from"@clack/prompts";var f=class extends a{async run(){if(this.#e){let t=await l.select({message:this.#t,initialValue:this.#r,options:A});l.isCancel(t)&&process.exit(),this.#n(t)}}get#t(){return"Checkout a branch or create a worktree?"}get#e(){return this.config.worktrees.enable}get#r(){return this.branch_state.checkout||this.config.branch_action_default}#n(t){this.branch_state.checkout=t}};import*as b from"@clack/prompts";var d=class extends a{async run(){if(!this.#t)return;let t=await b.text({message:this.#r,placeholder:"",initialValue:this.#n,validate:r=>this.#i(r)});b.isCancel(t)&&process.exit(0),this.#o(t??"")}get#t(){return this.config.branch_user.enable}get#e(){return this.config.branch_user.required}get#r(){return this.#e?"Type your git username":h("Type your git username")}get#n(){return this.branch_state.user||G(this.prompt_cache,"username")}#i(t){if(this.#e&&!t)return"Please enter a username"}#o(t){this.branch_state.user=t.replace(/\s+/g,"-").toLowerCase(),L(this.prompt_cache,"username",this.branch_state.user)}};import*as v from"@clack/prompts";var y=class extends a{async run(){if(!this.#t)return;let t=await v.select({message:this.#e,initialValue:this.#r,options:this.#n});v.isCancel(t)&&process.exit(0),this.#i(t)}get#t(){return this.config.branch_type.enable}get#e(){return"Select a branch type"}get#r(){return this.branch_state.type||this.config.commit_type.initial_value}get#n(){return this.config.commit_type.options}#i(t){this.branch_state.type=t}};import*as w from"@clack/prompts";var k=class extends a{async run(){if(!this.#t)return;let t=await w.text({message:this.#r,placeholder:"",validate:r=>this.#n(r),initialValue:this.branch_state.ticket});w.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_ticket.enable}get#e(){return this.config.branch_ticket.required}get#r(){return this.#e?"Type ticket / issue number":h("Type ticket / issue number")}#n(t){if(this.#e&&!t)return"Please enter a ticket / issue"}#i(t){this.branch_state.ticket=t}};import*as C from"@clack/prompts";var x=class extends a{async run(){if(!this.#t)return;let t=await C.text({message:this.#r,placeholder:"",validate:r=>this.#n(r),initialValue:this.branch_state.version});C.isCancel(t)&&process.exit(0),this.#i(t??"")}get#t(){return this.config.branch_version.enable}get#e(){return this.config.branch_version.required}get#r(){return this.#e?"Type version number":h("Type version number")}#n(t){if(this.#e&&!t)return"Please enter a version"}#i(t){this.branch_state.version=t}};import*as I from"@clack/prompts";var $=class extends a{async run(){let t=await I.text({message:this.#t,placeholder:"",validate:r=>this.#r(r),initialValue:this.branch_state.description});I.isCancel(t)&&process.exit(0),this.#n(t??"")}get#t(){return"Type a short description"}get#e(){return this.config.branch_description.max_length}#r(t){if(!t)return"Please enter a description";if(t.length>this.#e)return`Exceeded max length. Description max [${this.#e}]`}#n(t){this.branch_state.description=t.replace(/\s+/g,"-").toLowerCase()}};import*as m from"@clack/prompts";import{execSync as S}from"child_process";import p from"picocolors";import{chdir as rt}from"process";import{parse as X}from"@bomb.sh/args";var q=["user","type","description","ticket","branch-version","checkout"],Y=["git-dir","work-tree"],Z=["interactive","dry-run","help","version"],P=class{#t;constructor(t){this.#t=t}get interactive(){return!this.#t.no_interactive}get dry_run(){return this.#t.dry_run}get help(){return this.#t.help}get version(){return this.#t.version}get git_args(){return this.#t.git_args}get branch_state(){return this.#t.branch_state}},s=new P(tt(process.argv.slice(2)));function tt(e){let t=X(e,{alias:{h:"help",v:"version"},boolean:Z,string:[...q,...Y]}),r={};return q.forEach(n=>{let i=t[n];if(i){let o=n==="branch-version"?"version":n.replace("-","_");o==="checkout"?r[o]=i??"branch":r[o]=i}}),{help:t.help===!0,version:t.version===!0,git_args:et(t["git-dir"],t["work-tree"]),no_interactive:t.interactive===!1,dry_run:t["dry-run"]===!0,branch_state:r}}function et(e,t){return`${e?`--git-dir=${e}`:""} ${t?`--work-tree=${t}`:""}`.trim()}function j(e,t){let r="";return t.branch_order.forEach(n=>{let i=`branch_${n}`;e[n]&&(r+=e[n]+t[i].separator)}),r.endsWith("-")||r.endsWith("/")||r.endsWith("_")?r.slice(0,-1).trim():r.trim()}function W(e,t,r){let n=r.split("/").pop()||"repo",i=t.worktrees.folder_template;i=i.replace("{{repo_name}}",n).replace("{{branch_description}}",e.description).replace("{{user}}",e.user||"").replace("{{type}}",e.type||"").replace("{{ticket}}",e.ticket||"").replace("{{version}}",e.version||""),i=i.replace(/\s/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"");let o=t.worktrees.base_path;return`${o}${o.endsWith("/")?"":"/"}${i}`}var g=class extends a{async run(){this.#i(),this.#o(),this.#a()}get#t(){return this.branch_state.checkout==="worktree"}get#e(){return this.#t?this.config.worktree_pre_commands:this.config.branch_pre_commands}get#r(){return this.#t?this.config.worktree_post_commands:this.config.branch_post_commands}get#n(){return j(this.branch_state,this.config)}#i(){this.#s(this.#e,"Something went wrong when executing pre-commands: ")}#o(){let t=this.#n,r=this.#c(t);if(!this.#t){try{S(`git ${s.git_args} checkout ${r} ${t}`,{stdio:"inherit"}),m.log.info(`Switched to a new branch '${p.bgGreen(" "+p.black(t)+" ")}'`)}catch{process.exit(0)}return}try{let n=W(this.branch_state,this.config,u(s.git_args));S(`git ${s.git_args} worktree add ${n} ${r} ${t}`,{stdio:"inherit"}),m.log.info(`Created a new worktree ${p.bgGreen(" "+p.black(n)+" ")}, checked out branch ${p.bgGreen(" "+p.black(t)+" ")}`),m.log.info(p.bgMagenta(p.black(` cd ${n} `))+" to navigate to your new worktree"),rt(n)}catch{process.exit(0)}}#a(){this.#s(this.#r,"Something went wrong when executing post-commands: ")}#s(t,r){t.forEach(n=>{try{S(n,{stdio:"inherit"})}catch(i){m.log.error(r+i),process.exit(0)}})}#c(t){let r="";try{S(`git ${s.git_args} show-ref ${t}`,{encoding:"utf-8"}),m.log.warning(p.yellow(`${t} already exists! Checking out existing branch.`))}catch{r="-b"}return r}};import{execSync as nt}from"child_process";import c from"picocolors";var it={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print branch commands without creating a branch or worktree.","--help":"Show help information and exit."},ot={"--user":"Set branch username segment.","--type":"Set branch type (for example feat, fix, docs).","--description":"Set branch description segment.","--ticket":"Set branch ticket/issue segment.","--branch-version":"Set branch version segment.","--checkout":"Choose branch or worktree checkout mode."},st={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function N(e){let n=" ";return Object.entries(e).map(([i,o])=>{let B=Math.max(2,26-i.length);return`${n}${i}${" ".repeat(B)}${o}`}).join(`
3
+ `)}function M(e,t){let r=_(),n="(none)";try{n=nt(`git ${s.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let i=H(e.commit_type.options,s.git_args)||"Unknown",o=e.check_ticket.infer_ticket?D({append_hashtag:e.check_ticket.append_hashtag,prepend_hashtag:e.check_ticket.prepend_hashtag},s.git_args)||"Unknown":"Infer Disabled",B=e.commit_type.options.map(R=>R.value).join(", ").trim(),z=e.commit_scope.options.map(R=>R.value).join(", ").trim(),J=N(it),K=N(st),Q=N(ot);console.log(`
4
+ ${c.green("\uF489 better-branch")} ${c.gray("v"+r)}
5
+
6
+ ${c.gray("BRANCH")}
7
+ ${n}
8
+ ${c.gray("Type")} ${c.blue(i)} ${c.gray("\xB7")} ${c.gray("Ticket")} ${c.magenta(o)}
9
+
10
+ ${c.gray("CONFIGURATION")}
11
+ ${t}
12
+
13
+ ${c.gray("Types")}
14
+ ${B}
15
+
16
+ ${c.gray("Scopes")}
17
+ ${z}
18
+
19
+ ${c.gray("CLI FLAGS")}
20
+ ${J}
21
+
22
+ ${c.gray("Branch Flags")}
23
+ ${Q}
24
+
25
+ ${c.gray("Git Flags (Advanced)")}
26
+ ${K}
27
+
28
+ `)}import*as O from"@clack/prompts";var ht=[f,d,y,k,x,$,g],{config:mt,config_source:gt}=E(" better-branch ",s.git_args);ut(mt,gt);async function ut(e,t){if(ct(u(s.git_args)),s.version){let o=_();O.log.step("Better Commits v"+o);return}if(s.help){M(e,t);return}let r=U(T,s.branch_state);if(!s.interactive)try{U(V(e),r)}catch(o){o instanceof pt?O.log.error(`Invalid branch input: ${o.message}`):O.log.error(`Failed to validate branch input: ${o}`),process.exit(0)}let n=e.cache_last_value?new at("better-commits"):F,i=s.interactive?ht:[g];for(let o of i)await new o(e,r,n).run()}
@@ -0,0 +1,4 @@
1
+ import*as t from"valibot";import*as s from"valibot";var p="custom",d=["closes","trailer","breaking-change","deprecated","custom"],_=s.picklist(["branch","worktree"]),g=s.picklist(["closes","trailer","breaking-change","deprecated","custom"]),O=s.picklist(["user","version","type","ticket","description"]),U=s.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"}],S=[{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 E=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"),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())})),S)}),{}),t.rawCheck(({dataset:o,addIssue:e})=>{o.typed&&!o.value.options.some(n=>n.value===o.value.initial_value)&&e({message:`Type: initial_value "${o.value.initial_value}" must exist in options`})}),t.transform(o=>({...o,options:o.options.map(e=>({...e,label:e.emoji&&o.append_emoji_to_label?`${e.emoji} ${e.label}`:e.label}))}))),N=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"),options:t.optional(t.array(t.object({value:t.string(),label:t.optional(t.string()),hint:t.optional(t.string())})),y)}),{}),t.rawCheck(({dataset:o,addIssue:e})=>{if(!o.typed)return;let n=o.value.options.map(i=>i.value);o.value.custom_scope&&n.push(p),n.includes(o.value.initial_value)||e({message:`Scope: initial_value "${o.value.initial_value}" must exist in options`})}),t.transform(o=>{let e=o.options.map(n=>n.value);return o.custom_scope&&!e.includes(p)?{...o,options:[...o.options,{label:p,value:p,hint:"Write a custom scope"}]}:o})),m=t.object({check_status:t.optional(t.boolean(),!0),commit_type:E,commit_scope:N,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(g),[]),options:t.optional(t.array(g),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(["/","-","_"]),"/")}),{}),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(_,"branch"),branch_order:t.optional(t.array(O),C),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())}),{})}),I={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(),"")},J=t.optional(t.object(I),{}),j={user:t.optional(t.string(),""),type:t.optional(t.string(),""),ticket:t.optional(t.string(),""),description:t.optional(t.string(),""),version:t.optional(t.string(),""),checkout:t.optional(_,"branch")},Y=t.optional(t.object(j),{});import{parse as R}from"@bomb.sh/args";var k=["type","scope","title","body","closes","ticket","trailer","deprecates","breaking-title","breaking-body","deprecates-title","deprecates-body","custom-footer"],P=["git-dir","work-tree"],w=["interactive","dry-run","help","version"],f=class{#t;constructor(e){this.#t=e}get git_args(){return this.#t.git_args}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 commit_state(){return this.#t.commit_state}},b=new f(F(process.argv.slice(2)));function F(o){let e=R(o,{alias:{h:"help",v:"version"},boolean:w,string:[...k,...P]}),n={};return k.forEach(i=>{let a=e[i];if(a){let v=i.replace("-","_");n[v]=a}}),{help:e.help===!0,version:e.version===!0,git_args:L(e["git-dir"],e["work-tree"]),no_interactive:e.interactive===!1,dry_run:e["dry-run"]===!0,commit_state:n}}function L(o,e){return`${o?`--git-dir=${o}`:""} ${e?`--work-tree=${e}`:""}`.trim()}import*as r from"@clack/prompts";import{execSync as $}from"child_process";import c from"fs";import{homedir as V}from"os";import l from"picocolors";import{ValiError as B,parse as T}from"valibot";var A=".better-commits.json",rt=`${l.dim("(<space> to select)")}`,at=`${l.dim("(<space> to select, <a> to select all)")}`,lt=`${l.dim("(optional)")}`,st=[{value:"closes",label:"closes <issue/ticket>",hint:"Attempts to infer ticket from branch"},{value:"trailer",label:"trailer",hint:"Appends trailer based on commit type"},{value:"breaking-change",label:"breaking change",hint:"Add breaking change"},{value:"deprecated",label:"deprecated",hint:"Add deprecated change"},{value:"custom",label:"custom",hint:"Add a custom footer"}],pt=[{value:"branch",label:"Branch"},{value:"worktree",label:"Worktree"}],ct={get:()=>"",set:(o,e)=>{},clear:()=>{}};function vt(o=" better-commits ",e=b.git_args){console.clear(),r.intro(`${l.bgCyan(l.black(o))}`);let n=null,i=M();c.existsSync(i)&&(n=x(i));let v=`${D(e)}/${A}`;if(c.existsSync(v)){r.log.step("Reading from Repository Config");let u=x(v);return{config:n?{...u,overrides:n.overrides.shell?n.overrides:u.overrides,confirm_with_editor:n.confirm_with_editor,cache_last_value:n.cache_last_value}:u,config_source:"repository"}}if(n)return r.log.step("Reading from Global Config"),{config:n,config_source:"global"};let h=T(m,{});return r.log.step("Config not found. Generating default .better-commit.json at $HOME"),c.writeFileSync(i,JSON.stringify(h,null,4)),{config:h,config_source:"none"}}function x(o){let e=null;try{e=JSON.parse(c.readFileSync(o,"utf8"))}catch(n){r.log.error(`Invalid JSON file. Exiting.
2
+ `+n),process.exit(0)}return H(e)}function H(o){try{return T(m,o)}catch(e){if(e instanceof B){let i=(e.issues[0].path??[]).map(a=>a.key).filter(a=>typeof a=="string"||typeof a=="number").join(".");r.log.error(`Invalid Configuration: ${l.red(i)}
3
+ `+e.message)}process.exit(0)}}function D(o=b.git_args){let e=".";try{e=$(`git ${o} rev-parse --show-toplevel`).toString().trim()}catch{r.log.warn("Could not find git root. If in a --bare repository, ignore this warning.")}return e}function M(){return V()+"/"+A}function ut(){try{return JSON.parse(c.readFileSync(new URL("../package.json",import.meta.url),"utf8")).version??"unknown"}catch{return"unknown"}}function _t(o,e){return e===o.length-1?"":`
4
+ `}function gt(o){let e=o.trim();return e.endsWith(".")?e.substring(0,e.length-1).trim():o.trim()}function mt(o,e){try{return o.get(e)??""}catch{r.log.warn(`Could not access ${e} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}return""}function ft(o,e,n){try{o.set(e,n)}catch{r.log.warn(`Could not access ${e} from cache. Check that "~/.config" exists. Set "cache_last_value" to false to disable.`)}}export{p as a,m as b,I as c,J as d,j as e,Y as f,b as g,A as h,st as i,pt as j,ct as k,vt as l,D as m,ut as n,_t as o,gt as p,mt as q,ft as r};
@@ -0,0 +1 @@
1
+ import{c as m,e as u,g as p}from"./chunk-OFJCRS3N.js";import*as s from"valibot";function _(t,n){let i=t.scope?t.scope.length+2:0,e=t.type?.length??0,r=n.include_ticket?t.ticket?.length??0:0,c=t.title?.length??0;return i+e+r+c}function a(t){return t.map(i=>i===""?'"" (none)':`"${i}"`).join(", ")}function R(t){let n=t.commit_type.options.map(e=>e.value),i=t.commit_scope.options.map(e=>e.value);return s.pipe(s.object(m),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.type?`"${e.value.type}"`:"(empty)";e.value.type&&!n.includes(e.value.type)&&r({message:`Invalid --type ${c}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=e.value.scope?`"${e.value.scope}"`:"(empty)";e.value.scope&&!t.commit_scope.custom_scope&&!i.includes(e.value.scope)&&r({message:`Invalid --scope ${c}. Valid scopes: ${a(i)}.`})}),s.rawCheck(({dataset:e,addIssue:r})=>{!e.typed||e.value.title.trim()||r({message:"Missing --title. Provide a non-empty commit title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{if(!e.typed)return;let c=_(e.value,{include_ticket:t.check_ticket.add_to_title});c>t.commit_title.max_size&&r({message:`Title exceeds max width. Current size is ${c}, max is ${t.commit_title.max_size} (includes type, scope, and ticket when enabled).`})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&t.commit_body.required&&!e.value.body.trim()&&r({message:"Missing --body. commit_body.required is enabled in config."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.closes&&!e.value.ticket&&r({message:'Invalid footer values: --closes requires --ticket (for example: --ticket "ABC-123").'})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.breaking_body&&!e.value.breaking_title&&r({message:"Invalid breaking change values: --breaking-body requires --breaking-title."})}),s.rawCheck(({dataset:e,addIssue:r})=>{e.typed&&e.value.deprecates_body&&!e.value.deprecates_title&&r({message:"Invalid deprecation values: --deprecates-body requires --deprecates-title."})}))}function q(t){let n=t.commit_type.options.map(i=>i.value);return s.pipe(s.object(u),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.type?`"${i.value.type}"`:"(empty)";i.value.type&&!n.includes(i.value.type)&&e({message:`Invalid --type ${r}. Valid types: ${a(n)}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{!i.typed||i.value.description.trim()||e({message:"Missing --description. Provide a non-empty branch description."})}),s.rawCheck(({dataset:i,addIssue:e})=>{if(!i.typed)return;let r=i.value.description.trim();r.length>t.branch_description.max_length&&e({message:`Description exceeds max length. Current length is ${r.length}, max is ${t.branch_description.max_length}.`})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_user.required&&!i.value.user.trim()&&e({message:"Missing --user. branch_user.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_ticket.required&&!i.value.ticket.trim()&&e({message:"Missing --ticket. branch_ticket.required is enabled in config."})}),s.rawCheck(({dataset:i,addIssue:e})=>{i.typed&&t.branch_version.required&&!i.value.version.trim()&&e({message:"Missing --branch-version. branch_version.required is enabled in config."})}))}import{execSync as h}from"child_process";var f=/\/(\w+-\d+)/,v=/^(\w+-\d+)/,y=/^([A-Z]+-[\[a-zA-Z\]\d]+)_/,k=/\/([A-Z]+-[\[a-zA-Z\]\d]+)_/,b=/\/(\d+)/,$=/^(\d+)/;function H(t){if(p.interactive)return;let n={ticket:"",type:""};if(t.check_ticket.infer_ticket){let e=w({append_hashtag:t.check_ticket.append_hashtag,prepend_hashtag:t.check_ticket.prepend_hashtag},p.git_args);n.ticket=e}let i=C(t.commit_type.options,p.git_args);return n.type=i,n}function C(t,n){let i=l(n);return i?E(i,t.map(e=>e.value)):""}function w(t,n){let i=l(n);return i?x(i,t):""}function x(t,n){let i=[t.match(y),t.match(k),t.match(f),t.match(b),t.match(v),t.match($)].filter(e=>e!=null).map(e=>e&&e.length>=2?e[1]:"");return!i.length||!i[0]?"":n.append_hashtag||n.prepend_hashtag==="Always"?`#${i[0]}`:i[0]}function E(t,n){return n.find(e=>{let r=new RegExp(`^${e}-`),c=new RegExp(`-${e}-`),g=new RegExp(`${e}/`);return[t.match(r),t.match(c),t.match(g)].filter(d=>d!=null).length>0})??""}function l(t){try{return h(`git ${t} branch --show-current`,{stdio:"pipe"}).toString().trim()}catch{return""}}import o from"picocolors";function X(t){return`${t} ${o.dim("\xB7 restored from cache")}`}function U(t){return`${t} ${o.dim("\xB7 inferred from branch")}`}function Z(t){return`${t} ${o.dim("\xB7 optional")}`}function j(t){return`${t} ${o.dim("\xB7 <space> to select")}`}function D(t){return`${t} ${o.dim("\xB7 dry run - changes will not be committed")}`}export{_ as a,R as b,q as c,H as d,C as e,w as f,X as g,U as h,Z as i,j,D as k};
package/dist/index.js CHANGED
@@ -1,32 +1,57 @@
1
1
  #! /usr/bin/env node
2
- import{a as A,c as T,e as g,g as x,h as b,j as R,k as v,l as P,m as j,n as G,o as N,p as D,r as I,s as W,t as M,u as V,v as C,w as H,x as k,y}from"./chunk-K2RPF2JY.js";import*as s from"@clack/prompts";import l from"picocolors";import{execSync as w}from"child_process";import{chdir as q}from"process";import{parse as K}from"valibot";import{execSync as X}from"child_process";import*as $ from"@clack/prompts";import E from"picocolors";var L=["M","T","R","D","A","C"];function S(){let e="";try{e=X(`git ${g.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(u){return $.log.error(E.red("Failed to git status"+u)),{index:[],work_tree:[]}}let t=e.split(`
3
- `),o=[],f=[];return t.forEach(u=>{let a=u.trimEnd();if(!a)return;let p=a.substring(2).trim(),h=a.charAt(0).trim(),i=a.charAt(1).trim();(h==="?"||i==="?")&&o.push(p),L.includes(h)&&f.push(p),L.includes(i)&&o.push(p)}),{index:f,work_tree:o}}function F(e){let t=e.join(" ");if(t)try{X(`git ${g.git_args} add ${t}`,{stdio:"pipe"}).toString(),$.log.success(E.green("Changes successfully staged"))}catch{$.log.error(E.red("Failed to stage changes"))}}import Y from"configstore";J(W());async function J(e){let t=K(T,{});q(V());let o=e.cache_last_value?new Y("better-commits"):I;if(e.check_status){let{index:i,work_tree:r}=S();s.log.step(l.black(l.bgGreen(" Checking Git Status ")));let n=i.reduce((c,m,d)=>l.green(c+m+C(i,d)),"");if(s.log.success(`Changes to be committed:
4
- `+n),r.length){let c=r.reduce((d,U,B)=>l.red(d+U+C(r,B)),"");s.log.error(`Changes not staged for commit:
5
- `+c);let m=await s.multiselect({message:`Some files have not been staged, would you like to add them now? ${x}`,options:[{value:".",label:"."},...r.map(d=>({value:d,label:d}))],required:!1});s.isCancel(m)&&process.exit(0),F(m)}S().index.length||(s.log.error(l.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}let f=e.commit_type.options.reduce((i,r)=>({...i,[r.value]:{emoji:r.emoji??"",trailer:r.trailer??""}}),{});if(e.commit_type.enable){let i="Select a commit type",r=e.commit_type.initial_value;if(e.commit_type.infer_type_from_branch){let _=e.commit_type.options.map(m=>m.value),c=M(_);c&&(i=`Commit type inferred from branch ${l.dim("(confirm / edit)")}`,r=c)}let n=await s.select({message:i,initialValue:k(o,"commit_type")||r,maxItems:e.commit_type.max_items,options:e.commit_type.options});s.isCancel(n)&&process.exit(0),y(o,"commit_type",n),t.trailer=f[n].trailer,t.type=e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="Start"?`${f[n].emoji} ${n}`.trim():n}if(e.commit_scope.enable){let i=await s.select({message:"Select a commit scope",initialValue:k(o,"commit_scope")||e.commit_scope.initial_value,maxItems:e.commit_scope.max_items,options:e.commit_scope.options});s.isCancel(i)&&process.exit(0),y(o,"commit_scope",i),i===A&&e.commit_scope.custom_scope&&(i=await s.text({message:"Write a custom scope",placeholder:""}),s.isCancel(i)&&process.exit(0)),t.scope=i}if(e.check_ticket.infer_ticket)try{let i=w(`git ${g.git_args} branch --show-current`,{stdio:"pipe"}).toString(),r=[i.match(P),i.match(j),i.match(R),i.match(G),i.match(v),i.match(N)].filter(n=>n!=null).map(n=>n&&n.length>=2?n[1]:"");r.length&&r[0]&&(t.ticket=e.check_ticket.append_hashtag||e.check_ticket.prepend_hashtag==="Prompt"?"#"+r[0]:r[0])}catch{}if(e.check_ticket.confirm_ticket){let i=await s.text({message:t.ticket?`Ticket / issue inferred from branch ${l.dim("(confirm / edit)")}`:`Add ticket / issue ${b}`,placeholder:"",initialValue:k(o,"commit_ticket")||t.ticket});s.isCancel(i)&&process.exit(0),y(o,"commit_ticket",i),t.ticket=i??""}e.check_ticket.prepend_hashtag==="Always"&&t.ticket&&!t.ticket.startsWith("#")&&(t.ticket="#"+t.ticket);let u=await s.text({message:"Write a brief title describing the commit",initialValue:k(o,"commit_title")||"",placeholder:"",validate:i=>{if(!i)return"Please enter a title";let r=t.scope?t.scope.length+2:0,n=t.type.length,_=e.check_ticket.add_to_title?t.ticket.length:0;if(r+n+_+i.length>e.commit_title.max_size)return`Exceeded max length. Title max [${e.commit_title.max_size}]`}});s.isCancel(u)&&process.exit(0),y(o,"commit_title",u);let a=u;if(e.commit_type.append_emoji_to_commit&&e.commit_type.emoji_commit_position==="After-Colon"&&(a=`${f[t.type].emoji} ${u}`),t.title=H(a),e.commit_body.enable){let i=await s.text({message:`Write a detailed description of the changes ${b}`,initialValue:k(o,"commit_body")||"",placeholder:"",validate:r=>{if(e.commit_body.required&&!r)return"Please enter a description"}});if(s.isCancel(i)&&process.exit(0),t.body=i??"",e.commit_body.split_by_period){let r=t.body.split(/\.\s+/).map(n=>n.trim());t.body=r.join(`.
6
- `)}y(o,"commit_body",i)}if(e.commit_footer.enable){let i=k(o,"commit_footer").split(","),r=await s.multiselect({message:`Select optional footers ${x}`,initialValues:i||e.commit_footer.initial_value,options:D,required:!1});if(s.isCancel(r)&&process.exit(0),y(o,"commit_footer",r.join(",")),r.includes("breaking-change")){let n=await s.text({message:"Breaking changes: Write a short title / summary",placeholder:"",validate:c=>{if(!c)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Breaking Changes: Write a description & migration instructions ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.breaking_title=n,t.breaking_body=_}if(r.includes("deprecated")){let n=await s.text({message:"Deprecated: Write a short title / summary",placeholder:"",validate:c=>{if(!c)return"Please enter a title / summary"}});s.isCancel(n)&&process.exit(0);let _=await s.text({message:`Deprecated: Write a description ${b}`,placeholder:""});s.isCancel(_)&&process.exit(0),t.deprecates_body=_,t.deprecates_title=n}if(r.includes("closes")&&(t.closes="Closes:"),r.includes("custom")){let n=await s.text({message:"Write a custom footer",placeholder:""});s.isCancel(n)&&process.exit(0),t.custom_footer=n}r.includes("trailer")||(t.trailer="")}if(e.confirm_with_editor){let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r} --edit`,i),process.exit(0)}let p=!0;e.print_commit_output&&s.note(O(t,e,!0,!1,!0),"Commit Preview"),e.confirm_commit&&(p=await s.confirm({message:"Confirm Commit?"}),s.isCancel(p)&&process.exit(0)),p||(s.log.info("Exiting without commit"),process.exit(0));try{s.log.info("Committing changes...");let i=e.overrides.shell?{shell:e.overrides.shell,stdio:"inherit"}:{stdio:"inherit"},r=t.trailer?`--trailer="${t.trailer}"`:"";w(`git ${g.git_args} commit -m "${O(t,e,!1,!0,!1)}" ${r}`,i)}catch(i){s.log.error("Something went wrong when committing: "+i);return}s.log.success("Commit Complete");let h=o.get("username");o.clear(),h&&o.set("username",h)}function O(e,t,o=!1,f=!1,u=!1){let a="";if(e.type&&(a+=o?l.blue(e.type):e.type),e.scope){let c=o?l.cyan(e.scope):e.scope;a+=`(${c})`}let p=e.ticket,h=t.check_ticket.surround;if(e.ticket&&h){let c=h.charAt(0),m=h.charAt(1);p=`${c}${e.ticket}${m}`}let i=t.check_ticket.title_position==="beginning";p&&t.check_ticket.add_to_title&&i&&(a=`${o?l.magenta(p):p} ${a}`);let r=t.check_ticket.title_position==="before-colon";if(p&&t.check_ticket.add_to_title&&r){let c=e.scope||e.type&&!t.check_ticket.surround?" ":"";a+=o?l.magenta(c+p):c+p}e.breaking_title&&t.breaking_change.add_exclamation_to_title&&(a+=o?l.red("!"):"!"),(e.scope||e.type||p&&r)&&(a+=": ");let n=t.check_ticket.title_position==="start",_=t.check_ticket.title_position==="end";if(p&&t.check_ticket.add_to_title&&n&&(a+=o?l.magenta(p)+" ":p+" "),e.title&&(a+=o?l.reset(e.title):e.title),p&&t.check_ticket.add_to_title&&_&&(a+=" "+(o?l.magenta(p):p)),e.body){let m=e.body.split("\\n").map(d=>o?l.reset(d.trim()):d.trim()).join(`
7
- `);a+=o?`
2
+ import{a as nt,b as at,d as ct,e as F,f as P,g as f,h as A,i as y,j as $,k as Y}from"./chunk-SIF4LZUS.js";import{a as Z,d as z,g as s,i as tt,k as et,l as it,m as ot,n as I,o as rt,p as st,q as g,r as u}from"./chunk-OFJCRS3N.js";import{chdir as kt}from"process";import*as H from"@clack/prompts";import{ValiError as vt,parse as ut}from"valibot";import Ct from"configstore";import*as T from"@clack/prompts";var m=class{constructor(t,e,o){this.config=t;this.commit_state=e;this.prompt_cache=o}};var R=class extends m{async run(){if(this.#o){let{initial_value:t,message:e}=this.#e,o=await T.select({message:e,initialValue:t,maxItems:this.#r,options:this.#t});T.isCancel(o)&&process.exit(0),this.#s(o)}}get#o(){return this.config.commit_type.enable}get#e(){let t=g(this.prompt_cache,"commit_type");if(t)return{initial_value:t,message:f("Commit type")};if(this.config.commit_type.infer_type_from_branch){let e=F(this.#t,s.git_args);if(e)return{message:A("Commit type"),initial_value:e}}return{initial_value:this.config.commit_type.initial_value,message:"Select a commit type"}}get#t(){return this.config.commit_type.options}get#i(){return this.#t.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??"",trailer:e.trailer??""}}),{})}get#r(){return this.config.commit_type.max_items}#s(t){u(this.prompt_cache,"commit_type",t);let e=this.#i;this.commit_state.trailer=e[t].trailer,this.commit_state.type=this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="Start"?`${e[t].emoji} ${t}`.trim():t}};import*as k from"@clack/prompts";var j=class extends m{async run(){if(!this.#o)return;let{initial_value:t,message:e}=this.#e(),o=await k.select({message:e,initialValue:t,maxItems:this.#t,options:this.#i});k.isCancel(o)&&process.exit(0),await this.#s(o)}get#o(){return this.config.commit_scope.enable}#e(){let t=g(this.prompt_cache,"commit_scope");return t?{initial_value:t,message:f("Commit scope")}:{initial_value:this.config.commit_scope.initial_value,message:"Select a commit scope"}}get#t(){return this.config.commit_scope.max_items}get#i(){return this.config.commit_scope.options}get#r(){return this.config.commit_scope.custom_scope}async#s(t){u(this.prompt_cache,"commit_scope",t);let e=t;if(e===Z&&this.#r){let o=await k.text({message:"Write a custom scope",placeholder:""});k.isCancel(o)&&process.exit(0),e=o??""}this.commit_state.scope=e}};import*as N from"@clack/prompts";var E=class extends m{async run(){let{initial_value:t,message:e}=this.#i();if(this.commit_state.ticket=t,this.#e){let o=await N.text({message:e,placeholder:"",initialValue:t});N.isCancel(o)&&process.exit(0),u(this.prompt_cache,"commit_ticket",o),this.commit_state.ticket=o??""}this.#t&&this.commit_state.ticket&&!this.commit_state.ticket.startsWith("#")&&(this.commit_state.ticket="#"+this.commit_state.ticket)}get#o(){return this.config.check_ticket.infer_ticket}get#e(){return this.config.check_ticket.confirm_ticket}get#t(){return this.config.check_ticket.prepend_hashtag==="Always"}#i(){let t=g(this.prompt_cache,"commit_ticket");if(t)return{initial_value:t,message:f("Ticket / issue")};if(this.#o){let e=P({append_hashtag:this.config.check_ticket.append_hashtag,prepend_hashtag:this.config.check_ticket.prepend_hashtag},s.git_args);if(e)return{initial_value:e,message:A("Ticket / issue")}}return{initial_value:this.commit_state.ticket,message:y("Add ticket / issue")}}};import*as G from"@clack/prompts";var D=class extends m{async run(){let{initial_value:t,message:e}=this.#o(),o=await G.text({message:e,initialValue:t,placeholder:"",validate:a=>this.#e(a)});G.isCancel(o)&&process.exit(0),this.#n(o??"")}#o(){let t=g(this.prompt_cache,"commit_title");return t?{initial_value:t,message:f("Commit title")}:{initial_value:this.commit_state.title,message:"Write a brief title describing the commit"}}#e(t){if(!t)return"Please enter a title";if(this.#i(t)>this.#t)return`Exceeded max length. Title max [${this.#t}]`}get#t(){return this.config.commit_title.max_size}#i(t){return nt({type:this.commit_state.type,scope:this.commit_state.scope,ticket:this.commit_state.ticket,title:t},{include_ticket:this.config.check_ticket.add_to_title})}get#r(){return this.config.commit_type.options.reduce((t,e)=>({...t,[e.value]:{emoji:e.emoji??""}}),{})}#s(t){return this.config.commit_type.append_emoji_to_commit&&this.config.commit_type.emoji_commit_position==="After-Colon"?`${this.#r[this.commit_state.type]?.emoji??""} ${t}`.trim():t}#n(t){u(this.prompt_cache,"commit_title",t),this.commit_state.title=st(this.#s(t))}};import*as L from"@clack/prompts";var M=class extends m{async run(){if(!this.#o)return;let{initial_value:t,message:e}=this.#e(),o=await L.text({message:e,initialValue:t,placeholder:"",validate:a=>this.#t(a)});L.isCancel(o)&&process.exit(0),this.#r(o??"")}get#o(){return this.config.commit_body.enable}#e(){let t=g(this.prompt_cache,"commit_body");return t?{initial_value:t,message:f("Commit body")}:{initial_value:"",message:y("Write a detailed description of the changes")}}#t(t){if(this.config.commit_body.required&&!t)return"Please enter a description"}#i(t){return this.config.commit_body.split_by_period?t.split(/\.\s+/).map(o=>o.trim()).join(`.
3
+ `):t}#r(t){u(this.prompt_cache,"commit_body",t),this.commit_state.body=this.#i(t)}};import*as h from"@clack/prompts";var V=class extends m{async run(){if(!this.#o)return;let{initial_values:t,message:e}=this.#i(),o=await h.multiselect({message:e,initialValues:t,options:this.#e,required:!1});h.isCancel(o)&&process.exit(0);let a=this.#s(o),r=await this.#n(a);this.#m(o,a,r)}get#o(){return this.config.commit_footer.enable}get#e(){let t=new Set(this.config.commit_footer.options);return tt.filter(e=>t.has(e.value))}get#t(){return this.#e.map(t=>t.value)}#i(){let t=g(this.prompt_cache,"commit_footer");return t?{initial_values:this.#r(t),message:$(f("Commit footers"))}:{initial_values:this.config.commit_footer.initial_value.filter(o=>this.#t.includes(o)),message:$(y("Select optional footers"))}}#r(t){return t.split(",").map(e=>e.trim()).filter(e=>this.#t.includes(e))}#s(t){return{includes_breaking_change:t.includes("breaking-change"),includes_deprecated:t.includes("deprecated"),includes_closes:t.includes("closes"),includes_custom:t.includes("custom"),includes_trailer:t.includes("trailer")}}async#n(t){let e={breaking_title:"",breaking_body:"",deprecated_title:"",deprecated_body:"",custom_footer:""};return t.includes_breaking_change&&(e.breaking_title=await this.#c("Breaking changes: Write a short title / summary"),e.breaking_body=await this.#a(y("Breaking Changes: Write a description & migration instructions"))),t.includes_deprecated&&(e.deprecated_title=await this.#c("Deprecated: Write a short title / summary"),e.deprecated_body=await this.#a(y("Deprecated: Write a description"))),t.includes_custom&&(e.custom_footer=await this.#a("Write a custom footer")),e}async#c(t){let e=await h.text({message:t,placeholder:"",validate:o=>{if(!o)return"Please enter a title / summary"}});return h.isCancel(e)&&process.exit(0),e??""}async#a(t){let e=await h.text({message:t,placeholder:""});return h.isCancel(e)&&process.exit(0),e??""}#m(t,e,o){u(this.prompt_cache,"commit_footer",t.join(",")),this.commit_state.breaking_title=o.breaking_title,this.commit_state.breaking_body=o.breaking_body,this.commit_state.deprecates_title=o.deprecated_title,this.commit_state.deprecates_body=o.deprecated_body,this.commit_state.custom_footer=o.custom_footer,this.commit_state.closes=e.includes_closes?"Closes:":"",e.includes_trailer||(this.commit_state.trailer="")}};import*as d from"@clack/prompts";import{execSync as mt}from"child_process";import p from"picocolors";function J({commit_state:i,config:t,colorize:e=!1,escape_quotes:o=!1,include_trailer:a=!1}){let r="";if(i.type&&(r+=e?p.blue(i.type):i.type),i.scope){let c=e?p.cyan(i.scope):i.scope;r+=`(${c})`}let n=i.ticket,l=t.check_ticket.surround;if(i.ticket&&l){let c=l.charAt(0),C=l.charAt(1);n=`${c}${i.ticket}${C}`}let v=t.check_ticket.title_position==="beginning";n&&t.check_ticket.add_to_title&&v&&(r=`${e?p.magenta(n):n} ${r}`);let w=t.check_ticket.title_position==="before-colon";if(n&&t.check_ticket.add_to_title&&w){let c=i.scope||i.type&&!t.check_ticket.surround?" ":"";r+=e?p.magenta(c+n):c+n}i.breaking_title&&t.breaking_change.add_exclamation_to_title&&(r+=e?p.red("!"):"!"),(i.scope||i.type||n&&w)&&(r+=": ");let U=t.check_ticket.title_position==="start",K=t.check_ticket.title_position==="end";if(n&&t.check_ticket.add_to_title&&U&&(r+=e?p.magenta(n)+" ":n+" "),i.title&&(r+=e?p.reset(i.title):i.title),n&&t.check_ticket.add_to_title&&K&&(r+=" "+(e?p.magenta(n):n)),i.body){let C=i.body.split("\\n").map(x=>e?p.reset(x.trim()):x.trim()).join(`
4
+ `);r+=`
8
5
 
9
- ${m}`:`
6
+ ${C}`}if(i.breaking_title){let c=e?p.red(`BREAKING CHANGE: ${i.breaking_title}`):`BREAKING CHANGE: ${i.breaking_title}`;r+=`
10
7
 
11
- ${m}`}if(e.breaking_title){let c=o?l.red(`BREAKING CHANGE: ${e.breaking_title}`):`BREAKING CHANGE: ${e.breaking_title}`;a+=`
8
+ ${c}`}if(i.breaking_body){let c=e?p.red(i.breaking_body):i.breaking_body;r+=`
12
9
 
13
- ${c}`}if(e.breaking_body){let c=o?l.red(e.breaking_body):e.breaking_body;a+=`
10
+ ${c}`}if(i.deprecates_title){let c=e?p.yellow(`DEPRECATED: ${i.deprecates_title}`):`DEPRECATED: ${i.deprecates_title}`;r+=`
14
11
 
15
- ${c}`}if(e.deprecates_title){let c=o?l.yellow(`DEPRECATED: ${e.deprecates_title}`):`DEPRECATED: ${e.deprecates_title}`;a+=`
12
+ ${c}`}if(i.deprecates_body){let c=e?p.yellow(i.deprecates_body):i.deprecates_body;r+=`
16
13
 
17
- ${c}`}if(e.deprecates_body){let c=o?l.yellow(e.deprecates_body):e.deprecates_body;a+=`
14
+ ${c}`}if(i.custom_footer){let C=i.custom_footer.split("\\n").map(x=>e?p.reset(x.trim()):x.trim()).join(`
15
+ `);r+=`
18
16
 
19
- ${c}`}if(e.custom_footer){let m=e.custom_footer.split("\\n").map(d=>o?l.reset(d.trim()):d.trim()).join(`
20
- `);a+=o?`
17
+ ${C}`}return i.closes&&i.ticket&&(r+=e?`
21
18
 
22
- ${m}`:`
19
+ ${p.reset(i.closes)} ${p.magenta(i.ticket)}`:`
23
20
 
24
- ${m}`}return e.closes&&e.ticket&&(a+=o?`
21
+ ${i.closes} ${i.ticket}`),a&&i.trailer&&(r+=e?`
25
22
 
26
- ${l.reset(e.closes)} ${l.magenta(e.ticket)}`:`
23
+ ${p.dim(i.trailer)}`:`
27
24
 
28
- ${e.closes} ${e.ticket}`),u&&e.trailer&&(a+=o?`
25
+ ${i.trailer}`),o&&(r=r.replaceAll('"','\\"').replaceAll("`","\\`")),r}var O=class extends m{async run(){this.#o&&(mt(`${this.#n} --edit`,this.#i),process.exit(0)),this.#e&&d.note(J({commit_state:this.commit_state,config:this.config,colorize:!0,escape_quotes:!1,include_trailer:!0}),"Commit Preview"),await this.#a()||(d.log.info("Exiting without commit"),process.exit(0));try{d.log.info(s.dry_run?Y("Committing changes..."):"Committing changes..."),mt(this.#n,s.dry_run?this.#r:this.#i)}catch(e){d.log.error("Something went wrong when committing: "+e);return}this.#m()}get#o(){return s.interactive&&this.config.confirm_with_editor}get#e(){return this.config.print_commit_output}get#t(){return this.config.confirm_commit}get#i(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"inherit"}:{stdio:"inherit"}}get#r(){return this.config.overrides.shell?{shell:this.config.overrides.shell,stdio:"pipe"}:{stdio:"pipe"}}get#s(){return this.commit_state.trailer?`--trailer="${this.commit_state.trailer}"`:""}get#n(){return`git ${s.git_args} commit -m "${J({commit_state:this.commit_state,config:this.config,colorize:!1,escape_quotes:!0,include_trailer:!1})}" ${this.#s} ${this.#c}`.trim()}get#c(){return s.dry_run?"--dry-run --porcelain --untracked-files=no":""}async#a(){if(!s.interactive||!this.#t)return!0;let t=await d.confirm({message:s.dry_run?Y("Confirm Commit?"):"Confirm Commit?"});return d.isCancel(t)&&process.exit(0),t}#m(){d.log.success("Commit Complete");let t=this.prompt_cache.get("username");this.prompt_cache.clear(),t&&this.prompt_cache.set("username",t)}};import*as b from"@clack/prompts";import S from"picocolors";import{execSync as lt}from"child_process";import*as W from"@clack/prompts";import Q from"picocolors";var pt=["M","T","R","D","A","C"];function X(){let i="";try{i=lt(`git ${s.git_args} status --porcelain`,{stdio:"pipe"}).toString()}catch(a){return W.log.error(Q.red("Failed to git status"+a)),{index:[],work_tree:[]}}let t=i.split(`
26
+ `),e=[],o=[];return t.forEach(a=>{let r=a.trimEnd();if(!r)return;let n=r.substring(2).trim(),l=r.charAt(0).trim(),v=r.charAt(1).trim();(l==="?"||v==="?")&&e.push(n),pt.includes(l)&&o.push(n),pt.includes(v)&&e.push(n)}),{index:o,work_tree:e}}function _t(i){let t=i.join(" ");if(t)try{lt(`git ${s.git_args} add ${t}`,{stdio:"pipe"}).toString(),W.log.success(Q.green("Changes successfully staged"))}catch{W.log.error(Q.red("Failed to stage changes"))}}var q=class extends m{async run(){if(!this.#o)return;let t=X();if(this.#e(t),t.work_tree.length){let e=await this.#i(t.work_tree);e.length&&_t(e)}this.#r()}get#o(){return this.config.check_status}#e(t){b.log.step(S.black(S.bgGreen(" Checking Git Status ")));let e=this.#t(t.index,S.green);if(b.log.success(`Changes to be committed:
27
+ `+e),!t.work_tree.length)return;let o=this.#t(t.work_tree,S.red);b.log.error(`Changes not staged for commit:
28
+ `+o)}#t(t,e){return t.reduce((o,a,r)=>e(o+a+rt(t,r)),"")}async#i(t){let e=await b.multiselect({message:$("Some files have not been staged, would you like to add them now?"),options:[{value:".",label:"."},...t.map(o=>({value:o,label:o}))],required:!1});return b.isCancel(e)&&process.exit(0),e}#r(){X().index.length||(b.log.error(S.red('no changes added to commit (use "git add" and/or "git commit -a")')),process.exit(0))}};import{execSync as ft}from"child_process";import _ from"picocolors";var dt={"better-branch":"Create a branch or worktree from a guided prompt flow.","better-commits-init":"Create a .better-commits.json config in this repository."},ht={"--interactive":"Run in interactive prompt mode (default behavior).","--dry-run":"Print the commit command without creating a commit.","--help":"Show help information and exit."},bt={"--type":"Set commit type (for example feat, fix, docs).","--scope":"Set commit scope.","--title":"Set commit title/description.","--body":"Set commit body text.","--closes":"Set issue/ticket id for a closes footer.","--ticket":"Set ticket value used in the title.","--trailer":"Set trailer footer value.","--deprecates":"Set issue/ticket id for a deprecates footer.","--breaking-title":"Set breaking-change title footer.","--breaking-body":"Set breaking-change body footer.","--deprecates-title":"Set deprecates footer title text.","--deprecates-body":"Set deprecates footer body text.","--custom-footer":"Set a custom footer line."},yt={"--git-dir":"Set the path to the .git directory.","--work-tree":"Set the path to the working tree root."};function B(i){let o=" ";return Object.entries(i).map(([a,r])=>{let n=Math.max(2,26-a.length);return`${o}${a}${" ".repeat(n)}${r}`}).join(`
29
+ `)}function gt(i,t){let e=I(),o="(none)";try{o=ft(`git ${s.git_args} branch --show-current`,{stdio:"pipe"}).toString().trim()||"(none)"}catch{}let a=F(i.commit_type.options,s.git_args)||"Unknown",r=i.check_ticket.infer_ticket?P({append_hashtag:i.check_ticket.append_hashtag,prepend_hashtag:i.check_ticket.prepend_hashtag},s.git_args)||"Unknown":"Infer Disabled",n=i.commit_type.options.map(c=>c.value).join(", ").trim(),l=i.commit_scope.options.map(c=>c.value).join(", ").trim(),v=B(ht),w=B(yt),U=B(bt),K=B(dt);console.log(`
30
+ ${_.green("\uF489 better-commits")} ${_.gray("v"+e)}
29
31
 
30
- ${l.dim(e.trailer)}`:`
32
+ ${_.gray("BRANCH")}
33
+ ${o}
34
+ ${_.gray("Type")} ${_.blue(a)} ${_.gray("\xB7")} ${_.gray("Ticket")} ${_.magenta(r)}
31
35
 
32
- ${e.trailer}`),f&&(a=a.replaceAll('"','\\"').replaceAll("`","\\`")),a}export{J as main};
36
+ ${_.gray("CONFIGURATION")}
37
+ ${t}
38
+
39
+ ${_.gray("Types")}
40
+ ${n}
41
+
42
+ ${_.gray("Scopes")}
43
+ ${l}
44
+
45
+ ${_.gray("CLI FLAGS")}
46
+ ${v}
47
+
48
+ ${_.gray("Commit Flags")}
49
+ ${U}
50
+
51
+ ${_.gray("Git Flags (Advanced)")}
52
+ ${w}
53
+
54
+ ${_.gray("ADDITIONAL COMMANDS")}
55
+ ${K}
56
+
57
+ `)}var xt=[q,R,j,E,D,M,V,O],{config:$t,config_source:Ot}=it();St($t,Ot);async function St(i,t){if(kt(ot()),s.version){let l=I();H.log.step("Better Commits v"+l);return}if(s.help){gt(i,t);return}let e=ct(i),o={...s.commit_state,type:(s.commit_state.type||e?.type)??"",ticket:(s.commit_state.ticket||e?.ticket)??""},a=ut(z,o);if(!s.interactive)try{ut(at(i),a)}catch(l){l instanceof vt?H.log.error(`Invalid --no-interactive commit input: ${l.message}`):H.log.error(`Failed to validate --no-interactive commit input: ${l}`),process.exit(0)}let r=i.cache_last_value?new Ct("better-commits"):et,n=s.interactive?xt:[O];for(let l of n)await new l(i,a,r).run()}export{St as main};