Compare commits

...

2 Commits

Author SHA1 Message Date
di-sukharev
50b44ec6b1 0.0.21 2023-03-06 22:37:09 +08:00
di-sukharev
5762c35a7f * 🎨 style(README.md): update OpenCommit logo filename
* 📝 docs(README.md): add examples section
The OpenCommit logo filename has been updated to match the new filename. The README.md file now includes an examples section that provides a link to the commits that demonstrate how OpenCommit works.

* 📝 chore(TODO.md): update TODO list
* 🐛 fix(TODO.md): add missing checkbox for a TODO item
The TODO list has been updated with new items. The esbuild bundler will be properly configured to make the bundle smaller. The code will be updated with // TODOs to make it easier to identify areas that need improvement. Small files will be batched in one request to improve performance. Tests will be added to ensure the code is working as expected. Finally, a hook will be made to work.

* ⬆️ chore(package.json): update version to 0.0.20
* 🐛 fix(package.json): change cli file extension from .mjs to .cjs
* 🌐 chore(package.json): add repository URL
* 🚀 chore(package.json): add deploy script
The version number has been updated to 0.0.20. The cli file extension has been changed from .mjs to .cjs to improve compatibility with Node.js. The repository URL has been added to the package.json file. A deploy script has been added to build, version, and publish the package to npm.

* 🎨 style(api.ts): remove unused import statement
* 🐛 fix(api.ts): remove setConfig function call
* 🚧 chore(api.ts): add comment to explain apiKey variable initialization
* 🚧 chore(api.ts): comment out code block that prompts user for OPENAI_API_KEY
The unused import statement for `text` function from `@clack/prompts` has been removed. The `setConfig` function call has been removed as it is not needed and was causing an error. A comment has been added to explain the initialization of the `apiKey` variable. The code block that prompts the user for `OPENAI_API_KEY` has been commented out as it is not needed and was causing an error.

* 🐛 fix(cli.ts): remove assert statement from packageJSON import
The assert statement is not necessary for importing the package.json file. Removing it improves the readability of the code.

* 🐛 fix(githook.ts): use __filename instead of fileURLToPath(new URL('cli.mjs', import.meta.url))
*  feat(githook.ts): add error handling for fs.realpath call
The fileURLToPath function is not necessary as __filename already provides the path to the current file. The error handling for the fs.realpath call is added to prevent the program from crashing if the symlink does not exist.

* 🐛 fix(generateCommitMessageFromGitDiff.ts): fix length calculation for prompt messages
* 💄 style(generateCommitMessageFromGitDiff.ts): add whitespace to improve readability
The length calculation for the prompt messages was incorrect, causing the maximum request token limit to be exceeded. This has been fixed by correctly calculating the length of the prompt messages. Additionally, whitespace has been added to improve the readability of the code.

* 🐛 fix(generateCommitMessageWithChatCompletion): fix commit message length check
* 🚀 chore(generateCommitMessageWithChatCompletion): add TODO for edge case handling
The commit message length check has been fixed to include the length of the initial messages prompt. This ensures that the commit message length is correctly calculated and prevents the commit message from exceeding the maximum required tokens. A TODO has been added to handle an edge case.

