format-commit 0.3.1 → 1.0.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.
@@ -1,20 +1,25 @@
1
1
  {
2
- "format": 1,
3
- "minLength": 8,
4
- "maxLength": 80,
5
- "changeVersion": "never",
6
- "releaseBranch": "main",
7
- "showAllVersionTypes": false,
8
- "stageAllChanges": false,
9
- "types": [
10
- { "value": "fix", "description": "Issue(s) fixing" },
11
- { "value": "feat", "description": "New feature(s)" },
12
- { "value": "core", "description": "Change(s) on the application core" },
13
- { "value": "test" , "description": "Change(s) related to tests" },
14
- { "value": "config" , "description": "Project configuration" },
15
- { "value": "doc" , "description": "Documentation / comment(s)" }
16
- ],
17
- "scopes": [
18
- { "value": "example", "description": "Your scope's description" }
19
- ]
2
+ "format": 1,
3
+ "branchFormat": 1,
4
+ "minLength": 8,
5
+ "maxLength": 80,
6
+ "changeVersion": "ignore",
7
+ "releaseBranch": "main",
8
+ "showAllVersionTypes": false,
9
+ "types": [
10
+ { "value": "fix", "description": "Issue(s) fixing" },
11
+ { "value": "feat", "description": "New feature(s)" },
12
+ { "value": "core", "description": "Change(s) on the application core" },
13
+ { "value": "test" , "description": "Change(s) related to tests" },
14
+ { "value": "config" , "description": "Project configuration" },
15
+ { "value": "doc" , "description": "Documentation / comment(s)" }
16
+ ],
17
+ "scopes": [
18
+ { "value": "example", "description": "Your scope's description" }
19
+ ],
20
+ "ai": {
21
+ "enabled": false,
22
+ "envPath": ".env",
23
+ "largeDiffTokenThreshold": 20000
24
+ }
20
25
  }
@@ -0,0 +1,109 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+
5
+ /** Check if a file path is in .gitignore */
6
+ const isInGitignore = (filePath) => {
7
+ try {
8
+ const gitignorePath = path.join(process.cwd(), '.gitignore');
9
+ if (!fs.existsSync(gitignorePath)) {
10
+ return false;
11
+ }
12
+ const gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
13
+ const lines = gitignoreContent.split('\n').map(l => l.trim());
14
+
15
+ const normalizedPath = filePath.startsWith('./') ? filePath.slice(2) : filePath;
16
+
17
+ return lines.some(line => {
18
+ if (!line || line.startsWith('#')) {return false;}
19
+ return line === normalizedPath || line === `/${normalizedPath}`;
20
+ });
21
+ } catch {
22
+ return false;
23
+ }
24
+ };
25
+
26
+ /** Add a file to .gitignore */
27
+ const addToGitignore = (filePath) => {
28
+ try {
29
+ const gitignorePath = path.join(process.cwd(), '.gitignore');
30
+ const normalizedPath = filePath.startsWith('./') ? filePath.slice(2) : filePath;
31
+
32
+ let content = '';
33
+ if (fs.existsSync(gitignorePath)) {
34
+ content = fs.readFileSync(gitignorePath, 'utf-8');
35
+ if (!content.endsWith('\n')) {
36
+ content += '\n';
37
+ }
38
+ }
39
+
40
+ content += `${normalizedPath}\n`;
41
+ fs.writeFileSync(gitignorePath, content);
42
+ return true;
43
+ } catch {
44
+ return false;
45
+ }
46
+ };
47
+
48
+ /** Check if a key exists in .env file */
49
+ const keyExistsInEnv = (envPath, keyName) => {
50
+ try {
51
+ if (!fs.existsSync(envPath)) {
52
+ return false;
53
+ }
54
+ const content = fs.readFileSync(envPath, 'utf-8');
55
+ const regex = new RegExp(`^${keyName}=`, 'm');
56
+ return regex.test(content);
57
+ } catch {
58
+ return false;
59
+ }
60
+ };
61
+
62
+ /** Add or update a key in .env file */
63
+ const setEnvKey = (envPath, keyName, value) => {
64
+ try {
65
+ let content = '';
66
+
67
+ if (fs.existsSync(envPath)) {
68
+ content = fs.readFileSync(envPath, 'utf-8');
69
+ const regex = new RegExp(`^${keyName}=.*$`, 'm');
70
+
71
+ if (regex.test(content)) {
72
+ content = content.replace(regex, `${keyName}=${value}`);
73
+ } else {
74
+ if (!content.endsWith('\n')) {content += '\n';}
75
+ content += `${keyName}=${value}\n`;
76
+ }
77
+ } else {
78
+ content = `${keyName}=${value}\n`;
79
+ }
80
+
81
+ fs.writeFileSync(envPath, content);
82
+ return true;
83
+ } catch {
84
+ return false;
85
+ }
86
+ };
87
+
88
+ /** Read a key from .env file */
89
+ const getEnvKey = (envPath, keyName) => {
90
+ try {
91
+ if (!fs.existsSync(envPath)) {
92
+ return null;
93
+ }
94
+ const content = fs.readFileSync(envPath, 'utf-8');
95
+ const regex = new RegExp(`^${keyName}=(.*)$`, 'm');
96
+ const match = content.match(regex);
97
+ return match ? match[1].trim() : null;
98
+ } catch {
99
+ return null;
100
+ }
101
+ };
102
+
103
+ export {
104
+ isInGitignore,
105
+ addToGitignore,
106
+ keyExistsInEnv,
107
+ setEnvKey,
108
+ getEnvKey,
109
+ };
package/lib/index.js CHANGED
@@ -1,50 +1,63 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
3
2
 
