changelog-tool 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
package/changelog.md CHANGED
@@ -1,6 +1,24 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.6.0 (2023-02-14)
5
+ ------------------
6
+
7
+ * The release command now automatically calls "npm version" if a package.json
8
+ was found in the project directory
9
+ * Bug fix: the --major and --minor arguments were ignored when using "add" to
10
+ create a new version log
11
+
12
+
13
+ 0.5.0 (2023-02-12)
14
+ ------------------
15
+
16
+ * Support changing the version to the next major/minor using the `--major` and
17
+ `--minor` arguments.
18
+ * The `add` command now uses the -m argument instead of a positional for the
19
+ message.
20
+
21
+
4
22
  0.4.1 (2023-02-12)
5
23
  ------------------
6
24
 
package/changelog.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { wrap } from './util.mjs';
1
+ import { calculateNextVersion, wrap } from './util.mjs';
2
2
 
3
3
  // @ts-check
4
4
  export class Changelog {
@@ -38,21 +38,14 @@ export class Changelog {
38
38
  * Adds a new version to the log. Version string is automatically increased
39
39
  * from the previous one
40
40
  *
41
+ * @param {'patch'|'minor'|'major'} changeType
41
42
  * @returns {VersionLog}
42
43
  */
43
- newVersion() {
44
+ newVersion(changeType = 'patch') {
44
45
 
45
- const lastVersionStr = this.versions[0].version;
46
- const lastVersionParts = lastVersionStr.split('.');
47
- if (!lastVersionParts.at(-1)?.match(/^[0-9]+$/)) {
48
- throw new Error(`Could not automatically determine the next version string after "${lastVersionStr}"`);
49
- }
50
- const newVersionStr = [
51
- ...lastVersionParts.slice(0, -1),
52
- // @ts-ignore-error 'Possibly udefined', but we know it isnt
53
- parseInt(lastVersionParts.at(-1)) + 1
54
- ].join('.');
55
- const versionLog = new VersionLog(newVersionStr);
46
+ const lastVersion = this.versions[0].version;
47
+ const newVersion = calculateNextVersion(lastVersion, changeType);
48
+ const versionLog = new VersionLog(newVersion);
56
49
 
57
50
  return this.add(versionLog);
58
51
 
package/cli.mjs CHANGED
@@ -3,9 +3,10 @@
3
3
  import { parseArgs } from 'node:util';
4
4
  import * as fs from 'node:fs/promises';
5
5
  import * as url from 'node:url';
6
- import { readPackageVersion, exists } from './util.mjs';
6
+ import { readPackageVersion, exists, calculateNextVersion } from './util.mjs';
7
7
  import { Changelog, VersionLog, LogItem } from './changelog.mjs';
8
8
  import { parseFile } from './parse.mjs';
9
+ import { execSync } from 'node:child_process';
9
10
 
10
11
  const filename = 'changelog.md';
11
12
 
@@ -31,6 +32,23 @@ async function main() {
31
32
  default: false,
32
33
  description: 'Show all versions',
33
34
  },
35
+ message: {
36
+ type: 'string',
37
+ description: 'Changelog message',
38
+ short: 'm'
39
+ },
40
+ patch: {
41
+ type: 'boolean',
42
+ description: 'Indicates that the current change is a patch-level change.',
43
+ },
44
+ minor: {
45
+ type: 'boolean',
46
+ description: 'Indicates that the current change is a minor change.',
47
+ },
48
+ major: {
49
+ type: 'boolean',
50
+ description: 'Indicates that the current change is a major change.',
51
+ },
34
52
  },
35
53
  allowPositionals: true,
36
54
  });
@@ -52,10 +70,21 @@ async function main() {
52
70
  await init();
53
71
  break;
54
72
  case 'add' :
55
- if (positionals.length < 2) {
56
- throw new Error('The "message" argument must be specified with the "add" command');
73
+ /** @type {'major' | 'minor' | 'patch'} */
74
+ let changeType = 'patch';
75
+ if (values.minor) {
76
+ changeType = 'minor';
57
77
  }
58
- await add(positionals.slice(1).join(' '));
78
+ if (values.major) {
79
+ changeType = 'major';
80
+ }
81
+ if (!values.message) {
82
+ throw new Error('The "-m" or "--message" argument is required');
83
+ }
84
+ await add({
85
+ message: values.message,
86
+ changeType,
87
+ });
59
88
  break;
60
89
  case 'release' :
61
90
  await release();
@@ -92,13 +121,13 @@ Manipulate your changelog file
92
121
 
93
122
  Usage:
94
123
 
95
- changelog init - Create a new, empty changelog.
96
- changelog add [message] - Adds a new line to the changelog.
97
- changelog release - Marks the current changelog as released.
98
- changelog show - Show the last changelog.
99
- changelog show [version] - Show the changelog of a specific version.
100
- changelog list - List all versions in the changelog.
101
- changelog format - Reformats the changelog in the standard format.
124
+ changelog init - Create a new, empty changelog.
125
+ changelog add -m [message] - Adds a new line to the changelog.
126
+ changelog release - Marks the current changelog as released.
127
+ changelog show - Show the last changelog.
128
+ changelog show [version] - Show the changelog of a specific version.
129
+ changelog list - List all versions in the changelog.
130
+ changelog format - Reformats the changelog in the standard format.
102
131
 
103
132
  The logs this tool uses follows a specific markdown format. Currently it will
104
133
  only look for a file named 'changelog.md' in the current directory.
@@ -170,16 +199,28 @@ async function format() {
170
199
  }
171
200
 
172
201
  /**
173
- * @param {string} message
202
+ * @param {Object} options
203
+ * @param {string} options.message
204
+ * @param {'patch'|'major'|'minor'} options.changeType
174
205
  */
175
- async function add(message) {
206
+ async function add({message, changeType}) {
176
207
  const changelog = await parseChangelog();
177
208
 
178
209
  let lastVersion = changelog.versions[0];
179
210
  if (lastVersion.date) {
180
- lastVersion = changelog.newVersion();
211
+ lastVersion = changelog.newVersion(changeType);
181
212
  console.log('Creating new version: %s', lastVersion.version);
213
+ } else {
214
+ if (changeType === 'minor' || changeType === 'major') {
215
+ const previousVersion = changelog.versions[1];
216
+ const updatedVersionStr = calculateNextVersion(previousVersion.version, changeType);
217
+ if (updatedVersionStr !== lastVersion.version) {
218
+ console.log('Updating unreleased version from %s to %s', lastVersion.version, updatedVersionStr);
219
+ lastVersion.version = updatedVersionStr;
220
+ }
221
+ }
182
222
  }
223
+
183
224
  lastVersion.add(message);
184
225
 
185
226
  await fs.writeFile(filename, changelog.toString());
@@ -198,6 +239,12 @@ async function release() {
198
239
  await fs.writeFile(filename, changelog.toString());
199
240
  console.log(`${changelog.versions.length} changelogs saved to ${filename}`);
200
241
 
242
+ if (await exists('package.json')) {
243
+ const command = `npm version "${lastVersion.version}" --no-git-tag-version`;
244
+ console.log(command);
245
+ execSync(command);
246
+ }
247
+
201
248
  }
202
249
 
203
250
  /**
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "changelog-tool",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "A CLI tool for manipulating changelogs",
5
+ "type": "module",
5
6
  "main": "index.mjs",
6
7
  "scripts": {
7
- "test": "node --test"
8
+ "test": "node --test",
9
+ "watch": "tsc --watch"
8
10
  },
9
11
  "keywords": [
10
12
  "changelog",
package/readme.md CHANGED
@@ -26,7 +26,7 @@ Installation
26
26
  ------------
27
27
 
28
28
  ```sh
29
- npm install changelog-tool --save-dev
29
+ npm install changelog-tool --global
30
30
  ```
31
31
 
32
32
  CLI
@@ -36,13 +36,55 @@ To tool can be used programmatically and with the CLI. The CLI has the
36
36
  following commands:
37
37
 
38
38
  ```
39
- npx changelog init - Create a new, empty npx changelog.
40
- npx changelog add [message] - Adds a new line to the npx changelog.
41
- npx changelog release - Marks the current npx changelog as released.
42
- npx changelog show - Show the last npx changelog.
43
- npx changelog show [version] - Show the npx changelog of a specific version.
44
- npx changelog list - List all versions in the npx changelog.
45
- npx changelog format - Reformats the npx changelog in the standard format.
39
+ changelog init - Create a new, empty npx changelog.
40
+ changelog add -m [message] - Adds a new line to the npx changelog.
41
+ changelog release - Marks the current npx changelog as released.
42
+ changelog show - Show the last npx changelog.
43
+ changelog show [version] - Show the npx changelog of a specific version.
44
+ changelog list - List all versions in the npx changelog.
45
+ changelog format - Reformats the npx changelog in the standard format.
46
46
  ```
47
47
 
48
- Feature requests and bug reports are welcome.
48
+ ### 'add' command
49
+
50
+ The add comment lets you add a new message at the bottom of the last unreleased
51
+ version.
52
+
53
+ To use it, just run:
54
+
55
+ ```
56
+ changelog add -m "Bug fix"
57
+ ```
58
+
59
+ If there is no unreleased version, it will create a new section and increase
60
+ the version number.
61
+
62
+ If the current change should result in a new major or minor version number, you
63
+ can use the following arguments.
64
+
65
+ ```
66
+ changelog add --minor -m "New feature"
67
+ changelog add --major -m "Backwards compatibility break"
68
+ ```
69
+
70
+ These settings will automatically adjust the version string of the most recent
71
+ unreleased version.
72
+
73
+ ### 'release' command
74
+
75
+ The release command will look for a recent unreleased version in the changelog
76
+ (where the date is marked `????-??-??`) and change it to the current date:
77
+
78
+ ```
79
+ changelog release
80
+ ```
81
+
82
+ If the tool detects a `package.json` file in the current directory, it will
83
+ also call:
84
+
85
+ ```
86
+ npm version [version] --no-git-tag-version
87
+ ```
88
+
89
+ This command adjust the `version` field in `package.json` to match the latest
90
+ changelog version.
package/test/parse.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import { test } from 'node:test';
2
3
  import { parse } from '../parse.mjs';
3
4
  import * as assert from 'node:assert';
package/tsconfig.json CHANGED
@@ -7,7 +7,6 @@
7
7
  "checkJs": true,
8
8
 
9
9
  "moduleResolution": "node",
10
- "resolveJsonModule": true,
11
10
 
12
11
  "noEmit": true,
13
12
  "strict": true,
package/util.mjs CHANGED
@@ -62,7 +62,7 @@ export function wrap(input, secondLineOffset = 0, lineLength = 79) {
62
62
  }
63
63
 
64
64
  const maxLength = lines.length > 1 ? lineLength - secondLineOffset : lineLength;
65
-
65
+
66
66
  const potentialNewLine = [lines.at(-1),word].join(' ');
67
67
  if (potentialNewLine.length>maxLength) {
68
68
  lines.push(word);
@@ -74,3 +74,37 @@ export function wrap(input, secondLineOffset = 0, lineLength = 79) {
74
74
  return lines.join('\n' + ' '.repeat(secondLineOffset));
75
75
 
76
76
  }
77
+
78
+ /**
79
+ * @param {string} prevVersion
80
+ * @param {'patch'|'minor'|'major'} changeType
81
+ * @returns {string}
82
+ */
83
+ export function calculateNextVersion(prevVersion, changeType = 'patch') {
84
+
85
+ // This function only currently understands 1 format, but this may change
86
+ // in the future.
87
+ if (!prevVersion.match(/^[0-9]+\.[0-9]+\.[0-9]+$/)) {
88
+ throw new Error(`Could not automatically determine the next ${changeType} version from ${prevVersion}. You might want to request a new feature to support this`);
89
+ }
90
+
91
+ const parts = prevVersion.split('.').map( part => +part);
92
+
93
+ switch(changeType) {
94
+ case 'major' :
95
+ parts[0]++;
96
+ parts[1]=0;
97
+ parts[2]=0;
98
+ break;
99
+ case 'minor' :
100
+ parts[1]++;
101
+ parts[2]=0;
102
+ break;
103
+ case 'patch' :
104
+ parts[2]++;
105
+ break;
106
+ }
107
+
108
+ return parts.join('.');
109
+
110
+ }