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:
@@ -84,6 +84,24 @@ To remove description:
|
|||||||
oc config set description=false
|
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
|
### 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`.
|
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`.
|
||||||
|
|||||||
+18
-1
@@ -53,7 +53,10 @@ class OpenAi {
|
|||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
outro(`${chalk.red('✖')} ${error}`);
|
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;
|
const openAiError = error.response.data.error;
|
||||||
|
|
||||||
if (openAiError?.message) outro(openAiError.message);
|
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();
|
export const api = new OpenAi();
|
||||||
|
|||||||
+3
-1
@@ -7,6 +7,7 @@ import { configCommand } from './commands/config';
|
|||||||
import { hookCommand, isHookCalled } from './commands/githook.js';
|
import { hookCommand, isHookCalled } from './commands/githook.js';
|
||||||
import { prepareCommitMessageHook } from './commands/prepare-commit-msg-hook';
|
import { prepareCommitMessageHook } from './commands/prepare-commit-msg-hook';
|
||||||
import { commit } from './commands/commit';
|
import { commit } from './commands/commit';
|
||||||
|
import { checkIsLatestVersion } from './utils/checkIsLatestVersion';
|
||||||
|
|
||||||
const extraArgs = process.argv.slice(2);
|
const extraArgs = process.argv.slice(2);
|
||||||
|
|
||||||
@@ -19,7 +20,8 @@ cli(
|
|||||||
ignoreArgv: (type) => type === 'unknown-flag' || type === 'argument',
|
ignoreArgv: (type) => type === 'unknown-flag' || type === 'argument',
|
||||||
help: { description: packageJSON.description }
|
help: { description: packageJSON.description }
|
||||||
},
|
},
|
||||||
() => {
|
async () => {
|
||||||
|
await checkIsLatestVersion();
|
||||||
if (isHookCalled) {
|
if (isHookCalled) {
|
||||||
prepareCommitMessageHook();
|
prepareCommitMessageHook();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+39
-12
@@ -16,11 +16,18 @@ import {
|
|||||||
outro,
|
outro,
|
||||||
isCancel,
|
isCancel,
|
||||||
intro,
|
intro,
|
||||||
multiselect
|
multiselect,
|
||||||
|
select
|
||||||
} from '@clack/prompts';
|
} from '@clack/prompts';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { trytm } from '../utils/trytm';
|
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 (
|
const generateCommitMessageFromGitDiff = async (
|
||||||
diff: string,
|
diff: string,
|
||||||
extraArgs: string[]
|
extraArgs: string[]
|
||||||
@@ -70,22 +77,42 @@ ${chalk.grey('——————————————————')}`
|
|||||||
outro(`${chalk.green('✔')} successfully committed`);
|
outro(`${chalk.green('✔')} successfully committed`);
|
||||||
|
|
||||||
outro(stdout);
|
outro(stdout);
|
||||||
|
const remotes = await getGitRemotes();
|
||||||
|
|
||||||
const isPushConfirmedByUser = await confirm({
|
if (remotes.length === 1) {
|
||||||
message: 'Do you want to run `git push`?'
|
const isPushConfirmedByUser = await confirm({
|
||||||
});
|
message: 'Do you want to run `git push`?'
|
||||||
|
});
|
||||||
|
|
||||||
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
||||||
const pushSpinner = spinner();
|
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`');
|
if (!isCancel(selectedRemote)) {
|
||||||
const { stdout } = await execa('git', ['push']);
|
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);
|
||||||
|
} else outro(`${chalk.gray('✖')} process cancelled`);
|
||||||
if (stdout) outro(stdout);
|
|
||||||
}
|
}
|
||||||
} else outro(`${chalk.gray('✖')} process cancelled`);
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function commit(
|
export async function commit(
|
||||||
|
|||||||
+6
-1
@@ -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_CN from '../i18n/zh_CN.json' assert { type: 'json' };
|
||||||
import zh_TW from '../i18n/zh_TW.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 ja from '../i18n/ja.json' assert { type: 'json' };
|
||||||
|
import pt_br from '../i18n/pt_br.json' assert { type: 'json' };
|
||||||
|
|
||||||
export enum I18nLocals {
|
export enum I18nLocals {
|
||||||
'en' = 'en',
|
'en' = 'en',
|
||||||
@@ -15,7 +16,8 @@ export enum I18nLocals {
|
|||||||
'de' = 'de',
|
'de' = 'de',
|
||||||
'fr' = 'fr',
|
'fr' = 'fr',
|
||||||
'it' = 'it',
|
'it' = 'it',
|
||||||
'ko' = 'ko'
|
'ko' = 'ko',
|
||||||
|
'pt_br' = 'pt_br'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const i18n = {
|
export const i18n = {
|
||||||
@@ -27,6 +29,7 @@ export const i18n = {
|
|||||||
fr,
|
fr,
|
||||||
it,
|
it,
|
||||||
ko,
|
ko,
|
||||||
|
pt_br
|
||||||
};
|
};
|
||||||
|
|
||||||
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
|
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
|
||||||
@@ -37,6 +40,8 @@ export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
|
|||||||
de: ['de', 'German' ,'Deutsch'],
|
de: ['de', 'German' ,'Deutsch'],
|
||||||
fr: ['fr', 'French', 'française'],
|
fr: ['fr', 'French', 'française'],
|
||||||
it: ['it', 'Italian', 'italiano'],
|
it: ['it', 'Italian', 'italiano'],
|
||||||
|
pt_br: ['pt_br', 'Portuguese', 'português'],
|
||||||
|
en: ['en', 'English', 'english'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getI18nLocal(value: string): string | boolean {
|
export function getI18nLocal(value: string): string | boolean {
|
||||||
|
|||||||
@@ -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."
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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.
|
||||||
|
`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
+2
-1
@@ -29,7 +29,8 @@ export const getStagedFiles = async (): Promise<string[]> => {
|
|||||||
const { stdout: files } = await execa('git', [
|
const { stdout: files } = await execa('git', [
|
||||||
'diff',
|
'diff',
|
||||||
'--name-only',
|
'--name-only',
|
||||||
'--cached'
|
'--cached',
|
||||||
|
'--relative'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!files) return [];
|
if (!files) return [];
|
||||||
|
|||||||
Reference in New Issue
Block a user