changelog-tool 0.4.1 → 0.6.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/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
+ }