@versatiles/release-tool 2.0.0 → 2.2.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
@@ -5,12 +5,12 @@
5
5
 
6
6
  Tools used for:
7
7
 
8
- * creating a graph of the source code as mermaid: [`vrt deps-graph`](#subcommand-vrt-deps-graph)
9
- * upgrading all package dependencies: [`vrt deps-upgrade`](#subcommand-vrt-deps-upgrade)
10
- * creating Markdown documentation of executables: [`vrt doc-command`](#subcommand-vrt-doc-command)
11
- * inserting Markdown into documents: [`vrt doc-insert`](#subcommand-vrt-doc-insert)
12
- * updating "Table of Content" in Markdown files: [`vrt doc-toc`](#subcommand-vrt-doc-toc)
13
- * releasing the project as npm package: [`vrt release-npm`](#subcommand-vrt-release-npm)
8
+ - creating a graph of the source code as mermaid: [`vrt deps-graph`](#subcommand-vrt-deps-graph)
9
+ - upgrading all package dependencies: [`vrt deps-upgrade`](#subcommand-vrt-deps-upgrade)
10
+ - creating Markdown documentation of executables: [`vrt doc-command`](#subcommand-vrt-doc-command)
11
+ - inserting Markdown into documents: [`vrt doc-insert`](#subcommand-vrt-doc-insert)
12
+ - updating "Table of Content" in Markdown files: [`vrt doc-toc`](#subcommand-vrt-doc-toc)
13
+ - releasing the project as npm package: [`vrt release-npm`](#subcommand-vrt-release-npm)
14
14
 
15
15
  # Installation
16
16
 
@@ -34,9 +34,9 @@ You need to configure the scripts in the package.json:
34
34
  }
35
35
  ```
36
36
 
37
- * `scripts.check` is **required** by the release command. Here you can lint, build and test your code.
38
- * `scripts.prepack` is **recommended** to ensure that all files are up-to-date before releasing. Here you can build code and documentation.
39
- * `scripts.release` is **recommended** to make it easy to release a new version.
37
+ - `scripts.check` is **required** by the release command. Here you can lint, build and test your code.
38
+ - `scripts.prepack` is **recommended** to ensure that all files are up-to-date before releasing. Here you can build code and documentation.
39
+ - `scripts.release` is **recommended** to make it easy to release a new version.
40
40
 
41
41
  # Command `vrt`
42
42
 
@@ -46,19 +46,34 @@ You need to configure the scripts in the package.json:
46
46
  $ vrt
47
47
  Usage: vrt [options] [command]
48
48
 
49
- versatiles release and documentaion tool
49
+ CLI tool for releasing packages and generating documentation for
50
+ Node.js/TypeScript projects.
50
51
 
51
52
  Options:
52
53
  -h, --help display help for command
53
54
 
54
55
  Commands:
55
- deps-graph draws a graph of all files in the project and outputs it as mermaid
56
- deps-upgrade upgrades all dependencies to the latest version
57
- doc-command <command> documents a runnable command and outputs it
58
- doc-insert <readme> [heading] [foldable] takes Markdown from stdin and insert it into a Markdown file
59
- doc-toc <readme> [heading] updates the TOC in a Markdown file
60
- release-npm [path] releases a npm package
56
+ check-package Check package.json for required scripts and other metadata.
57
+ deps-graph Analyze project files and output a dependency graph as Mermaid markup.
58
+ deps-upgrade Upgrade all dependencies in the current project to their latest versions.
59
+ doc-command <command> Generate Markdown documentation for a specified command and output the result.
60
+ doc-insert <readme> [heading] [foldable] Insert Markdown from stdin into a specified section of a Markdown file.
61
+ doc-toc <readme> [heading] Generate a Table of Contents (TOC) in a Markdown file.
62
+ doc-typescript [options] Generate documentation for a TypeScript project.
61
63
  help [command] display help for command
64
+ release-npm [path] Publish an npm package from the specified path to the npm registry.
65
+ ```
66
+
67
+ ## Subcommand: `vrt check-package`
68
+
69
+ ```console
70
+ $ vrt check-package
71
+ Usage: vrt check-package [options]
72
+
73
+ Check package.json for required scripts and other metadata.
74
+
75
+ Options:
76
+ -h, --help display help for command
62
77
  ```
63
78
 
64
79
  ## Subcommand: `vrt deps-graph`
@@ -67,7 +82,7 @@ Commands:
67
82
  $ vrt deps-graph
68
83
  Usage: vrt deps-graph [options]
69
84
 
70
- draws a graph of all files in the project and outputs it as mermaid
85
+ Analyze project files and output a dependency graph as Mermaid markup.
71
86
 
72
87
  Options:
73
88
  -h, --help display help for command
@@ -79,7 +94,7 @@ Options:
79
94
  $ vrt deps-upgrade
80
95
  Usage: vrt deps-upgrade [options]
81
96
 
82
- upgrades all dependencies to the latest version
97
+ Upgrade all dependencies in the current project to their latest versions.
83
98
 
84
99
  Options:
85
100
  -h, --help display help for command
@@ -91,10 +106,10 @@ Options:
91
106
  $ vrt doc-command
92
107
  Usage: vrt doc-command [options] <command>
93
108
 
94
- documents a runnable command and outputs it
109
+ Generate Markdown documentation for a specified command and output the result.
95
110
 
96
111
  Arguments:
97
- command command to run
112
+ command Command to document (e.g., "npm run build").
98
113
 
99
114
  Options:
100
115
  -h, --help display help for command
@@ -106,12 +121,14 @@ Options:
106
121
  $ vrt doc-insert
107
122
  Usage: vrt doc-insert [options] <readme> [heading] [foldable]
108
123
 
109
- takes Markdown from stdin and insert it into a Markdown file
124
+ Insert Markdown from stdin into a specified section of a Markdown file.
110
125
 
111
126
  Arguments:
112
- readme Markdown file, like a readme.md
113
- heading Heading in the Markdown file (default: "# API")
114
- foldable Make content foldable (default: false)
127
+ readme Path to the target Markdown file (e.g., README.md).
128
+ heading Heading in the Markdown file where content should be placed.
129
+ Default is "# API". (default: "# API")
130
+ foldable Whether to wrap the inserted content in a foldable section.
131
+ (default: false)
115
132
 
116
133
  Options:
117
134
  -h, --help display help for command
@@ -123,26 +140,46 @@ Options:
123
140
  $ vrt doc-toc
124
141
  Usage: vrt doc-toc [options] <readme> [heading]
125
142
 
126
- updates the TOC in a Markdown file
143
+ Generate a Table of Contents (TOC) in a Markdown file.
127
144
 
128
145
  Arguments:
129
- readme Markdown file, like a readme.md
130
- heading Heading in the Markdown file (default: "# Table of Content")
146
+ readme Path to the Markdown file (e.g., README.md).
147
+ heading Heading in the Markdown file where TOC should be inserted. Default
148
+ is "# Table of Content". (default: "# Table of Content")
131
149
 
132
150
  Options:
133
151
  -h, --help display help for command
134
152
  ```
135
153
 
154
+ ## Subcommand: `vrt doc-typescript`
155
+
156
+ ```console
157
+ $ vrt doc-typescript
158
+ Usage: vrt doc-typescript [options]
159
+
160
+ Generate documentation for a TypeScript project.
161
+
162
+ Options:
163
+ -f, --format <format> Allowed are "markdown", "wiki" and "html". Default
164
+ is "markdown".
165
+ -h, --help display help for command
166
+ -i, --input <entryPoint> Entry point of the TypeScript project. Default is
167
+ "./src/index.ts".
168
+ -o, --output <outputPath> Output path for the generated documentation.
169
+ Default is "./docs".
170
+ ```
171
+
136
172
  ## Subcommand: `vrt release-npm`
137
173
 
138
174
  ```console
139
175
  $ vrt release-npm
140
176
  Usage: vrt release-npm [options] [path]
141
177
 
142
- releases a npm package
178
+ Publish an npm package from the specified path to the npm registry.
143
179
 
144
180
  Arguments:
145
- path root path of the Node.js project
181
+ path Root path of the Node.js project. Defaults to the current
182
+ directory.
146
183
 
147
184
  Options:
148
185
  -h, --help display help for command
@@ -159,32 +196,38 @@ flowchart TB
159
196
 
160
197
  subgraph 0["src"]
161
198
  subgraph 1["commands"]
162
- 2["command.ts"]
163
- 5["dependency-graph.ts"]
164
- 7["markdown.ts"]
165
- 8["release.ts"]
166
- B["upgrade-dependencies.ts"]
199
+ 2["check-package.ts"]
200
+ 5["deps-graph.ts"]
201
+ 6["deps-upgrade.ts"]
202
+ 8["doc-command.ts"]
203
+ A["doc-typescript.ts"]
204
+ B["markdown.ts"]
205
+ C["release-npm.ts"]
167
206
  end
168
207
  subgraph 3["lib"]
169
- 4["utils.ts"]
170
- 6["log.ts"]
171
- 9["git.ts"]
172
- A["shell.ts"]
208
+ 4["log.ts"]
209
+ 7["shell.ts"]
210
+ 9["utils.ts"]
211
+ D["git.ts"]
173
212
  end
174
- C["index.ts"]
213
+ E["index.ts"]
175
214
  end
176
215
  2-->4
177
- 5-->6
178
- 7-->4
216
+ 5-->4
217
+ 6-->4
218
+ 6-->7
179
219
  8-->9
180
- 8-->6
181
- 8-->A
182
- 9-->A
183
- B-->6
184
- B-->A
185
- C-->2
186
- C-->5
220
+ A-->4
221
+ B-->9
222
+ C-->D
223
+ C-->4
187
224
  C-->7
188
- C-->8
189
- C-->B
225
+ D-->7
226
+ E-->2
227
+ E-->5
228
+ E-->6
229
+ E-->8
230
+ E-->A
231
+ E-->B
232
+ E-->C
190
233
  ```
@@ -0,0 +1 @@
1
+ export declare function checkPackage(directory: string): void;
@@ -0,0 +1,53 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { panic, info, warn } from '../lib/log.js';
3
+ import { resolve } from 'node:path';
4
+ export function checkPackage(directory) {
5
+ const pack = JSON.parse(readFileSync(resolve(directory, 'package.json'), 'utf8'));
6
+ const { scripts } = pack;
7
+ if (!scripts)
8
+ panic('scripts not found');
9
+ if (!scripts.test)
10
+ info('scripts.test is recommended');
11
+ if (!scripts.doc)
12
+ info('scripts.doc is recommended');
13
+ if (!scripts.build)
14
+ panic('scripts.build is required');
15
+ if (!scripts.check)
16
+ panic('scripts.check is required');
17
+ if (!scripts.check.includes('npm run build')) {
18
+ warn(`scripts.check should include "npm run build", but is "${scripts.check}"`);
19
+ }
20
+ if (!scripts.prepack)
21
+ panic('scripts.prepack is required');
22
+ if (scripts.prepack !== 'npm run build') {
23
+ warn(`scripts.prepack should be "npm run build", but is "${scripts.prepack}"`);
24
+ }
25
+ if (!scripts.release)
26
+ panic('scripts.release is required');
27
+ if (scripts.release !== 'vrt release-npm') {
28
+ warn(`scripts.release should be "vrt release-npm", but is "${scripts.release}"`);
29
+ }
30
+ if (!scripts.upgrade) {
31
+ warn('scripts.upgrade is recommended');
32
+ }
33
+ else if (scripts.upgrade !== 'vrt deps-upgrade') {
34
+ info(`scripts.upgrade should be "vrt deps-upgrade", but is "${scripts.upgrade}"`);
35
+ }
36
+ if (!scripts['doc-graph']) {
37
+ info(`scripts.doc-graph could be: "vrt deps-graph | vrt doc-insert README.md '## Dependency Graph'"`);
38
+ }
39
+ else {
40
+ if (scripts.doc && !scripts.doc.includes('npm run doc-graph')) {
41
+ info('scripts.doc should include "npm run doc-graph"');
42
+ }
43
+ }
44
+ ['npm-check-updates'].forEach((dep) => {
45
+ if (pack.dependencies?.[dep]) {
46
+ info(`dependencies "${dep}" is probably not needed`);
47
+ }
48
+ if (pack.devDependencies?.[dep]) {
49
+ info(`devDependencies "${dep}" is probably not needed`);
50
+ }
51
+ });
52
+ }
53
+ //# sourceMappingURL=check-package.js.map
@@ -18,4 +18,4 @@ export async function generateDependencyGraph(directory) {
18
18
  output = output.replace('flowchart LR', 'flowchart TB');
19
19
  process.stdout.write(Buffer.from('```mermaid\n' + output + '```\n'));
20
20
  }
21
- //# sourceMappingURL=dependency-graph.js.map
21
+ //# sourceMappingURL=deps-graph.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Upgrades the dependencies in a package.json file to their latest versions, removes existing
3
+ * installed modules, and reinstalls them in the specified directory.
4
+ *
5
+ * This function performs the following steps:
6
+ * 1. Checks for outdated dependencies by running `npm outdated --all --json`.
7
+ * 2. Reads the project's package.json file and updates any existing dependencies to their latest versions.
8
+ * 3. Removes all installed modules (`node_modules`) and the lock file (`package-lock.json`).
9
+ * 4. Reinstalls and updates all dependencies.
10
+ * 5. Logs a message indicating that all dependencies are up to date.
11
+ *
12
+ * @param directory - The path to the directory containing the Node.js project.
13
+ * @returns A promise that resolves when the process is complete.
14
+ */
15
+ export declare function upgradeDependencies(directory: string): Promise<void>;
@@ -0,0 +1,99 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { check, info } from '../lib/log.js';
3
+ import { getShell } from '../lib/shell.js';
4
+ /**
5
+ * Upgrades the dependencies in a package.json file to their latest versions, removes existing
6
+ * installed modules, and reinstalls them in the specified directory.
7
+ *
8
+ * This function performs the following steps:
9
+ * 1. Checks for outdated dependencies by running `npm outdated --all --json`.
10
+ * 2. Reads the project's package.json file and updates any existing dependencies to their latest versions.
11
+ * 3. Removes all installed modules (`node_modules`) and the lock file (`package-lock.json`).
12
+ * 4. Reinstalls and updates all dependencies.
13
+ * 5. Logs a message indicating that all dependencies are up to date.
14
+ *
15
+ * @param directory - The path to the directory containing the Node.js project.
16
+ * @returns A promise that resolves when the process is complete.
17
+ */
18
+ export async function upgradeDependencies(directory) {
19
+ const shell = getShell(directory);
20
+ // Step 1: Check and upgrade all versions
21
+ await check('Upgrade all versions', async () => {
22
+ const { stdout } = await shell.run('npm outdated --all --json', false);
23
+ const outdated = JSON.parse(stdout);
24
+ const latestVersions = new Map();
25
+ // Collect the latest version for each dependency
26
+ for (const [name, entry] of Object.entries(outdated)) {
27
+ let version = '0.0.0';
28
+ if (Array.isArray(entry)) {
29
+ for (const item of entry) {
30
+ if (isGreaterSemver(item.latest, version))
31
+ version = item.latest;
32
+ }
33
+ }
34
+ else {
35
+ version = entry.latest;
36
+ }
37
+ latestVersions.set(name, version);
38
+ }
39
+ // Load package.json
40
+ const pack = JSON.parse(readFileSync('package.json', 'utf8'));
41
+ // Update dependencies to their latest versions
42
+ patch(pack.dependencies);
43
+ patch(pack.devDependencies);
44
+ patch(pack.optionalDependencies);
45
+ patch(pack.peerDependencies);
46
+ // Write the updated package.json
47
+ writeFileSync('package.json', JSON.stringify(pack, null, 2) + '\n');
48
+ /**
49
+ * Mutates the provided dependency object by updating
50
+ * each dependency to the latest known version (if available).
51
+ *
52
+ * @param dependencies - A mapping of dependency names to their currently specified versions.
53
+ */
54
+ function patch(dependencies) {
55
+ if (!dependencies)
56
+ return;
57
+ for (const name of Object.keys(dependencies)) {
58
+ const version = latestVersions.get(name);
59
+ if (version)
60
+ dependencies[name] = '^' + version;
61
+ }
62
+ }
63
+ });
64
+ // Step 2: Remove existing dependencies and lock file
65
+ await check('Remove all dependencies', async () => {
66
+ await shell.run('rm -rf node_modules');
67
+ await shell.run('rm -f package-lock.json');
68
+ });
69
+ // Step 3: Reinstall/upgrade all dependencies
70
+ await check('Upgrade all dependencies', shell.stdout('npm update --save'));
71
+ // Final log message
72
+ info('All dependencies are up to date');
73
+ }
74
+ /**
75
+ * Compares two semantic version strings (major.minor.patch) and checks if `a` is greater than `b`.
76
+ *
77
+ * @param a - A semantic version string (e.g., "1.2.3").
78
+ * @param b - Another semantic version string (e.g., "1.2.4").
79
+ * @returns `true` if `a` is greater than `b`, otherwise `false`.
80
+ * @throws If either version string is invalid (i.e., not in "x.x.x" format).
81
+ */
82
+ function isGreaterSemver(a, b) {
83
+ const pa = a.split('.');
84
+ const pb = b.split('.');
85
+ for (let i = 0; i < 3; i++) {
86
+ const na = Number(pa[i]);
87
+ const nb = Number(pb[i]);
88
+ if (isNaN(na))
89
+ throw new Error('Invalid version number: ' + a);
90
+ if (isNaN(nb))
91
+ throw new Error('Invalid version number: ' + b);
92
+ if (na > nb)
93
+ return true;
94
+ if (na < nb)
95
+ return false;
96
+ }
97
+ return false;
98
+ }
99
+ //# sourceMappingURL=deps-upgrade.js.map
@@ -31,7 +31,13 @@ export async function generateCommandDocumentation(command) {
31
31
  */
32
32
  async function getCommandResults(command) {
33
33
  return new Promise((resolve, reject) => {
34
- const env = { ...process.env, NODE_ENV: undefined };
34
+ const env = {
35
+ ...process.env,
36
+ NODE_ENV: undefined,
37
+ NODE_DISABLE_COLORS: '1',
38
+ NO_COLORS: '1',
39
+ FORCE_COLOR: '0'
40
+ };
35
41
  // Spawn a child process to run the command with the '--help' flag.
36
42
  const childProcess = cp.spawn('npx', [...command.split(' '), '--help'], { env });
37
43
  let output = '';
@@ -81,4 +87,4 @@ function extractSubcommands(result) {
81
87
  return [subcommand];
82
88
  });
83
89
  }
84
- //# sourceMappingURL=command.js.map
90
+ //# sourceMappingURL=doc-command.js.map
@@ -0,0 +1,6 @@
1
+ export declare function generateTypescriptDocs(options: {
2
+ entryPoint?: string;
3
+ outputPath?: string;
4
+ format?: 'markdown' | 'wiki' | 'html';
5
+ quiet?: boolean;
6
+ }): Promise<void>;
@@ -0,0 +1,49 @@
1
+ import * as td from 'typedoc';
2
+ import { panic, warn } from '../lib/log.js';
3
+ export async function generateTypescriptDocs(options) {
4
+ const { entryPoint, outputPath, quiet } = options;
5
+ const format = options.format ?? 'markdown';
6
+ const isMarkdown = format !== 'html';
7
+ const plugin = [
8
+ isMarkdown && 'typedoc-plugin-markdown',
9
+ format === 'wiki' && 'typedoc-github-wiki-theme',
10
+ format === 'html' && 'typedoc-unhoax-theme',
11
+ ].filter(Boolean);
12
+ const app = await td.Application.bootstrapWithPlugins({
13
+ entryPoints: [entryPoint ?? './src/index.ts'],
14
+ gitRevision: 'main',
15
+ out: outputPath ?? './docs',
16
+ plugin,
17
+ logLevel: quiet ? 'Warn' : 'Info',
18
+ }, [
19
+ new td.TypeDocReader(),
20
+ new td.PackageJsonReader(),
21
+ new td.TSConfigReader(),
22
+ ]);
23
+ app.options.setValue('readme', 'none');
24
+ if (isMarkdown) {
25
+ app.options.setValue('hidePageHeader', true);
26
+ app.options.setValue('classPropertiesFormat', 'table');
27
+ app.options.setValue('enumMembersFormat', 'table');
28
+ app.options.setValue('indexFormat', 'table');
29
+ app.options.setValue('interfacePropertiesFormat', 'table');
30
+ app.options.setValue('parametersFormat', 'table');
31
+ app.options.setValue('propertiesFormat', 'table');
32
+ app.options.setValue('propertyMembersFormat', 'table');
33
+ app.options.setValue('typeDeclarationFormat', 'table');
34
+ }
35
+ const project = await app.convert();
36
+ if (!project)
37
+ panic('Failed to convert project');
38
+ app.validate(project);
39
+ if (app.logger.hasWarnings())
40
+ warn('Warnings found during validation');
41
+ if (app.logger.hasErrors())
42
+ panic('Errors found during validation');
43
+ await app.generateOutputs(project);
44
+ if (app.logger.hasWarnings())
45
+ warn('Warnings found during validation');
46
+ if (app.logger.hasErrors())
47
+ panic('Errors found during validation');
48
+ }
49
+ //# sourceMappingURL=doc-typescript.js.map
@@ -1,5 +1,6 @@
1
1
  import { remark } from 'remark';
2
2
  import remarkGfm from 'remark-gfm';
3
+ import remarkStringify from 'remark-stringify';
3
4
  import { getErrorMessage } from '../lib/utils.js';
4
5
  /**
5
6
  * Injects a Markdown segment under a specified heading in a Markdown document.
@@ -37,7 +38,16 @@ export function injectMarkdown(document, segment, heading, foldable) {
37
38
  // Merge the original document AST with the new segment AST.
38
39
  mergeSegments(documentAst, segmentAst, startIndex + 1, endIndex);
39
40
  // Convert the modified AST back to a Markdown string and return.
40
- return remark().stringify(documentAst);
41
+ const result = remark()
42
+ .use(remarkGfm, {
43
+ tableCellPadding: true,
44
+ })
45
+ .use(remarkStringify, {
46
+ bullet: '-',
47
+ rule: '-',
48
+ })
49
+ .stringify(documentAst);
50
+ return result;
41
51
  }
42
52
  /**
43
53
  * Updates the Table of Contents (TOC) of a Markdown document.
@@ -126,4 +126,4 @@ export async function release(directory, branch = 'main') {
126
126
  }
127
127
  }
128
128
  }
129
- //# sourceMappingURL=release.js.map
129
+ //# sourceMappingURL=release-npm.js.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env -S node --enable-source-maps
2
2
  import { Command } from 'commander';
3
+ /**
4
+ * Main CLI program, configured with custom text styling for titles, commands, options, etc.
5
+ */
3
6
  export declare const program: Command;
package/dist/index.js CHANGED
@@ -1,70 +1,141 @@
1
1
  #!/usr/bin/env -S node --enable-source-maps
2
2
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { resolve } from 'node:path';
4
+ import { styleText } from 'node:util';
4
5
  import { injectMarkdown, updateTOC } from './commands/markdown.js';
5
6
  import { Command, InvalidArgumentError } from 'commander';
6
7
  import { cwd } from 'node:process';
7
- import { generateCommandDocumentation } from './commands/command.js';
8
- import { release } from './commands/release.js';
9
- import { upgradeDependencies } from './commands/upgrade-dependencies.js';
10
- import { generateDependencyGraph } from './commands/dependency-graph.js';
8
+ import { generateCommandDocumentation } from './commands/doc-command.js';
9
+ import { release } from './commands/release-npm.js';
10
+ import { upgradeDependencies } from './commands/deps-upgrade.js';
11
+ import { generateDependencyGraph } from './commands/deps-graph.js';
12
+ import { checkPackage } from './commands/check-package.js';
13
+ import { generateTypescriptDocs } from './commands/doc-typescript.js';
14
+ /**
15
+ * Main CLI program, configured with custom text styling for titles, commands, options, etc.
16
+ */
11
17
  export const program = new Command();
18
+ program.configureHelp({
19
+ styleTitle: (str) => styleText('bold', str),
20
+ styleCommandText: (str) => styleText('bold', str),
21
+ styleOptionText: (str) => styleText('cyan', str),
22
+ styleArgumentText: (str) => styleText('green', str),
23
+ styleSubcommandText: (str) => styleText('yellow', str),
24
+ sortOptions: true,
25
+ sortSubcommands: true,
26
+ });
12
27
  program
13
28
  .name('vrt')
14
- .description('versatiles release and documentaion tool');
29
+ .description('CLI tool for releasing packages and generating documentation for Node.js/TypeScript projects.');
30
+ /**
31
+ * Command: check-package
32
+ * Checks that the project's package.json includes certain required scripts/fields.
33
+ */
34
+ program.command('check-package')
35
+ .description('Check package.json for required scripts and other metadata.')
36
+ .action(() => {
37
+ void checkPackage(process.cwd());
38
+ });
39
+ /**
40
+ * Command: deps-graph
41
+ * Analyzes the project’s files to produce a dependency graph (in Mermaid format).
42
+ */
15
43
  program.command('deps-graph')
16
- .description('draws a graph of all files in the project and outputs it as mermaid')
44
+ .description('Analyze project files and output a dependency graph as Mermaid markup.')
17
45
  .action(() => {
18
46
  void generateDependencyGraph(process.cwd());
19
47
  });
48
+ /**
49
+ * Command: deps-upgrade
50
+ * Upgrades project dependencies in package.json to their latest versions and reinstalls them.
51
+ */
20
52
  program.command('deps-upgrade')
21
- .description('upgrades all dependencies to the latest version')
53
+ .description('Upgrade all dependencies in the current project to their latest versions.')
22
54
  .action(() => {
23
55
  void upgradeDependencies(process.cwd());
24
56
  });
57
+ /**
58
+ * Command: doc-command
59
+ * Generates Markdown documentation for a given CLI command.
60
+ */
25
61
  program.command('doc-command')
26
- .description('documents a runnable command and outputs it')
27
- .argument('<command>', 'command to run')
62
+ .description('Generate Markdown documentation for a specified command and output the result.')
63
+ .argument('<command>', 'Command to document (e.g., "npm run build").')
28
64
  .action(async (command) => {
29
65
  const mdDocumentation = await generateCommandDocumentation(command);
30
66
  process.stdout.write(mdDocumentation);
31
67
  });
68
+ /**
69
+ * Command: doc-insert
70
+ * Inserts Markdown content from stdin into a specified Markdown file under a given heading.
71
+ * Optionally makes the inserted content foldable.
72
+ */
32
73
  program.command('doc-insert')
33
- .description('takes Markdown from stdin and insert it into a Markdown file')
34
- .argument('<readme>', 'Markdown file, like a readme.md', checkFilename)
35
- .argument('[heading]', 'Heading in the Markdown file', '# API')
36
- .argument('[foldable]', 'Make content foldable', false)
74
+ .description('Insert Markdown from stdin into a specified section of a Markdown file.')
75
+ .argument('<readme>', 'Path to the target Markdown file (e.g., README.md).', checkFilename)
76
+ .argument('[heading]', 'Heading in the Markdown file where content should be placed. Default is "# API".', '# API')
77
+ .argument('[foldable]', 'Whether to wrap the inserted content in a foldable section.', false)
37
78
  .action(async (mdFilename, heading, foldable) => {
38
79
  const buffers = [];
39
- for await (const data of process.stdin)
80
+ for await (const data of process.stdin) {
40
81
  buffers.push(data);
41
- const mdContent = '<!--- This chapter is generated automatically --->\n' + Buffer.concat(buffers).toString();
82
+ }
83
+ const mdContent = '<!--- This chapter is generated automatically --->\n'
84
+ + Buffer.concat(buffers).toString();
42
85
  let mdFile = readFileSync(mdFilename, 'utf8');
43
86
  mdFile = injectMarkdown(mdFile, mdContent, heading, foldable);
44
87
  writeFileSync(mdFilename, mdFile);
45
88
  });
89
+ /**
90
+ * Command: doc-toc
91
+ * Updates or generates a Table of Contents in a Markdown file under a specified heading.
92
+ */
46
93
  program.command('doc-toc')
47
- .description('updates the TOC in a Markdown file')
48
- .argument('<readme>', 'Markdown file, like a readme.md', checkFilename)
49
- .argument('[heading]', 'Heading in the Markdown file', '# Table of Content')
94
+ .description('Generate a Table of Contents (TOC) in a Markdown file.')
95
+ .argument('<readme>', 'Path to the Markdown file (e.g., README.md).', checkFilename)
96
+ .argument('[heading]', 'Heading in the Markdown file where TOC should be inserted. Default is "# Table of Content".', '# Table of Content')
50
97
  .action((mdFilename, heading) => {
51
98
  let mdFile = readFileSync(mdFilename, 'utf8');
52
99
  mdFile = updateTOC(mdFile, heading);
53
100
  writeFileSync(mdFilename, mdFile);
54
101
  });
102
+ /**
103
+ * Command: doc-typescript
104
+ * Generates documentation for a TypeScript project.
105
+ * Allows specifying entry point and output location.
106
+ */
107
+ program.command('doc-typescript')
108
+ .description('Generate documentation for a TypeScript project.')
109
+ .option('-i, --input <entryPoint>', 'Entry point of the TypeScript project. Default is "./src/index.ts".')
110
+ .option('-o, --output <outputPath>', 'Output path for the generated documentation. Default is "./docs".')
111
+ .option('-f, --format <format>', 'Allowed are "markdown", "wiki" and "html". Default is "markdown".')
112
+ .action(async (options) => {
113
+ await generateTypescriptDocs(options);
114
+ });
115
+ /**
116
+ * Command: release-npm
117
+ * Releases/publishes an npm package from a specified project path to the npm registry.
118
+ */
55
119
  program.command('release-npm')
56
- .description('releases a npm package')
57
- .argument('[path]', 'root path of the Node.js project')
120
+ .description('Publish an npm package from the specified path to the npm registry.')
121
+ .argument('[path]', 'Root path of the Node.js project. Defaults to the current directory.')
58
122
  .action((path) => {
59
123
  void release(resolve(path ?? '.', process.cwd()), 'main');
60
124
  });
61
125
  if (process.env.NODE_ENV !== 'test') {
62
126
  await program.parseAsync();
63
127
  }
128
+ /**
129
+ * Validates that the given filename exists.
130
+ * Throws an InvalidArgumentError if the file cannot be found.
131
+ *
132
+ * @param filename - The filename to check.
133
+ * @returns The resolved full path if the file exists.
134
+ */
64
135
  function checkFilename(filename) {
65
136
  const fullname = resolve(cwd(), filename);
66
137
  if (!existsSync(fullname)) {
67
- throw new InvalidArgumentError('file not found');
138
+ throw new InvalidArgumentError(`File not found: ${filename}`);
68
139
  }
69
140
  return fullname;
70
141
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versatiles/release-tool",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "VersaTiles release and documentation tools",
5
5
  "bin": {
6
6
  "vrt": "./dist/index.js"
@@ -10,7 +10,8 @@
10
10
  "dist/**/*.d.ts"
11
11
  ],
12
12
  "scripts": {
13
- "build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/index.js && npm run doc",
13
+ "build": "npm run build-node && npm run doc",
14
+ "build-node": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/index.js",
14
15
  "check": "npm run lint && npm run build && npm run test",
15
16
  "dev": "tsx src/index.ts",
16
17
  "doc": "npm run doc-command && npm run doc-graph",
@@ -18,7 +19,7 @@
18
19
  "doc-graph": "tsx src/index.ts deps-graph | tsx src/index.ts doc-insert README.md '## Dependency Graph'",
19
20
  "lint": "eslint . --color",
20
21
  "prepack": "npm run build",
21
- "release": "npm run build && tsx src/index.ts release-npm",
22
+ "release": "tsx src/index.ts release-npm",
22
23
  "test-coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
23
24
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
24
25
  "upgrade": "tsx src/index.ts deps-upgrade"
@@ -32,6 +33,7 @@
32
33
  },
33
34
  "homepage": "https://github.com/versatiles-org/node-release-tool",
34
35
  "devDependencies": {
36
+ "@schemastore/package": "^0.0.10",
35
37
  "@types/jest": "^29.5.14",
36
38
  "@types/node": "^22.13.5",
37
39
  "@typescript-eslint/eslint-plugin": "^8.22.0",
@@ -48,6 +50,10 @@
48
50
  "commander": "^13.1.0",
49
51
  "dependency-cruiser": "^16.10.0",
50
52
  "remark": "^15.0.1",
51
- "remark-gfm": "^4.0.1"
53
+ "remark-gfm": "^4.0.1",
54
+ "typedoc": "^0.27.8",
55
+ "typedoc-github-wiki-theme": "^2.1.0",
56
+ "typedoc-plugin-markdown": "^4.4.2",
57
+ "typedoc-unhoax-theme": "^0.4.6"
52
58
  }
53
59
  }
@@ -1 +0,0 @@
1
- export declare function upgradeDependencies(directory: string): Promise<void>;
@@ -1,12 +0,0 @@
1
- import { check, info } from '../lib/log.js';
2
- import { getShell } from '../lib/shell.js';
3
- export async function upgradeDependencies(directory) {
4
- const shell = getShell(directory);
5
- await check('Remove all dependencies', async () => {
6
- await shell.run('rm -rf node_modules');
7
- await shell.run('rm -f package-lock.json');
8
- });
9
- await check('Upgrade all dependencies', shell.stdout('npm update --save'));
10
- info('All dependencies are up to date');
11
- }
12
- //# sourceMappingURL=upgrade-dependencies.js.map