Skip to content

Commit 6d3b02d

Browse files
committed
feat(core): rearchitect application structure, improve type safety, and enhance error handling
- Refactored core modules for better maintainability and scalability - Introduced comprehensive type annotations to improve type safety - Enhanced error handling with more descriptive messages and structured exception management - Updated existing components to align with the new architecture - Improved overall application performance and reliability
1 parent 624438e commit 6d3b02d

15 files changed

+390
-252
lines changed

bin/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import arg from "arg";
33
import chalk from "chalk";
44
import { start } from "../src/commands/start";
55
import { reset } from "../src/commands/reset";
6-
import { importKey } from "../src/utils/importKey";
7-
import createLogger from "../src/logger";
6+
import { importKey } from "../src/commands/import";
7+
import createLogger from "../src/utils/logger";
88
import boxen from 'boxen';
99
import { GitKeyKitCodes } from "../src/gitkeykitCodes";
1010

11-
// Setup process handlers
1211
process.on("SIGINT", () => process.exit(GitKeyKitCodes.SUCCESS));
1312
process.on("SIGTERM", () => process.exit(GitKeyKitCodes.SUCCESS));
1413

src/commands/_start.txt

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/utils/importKey.ts renamed to src/commands/import.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ export function importKey(key: string): boolean {
77
} catch (error: any) {
88
throw new Error(`Error importing key: ${(error as Error).message}`);
99
}
10-
}
10+
}

src/commands/reset.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { execSync } from "child_process";
22
import { existsSync, writeFileSync } from "fs";
3-
import createLogger from "../logger";
3+
import createLogger from "../utils/logger";
44
import os from "os";
55
import path from "path";
66
import { GitKeyKitCodes } from "../gitkeykitCodes";
@@ -61,4 +61,4 @@ export function reset(): GitKeyKitCodes {
6161
logger.error("Error: Failed to reset git configuration.");
6262
return GitKeyKitCodes.ERR_GIT_CONFIG_RESET;
6363
}
64-
}
64+
}

src/commands/start.ts

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,59 @@
1-
import os from "os";
2-
import createLogger from "../logger";
3-
import { execSync } from "child_process";
4-
import { checkSecretKeys } from "../utils/checkSecretKeys";
1+
import { checkRequiredDependencies } from '../utils/checkDependencies';
2+
import { checkSecretKeys } from '../utils/checkSecretKeys';
3+
import { createPgpKey } from '../utils/createKey';
4+
import { setGitConfig } from '../utils/setGitConfig'
5+
import { addExtraConfig } from '../utils/linuxConfig';
6+
import { platform } from 'os';
7+
// import chalk from 'chalk';
8+
import { GitKeyKitCodes } from '../gitkeykitCodes';
9+
import createLogger from '../utils/logger';
510

