@gilbert_oliveira/commit-wizard 1.0.19 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,58 +1,80 @@
1
1
  # Commit Wizard
2
2
 
3
- O **Commit Wizard** é uma ferramenta automatizada para a geração de mensagens de commit com base na convenção de **Conventional Commits**. Ele ajuda a garantir que suas mensagens de commit sigam um padrão consistente e facilite a comunicação de mudanças no código.
3
+ Gere mensagens de commit convencionais automaticamente com base nas alterações no código usando a API da OpenAI.
4
4
 
5
- ## Funcionalidades
5
+ ## ✨ Visão Geral
6
6
 
7
- - Geração automática de mensagens de commit usando o **Cody**.
8
- - Garantia de que a mensagem de commit siga o padrão **Conventional Commits**.
9
- - Oferece a opção de editar ou confirmar a mensagem gerada.
10
- - Verificação se o repositório Git está inicializado e se o usuário está autenticado no **Cody**.
11
- - Integração com a ferramenta **Cody** para sugestão de mensagens de commit baseadas no diff de código.
7
+ Este projeto é uma ferramenta de linha de comando (CLI) chamada `commit-wizard`, que utiliza a API da OpenAI para gerar mensagens de commit com base no `diff` dos arquivos que estão em *staged* no Git.
12
8
 
13
- ## Instalação
9
+ ## 🚀 Instalação
14
10
 
15
- ### Requisitos
16
-
17
- - **Node.js**: A ferramenta requer o **Node.js** para ser executada.
18
- - **Cody**: A ferramenta usa o **Cody** da Sourcegraph para gerar as mensagens de commit.
19
-
20
- ### Instalação Global
11
+ ```bash
12
+ npm install -g commit-wizard
13
+ ```
21
14
 
22
- Para instalar o Commit Wizard globalmente, execute o seguinte comando:
15
+ Ou, se estiver usando localmente:
23
16
 
24
17
  ```bash
25
- npm install -g @gilbert_oliveira/commit-wizard
18
+ npm install
26
19
  ```
27
20
 
28
- ### Instalação Local
21
+ ## ⚙️ Configuração
29
22
 
30
- Para instalar o Commit Wizard localmente, execute o seguinte comando:
23
+ Antes de usar, você precisa definir a variável de ambiente com sua chave da OpenAI:
31
24
 
32
25
  ```bash
33
- npm install @gilbert_oliveira/commit-wizard
26
+ export OPENAI_API_KEY=sk-...
34
27
  ```
35
28
 
36
- ## Uso
29
+ Você pode adicionar isso no seu `.bashrc`, `.zshrc` ou arquivo de ambiente equivalente.
37
30
 
38
- Para usar o Commit Wizard, execute o seguinte comando no terminal:
31
+ ## 🧠 Como Funciona
32
+
33
+ 1. O script lê os arquivos que estão em *staged* (`git diff --cached`).
34
+ 2. Envia esse diff para a API da OpenAI.
35
+ 3. Recebe uma sugestão de mensagem de commit no formato convencional (`feat:`, `fix:`, etc).
36
+ 4. Exibe a mensagem para revisão.
37
+
38
+ ## 📝 Exemplo de Uso
39
39
 
40
40
  ```bash
41
- commit-wizard
41
+ npx commit-wizard
42
42
  ```
43
43
 
44
- O Commit Wizard irá gerar uma mensagem de commit com base nas mudanças no repositório Git e na convenção de **Conventional Commits**. Você pode editar a mensagem gerada ou confirmá-la.
44
+ Resultado esperado:
45
45
 
46
- ## Contribuição
46
+ ```
47
+ Sugestão de commit:
48
+ feat: adiciona verificação automática para arquivos staged usando GPT-4
49
+ ```
47
50
 
48
- Se você quiser contribuir com o Commit Wizard, siga as instruções abaixo:
51
+ ## 🛠 Tecnologias Utilizadas
49
52
 
50
- 1. Faça um fork do repositório.
51
- 2. Crie uma nova branch com a sua feature: `git checkout -b my-feature`
52
- 3. Faça o commit das suas alterações: `git commit -m 'feat: My new feature'`
53
- 4. Faça o push para a sua branch: `git push origin my-feature`
54
- 5. Abra um Pull Request
53
+ - Node.js
54
+ - TypeScript
55
+ - OpenAI API
56
+ - Commander (CLI)
57
+ - Dotenv
55
58
 
