mirror of
https://github.com/di-sukharev/opencommit.git
synced 2026-01-12 23:28:16 -05:00
Compare commits
91 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9c66ae168 | ||
|
|
18b0004b81 | ||
|
|
4d4157087e | ||
|
|
3edb6e2fc1 | ||
|
|
d428102a67 | ||
|
|
9404f5d410 | ||
|
|
8c1eb4a5ad | ||
|
|
bafe7e9ede | ||
|
|
a4716b35a4 | ||
|
|
c1e9062ce0 | ||
|
|
c7efa6f935 | ||
|
|
1b70de1d20 | ||
|
|
853662acc4 | ||
|
|
0e1ad33179 | ||
|
|
e7eaa5425e | ||
|
|
4b96670374 | ||
|
|
e128cdece1 | ||
|
|
4cc73208cd | ||
|
|
ea864d18f4 | ||
|
|
5d131e66fa | ||
|
|
bf24be92a1 | ||
|
|
3103ae18b8 | ||
|
|
7c9feba3ba | ||
|
|
58369e4df9 | ||
|
|
3d50a67ece | ||
|
|
a2d03e054c | ||
|
|
1c113c2901 | ||
|
|
18dcb8e8c2 | ||
|
|
8b17b5e906 | ||
|
|
284604f6a4 | ||
|
|
bdce94f2ac | ||
|
|
a3fade4d42 | ||
|
|
83906fc704 | ||
|
|
e7f7bfc2bd | ||
|
|
3885ae5893 | ||
|
|
b8e05a5852 | ||
|
|
677b7ecad9 | ||
|
|
6ab06f9db3 | ||
|
|
38ac20612b | ||
|
|
54b8ba7419 | ||
|
|
ff81d7e1ca | ||
|
|
a6ccdb5f77 | ||
|
|
fef8027959 | ||
|
|
0f48cc616e | ||
|
|
b54ff02930 | ||
|
|
7fb46de105 | ||
|
|
2f6e98dc30 | ||
|
|
2aa6582c52 | ||
|
|
2acf833cd0 | ||
|
|
3f7025d50a | ||
|
|
d793bf1340 | ||
|
|
0092e92061 | ||
|
|
0f33b74942 | ||
|
|
8f0a32275e | ||
|
|
b3509e34d0 | ||
|
|
5449d5cd61 | ||
|
|
b0d27e62ba | ||
|
|
5ae52cd8bb | ||
|
|
57baedd0b0 | ||
|
|
d4fc651fec | ||
|
|
04d40b5379 | ||
|
|
ec2e4c628c | ||
|
|
c787329710 | ||
|
|
0d1f72bdec | ||
|
|
5d0c69e849 | ||
|
|
9754442efa | ||
|
|
a619cd1f78 | ||
|
|
1fc4a6b6c0 | ||
|
|
798bddba81 | ||
|
|
42ed2a31f4 | ||
|
|
571e1e9d8f | ||
|
|
bd8de7a8ea | ||
|
|
913bcd379f | ||
|
|
25468f67ad | ||
|
|
6766f62848 | ||
|
|
71c36db265 | ||
|
|
ed66e403e7 | ||
|
|
b89e50ebbf | ||
|
|
38ebe49daa | ||
|
|
6ccded1f23 | ||
|
|
31357132e4 | ||
|
|
b35a393152 | ||
|
|
8fe382a072 | ||
|
|
4b703c634a | ||
|
|
6821e937cf | ||
|
|
69f3c48b2c | ||
|
|
f49f1a86df | ||
|
|
98945df561 | ||
|
|
e8e190ff3d | ||
|
|
9c3f28b7c6 | ||
|
|
e146d4d60d |
8
.github/CONTRIBUTING.md
vendored
8
.github/CONTRIBUTING.md
vendored
@@ -1,6 +1,6 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
Thank you for considering contributing to the project. Let's shake it baby.
|
||||
Thanks for considering contributing to the project.
|
||||
|
||||
## How to contribute
|
||||
|
||||
@@ -9,7 +9,7 @@ Thank you for considering contributing to the project. Let's shake it baby.
|
||||
3. Create a new branch for your changes.
|
||||
4. Make your changes and commit them with descriptive commit messages.
|
||||
5. Push your changes to your forked repository.
|
||||
6. Create a pull request from your branch to the `master` branch.
|
||||
6. Create a pull request from your branch to the `dev` branch.
|
||||
|
||||
## Getting started
|
||||
|
||||
@@ -28,9 +28,9 @@ Use the library to generate commits, stage the files and run `npm run dev` :)
|
||||
|
||||
If you encounter any issues while using the project, please report them on the GitHub issue tracker. When reporting issues, please include as much information as possible, such as steps to reproduce the issue, expected behavior, and actual behavior.
|
||||
|
||||
## Contact us
|
||||
## Contacts
|
||||
|
||||
If you have any questions about contributing to the project, please contact us by [creating an issue](https://github.com/di-sukharev/open-commit/issues) on the GitHub issue tracker.
|
||||
If you have any questions about contributing to the project, please contact by [creating an issue](https://github.com/di-sukharev/open-commit/issues) on the GitHub issue tracker.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
10
.github/TODO.md
vendored
Normal file
10
.github/TODO.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# TODOs
|
||||
|
||||
- [x] set prepare-commit-msg hook
|
||||
- [] show "new version available" message, look into this commit e146d4d cli.ts file
|
||||
- [] make bundle smaller by properly configuring esbuild
|
||||
- [] [build for both mjs and cjs](https://snyk.io/blog/best-practices-create-modern-npm-package/)
|
||||
- [] do // TODOs in the code
|
||||
- [x] batch small files in one request
|
||||
- [] add tests
|
||||
- [] optimize prompt, maybe no prompt would be cleaner
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -10,4 +10,6 @@ application.log
|
||||
logfile.log
|
||||
uncaughtExceptions.log
|
||||
.vscode
|
||||
src/*.json
|
||||
src/*.json
|
||||
.idea
|
||||
test.ts
|
||||
60
README.md
60
README.md
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<img src=".github/logo-grad.svg" alt="OpenCommit logo"/>
|
||||
<h1 align="center">OpenCommit</h1>
|
||||
<h4 align="center">Author <a href="https://github.com/di-sukharev">@di-sukharev</a> <a href="https://twitter.com/io_Y_oi"><img src="https://img.shields.io/twitter/follow/io_Y_oi?style=flat&label=io_Y_oi&logo=twitter&color=0bf&logoColor=fff" align="center"></a>
|
||||
<h4 align="center">Follow the bird <a href="https://twitter.com/io_Y_oi"><img src="https://img.shields.io/twitter/follow/io_Y_oi?style=flat&label=io_Y_oi&logo=twitter&color=0bf&logoColor=fff" align="center"></a>
|
||||
</h4>
|
||||
</div>
|
||||
<h2>GPT CLI to auto-generate impressive commits in 1 second</h2>
|
||||
@@ -20,17 +20,15 @@ All the commits in this repo are done with OpenCommit — look into [the commits
|
||||
|
||||
## Setup
|
||||
|
||||
> The minimum supported version of Node.js is the latest v14. Check your Node.js version with `node --version`.
|
||||
|
||||
1. Install opencommit globally to use in any repository:
|
||||
1. Install OpenCommit globally to use in any repository:
|
||||
|
||||
```sh
|
||||
npm install -g opencommit
|
||||
```
|
||||
|
||||
2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys)
|
||||
2. Get your API key from [OpenAI](https://platform.openai.com/account/api-keys). Make sure you add payment details, so API works.
|
||||
|
||||
3. Set the key to opencommit config:
|
||||
3. Set the key to OpenCommit config:
|
||||
|
||||
```sh
|
||||
opencommit config set OPENAI_API_KEY=<your_api_key>
|
||||
@@ -40,7 +38,7 @@ All the commits in this repo are done with OpenCommit — look into [the commits
|
||||
|
||||
## Usage
|
||||
|
||||
You can call `opencommit` directly to generate a commit message for your staged changes:
|
||||
You can call OpenCommit directly to generate a commit message for your staged changes:
|
||||
|
||||
```sh
|
||||
git add <files...>
|
||||
@@ -86,9 +84,53 @@ 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`.
|
||||
|
||||
```sh
|
||||
oc --no-verify
|
||||
```
|
||||
|
||||
is translated to :
|
||||
|
||||
```sh
|
||||
git commit -m "${generatedMessage}" --no-verify
|
||||
```
|
||||
|
||||
### Ignore files
|
||||
You can ignore files from submission to OpenAI by creating a `.opencommitignore` file. For example:
|
||||
|
||||
```ignorelang
|
||||
path/to/large-asset.zip
|
||||
**/*.jpg
|
||||
```
|
||||
|
||||
This is useful for preventing opencommit from uploading artifacts and large files.
|
||||
|
||||
By default, opencommit ignores files matching: `*-lock.*` and `*.lock`
|
||||
|
||||
## Git hook
|
||||
|
||||
You can set opencommit as Git [`prepare-commit-msg`](https://git-scm.com/docs/githooks#_prepare_commit_msg) hook. Hook integrates with you IDE Source Control and allows you edit the message before commit.
|
||||
You can set OpenCommit as Git [`prepare-commit-msg`](https://git-scm.com/docs/githooks#_prepare_commit_msg) hook. Hook integrates with you IDE Source Control and allows you edit the message before commit.
|
||||
|
||||
To set the hook:
|
||||
|
||||
@@ -113,4 +155,4 @@ Or follow the process of your IDE Source Control feature, when it calls `git com
|
||||
|
||||
## Payments
|
||||
|
||||
You pay for your own requests to OpenAI API. OpenCommit uses ChatGPT official model, that is ~10x times cheaper than GPT-3.
|
||||
You pay for your own requests to OpenAI API. OpenCommit uses ChatGPT official model, that is ~10x times cheaper than GPT-3 and ~6x times cheaper than GPT-4.
|
||||
|
||||
8
TODO.md
8
TODO.md
@@ -1,8 +0,0 @@
|
||||
# TODOs
|
||||
|
||||
- [] make bundle smaller by properly configuring esbuild
|
||||
- [] [build for both mjs and cjs](https://snyk.io/blog/best-practices-create-modern-npm-package/)
|
||||
- [] do // TODOs in the code
|
||||
- [] batch small files in one request
|
||||
- [] add tests
|
||||
- [] make hook work
|
||||
604
package-lock.json
generated
604
package-lock.json
generated
@@ -1,26 +1,28 @@
|
||||
{
|
||||
"name": "open-commit",
|
||||
"version": "1.0.15",
|
||||
"name": "opencommit",
|
||||
"version": "1.1.32",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "open-commit",
|
||||
"version": "1.0.15",
|
||||
"license": "ISC",
|
||||
"name": "opencommit",
|
||||
"version": "1.1.32",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^0.6.1",
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"axios": "^1.3.4",
|
||||
"chalk": "^5.2.0",
|
||||
"cleye": "^1.3.2",
|
||||
"execa": "^7.0.0",
|
||||
"ignore": "^5.2.4",
|
||||
"ini": "^3.0.1",
|
||||
"inquirer": "^9.1.4",
|
||||
"openai": "^3.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"oc": "out/cli.mjs",
|
||||
"opencommit": "out/cli.mjs"
|
||||
"oc": "out/cli.cjs",
|
||||
"opencommit": "out/cli.cjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ini": "^1.3.31",
|
||||
@@ -31,28 +33,29 @@
|
||||
"dotenv": "^16.0.3",
|
||||
"esbuild": "^0.15.18",
|
||||
"eslint": "^8.28.0",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@clack/core": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.0.tgz",
|
||||
"integrity": "sha512-ujw1888RciTArxUvwLOf24XSygRX7F4qiCPI7WLH3zCTZJuqKPMcTS7Wqjz0x/AuMpwGPlzhKln4+sCuQqYxzA==",
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.2.tgz",
|
||||
"integrity": "sha512-FZnsNynwGDIDktx6PEZK1EuCkFpY4ldEX6VYvfl0dqeoLPb9Jpw1xoUXaVcGR8ExmYNm1w2vdGdJkEUYD/2pqg==",
|
||||
"dependencies": {
|
||||
"picocolors": "^1.0.0",
|
||||
"sisteransi": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@clack/prompts": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.6.1.tgz",
|
||||
"integrity": "sha512-7KuMST/5zB7KpvfR00kcnbOaXmfN6tkJmkLpAyV2Iv2SJ7oxFbhNFvR5OQJynSKDhU8oOp/eFMK6Q0k/DXsq8A==",
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.6.3.tgz",
|
||||
"integrity": "sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw==",
|
||||
"bundleDependencies": [
|
||||
"is-unicode-supported"
|
||||
],
|
||||
"dependencies": {
|
||||
"@clack/core": "^0.3.0",
|
||||
"@clack/core": "^0.3.2",
|
||||
"is-unicode-supported": "*",
|
||||
"picocolors": "^1.0.0",
|
||||
"sisteransi": "^1.0.5"
|
||||
@@ -81,6 +84,43 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@dqbd/tiktoken": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@dqbd/tiktoken/-/tiktoken-1.0.2.tgz",
|
||||
"integrity": "sha512-AjGTBRWsMoVmVeN55NLyupyM8TNamOUBl6tj5t/leLDVup3CFGO9tVagNL1jf3GyZLkWZSTmYVbPQ/M2LEcNzw=="
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
|
||||
"integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
|
||||
"integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
|
||||
@@ -274,14 +314,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz",
|
||||
"integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz",
|
||||
"integrity": "sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.54.0",
|
||||
"@typescript-eslint/type-utils": "5.54.0",
|
||||
"@typescript-eslint/utils": "5.54.0",
|
||||
"@typescript-eslint/scope-manager": "5.54.1",
|
||||
"@typescript-eslint/type-utils": "5.54.1",
|
||||
"@typescript-eslint/utils": "5.54.1",
|
||||
"debug": "^4.3.4",
|
||||
"grapheme-splitter": "^1.0.4",
|
||||
"ignore": "^5.2.0",
|
||||
@@ -308,14 +348,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz",
|
||||
"integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz",
|
||||
"integrity": "sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.54.0",
|
||||
"@typescript-eslint/types": "5.54.0",
|
||||
"@typescript-eslint/typescript-estree": "5.54.0",
|
||||
"@typescript-eslint/scope-manager": "5.54.1",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/typescript-estree": "5.54.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -335,13 +375,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz",
|
||||
"integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz",
|
||||
"integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.0",
|
||||
"@typescript-eslint/visitor-keys": "5.54.0"
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -352,13 +392,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz",
|
||||
"integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz",
|
||||
"integrity": "sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "5.54.0",
|
||||
"@typescript-eslint/utils": "5.54.0",
|
||||
"@typescript-eslint/typescript-estree": "5.54.1",
|
||||
"@typescript-eslint/utils": "5.54.1",
|
||||
"debug": "^4.3.4",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
@@ -379,9 +419,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz",
|
||||
"integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz",
|
||||
"integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -392,13 +432,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz",
|
||||
"integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz",
|
||||
"integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.0",
|
||||
"@typescript-eslint/visitor-keys": "5.54.0",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -419,16 +459,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz",
|
||||
"integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz",
|
||||
"integrity": "sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@types/semver": "^7.3.12",
|
||||
"@typescript-eslint/scope-manager": "5.54.0",
|
||||
"@typescript-eslint/types": "5.54.0",
|
||||
"@typescript-eslint/typescript-estree": "5.54.0",
|
||||
"@typescript-eslint/scope-manager": "5.54.1",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/typescript-estree": "5.54.1",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0",
|
||||
"semver": "^7.3.7"
|
||||
@@ -445,12 +485,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz",
|
||||
"integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz",
|
||||
"integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.0",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -542,15 +582,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
@@ -935,6 +971,54 @@
|
||||
"esbuild-windows-arm64": "0.15.18"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
|
||||
"integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-android-arm64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
|
||||
"integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
|
||||
"integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-darwin-arm64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
|
||||
@@ -951,6 +1035,262 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
|
||||
"integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-freebsd-arm64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
|
||||
"integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-32": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
|
||||
"integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
|
||||
"integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
|
||||
"integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-arm64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
|
||||
"integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-mips64le": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
|
||||
"integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-ppc64le": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
|
||||
"integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-riscv64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
|
||||
"integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-s390x": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
|
||||
"integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-netbsd-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
|
||||
"integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-openbsd-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
|
||||
"integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-sunos-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
|
||||
"integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-32": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
|
||||
"integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
|
||||
"integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-windows-arm64": {
|
||||
"version": "0.15.18",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
|
||||
"integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@@ -1069,6 +1409,21 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -1125,9 +1480,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esquery": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz",
|
||||
"integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==",
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
|
||||
"integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
@@ -1206,31 +1561,6 @@
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/execa/node_modules/mimic-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/execa/node_modules/onetime": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/external-editor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||
@@ -1557,7 +1887,6 @@
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
@@ -1890,11 +2219,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
@@ -1967,14 +2299,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
"mimic-fn": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -2172,6 +2504,21 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.8.4",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz",
|
||||
"integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
@@ -2207,9 +2554,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz",
|
||||
"integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==",
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
@@ -2255,6 +2602,28 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
@@ -2319,11 +2688,6 @@
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs/node_modules/tslib": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@@ -2583,10 +2947,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||
},
|
||||
"node_modules/tsutils": {
|
||||
"version": "3.21.0",
|
||||
@@ -2603,6 +2966,12 @@
|
||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tsutils/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -2726,17 +3095,6 @@
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/strip-ansi": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
|
||||
|
||||
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "opencommit",
|
||||
"version": "1.0.15",
|
||||
"version": "1.1.32",
|
||||
"description": "GPT CLI to auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
|
||||
"keywords": [
|
||||
"git",
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"author": "https://github.com/di-sukharev",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"out/**/*"
|
||||
],
|
||||
@@ -41,8 +41,9 @@
|
||||
"start": "node ./out/cli.cjs",
|
||||
"dev": "ts-node ./src/cli.ts",
|
||||
"build": "rimraf out && esbuild ./src/cli.ts --bundle --outfile=out/cli.cjs --format=cjs --platform=node",
|
||||
"deploy": "npm run build && npm version patch && npm publish",
|
||||
"lint": "eslint src --ext ts && tsc --noEmit"
|
||||
"deploy": "npm run build && npm version patch && npm publish --tag latest",
|
||||
"lint": "eslint src --ext ts && tsc --noEmit",
|
||||
"format": "prettier --write src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ini": "^1.3.31",
|
||||
@@ -53,6 +54,7 @@
|
||||
"dotenv": "^16.0.3",
|
||||
"esbuild": "^0.15.18",
|
||||
"eslint": "^8.28.0",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.3"
|
||||
},
|
||||
@@ -62,6 +64,7 @@
|
||||
"chalk": "^5.2.0",
|
||||
"cleye": "^1.3.2",
|
||||
"execa": "^7.0.0",
|
||||
"ignore": "^5.2.4",
|
||||
"ini": "^3.0.1",
|
||||
"inquirer": "^9.1.4",
|
||||
"openai": "^3.2.1"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export enum COMMANDS {
|
||||
config = 'config',
|
||||
hook = 'hook'
|
||||
hook = 'hook',
|
||||
config = 'config'
|
||||
}
|
||||
|
||||
50
src/api.ts
50
src/api.ts
@@ -1,4 +1,6 @@
|
||||
import { intro, outro } from '@clack/prompts';
|
||||
import axios from 'axios';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
ChatCompletionRequestMessage,
|
||||
Configuration as OpenAiApiConfiguration,
|
||||
@@ -17,26 +19,15 @@ if (!apiKey && command !== 'config' && mode !== CONFIG_MODES.set) {
|
||||
intro('opencommit');
|
||||
|
||||
outro(
|
||||
'OPENAI_API_KEY is not set, please run `oc config set OPENAI_API_KEY=<your token>`'
|
||||
'OPENAI_API_KEY is not set, please run `oc config set OPENAI_API_KEY=<your token>. Make sure you add payment details, so API works.`'
|
||||
);
|
||||
outro(
|
||||
'For help Look into README https://github.com/di-sukharev/opencommit#setup'
|
||||
'For help look into README https://github.com/di-sukharev/opencommit#setup'
|
||||
);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// if (!apiKey) {
|
||||
// intro('opencommit');
|
||||
// const apiKey = await text({
|
||||
// message: 'input your OPENAI_API_KEY'
|
||||
// });
|
||||
|
||||
// setConfig([[CONFIG_KEYS.OPENAI_API_KEY as string, apiKey as any]]);
|
||||
|
||||
// outro('OPENAI_API_KEY is set');
|
||||
// }
|
||||
|
||||
class OpenAi {
|
||||
private openAiApiConfiguration = new OpenAiApiConfiguration({
|
||||
apiKey: apiKey
|
||||
@@ -59,11 +50,38 @@ class OpenAi {
|
||||
const message = data.choices[0].message;
|
||||
|
||||
return message?.content;
|
||||
} catch (error) {
|
||||
// console.error('openAI api error', { error });
|
||||
throw error;
|
||||
} catch (error: unknown) {
|
||||
outro(`${chalk.red('✖')} ${error}`);
|
||||
|
||||
if (
|
||||
axios.isAxiosError<{ error?: { message: string } }>(error) &&
|
||||
error.response?.status === 401
|
||||
) {
|
||||
const openAiError = error.response.data.error;
|
||||
|
||||
if (openAiError?.message) outro(openAiError.message);
|
||||
outro(
|
||||
'For help look into README https://github.com/di-sukharev/opencommit#setup'
|
||||
);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
18
src/cli.ts
18
src/cli.ts
@@ -7,10 +7,9 @@ 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 { execa } from 'execa';
|
||||
import { outro } from '@clack/prompts';
|
||||
// import { checkIsLatestVersion } from './utils/checkIsLatestVersion';
|
||||
|
||||
const rawArgv = process.argv.slice(2);
|
||||
const extraArgs = process.argv.slice(2);
|
||||
|
||||
cli(
|
||||
{
|
||||
@@ -22,17 +21,12 @@ cli(
|
||||
help: { description: packageJSON.description }
|
||||
},
|
||||
async () => {
|
||||
// await checkIsLatestVersion();
|
||||
if (isHookCalled) {
|
||||
await prepareCommitMessageHook();
|
||||
prepareCommitMessageHook();
|
||||
} else {
|
||||
await commit();
|
||||
const { stdout } = await execa('npm', ['view', 'opencommit', 'version']);
|
||||
|
||||
if (stdout !== packageJSON.version)
|
||||
outro(
|
||||
'new opencommit version is available, update with `npm i -g opencommit`'
|
||||
);
|
||||
commit(extraArgs);
|
||||
}
|
||||
},
|
||||
rawArgv
|
||||
extraArgs
|
||||
);
|
||||
|
||||
@@ -3,12 +3,34 @@ import {
|
||||
GenerateCommitMessageErrorEnum,
|
||||
generateCommitMessageWithChatCompletion
|
||||
} from '../generateCommitMessageFromGitDiff';
|
||||
import { assertGitRepo, getStagedGitDiff } from '../utils/git';
|
||||
import { spinner, confirm, outro, isCancel, intro } from '@clack/prompts';
|
||||
import {
|
||||
assertGitRepo,
|
||||
getChangedFiles,
|
||||
getDiff,
|
||||
getStagedFiles,
|
||||
gitAdd
|
||||
} from '../utils/git';
|
||||
import {
|
||||
spinner,
|
||||
confirm,
|
||||
outro,
|
||||
isCancel,
|
||||
intro,
|
||||
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
|
||||
diff: string,
|
||||
extraArgs: string[]
|
||||
): Promise<void> => {
|
||||
await assertGitRepo();
|
||||
|
||||
@@ -41,59 +63,102 @@ ${chalk.grey('——————————————————')}`
|
||||
);
|
||||
|
||||
const isCommitConfirmedByUser = await confirm({
|
||||
message: 'Confirm the commit message'
|
||||
message: 'Confirm the commit message?'
|
||||
});
|
||||
|
||||
if (isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
|
||||
const { stdout } = await execa('git', ['commit', '-m', commitMessage]);
|
||||
const { stdout } = await execa('git', [
|
||||
'commit',
|
||||
'-m',
|
||||
commitMessage,
|
||||
...extraArgs
|
||||
]);
|
||||
|
||||
outro(`${chalk.green('✔')} successfully committed`);
|
||||
|
||||
outro(stdout);
|
||||
const isPushConfirmedByUser = await confirm({
|
||||
message: 'Do you want to run `git push`?'
|
||||
});
|
||||
const remotes = await getGitRemotes();
|
||||
|
||||
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
||||
const pushSpinner = spinner();
|
||||
if (remotes.length === 1) {
|
||||
const isPushConfirmedByUser = await confirm({
|
||||
message: 'Do you want to run `git push`?'
|
||||
});
|
||||
|
||||
pushSpinner.start('Running `git push`');
|
||||
const { stdout } = await execa('git', ['push']);
|
||||
pushSpinner.stop(`${chalk.green('✔')} successfully pushed all commits`);
|
||||
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
|
||||
const pushSpinner = spinner();
|
||||
|
||||
if (stdout) outro(stdout);
|
||||
pushSpinner.start(`Running \`git push ${remotes[0]}\``);
|
||||
|
||||
const { stdout } = await execa('git', [
|
||||
'push',
|
||||
'--verbose',
|
||||
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;
|
||||
|
||||
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}`
|
||||
);
|
||||
|
||||
if (stdout) outro(stdout);
|
||||
} else outro(`${chalk.gray('✖')} process cancelled`);
|
||||
}
|
||||
} else outro(`${chalk.gray('✖')} process cancelled`);
|
||||
}
|
||||
};
|
||||
|
||||
export async function commit(isStageAllFlag = false) {
|
||||
intro('open-commit');
|
||||
export async function commit(
|
||||
extraArgs: string[] = [],
|
||||
isStageAllFlag: Boolean = false
|
||||
) {
|
||||
if (isStageAllFlag) {
|
||||
const changedFiles = await getChangedFiles();
|
||||
|
||||
const stagedFilesSpinner = spinner();
|
||||
stagedFilesSpinner.start('Counting staged files');
|
||||
const staged = await getStagedGitDiff(isStageAllFlag);
|
||||
if (changedFiles) await gitAdd({ files: changedFiles });
|
||||
else {
|
||||
outro('No changes detected, write some code and run `oc` again');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!staged && isStageAllFlag) {
|
||||
outro(
|
||||
`${chalk.red(
|
||||
'No changes detected'
|
||||
)} — write some code, stage the files ${chalk
|
||||
.hex('0000FF')
|
||||
.bold('`git add .`')} and rerun ${chalk
|
||||
.hex('0000FF')
|
||||
.bold('`oc`')} command.`
|
||||
);
|
||||
const [stagedFiles, errorStagedFiles] = await trytm(getStagedFiles());
|
||||
const [changedFiles, errorChangedFiles] = await trytm(getChangedFiles());
|
||||
|
||||
if (!changedFiles?.length && !stagedFiles?.length) {
|
||||
outro(chalk.red('No changes detected'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!staged) {
|
||||
outro(
|
||||
`${chalk.red('Nothing to commit')} — stage the files ${chalk
|
||||
.hex('0000FF')
|
||||
.bold('`git add .`')} and rerun ${chalk
|
||||
.hex('0000FF')
|
||||
.bold('`oc`')} command.`
|
||||
);
|
||||
intro('open-commit');
|
||||
if (errorChangedFiles ?? errorStagedFiles) {
|
||||
outro(`${chalk.red('✖')} ${errorChangedFiles ?? errorStagedFiles}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const stagedFilesSpinner = spinner();
|
||||
|
||||
stagedFilesSpinner.start('Counting staged files');
|
||||
|
||||
if (!stagedFiles.length) {
|
||||
stagedFilesSpinner.stop('No files are staged');
|
||||
const isStageAllAndCommitConfirmedByUser = await confirm({
|
||||
message: 'Do you want to stage all files and generate commit message?'
|
||||
@@ -103,17 +168,44 @@ export async function commit(isStageAllFlag = false) {
|
||||
isStageAllAndCommitConfirmedByUser &&
|
||||
!isCancel(isStageAllAndCommitConfirmedByUser)
|
||||
) {
|
||||
await commit(true);
|
||||
await commit(extraArgs, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (stagedFiles.length === 0 && changedFiles.length > 0) {
|
||||
const files = (await multiselect({
|
||||
message: chalk.cyan('Select the files you want to add to the commit:'),
|
||||
options: changedFiles.map((file) => ({
|
||||
value: file,
|
||||
label: file
|
||||
}))
|
||||
})) as string[];
|
||||
|
||||
if (isCancel(files)) process.exit(1);
|
||||
|
||||
await gitAdd({ files });
|
||||
}
|
||||
|
||||
await commit(extraArgs, false);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
stagedFilesSpinner.stop(
|
||||
`${staged.files.length} staged files:\n${staged.files
|
||||
`${stagedFiles.length} staged files:\n${stagedFiles
|
||||
.map((file) => ` ${file}`)
|
||||
.join('\n')}`
|
||||
);
|
||||
|
||||
await generateCommitMessageFromGitDiff(staged.diff);
|
||||
const [, generateCommitError] = await trytm(
|
||||
generateCommitMessageFromGitDiff(
|
||||
await getDiff({ files: stagedFiles }),
|
||||
extraArgs
|
||||
)
|
||||
);
|
||||
|
||||
if (generateCommitError) {
|
||||
outro(`${chalk.red('✖')} ${generateCommitError}`);
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ import { homedir } from 'os';
|
||||
import { intro, outro } from '@clack/prompts';
|
||||
import chalk from 'chalk';
|
||||
import { COMMANDS } from '../CommandsEnum';
|
||||
import { getI18nLocal } from '../i18n';
|
||||
|
||||
export enum CONFIG_KEYS {
|
||||
OPENAI_API_KEY = 'OPENAI_API_KEY',
|
||||
description = 'description',
|
||||
emoji = 'emoji'
|
||||
emoji = 'emoji',
|
||||
language = 'language'
|
||||
}
|
||||
|
||||
export enum CONFIG_MODES {
|
||||
@@ -24,7 +26,11 @@ const validateConfig = (
|
||||
validationMessage: string
|
||||
) => {
|
||||
if (!condition) {
|
||||
throw new Error(`Unsupported config key ${key}: ${validationMessage}`);
|
||||
outro(
|
||||
`${chalk.red('✖')} Unsupported config key ${key}: ${validationMessage}`
|
||||
);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,6 +50,7 @@ export const configValidators = {
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
[CONFIG_KEYS.description](value: any) {
|
||||
validateConfig(
|
||||
CONFIG_KEYS.description,
|
||||
@@ -53,6 +60,7 @@ export const configValidators = {
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
[CONFIG_KEYS.emoji](value: any) {
|
||||
validateConfig(
|
||||
CONFIG_KEYS.emoji,
|
||||
@@ -61,6 +69,15 @@ export const configValidators = {
|
||||
);
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
[CONFIG_KEYS.language](value: any) {
|
||||
validateConfig(
|
||||
CONFIG_KEYS.language,
|
||||
getI18nLocal(value),
|
||||
`${value} is not supported yet`
|
||||
);
|
||||
return getI18nLocal(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
11
src/commands/githook.ts
Normal file → Executable file
11
src/commands/githook.ts
Normal file → Executable file
@@ -6,6 +6,7 @@ import { existsSync } from 'fs';
|
||||
import chalk from 'chalk';
|
||||
import { intro, outro } from '@clack/prompts';
|
||||
import { COMMANDS } from '../CommandsEnum.js';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const HOOK_NAME = 'prepare-commit-msg';
|
||||
const SYMLINK_URL = `.git/hooks/${HOOK_NAME}`;
|
||||
@@ -28,7 +29,7 @@ export const hookCommand = command(
|
||||
const { setUnset: mode } = argv._;
|
||||
|
||||
if (mode === 'set') {
|
||||
intro(`setting opencommit as '${HOOK_NAME}' hook`);
|
||||
intro(`setting OpenCommit as '${HOOK_NAME}' hook`);
|
||||
|
||||
if (isHookExists) {
|
||||
let realPath;
|
||||
@@ -40,7 +41,7 @@ export const hookCommand = command(
|
||||
}
|
||||
|
||||
if (realPath === HOOK_URL)
|
||||
return outro(`opencommit is already set as '${HOOK_NAME}'`);
|
||||
return outro(`OpenCommit is already set as '${HOOK_NAME}'`);
|
||||
|
||||
throw new Error(
|
||||
`Different ${HOOK_NAME} is already set. Remove it before setting opencommit as '${HOOK_NAME}' hook.`
|
||||
@@ -55,18 +56,18 @@ export const hookCommand = command(
|
||||
}
|
||||
|
||||
if (mode === 'unset') {
|
||||
intro(`unsetting opencommit as '${HOOK_NAME}' hook`);
|
||||
intro(`unsetting OpenCommit as '${HOOK_NAME}' hook`);
|
||||
|
||||
if (!isHookExists) {
|
||||
return outro(
|
||||
`opencommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove`
|
||||
`OpenCommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove`
|
||||
);
|
||||
}
|
||||
|
||||
const realpath = await fs.realpath(SYMLINK_URL);
|
||||
if (realpath !== HOOK_URL) {
|
||||
return outro(
|
||||
`opencommit wasn't previously set as '${HOOK_NAME}' hook, but different hook was, if you want to remove it — do it manually`
|
||||
`OpenCommit wasn't previously set as '${HOOK_NAME}' hook, but different hook was, if you want to remove it — do it manually`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs/promises';
|
||||
import chalk from 'chalk';
|
||||
import { intro, outro } from '@clack/prompts';
|
||||
import { getStagedGitDiff } from '../utils/git';
|
||||
import { intro, outro, spinner } from '@clack/prompts';
|
||||
import { getChangedFiles, getDiff, getStagedFiles, gitAdd } from '../utils/git';
|
||||
import { getConfig } from './config';
|
||||
import { generateCommitMessageWithChatCompletion } from '../generateCommitMessageFromGitDiff';
|
||||
|
||||
@@ -17,7 +17,17 @@ export const prepareCommitMessageHook = async () => {
|
||||
|
||||
if (commitSource) return;
|
||||
|
||||
const staged = await getStagedGitDiff();
|
||||
const stagedFiles = await getStagedFiles();
|
||||
const changedFiles = await getChangedFiles();
|
||||
|
||||
if (!stagedFiles && !changedFiles) {
|
||||
outro('No changes detected, write some code and run `oc` again');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!stagedFiles && changedFiles) await gitAdd({ files: changedFiles });
|
||||
|
||||
const staged = await getStagedFiles();
|
||||
|
||||
if (!staged) return;
|
||||
|
||||
@@ -31,11 +41,15 @@ export const prepareCommitMessageHook = async () => {
|
||||
);
|
||||
}
|
||||
|
||||
const spin = spinner();
|
||||
spin.start('Generating commit message');
|
||||
const commitMessage = await generateCommitMessageWithChatCompletion(
|
||||
staged.diff
|
||||
await getDiff({ files: staged })
|
||||
);
|
||||
|
||||
if (typeof commitMessage !== 'string') throw new Error(commitMessage.error);
|
||||
if (typeof commitMessage !== 'string') {
|
||||
spin.stop('Error');
|
||||
throw new Error(commitMessage.error);
|
||||
} else spin.stop('Done');
|
||||
|
||||
const fileContent = await fs.readFile(messageFilePath);
|
||||
|
||||
|
||||
@@ -4,54 +4,54 @@ import {
|
||||
} from 'openai';
|
||||
import { api } from './api';
|
||||
import { getConfig } from './commands/config';
|
||||
import { mergeStrings } from './utils/mergeStrings';
|
||||
import { mergeDiffs } from './utils/mergeDiffs';
|
||||
import { i18n, I18nLocals } from './i18n';
|
||||
import { tokenCount } from './utils/tokenCount';
|
||||
|
||||
const config = getConfig();
|
||||
const translation = i18n[(config?.language as I18nLocals) || 'en'];
|
||||
|
||||
const INIT_MESSAGES_PROMPT: Array<ChatCompletionRequestMessage> = [
|
||||
{
|
||||
role: ChatCompletionRequestMessageRoleEnum.System,
|
||||
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message. ${
|
||||
config?.emoji
|
||||
? 'Use Gitmoji convention to preface the commit'
|
||||
: 'Do not preface the commit with anything'
|
||||
}, use the present tense. ${
|
||||
config?.description
|
||||
? 'Add a short description of what commit is about after the commit message. Don\'t start it with "This commit", just describe the changes.'
|
||||
: "Don't add any descriptions to the commit, only commit message."
|
||||
}`
|
||||
// prettier-ignore
|
||||
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain why a change was done. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message.
|
||||
${config?.emoji? 'Use GitMoji convention to preface the commit.': 'Do not preface the commit with anything.'}
|
||||
${config?.description ? 'Add a short description of WHY the changes are done after the commit message. Don\'t start it with "This commit", just describe the changes.': "Don't add any descriptions to the commit, only commit message."}
|
||||
Use the present tense. Lines must not be longer than 74 characters. Use ${translation.localLanguage} to answer.`
|
||||
},
|
||||
{
|
||||
role: ChatCompletionRequestMessageRoleEnum.User,
|
||||
content: `diff --git a/src/server.ts b/src/server.ts
|
||||
index ad4db42..f3b18a9 100644
|
||||
--- a/src/server.ts
|
||||
+++ b/src/server.ts
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
initWinstonLogger();
|
||||
|
||||
const app = express();
|
||||
-const port = 7799;
|
||||
+const PORT = 7799;
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
@@ -34,6 +34,6 @@ app.use((_, res, next) => {
|
||||
// ROUTES
|
||||
app.use(PROTECTED_ROUTER_URL, protectedRouter);
|
||||
|
||||
-app.listen(port, () => {
|
||||
- console.log(\`Server listening on port \${port}\`);
|
||||
+app.listen(process.env.PORT || PORT, () => {
|
||||
+ console.log(\`Server listening on port \${PORT}\`);
|
||||
});`
|
||||
index ad4db42..f3b18a9 100644
|
||||
--- a/src/server.ts
|
||||
+++ b/src/server.ts
|
||||
@@ -10,7 +10,7 @@
|
||||
import {
|
||||
initWinstonLogger();
|
||||
|
||||
const app = express();
|
||||
-const port = 7799;
|
||||
+const PORT = 7799;
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
@@ -34,6 +34,6 @@
|
||||
app.use((_, res, next) => {
|
||||
// ROUTES
|
||||
app.use(PROTECTED_ROUTER_URL, protectedRouter);
|
||||
|
||||
-app.listen(port, () => {
|
||||
- console.log(\`Server listening on port \${port}\`);
|
||||
+app.listen(process.env.PORT || PORT, () => {
|
||||
+ console.log(\`Server listening on port \${PORT}\`);
|
||||
});`
|
||||
},
|
||||
{
|
||||
role: ChatCompletionRequestMessageRoleEnum.Assistant,
|
||||
// prettier-ignore
|
||||
content: `* ${config?.emoji ? '🐛 ' : ''}fix(server.ts): change port variable case from lowercase port to uppercase PORT
|
||||
* ${config?.emoji ? '✨ ' : ''}feat(server.ts): add support for process.env.PORT environment variable
|
||||
${config?.description ? 'The port variable is now named PORT, which improves consistency with the naming conventions as PORT is a constant. Support for an environment variable allows the application to be more flexible as it can now run on any available port specified via the process.env.PORT environment variable.' : ''}`
|
||||
content: `${config?.emoji ? '🐛 ' : ''}${translation.commitFix}
|
||||
${config?.emoji ? '✨ ' : ''}${translation.commitFeat}
|
||||
${config?.description ? translation.commitDescription : ''}`
|
||||
}
|
||||
];
|
||||
|
||||
@@ -79,8 +79,8 @@ interface GenerateCommitMessageError {
|
||||
}
|
||||
|
||||
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
|
||||
(msg) => msg.content
|
||||
).join('').length;
|
||||
(msg) => tokenCount(msg.content) + 4
|
||||
).reduce((a, b) => a + b, 0);
|
||||
|
||||
const MAX_REQ_TOKENS = 3900 - INIT_MESSAGES_PROMPT_LENGTH;
|
||||
|
||||
@@ -88,8 +88,11 @@ export const generateCommitMessageWithChatCompletion = async (
|
||||
diff: string
|
||||
): Promise<string | GenerateCommitMessageError> => {
|
||||
try {
|
||||
if (diff.length >= MAX_REQ_TOKENS) {
|
||||
const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(diff);
|
||||
if (tokenCount(diff) >= MAX_REQ_TOKENS) {
|
||||
const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(
|
||||
diff,
|
||||
MAX_REQ_TOKENS
|
||||
);
|
||||
|
||||
const commitMessages = await Promise.all(commitMessagePromises);
|
||||
|
||||
@@ -109,22 +112,28 @@ export const generateCommitMessageWithChatCompletion = async (
|
||||
}
|
||||
};
|
||||
|
||||
function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
||||
const lineSeparator = '\n@@';
|
||||
const [fileHeader, ...fileDiffByLines] = fileDiff.split(lineSeparator);
|
||||
function getMessagesPromisesByChangesInFile(
|
||||
fileDiff: string,
|
||||
separator: string,
|
||||
maxChangeLength: number
|
||||
) {
|
||||
const hunkHeaderSeparator = '@@ ';
|
||||
const [fileHeader, ...fileDiffByLines] = fileDiff.split(hunkHeaderSeparator);
|
||||
|
||||
// merge multiple line-diffs into 1 to save tokens
|
||||
const mergedLines = mergeStrings(
|
||||
fileDiffByLines.map((line) => lineSeparator + line),
|
||||
MAX_REQ_TOKENS
|
||||
const mergedChanges = mergeDiffs(
|
||||
fileDiffByLines.map((line) => hunkHeaderSeparator + line),
|
||||
maxChangeLength
|
||||
);
|
||||
|
||||
const lineDiffsWithHeader = mergedLines.map(
|
||||
(d) => fileHeader + lineSeparator + d
|
||||
const lineDiffsWithHeader = mergedChanges.map(
|
||||
(change) => fileHeader + change
|
||||
);
|
||||
|
||||
const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map((d) => {
|
||||
const messages = generateCommitMessageChatCompletionPrompt(separator + d);
|
||||
const commitMsgsFromFileLineDiffs = lineDiffsWithHeader.map((lineDiff) => {
|
||||
const messages = generateCommitMessageChatCompletionPrompt(
|
||||
separator + lineDiff
|
||||
);
|
||||
|
||||
return api.generateCommitMessage(messages);
|
||||
});
|
||||
@@ -132,20 +141,27 @@ function getMessagesPromisesByLines(fileDiff: string, separator: string) {
|
||||
return commitMsgsFromFileLineDiffs;
|
||||
}
|
||||
|
||||
function getCommitMsgsPromisesFromFileDiffs(diff: string) {
|
||||
export function getCommitMsgsPromisesFromFileDiffs(
|
||||
diff: string,
|
||||
maxDiffLength: number
|
||||
) {
|
||||
const separator = 'diff --git ';
|
||||
|
||||
const diffByFiles = diff.split(separator).slice(1);
|
||||
|
||||
// merge multiple files-diffs into 1 prompt to save tokens
|
||||
const mergedFilesDiffs = mergeStrings(diffByFiles, MAX_REQ_TOKENS);
|
||||
const mergedFilesDiffs = mergeDiffs(diffByFiles, maxDiffLength);
|
||||
|
||||
const commitMessagePromises = [];
|
||||
|
||||
for (const fileDiff of mergedFilesDiffs) {
|
||||
if (fileDiff.length >= MAX_REQ_TOKENS) {
|
||||
if (tokenCount(fileDiff) >= maxDiffLength) {
|
||||
// if file-diff is bigger than gpt context — split fileDiff into lineDiff
|
||||
const messagesPromises = getMessagesPromisesByLines(fileDiff, separator);
|
||||
const messagesPromises = getMessagesPromisesByChangesInFile(
|
||||
fileDiff,
|
||||
separator,
|
||||
maxDiffLength
|
||||
);
|
||||
|
||||
commitMessagePromises.push(...messagesPromises);
|
||||
} else {
|
||||
|
||||
6
src/i18n/de.json
Normal file
6
src/i18n/de.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "Deutsch",
|
||||
"commitFix": "fix(server.ts): Ändere die Groß- und Kleinschreibung der Port-Variable von Kleinbuchstaben auf Großbuchstaben PORT.",
|
||||
"commitFeat": "Funktion(server.ts): Unterstützung für die Umgebungsvariable process.env.PORT hinzufügen",
|
||||
"commitDescription": "Die Port-Variable heißt jetzt PORT, was die Konsistenz mit den Namenskonventionen verbessert, da PORT eine Konstante ist. Die Unterstützung für eine Umgebungsvariable ermöglicht es der Anwendung, flexibler zu sein, da sie jetzt auf jedem verfügbaren Port laufen kann, der über die Umgebungsvariable process.env.PORT angegeben wird."
|
||||
}
|
||||
6
src/i18n/en.json
Normal file
6
src/i18n/en.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "english",
|
||||
"commitFix": "fix(server.ts): change port variable case from lowercase port to uppercase PORT",
|
||||
"commitFeat": "feat(server.ts): add support for process.env.PORT environment variable",
|
||||
"commitDescription": "The port variable is now named PORT, which improves consistency with the naming conventions as PORT is a constant. Support for an environment variable allows the application to be more flexible as it can now run on any available port specified via the process.env.PORT environment variable."
|
||||
}
|
||||
7
src/i18n/es_ES.json
Normal file
7
src/i18n/es_ES.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"localLanguage": "spanish",
|
||||
"commitFix": "fix(server.ts): cambiar la variable port de minúsculas a mayúsculas PORT",
|
||||
"commitFeat": "feat(server.ts): añadir soporte para la variable de entorno process.env.PORT",
|
||||
"commitDescription": "La variable port ahora se llama PORT, lo que mejora la coherencia con las convenciones de nomenclatura, ya que PORT es una constante. El soporte para una variable de entorno permite que la aplicación sea más flexible, ya que ahora puede ejecutarse en cualquier puerto disponible especificado a través de la variable de entorno process.env.PORT."
|
||||
}
|
||||
|
||||
6
src/i18n/fr.json
Normal file
6
src/i18n/fr.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "française",
|
||||
"commitFix": "corriger(server.ts) : changer la casse de la variable de port de minuscules à majuscules (PORT)",
|
||||
"commitFeat": "fonctionnalité(server.ts) : ajouter la prise en charge de la variable d'environnement process.env.PORT",
|
||||
"commitDescription": "La variable de port est maintenant nommée PORT, ce qui améliore la cohérence avec les conventions de nommage car PORT est une constante. La prise en charge d'une variable d'environnement permet à l'application d'être plus flexible car elle peut maintenant s'exécuter sur n'importe quel port disponible spécifié via la variable d'environnement process.env.PORT."
|
||||
}
|
||||
70
src/i18n/index.ts
Normal file
70
src/i18n/index.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import en from '../i18n/en.json' assert { type: 'json' };
|
||||
import de from '../i18n/de.json' assert { type: 'json' };
|
||||
import fr from '../i18n/fr.json' assert { type: 'json' };
|
||||
import it from '../i18n/it.json' assert { type: 'json' };
|
||||
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' };
|
||||
import vi_VN from '../i18n/vi_VN.json' assert { type: 'json' };
|
||||
import es_ES from '../i18n/es_ES.json' assert { type: 'json' };
|
||||
import sv from '../i18n/sv.json' assert { type: 'json' };
|
||||
import ru from '../i18n/ru.json' assert { type: 'json' };
|
||||
|
||||
export enum I18nLocals {
|
||||
'en' = 'en',
|
||||
'zh_CN' = 'zh_CN',
|
||||
'zh_TW' = 'zh_TW',
|
||||
'ja' = 'ja',
|
||||
'de' = 'de',
|
||||
'fr' = 'fr',
|
||||
'it' = 'it',
|
||||
'ko' = 'ko',
|
||||
'pt_br' = 'pt_br',
|
||||
'es_ES' = 'es_ES',
|
||||
'sv' = 'sv',
|
||||
'ru' = 'ru',
|
||||
};
|
||||
|
||||
export const i18n = {
|
||||
en,
|
||||
zh_CN,
|
||||
zh_TW,
|
||||
ja,
|
||||
de,
|
||||
fr,
|
||||
it,
|
||||
ko,
|
||||
pt_br,
|
||||
vi_VN,
|
||||
es_ES,
|
||||
sv,
|
||||
ru,
|
||||
};
|
||||
|
||||
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
|
||||
zh_CN: ['zh_CN', '简体中文', '中文', '简体'],
|
||||
zh_TW: ['zh_TW', '繁體中文', '繁體'],
|
||||
ja: ['ja', 'Japanese', 'にほんご'],
|
||||
ko: ['ko', 'Korean', '한국어'],
|
||||
de: ['de', 'German' ,'Deutsch'],
|
||||
fr: ['fr', 'French', 'française'],
|
||||
it: ['it', 'Italian', 'italiano'],
|
||||
pt_br: ['pt_br', 'Portuguese', 'português'],
|
||||
vi_VN: ['vi_VN', 'Vietnamese', 'tiếng Việt'],
|
||||
en: ['en', 'English', 'english'],
|
||||
es_ES: ['es_ES', 'Spanish', 'español'],
|
||||
sv: ['sv', 'Swedish', 'Svenska'],
|
||||
ru: ['ru', 'Russian', 'русский'],
|
||||
};
|
||||
|
||||
export function getI18nLocal(value: string): string | boolean {
|
||||
for (const key in I18N_CONFIG_ALIAS) {
|
||||
const aliases = I18N_CONFIG_ALIAS[key];
|
||||
if (aliases.includes(value)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
6
src/i18n/it.json
Normal file
6
src/i18n/it.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "italiano",
|
||||
"commitFix": "fix(server.ts): cambia il caso della variabile di porta da minuscolo port a maiuscolo PORT",
|
||||
"commitFeat": "funzionalità(server.ts): aggiungi supporto per la variabile di ambiente process.env.PORT",
|
||||
"commitDescription": "La variabile di porta è ora chiamata PORT, il che migliora la coerenza con le convenzioni di denominazione in quanto PORT è una costante. Il supporto per una variabile di ambiente consente all'applicazione di essere più flessibile poiché ora può essere eseguita su qualsiasi porta disponibile specificata tramite la variabile di ambiente process.env.PORT."
|
||||
}
|
||||
6
src/i18n/ja.json
Normal file
6
src/i18n/ja.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "にほんご",
|
||||
"commitFix": "修正(server.ts): ポート変数のケースを小文字のポートから大文字のPORTに変更",
|
||||
"commitFeat": "新機能(server.ts): process.env.PORT環境変数のサポートを追加する",
|
||||
"commitDescription": "ポート変数は現在PORTという名前になっており、PORTは定数であるため命名規則に一貫性があります。環境変数のサポートにより、アプリケーションはより柔軟になり、process.env.PORT環境変数で指定された任意の利用可能なポートで実行できるようになりまし"
|
||||
}
|
||||
6
src/i18n/ko.json
Normal file
6
src/i18n/ko.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "한국어",
|
||||
"commitFix": "fix(server.ts): 포트 변수를 소문자 port에서 대문자 PORT로 변경",
|
||||
"commitFeat": "피트(server.ts): process.env.PORT 환경 변수 지원 추가",
|
||||
"commitDescription": "포트 변수는 이제 PORT로 이름이 지정되어 상수인 PORT와 일관성 있는 이름 규칙을 따릅니다. 환경 변수 지원을 통해 애플리케이션은 이제 process.env.PORT 환경 변수로 지정된 사용 가능한 모든 포트에서 실행할 수 있으므로 더 유연해졌습니다."
|
||||
}
|
||||
7
src/i18n/pt_br.json
Normal file
7
src/i18n/pt_br.json
Normal 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."
|
||||
}
|
||||
|
||||
6
src/i18n/ru.json
Normal file
6
src/i18n/ru.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "русский",
|
||||
"commitFix": "fix(server.ts): изменение регистра переменной порта с нижнего регистра port на верхний регистр PORT",
|
||||
"commitFeat": "feat(server.ts): добавлена поддержка переменной окружения process.env.PORT",
|
||||
"commitDescription": "Переменная port теперь называется PORT, что улучшает согласованность с соглашениями об именовании констант. Поддержка переменной окружения позволяет приложению быть более гибким, запускаясь на любом доступном порту, указанном с помощью переменной окружения process.env.PORT."
|
||||
}
|
||||
6
src/i18n/sv.json
Normal file
6
src/i18n/sv.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "svenska",
|
||||
"commitFix": "fixa(server.ts): ändra variabelnamnet för port från små bokstäver till stora bokstäver PORT",
|
||||
"commitFeat": "nyhet(server.ts): lägg till stöd för process.env.PORT miljövariabel",
|
||||
"commitDescription": "Variabeln som innehåller portnumret heter nu PORT vilket förbättrar konsekvensen med namngivningskonventionerna eftersom PORT är en konstant. Stöd för en miljövariabel gör att applikationen kan vara mer flexibel då den nu kan köras på vilken port som helst som specificeras via miljövariabeln process.env.PORT."
|
||||
}
|
||||
6
src/i18n/vi_VN.json
Normal file
6
src/i18n/vi_VN.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "vietnamese",
|
||||
"commitFix": "fix(server.ts): thay đổi chữ viết thường của biến port thành chữ viết hoa PORT",
|
||||
"commitFeat": "feat(server.ts): thêm hỗ trợ cho biến môi trường process.env.PORT",
|
||||
"commitDescription": "Biến port đã được đổi tên thành PORT, giúp cải thiện tính nhất quán trong việc đặt tên theo quy ước vì PORT là một hằng số. Hỗ trợ cho biến môi trường cho phép ứng dụng linh hoạt hơn khi có thể chạy trên bất kỳ cổng nào được chỉ định thông qua biến môi trường process.env.PORT."
|
||||
}
|
||||
6
src/i18n/zh_CN.json
Normal file
6
src/i18n/zh_CN.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "简体中文",
|
||||
"commitFix": "修复(server.ts):将端口变量从小写port改为大写PORT",
|
||||
"commitFeat": "功能(server.ts):添加对process.env.PORT环境变量的支持",
|
||||
"commitDescription": "现在端口变量被命名为PORT,这提高了命名约定的一致性,因为PORT是一个常量。环境变量的支持使应用程序更加灵活,因为它现在可以通过process.env.PORT环境变量在任何可用端口上运行。"
|
||||
}
|
||||
6
src/i18n/zh_TW.json
Normal file
6
src/i18n/zh_TW.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"localLanguage": "繁體中文",
|
||||
"commitFix": "修正(server.ts):將端口變數從小寫端口改為大寫PORT",
|
||||
"commitFeat": "功能(server.ts):新增對process.env.PORT環境變數的支援",
|
||||
"commitDescription": "現在port變數已更名為PORT,以符合命名慣例,因為PORT是一個常量。支援環境變數可以使應用程序更靈活,因為它現在可以通過process.env.PORT環境變數運行在任何可用端口上。"
|
||||
}
|
||||
23
src/utils/checkIsLatestVersion.ts
Normal file
23
src/utils/checkIsLatestVersion.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
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.
|
||||
`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
112
src/utils/git.ts
112
src/utils/git.ts
@@ -1,5 +1,7 @@
|
||||
import { execa } from 'execa';
|
||||
import { spinner } from '@clack/prompts';
|
||||
import { outro, spinner } from '@clack/prompts';
|
||||
import { readFileSync } from 'fs';
|
||||
import ignore, { Ignore } from 'ignore';
|
||||
|
||||
export const assertGitRepo = async () => {
|
||||
try {
|
||||
@@ -9,41 +11,91 @@ export const assertGitRepo = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const excludeBigFilesFromDiff = ['*-lock.*', '*.lock'].map(
|
||||
(file) => `:(exclude)${file}`
|
||||
);
|
||||
// const excludeBigFilesFromDiff = ['*-lock.*', '*.lock'].map(
|
||||
// (file) => `:(exclude)${file}`
|
||||
// );
|
||||
|
||||
export interface StagedDiff {
|
||||
files: string[];
|
||||
diff: string;
|
||||
}
|
||||
export const getOpenCommitIgnore = (): Ignore => {
|
||||
const ig = ignore();
|
||||
|
||||
export const getStagedGitDiff = async (
|
||||
isStageAllFlag = false
|
||||
): Promise<StagedDiff | null> => {
|
||||
if (isStageAllFlag) {
|
||||
const stageAllSpinner = spinner();
|
||||
stageAllSpinner.start('Staging all changes');
|
||||
await execa('git', ['add', '.']);
|
||||
stageAllSpinner.stop('Done');
|
||||
try {
|
||||
ig.add(readFileSync('.opencommitignore').toString().split('\n'));
|
||||
} catch (e) {}
|
||||
|
||||
return ig;
|
||||
};
|
||||
|
||||
export const getStagedFiles = async (): Promise<string[]> => {
|
||||
const { stdout: gitDir } = await execa("git", [
|
||||
"rev-parse",
|
||||
"--show-toplevel"
|
||||
]);
|
||||
|
||||
const { stdout: files } = await execa("git", [
|
||||
"diff",
|
||||
"--name-only",
|
||||
"--cached",
|
||||
"--relative",
|
||||
gitDir
|
||||
]);
|
||||
|
||||
if (!files) return [];
|
||||
|
||||
const filesList = files.split('\n');
|
||||
|
||||
const ig = getOpenCommitIgnore();
|
||||
const allowedFiles = filesList.filter((file) => !ig.ignores(file));
|
||||
|
||||
if (!allowedFiles) return [];
|
||||
|
||||
return allowedFiles.sort();
|
||||
};
|
||||
|
||||
export const getChangedFiles = async (): Promise<string[]> => {
|
||||
const { stdout: modified } = await execa('git', ['ls-files', '--modified']);
|
||||
const { stdout: others } = await execa('git', [
|
||||
'ls-files',
|
||||
'--others',
|
||||
'--exclude-standard'
|
||||
]);
|
||||
|
||||
const files = [...modified.split('\n'), ...others.split('\n')].filter(
|
||||
(file) => !!file
|
||||
);
|
||||
|
||||
return files.sort();
|
||||
};
|
||||
|
||||
export const gitAdd = async ({ files }: { files: string[] }) => {
|
||||
const gitAddSpinner = spinner();
|
||||
gitAddSpinner.start('Adding files to commit');
|
||||
await execa('git', ['add', ...files]);
|
||||
gitAddSpinner.stop('Done');
|
||||
};
|
||||
|
||||
export const getDiff = async ({ files }: { files: string[] }) => {
|
||||
const lockFiles = files.filter(
|
||||
(file) => file.includes('.lock') || file.includes('-lock.')
|
||||
);
|
||||
|
||||
if (lockFiles.length) {
|
||||
outro(
|
||||
`Some files are '.lock' files which are excluded by default from 'git diff'. No commit messages are generated for this files:\n${lockFiles.join(
|
||||
'\n'
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
const diffStaged = ['diff', '--staged'];
|
||||
const { stdout: files } = await execa('git', [
|
||||
...diffStaged,
|
||||
'--name-only',
|
||||
...excludeBigFilesFromDiff
|
||||
]);
|
||||
|
||||
if (!files) return null;
|
||||
const filesWithoutLocks = files.filter(
|
||||
(file) => !file.includes('.lock') && !file.includes('-lock.')
|
||||
);
|
||||
|
||||
const { stdout: diff } = await execa('git', [
|
||||
...diffStaged,
|
||||
...excludeBigFilesFromDiff
|
||||
'diff',
|
||||
'--staged',
|
||||
'--',
|
||||
...filesWithoutLocks
|
||||
]);
|
||||
|
||||
return {
|
||||
files: files.split('\n').sort(),
|
||||
diff
|
||||
};
|
||||
return diff;
|
||||
};
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
export function mergeStrings(arr: string[], maxStringLength: number): string[] {
|
||||
import { tokenCount } from './tokenCount';
|
||||
export function mergeDiffs(arr: string[], maxStringLength: number): string[] {
|
||||
const mergedArr: string[] = [];
|
||||
let currentItem: string = arr[0];
|
||||
for (const item of arr.slice(1)) {
|
||||
if (currentItem.length + item.length <= maxStringLength) {
|
||||
if (tokenCount(currentItem + item) <= maxStringLength) {
|
||||
currentItem += item;
|
||||
} else {
|
||||
mergedArr.push(currentItem);
|
||||
currentItem = item;
|
||||
}
|
||||
}
|
||||
|
||||
mergedArr.push(currentItem);
|
||||
|
||||
return mergedArr;
|
||||
}
|
||||
14
src/utils/tokenCount.ts
Normal file
14
src/utils/tokenCount.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// import { Tiktoken } from '@dqbd/tiktoken/lite';
|
||||
// import cl100k_base from '@dqbd/tiktoken/encoders/cl100k_base.json' assert { type: 'json' };
|
||||
|
||||
export function tokenCount(content: string): number {
|
||||
// const encoding = new Tiktoken(
|
||||
// cl100k_base.bpe_ranks,
|
||||
// cl100k_base.special_tokens,
|
||||
// cl100k_base.pat_str
|
||||
// );
|
||||
// const tokens = encoding.encode(content);
|
||||
// encoding.free();
|
||||
|
||||
return content.length / 2.7;
|
||||
}
|
||||
12
src/utils/trytm.ts
Normal file
12
src/utils/trytm.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const trytm = async <T>(
|
||||
promise: Promise<T>
|
||||
): Promise<[T, null] | [null, Error]> => {
|
||||
try {
|
||||
const data = await promise;
|
||||
return [data, null];
|
||||
} catch (throwable) {
|
||||
if (throwable instanceof Error) return [null, throwable];
|
||||
|
||||
throw throwable;
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"target": "ESNext",
|
||||
"lib": ["ES5", "ES6"],
|
||||
|
||||
"module": "ESNext",
|
||||
|
||||
Reference in New Issue
Block a user