4
- const { Command } = require('commander');
5
- const fs = require('fs');
6
- const utils = require('./utils');
7
- const setup = require('./setup');
8
- const commit = require('./commit');
9
- const options = require('./options.json');
3
+ import { Command } from 'commander';
4
+ import fs from 'fs';
5
+ import * as utils from './utils.js';
6
+ import setup from './setup.js';
7
+ import commit from './commit.js';
8
+ import { readFileSync } from 'fs';
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname, join } from 'path';
11
+
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ const options = JSON.parse(
17
+ readFileSync(join(__dirname, 'options.json'), 'utf-8')
18
+ );
19
+
10
20
 
11
21
  const program = new Command();
12
22
 
13
23
  program
14
- .name('format-commit')
15
- .description('CLI to standardize commit nomenclature')
16
- .version('0.3.1')
17
- .option('-c, --config', 'generate a configuration file on your project for format-commit')
18
- .option('-t, --test', 'start script without finalize commit (for tests)');
24
+ .name('format-commit')
25
+ .description('CLI to standardize commit nomenclature')
26
+ .version('0.3.1')
27
+ .option('-b, --branch', 'create a new branch with standardized naming')
28
+ .option('-c, --config', 'generate a configuration file on your project for format-commit')
29
+ .option('-t, --test', 'start without finalize commit (for tests)');
19
30
 
20
31
  try {
21
- program.parse(process.argv);
32
+ program.parse(process.argv);
22
33
  } catch (error) {
23
- console.error('Error parsing arguments:', error.message);
24
- process.exit(1);
34
+ console.error('Error parsing arguments:', error.message);
35
+ process.exit(1);
25
36
  }
26
37
 
