@programinglive/commiter 1.0.5 โ†’ 1.0.8

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/index.js CHANGED
@@ -1,129 +1,148 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Commiter - Commit convention tooling for standard-version releases
5
- *
6
- * This package helps enforce conventional commits and automate releases
7
- * with beautiful changelogs featuring icons for each commit type.
8
- */
9
-
10
- const { execSync } = require('child_process');
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- function ensureSafeTestScript(scripts = {}) {
15
- const defaultFailingTestScript = 'echo "Error: no test specified" && exit 1';
16
- if (!scripts.test || scripts.test === defaultFailingTestScript) {
17
- scripts.test = 'echo "No tests specified"';
18
- }
19
- return scripts;
20
- }
21
-
22
- function setupCommiter() {
23
- console.log('๐Ÿš€ Setting up Commiter...\n');
24
-
25
- // Check if package.json exists
26
- if (!fs.existsSync('package.json')) {
27
- console.error('โŒ Error: package.json not found. Please run this in a Node.js project directory.');
28
- process.exit(1);
29
- }
30
-
31
- try {
32
- // Install dependencies
33
- console.log('๐Ÿ“ฆ Installing dependencies...');
34
- execSync('npm install --save-dev standard-version @commitlint/cli @commitlint/config-conventional husky', {
35
- stdio: 'inherit'
36
- });
37
-
38
- // Read package.json
39
- const packageJsonPath = path.join(process.cwd(), 'package.json');
40
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
41
-
42
- packageJson.scripts = ensureSafeTestScript(packageJson.scripts || {});
43
- // Add scripts
44
- packageJson.scripts.prepare = 'husky';
45
- packageJson.scripts.release = 'standard-version';
46
- packageJson.scripts['release:major'] = 'npm run release -- --release-as major';
47
- packageJson.scripts['release:minor'] = 'npm run release -- --release-as minor';
48
- packageJson.scripts['release:patch'] = 'npm run release -- --release-as patch';
49
-
50
- // Add standard-version config
51
- packageJson['standard-version'] = {
52
- releaseCommitMessageFormat: 'chore(release): {{currentTag}} ๐Ÿš€',
53
- types: [
54
- { type: 'feat', section: 'โœจ Features' },
55
- { type: 'fix', section: '๐Ÿ› Bug Fixes' },
56
- { type: 'perf', section: 'โšก Performance' },
57
- { type: 'refactor', section: 'โ™ป๏ธ Refactors' },
58
- { type: 'docs', section: '๐Ÿ“ Documentation' },
59
- { type: 'style', section: '๐Ÿ’„ Styles' },
60
- { type: 'test', section: 'โœ… Tests' },
61
- { type: 'build', section: '๐Ÿ—๏ธ Build System' },
62
- { type: 'ci', section: '๐Ÿ‘ท Continuous Integration' },
63
- { type: 'chore', section: '๐Ÿงน Chores' },
64
- { type: 'revert', section: 'โช Reverts' }
65
- ]
66
- };
67
-
68
- // Write updated package.json
69
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
70
-
71
- // Determine commitlint config format based on project module type
72
- const isEsmProject = packageJson.type === 'module';
73
- const commitlintConfigFile = isEsmProject ? 'commitlint.config.js' : 'commitlint.config.cjs';
74
- const commitlintConfigContent = isEsmProject
75
- ? `export default {
76
- extends: ['@commitlint/config-conventional'],
77
- ignores: [(message) => message.startsWith('chore(release):')]
78
- }\n`
79
- : `module.exports = {
80
- extends: ['@commitlint/config-conventional'],
81
- ignores: [(message) => message.startsWith('chore(release):')]
82
- }\n`;
83
-
84
- const legacyCommitlintConfigFile = isEsmProject ? 'commitlint.config.cjs' : 'commitlint.config.js';
85
- if (fs.existsSync(legacyCommitlintConfigFile)) {
86
- fs.rmSync(legacyCommitlintConfigFile);
87
- }
88
-
89
- console.log(`โš™๏ธ Creating commitlint config (${commitlintConfigFile})...`);
90
- fs.writeFileSync(commitlintConfigFile, commitlintConfigContent);
91
-
92
- // Initialize Husky
93
- console.log('๐Ÿถ Setting up Husky...');
94
- execSync('npx husky init', { stdio: 'inherit' });
95
-
96
- // Create commit-msg hook
97
- const huskyDir = path.join(process.cwd(), '.husky');
98
- if (!fs.existsSync(huskyDir)) {
99
- fs.mkdirSync(huskyDir, { recursive: true });
100
- }
101
-
102
- const commitMsgHook = `#!/usr/bin/env sh
103
-
104
- npx --no -- commitlint --edit "$1"
105
- `;
106
- fs.writeFileSync(path.join(huskyDir, 'commit-msg'), commitMsgHook);
107
- fs.chmodSync(path.join(huskyDir, 'commit-msg'), 0o755);
108
-
109
- console.log('\nโœ… Commiter setup complete!\n');
110
- console.log('๐Ÿ“š Available commands:');
111
- console.log(' npm run release:major - Create a major release (1.0.0 โ†’ 2.0.0)');
112
- console.log(' npm run release:minor - Create a minor release (1.0.0 โ†’ 1.1.0)');
113
- console.log(' npm run release:patch - Create a patch release (1.0.0 โ†’ 1.0.1)');
114
- console.log(' npm run release - Auto-detect version bump\n');
115
- console.log('๐ŸŽฏ Commit format: type(scope): subject');
116
- console.log(' Example: feat(auth): add user login\n');
117
-
118
- } catch (error) {
119
- console.error('โŒ Error during setup:', error.message);
120
- process.exit(1);
121
- }
122
- }
123
-
124
- // Run setup if called directly
125
- if (require.main === module) {
126
- setupCommiter();
127
- }
128
-
129
- module.exports = { setupCommiter, ensureSafeTestScript };
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Commiter - Commit convention tooling for standard-version releases
5
+ *
6
+ * This package helps enforce conventional commits and automate releases
7
+ * with beautiful changelogs featuring icons for each commit type.
8
+ */
9
+
10
+ const { execSync } = require('child_process');
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ function ensureSafeTestScript(scripts = {}) {
15
+ const defaultFailingTestScript = 'echo "Error: no test specified" && exit 1';
16
+ if (!scripts.test || scripts.test === defaultFailingTestScript) {
17
+ scripts.test = 'echo "No tests specified"';
18
+ }
19
+ return scripts;
20
+ }
21
+
22
+ function setupCommiter() {
23
+ console.log('๐Ÿš€ Setting up Commiter...\n');
24
+
25
+ // Check if package.json exists
26
+ if (!fs.existsSync('package.json')) {
27
+ console.error('โŒ Error: package.json not found. Please run this in a Node.js project directory.');
28
+ process.exit(1);
29
+ }
30
+
31
+ try {
32
+ // Install dependencies
33
+ console.log('๐Ÿ“ฆ Installing dependencies...');
34
+ execSync('npm install --save-dev standard-version @commitlint/cli @commitlint/config-conventional husky', {
35
+ stdio: 'inherit'
36
+ });
37
+
38
+ // Read package.json
39
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
40
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
41
+
42
+ packageJson.scripts = ensureSafeTestScript(packageJson.scripts || {});
43
+ // Add scripts
44
+ packageJson.scripts.prepare = 'husky';
45
+ packageJson.scripts.release = 'node scripts/release.js';
46
+ packageJson.scripts['release:major'] = 'node scripts/release.js major';
47
+ packageJson.scripts['release:minor'] = 'node scripts/release.js minor';
48
+ packageJson.scripts['release:patch'] = 'node scripts/release.js patch';
49
+
50
+ // Add standard-version config
51
+ packageJson['standard-version'] = {
52
+ releaseCommitMessageFormat: 'chore(release): {{currentTag}} ๐Ÿš€',
53
+ types: [
54
+ { type: 'feat', section: 'โœจ Features' },
55
+ { type: 'fix', section: '๐Ÿ› Bug Fixes' },
56
+ { type: 'perf', section: 'โšก Performance' },
57
+ { type: 'refactor', section: 'โ™ป๏ธ Refactors' },
58
+ { type: 'docs', section: '๐Ÿ“ Documentation' },
59
+ { type: 'style', section: '๐Ÿ’„ Styles' },
60
+ { type: 'test', section: 'โœ… Tests' },
61
+ { type: 'build', section: '๐Ÿ—๏ธ Build System' },
62
+ { type: 'ci', section: '๐Ÿ‘ท Continuous Integration' },
63
+ { type: 'chore', section: '๐Ÿงน Chores' },
64
+ { type: 'revert', section: 'โช Reverts' }
65
+ ]
66
+ };
67
+
68
+ // Write updated package.json
69
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
70
+
71
+ // Create release helper script
72
+ console.log('๐Ÿ› ๏ธ Creating release helper script...');
73
+ const releaseScriptDir = path.join(process.cwd(), 'scripts');
74
+ if (!fs.existsSync(releaseScriptDir)) {
75
+ fs.mkdirSync(releaseScriptDir, { recursive: true });
76
+ }
77
+
78
+ const releaseScriptPath = path.join(releaseScriptDir, 'release.js');
79
+ const releaseScriptSource = path.join(__dirname, 'scripts', 'release.js');
80
+ const releaseScriptContent = fs.readFileSync(releaseScriptSource, 'utf8');
81
+
82
+ fs.writeFileSync(releaseScriptPath, releaseScriptContent + '\n');
83
+ try {
84
+ fs.chmodSync(releaseScriptPath, 0o755);
85
+ } catch (error) {
86
+ // Ignore chmod errors on non-POSIX systems
87
+ }
88
+
89
+ // Determine commitlint config format based on project module type
90
+ const isEsmProject = packageJson.type === 'module';
91
+ const commitlintConfigFile = isEsmProject ? 'commitlint.config.js' : 'commitlint.config.cjs';
92
+ const commitlintConfigContent = isEsmProject
93
+ ? `export default {
94
+ extends: ['@commitlint/config-conventional'],
95
+ ignores: [(message) => message.startsWith('chore(release):')]
96
+ }\n`
97
+ : `module.exports = {
98
+ extends: ['@commitlint/config-conventional'],
99
+ ignores: [(message) => message.startsWith('chore(release):')]
100
+ }\n`;
101
+
102
+ const legacyCommitlintConfigFile = isEsmProject ? 'commitlint.config.cjs' : 'commitlint.config.js';
103
+ if (fs.existsSync(legacyCommitlintConfigFile)) {
104
+ fs.rmSync(legacyCommitlintConfigFile);
105
+ }
106
+
107
+ console.log(`โš™๏ธ Creating commitlint config (${commitlintConfigFile})...`);
108
+ fs.writeFileSync(commitlintConfigFile, commitlintConfigContent);
109
+
110
+ // Initialize Husky
111
+ console.log('๐Ÿถ Setting up Husky...');
112
+ execSync('npx husky init', { stdio: 'inherit' });
113
+
114
+ // Create commit-msg hook
115
+ const huskyDir = path.join(process.cwd(), '.husky');
116
+ if (!fs.existsSync(huskyDir)) {
117
+ fs.mkdirSync(huskyDir, { recursive: true });
118
+ }
119
+
120
+ const commitMsgHook = `#!/usr/bin/env sh
121
+
122
+ npx --no -- commitlint --edit "$1"
123
+ `;
124
+ fs.writeFileSync(path.join(huskyDir, 'commit-msg'), commitMsgHook);
125
+ fs.chmodSync(path.join(huskyDir, 'commit-msg'), 0o755);
126
+
127
+ console.log('\nโœ… Commiter setup complete!\n');
128
+ console.log('๐Ÿ“š Available commands:');
129
+ console.log(' npm run release major - Create a major release (1.0.0 โ†’ 2.0.0)');
130
+ console.log(' npm run release minor - Create a minor release (1.0.0 โ†’ 1.1.0)');
131
+ console.log(' npm run release patch - Create a patch release (1.0.0 โ†’ 1.0.1)');
132
+ console.log(' npm run release - Auto-detect version bump');
133
+ console.log(' npm run release -- --prerelease beta - Create a beta prerelease\n');
134
+ console.log('๐ŸŽฏ Commit format: type(scope): subject');
135
+ console.log(' Example: feat(auth): add user login\n');
136
+
137
+ } catch (error) {
138
+ console.error('โŒ Error during setup:', error.message);
139
+ process.exit(1);
140
+ }
141
+ }
142
+
143
+ // Run setup if called directly
144
+ if (require.main === module) {
145
+ setupCommiter();
146
+ }
147
+
148
+ module.exports = { setupCommiter, ensureSafeTestScript };
package/package.json CHANGED
@@ -1,94 +1,94 @@
1
- {
2
- "name": "@programinglive/commiter",
3
- "version": "1.0.5",
4
- "description": "Commit convention tooling for standard-version releases with beautiful changelogs",
5
- "main": "index.js",
6
- "bin": {
7
- "commiter": "./index.js"
8
- },
9
- "scripts": {
10
- "test": "node test/ensureSafeTestScript.test.js",
11
- "prepare": "husky",
12
- "release": "standard-version",
13
- "release:major": "npm run release -- --release-as major",
14
- "release:minor": "npm run release -- --release-as minor",
15
- "release:patch": "npm run release -- --release-as patch"
16
- },
17
- "keywords": [
18
- "commit",
19
- "conventional-commits",
20
- "standard-version",
21
- "changelog",
22
- "versioning",
23
- "semantic-release",
24
- "git-hooks",
25
- "husky",
26
- "commitlint"
27
- ],
28
- "author": "Programming Live",
29
- "license": "MIT",
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/programinglive/commiter.git"
33
- },
34
- "bugs": {
35
- "url": "https://github.com/programinglive/commiter/issues"
36
- },
37
- "homepage": "https://github.com/programinglive/commiter#readme",
38
- "type": "commonjs",
39
- "standard-version": {
40
- "releaseCommitMessageFormat": "chore(release): {{currentTag}} ๐Ÿš€",
41
- "types": [
42
- {
43
- "type": "feat",
44
- "section": "โœจ Features"
45
- },
46
- {
47
- "type": "fix",
48
- "section": "๐Ÿ› Bug Fixes"
49
- },
50
- {
51
- "type": "perf",
52
- "section": "โšก Performance"
53
- },
54
- {
55
- "type": "refactor",
56
- "section": "โ™ป๏ธ Refactors"
57
- },
58
- {
59
- "type": "docs",
60
- "section": "๐Ÿ“ Documentation"
61
- },
62
- {
63
- "type": "style",
64
- "section": "๐Ÿ’„ Styles"
65
- },
66
- {
67
- "type": "test",
68
- "section": "โœ… Tests"
69
- },
70
- {
71
- "type": "build",
72
- "section": "๐Ÿ—๏ธ Build System"
73
- },
74
- {
75
- "type": "ci",
76
- "section": "๐Ÿ‘ท Continuous Integration"
77
- },
78
- {
79
- "type": "chore",
80
- "section": "๐Ÿงน Chores"
81
- },
82
- {
83
- "type": "revert",
84
- "section": "โช Reverts"
85
- }
86
- ]
87
- },
88
- "devDependencies": {
89
- "@commitlint/cli": "^20.1.0",
90
- "@commitlint/config-conventional": "^20.0.0",
91
- "husky": "^9.1.7",
92
- "standard-version": "^9.5.0"
93
- }
94
- }
1
+ {
2
+ "name": "@programinglive/commiter",
3
+ "version": "1.0.8",
4
+ "description": "Commit convention tooling for standard-version releases with beautiful changelogs",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "commiter": "./index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node test/ensureSafeTestScript.test.js",
11
+ "prepare": "husky",
12
+ "release": "node scripts/release.js",
13
+ "release:major": "node scripts/release.js major",
14
+ "release:minor": "node scripts/release.js minor",
15
+ "release:patch": "node scripts/release.js patch"
16
+ },
17
+ "keywords": [
18
+ "commit",
19
+ "conventional-commits",
20
+ "standard-version",
21
+ "changelog",
22
+ "versioning",
23
+ "semantic-release",
24
+ "git-hooks",
25
+ "husky",
26
+ "commitlint"
27
+ ],
28
+ "author": "Programming Live",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/programinglive/commiter.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/programinglive/commiter/issues"
36
+ },
37
+ "homepage": "https://github.com/programinglive/commiter#readme",
38
+ "type": "commonjs",
39
+ "standard-version": {
40
+ "releaseCommitMessageFormat": "chore(release): {{currentTag}} ๐Ÿš€",
41
+ "types": [
42
+ {
43
+ "type": "feat",
44
+ "section": "โœจ Features"
45
+ },
46
+ {
47
+ "type": "fix",
48
+ "section": "๐Ÿ› Bug Fixes"
49
+ },
50
+ {
51
+ "type": "perf",
52
+ "section": "โšก Performance"
53
+ },
54
+ {
55
+ "type": "refactor",
56
+ "section": "โ™ป๏ธ Refactors"
57
+ },
58
+ {
59
+ "type": "docs",
60
+ "section": "๐Ÿ“ Documentation"
61
+ },
62
+ {
63
+ "type": "style",
64
+ "section": "๐Ÿ’„ Styles"
65
+ },
66
+ {
67
+ "type": "test",
68
+ "section": "โœ… Tests"
69
+ },
70
+ {
71
+ "type": "build",
72
+ "section": "๐Ÿ—๏ธ Build System"
73
+ },
74
+ {
75
+ "type": "ci",
76
+ "section": "๐Ÿ‘ท Continuous Integration"
77
+ },
78
+ {
79
+ "type": "chore",
80
+ "section": "๐Ÿงน Chores"
81
+ },
82
+ {
83
+ "type": "revert",
84
+ "section": "โช Reverts"
85
+ }
86
+ ]
87
+ },
88
+ "devDependencies": {
89
+ "@commitlint/cli": "^20.1.0",
90
+ "@commitlint/config-conventional": "^20.0.0",
91
+ "husky": "^9.1.7",
92
+ "standard-version": "^9.5.0"
93
+ }
94
+ }
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require('child_process');
4
+
5
+ const VALID_RELEASE_TYPES = new Set([
6
+ 'major',
7
+ 'minor',
8
+ 'patch',
9
+ 'premajor',
10
+ 'preminor',
11
+ 'prepatch',
12
+ 'prerelease'
13
+ ]);
14
+
15
+ const SEMVER_REGEX = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
16
+
17
+ function getCliArguments(argv = process.argv) {
18
+ const rawArgs = argv.slice(2);
19
+ if (rawArgs.length === 0) {
20
+ return { releaseType: undefined, extraArgs: [] };
21
+ }
22
+
23
+ if (rawArgs[0].startsWith('-')) {
24
+ return { releaseType: undefined, extraArgs: rawArgs };
25
+ }
26
+
27
+ const [firstArg, ...rest] = rawArgs;
28
+ return { releaseType: firstArg, extraArgs: rest };
29
+ }
30
+
31
+ function getNpmRunArgument(env = process.env) {
32
+ try {
33
+ const npmArgs = JSON.parse(env.npm_config_argv || '{}');
34
+ const original = npmArgs.original || [];
35
+ const releaseIndex = original.lastIndexOf('release');
36
+ if (releaseIndex !== -1) {
37
+ return original[releaseIndex + 1];
38
+ }
39
+ } catch (error) {
40
+ // Ignore JSON parsing issues and fall back to defaults
41
+ }
42
+ return undefined;
43
+ }
44
+
45
+ function buildStandardVersionArgs({ releaseType, extraArgs }) {
46
+ const args = [];
47
+ if (releaseType) {
48
+ const normalized = releaseType.trim();
49
+ const isValid = VALID_RELEASE_TYPES.has(normalized) || SEMVER_REGEX.test(normalized);
50
+ if (!isValid) {
51
+ const allowed = Array.from(VALID_RELEASE_TYPES).join(', ');
52
+ throw new Error(`Unknown release type "${normalized}". Use one of ${allowed} or a valid semver version.`);
53
+ }
54
+ args.push('--release-as', normalized);
55
+ }
56
+
57
+ if (Array.isArray(extraArgs) && extraArgs.length > 0) {
58
+ args.push(...extraArgs);
59
+ }
60
+
61
+ return args;
62
+ }
63
+
64
+ function runRelease({ argv = process.argv, env = process.env, spawn = spawnSync } = {}) {
65
+ const { releaseType: cliReleaseType, extraArgs } = getCliArguments(argv);
66
+ const inferredReleaseType = cliReleaseType || getNpmRunArgument(env);
67
+ const standardVersionArgs = buildStandardVersionArgs({
68
+ releaseType: inferredReleaseType,
69
+ extraArgs
70
+ });
71
+
72
+ const standardVersionBin = require.resolve('standard-version/bin/cli.js');
73
+ return spawn(process.execPath, [standardVersionBin, ...standardVersionArgs], {
74
+ stdio: 'inherit'
75
+ });
76
+ }
77
+
78
+ if (require.main === module) {
79
+ try {
80
+ const result = runRelease();
81
+ if (result.status !== 0) {
82
+ process.exit(result.status ?? 1);
83
+ }
84
+ } catch (error) {
85
+ console.error(`โŒ ${error.message}`);
86
+ process.exit(1);
87
+ }
88
+ }
89
+
90
+ module.exports = {
91
+ VALID_RELEASE_TYPES,
92
+ SEMVER_REGEX,
93
+ getCliArguments,
94
+ getNpmRunArgument,
95
+ buildStandardVersionArgs,
96
+ runRelease
97
+ };