better-commits 1.23.2 → 1.23.3
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 +628 -19
- package/dist/chunk-GAAS3VS3.js +922 -0
- package/dist/chunk-H5CLUQIL.js +313 -0
- package/dist/index.js +1122 -41
- package/dist/init.js +44 -1
- package/package.json +12 -4
- 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,313 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BRANCH_STATE_ENTRIES,
|
|
3
|
+
COMMIT_STATE_ENTRIES,
|
|
4
|
+
CUSTOM_SCOPE_KEY,
|
|
5
|
+
flags
|
|
6
|
+
} from "./chunk-GAAS3VS3.js";
|
|
7
|
+
|
|
8
|
+
// src/utils/no-interactive-validation.ts
|
|
9
|
+
import * as v from "valibot";
|
|
10
|
+
|
|
11
|
+
// src/utils/commit-title-size.ts
|
|
12
|
+
function get_commit_title_size(val, options) {
|
|
13
|
+
const commit_scope_size = val.scope ? val.scope.length + 2 : 0;
|
|
14
|
+
const commit_type_size = val.type?.length ?? 0;
|
|
15
|
+
const commit_ticket_size = options.include_ticket ? val.ticket?.length ?? 0 : 0;
|
|
16
|
+
const title_size = val.title?.length ?? 0;
|
|
17
|
+
return commit_scope_size + commit_type_size + commit_ticket_size + title_size;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/utils/no-interactive-validation.ts
|
|
21
|
+
function format_allowed_values(values) {
|
|
22
|
+
const printable_values = values.map(
|
|
23
|
+
(value) => value === "" ? '"" (none)' : `"${value}"`
|
|
24
|
+
);
|
|
25
|
+
return printable_values.join(", ");
|
|
26
|
+
}
|
|
27
|
+
function create_strict_commit_state(config) {
|
|
28
|
+
const type_values = config.commit_type.options.map((option) => option.value);
|
|
29
|
+
const scope_values = config.commit_scope.options.map(
|
|
30
|
+
(option) => option.value
|
|
31
|
+
);
|
|
32
|
+
return v.pipe(
|
|
33
|
+
v.object(COMMIT_STATE_ENTRIES),
|
|
34
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
35
|
+
if (!dataset.typed)
|
|
36
|
+
return;
|
|
37
|
+
const received = dataset.value.type ? `"${dataset.value.type}"` : "(empty)";
|
|
38
|
+
if (dataset.value.type && !type_values.includes(dataset.value.type)) {
|
|
39
|
+
addIssue({
|
|
40
|
+
message: `Invalid --type ${received}. Valid types: ${format_allowed_values(type_values)}.`
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
45
|
+
if (!dataset.typed)
|
|
46
|
+
return;
|
|
47
|
+
const received = dataset.value.scope ? `"${dataset.value.scope}"` : "(empty)";
|
|
48
|
+
if (dataset.value.scope && !config.commit_scope.custom_scope && !scope_values.includes(dataset.value.scope)) {
|
|
49
|
+
addIssue({
|
|
50
|
+
message: `Invalid --scope ${received}. Valid scopes: ${format_allowed_values(scope_values)}.`
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
55
|
+
if (!dataset.typed || dataset.value.title.trim())
|
|
56
|
+
return;
|
|
57
|
+
addIssue({
|
|
58
|
+
message: "Missing --title. Provide a non-empty commit title."
|
|
59
|
+
});
|
|
60
|
+
}),
|
|
61
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
62
|
+
if (!dataset.typed)
|
|
63
|
+
return;
|
|
64
|
+
const size = get_commit_title_size(dataset.value, {
|
|
65
|
+
include_ticket: config.check_ticket.add_to_title
|
|
66
|
+
});
|
|
67
|
+
if (size > config.commit_title.max_size) {
|
|
68
|
+
addIssue({
|
|
69
|
+
message: `Title exceeds max width. Current size is ${size}, max is ${config.commit_title.max_size} (includes type, scope, and ticket when enabled).`
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}),
|
|
73
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
74
|
+
if (dataset.typed && config.commit_body.required && !dataset.value.body.trim()) {
|
|
75
|
+
addIssue({
|
|
76
|
+
message: "Missing --body. commit_body.required is enabled in config."
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}),
|
|
80
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
81
|
+
if (dataset.typed && dataset.value.closes && !dataset.value.ticket) {
|
|
82
|
+
addIssue({
|
|
83
|
+
message: 'Invalid footer values: --closes requires --ticket (for example: --ticket "ABC-123").'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}),
|
|
87
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
88
|
+
if (dataset.typed && dataset.value.breaking_body && !dataset.value.breaking_title) {
|
|
89
|
+
addIssue({
|
|
90
|
+
message: "Invalid breaking change values: --breaking-body requires --breaking-title."
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}),
|
|
94
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
95
|
+
if (dataset.typed && dataset.value.deprecates_body && !dataset.value.deprecates_title) {
|
|
96
|
+
addIssue({
|
|
97
|
+
message: "Invalid deprecation values: --deprecates-body requires --deprecates-title."
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
function create_strict_branch_state(config) {
|
|
104
|
+
const type_values = config.commit_type.options.map((option) => option.value);
|
|
105
|
+
const scope_values = config.commit_scope.options.map(
|
|
106
|
+
(option) => option.value
|
|
107
|
+
);
|
|
108
|
+
return v.pipe(
|
|
109
|
+
v.object(BRANCH_STATE_ENTRIES),
|
|
110
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
111
|
+
if (!dataset.typed)
|
|
112
|
+
return;
|
|
113
|
+
const received = dataset.value.type ? `"${dataset.value.type}"` : "(empty)";
|
|
114
|
+
if (dataset.value.type && !type_values.includes(dataset.value.type)) {
|
|
115
|
+
addIssue({
|
|
116
|
+
message: `Invalid --type ${received}. Valid types: ${format_allowed_values(type_values)}.`
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}),
|
|
120
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
121
|
+
if (!dataset.typed)
|
|
122
|
+
return;
|
|
123
|
+
const received = dataset.value.scope ? `"${dataset.value.scope}"` : "(empty)";
|
|
124
|
+
if (dataset.value.scope && !config.commit_scope.custom_scope && !scope_values.includes(dataset.value.scope)) {
|
|
125
|
+
addIssue({
|
|
126
|
+
message: `Invalid --scope ${received}. Valid scopes: ${format_allowed_values(scope_values)}.`
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}),
|
|
130
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
131
|
+
if (!dataset.typed || dataset.value.description.trim())
|
|
132
|
+
return;
|
|
133
|
+
addIssue({
|
|
134
|
+
message: "Missing --description. Provide a non-empty branch description."
|
|
135
|
+
});
|
|
136
|
+
}),
|
|
137
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
138
|
+
if (!dataset.typed)
|
|
139
|
+
return;
|
|
140
|
+
const description = dataset.value.description.trim();
|
|
141
|
+
if (description.length > config.branch_description.max_length) {
|
|
142
|
+
addIssue({
|
|
143
|
+
message: `Description exceeds max length. Current length is ${description.length}, max is ${config.branch_description.max_length}.`
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}),
|
|
147
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
148
|
+
if (dataset.typed && config.branch_user.required && !dataset.value.user.trim()) {
|
|
149
|
+
addIssue({
|
|
150
|
+
message: "Missing --user. branch_user.required is enabled in config."
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}),
|
|
154
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
155
|
+
if (dataset.typed && config.branch_ticket.required && !dataset.value.ticket.trim()) {
|
|
156
|
+
addIssue({
|
|
157
|
+
message: "Missing --ticket. branch_ticket.required is enabled in config."
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}),
|
|
161
|
+
v.rawCheck(({ dataset, addIssue }) => {
|
|
162
|
+
if (dataset.typed && config.branch_version.required && !dataset.value.version.trim()) {
|
|
163
|
+
addIssue({
|
|
164
|
+
message: "Missing --branch-version. branch_version.required is enabled in config."
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/utils/infer.ts
|
|
172
|
+
import { execSync } from "child_process";
|
|
173
|
+
var REGEX_SLASH_TAG = /\/(\w+-\d+)/;
|
|
174
|
+
var REGEX_START_TAG = /^(\w+-\d+)/;
|
|
175
|
+
var REGEX_START_UND = /^([A-Z]+-[\[a-zA-Z\]\d]+)_/;
|
|
176
|
+
var REGEX_SLASH_UND = /\/([A-Z]+-[\[a-zA-Z\]\d]+)_/;
|
|
177
|
+
var REGEX_SLASH_NUM = /\/(\d+)/;
|
|
178
|
+
var REGEX_START_NUM = /^(\d+)/;
|
|
179
|
+
function infer_not_interactive(config) {
|
|
180
|
+
if (flags.interactive)
|
|
181
|
+
return;
|
|
182
|
+
let inferred_state = { ticket: "", type: "", scope: "" };
|
|
183
|
+
if (config.check_ticket.infer_ticket) {
|
|
184
|
+
const inferred_ticket = infer_ticket_from_git(
|
|
185
|
+
{
|
|
186
|
+
append_hashtag: config.check_ticket.append_hashtag,
|
|
187
|
+
prepend_hashtag: config.check_ticket.prepend_hashtag
|
|
188
|
+
},
|
|
189
|
+
flags.git_args
|
|
190
|
+
);
|
|
191
|
+
inferred_state.ticket = inferred_ticket;
|
|
192
|
+
}
|
|
193
|
+
const inferred_type = infer_type_from_git(
|
|
194
|
+
config.commit_type.options,
|
|
195
|
+
flags.git_args
|
|
196
|
+
);
|
|
197
|
+
inferred_state.type = inferred_type;
|
|
198
|
+
if (config.commit_scope.enable && config.commit_scope.infer_scope_from_branch) {
|
|
199
|
+
const inferred_scope = infer_scope_from_git(
|
|
200
|
+
config.commit_scope.options,
|
|
201
|
+
flags.git_args
|
|
202
|
+
);
|
|
203
|
+
inferred_state.scope = inferred_scope;
|
|
204
|
+
}
|
|
205
|
+
return inferred_state;
|
|
206
|
+
}
|
|
207
|
+
function infer_type_from_git(options, git_args) {
|
|
208
|
+
const branch = get_current_branch(git_args);
|
|
209
|
+
if (!branch)
|
|
210
|
+
return "";
|
|
211
|
+
return infer_type_from_branch(
|
|
212
|
+
branch,
|
|
213
|
+
options.map((option) => option.value)
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
function infer_ticket_from_git(options, git_args) {
|
|
217
|
+
const branch = get_current_branch(git_args);
|
|
218
|
+
if (!branch)
|
|
219
|
+
return "";
|
|
220
|
+
return infer_ticket_from_branch(branch, options);
|
|
221
|
+
}
|
|
222
|
+
function infer_scope_from_git(options, git_args) {
|
|
223
|
+
const branch = get_current_branch(git_args);
|
|
224
|
+
if (!branch)
|
|
225
|
+
return "";
|
|
226
|
+
return infer_scope_from_branch(branch, options);
|
|
227
|
+
}
|
|
228
|
+
function infer_ticket_from_branch(branch, options) {
|
|
229
|
+
const found = [
|
|
230
|
+
branch.match(REGEX_START_UND),
|
|
231
|
+
branch.match(REGEX_SLASH_UND),
|
|
232
|
+
branch.match(REGEX_SLASH_TAG),
|
|
233
|
+
branch.match(REGEX_SLASH_NUM),
|
|
234
|
+
branch.match(REGEX_START_TAG),
|
|
235
|
+
branch.match(REGEX_START_NUM)
|
|
236
|
+
].filter((value) => value != null).map((value) => value && value.length >= 2 ? value[1] : "");
|
|
237
|
+
if (!found.length || !found[0])
|
|
238
|
+
return "";
|
|
239
|
+
return options.append_hashtag || options.prepend_hashtag === "Always" ? `#${found[0]}` : found[0];
|
|
240
|
+
}
|
|
241
|
+
function infer_type_from_branch(branch, types) {
|
|
242
|
+
const found = types.find((type) => {
|
|
243
|
+
const start_dash = new RegExp(`^${type}-`);
|
|
244
|
+
const between_dash = new RegExp(`-${type}-`);
|
|
245
|
+
const before_slash = new RegExp(`${type}/`);
|
|
246
|
+
const matches = [
|
|
247
|
+
branch.match(start_dash),
|
|
248
|
+
branch.match(between_dash),
|
|
249
|
+
branch.match(before_slash)
|
|
250
|
+
].filter((value) => value != null);
|
|
251
|
+
return matches.length > 0;
|
|
252
|
+
});
|
|
253
|
+
return found ?? "";
|
|
254
|
+
}
|
|
255
|
+
function escape_regexp(value) {
|
|
256
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
257
|
+
}
|
|
258
|
+
function infer_scope_from_branch(branch, options) {
|
|
259
|
+
const scopes = options.map((option) => option.value).filter((scope) => scope && scope !== CUSTOM_SCOPE_KEY).sort((a, b) => b.length - a.length);
|
|
260
|
+
const found = scopes.find((scope) => {
|
|
261
|
+
const standalone_scope = new RegExp(
|
|
262
|
+
`(?:^|[/_-])${escape_regexp(scope)}(?=$|[/_-])`
|
|
263
|
+
);
|
|
264
|
+
return standalone_scope.test(branch);
|
|
265
|
+
});
|
|
266
|
+
return found ?? "";
|
|
267
|
+
}
|
|
268
|
+
function get_current_branch(git_args) {
|
|
269
|
+
try {
|
|
270
|
+
return execSync(`git ${git_args} branch --show-current`, {
|
|
271
|
+
stdio: "pipe"
|
|
272
|
+
}).toString().trim();
|
|
273
|
+
} catch {
|
|
274
|
+
return "";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/utils/messages.ts
|
|
279
|
+
import color from "picocolors";
|
|
280
|
+
function cache_message(message) {
|
|
281
|
+
return `${message} ${color.dim("\xB7 restored from cache")}`;
|
|
282
|
+
}
|
|
283
|
+
function inferred_message(message) {
|
|
284
|
+
return `${message} ${color.dim("\xB7 inferred from branch")}`;
|
|
285
|
+
}
|
|
286
|
+
function optional_message(message) {
|
|
287
|
+
return `${message} ${color.dim("\xB7 optional")}`;
|
|
288
|
+
}
|
|
289
|
+
function space_to_select_message(message) {
|
|
290
|
+
return `${message} ${color.dim("\xB7 <space> to select")}`;
|
|
291
|
+
}
|
|
292
|
+
function a_for_all_message(message) {
|
|
293
|
+
return `${message} ${color.dim("\xB7 <space> to select \xB7 <a> to select all")}`;
|
|
294
|
+
}
|
|
295
|
+
function dry_run_message(message) {
|
|
296
|
+
return `${message} ${color.dim("\xB7 dry run - changes will not be committed")}`;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export {
|
|
300
|
+
get_commit_title_size,
|
|
301
|
+
create_strict_commit_state,
|
|
302
|
+
create_strict_branch_state,
|
|
303
|
+
infer_not_interactive,
|
|
304
|
+
infer_type_from_git,
|
|
305
|
+
infer_ticket_from_git,
|
|
306
|
+
infer_scope_from_git,
|
|
307
|
+
cache_message,
|
|
308
|
+
inferred_message,
|
|
309
|
+
optional_message,
|
|
310
|
+
space_to_select_message,
|
|
311
|
+
a_for_all_message,
|
|
312
|
+
dry_run_message
|
|
313
|
+
};
|