better-commits 1.20.0-cli-flags → 1.20.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/docs/valibot.md DELETED
@@ -1,228 +0,0 @@
1
- # Valibot Usage
2
-
3
- `better-commits` uses [`valibot`](https://valibot.dev) (`^0.30.0`) for all runtime schema validation, type inference, and config parsing. Valibot defines the shape of every configuration object, commit state, and branch state in the application.
4
-
5
- ## Files
6
-
7
- | File | Role |
8
- | ----------------------- | ------------------------------------------------------------------ |
9
- | `src/valibot-consts.ts` | Shared picklist schemas and constant arrays |
10
- | `src/valibot-state.ts` | Core schema definitions for `Config`, `CommitState`, `BranchState` |
11
- | `src/utils.ts` | Config loading, `parse`, and `ValiError` handling |
12
- | `src/index.ts` | Parses `CommitState`; uses `Output<>` types |
13
- | `src/branch.ts` | Parses `BranchState`; uses `Output<>` types |
14
- | `src/init.ts` | Calls `parse(Config, {})` to generate a default config file |
15
-
16
- ## Schema Overview
17
-
18
- ### `src/valibot-consts.ts` — Picklist Constants
19
-
20
- Defines shared enum-like schemas used across the codebase:
21
-
22
- ```ts
23
- export const V_BRANCH_ACTIONS = v.picklist(["branch", "worktree"]);
24
- export const V_FOOTER_OPTIONS = v.picklist([
25
- "closes",
26
- "trailer",
27
- "breaking-change",
28
- "deprecated",
29
- "custom",
30
- ]);
31
- export const V_BRANCH_FIELDS = v.picklist([
32
- "user",
33
- "version",
34
- "type",
35
- "ticket",
36
- "description",
37
- ]);
38
- export const V_BRANCH_CONFIG_FIELDS = v.picklist([
39
- "branch_user",
40
- "branch_version",
41
- "branch_type",
42
- "branch_ticket",
43
- "branch_description",
44
- ]);
45
- ```
46
-
47
- Constant arrays are typed using `v.Output<>` to derive element types directly from the schemas:
48
-
49
- ```ts
50
- export const FOOTER_OPTION_VALUES: v.Output<typeof V_FOOTER_OPTIONS>[] = [...];
51
- export const BRANCH_ORDER_DEFAULTS: v.Output<typeof V_BRANCH_FIELDS>[] = [...];
52
- ```
53
-
54
- ---
55
-
56
- ### `src/valibot-state.ts` — Core Schemas
57
-
58
- #### `Config`
59
-
60
- The main application config schema. Validates `.better-commits.json`. Parsing an empty object `{}` produces a fully-defaulted config.
61
-
62
- Key fields and their validators:
63
-
64
- | Field | Schema | Default |
65
- | ------------------------ | ------------------------------------------------------------- | ---------- |
66
- | `check_status` | `v.optional(v.boolean(), true)` | `true` |
67
- | `cache_last_value` | `v.optional(v.boolean(), true)` | `true` |
68
- | `confirm_with_editor` | `v.optional(v.boolean(), false)` | `false` |
69
- | `confirm_commit` | `v.optional(v.boolean(), true)` | `true` |
70
- | `print_commit_output` | `v.optional(v.boolean(), true)` | `true` |
71
- | `enable_worktrees` | `v.optional(v.boolean(), true)` | `true` |
72
- | `branch_pre_commands` | `v.optional(v.array(v.string()), [])` | `[]` |
73
- | `branch_post_commands` | `v.optional(v.array(v.string()), [])` | `[]` |
74
- | `worktree_pre_commands` | `v.optional(v.array(v.string()), [])` | `[]` |
75
- | `worktree_post_commands` | `v.optional(v.array(v.string()), [])` | `[]` |
76
- | `branch_action_default` | `v.optional(V_BRANCH_ACTIONS, "branch")` | `"branch"` |
77
- | `branch_order` | `v.optional(v.array(V_BRANCH_FIELDS), BRANCH_ORDER_DEFAULTS)` | all fields |
78
-
79
- **Notable nested validators:**
80
-
81
- - `commit_type.options[].emoji` — `v.string([v.emoji()])` validates the value is a real emoji character
82
- - `commit_type.max_items` / `commit_scope.max_items` — `v.number([v.minValue(1)])` enforces minimum of 1
83
- - `check_ticket.prepend_hashtag` — `v.picklist(["Never", "Always", "Prompt"])`
84
- - `check_ticket.surround` — `v.picklist(["", "()", "[]", "{}"])`
85
- - `check_ticket.title_position` — `v.picklist(["start", "end", "before-colon", "beginning"])`
86
- - `branch_*.separator` — `v.picklist(["/", "-", "_"])` (branch_description also allows `""`)
87
-
88
- **Cross-field validation with `v.custom`:**
89
-
90
- Both `commit_type` and `commit_scope` use `v.custom` to ensure `initial_value` exists within their `options` array:
91
-
92
- ```ts
93
- v.custom(
94
- (val) =>
95
- !val.initial_value ||
96
- val.options.some((o) => o.value === val.initial_value),
97
- (val) =>
98
- `Type: initial_value "${val.input.initial_value}" must exist in options`,
99
- );
100
- ```
101
-
102
- **Post-parse transformation with `v.transform`:**
103
-
104
- - `commit_type` — when `append_emoji_to_label` is `true`, prepends emoji to each option's label
105
- - `commit_scope` — when `custom_scope` is `true`, injects `{ label: "custom", value: "custom", hint: "..." }` into options if not already present
106
-
107
- ---
108
-
109
- #### `CommitState`
110
-
111
- Models the mutable in-memory state of an in-progress commit. All fields are `v.optional(v.string(), "")`.
112
-
113
- | Field | Purpose |
114
- | ------------------ | --------------------------- |
115
- | `type` | Commit type (e.g. `"feat"`) |
116
- | `scope` | Commit scope (e.g. `"app"`) |
117
- | `title` | Short commit title |
118
- | `body` | Long commit body |
119
- | `closes` | "Closes: " footer token |
120
- | `ticket` | Issue/ticket number |
121
- | `breaking_title` | Breaking change summary |
122
- | `breaking_body` | Breaking change description |
123
- | `deprecates` | Deprecation marker |
124
- | `deprecates_title` | Deprecation summary |
125
- | `deprecates_body` | Deprecation description |
126
- | `custom_footer` | Custom footer text |
127
- | `trailer` | Git trailer string |
128
-
129
- ---
130
-
131
- #### `BranchState`
132
-
133
- Models the mutable in-memory state for the `better-branch` CLI flow. All fields are `v.optional(v.string(), "")`.
134
-
135
- | Field | Purpose |
136
- | ------------- | ----------------------------------- |
137
- | `user` | Git username portion of branch name |
138
- | `type` | Branch type (mirrors commit type) |
139
- | `ticket` | Ticket/issue number |
140
- | `description` | Short branch description |
141
- | `version` | Version number |
142
-
143
- ---
144
-
145
- ## Runtime Usage
146
-
147
- ### Parsing with defaults
148
-
149
- All three state objects are initialized by parsing an empty object, which triggers all `v.optional` defaults:
150
-
151
- ```ts
152
- // src/index.ts
153
- const commit_state = parse(CommitState, {});
154
-
155
- // src/branch.ts
156
- const branch_state = parse(BranchState, {});
157
-
158
- // src/init.ts
159
- const default_config = parse(Config, {});
160
- ```
161
-
162
- ### Config validation in `src/utils.ts`
163
-
164
- `validate_config` wraps `parse(Config, config)` to produce human-friendly errors:
165
-
166
- ```ts
167
- function validate_config(config: unknown) {
168
- try {
169
- return parse(Config, config);
170
- } catch (err) {
171
- if (err instanceof ValiError) {
172
- const path = err.issues[0].path?.map((p) => p.key).join(".");
173
- p.log.error(`Invalid config at: ${path}`);
174
- process.exit(1);
175
- }
176
- }
177
- }
178
- ```
179
-
180
- ### TypeScript types via `Output<>`
181
-
182
- `Output<typeof Schema>` is used throughout as the TypeScript type for parsed objects, avoiding manual interface duplication:
183
-
184
- ```ts
185
- // Function signatures
186
- function build_commit_string(
187
- state: Output<typeof CommitState>,
188
- config: Output<typeof Config>
189
- ): string { ... }
190
-
191
- // Variable types
192
- const checkout_type: Output<typeof V_BRANCH_ACTIONS> = ...;
193
- ```
194
-
195
- ---
196
-
197
- ## Valibot API Summary
198
-
199
- | API | Purpose |
200
- | ----------------------------- | ---------------------------------------------------------------------- |
201
- | `v.object({...})` | Defines all three top-level schemas and all nested sub-objects |
202
- | `v.optional(schema, default)` | Makes fields optional with a fallback default |
203
- | `v.boolean()` | Validates boolean config flags |
204
- | `v.string()` | Validates string fields |
205
- | `v.number([...])` | Validates number fields with optional pipe validators |
206
- | `v.array(schema)` | Validates array fields |
207
- | `v.picklist([...])` | Validates enum-like string fields |
208
- | `v.minValue(1)` | Pipe validator: enforces a minimum numeric value |
209
- | `v.emoji()` | Pipe validator: ensures a string is a valid emoji character |
210
- | `v.custom(fn, msgFn)` | Cross-field validation with a custom predicate |
211
- | `v.transform(schema, fn)` | Post-parse transformation of validated data |
212
- | `parse(schema, data)` | Parses and validates data, applying all defaults and transforms |
213
- | `Output<typeof Schema>` | TypeScript utility to extract the inferred output type |
214
- | `ValiError` | Error class caught to produce human-readable validation error messages |
215
-
216
- ---
217
-
218
- ## Known Quirk
219
-
220
- `src/branch.ts` contains a bare no-op reference to `CommitState` at the bottom of the file:
221
-
222
- ```ts
223
- // TODO: No idea what's happening here
224
- // If you don't use CommitState, (even in unreachable code), parse fails on Config
225
- CommitState;
226
- ```
227
-
228
- This is a workaround for a bundler/tree-shaking issue: without this reference, `parse(Config, ...)` fails at runtime. The root cause is likely that `CommitState` imports something from `valibot-state.ts` that is needed for `Config` to work correctly at runtime, but the bundler eliminates it as dead code without this reference.