27
38
  (async () => {
28
- const opts = program.opts();
39
+ const opts = program.opts();
40
+
41
+ if (opts.config) {
42
+ await setup(false);
43
+ return;
44
+ }
29
45
 
30
- if (opts.config) {
31
- await setup(false);
46
+ // Get config from consumer package root, generate new config file if not found
47
+ fs.readFile(`./${options.configFile}.json`, async (err, data) => {
48
+ if (err) {
49
+ utils.log('no configuration found', 'warning');
50
+ const setupResult = await setup(true);
51
+ if (setupResult && setupResult.commitAfter) {
52
+ commit(setupResult.config, opts.test);
53
+ }
54
+ } else {
55
+ if (opts.branch) {
56
+ const { default: createBranch } = await import('./create-branch.js');
57
+ createBranch(JSON.parse(data), opts.test);
32
58
  return;
59
+ }
60
+ commit(JSON.parse(data), opts.test);
33
61
  }
34
-
35
- /**
36
- * Get config from consumer package root
37
- * Generate new config file if not founded
38
- */
39
- fs.readFile(`./${options.configFile}.json`, async (err, data) => {
40
- if (err) {
41
- utils.log('no configuration found', 'warning');
42
- const setupResult = await setup(true);
43
- if (setupResult && setupResult.commitAfter) {
44
- commit(setupResult.config, opts.test);
45
- }
46
- } else {
47
- commit(JSON.parse(data), opts.test);
48
- }
49
- });
62
+ });
50
63
  })();
package/lib/options.json CHANGED
@@ -1,31 +1,62 @@
1
1
  {
2
- "configFile": "commit-config",
3
- "commitFormats": [
4
- { "value": 1, "title": "(type) Name" },
5
- { "value": 2, "title": "(type) name" },
6
- { "value": 3, "title": "type: Name" },
7
- { "value": 4, "title": "type: name" },
8
- { "value": 5, "title": "type(scope) Name" },
9
- { "value": 6, "title": "type(scope) name" },
10
- { "value": 7, "title": "type(scope): Name" },
11
- { "value": 8, "title": "type(scope): name" }
12
- ],
13
- "versionChangeMode": [
14
- { "value": "never", "title": "never (always ask)" },
15
- { "value": "releaseBranch", "title": "only on release branch" },
16
- { "value": "always" }
17
- ],
18
- "versionTypes": [
19
- { "value": "patch" },
20
- { "value": "minor" },
21
- { "value": "major" },
22
- { "value": "custom", "title": "<custom>" }
23
- ],
24
- "allVersionTypes": [
25
- { "value": "prepatch" },
26
- { "value": "preminor" },
27
- { "value": "premajor" },
28
- { "value": "prerelease", "title": "prerelease <tag>" },
29
- { "value": "from-git" }
30
- ]
2
+ "configFile": "commit-config",
3
+ "commitFormats": [
4
+ { "value": 1, "title": "(type) Name" },
5
+ { "value": 2, "title": "(type) name" },
6
+ { "value": 3, "title": "type: Name" },
7
+ { "value": 4, "title": "type: name" },
8
+ { "value": 5, "title": "type(scope) Name" },
9
+ { "value": 6, "title": "type(scope) name" },
10
+ { "value": 7, "title": "type(scope): Name" },
11
+ { "value": 8, "title": "type(scope): name" }
12
+ ],
13
+ "branchFormats": [
14
+ { "value": 1, "title": "type/description" },
15
+ { "value": 2, "title": "type/scope/description" }
16
+ ],
17
+ "versionChangeMode": [
18
+ { "value": "ignore", "title": "never (ignore)" },
19
+ { "value": "never", "title": "never (always ask)" },
20
+ { "value": "releaseBranch", "title": "only on release branch" },
21
+ { "value": "always" }
22
+ ],
23
+ "versionTypes": [
24
+ { "value": "patch" },
25
+ { "value": "minor" },
26
+ { "value": "major" },
27
+ { "value": "custom", "title": "<custom>" }
28
+ ],
29
+ "allVersionTypes": [
30
+ { "value": "prepatch" },
31
+ { "value": "preminor" },
32
+ { "value": "premajor" },
33
+ { "value": "prerelease", "title": "prerelease <tag>" },
34
+ { "value": "from-git" }
35
+ ],
36
+ "aiProviders": [
37
+ {
38
+ "value": "anthropic",
39
+ "title": "Anthropic (Claude)",
40
+ "models": [
41
+ { "value": "claude-haiku-4-5", "title": "Claude Haiku 4.5 (Fast & Cheap)" },
42
+ { "value": "claude-sonnet-4-5", "title": "Claude Sonnet 4.5 (Balanced)" }
43
+ ]
44
+ },
45
+ {
46
+ "value": "openai",
47
+ "title": "OpenAI (GPT)",
48
+ "models": [
49
+ { "value": "gpt-4o-mini", "title": "GPT-4o Mini (Fast & Cheap)" },
50
+ { "value": "gpt-4o", "title": "GPT-4o (More Capable)" }
51
+ ]
52
+ },
53
+ {
54
+ "value": "google",
55
+ "title": "Google (Gemini)",
56
+ "models": [
57
+ { "value": "gemini-2.0-flash", "title": "Gemini 2.0 Flash (Fast & Free)" },
58
+ { "value": "gemini-1.5-pro", "title": "Gemini 1.5 Pro (More Capable)" }
59
+ ]
60
+ }
61
+ ]
31
62
  }