commit-sense-cli 1.0.1 → 1.1.0

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
@@ -15,7 +15,7 @@ CommitSense helps developers write accurate, meaningful, and semantically correc
15
15
  ## Installation
16
16
 
17
17
  ```bash
18
- npm install -g commit-sense
18
+ npm install -g commit-sense-cli
19
19
  ```
20
20
 
21
21
  ## Usage
@@ -29,7 +29,7 @@ git add .
29
29
  Run CommitSense instead of `git commit`:
30
30
 
31
31
  ```bash
32
- commit-sense
32
+ commit-sense-cli
33
33
  ```
34
34
 
35
35
  Follow the interactive prompts to confirm or edit the commit message.
@@ -41,3 +41,21 @@ Follow the interactive prompts to confirm or edit the commit message.
41
41
  3. Build: `npm run build`
42
42
  4. Run locally: `npm run dev` (or `node bin/commitsense.js`)
43
43
 
44
+ ## Optional: Enforce Commit Convention
45
+
46
+ You can use `commit-sense-cli` to validate commit messages with git hooks (e.g., using **Husky**).
47
+
48
+ 1. Install Husky:
49
+ ```bash
50
+ npm install --save-dev husky
51
+ npx husky init
52
+ ```
53
+
54
+ 2. Add a `commit-msg` hook:
55
+ ```bash
56
+ echo "npx commit-sense-cli validate \$1" > .husky/commit-msg
57
+ ```
58
+
59
+ Now, if you try to commit with an invalid message (e.g., `git commit -m "bad message"`), it will be rejected.
60
+
61
+
@@ -0,0 +1,5 @@
1
+ export interface ValidationResult {
2
+ isValid: boolean;
3
+ errors: string[];
4
+ }
5
+ export declare function validateCommitMessage(message: string): ValidationResult;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateCommitMessage = validateCommitMessage;
4
+ function validateCommitMessage(message) {
5
+ const errors = [];
6
+ const conventionalCommitRegex = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+$/;
7
+ const firstLine = message.split('\n')[0];
8
+ if (!conventionalCommitRegex.test(firstLine)) {
9
+ errors.push('Commit message must follow format: type(scope): subject');
10
+ errors.push('Example: feat(auth): add login support');
11
+ errors.push('Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert');
12
+ }
13
+ return {
14
+ isValid: errors.length === 0,
15
+ errors
16
+ };
17
+ }
package/dist/index.js CHANGED
@@ -9,7 +9,55 @@ const git_1 = require("./utils/git");
9
9
  const classifier_1 = require("./analysis/classifier");
10
10
  const scope_1 = require("./analysis/scope");
11
11
  const child_process_1 = require("child_process");
12
+ const validator_1 = require("./analysis/validator");
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
12
14
  async function main() {
15
+ // 0. Handle Validation Command
16
+ const args = process.argv.slice(2);
17
+ if (args.length > 0 && (args[0] === 'validate' || args[0] === '--validate')) {
18
+ const msgFile = args[1];
19
+ if (!msgFile) {
20
+ console.error(chalk_1.default.red('Error: Commit message file path required for validation.'));
21
+ process.exit(1);
22
+ }
23
+ try {
24
+ const msg = await fs_extra_1.default.readFile(msgFile, 'utf-8');
25
+ const result = (0, validator_1.validateCommitMessage)(msg);
26
+ if (!result.isValid) {
27
+ console.error(chalk_1.default.red('Invalid Commit Message:'));
28
+ result.errors.forEach(e => console.error(chalk_1.default.yellow(` - ${e}`)));
29
+ // Provide Suggestions
30
+ try {
31
+ const stagedFiles = await (0, git_1.getStagedFiles)();
32
+ if (stagedFiles.length > 0) {
33
+ const fileChanges = await Promise.all(stagedFiles.map(async (file) => ({
34
+ path: file,
35
+ diff: await (0, git_1.getStagedFileDiff)(file)
36
+ })));
37
+ const classification = await (0, classifier_1.classifyChanges)(fileChanges);
38
+ const suggestedScope = (0, scope_1.detectScope)(stagedFiles);
39
+ console.log(chalk_1.default.cyan('\n----------------------------------------'));
40
+ console.log(chalk_1.default.cyan('🤖 CommitSense Suggestion:'));
41
+ console.log(chalk_1.default.green(`${classification.type}${suggestedScope ? `(${suggestedScope})` : ''}: <description>`));
42
+ console.log(chalk_1.default.gray(`Reason: ${classification.reason}`));
43
+ console.log(chalk_1.default.cyan('----------------------------------------\n'));
44
+ }
45
+ }
46
+ catch (err) {
47
+ // Ignore analysis errors during validation to avoid noise
48
+ }
49
+ process.exit(1);
50
+ }
51
+ else {
52
+ console.log(chalk_1.default.green('Commit message is valid.'));
53
+ process.exit(0);
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.error(chalk_1.default.red(`Error reading commit message file: ${msgFile}`), error);
58
+ process.exit(1);
59
+ }
60
+ }
13
61
  console.log(chalk_1.default.cyan('CommitSense - Smart Commit Wizard'));
14
62
  // 1. Get staged files
15
63
  const stagedFiles = await (0, git_1.getStagedFiles)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commit-sense-cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -19,7 +19,8 @@
19
19
  "scripts": {
20
20
  "test": "jest",
21
21
  "build": "tsc",
22
- "dev": "ts-node src/index.ts"
22
+ "dev": "ts-node src/index.ts",
23
+ "prepare": "husky"
23
24
  },
24
25
  "repository": {
25
26
  "type": "git",
@@ -34,9 +35,11 @@
34
35
  },
35
36
  "homepage": "https://github.com/abhishekpanda0620/commit-sense#readme",
36
37
  "dependencies": {
38
+ "@types/fs-extra": "^11.0.4",
37
39
  "@types/node": "^25.2.3",
38
40
  "chalk": "^5.6.2",
39
41
  "commander": "^14.0.3",
42
+ "fs-extra": "^11.3.3",
40
43
  "prompts": "^2.4.2",
41
44
  "simple-git": "^3.30.0",
42
45
  "ts-node": "^10.9.2",
@@ -45,6 +48,7 @@
45
48
  "devDependencies": {
46
49
  "@types/jest": "^30.0.0",
47
50
  "@types/prompts": "^2.4.9",
51
+ "husky": "^9.1.7",
48
52
  "jest": "^30.2.0",
49
53
  "ts-jest": "^29.4.6"
50
54
  }