feat(cli.ts): check if the latest version of opencommit is being used on startup

feat(api.ts): add function to get the latest version of opencommit from unpkg.com

feat(commit.ts): add support for pushing to multiple remotes and prompt user to choose which remote to push to

feat(i18n): add support for Portuguese (Brazil) language and translation for commit messages in pt_br.json

feat(utils): add checkIsLatestVersion function to check if the current version is the latest version
fix(git.ts): add --relative flag to getStagedFiles function to return relative paths
This commit is contained in:
di-sukharev
2023-03-21 15:36:05 +08:00
8 changed files with 115 additions and 16 deletions

View File

@@ -84,6 +84,24 @@ To remove description:
oc config set description=false
```
### Internationalization support
To specify the language used to generate commit messages:
```sh
# de, German ,Deutsch
oc config set language=de
oc config set language=German
oc config set language=Deutsch
# fr, French, française
oc config set language=fr
oc config set language=French
oc config set language=française
```
The default language set is **English**
All available languages are currently listed in the [i18n](https://github.com/di-sukharev/opencommit/tree/master/src/i18n) folder
### Git flags
The `opencommit` or `oc` commands can be used in place of the `git commit -m "${generatedMessage}"` command. This means that any regular flags that are used with the `git commit` command will also be applied when using `opencommit` or `oc`.

View File

@@ -53,7 +53,10 @@ class OpenAi {
} catch (error: unknown) {
outro(`${chalk.red('✖')} ${error}`);
if (axios.isAxiosError<{ error?: { message: string } }>(error) && error.response?.status === 401) {
if (
axios.isAxiosError<{ error?: { message: string } }>(error) &&
error.response?.status === 401
) {
const openAiError = error.response.data.error;
if (openAiError?.message) outro(openAiError.message);
@@ -67,4 +70,18 @@ class OpenAi {
};
}
export const getOpenCommitLatestVersion = async (): Promise<
string | undefined
> => {
try {
const { data } = await axios.get(
'https://unpkg.com/opencommit/package.json'
);
return data.version;
} catch (_) {
outro('Error while getting the latest version of opencommit');
return undefined;
}
};
export const api = new OpenAi();

View File

@@ -7,6 +7,7 @@ import { configCommand } from './commands/config';
import { hookCommand, isHookCalled } from './commands/githook.js';
import { prepareCommitMessageHook } from './commands/prepare-commit-msg-hook';
import { commit } from './commands/commit';
import { checkIsLatestVersion } from './utils/checkIsLatestVersion';
const extraArgs = process.argv.slice(2);
@@ -19,7 +20,8 @@ cli(
ignoreArgv: (type) => type === 'unknown-flag' || type === 'argument',
help: { description: packageJSON.description }
},
() => {
async () => {
await checkIsLatestVersion();
if (isHookCalled) {
prepareCommitMessageHook();
} else {

View File

@@ -16,11 +16,18 @@ import {
outro,
isCancel,
intro,
multiselect
multiselect,
select
} from '@clack/prompts';
import chalk from 'chalk';
import { trytm } from '../utils/trytm';
// Adding a function to get the list of remotes
const getGitRemotes = async () => {
const { stdout } = await execa('git', ['remote']);
return stdout.split('\n').filter((remote) => remote.trim() !== '');
};
const generateCommitMessageFromGitDiff = async (
diff: string,
extraArgs: string[]
@@ -70,22 +77,42 @@ ${chalk.grey('——————————————————')}`
outro(`${chalk.green('✔')} successfully committed`);
outro(stdout);
const remotes = await getGitRemotes();
const isPushConfirmedByUser = await confirm({
message: 'Do you want to run `git push`?'
});
if (remotes.length === 1) {
const isPushConfirmedByUser = await confirm({
message: 'Do you want to run `git push`?'
});
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
const pushSpinner = spinner();
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
const pushSpinner = spinner();
pushSpinner.start(`Running \`git push ${remotes[0]}\``);
const { stdout } = await execa('git', ['push', remotes[0]]);
pushSpinner.stop(
`${chalk.green('✔')} successfully pushed all commits to ${remotes[0]}`
);
if (stdout) outro(stdout);
}
} else {
const selectedRemote = (await select({
message: 'Choose a remote to push to',
options: remotes.map((remote) => ({ value: remote, label: remote }))
})) as string;
pushSpinner.start('Running `git push`');
const { stdout } = await execa('git', ['push']);
if (!isCancel(selectedRemote)) {
const pushSpinner = spinner();
pushSpinner.start(`Running \`git push ${selectedRemote}\``);
const { stdout } = await execa('git', ['push', selectedRemote]);
pushSpinner.stop(
`${chalk.green(
'✔'
)} successfully pushed all commits to ${selectedRemote}`
);
pushSpinner.stop(`${chalk.green('✔')} successfully pushed all commits`);
if (stdout) outro(stdout);
if (stdout) outro(stdout);
} else outro(`${chalk.gray('✖')} process cancelled`);
}
} else outro(`${chalk.gray('✖')} process cancelled`);
}
};
export async function commit(

View File

@@ -6,6 +6,7 @@ import ko from '../i18n/ko.json' assert { type: 'json' };
import zh_CN from '../i18n/zh_CN.json' assert { type: 'json' };
import zh_TW from '../i18n/zh_TW.json' assert { type: 'json' };
import ja from '../i18n/ja.json' assert { type: 'json' };
import pt_br from '../i18n/pt_br.json' assert { type: 'json' };
export enum I18nLocals {
'en' = 'en',
@@ -15,7 +16,8 @@ export enum I18nLocals {
'de' = 'de',
'fr' = 'fr',
'it' = 'it',
'ko' = 'ko'
'ko' = 'ko',
'pt_br' = 'pt_br'
};
export const i18n = {
@@ -27,6 +29,7 @@ export const i18n = {
fr,
it,
ko,
pt_br
};
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
@@ -37,6 +40,8 @@ export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
de: ['de', 'German' ,'Deutsch'],
fr: ['fr', 'French', 'française'],
it: ['it', 'Italian', 'italiano'],
pt_br: ['pt_br', 'Portuguese', 'português'],
en: ['en', 'English', 'english'],
};
export function getI18nLocal(value: string): string | boolean {

7
src/i18n/pt_br.json Normal file
View File

@@ -0,0 +1,7 @@
{
"localLanguage": "português",
"commitFix": "fix(server.ts): altera o caso da variável de porta de port minúscula para PORT maiúscula",
"commitFeat": "feat(server.ts): adiciona suporte para a variável de ambiente process.env.PORT",
"commitDescription": "A variável de porta agora é denominada PORT, o que melhora a consistência com as convenções de nomenclatura, pois PORT é uma constante. O suporte para uma variável de ambiente permite que o aplicativo seja mais flexível, pois agora pode ser executado em qualquer porta disponível especificada por meio da variável de ambiente process.env.PORT."
}

View File

@@ -0,0 +1,22 @@
import { getOpenCommitLatestVersion } from '../api';
import currentPackage from '../../package.json' assert { type: 'json' };
import chalk from 'chalk';
export const checkIsLatestVersion = async () => {
const latestVersion = await getOpenCommitLatestVersion();
if (latestVersion) {
const currentVersion = currentPackage.version;
if (currentVersion !== latestVersion) {
console.warn(
chalk.yellow(
`
You are not using the latest stable version of OpenCommit with new features and bug fixes.
Current version: ${currentVersion}. Latest version: ${latestVersion}.
🚀 To update run: npm i -g opencommit@latest.
`
)
);
}
}
};

View File

@@ -29,7 +29,8 @@ export const getStagedFiles = async (): Promise<string[]> => {
const { stdout: files } = await execa('git', [
'diff',
'--name-only',
'--cached'
'--cached',
'--relative'
]);
if (!files) return [];