diff --git a/README.md b/README.md index cc3ffc5..73d6d1c 100644 --- a/README.md +++ b/README.md @@ -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`. diff --git a/src/api.ts b/src/api.ts index 72dcece..0d1b36f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -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(); diff --git a/src/cli.ts b/src/cli.ts index 74c9800..3740998 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -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 { diff --git a/src/commands/commit.ts b/src/commands/commit.ts index d3a5c5d..af6759f 100644 --- a/src/commands/commit.ts +++ b/src/commands/commit.ts @@ -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( diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 27590cc..0077b25 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -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 { diff --git a/src/i18n/pt_br.json b/src/i18n/pt_br.json new file mode 100644 index 0000000..0c86700 --- /dev/null +++ b/src/i18n/pt_br.json @@ -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." +} + \ No newline at end of file diff --git a/src/utils/checkIsLatestVersion.ts b/src/utils/checkIsLatestVersion.ts new file mode 100644 index 0000000..89f2751 --- /dev/null +++ b/src/utils/checkIsLatestVersion.ts @@ -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. + ` + ) + ); + } + } +}; diff --git a/src/utils/git.ts b/src/utils/git.ts index b558581..bba4948 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -29,7 +29,8 @@ export const getStagedFiles = async (): Promise => { const { stdout: files } = await execa('git', [ 'diff', '--name-only', - '--cached' + '--cached', + '--relative' ]); if (!files) return [];