better-commits 1.20.0-cli-flags → 1.20.1-temp.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/branch.js +1 -1
- package/dist/{chunk-SIF4LZUS.js → chunk-LPU7O52G.js} +1 -1
- package/dist/chunk-QPUTIRGU.js +245 -0
- package/dist/index.js +2 -2
- package/dist/init.js +1 -1
- package/package.json +7 -1
- package/readme.md +141 -173
- package/.better-commits.json +0 -52
- package/.github/workflows/publish.yml +0 -34
- package/.github/workflows/test.yml +0 -27
- package/.opencode/package-lock.json +0 -115
- package/.opencode/plans/cli-args.md +0 -182
- package/.prettierignore +0 -5
- package/.prettierrc +0 -1
- package/.svelte-kit/ambient.d.ts +0 -289
- package/.svelte-kit/generated/client/app.js +0 -28
- package/.svelte-kit/generated/client/matchers.js +0 -1
- package/.svelte-kit/generated/client/nodes/0.js +0 -1
- package/.svelte-kit/generated/client/nodes/1.js +0 -1
- package/.svelte-kit/tsconfig.json +0 -49
- package/0001-feat-branch-124-update-worktrees-feature.patch +0 -316
- package/dist/chunk-OFJCRS3N.js +0 -4
- package/docs/ai-skills.yaml +0 -48
- package/docs/clack.md +0 -143
- package/docs/valibot.md +0 -228
- package/src/args.test.ts +0 -102
- package/src/args.ts +0 -106
- package/src/branch-args.test.ts +0 -72
- package/src/branch-args.ts +0 -106
- package/src/branch-help.ts +0 -114
- package/src/branch.ts +0 -95
- package/src/git.ts +0 -60
- package/src/help.ts +0 -131
- package/src/index.test.ts +0 -7
- package/src/index.ts +0 -100
- package/src/init.ts +0 -25
- package/src/prompts/branch-checkout.prompt.ts +0 -36
- package/src/prompts/branch-confirm.prompt.ts +0 -134
- package/src/prompts/branch-description.prompt.ts +0 -37
- package/src/prompts/branch-runnable.ts +0 -13
- package/src/prompts/branch-ticket.prompt.ts +0 -41
- package/src/prompts/branch-type.prompt.ts +0 -43
- 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 -57
- package/src/prompts/commit-confirm.prompt.ts +0 -119
- package/src/prompts/commit-footer.prompt.ts +0 -195
- package/src/prompts/commit-scope.prompt.ts +0 -73
- package/src/prompts/commit-status.prompt.ts +0 -75
- 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 -93
- package/src/prompts/runnable.ts +0 -13
- package/src/utils/build-branch.test.ts +0 -141
- package/src/utils/build-branch.ts +0 -46
- package/src/utils/build-commit-string.test.ts +0 -253
- package/src/utils/build-commit-string.ts +0 -158
- package/src/utils/commit-title-size.ts +0 -24
- package/src/utils/infer.test.ts +0 -83
- package/src/utils/infer.ts +0 -114
- package/src/utils/messages.ts +0 -25
- package/src/utils/no-interactive-branch-validation.test.ts +0 -170
- package/src/utils/no-interactive-validation.test.ts +0 -174
- package/src/utils/no-interactive-validation.ts +0 -190
- package/src/utils.ts +0 -219
- package/src/valibot-consts.ts +0 -114
- package/src/valibot-state.test.ts +0 -48
- package/src/valibot-state.ts +0 -265
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -12
- package/vitest.config.ts +0 -8
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import { InferOutput } from "valibot";
|
|
3
|
-
import { V_FOOTER_OPTIONS } from "../valibot-consts";
|
|
4
|
-
import {
|
|
5
|
-
COMMIT_FOOTER_OPTIONS,
|
|
6
|
-
get_value_from_cache,
|
|
7
|
-
set_value_cache,
|
|
8
|
-
} from "../utils";
|
|
9
|
-
import {
|
|
10
|
-
cache_message,
|
|
11
|
-
optional_message,
|
|
12
|
-
space_to_select_message,
|
|
13
|
-
} from "../utils/messages";
|
|
14
|
-
import { Runnable } from "./runnable";
|
|
15
|
-
|
|
16
|
-
type FooterOption = InferOutput<typeof V_FOOTER_OPTIONS>;
|
|
17
|
-
type FooterPromptOption = {
|
|
18
|
-
value: FooterOption;
|
|
19
|
-
label: string;
|
|
20
|
-
hint: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
type FooterSelection = {
|
|
24
|
-
includes_breaking_change: boolean;
|
|
25
|
-
includes_deprecated: boolean;
|
|
26
|
-
includes_closes: boolean;
|
|
27
|
-
includes_custom: boolean;
|
|
28
|
-
includes_trailer: boolean;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
type FooterInputs = {
|
|
32
|
-
breaking_title: string;
|
|
33
|
-
breaking_body: string;
|
|
34
|
-
deprecated_title: string;
|
|
35
|
-
deprecated_body: string;
|
|
36
|
-
custom_footer: string;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export class CommitFooterPrompt extends Runnable {
|
|
40
|
-
async run(): Promise<void> {
|
|
41
|
-
if (!this.#is_enabled) return;
|
|
42
|
-
|
|
43
|
-
const { initial_values, message } = this.#get_initial_value();
|
|
44
|
-
const commit_footer = (await p.multiselect({
|
|
45
|
-
message,
|
|
46
|
-
initialValues: initial_values,
|
|
47
|
-
options: this.#options,
|
|
48
|
-
required: false,
|
|
49
|
-
})) as FooterOption[];
|
|
50
|
-
if (p.isCancel(commit_footer)) process.exit(0);
|
|
51
|
-
|
|
52
|
-
const selection = this.#get_selection(commit_footer);
|
|
53
|
-
const footer_inputs = await this.#get_footer_inputs(selection);
|
|
54
|
-
this.#run_post_effects(commit_footer, selection, footer_inputs);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
get #is_enabled(): boolean {
|
|
58
|
-
return this.config.commit_footer.enable;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
get #options(): FooterPromptOption[] {
|
|
62
|
-
const allowed_values = new Set(this.config.commit_footer.options);
|
|
63
|
-
return COMMIT_FOOTER_OPTIONS.filter((option) =>
|
|
64
|
-
allowed_values.has(option.value as FooterOption),
|
|
65
|
-
) as FooterPromptOption[];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
get #available_option_values(): FooterOption[] {
|
|
69
|
-
return this.#options.map((option) => option.value);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
#get_initial_value(): { initial_values: FooterOption[]; message: string } {
|
|
73
|
-
const cache_value = get_value_from_cache(
|
|
74
|
-
this.prompt_cache,
|
|
75
|
-
"commit_footer",
|
|
76
|
-
);
|
|
77
|
-
if (cache_value) {
|
|
78
|
-
return {
|
|
79
|
-
initial_values: this.#parse_cache_value(cache_value),
|
|
80
|
-
message: space_to_select_message(cache_message("Commit footers")),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const initial_values = this.config.commit_footer.initial_value.filter(
|
|
85
|
-
(value) => this.#available_option_values.includes(value),
|
|
86
|
-
);
|
|
87
|
-
return {
|
|
88
|
-
initial_values,
|
|
89
|
-
message: space_to_select_message(
|
|
90
|
-
optional_message("Select optional footers"),
|
|
91
|
-
),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
#parse_cache_value(cache_value: string): FooterOption[] {
|
|
96
|
-
return cache_value
|
|
97
|
-
.split(",")
|
|
98
|
-
.map((value) => value.trim())
|
|
99
|
-
.filter((value): value is FooterOption =>
|
|
100
|
-
this.#available_option_values.includes(value as FooterOption),
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
#get_selection(commit_footer: FooterOption[]): FooterSelection {
|
|
105
|
-
return {
|
|
106
|
-
includes_breaking_change: commit_footer.includes("breaking-change"),
|
|
107
|
-
includes_deprecated: commit_footer.includes("deprecated"),
|
|
108
|
-
includes_closes: commit_footer.includes("closes"),
|
|
109
|
-
includes_custom: commit_footer.includes("custom"),
|
|
110
|
-
includes_trailer: commit_footer.includes("trailer"),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async #get_footer_inputs(selection: FooterSelection): Promise<FooterInputs> {
|
|
115
|
-
const footer_inputs: FooterInputs = {
|
|
116
|
-
breaking_title: "",
|
|
117
|
-
breaking_body: "",
|
|
118
|
-
deprecated_title: "",
|
|
119
|
-
deprecated_body: "",
|
|
120
|
-
custom_footer: "",
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
if (selection.includes_breaking_change) {
|
|
124
|
-
footer_inputs.breaking_title = await this.#required_text(
|
|
125
|
-
"Breaking changes: Write a short title / summary",
|
|
126
|
-
);
|
|
127
|
-
footer_inputs.breaking_body = await this.#optional_text(
|
|
128
|
-
optional_message(
|
|
129
|
-
"Breaking Changes: Write a description & migration instructions",
|
|
130
|
-
),
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (selection.includes_deprecated) {
|
|
135
|
-
footer_inputs.deprecated_title = await this.#required_text(
|
|
136
|
-
"Deprecated: Write a short title / summary",
|
|
137
|
-
);
|
|
138
|
-
footer_inputs.deprecated_body = await this.#optional_text(
|
|
139
|
-
optional_message("Deprecated: Write a description"),
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (selection.includes_custom) {
|
|
144
|
-
footer_inputs.custom_footer = await this.#optional_text(
|
|
145
|
-
"Write a custom footer",
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return footer_inputs;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async #required_text(message: string): Promise<string> {
|
|
153
|
-
const response = await p.text({
|
|
154
|
-
message,
|
|
155
|
-
placeholder: "",
|
|
156
|
-
validate: (value) => {
|
|
157
|
-
if (!value) return "Please enter a title / summary";
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
if (p.isCancel(response)) process.exit(0);
|
|
161
|
-
return response ?? "";
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async #optional_text(message: string): Promise<string> {
|
|
165
|
-
const response = await p.text({
|
|
166
|
-
message,
|
|
167
|
-
placeholder: "",
|
|
168
|
-
});
|
|
169
|
-
if (p.isCancel(response)) process.exit(0);
|
|
170
|
-
return response ?? "";
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
#run_post_effects(
|
|
174
|
-
commit_footer: FooterOption[],
|
|
175
|
-
selection: FooterSelection,
|
|
176
|
-
footer_inputs: FooterInputs,
|
|
177
|
-
): void {
|
|
178
|
-
set_value_cache(
|
|
179
|
-
this.prompt_cache,
|
|
180
|
-
"commit_footer",
|
|
181
|
-
commit_footer.join(","),
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
this.commit_state.breaking_title = footer_inputs.breaking_title;
|
|
185
|
-
this.commit_state.breaking_body = footer_inputs.breaking_body;
|
|
186
|
-
this.commit_state.deprecates_title = footer_inputs.deprecated_title;
|
|
187
|
-
this.commit_state.deprecates_body = footer_inputs.deprecated_body;
|
|
188
|
-
this.commit_state.custom_footer = footer_inputs.custom_footer;
|
|
189
|
-
|
|
190
|
-
this.commit_state.closes = selection.includes_closes ? "Closes:" : "";
|
|
191
|
-
if (!selection.includes_trailer) {
|
|
192
|
-
this.commit_state.trailer = "";
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import { CUSTOM_SCOPE_KEY } from "../valibot-consts";
|
|
3
|
-
import { get_value_from_cache, set_value_cache } from "../utils";
|
|
4
|
-
import { cache_message } from "../utils/messages";
|
|
5
|
-
import { Runnable } from "./runnable";
|
|
6
|
-
|
|
7
|
-
export class CommitScopePrompt extends Runnable {
|
|
8
|
-
async run(): Promise<void> {
|
|
9
|
-
if (!this.#is_enabled) return;
|
|
10
|
-
const { initial_value, message } = this.#get_initial_value();
|
|
11
|
-
|
|
12
|
-
let commit_scope = await p.select({
|
|
13
|
-
message,
|
|
14
|
-
initialValue: initial_value,
|
|
15
|
-
maxItems: this.#max_items,
|
|
16
|
-
options: this.#options,
|
|
17
|
-
});
|
|
18
|
-
if (p.isCancel(commit_scope)) process.exit(0);
|
|
19
|
-
|
|
20
|
-
await this.#post_run_effects(commit_scope);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get #is_enabled(): boolean {
|
|
24
|
-
return this.config.commit_scope.enable;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
#get_initial_value(): { initial_value: string; message: string } {
|
|
28
|
-
const cache_value = get_value_from_cache(this.prompt_cache, "commit_scope");
|
|
29
|
-
if (cache_value) {
|
|
30
|
-
return {
|
|
31
|
-
initial_value: cache_value,
|
|
32
|
-
message: cache_message("Commit scope"),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
initial_value: this.config.commit_scope.initial_value,
|
|
38
|
-
message: "Select a commit scope",
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get #max_items(): number | undefined {
|
|
43
|
-
return this.config.commit_scope.max_items;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
get #options(): {
|
|
47
|
-
label?: string | undefined;
|
|
48
|
-
value: string;
|
|
49
|
-
hint?: string;
|
|
50
|
-
}[] {
|
|
51
|
-
return this.config.commit_scope.options;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get #custom_scope_enabled(): boolean {
|
|
55
|
-
return this.config.commit_scope.custom_scope;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async #post_run_effects(prompt_result: string): Promise<void> {
|
|
59
|
-
set_value_cache(this.prompt_cache, "commit_scope", prompt_result);
|
|
60
|
-
|
|
61
|
-
let commit_scope_value = prompt_result;
|
|
62
|
-
if (commit_scope_value === CUSTOM_SCOPE_KEY && this.#custom_scope_enabled) {
|
|
63
|
-
const commit_scope = await p.text({
|
|
64
|
-
message: "Write a custom scope",
|
|
65
|
-
placeholder: "",
|
|
66
|
-
});
|
|
67
|
-
if (p.isCancel(commit_scope)) process.exit(0);
|
|
68
|
-
commit_scope_value = commit_scope ?? "";
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
this.commit_state.scope = commit_scope_value;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import color from "picocolors";
|
|
3
|
-
import { addNewLine } from "../utils";
|
|
4
|
-
import { space_to_select_message } from "../utils/messages";
|
|
5
|
-
import { git_add, git_status } from "../git";
|
|
6
|
-
import { Runnable } from "./runnable";
|
|
7
|
-
|
|
8
|
-
export class CommitStatusPrompt extends Runnable {
|
|
9
|
-
async run(): Promise<void> {
|
|
10
|
-
if (!this.#is_enabled) return;
|
|
11
|
-
|
|
12
|
-
const status = git_status();
|
|
13
|
-
this.#log_status(status);
|
|
14
|
-
|
|
15
|
-
if (status.work_tree.length) {
|
|
16
|
-
const selected_for_staging = await this.#select_for_staging(
|
|
17
|
-
status.work_tree,
|
|
18
|
-
);
|
|
19
|
-
if (selected_for_staging.length) {
|
|
20
|
-
git_add(selected_for_staging);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
this.#ensure_staged_changes();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get #is_enabled(): boolean {
|
|
28
|
-
return this.config.check_status;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
#log_status(status: { index: string[]; work_tree: string[] }): void {
|
|
32
|
-
p.log.step(color.black(color.bgGreen(" Checking Git Status ")));
|
|
33
|
-
|
|
34
|
-
const staged_files = this.#format_files(status.index, color.green);
|
|
35
|
-
p.log.success("Changes to be committed:\n" + staged_files);
|
|
36
|
-
|
|
37
|
-
if (!status.work_tree.length) return;
|
|
38
|
-
const unstaged_files = this.#format_files(status.work_tree, color.red);
|
|
39
|
-
p.log.error("Changes not staged for commit:\n" + unstaged_files);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
#format_files(files: string[], colorize: (value: string) => string): string {
|
|
43
|
-
return files.reduce(
|
|
44
|
-
(acc, curr, index) => colorize(acc + curr + addNewLine(files, index)),
|
|
45
|
-
"",
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async #select_for_staging(work_tree: string[]): Promise<string[]> {
|
|
50
|
-
const selected_for_staging = (await p.multiselect({
|
|
51
|
-
message: space_to_select_message(
|
|
52
|
-
"Some files have not been staged, would you like to add them now?",
|
|
53
|
-
),
|
|
54
|
-
options: [
|
|
55
|
-
{ value: ".", label: "." },
|
|
56
|
-
...work_tree.map((v) => ({ value: v, label: v })),
|
|
57
|
-
],
|
|
58
|
-
required: false,
|
|
59
|
-
})) as string[];
|
|
60
|
-
if (p.isCancel(selected_for_staging)) process.exit(0);
|
|
61
|
-
return selected_for_staging;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
#ensure_staged_changes(): void {
|
|
65
|
-
const updated_status = git_status();
|
|
66
|
-
if (updated_status.index.length) return;
|
|
67
|
-
|
|
68
|
-
p.log.error(
|
|
69
|
-
color.red(
|
|
70
|
-
'no changes added to commit (use "git add" and/or "git commit -a")',
|
|
71
|
-
),
|
|
72
|
-
);
|
|
73
|
-
process.exit(0);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import { flags } from "../args";
|
|
3
|
-
import { get_value_from_cache, set_value_cache } from "../utils";
|
|
4
|
-
import { infer_ticket_from_git } from "../utils/infer";
|
|
5
|
-
import {
|
|
6
|
-
cache_message,
|
|
7
|
-
inferred_message,
|
|
8
|
-
optional_message,
|
|
9
|
-
} from "../utils/messages";
|
|
10
|
-
import { Runnable } from "./runnable";
|
|
11
|
-
|
|
12
|
-
export class CommitTicketPrompt extends Runnable {
|
|
13
|
-
async run(): Promise<void> {
|
|
14
|
-
const { initial_value, message } = this.#get_initial_value();
|
|
15
|
-
this.commit_state.ticket = initial_value;
|
|
16
|
-
|
|
17
|
-
if (this.#confirm_ticket_enabled) {
|
|
18
|
-
const user_commit_ticket = await p.text({
|
|
19
|
-
message,
|
|
20
|
-
placeholder: "",
|
|
21
|
-
initialValue: initial_value,
|
|
22
|
-
});
|
|
23
|
-
if (p.isCancel(user_commit_ticket)) process.exit(0);
|
|
24
|
-
set_value_cache(this.prompt_cache, "commit_ticket", user_commit_ticket);
|
|
25
|
-
this.commit_state.ticket = user_commit_ticket ?? "";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
this.#prepend_hashtag_always &&
|
|
30
|
-
this.commit_state.ticket &&
|
|
31
|
-
!this.commit_state.ticket.startsWith("#")
|
|
32
|
-
) {
|
|
33
|
-
this.commit_state.ticket = "#" + this.commit_state.ticket;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get #infer_ticket_enabled(): boolean {
|
|
38
|
-
return this.config.check_ticket.infer_ticket;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get #confirm_ticket_enabled(): boolean {
|
|
42
|
-
return this.config.check_ticket.confirm_ticket;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get #prepend_hashtag_always(): boolean {
|
|
46
|
-
return this.config.check_ticket.prepend_hashtag === "Always";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
#get_initial_value(): { initial_value: string; message: string } {
|
|
50
|
-
const cache_value = get_value_from_cache(
|
|
51
|
-
this.prompt_cache,
|
|
52
|
-
"commit_ticket",
|
|
53
|
-
);
|
|
54
|
-
if (cache_value) {
|
|
55
|
-
return {
|
|
56
|
-
initial_value: cache_value,
|
|
57
|
-
message: cache_message("Ticket / issue"),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (this.#infer_ticket_enabled) {
|
|
62
|
-
const inferred_value = infer_ticket_from_git(
|
|
63
|
-
{
|
|
64
|
-
append_hashtag: this.config.check_ticket.append_hashtag,
|
|
65
|
-
prepend_hashtag: this.config.check_ticket.prepend_hashtag,
|
|
66
|
-
},
|
|
67
|
-
flags.git_args,
|
|
68
|
-
);
|
|
69
|
-
if (inferred_value) {
|
|
70
|
-
return {
|
|
71
|
-
initial_value: inferred_value,
|
|
72
|
-
message: inferred_message("Ticket / issue"),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
initial_value: this.commit_state.ticket,
|
|
79
|
-
message: optional_message("Add ticket / issue"),
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import {
|
|
3
|
-
clean_commit_title,
|
|
4
|
-
get_value_from_cache,
|
|
5
|
-
set_value_cache,
|
|
6
|
-
} from "../utils";
|
|
7
|
-
import { cache_message } from "../utils/messages";
|
|
8
|
-
import { get_commit_title_size } from "../utils/commit-title-size";
|
|
9
|
-
import { Runnable } from "./runnable";
|
|
10
|
-
|
|
11
|
-
export class CommitTitlePrompt extends Runnable {
|
|
12
|
-
async run(): Promise<void> {
|
|
13
|
-
const { initial_value, message } = this.#get_initial_value();
|
|
14
|
-
const commit_title = await p.text({
|
|
15
|
-
message,
|
|
16
|
-
initialValue: initial_value,
|
|
17
|
-
placeholder: "",
|
|
18
|
-
validate: (value) => this.#validate(value),
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (p.isCancel(commit_title)) process.exit(0);
|
|
22
|
-
this.#run_post_effects(commit_title ?? "");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
#get_initial_value(): { initial_value: string; message: string } {
|
|
26
|
-
const cache_value = get_value_from_cache(this.prompt_cache, "commit_title");
|
|
27
|
-
if (cache_value) {
|
|
28
|
-
return {
|
|
29
|
-
initial_value: cache_value,
|
|
30
|
-
message: cache_message("Commit title"),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// this.commit_state.title will pull from flag if populated
|
|
35
|
-
return {
|
|
36
|
-
initial_value: this.commit_state.title,
|
|
37
|
-
message: "Write a brief title describing the commit",
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#validate(value: string | undefined): string | undefined {
|
|
42
|
-
if (!value) return "Please enter a title";
|
|
43
|
-
|
|
44
|
-
if (this.#get_size(value) > this.#max_size) {
|
|
45
|
-
return `Exceeded max length. Title max [${this.#max_size}]`;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get #max_size(): number {
|
|
50
|
-
return this.config.commit_title.max_size;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
#get_size(value: string): number {
|
|
54
|
-
return get_commit_title_size(
|
|
55
|
-
{
|
|
56
|
-
type: this.commit_state.type,
|
|
57
|
-
scope: this.commit_state.scope,
|
|
58
|
-
ticket: this.commit_state.ticket,
|
|
59
|
-
title: value,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
include_ticket: this.config.check_ticket.add_to_title,
|
|
63
|
-
},
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// TODO: Extract to a Runnable abstract function?
|
|
68
|
-
get #value_to_data(): Record<string, { emoji: string }> {
|
|
69
|
-
return this.config.commit_type.options.reduce(
|
|
70
|
-
(acc, curr) => ({
|
|
71
|
-
...acc,
|
|
72
|
-
[curr.value]: {
|
|
73
|
-
emoji: curr.emoji ?? "",
|
|
74
|
-
},
|
|
75
|
-
}),
|
|
76
|
-
{},
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#title_with_emoji(title: string): string {
|
|
81
|
-
if (
|
|
82
|
-
this.config.commit_type.append_emoji_to_commit &&
|
|
83
|
-
this.config.commit_type.emoji_commit_position === "After-Colon"
|
|
84
|
-
) {
|
|
85
|
-
const emoji = this.#value_to_data[this.commit_state.type]?.emoji ?? "";
|
|
86
|
-
return `${emoji} ${title}`.trim();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return title;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
#run_post_effects(prompt_result: string): void {
|
|
93
|
-
set_value_cache(this.prompt_cache, "commit_title", prompt_result);
|
|
94
|
-
this.commit_state.title = clean_commit_title(
|
|
95
|
-
this.#title_with_emoji(prompt_result),
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import { flags } from "../args";
|
|
3
|
-
import { get_value_from_cache, set_value_cache } from "../utils";
|
|
4
|
-
import { infer_type_from_git } from "../utils/infer";
|
|
5
|
-
import { cache_message, inferred_message } from "../utils/messages";
|
|
6
|
-
import { Runnable } from "./runnable";
|
|
7
|
-
|
|
8
|
-
export class CommitTypePrompt extends Runnable {
|
|
9
|
-
async run() {
|
|
10
|
-
if (this.#is_enabled) {
|
|
11
|
-
const { initial_value, message } = this.#initial_value;
|
|
12
|
-
const commit_type = await p.select({
|
|
13
|
-
message,
|
|
14
|
-
initialValue: initial_value,
|
|
15
|
-
maxItems: this.#max_items,
|
|
16
|
-
options: this.#options,
|
|
17
|
-
});
|
|
18
|
-
if (p.isCancel(commit_type)) process.exit(0);
|
|
19
|
-
|
|
20
|
-
this.#run_post_effects(commit_type);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get #is_enabled(): boolean {
|
|
25
|
-
return this.config.commit_type.enable;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get #initial_value(): { initial_value: string | undefined; message: string } {
|
|
29
|
-
const cache_value = get_value_from_cache(this.prompt_cache, "commit_type");
|
|
30
|
-
if (cache_value)
|
|
31
|
-
return {
|
|
32
|
-
initial_value: cache_value,
|
|
33
|
-
message: cache_message("Commit type"),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
if (this.config.commit_type.infer_type_from_branch) {
|
|
37
|
-
const type_from_branch = infer_type_from_git(
|
|
38
|
-
this.#options,
|
|
39
|
-
flags.git_args,
|
|
40
|
-
);
|
|
41
|
-
if (type_from_branch) {
|
|
42
|
-
return {
|
|
43
|
-
message: inferred_message("Commit type"),
|
|
44
|
-
initial_value: type_from_branch,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
initial_value: this.config.commit_type.initial_value,
|
|
51
|
-
message: "Select a commit type",
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get #options(): {
|
|
56
|
-
label: string | undefined;
|
|
57
|
-
value: string;
|
|
58
|
-
emoji?: string;
|
|
59
|
-
hint?: string;
|
|
60
|
-
trailer?: string;
|
|
61
|
-
}[] {
|
|
62
|
-
return this.config.commit_type.options;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
get #value_to_data(): Record<string, { emoji: string; trailer: string }> {
|
|
66
|
-
return this.#options.reduce(
|
|
67
|
-
(acc, curr) => ({
|
|
68
|
-
...acc,
|
|
69
|
-
[curr.value]: {
|
|
70
|
-
emoji: curr.emoji ?? "",
|
|
71
|
-
trailer: curr.trailer ?? "",
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
{},
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get #max_items(): number | undefined {
|
|
79
|
-
return this.config.commit_type.max_items;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
#run_post_effects(prompt_result: string): void {
|
|
83
|
-
set_value_cache(this.prompt_cache, "commit_type", prompt_result);
|
|
84
|
-
|
|
85
|
-
const value_to_data = this.#value_to_data;
|
|
86
|
-
this.commit_state.trailer = value_to_data[prompt_result].trailer;
|
|
87
|
-
this.commit_state.type =
|
|
88
|
-
this.config.commit_type.append_emoji_to_commit &&
|
|
89
|
-
this.config.commit_type.emoji_commit_position === "Start"
|
|
90
|
-
? `${value_to_data[prompt_result].emoji} ${prompt_result}`.trim()
|
|
91
|
-
: prompt_result;
|
|
92
|
-
}
|
|
93
|
-
}
|
package/src/prompts/runnable.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { InferOutput } from "valibot";
|
|
2
|
-
import { CommitState, Config } from "../valibot-state";
|
|
3
|
-
import Configstore from "configstore";
|
|
4
|
-
|
|
5
|
-
export abstract class Runnable {
|
|
6
|
-
constructor(
|
|
7
|
-
protected config: InferOutput<typeof Config>,
|
|
8
|
-
protected commit_state: InferOutput<typeof CommitState>,
|
|
9
|
-
protected prompt_cache: Configstore,
|
|
10
|
-
) {}
|
|
11
|
-
|
|
12
|
-
abstract run(): Promise<void>;
|
|
13
|
-
}
|