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 CHANGED
@@ -1,32 +1,52 @@
1
1
  # format-commit
2
2
 
3
- Easily format and standardize your commits for all your javascript projects using Git.
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
- $ npm i format-commit --save-dev
10
+ npm i format-commit --save-dev
9
11
  ```
10
12
 
11
13
  ## Usage
12
14
 
13
- In the scripts part of your package.json file add a new line `"commit": "format-commit"` and use `$ npm run commit` to commit your changes with format-commit.
15
+ Add to your `package.json` scripts:
16
+ ```json
17
+ "scripts": {
18
+ "commit": "format-commit"
19
+ }
20
+ ```
14
21
 
15
- Or install format-commit globally to use directly `$ format-commit` command .
22
+ Then use:
23
+ ```sh
24
+ npm run commit
25
+ ```
16
26
 
17
- The first time you use the command within your project, format-commit will ask you some questions to configure your commits and create a configuration file `commit-config.json` at the root of your project.
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
- If you want to change format-commit configuration without manually editing the json file you can run the command `$ format-commit --config`.
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** | The formatting of your commit titles. <br> 1: (type) Name / 2: (type) name <br> 3: type: Name / 4: type: Name |
26
- | **types** | The different types of commit allowed. Not defined during assisted configuration, default values used: <br> feat / fix / core / test |
27
- | **minLength** | Minimum size allowed for your commit titles |
28
- | **maxLength** | Maximum size allowed for your commit titles |
29
- | **changeVersion** | "always": All commits must obligatorily involve a change of version (no preliminary request). <br> "only on release branch": All commits on your release/main branch must obligatorily involve a change of version (no preliminary request). <br> "never": Commits do not necessarily lead to a version change whatever the branch, the wizard will always ask. |
30
- | **releaseBranch** | Release/main Git branch of your project. Use if changeVersion is defined on "only on release branch". |
31
- | **showAllVersionTypes** | Show all possible types of version changes in the wizard, or show only the main ones (major / minor / patch / \<custom\>) |
32
- | **stageAllChanges** | Auto-stage all changes before each commit |
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 (options, config) => {
8
- if (!options || !config) {
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
- * Get commit allowed types from custom config if exist
27
- * or get default types from options file
28
- */
29
- choices: config.types ? config.types : options.commitTypes,
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(commit.type, commit.title, config.format);
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;
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "format": 1,
3
3
  "minLength": 8,
4
- "maxLength": 70,
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": "Bug(s) correction" },
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 { program } = require('commander');
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.option('-c, --config', 'generate a configuration file on your project for format-commit');
12
- program.parse(process.argv);
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
- if (program.config) {
16
- await setup();
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(options);
42
+ const setupResult = await setup(true);
27
43
  if (setupResult && setupResult.commitAfter) {
28
- commit(options, setupResult.config);
44
+ commit(setupResult.config, opts.test);
29
45
  }
30
46
  } else {
31
- commit(options, JSON.parse(data));
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": "never", "title": "never (always ask)" }
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 (options) => {
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(`write ${options.configFile} file...`);
103
- fs.writeFileSync(`./${options.configFile}.json`, parsedConfig);
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.1.10",
4
- "description": "Format and standardize your git commits",
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": "^6.2.1",
33
- "kleur": "^4.1.3",
34
- "prompts": "^2.4.0"
46
+ "commander": "^14.0.0",
47
+ "kleur": "^4.1.4",
48
+ "prompts": "^2.4.2"
35
49
  },
36
50
  "devDependencies": {
37
- "eslint": "^7.16.0"
38
- },
39
- "repository": {
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
  }