* 🐛 fix(tsconfig.json): remove commented out rootDir property
* 🚀 chore(tsconfig.json): update compiler options
The rootDir property was commented out and not being used, so it was removed. The compiler options were updated to target ES2020, use CommonJS module, and allow importing of JSON files. The outDir property was set to "./out". The strict option was enabled along with noUnusedLocals and noUnusedParameters. The skipLibCheck option was set to true.
2023-03-06 22:36:52 +08:00
9 changed files with 78 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
<div align="center">
<div>
<img src=".github/OC-grad.svg" alt="OpenCommit logo"/>
<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>
@@ -11,6 +11,10 @@
---
## Examples
Look into [the commits](https://github.com/di-sukharev/opencommit/commit/4795a695800686c42e7c72fca7569103d21cd510) to see how OpenCommit works. Emoji and long commit description text is configurable.
## Setup
> The minimum supported version of Node.js is the latest v14. Check your Node.js version with `node --version`.

View File

@@ -1,4 +1,8 @@
# TODOs
- [] [build for both mjs and cjs](https://snyk.io/blog/best-practices-create-modern-npm-package/)
- []
- [] make bundle smaller by properly configuring esbuild
- [] do // TODOs in the code
- [] batch small files in one request
- [] add tests
- [] make hook work

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "open-commit",
"version": "0.0.1",
"version": "0.0.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "open-commit",
"version": "0.0.1",
"version": "0.0.21",
"license": "ISC",
"dependencies": {
"@clack/prompts": "^0.6.1",

View File

@@ -1,6 +1,6 @@
{
"name": "opencommit",
"version": "0.0.1",
"version": "0.0.21",
"description": "AI generates conventional commits with mind-blowing accuracy.",
"keywords": [
"git",
@@ -12,11 +12,14 @@
],
"main": "cli.js",
"bin": {
"opencommit": "./out/cli.mjs",
"oc": "./out/cli.mjs"
"opencommit": "./out/cli.cjs",
"oc": "./out/cli.cjs"
},
"repository": {
"url": "https://github.com/di-sukharev/opencommit"
},
"type": "module",
"author": "",
"author": "https://github.com/di-sukharev",
"license": "ISC",
"files": [
"out/**/*"
@@ -31,9 +34,10 @@
},
"scripts": {
"watch": "npm run -S build -- --sourcemap --watch",
"start": "node ./out/cli.mjs",
"start": "node ./out/cli.cjs",
"dev": "ts-node ./src/cli.ts",
"build": "rimraf out && esbuild ./src/cli.ts --bundle --outfile=out/cli.mjs --format=esm --platform=node",
"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"
},
"devDependencies": {

View File

@@ -1,4 +1,4 @@
import { intro, outro, text } from '@clack/prompts';
import { intro, outro } from '@clack/prompts';
import {
ChatCompletionRequestMessage,
ChatCompletionResponseMessage,
@@ -6,7 +6,7 @@ import {
OpenAIApi
} from 'openai';
import { CONFIG_KEYS, getConfig, setConfig } from './commands/config';
import { getConfig } from './commands/config';
const config = getConfig();
@@ -14,15 +14,26 @@ let apiKey = config?.OPENAI_API_KEY;
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');
outro(
'OPENAI_API_KEY is not set, please run `oc config set OPENAI_API_KEY=<your token>`'
);
outro(
'For help Look into README https://github.com/di-sukharev/opencommit#setup'
);
}
// 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

2
src/cli.ts Normal file → Executable file
View File

@@ -1,7 +1,7 @@
#!/usr/bin/env node
import { cli } from 'cleye';
import packageJSON from '../package.json' assert { type: 'json' };
import packageJSON from '../package.json';
import { configCommand } from './commands/config';
import { hookCommand, isHookCalled } from './commands/githook.js';

View File

@@ -20,7 +20,7 @@ export const hookCommand = command(
parameters: ['<set/unset>']
},
async (argv) => {
const HOOK_PATH = fileURLToPath(new URL('cli.mjs', import.meta.url));
const HOOK_URL = __filename;
try {
await assertGitRepo();
@@ -29,10 +29,17 @@ export const hookCommand = command(
if (mode === 'set') {
intro(`setting opencommit as '${HOOK_NAME}' hook`);
if (isHookExists) {
const realPath = await fs.realpath(SYMLINK_URL);
if (realPath === HOOK_PATH)
if (isHookExists) {
let realPath;
try {
realPath = await fs.realpath(SYMLINK_URL);
} catch (error) {
outro(error as string);
realPath = null;
}
if (realPath === HOOK_URL)
return outro(`opencommit is already set as '${HOOK_NAME}'`);
throw new Error(
@@ -41,7 +48,7 @@ export const hookCommand = command(
}
await fs.mkdir(path.dirname(SYMLINK_URL), { recursive: true });
await fs.symlink(HOOK_PATH, SYMLINK_URL, 'file');
await fs.symlink(HOOK_URL, SYMLINK_URL, 'file');
await fs.chmod(SYMLINK_URL, 0o755);
return outro(`${chalk.green('✔')} Hook set`);
@@ -49,6 +56,7 @@ export const hookCommand = command(
if (mode === 'unset') {
intro(`unsetting opencommit as '${HOOK_NAME}' hook`);
if (!isHookExists) {
return outro(
`opencommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove`
@@ -56,7 +64,7 @@ export const hookCommand = command(
}
const realpath = await fs.realpath(SYMLINK_URL);
if (realpath !== HOOK_PATH) {
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`
);

View File

@@ -77,13 +77,17 @@ interface GenerateCommitMessageError {
error: GenerateCommitMessageErrorEnum;
}
const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
(msg) => msg.content
).join('').length;
export const generateCommitMessageWithChatCompletion = async (
diff: string
): Promise<string | GenerateCommitMessageError> => {
try {
const MAX_REQ_TOKENS = 3900;
if (diff.length >= MAX_REQ_TOKENS) {
if (INIT_MESSAGES_PROMPT_LENGTH + diff.length >= MAX_REQ_TOKENS) {
const separator = 'diff --git ';
const diffByFiles = diff.split(separator).slice(1);
@@ -91,11 +95,13 @@ export const generateCommitMessageWithChatCompletion = async (
const commitMessages = [];
for (const diffFile of diffByFiles) {
if (diffFile.length >= MAX_REQ_TOKENS) continue;
if (INIT_MESSAGES_PROMPT_LENGTH + diffFile.length >= MAX_REQ_TOKENS)
continue;
const messages = generateCommitMessageChatCompletionPrompt(
separator + diffFile
);
const commitMessage = await api.generateCommitMessage(messages);
// TODO: handle this edge case

View File

@@ -1,36 +1,25 @@
{
"compilerOptions": {
/* Projects */
"target": "ES2020",
"lib": ["ES5"],
/* Language and Environment */
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"ESNext"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
"module": "CommonJS",
// "rootDir": "./src",
"moduleResolution": "node",
"resolveJsonModule": true,
/* Modules */
"module": "ESNext" /* Specify what module code is generated. */,
// "rootDir": "./src" /* Specify the root folder within your source files. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
"resolveJsonModule": true /* Enable importing .json files. */,
"allowJs": true,
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */,
"outDir": "./out",
/* Emit */
"outDir": "./out" /* Specify an output folder for all emitted files. */,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
/* Interop Constraints */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"noUnusedLocals": true /* Enable error reporting when local variables aren't read. */,
"noUnusedParameters": true /* Raise an error when a function parameter isn't read. */,
/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipLibCheck": true
},
"exclude": ["node_modules"],
"ts-node": {