6-
const platform: NodeJS.Platform = os.platform();
7-
const logger = createLogger("commands: start");
8-
let gpgAgentAddress: string[];
9-
10-
export async function start(): Promise<void> {
11-
logger.highlight("Operating System:", platform);
11+
const logger = createLogger('commands:start');
1212

13+
export async function start(): Promise<GitKeyKitCodes> {
1314
try {
14-
// Check GPG version
15-
const gpgVersion = execSync("gpg --version").toString();
16-
if (gpgVersion.includes("gpg (GnuPG)")) {
17-
logger.blue("GPG is installed on your system.");
18-
} else {
19-
logger.warning("GPG is not installed on your system.");
15+
// Check dependencies
16+
const { code, gpgPath } = await checkRequiredDependencies();
17+
if (code !== GitKeyKitCodes.SUCCESS) {
18+
return code;
19+
}
20+
21+
if (!gpgPath) {
22+
logger.error('GPG path not found');
23+
return GitKeyKitCodes.ERR_GPG_NOT_FOUND;
2024
}
2125

22-
if (platform === "win32") {
23-
// Check for GPG program on Windows
24-
const gpgPath = execSync("cmd /c where gpg").toString().trim().split("\r\n");
25-
if (gpgPath.length > 0) {
26-
gpgAgentAddress = gpgPath;
27-
logger.log("GPG program is located at:");
28-
gpgPath.forEach((path) => logger.log(path));
29-
await checkSecretKeys(gpgAgentAddress);
30-
} else {
31-
logger.error("GPG program is not found on your system.");
26+
// Check for existing GPG keys
27+
const secretKeyResult = await checkSecretKeys();
28+
if (secretKeyResult !== GitKeyKitCodes.SUCCESS) {
29+
// Create new key if none exists
30+
const keyResult = await createPgpKey();
31+
if (keyResult !== GitKeyKitCodes.SUCCESS) {
32+
return keyResult;
3233
}
33-
} else if (platform === "linux") {
34-
// Check for GPG program on Linux
35-
const gpgPath = execSync("which gpg").toString().trim().split("\n");
36-
if (gpgPath.length > 0) {
37-
gpgAgentAddress = gpgPath;
38-
logger.log("GPG program is located at:", gpgPath);
39-
await checkSecretKeys(gpgAgentAddress);
40-
} else {
41-
logger.error("GPG program is not found on your system.");
34+
}
35+
36+
// Configure git
37+
const gitConfigResult = await setGitConfig(gpgPath);
38+
if (gitConfigResult !== GitKeyKitCodes.SUCCESS) {
39+
return gitConfigResult;
40+
}
41+
42+
// Add extra configuration for non-Windows platforms
43+
if (platform() !== 'win32') {
44+
const configResult = await addExtraConfig();
45+
if (configResult !== GitKeyKitCodes.SUCCESS) {
46+
return configResult;
4247
}
43-
} else {
44-
process.exit(1);
4548
}
46-
} catch (error: any) {
47-
logger.error("Error:", (error as Error).message);
49+
50+
logger.green('Setup complete. Happy coding! 🎉');
51+
return GitKeyKitCodes.SUCCESS;
52+
53+
} catch (error) {
54+
if (error instanceof Error) {
55+
logger.error(`Unexpected error: ${error.message}`);
56+
}
57+
return GitKeyKitCodes.ERR_INVALID_INPUT;
4858
}
49-
}
59+
}

src/systemCheck.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { exec } from 'child_process';
2+
import { promisify } from 'util';
3+
import { GitKeyKitCodes } from './gitkeykitCodes';
4+
import { platform } from 'os';
5+
6+
const execAsync = promisify(exec);
7+
8+
const COMMANDS = {
9+
GPG_CHECK: platform() === 'win32' ? 'where gpg' : 'which gpg',
10+
GIT_CHECK: platform() === 'win32' ? 'where git' : 'which git'
11+
};
12+
13+
/**
14+
* Checks if GPG is installed and returns its path
15+
* @returns Promise resolving to GPG path or error code
16+
*/
17+
export async function checkGpgInstallation(): Promise<{ code: GitKeyKitCodes, path?: string }> {
18+
try {
19+
const { stdout } = await execAsync(COMMANDS.GPG_CHECK);
20+
const gpgPath = stdout.trim();
21+
22+
if (gpgPath) {
23+
return {
24+
code: GitKeyKitCodes.SUCCESS,
25+
path: gpgPath
26+
};
27+
}
28+
29+
return {
30+
code: GitKeyKitCodes.ERR_GPG_NOT_FOUND
31+
};
32+
} catch (error) {
33+
return {
34+
code: GitKeyKitCodes.ERR_GPG_NOT_FOUND
35+
};
36+
}
37+
}
38+
39+
/**
40+
* Checks if Git is installed
41+
* @returns Promise resolving to success or error code
42+
*/
43+
export async function checkGitInstallation(): Promise<GitKeyKitCodes> {
44+
try {
45+
await execAsync(COMMANDS.GIT_CHECK);
46+
return GitKeyKitCodes.SUCCESS;
47+
} catch (error) {
48+
return GitKeyKitCodes.ERR_GIT_NOT_FOUND;
49+
}
50+
}
51+
52+
/**
53+
* Checks all required dependencies
54+
* @returns Promise resolving to GPG path or error code
55+
*/
56+
export async function checkRequiredDependencies(): Promise<{ code: GitKeyKitCodes, gpgPath?: string }> {
57+
// Check Git first
58+
const gitCheck = await checkGitInstallation();
59+
if (gitCheck !== GitKeyKitCodes.SUCCESS) {
60+
return { code: gitCheck };
61+
}
62+
63+
// Then check GPG
64+
const gpgCheck = await checkGpgInstallation();
65+
return {
66+
code: gpgCheck.code,
67+
gpgPath: gpgCheck.path
68+
};
69+
}

src/utils/checkDependencies.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { GitKeyKitCodes } from "../gitkeykitCodes";
2+
import { checkGitInstallation, checkGpgInstallation } from "../systemCheck";
3+
4+
/**
5+
* Checks all required dependencies
6+
* @returns Promise resolving to GPG path or error code
7+
*/
8+
export async function checkRequiredDependencies(): Promise<{ code: GitKeyKitCodes, gpgPath?: string }> {
9+
// Check Git first
10+
const gitCheck = await checkGitInstallation();
11+
if (gitCheck !== GitKeyKitCodes.SUCCESS) {
12+
return { code: gitCheck };
13+
}
14+
15+
// Then check GPG
16+
const gpgCheck = await checkGpgInstallation();
17+
return {
18+
code: gpgCheck.code,
19+
gpgPath: gpgCheck.path
20+
};
21+
}

src/utils/checkSecretKeys.ts

Lines changed: 28 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,31 @@
1-
import { execSync } from "child_process";
2-
import confirm from "@inquirer/confirm";
3-
import { configureGPG } from "./configureGPG";
4-
import { setGitConfig } from "./setGitConfig";
5-
import { generateGpgKeys } from "./generate";
6-
import createLogger from "../logger";
7-
import os from "os";
1+
import { spawn } from 'child_process';
2+
import { GitKeyKitCodes } from "../gitkeykitCodes";
83

9-
const platform: NodeJS.Platform = os.platform();
10-
const logger = createLogger("commands: start");
4+
/**
5+
* Checks if GPG secret keys exist on the system
6+
* @returns Promise that resolves to a GitKeyKitCodes value
7+
*/
8+
export async function checkSecretKeys(): Promise<GitKeyKitCodes> {
9+
return new Promise((resolve) => {
10+
const gpgProcess = spawn('gpg', ['--list-secret-keys']);
11+
let foundSecretKey = false;
1112

12-
export async function checkSecretKeys(gpgAgentAddress: string[]) {
13-
try {
14-
// Check for secret keys
15-
const secretKeys = execSync("gpg --list-secret-keys").toString();
16-
if (secretKeys.includes("sec")) {
17-
logger.blue("Secret keys are present on your system.");
18-
await setGitConfig(gpgAgentAddress);
19-
if (platform === "linux") {
20-
await configureGPG();
21-
logger.green("Setup finished! Happy coding!");
22-
process.exit(1);
13+
gpgProcess.stdout.on('data', (data: Buffer) => {
14+
const output = data.toString();
15+
if (output.includes('sec')) {
16+
foundSecretKey = true;
2317
}
24-
logger.green("Setup finished! Happy coding!");
25-
} else {
26-
logger.warning("No secret keys found on your system.");
27-
const ok = await confirm({ message: "Do you want to generate GPG keys now?" });
28-
if (ok) {
29-
await generateGpgKeys();
30-
await setGitConfig(gpgAgentAddress);
31-
logger.highlight("Before config");
32-
if (platform === "linux") {
33-
await configureGPG();
34-
logger.green("Setup finished! Happy coding!");
35-
process.exit(1);
36-
}
37-
logger.green("Setup finished! Happy coding!");
38-
process.exit(1);
39-
} else {
40-
process.exit(1);
41-
}
42-
}
43-
} catch (error: any) {
44-
logger.error("Error:", (error as Error).message);
45-
}
46-
}
18+
});
19+
20+
gpgProcess.on('error', () => {
21+
resolve(GitKeyKitCodes.ERR_NO_SECRET_KEYS);
22+
});
23+
24+
gpgProcess.on('close', () => {
25+
resolve(foundSecretKey ?
26+
GitKeyKitCodes.SUCCESS :
27+
GitKeyKitCodes.ERR_NO_SECRET_KEYS
28+
);
29+
});
30+
});
31+
}

src/utils/configureGPG.ts

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)