Files
aicommits/src/commands/aicommits.ts
hiroki osame 5fe127d377 feat: show error stack on unknown error (#124)
* feat: show error stack on unknown error

* improve message
2023-03-03 00:58:22 -05:00

85 lines
2.1 KiB
TypeScript

import { execa } from 'execa';
import {
black, dim, green, red, bgCyan,
} from 'kolorist';
import {
intro, outro, spinner, select, confirm, isCancel,
} from '@clack/prompts';
import {
assertGitRepo,
getStagedDiff,
getDetectedMessage,
} from '../utils/git.js';
import { getConfig } from '../utils/config.js';
import { generateCommitMessage } from '../utils/openai.js';
import { KnownError, handleCliError } from '../utils/error.js';
export default async (
generate: number,
rawArgv: string[],
) => (async () => {
intro(bgCyan(black(' aicommits ')));
await assertGitRepo();
const detectingFiles = spinner();
detectingFiles.start('Detecting staged files');
const staged = await getStagedDiff();
if (!staged) {
throw new KnownError('No staged changes found. Make sure to stage your changes with `git add`.');
}
detectingFiles.stop(`${getDetectedMessage(staged.files)}:\n${
staged.files.map(file => ` ${file}`).join('\n')
}`);
const config = await getConfig();
const OPENAI_KEY = process.env.OPENAI_KEY ?? process.env.OPENAI_API_KEY ?? config.OPENAI_KEY;
if (!OPENAI_KEY) {
throw new KnownError('Please set your OpenAI API key via `aicommits config set OPENAI_KEY=<your token>`');
}
const s = spinner();
s.start('The AI is analyzing your changes');
const messages = await generateCommitMessage(
OPENAI_KEY,
staged.diff,
generate,
);
s.stop('Changes analyzed');
let message: string;
if (messages.length === 1) {
[message] = messages;
const confirmed = await confirm({
message: `Use this commit message?\n\n ${message}\n`,
});
if (!confirmed || isCancel(confirmed)) {
outro('Commit cancelled');
return;
}
} else {
const selected = await select({
message: `Pick a commit message to use: ${dim('(Ctrl+c to exit)')}`,
options: messages.map(value => ({ label: value, value })),
});
if (isCancel(selected)) {
outro('Commit cancelled');
return;
}
message = selected;
}
await execa('git', ['commit', '-m', message, ...rawArgv]);
outro(`${green('✔')} Successfully committed!`);
})().catch((error) => {
outro(`${red('✖')} ${error.message}`);
handleCliError(error);
process.exit(1);
});