56
- ## Licença
59
+ ## 🧪 Scripts Disponíveis
60
+
61
+ - `npm run build`: compila o TypeScript para JavaScript.
62
+ - `npm start`: executa o CLI direto pelo TypeScript (com ts-node).
63
+ - `npm run dev`: roda em modo de desenvolvimento com `ts-node-dev`.
64
+
65
+ ## ✅ Commit Convencional
66
+
67
+ Este projeto segue o padrão de commit convencional, como:
68
+
69
+ - `feat:` para novas funcionalidades
70
+ - `fix:` para correções de bugs
71
+ - `docs:` para documentação
72
+ - `refactor:` para mudanças internas no código
73
+
74
+ ## 📄 Licença
57
75
 
58
76
  Este projeto está licenciado sob a licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes.
77
+
78
+ ---
79
+
80
+ Feito com 💜 por Gilbert de Oliveira Santos
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@gilbert_oliveira/commit-wizard",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "description": "O **Commit Wizard** é uma ferramenta automatizada para geração de mensagens de commit com base na convenção de **Conventional Commits**. Ele ajuda a garantir que suas mensagens de commit sigam um padrão consistente e facilite a comunicação de mudanças no código.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "commit-wizard": "dist/index.js"
8
+ "commit-wizard": "ts-node src/index.ts"
9
9
  },
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
13
  "scripts": {
14
- "start": "node dist/index.js",
15
- "dev": "tsc --watch",
16
- "build": "tsc"
14
+ "start": "ts-node src/index.ts",
15
+ "build": "tsc",
16
+ "dev": "tsc --watch"
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
package/dist/index.d.ts DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env ts-node
2
- /**
3
- * Realiza a chamada à API do OpenAI.
4
- * @param prompt Texto que será enviado como mensagem do usuário.
5
- * @param mode Define o contexto: 'commit' para gerar mensagem de commit ou outro valor para resumo.
6
- * @returns Resposta da API (string com a mensagem ou o resumo).
7
- */
8
- export declare function callOpenAI(prompt: string, mode?: string): Promise<string>;
9
- /**
10
- * Divide o diff em chunks menores com base na contagem de tokens.
11
- * Utiliza o gpt-tokenizer para garantir que cada chunk não exceda o limite de tokens.
12
- * @param diff O diff completo em formato de string.
13
- * @param maxTokens Quantidade máxima de tokens permitida para cada chunk (padrão: 1000 tokens).
14
- * @returns Array de strings, cada uma representando um chunk.
15
- */
16
- export declare function chunkDiff(diff: string, maxTokens?: number): string[];
package/dist/index.js DELETED
@@ -1,237 +0,0 @@
1
- #!/usr/bin/env ts-node
2
- import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import os from 'os';
5
- import path from 'path';
6
- import fs from 'fs';
7
- import { execSync } from 'child_process';
8
- import ora from 'ora';
9
- import { encode, decode } from 'gpt-tokenizer';
10
- const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
11
- if (!OPENAI_API_KEY) {
12
- throw new Error("Chave da API do OpenAI não configurada. Defina a variável de ambiente OPENAI_API_KEY.");
13
- }
14
- /**
15
- * Realiza a chamada à API do OpenAI.
16
- * @param prompt Texto que será enviado como mensagem do usuário.
17
- * @param mode Define o contexto: 'commit' para gerar mensagem de commit ou outro valor para resumo.
18
- * @returns Resposta da API (string com a mensagem ou o resumo).
19
- */
20
- export async function callOpenAI(prompt, mode = 'commit') {
21
- const url = 'https://api.openai.com/v1/chat/completions';
22
- // Escolhe o prompt inicial de acordo com o modo.
23
- const systemPrompt = mode === 'commit'
24
- ? "Você é um assistente que gera mensagens de commit seguindo a convenção do Conventional Commits."
25
- : "Você é um assistente que resume alterações de código de forma breve, usando linguagem imperativa em português.";
26
- const body = {
27
- model: "gpt-4-turbo",
28
- messages: [
29
- { role: "system", content: systemPrompt },
30
- { role: "user", content: prompt }
31
- ],
32
- temperature: 0.2
33
- };
34
- const response = await fetch(url, {
35
- method: "POST",
36
- headers: {
37
- "Content-Type": "application/json",
38
- "Authorization": `Bearer ${OPENAI_API_KEY}`
39
- },
40
- body: JSON.stringify(body)
41
- });
42
- if (!response.ok) {
43
- throw new Error(`Erro na API OpenAI: ${response.statusText}`);
44
- }
45
- const data = await response.json();
46
- // Retorna a resposta do primeiro "choice".
47
- return data.choices[0].message.content.trim();
48
- }
49
- /**
50
- * Divide o diff em chunks menores com base na contagem de tokens.
51
- * Utiliza o gpt-tokenizer para garantir que cada chunk não exceda o limite de tokens.
52
- * @param diff O diff completo em formato de string.
53
- * @param maxTokens Quantidade máxima de tokens permitida para cada chunk (padrão: 1000 tokens).
54
- * @returns Array de strings, cada uma representando um chunk.
55
- */
56
- export function chunkDiff(diff, maxTokens = 1000) {
57
- // Codifica o diff para obter o array de tokens.
58
- const tokens = encode(diff);
59
- // Se o diff couber em um único chunk, retorna-o diretamente.
60
- if (tokens.length <= maxTokens) {
61
- return [diff];
62
- }
63
- const chunks = [];
64
- // Percorre os tokens de forma que cada chunk contenha no máximo maxTokens tokens.
65
- for (let i = 0; i < tokens.length; i += maxTokens) {
66
- const chunkTokens = tokens.slice(i, i + maxTokens);
67
- const chunkText = decode(chunkTokens);
68
- chunks.push(chunkText);
69
- }
70
- return chunks;
71
- }
72
- // Pré-prompt para a geração da mensagem de commit conforme as convenções
73
- const COMMIT_PROMPT = `
74
- Por favor, escreva a mensagem de commit para este diff usando a convenção de Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0/.
75
- A mensagem deve começar com um tipo de commit, como:
76
- feat: para novas funcionalidades
77
- fix: para correções de bugs
78
- chore: para alterações que não afetam a funcionalidade
79
- docs: para mudanças na documentação
80
- style: para alterações no estilo do código (como formatação)
81
- refactor: para alterações no código que não alteram a funcionalidade
82
- perf: para melhorias de desempenho
83
- test: para alterações nos testes
84
- ci: para mudanças no pipeline de integração contínua
85
-
86
- Exemplo:
87
- feat(auth): adicionar suporte ao login com Google
88
-
89
- Caso o commit seja uma alteração significativa (breaking change), inclua um título com \`!\` após o tipo de commit e adicione a explicação em \`BREAKING CHANGE\`:
90
- feat!(auth): reestruturar fluxo de login
91
- BREAKING CHANGE: A API de login foi alterada e não é compatível com versões anteriores.
92
-
93
- Gere também uma descrição mais detalhada do commit, se necessário.
94
-
95
- Use sempre linguagem imperativa e primeira pessoa do singular, como:
96
- - "adiciona recurso"
97
- - "corrige bug"
98
- - "remove arquivo"
99
-
100
- Lembre-se: os textos fora do Conventional Commit devem ser em português.
101
- `;
102
- async function main() {
103
- // Verifica se o diretório é um repositório git.
104
- try {
105
- execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
106
- }
107
- catch {
108
- console.error(chalk.red('❌ Este diretório não é um repositório git.'));
109
- process.exit(1);
110
- }
111
- // Verifica se há alterações staged, desconsiderando arquivos .lock
112
- let stagedFiles;
113
- try {
114
- stagedFiles = execSync('git diff --cached --name-only -- . ":(exclude)*.lock"', { encoding: 'utf8' }).toString().trim();
115
- if (!stagedFiles) {
116
- console.log(chalk.yellow('⚠️ Não há alterações staged para o commit.'));
117
- process.exit(0);
118
- }
119
- }
120
- catch (error) {
121
- console.error(chalk.red('❌ Erro ao verificar alterações staged:'), error);
122
- process.exit(1);
123
- }
124
- // Obtém o diff completo das alterações staged, ignorando arquivos .lock
125
- let diff;
126
- try {
127
- diff = execSync('git diff --cached -- . ":(exclude)*.lock"', { encoding: 'utf8' });
128
- }
129
- catch (error) {
130
- console.error(chalk.red('❌ Erro ao obter o diff:'), error);
131
- process.exit(1);
132
- }
133
- // Divide o diff em chunks com base no número máximo de tokens.
134
- const MAX_TOKENS = 1000;
135
- const chunks = chunkDiff(diff, MAX_TOKENS);
136
- let inputForCommit;
137
- if (chunks.length === 1) {
138
- inputForCommit = chunks[0];
139
- }
140
- else {
141
- // Se houver vários chunks, gera um resumo para todos eles utilizando um único spinner.
142
- const partialSummaries = [];
143
- const chunkSummaryPrefix = "A partir do diff abaixo, extraia um resumo breve das alterações (use linguagem imperativa e em português):";
144
- // Inicia um spinner único para todo o processo
145
- const spinnerSummary = ora("Gerando resumo do commit.").start();
146
- try {
147
- for (const chunk of chunks) {
148
- const prompt = `${chunkSummaryPrefix}\n\n${chunk}`;
149
- const summary = await callOpenAI(prompt, 'resumo');
150
- partialSummaries.push(summary);
151
- }
152
- spinnerSummary.succeed("Resumo do commit gerado.");
153
- }
154
- catch (error) {
155
- spinnerSummary.fail("Erro ao gerar resumo do commit.");
156
- console.error(chalk.red('❌ Erro ao gerar resumo para o commit:'), error);
157
- process.exit(1);
158
- }
159
- inputForCommit = partialSummaries.join("\n\n");
160
- }
161
- // Gera a mensagem de commit com o pré-prompt e o diff (ou seus resumos).
162
- const finalPrompt = `${COMMIT_PROMPT}\n\nDiff:\n\n${inputForCommit}`;
163
- const spinnerCommit = ora('Gerando mensagem de commit com base no diff...').start();
164
- let generatedMessage;
165
- try {
166
- generatedMessage = await callOpenAI(finalPrompt, 'commit');
167
- // Remove os delimitadores de bloco de código (```)
168
- generatedMessage = generatedMessage.replace(/```/g, '').trim();
169
- spinnerCommit.succeed('Mensagem de commit gerada com sucesso.');
170
- }
171
- catch (error) {
172
- spinnerCommit.fail('Erro ao gerar a mensagem de commit.');
173
- console.error(chalk.red('❌ Erro ao gerar a mensagem de commit:'), error);
174
- process.exit(1);
175
- }
176
- console.log(chalk.greenBright('\n✨ Mensagem de commit gerada automaticamente:'));
177
- console.log(chalk.yellowBright(generatedMessage));
178
- // Pergunta ao usuário se deseja confirmar, editar ou cancelar o commit.
179
- const promptModule = inquirer.createPromptModule();
180
- const { action } = await promptModule([
181
- {
182
- type: 'list',
183
- name: 'action',
184
- message: chalk.blue.bold('O que deseja fazer com a mensagem de commit gerada?'),
185
- choices: [
186
- { name: '📌 Confirmar e commitar', value: 'confirm' },
187
- { name: '📝 Editar a mensagem antes de commitar', value: 'edit' },
188
- { name: '🚫 Cancelar o commit', value: 'cancel' },
189
- ],
190
- },
191
- ]);
192
- // Cria um arquivo temporário para armazenar a mensagem (para edição se necessário).
193
- const tempFilePath = path.join(os.tmpdir(), 'COMMIT_EDITMSG');
194
- fs.writeFileSync(tempFilePath, generatedMessage);
195
- if (action === 'edit') {
196
- console.log(chalk.cyan('📝 Abrindo editor para edição da mensagem...'));
197
- const editor = process.env.EDITOR || 'nano';
198
- try {
199
- execSync(`${editor} ${tempFilePath}`, { stdio: 'inherit' });
200
- }
201
- catch (error) {
202
- console.error(chalk.red('❌ Erro ao abrir o editor:'), error);
203
- process.exit(1);
204
- }
205
- }
206
- else if (action === 'cancel') {
207
- console.log(chalk.yellow('🚫 Commit cancelado pelo usuário.'));
208
- fs.unlinkSync(tempFilePath);
209
- process.exit(0);
210
- }
211
- // Lê a mensagem final (após eventual edição).
212
- const finalMessage = fs.readFileSync(tempFilePath, 'utf8').trim();
213
- if (!finalMessage) {
214
- console.error(chalk.red('❌ Nenhuma mensagem inserida, commit cancelado.'));
215
- fs.unlinkSync(tempFilePath);
216
- process.exit(1);
217
- }
218
- // Captura quaisquer argumentos adicionais passados para o comando.
219
- const gitArgs = process.argv.slice(2).join(' ');
220
- console.log(chalk.blue('🔍 Argumentos adicionais para o commit:'), gitArgs);
221
- // Realiza o commit com a mensagem final.
222
- try {
223
- execSync(`git commit -F ${tempFilePath} ${gitArgs}`, { stdio: 'inherit' });
224
- console.log(chalk.green.bold('✅ Commit realizado com sucesso.'));
225
- }
226
- catch (error) {
227
- console.error(chalk.red('❌ Erro ao realizar o commit:'), error);
228
- }
229
- finally {
230
- fs.unlinkSync(tempFilePath);
231
- }
232
- }
233
- main().catch((err) => {
234
- console.error(chalk.red('❌ Erro durante o commit:'), err);
235
- process.exit(1);
236
- });
237
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}