Skip to content

Commit 96c293c

Browse files
committed
refactor: Update version in package.json, improve logging and error handling.
1 parent 9e50e68 commit 96c293c

File tree

9 files changed

+143
-62
lines changed

9 files changed

+143
-62
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "commitfy",
3-
"version": "0.0.10",
3+
"version": "0.0.11",
44
"main": "lib/index.js",
55
"repository": "https://github.com/ribeirogab/commitfy.git",
66
"author": "ribeirogab <[email protected]>",

src/commands/generate-commit.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
type AppUtils,
23
type EnvUtils,
34
type InputUtils,
45
InputUtilsCustomChoiceEnum,
@@ -15,21 +16,23 @@ export class GenerateCommit {
1516
private readonly envUtils: EnvUtils,
1617
private readonly processUtils: ProcessUtils,
1718
private readonly inputUtils: InputUtils,
19+
private readonly appUtils: AppUtils,
1820
) {
1921
this.provider = this.providers[this.envUtils.get().PROVIDER];
2022
}
2123

2224
public async execute(): Promise<void> {
2325
if (!this.provider) {
24-
console.error(
25-
'commitfy: provider not found\nRun `commitfy setup` to set up the provider.',
26-
);
26+
this.appUtils.logger.error('AI provider not set.');
27+
console.log("Run 'commitfy setup' to set up the provider.");
28+
29+
process.exit(0);
2730
}
2831

2932
const diff = await this.processUtils.exec('git diff --cached');
3033

3134
if (!diff) {
32-
console.error('No changes to commit');
35+
console.error(`${this.appUtils.name}: no changes to commit.`);
3336

3437
process.exit(0);
3538
}

src/commands/help.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@ export class Help {
33
const commands = [
44
{
55
command: 'cfy',
6-
description: 'Create and run a new container from an image',
6+
description: 'Create commit messages and show on the terminal',
77
},
88
{
99
command: 'cfy setup',
1010
description:
11-
'Responsible for initial setup and updating configurations',
11+
'Responsible for initial setup and updating configurations.',
1212
},
1313
{
1414
command: 'cfy --help',
15-
description: 'List all commands and their usage',
15+
description:
16+
'List all commands and information of files and providers.',
1617
},
17-
{ command: 'cfy --version', description: 'Output the current version' },
18+
{ command: 'cfy --version', description: 'Output the current version.' },
1819
];
1920

2021
const directoriesAndFiles = [
21-
{ path: '~/.commitfy', description: 'Directory for configs' },
22+
{ path: '~/.commitfy', description: 'Directory for all configs.' },
2223
{
2324
path: '~/.commitfy/.env',
24-
description: 'File for environment variables',
25+
description: 'File for environment variables.',
2526
},
2627
];
2728

@@ -36,5 +37,12 @@ export class Help {
3637
directoriesAndFiles.forEach(({ path, description }) => {
3738
console.log(` ${path.padEnd(25)} ${description}`);
3839
});
40+
41+
console.log('\nProviders:');
42+
console.log(' OpenAI:');
43+
44+
console.log(
45+
' - API key required. Get it from https://platform.openai.com/account/api-keys.',
46+
);
3947
}
4048
}

src/container.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type { Providers } from './interfaces';
33
import { OpenAIProvider } from './providers';
44
import { AppUtils, EnvUtils, InputUtils, ProcessUtils } from './utils';
55

6-
const processUtils = new ProcessUtils();
76
const inputUtils = new InputUtils();
87
const appUtils = new AppUtils();
8+
const processUtils = new ProcessUtils(appUtils);
99
const envUtils = new EnvUtils(appUtils);
1010

1111
const providers: Providers = {
12-
openai: new OpenAIProvider(envUtils, inputUtils),
12+
openai: new OpenAIProvider(envUtils, inputUtils, appUtils),
1313
};
1414

1515
const setup = new Setup(providers, inputUtils);
@@ -23,6 +23,7 @@ const generateCommit = new GenerateCommit(
2323
envUtils,
2424
processUtils,
2525
inputUtils,
26+
appUtils,
2627
);
2728

2829
export { setup, help, getVersion, generateCommit };

src/index.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
import { generateCommit, getVersion, help, setup } from './container';
22

3-
export enum CommandEnum {
4-
GetVersion = '-v, --v, -version, --version',
5-
GenerateCommit = 'run, generate-commit',
6-
Setup = 'setup',
7-
Help = '--help',
3+
enum CommandEnum {
4+
GenerateCommit,
5+
GetVersion,
6+
Setup,
7+
Help,
88
}
99

10-
const COMMAND_MAPPER = [
11-
{
12-
match: CommandEnum.Setup.split(',').map((command) => command.trim()),
13-
command: setup,
10+
const COMMAND_MAPPER = {
11+
[CommandEnum.GenerateCommit]: {
12+
match: ['run', 'generate-commit'],
13+
command: generateCommit,
1414
},
15-
{
16-
match: CommandEnum.GetVersion.split(',').map((command) => command.trim()),
15+
16+
[CommandEnum.GetVersion]: {
17+
match: ['-v', '--v', '-version', '--version'],
1718
command: getVersion,
1819
},
19-
{
20-
match: CommandEnum.GenerateCommit.split(',').map((command) =>
21-
command.trim(),
22-
),
23-
command: generateCommit,
20+
21+
[CommandEnum.Setup]: {
22+
match: ['setup'],
23+
command: setup,
2424
},
25-
{
26-
match: CommandEnum.Help.split(',').map((command) => command.trim()),
25+
26+
[CommandEnum.Help]: {
27+
match: ['--help'],
2728
command: help,
2829
},
29-
];
30+
};
3031

3132
export const run = async () => {
3233
const command = process.argv[2];
@@ -35,7 +36,7 @@ export const run = async () => {
3536
return generateCommit.execute();
3637
}
3738

38-
const matchedCommand = COMMAND_MAPPER.find(({ match }) =>
39+
const matchedCommand = Object.values(COMMAND_MAPPER).find(({ match }) =>
3940
match.includes(command),
4041
);
4142

src/interfaces/utils/app.utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2+
export type AppLoggerMessage = any;
3+
4+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5+
export type AppLoggerOptionalParams = any;
6+
7+
type LoggerFunction = (
8+
message?: AppLoggerMessage,
9+
...params: AppLoggerOptionalParams[]
10+
) => void;
11+
112
export interface AppUtils {
213
projectConfigDirectory: string;
314
homeDirectory: string;
415
envFilePath: string;
516
version: string;
617
name: string;
18+
logger: {
19+
error: LoggerFunction;
20+
warn: LoggerFunction;
21+
log: LoggerFunction;
22+
};
723
}

src/providers/openai.provider.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { OpenAI } from 'openai';
22

33
import {
4+
type AppUtils,
45
type EnvUtils,
56
InputTypeEnum,
67
type InputUtils,
@@ -14,6 +15,7 @@ export class OpenAIProvider implements Provider {
1415
constructor(
1516
private readonly envUtils: EnvUtils,
1617
private readonly inputUtils: InputUtils,
18+
private readonly appUtils: AppUtils,
1719
) {}
1820

1921
private get client() {
@@ -32,12 +34,54 @@ export class OpenAIProvider implements Provider {
3234
return this.openai;
3335
}
3436

37+
public async setup(): Promise<void> {
38+
const env = this.envUtils.get();
39+
40+
try {
41+
const apiKey = await this.inputUtils.prompt({
42+
message: 'Enter your OpenAI API key:',
43+
default: env.OPENAI_API_KEY,
44+
type: InputTypeEnum.Input,
45+
});
46+
47+
const numberOfCommits = await this.inputUtils.prompt({
48+
default: env.OPENAI_N_COMMITS ? String(env.OPENAI_N_COMMITS) : '2',
49+
message: 'Enter the number of commits to generate:',
50+
type: InputTypeEnum.Input,
51+
});
52+
53+
this.envUtils.update({
54+
...env,
55+
OPENAI_API_KEY: apiKey,
56+
});
57+
58+
this.envUtils.update({
59+
...env,
60+
OPENAI_N_COMMITS: Number(numberOfCommits),
61+
PROVIDER: ProviderEnum.OpenAI,
62+
OPENAI_API_KEY: apiKey,
63+
});
64+
65+
// Ensure the OpenAI integration is working
66+
await this.test();
67+
68+
console.log('\x1b[32m✓\x1b[0m', 'OpenAI setup successfully completed.');
69+
} catch (error) {
70+
this.envUtils.update(env);
71+
72+
this.appUtils.logger.error('Failed to set up OpenAI.', error);
73+
process.exit(1);
74+
}
75+
}
76+
3577
public async generateCommitMessages({
3678
diff,
3779
}: {
3880
diff: string;
3981
}): Promise<string[]> {
4082
try {
83+
this.checkRequiredEnvVars();
84+
4185
const prompt = `Generate a concise and clear commit message using the commitizen format (e.g., feat, chore, refactor, etc.) for the following code changes. The message should be at most 72 characters long:`;
4286
const n = Number(this.envUtils.get().OPENAI_N_COMMITS) || 2;
4387

@@ -61,37 +105,24 @@ export class OpenAIProvider implements Provider {
61105

62106
return commitMessages;
63107
} catch (error) {
64-
console.error('Failed to generate commit message');
108+
this.appUtils.logger.error(
109+
'Failed to generate commit message.',
110+
error?.error ? `\nOpenAI error:` : '',
111+
error?.error ? error?.error : '',
112+
);
65113

66-
throw error;
114+
process.exit(1);
67115
}
68116
}
69117

70-
public async setup(): Promise<void> {
118+
private checkRequiredEnvVars(): void {
71119
const env = this.envUtils.get();
72120

73-
const apiKey = await this.inputUtils.prompt({
74-
message: 'Enter your OpenAI API key:',
75-
default: env.OPENAI_API_KEY,
76-
type: InputTypeEnum.Input,
77-
});
78-
79-
const numberOfCommits = await this.inputUtils.prompt({
80-
message: 'Enter the number of commits to generate:',
81-
default: String(env.OPENAI_N_COMMITS) || '2',
82-
type: InputTypeEnum.Input,
83-
});
84-
85-
this.envUtils.update({
86-
...env,
87-
OPENAI_N_COMMITS: Number(numberOfCommits),
88-
PROVIDER: ProviderEnum.OpenAI,
89-
OPENAI_API_KEY: apiKey,
90-
});
91-
92-
await this.test();
93-
94-
console.log('\x1b[32m✓\x1b[0m', 'OpenAI setup successfully completed');
121+
if (!env.OPENAI_API_KEY) {
122+
this.appUtils.logger.error('OPENAI_API_KEY is required');
123+
this.appUtils.logger.log("Run 'commitfy setup' to set up.");
124+
process.exit(0);
125+
}
95126
}
96127

97128
private async test(): Promise<void> {

src/utils/app.utils.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import * as path from 'node:path';
55
import { AppUtils as AppUtilsInterface } from '../interfaces';
66

77
export class AppUtils implements AppUtilsInterface {
8-
public readonly name = 'commitfy';
98
public readonly homeDirectory = os.homedir();
109
public readonly projectConfigDirectory = path.resolve(
1110
this.homeDirectory,
@@ -17,17 +16,30 @@ export class AppUtils implements AppUtilsInterface {
1716
'.env',
1817
);
1918

19+
public readonly logger: AppUtilsInterface['logger'] = {
20+
error: (message, ...params) =>
21+
console.error(`${this.name}:`, ...[message, ...params]),
22+
warn: (message, ...params) =>
23+
console.warn(`${this.name}:`, ...[message, ...params]),
24+
log: (message, ...params) =>
25+
console.log(`${this.name}:`, ...[message, ...params]),
26+
};
27+
2028
constructor() {
2129
if (!fs.existsSync(this.projectConfigDirectory)) {
2230
fs.mkdirSync(this.projectConfigDirectory);
2331
}
2432
}
2533

34+
public get name() {
35+
return this.packageJson.name;
36+
}
37+
2638
public get version() {
2739
return this.packageJson.version;
2840
}
2941

30-
private get packageJson(): { version: string } {
42+
private get packageJson(): { version: string; name: string } {
3143
return JSON.parse(
3244
fs.readFileSync(path.resolve(__dirname, '..', 'package.json'), 'utf-8'),
3345
);

src/utils/process.utils.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
import { exec } from 'node:child_process';
22

3-
import type { ProcessUtils as ProcessUtilsInterface } from '../interfaces';
3+
import type {
4+
AppUtils,
5+
ProcessUtils as ProcessUtilsInterface,
6+
} from '../interfaces';
47

58
export class ProcessUtils implements ProcessUtilsInterface {
9+
constructor(private readonly appUtils: AppUtils) {}
10+
611
public async exec(command: string): Promise<string> {
712
return new Promise((resolve, reject) => {
813
exec(command, (error, stdout, stderr) => {
914
if (error) {
10-
console.error(`Error executing command: ${command}\n${error}`);
15+
this.appUtils.logger.error(
16+
`Error executing command '${command}'\n`,
17+
error,
18+
);
19+
1120
reject(stderr);
1221
} else {
1322
resolve(stdout);

0 commit comments

Comments
 (0)