format-commit 0.1.10 → 0.3.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 +34 -14
- package/lib/commit.js +39 -9
- package/lib/default-config.json +9 -4
- package/lib/index.js +24 -8
- package/lib/options.json +11 -7
- package/lib/setup.js +16 -8
- package/lib/utils.js +9 -1
- package/package.json +34 -27
package/README.md
CHANGED
|
@@ -1,32 +1,52 @@
|
|
|
1
1
|
# format-commit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
🚀 Lightweight CLI for consistent commit message formatting.
|
|
4
|
+
|
|
5
|
+
Standardize your commit naming with basic rules, and guide your workflow through an automated script. No bloat, no complexity — just clean, consistent commits.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
9
|
```sh
|
|
8
|
-
|
|
10
|
+
npm i format-commit --save-dev
|
|
9
11
|
```
|
|
10
12
|
|
|
11
13
|
## Usage
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
Add to your `package.json` scripts:
|
|
16
|
+
```json
|
|
17
|
+
"scripts": {
|
|
18
|
+
"commit": "format-commit"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
Then use:
|
|
23
|
+
```sh
|
|
24
|
+
npm run commit
|
|
25
|
+
```
|
|
16
26
|
|
|
17
|
-
|
|
27
|
+
Or install globally:
|
|
28
|
+
```sh
|
|
29
|
+
npm i -g format-commit
|
|
30
|
+
format-commit
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
On first use, format-commit will prompt you to configure your commit format and create a `commit-config.json` file.
|
|
18
34
|
|
|
19
|
-
|
|
35
|
+
To reconfigure later, run:
|
|
36
|
+
```sh
|
|
37
|
+
format-commit --config
|
|
38
|
+
```
|
|
20
39
|
|
|
21
40
|
## Configuration
|
|
22
41
|
|
|
23
42
|
| Property | Description |
|
|
24
43
|
| :------- | :---------- |
|
|
25
|
-
| **format** |
|
|
26
|
-
| **types** |
|
|
27
|
-
| **
|
|
28
|
-
| **
|
|
29
|
-
| **
|
|
30
|
-
| **
|
|
31
|
-
| **
|
|
32
|
-
| **
|
|
44
|
+
| **format** | Commit title format:<br>1 - `(type) Name` / 2 - `(type) name`<br>3 - `type: Name` / 4 - `type: name`<br>5 - `type(scope) Name` / 6 - `type(scope) name`<br>7 - `type(scope): Name` / 8 - `type(scope): name` |
|
|
45
|
+
| **types** | Allowed commit types (default: `feat`, `fix`, `core`, `test`, `config`, `doc`) |
|
|
46
|
+
| **scopes** | Application scopes for commit categorization (formats 5-8 only) |
|
|
47
|
+
| **minLength** | Minimum commit title length |
|
|
48
|
+
| **maxLength** | Maximum commit title length |
|
|
49
|
+
| **changeVersion** | Version change policy:<br>`always` - All commits require version change<br>`only on release branch` - Only release branch commits require version change<br>`never` - Always prompt for version change |
|
|
50
|
+
| **releaseBranch** | Main/release branch name (used with `only on release branch`) |
|
|
51
|
+
| **showAllVersionTypes** | Show all version types or only main ones (`major`/`minor`/`patch`/`custom`) |
|
|
52
|
+
| **stageAllChanges** | Auto-stage all changes before commit |
|
package/lib/commit.js
CHANGED
|
@@ -2,31 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
const prompts = require('prompts');
|
|
4
4
|
const utils = require('./utils');
|
|
5
|
+
const options = require('./options.json');
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
module.exports = async (
|
|
8
|
-
if (!
|
|
8
|
+
module.exports = async (config, testMode) => {
|
|
9
|
+
if (!config) {
|
|
9
10
|
return;
|
|
10
11
|
}
|
|
11
12
|
utils.log('new commit');
|
|
12
13
|
|
|
14
|
+
if (testMode) {
|
|
15
|
+
utils.log('test mode enabled - commit will not be performed', 'warning');
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
/**
|
|
14
19
|
* Get current git branch for version change option "only on release branch"
|
|
15
20
|
*/
|
|
16
21
|
const currentBranch = utils.getCurrentBranch();
|
|
17
22
|
const askForVersion = utils.askForVersion(config, currentBranch);
|
|
18
23
|
|
|
24
|
+
const noType = !config.types || (config.types && config.types.length === 0);
|
|
25
|
+
if (noType) {
|
|
26
|
+
utils.log('no types defined - please update config', 'error');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const noScope = !config.scopes || (config.scopes && config.scopes.length === 0);
|
|
31
|
+
if (config.format >= 5 && noScope) {
|
|
32
|
+
utils.log('no scopes defined - update config or format option', 'error');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
19
36
|
let cancelled = false;
|
|
20
37
|
const commit = await prompts([
|
|
21
38
|
{
|
|
22
39
|
type: 'select',
|
|
23
40
|
name: 'type',
|
|
24
41
|
message: 'Type of changes',
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
choices: config.types,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: config.format >= 5 ? 'select' : null,
|
|
46
|
+
name: 'scope',
|
|
47
|
+
message: 'Scope',
|
|
48
|
+
choices: config.scopes,
|
|
30
49
|
},
|
|
31
50
|
{
|
|
32
51
|
type: 'text',
|
|
@@ -81,7 +100,7 @@ module.exports = async (options, config) => {
|
|
|
81
100
|
* Handle prompt cancellation and stop commit execution
|
|
82
101
|
*/
|
|
83
102
|
if (cancelled) {
|
|
84
|
-
utils.log('commit cancelled');
|
|
103
|
+
utils.log('commit cancelled', 'error');
|
|
85
104
|
return;
|
|
86
105
|
}
|
|
87
106
|
|
|
@@ -92,7 +111,18 @@ module.exports = async (options, config) => {
|
|
|
92
111
|
if (config.stageAllChanges) {
|
|
93
112
|
utils.handleCmdExec('git add -A');
|
|
94
113
|
}
|
|
95
|
-
const commitTitle = utils.formatCommitTitle(
|
|
114
|
+
const commitTitle = utils.formatCommitTitle(
|
|
115
|
+
commit.type,
|
|
116
|
+
commit.title,
|
|
117
|
+
config.format,
|
|
118
|
+
commit.scope
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (testMode) {
|
|
122
|
+
utils.log(commitTitle, 'warning');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
96
126
|
const commitRes = utils.handleCmdExec(`git commit -m "${commitTitle}" -m "${commit.description}"`);
|
|
97
127
|
if (!commitRes) {
|
|
98
128
|
return;
|
package/lib/default-config.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"format": 1,
|
|
3
3
|
"minLength": 8,
|
|
4
|
-
"maxLength":
|
|
4
|
+
"maxLength": 80,
|
|
5
5
|
"changeVersion": "never",
|
|
6
6
|
"releaseBranch": "master",
|
|
7
7
|
"showAllVersionTypes": false,
|
|
8
8
|
"stageAllChanges": false,
|
|
9
9
|
"types": [
|
|
10
|
-
{ "value": "fix", "description": "
|
|
11
|
-
{ "value": "feat", "description": "New feature(s)"},
|
|
10
|
+
{ "value": "fix", "description": "Issue(s) fixing" },
|
|
11
|
+
{ "value": "feat", "description": "New feature(s)" },
|
|
12
12
|
{ "value": "core", "description": "Change(s) on the application core" },
|
|
13
|
-
{ "value": "test" , "description": "Change(s) related to tests"}
|
|
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" }
|
|
14
19
|
]
|
|
15
20
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const { Command } = require('commander');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const utils = require('./utils');
|
|
7
7
|
const setup = require('./setup');
|
|
8
8
|
const commit = require('./commit');
|
|
9
9
|
const options = require('./options.json');
|
|
10
10
|
|
|
11
|
-
program
|
|
12
|
-
|
|
11
|
+
const program = new Command();
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.name('format-commit')
|
|
15
|
+
.description('CLI to standardize commit nomenclature')
|
|
16
|
+
.version('0.3.0')
|
|
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)');
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
program.parse(process.argv);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error('Error parsing arguments:', error.message);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
13
26
|
|
|
14
27
|
(async () => {
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
const opts = program.opts();
|
|
29
|
+
|
|
30
|
+
if (opts.config) {
|
|
31
|
+
await setup(false);
|
|
17
32
|
return;
|
|
18
33
|
}
|
|
34
|
+
|
|
19
35
|
/**
|
|
20
36
|
* Get config from consumer package root
|
|
21
37
|
* Generate new config file if not founded
|
|
@@ -23,12 +39,12 @@ program.parse(process.argv);
|
|
|
23
39
|
fs.readFile(`./${options.configFile}.json`, async (err, data) => {
|
|
24
40
|
if (err) {
|
|
25
41
|
utils.log('no configuration found', 'warning');
|
|
26
|
-
const setupResult = await setup(
|
|
42
|
+
const setupResult = await setup(true);
|
|
27
43
|
if (setupResult && setupResult.commitAfter) {
|
|
28
|
-
commit(
|
|
44
|
+
commit(setupResult.config, opts.test);
|
|
29
45
|
}
|
|
30
46
|
} else {
|
|
31
|
-
commit(
|
|
47
|
+
commit(JSON.parse(data), opts.test);
|
|
32
48
|
}
|
|
33
49
|
});
|
|
34
50
|
})();
|
package/lib/options.json
CHANGED
|
@@ -4,23 +4,27 @@
|
|
|
4
4
|
{ "value": 1, "title": "(type) Name" },
|
|
5
5
|
{ "value": 2, "title": "(type) name" },
|
|
6
6
|
{ "value": 3, "title": "type: Name" },
|
|
7
|
-
{ "value": 4, "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" }
|
|
8
12
|
],
|
|
9
13
|
"versionChangeMode": [
|
|
10
|
-
{ "value": "always" },
|
|
14
|
+
{ "value": "never", "title": "never (always ask)" },
|
|
11
15
|
{ "value": "releaseBranch", "title": "only on release branch" },
|
|
12
|
-
{ "value": "
|
|
16
|
+
{ "value": "always" }
|
|
13
17
|
],
|
|
14
18
|
"versionTypes": [
|
|
15
|
-
{ "value": "major" },
|
|
16
|
-
{ "value": "minor" },
|
|
17
19
|
{ "value": "patch" },
|
|
20
|
+
{ "value": "minor" },
|
|
21
|
+
{ "value": "major" },
|
|
18
22
|
{ "value": "custom", "title": "<custom>" }
|
|
19
23
|
],
|
|
20
24
|
"allVersionTypes": [
|
|
21
|
-
{ "value": "premajor" },
|
|
22
|
-
{ "value": "preminor" },
|
|
23
25
|
{ "value": "prepatch" },
|
|
26
|
+
{ "value": "preminor" },
|
|
27
|
+
{ "value": "premajor" },
|
|
24
28
|
{ "value": "prerelease", "title": "prerelease <tag>" },
|
|
25
29
|
{ "value": "from-git" }
|
|
26
30
|
]
|
package/lib/setup.js
CHANGED
|
@@ -4,12 +4,10 @@ const prompts = require('prompts');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const utils = require('./utils');
|
|
6
6
|
const defaultConfig = require('./default-config.json');
|
|
7
|
+
const options = require('./options.json');
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
module.exports = async (
|
|
10
|
-
if (!options) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
10
|
+
module.exports = async (askForCommitAfter) => {
|
|
13
11
|
utils.log('create config file');
|
|
14
12
|
|
|
15
13
|
/**
|
|
@@ -64,7 +62,7 @@ module.exports = async (options) => {
|
|
|
64
62
|
initial: defaultConfig.showAllVersionTypes,
|
|
65
63
|
},
|
|
66
64
|
{
|
|
67
|
-
type: 'confirm',
|
|
65
|
+
type: askForCommitAfter ? 'confirm' : null,
|
|
68
66
|
name: 'commitAfter',
|
|
69
67
|
message: 'Commit your changes now? (or exit the configuration without committing)',
|
|
70
68
|
initial: false,
|
|
@@ -80,7 +78,7 @@ module.exports = async (options) => {
|
|
|
80
78
|
* Handle prompt cancellation and stop setup execution
|
|
81
79
|
*/
|
|
82
80
|
if (cancelled) {
|
|
83
|
-
utils.log('setup cancelled');
|
|
81
|
+
utils.log('setup cancelled', 'error');
|
|
84
82
|
return;
|
|
85
83
|
}
|
|
86
84
|
|
|
@@ -90,6 +88,9 @@ module.exports = async (options) => {
|
|
|
90
88
|
const config = {
|
|
91
89
|
format: configChoices.format,
|
|
92
90
|
types: defaultConfig.types,
|
|
91
|
+
scopes: configChoices.format >= 5
|
|
92
|
+
? defaultConfig.scopes
|
|
93
|
+
: undefined,
|
|
93
94
|
minLength: configChoices.minLength,
|
|
94
95
|
maxLength: configChoices.maxLength,
|
|
95
96
|
changeVersion: configChoices.changeVersion,
|
|
@@ -99,8 +100,15 @@ module.exports = async (options) => {
|
|
|
99
100
|
};
|
|
100
101
|
const parsedConfig = JSON.stringify(config, null, 2);
|
|
101
102
|
|
|
102
|
-
utils.log(`
|
|
103
|
-
|
|
103
|
+
utils.log(`save ${options.configFile}.json file...`);
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
fs.writeFileSync(`./${options.configFile}.json`, parsedConfig);
|
|
107
|
+
utils.log('config file successfully created', 'success');
|
|
108
|
+
} catch (err) {
|
|
109
|
+
utils.log(`unable to save config file: ${err}`, 'error');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
104
112
|
|
|
105
113
|
return {
|
|
106
114
|
config,
|
package/lib/utils.js
CHANGED
|
@@ -44,7 +44,7 @@ const validVersion = (version) => {
|
|
|
44
44
|
return true;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
const formatCommitTitle = (type, title, format) => {
|
|
47
|
+
const formatCommitTitle = (type, title, format, scope = '*') => {
|
|
48
48
|
switch (format) {
|
|
49
49
|
case 1:
|
|
50
50
|
default:
|
|
@@ -55,6 +55,14 @@ const formatCommitTitle = (type, title, format) => {
|
|
|
55
55
|
return `${type}: ${title[0].toUpperCase()}${title.substr(1).toLowerCase()}`;
|
|
56
56
|
case 4:
|
|
57
57
|
return `${type}: ${title.toLowerCase()}`;
|
|
58
|
+
case 5:
|
|
59
|
+
return `${type}(${scope}) ${title[0].toUpperCase()}${title.substr(1).toLowerCase()}`;
|
|
60
|
+
case 6:
|
|
61
|
+
return `${type}(${scope}) ${title.toLowerCase()}`;
|
|
62
|
+
case 7:
|
|
63
|
+
return `${type}(${scope}): ${title[0].toUpperCase()}${title.substr(1).toLowerCase()}`;
|
|
64
|
+
case 8:
|
|
65
|
+
return `${type}(${scope}): ${title.toLowerCase()}`;
|
|
58
66
|
}
|
|
59
67
|
};
|
|
60
68
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "format-commit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Lightweight CLI to standardize commit messages",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Thomas BARKATS",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"git",
|
|
9
|
+
"commit",
|
|
10
|
+
"commits",
|
|
11
|
+
"cli",
|
|
12
|
+
"format",
|
|
13
|
+
"standardize",
|
|
14
|
+
"conventional",
|
|
15
|
+
"semantic",
|
|
16
|
+
"workflow",
|
|
17
|
+
"tool",
|
|
18
|
+
"javascript",
|
|
19
|
+
"nodejs"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/thomasbarkats/format-commit.git"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/thomasbarkats/format-commit#readme",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/thomasbarkats/format-commit/issues"
|
|
28
|
+
},
|
|
5
29
|
"main": "./lib/index.js",
|
|
6
30
|
"type": "commonjs",
|
|
7
31
|
"scripts": {
|
|
@@ -9,7 +33,8 @@
|
|
|
9
33
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
34
|
"lint": "eslint . --ext .js --fix",
|
|
11
35
|
"prepublishOnly": "npm run lint",
|
|
12
|
-
"preversion": "npm run lint"
|
|
36
|
+
"preversion": "npm run lint",
|
|
37
|
+
"commit": "npm run lint && npm run start"
|
|
13
38
|
},
|
|
14
39
|
"files": [
|
|
15
40
|
"lib/**/*"
|
|
@@ -17,31 +42,13 @@
|
|
|
17
42
|
"bin": {
|
|
18
43
|
"format-commit": "./lib/index.js"
|
|
19
44
|
},
|
|
20
|
-
"author": "Sendups",
|
|
21
|
-
"keywords": [
|
|
22
|
-
"git",
|
|
23
|
-
"commit",
|
|
24
|
-
"cli",
|
|
25
|
-
"format",
|
|
26
|
-
"standardize",
|
|
27
|
-
"light",
|
|
28
|
-
"minimalist"
|
|
29
|
-
],
|
|
30
|
-
"license": "ISC",
|
|
31
45
|
"dependencies": {
|
|
32
|
-
"commander": "^
|
|
33
|
-
"kleur": "^4.1.
|
|
34
|
-
"prompts": "^2.4.
|
|
46
|
+
"commander": "^14.0.0",
|
|
47
|
+
"kleur": "^4.1.4",
|
|
48
|
+
"prompts": "^2.4.2"
|
|
35
49
|
},
|
|
36
50
|
"devDependencies": {
|
|
37
|
-
"eslint": "^
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"type": "git",
|
|
41
|
-
"url": "git+https://github.com/sendups/format-commit.git"
|
|
42
|
-
},
|
|
43
|
-
"bugs": {
|
|
44
|
-
"url": "https://github.com/sendups/format-commit/issues"
|
|
45
|
-
},
|
|
46
|
-
"homepage": "https://github.com/sendups/format-commit#readme"
|
|
51
|
+
"@eslint/js": "^9.27.0",
|
|
52
|
+
"eslint": "^9.27.0"
|
|
53
|
+
}
|
|
47
54
|
}
|