@versatiles/release-tool 1.2.7 → 2.1.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/LICENSE +20 -17
- package/README.md +133 -43
- package/dist/commands/check-package.d.ts +1 -0
- package/dist/commands/check-package.js +53 -0
- package/dist/commands/deps-graph.d.ts +1 -0
- package/dist/commands/deps-graph.js +21 -0
- package/dist/commands/deps-upgrade.d.ts +15 -0
- package/dist/commands/deps-upgrade.js +97 -0
- package/dist/commands/{command.js → doc-command.js} +8 -2
- package/dist/commands/doc-typescript.d.ts +4 -0
- package/dist/commands/doc-typescript.js +43 -0
- package/dist/commands/{release.js → release-npm.js} +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +102 -29
- package/dist/lib/log.d.ts +1 -1
- package/dist/lib/log.js +2 -2
- package/package.json +24 -19
- package/LICENSE.md +0 -24
- package/dist/commands/typedoc.d.ts +0 -6
- package/dist/commands/typedoc.js +0 -282
- /package/dist/commands/{command.d.ts → doc-command.d.ts} +0 -0
- /package/dist/commands/{release.d.ts → release-npm.d.ts} +0 -0
package/LICENSE
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
of this software
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
24
|
+
For more information, please refer to [unlicense.org](https://unlicense.org/)
|
package/README.md
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
# VersaTiles Release Tools
|
|
5
5
|
|
|
6
|
-
Tools used
|
|
6
|
+
Tools used for:
|
|
7
7
|
|
|
8
|
-
* creating
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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)
|
|
13
14
|
|
|
14
15
|
# Installation
|
|
15
16
|
|
|
@@ -37,8 +38,6 @@ You need to configure the scripts in the package.json:
|
|
|
37
38
|
* `scripts.prepack` is **recommended** to ensure that all files are up-to-date before releasing. Here you can build code and documentation.
|
|
38
39
|
* `scripts.release` is **recommended** to make it easy to release a new version.
|
|
39
40
|
|
|
40
|
-
Have a look at this [package.json](https://github.com/versatiles-org/node-release-tool/blob/main/package.json) as an example.
|
|
41
|
-
|
|
42
41
|
# Command `vrt`
|
|
43
42
|
|
|
44
43
|
<!--- This chapter is generated automatically --->
|
|
@@ -47,95 +46,186 @@ Have a look at this [package.json](https://github.com/versatiles-org/node-releas
|
|
|
47
46
|
$ vrt
|
|
48
47
|
Usage: vrt [options] [command]
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
CLI tool for releasing packages and generating documentation for
|
|
50
|
+
Node.js/TypeScript projects.
|
|
51
51
|
|
|
52
52
|
Options:
|
|
53
|
-
-h, --help
|
|
53
|
+
-h, --help display help for command
|
|
54
54
|
|
|
55
55
|
Commands:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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.
|
|
63
|
+
help [command] display help for command
|
|
64
|
+
release-npm [path] Publish an npm package from the specified path to the npm registry.
|
|
62
65
|
```
|
|
63
66
|
|
|
64
|
-
## Subcommand: `vrt
|
|
67
|
+
## Subcommand: `vrt check-package`
|
|
65
68
|
|
|
66
69
|
```console
|
|
67
|
-
$ vrt
|
|
68
|
-
Usage: vrt
|
|
70
|
+
$ vrt check-package
|
|
71
|
+
Usage: vrt check-package [options]
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
Check package.json for required scripts and other metadata.
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
Options:
|
|
76
|
+
-h, --help display help for command
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Subcommand: `vrt deps-graph`
|
|
80
|
+
|
|
81
|
+
```console
|
|
82
|
+
$ vrt deps-graph
|
|
83
|
+
Usage: vrt deps-graph [options]
|
|
84
|
+
|
|
85
|
+
Analyze project files and output a dependency graph as Mermaid markup.
|
|
86
|
+
|
|
87
|
+
Options:
|
|
88
|
+
-h, --help display help for command
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Subcommand: `vrt deps-upgrade`
|
|
92
|
+
|
|
93
|
+
```console
|
|
94
|
+
$ vrt deps-upgrade
|
|
95
|
+
Usage: vrt deps-upgrade [options]
|
|
96
|
+
|
|
97
|
+
Upgrade all dependencies in the current project to their latest versions.
|
|
75
98
|
|
|
76
99
|
Options:
|
|
77
100
|
-h, --help display help for command
|
|
78
101
|
```
|
|
79
102
|
|
|
80
|
-
## Subcommand: `vrt
|
|
103
|
+
## Subcommand: `vrt doc-command`
|
|
81
104
|
|
|
82
105
|
```console
|
|
83
|
-
$ vrt
|
|
84
|
-
Usage: vrt
|
|
106
|
+
$ vrt doc-command
|
|
107
|
+
Usage: vrt doc-command [options] <command>
|
|
85
108
|
|
|
86
|
-
|
|
109
|
+
Generate Markdown documentation for a specified command and output the result.
|
|
87
110
|
|
|
88
111
|
Arguments:
|
|
89
|
-
command
|
|
112
|
+
command Command to document (e.g., "npm run build").
|
|
90
113
|
|
|
91
114
|
Options:
|
|
92
115
|
-h, --help display help for command
|
|
93
116
|
```
|
|
94
117
|
|
|
95
|
-
## Subcommand: `vrt
|
|
118
|
+
## Subcommand: `vrt doc-insert`
|
|
96
119
|
|
|
97
120
|
```console
|
|
98
|
-
$ vrt
|
|
99
|
-
Usage: vrt
|
|
121
|
+
$ vrt doc-insert
|
|
122
|
+
Usage: vrt doc-insert [options] <readme> [heading] [foldable]
|
|
100
123
|
|
|
101
|
-
|
|
124
|
+
Insert Markdown from stdin into a specified section of a Markdown file.
|
|
102
125
|
|
|
103
126
|
Arguments:
|
|
104
|
-
readme Markdown file
|
|
105
|
-
heading Heading in the Markdown file
|
|
106
|
-
|
|
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)
|
|
107
132
|
|
|
108
133
|
Options:
|
|
109
134
|
-h, --help display help for command
|
|
110
135
|
```
|
|
111
136
|
|
|
112
|
-
## Subcommand: `vrt
|
|
137
|
+
## Subcommand: `vrt doc-toc`
|
|
113
138
|
|
|
114
139
|
```console
|
|
115
|
-
$ vrt
|
|
116
|
-
Usage: vrt
|
|
140
|
+
$ vrt doc-toc
|
|
141
|
+
Usage: vrt doc-toc [options] <readme> [heading]
|
|
117
142
|
|
|
118
|
-
|
|
143
|
+
Generate a Table of Contents (TOC) in a Markdown file.
|
|
119
144
|
|
|
120
145
|
Arguments:
|
|
121
|
-
readme Markdown file
|
|
122
|
-
heading Heading in the Markdown file
|
|
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")
|
|
123
149
|
|
|
124
150
|
Options:
|
|
125
151
|
-h, --help display help for command
|
|
126
152
|
```
|
|
127
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
|
+
-h, --help display help for command
|
|
164
|
+
-i <entryPoint> Entry point of the TypeScript project. Default is
|
|
165
|
+
"./src/index.ts".
|
|
166
|
+
-o <outputPath> Output path for the generated documentation. Default is
|
|
167
|
+
"./docs".
|
|
168
|
+
```
|
|
169
|
+
|
|
128
170
|
## Subcommand: `vrt release-npm`
|
|
129
171
|
|
|
130
172
|
```console
|
|
131
173
|
$ vrt release-npm
|
|
132
174
|
Usage: vrt release-npm [options] [path]
|
|
133
175
|
|
|
134
|
-
|
|
176
|
+
Publish an npm package from the specified path to the npm registry.
|
|
135
177
|
|
|
136
178
|
Arguments:
|
|
137
|
-
path
|
|
179
|
+
path Root path of the Node.js project. Defaults to the current
|
|
180
|
+
directory.
|
|
138
181
|
|
|
139
182
|
Options:
|
|
140
183
|
-h, --help display help for command
|
|
141
184
|
```
|
|
185
|
+
|
|
186
|
+
# Development
|
|
187
|
+
|
|
188
|
+
## Dependency Graph
|
|
189
|
+
|
|
190
|
+
<!--- This chapter is generated automatically --->
|
|
191
|
+
|
|
192
|
+
```mermaid
|
|
193
|
+
flowchart TB
|
|
194
|
+
|
|
195
|
+
subgraph 0["src"]
|
|
196
|
+
subgraph 1["commands"]
|
|
197
|
+
2["check-package.ts"]
|
|
198
|
+
5["deps-graph.ts"]
|
|
199
|
+
6["deps-upgrade.ts"]
|
|
200
|
+
8["doc-command.ts"]
|
|
201
|
+
A["doc-typescript.ts"]
|
|
202
|
+
B["markdown.ts"]
|
|
203
|
+
C["release-npm.ts"]
|
|
204
|
+
end
|
|
205
|
+
subgraph 3["lib"]
|
|
206
|
+
4["log.ts"]
|
|
207
|
+
7["shell.ts"]
|
|
208
|
+
9["utils.ts"]
|
|
209
|
+
D["git.ts"]
|
|
210
|
+
end
|
|
211
|
+
E["index.ts"]
|
|
212
|
+
end
|
|
213
|
+
2-->4
|
|
214
|
+
5-->4
|
|
215
|
+
6-->4
|
|
216
|
+
6-->7
|
|
217
|
+
8-->9
|
|
218
|
+
A-->4
|
|
219
|
+
B-->9
|
|
220
|
+
C-->D
|
|
221
|
+
C-->4
|
|
222
|
+
C-->7
|
|
223
|
+
D-->7
|
|
224
|
+
E-->2
|
|
225
|
+
E-->5
|
|
226
|
+
E-->6
|
|
227
|
+
E-->8
|
|
228
|
+
E-->A
|
|
229
|
+
E-->B
|
|
230
|
+
E-->C
|
|
231
|
+
```
|
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateDependencyGraph(directory: string): Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { cruise } from 'dependency-cruiser';
|
|
2
|
+
import { panic } from '../lib/log.js';
|
|
3
|
+
export async function generateDependencyGraph(directory) {
|
|
4
|
+
let cruiseResult;
|
|
5
|
+
try {
|
|
6
|
+
cruiseResult = await cruise([directory], {
|
|
7
|
+
includeOnly: '^src',
|
|
8
|
+
outputType: 'mermaid',
|
|
9
|
+
exclude: ["\\.(test|d)\\.ts$", "node_modules"],
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
catch (pError) {
|
|
13
|
+
panic(String(pError));
|
|
14
|
+
}
|
|
15
|
+
let { output } = cruiseResult;
|
|
16
|
+
if (typeof output !== 'string')
|
|
17
|
+
panic('no output');
|
|
18
|
+
output = output.replace('flowchart LR', 'flowchart TB');
|
|
19
|
+
process.stdout.write(Buffer.from('```mermaid\n' + output + '```\n'));
|
|
20
|
+
}
|
|
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,97 @@
|
|
|
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 latestVersion = 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
|
+
latestVersion.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
|
+
dependencies[name] = latestVersion.get(name) ?? dependencies[name];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// Step 2: Remove existing dependencies and lock file
|
|
63
|
+
await check('Remove all dependencies', async () => {
|
|
64
|
+
await shell.run('rm -rf node_modules');
|
|
65
|
+
await shell.run('rm -f package-lock.json');
|
|
66
|
+
});
|
|
67
|
+
// Step 3: Reinstall/upgrade all dependencies
|
|
68
|
+
await check('Upgrade all dependencies', shell.stdout('npm update --save'));
|
|
69
|
+
// Final log message
|
|
70
|
+
info('All dependencies are up to date');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Compares two semantic version strings (major.minor.patch) and checks if `a` is greater than `b`.
|
|
74
|
+
*
|
|
75
|
+
* @param a - A semantic version string (e.g., "1.2.3").
|
|
76
|
+
* @param b - Another semantic version string (e.g., "1.2.4").
|
|
77
|
+
* @returns `true` if `a` is greater than `b`, otherwise `false`.
|
|
78
|
+
* @throws If either version string is invalid (i.e., not in "x.x.x" format).
|
|
79
|
+
*/
|
|
80
|
+
function isGreaterSemver(a, b) {
|
|
81
|
+
const pa = a.split('.');
|
|
82
|
+
const pb = b.split('.');
|
|
83
|
+
for (let i = 0; i < 3; i++) {
|
|
84
|
+
const na = Number(pa[i]);
|
|
85
|
+
const nb = Number(pb[i]);
|
|
86
|
+
if (isNaN(na))
|
|
87
|
+
throw new Error('Invalid version number: ' + a);
|
|
88
|
+
if (isNaN(nb))
|
|
89
|
+
throw new Error('Invalid version number: ' + b);
|
|
90
|
+
if (na > nb)
|
|
91
|
+
return true;
|
|
92
|
+
if (na < nb)
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
//# 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 = {
|
|
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,43 @@
|
|
|
1
|
+
import * as td from 'typedoc';
|
|
2
|
+
import * as tdMarkdown from 'typedoc-plugin-markdown';
|
|
3
|
+
import * as tdTheme from 'typedoc-github-wiki-theme';
|
|
4
|
+
import { panic, warn } from '../lib/log.js';
|
|
5
|
+
export async function generateTypescriptDocs(options) {
|
|
6
|
+
const app = await td.Application.bootstrapWithPlugins({
|
|
7
|
+
entryPoints: [options.entryPoint ?? './src/index.ts'],
|
|
8
|
+
gitRevision: 'main',
|
|
9
|
+
outputs: [{ name: 'markdown', path: options.outputPath ?? './docs' }],
|
|
10
|
+
}, [
|
|
11
|
+
new td.ArgumentsReader(0),
|
|
12
|
+
new td.TypeDocReader(),
|
|
13
|
+
new td.PackageJsonReader(),
|
|
14
|
+
new td.TSConfigReader(),
|
|
15
|
+
new td.ArgumentsReader(300),
|
|
16
|
+
]);
|
|
17
|
+
tdMarkdown.load(app);
|
|
18
|
+
tdTheme.load(app);
|
|
19
|
+
app.options.setValue('readme', 'none');
|
|
20
|
+
app.options.setValue('hidePageHeader', true);
|
|
21
|
+
app.options.setValue('classPropertiesFormat', 'table');
|
|
22
|
+
app.options.setValue('enumMembersFormat', 'table');
|
|
23
|
+
app.options.setValue('indexFormat', 'table');
|
|
24
|
+
app.options.setValue('interfacePropertiesFormat', 'table');
|
|
25
|
+
app.options.setValue('parametersFormat', 'table');
|
|
26
|
+
app.options.setValue('propertiesFormat', 'table');
|
|
27
|
+
app.options.setValue('propertyMembersFormat', 'table');
|
|
28
|
+
app.options.setValue('typeDeclarationFormat', 'table');
|
|
29
|
+
const project = await app.convert();
|
|
30
|
+
if (!project)
|
|
31
|
+
panic('Failed to convert project');
|
|
32
|
+
app.validate(project);
|
|
33
|
+
if (app.logger.hasWarnings())
|
|
34
|
+
warn('Warnings found during validation');
|
|
35
|
+
if (app.logger.hasErrors())
|
|
36
|
+
panic('Errors found during validation');
|
|
37
|
+
await app.generateOutputs(project);
|
|
38
|
+
if (app.logger.hasWarnings())
|
|
39
|
+
warn('Warnings found during validation');
|
|
40
|
+
if (app.logger.hasErrors())
|
|
41
|
+
panic('Errors found during validation');
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=doc-typescript.js.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,67 +1,140 @@
|
|
|
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 {
|
|
4
|
+
import { styleText } from 'node:util';
|
|
5
5
|
import { injectMarkdown, updateTOC } from './commands/markdown.js';
|
|
6
6
|
import { Command, InvalidArgumentError } from 'commander';
|
|
7
7
|
import { cwd } from 'node:process';
|
|
8
|
-
import { generateCommandDocumentation } from './commands/command.js';
|
|
9
|
-
import { release } from './commands/release.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
|
+
*/
|
|
10
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
|
+
});
|
|
11
27
|
program
|
|
12
28
|
.name('vrt')
|
|
13
|
-
.description('
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
+
*/
|
|
43
|
+
program.command('deps-graph')
|
|
44
|
+
.description('Analyze project files and output a dependency graph as Mermaid markup.')
|
|
45
|
+
.action(() => {
|
|
46
|
+
void generateDependencyGraph(process.cwd());
|
|
21
47
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Command: deps-upgrade
|
|
50
|
+
* Upgrades project dependencies in package.json to their latest versions and reinstalls them.
|
|
51
|
+
*/
|
|
52
|
+
program.command('deps-upgrade')
|
|
53
|
+
.description('Upgrade all dependencies in the current project to their latest versions.')
|
|
54
|
+
.action(() => {
|
|
55
|
+
void upgradeDependencies(process.cwd());
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Command: doc-command
|
|
59
|
+
* Generates Markdown documentation for a given CLI command.
|
|
60
|
+
*/
|
|
61
|
+
program.command('doc-command')
|
|
62
|
+
.description('Generate Markdown documentation for a specified command and output the result.')
|
|
63
|
+
.argument('<command>', 'Command to document (e.g., "npm run build").')
|
|
25
64
|
.action(async (command) => {
|
|
26
65
|
const mdDocumentation = await generateCommandDocumentation(command);
|
|
27
66
|
process.stdout.write(mdDocumentation);
|
|
28
67
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
+
*/
|
|
73
|
+
program.command('doc-insert')
|
|
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)
|
|
34
78
|
.action(async (mdFilename, heading, foldable) => {
|
|
35
79
|
const buffers = [];
|
|
36
|
-
for await (const data of process.stdin)
|
|
80
|
+
for await (const data of process.stdin) {
|
|
37
81
|
buffers.push(data);
|
|
38
|
-
|
|
82
|
+
}
|
|
83
|
+
const mdContent = '<!--- This chapter is generated automatically --->\n'
|
|
84
|
+
+ Buffer.concat(buffers).toString();
|
|
39
85
|
let mdFile = readFileSync(mdFilename, 'utf8');
|
|
40
86
|
mdFile = injectMarkdown(mdFile, mdContent, heading, foldable);
|
|
41
87
|
writeFileSync(mdFilename, mdFile);
|
|
42
88
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Command: doc-toc
|
|
91
|
+
* Updates or generates a Table of Contents in a Markdown file under a specified heading.
|
|
92
|
+
*/
|
|
93
|
+
program.command('doc-toc')
|
|
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')
|
|
47
97
|
.action((mdFilename, heading) => {
|
|
48
98
|
let mdFile = readFileSync(mdFilename, 'utf8');
|
|
49
99
|
mdFile = updateTOC(mdFile, heading);
|
|
50
100
|
writeFileSync(mdFilename, mdFile);
|
|
51
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 <entryPoint>', 'Entry point of the TypeScript project. Default is "./src/index.ts".')
|
|
110
|
+
.option('-o <outputPath>', 'Output path for the generated documentation. Default is "./docs".')
|
|
111
|
+
.action(async (options) => {
|
|
112
|
+
await generateTypescriptDocs(options);
|
|
113
|
+
});
|
|
114
|
+
/**
|
|
115
|
+
* Command: release-npm
|
|
116
|
+
* Releases/publishes an npm package from a specified project path to the npm registry.
|
|
117
|
+
*/
|
|
52
118
|
program.command('release-npm')
|
|
53
|
-
.description('
|
|
54
|
-
.argument('[path]', '
|
|
119
|
+
.description('Publish an npm package from the specified path to the npm registry.')
|
|
120
|
+
.argument('[path]', 'Root path of the Node.js project. Defaults to the current directory.')
|
|
55
121
|
.action((path) => {
|
|
56
|
-
void release(resolve(path ?? '
|
|
122
|
+
void release(resolve(path ?? '.', process.cwd()), 'main');
|
|
57
123
|
});
|
|
58
124
|
if (process.env.NODE_ENV !== 'test') {
|
|
59
125
|
await program.parseAsync();
|
|
60
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Validates that the given filename exists.
|
|
129
|
+
* Throws an InvalidArgumentError if the file cannot be found.
|
|
130
|
+
*
|
|
131
|
+
* @param filename - The filename to check.
|
|
132
|
+
* @returns The resolved full path if the file exists.
|
|
133
|
+
*/
|
|
61
134
|
function checkFilename(filename) {
|
|
62
135
|
const fullname = resolve(cwd(), filename);
|
|
63
136
|
if (!existsSync(fullname)) {
|
|
64
|
-
throw new InvalidArgumentError(
|
|
137
|
+
throw new InvalidArgumentError(`File not found: ${filename}`);
|
|
65
138
|
}
|
|
66
139
|
return fullname;
|
|
67
140
|
}
|
package/dist/lib/log.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export declare function panic(text: string): never;
|
|
|
2
2
|
export declare function warn(text: string): void;
|
|
3
3
|
export declare function info(text: string): void;
|
|
4
4
|
export declare function abort(): never;
|
|
5
|
-
export declare function check<T>(message: string, promise: Promise<T>): Promise<T>;
|
|
5
|
+
export declare function check<T>(message: string, promise: (Promise<T>) | (() => Promise<T>)): Promise<T>;
|
package/dist/lib/log.js
CHANGED
|
@@ -15,14 +15,14 @@ export function abort() {
|
|
|
15
15
|
export async function check(message, promise) {
|
|
16
16
|
process.stderr.write(`\x1b[0;90m\u2B95 ${message}\x1b[0m`);
|
|
17
17
|
try {
|
|
18
|
-
const result = await promise;
|
|
18
|
+
const result = await (typeof promise === 'function' ? promise() : promise);
|
|
19
19
|
process.stderr.write(`\r\x1b[0;92m\u2714 ${message}\x1b[0m\n`);
|
|
20
20
|
return result;
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
23
|
process.stderr.write(`\r\x1b[0;91m\u2718 ${message}\x1b[0m\n`);
|
|
24
24
|
panic(error.message);
|
|
25
|
-
throw
|
|
25
|
+
throw error;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
//# sourceMappingURL=log.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versatiles/release-tool",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "VersaTiles release and documentation tools",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vrt": "./dist/index.js"
|
|
@@ -10,44 +10,49 @@
|
|
|
10
10
|
"dist/**/*.d.ts"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "
|
|
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",
|
|
17
|
+
"doc": "npm run doc-command && npm run doc-graph",
|
|
18
|
+
"doc-command": "tsx src/index.ts doc-command vrt | tsx src/index.ts doc-insert README.md '# Command'",
|
|
19
|
+
"doc-graph": "tsx src/index.ts deps-graph | tsx src/index.ts doc-insert README.md '## Dependency Graph'",
|
|
16
20
|
"lint": "eslint . --color",
|
|
17
|
-
"prepack": "npm run build
|
|
18
|
-
"release": "
|
|
21
|
+
"prepack": "npm run build",
|
|
22
|
+
"release": "tsx src/index.ts release-npm",
|
|
19
23
|
"test-coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
20
24
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
21
|
-
"upgrade": "
|
|
25
|
+
"upgrade": "tsx src/index.ts deps-upgrade"
|
|
22
26
|
},
|
|
23
|
-
"author": "
|
|
27
|
+
"author": "Michael Kreil <versatiles@michael-kreil.de>",
|
|
24
28
|
"license": "Unlicense",
|
|
25
29
|
"type": "module",
|
|
26
30
|
"repository": {
|
|
27
31
|
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/versatiles-org/node-
|
|
32
|
+
"url": "git+https://github.com/versatiles-org/node-release-tool.git"
|
|
29
33
|
},
|
|
30
|
-
"homepage": "https://github.com/versatiles-org/node-
|
|
34
|
+
"homepage": "https://github.com/versatiles-org/node-release-tool",
|
|
31
35
|
"devDependencies": {
|
|
32
|
-
"@
|
|
36
|
+
"@schemastore/package": "^0.0.10",
|
|
33
37
|
"@types/jest": "^29.5.14",
|
|
34
|
-
"@types/node": "^22.13.
|
|
38
|
+
"@types/node": "^22.13.5",
|
|
35
39
|
"@typescript-eslint/eslint-plugin": "^8.22.0",
|
|
36
40
|
"@typescript-eslint/parser": "^8.22.0",
|
|
37
|
-
"eslint": "^9.
|
|
41
|
+
"eslint": "^9.21.0",
|
|
38
42
|
"jest": "^29.7.0",
|
|
39
|
-
"npm-check-updates": "^17.1.14",
|
|
40
43
|
"ts-jest": "^29.2.5",
|
|
41
|
-
"
|
|
42
|
-
"tsx": "^4.19.2",
|
|
44
|
+
"tsx": "^4.19.3",
|
|
43
45
|
"typescript": "^5.7.3",
|
|
44
|
-
"typescript-eslint": "^8.
|
|
46
|
+
"typescript-eslint": "^8.24.1"
|
|
45
47
|
},
|
|
46
48
|
"dependencies": {
|
|
47
|
-
"@inquirer/select": "^4.0.
|
|
49
|
+
"@inquirer/select": "^4.0.9",
|
|
48
50
|
"commander": "^13.1.0",
|
|
51
|
+
"dependency-cruiser": "^16.10.0",
|
|
49
52
|
"remark": "^15.0.1",
|
|
50
|
-
"remark-gfm": "^4.0.
|
|
51
|
-
"typedoc": "^0.27.
|
|
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"
|
|
52
57
|
}
|
|
53
58
|
}
|
package/LICENSE.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
This is free and unencumbered software released into the public domain.
|
|
2
|
-
|
|
3
|
-
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
-
distribute this software, either in source code form or as a compiled
|
|
5
|
-
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
-
means.
|
|
7
|
-
|
|
8
|
-
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
-
of this software dedicate any and all copyright interest in the
|
|
10
|
-
software to the public domain. We make this dedication for the benefit
|
|
11
|
-
of the public at large and to the detriment of our heirs and
|
|
12
|
-
successors. We intend this dedication to be an overt act of
|
|
13
|
-
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
-
software under copyright law.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
-
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
-
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
-
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
|
|
24
|
-
For more information, please refer to [unlicense.org](https://unlicense.org/)
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate markdown documentation from TypeScript files.
|
|
3
|
-
* @param sourceFilePaths - Array of absolute TypeScript file paths.
|
|
4
|
-
* @param tsConfigPath - Absolute file path of tsconfig.json.
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateTsMarkdownDoc(sourceFilePaths: string[], tsConfigPath: string): Promise<string>;
|
package/dist/commands/typedoc.js
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { Application, ReflectionKind, } from 'typedoc';
|
|
2
|
-
/**
|
|
3
|
-
* Generate markdown documentation from TypeScript files.
|
|
4
|
-
* @param sourceFilePaths - Array of absolute TypeScript file paths.
|
|
5
|
-
* @param tsConfigPath - Absolute file path of tsconfig.json.
|
|
6
|
-
*/
|
|
7
|
-
export async function generateTsMarkdownDoc(sourceFilePaths, tsConfigPath) {
|
|
8
|
-
const app = await Application.bootstrap({ entryPoints: sourceFilePaths, tsconfig: tsConfigPath });
|
|
9
|
-
const project = await app.convert();
|
|
10
|
-
if (!project) {
|
|
11
|
-
throw new Error('Failed to convert TypeScript project.');
|
|
12
|
-
}
|
|
13
|
-
return Array.from(documentProject(project)).join('\n');
|
|
14
|
-
}
|
|
15
|
-
function* documentProject(project) {
|
|
16
|
-
if (!project.groups) {
|
|
17
|
-
throw new Error('No TypeScript code to document found! Is this a lib?');
|
|
18
|
-
}
|
|
19
|
-
for (const group of project.groups) {
|
|
20
|
-
yield '\n# ' + group.title;
|
|
21
|
-
for (const d of group.children) {
|
|
22
|
-
const declaration = d;
|
|
23
|
-
switch (declaration.kind) {
|
|
24
|
-
case ReflectionKind.Class:
|
|
25
|
-
yield* documentClass(declaration);
|
|
26
|
-
break;
|
|
27
|
-
case ReflectionKind.Function:
|
|
28
|
-
yield* documentMethod(declaration, 2);
|
|
29
|
-
break;
|
|
30
|
-
case ReflectionKind.Interface:
|
|
31
|
-
yield* documentInterface(declaration);
|
|
32
|
-
break;
|
|
33
|
-
case ReflectionKind.TypeAlias:
|
|
34
|
-
yield* documentType(declaration);
|
|
35
|
-
break;
|
|
36
|
-
case ReflectionKind.Variable:
|
|
37
|
-
yield* documentVariable(declaration);
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
throw new Error('implement ' + declaration.kind);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function* documentInterface(declaration) {
|
|
46
|
-
yield `\n## Interface: \`${declaration.name}\`<a id="${createAnchorId(declaration)}"></a>`;
|
|
47
|
-
yield '\n```typescript';
|
|
48
|
-
yield 'interface {';
|
|
49
|
-
for (const child of declaration.children ?? []) {
|
|
50
|
-
if (child.kind !== ReflectionKind.Property)
|
|
51
|
-
throw Error('should be a property inside an interface');
|
|
52
|
-
if (child.type == null)
|
|
53
|
-
throw Error('should have a type');
|
|
54
|
-
const name = child.name + (child.flags.isOptional ? '?' : '');
|
|
55
|
-
yield ` ${name}: ${formatTypeDeclaration(child.type)};`;
|
|
56
|
-
}
|
|
57
|
-
yield '}';
|
|
58
|
-
yield '```';
|
|
59
|
-
}
|
|
60
|
-
function* documentType(declaration) {
|
|
61
|
-
yield `\n## Type: \`${declaration.name}\`<a id="${createAnchorId(declaration)}"></a>`;
|
|
62
|
-
if (declaration.type) {
|
|
63
|
-
yield `\n**Type:** <code>${formatTypeDeclaration(declaration.type)}</code>`;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function* documentClass(declaration) {
|
|
67
|
-
yield `\n## Class: \`${declaration.name}\`<a id="${createAnchorId(declaration)}"></a>`;
|
|
68
|
-
yield* documentSummaryBlock(declaration);
|
|
69
|
-
for (const group of declaration.groups ?? []) {
|
|
70
|
-
const publicMembers = group.children.filter(member => !member.flags.isPrivate && !member.flags.isProtected);
|
|
71
|
-
if (publicMembers.length === 0)
|
|
72
|
-
continue;
|
|
73
|
-
// Sort by order in code
|
|
74
|
-
publicMembers.sort((a, b) => a.id - b.id);
|
|
75
|
-
switch (group.title) {
|
|
76
|
-
case 'Constructors':
|
|
77
|
-
if (publicMembers.length !== 1)
|
|
78
|
-
throw Error('publicMembers.length !== 1');
|
|
79
|
-
yield* documentMethod(publicMembers[0], 3, true);
|
|
80
|
-
continue;
|
|
81
|
-
case 'Accessors':
|
|
82
|
-
yield '\n### Accessors';
|
|
83
|
-
for (const member of publicMembers)
|
|
84
|
-
yield documentAccessor(member);
|
|
85
|
-
continue;
|
|
86
|
-
case 'Properties':
|
|
87
|
-
yield '\n### Properties';
|
|
88
|
-
for (const member of publicMembers)
|
|
89
|
-
yield documentProperty(member);
|
|
90
|
-
continue;
|
|
91
|
-
case 'Methods':
|
|
92
|
-
for (const member of publicMembers)
|
|
93
|
-
yield* documentMethod(member, 3);
|
|
94
|
-
continue;
|
|
95
|
-
default:
|
|
96
|
-
console.log(group);
|
|
97
|
-
throw Error('Unknown group title');
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
function* documentMethod(method, depth, isConstructor = false) {
|
|
102
|
-
if (method.signatures?.length !== 1)
|
|
103
|
-
throw Error('should be 1');
|
|
104
|
-
const [signature] = method.signatures;
|
|
105
|
-
const parameters = formatMethodParameters(signature.parameters ?? []);
|
|
106
|
-
if (isConstructor) {
|
|
107
|
-
yield `\n${'#'.repeat(depth)} Constructor: \`new ${signature.name}(${parameters})\``;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
yield `\n${'#'.repeat(depth)} Method: \`${signature.name}(${parameters})\``;
|
|
111
|
-
}
|
|
112
|
-
yield* documentSummaryBlock(signature);
|
|
113
|
-
if (signature.parameters && signature.parameters.length > 0) {
|
|
114
|
-
yield '';
|
|
115
|
-
yield '**Parameters:**';
|
|
116
|
-
for (const parameter of signature.parameters) {
|
|
117
|
-
yield documentProperty(parameter);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (signature.type && !isConstructor) {
|
|
121
|
-
yield `\n**Returns:** <code>${formatTypeDeclaration(signature.type)}</code>`;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function formatMethodParameters(parameters) {
|
|
125
|
-
return parameters.map(param => param.name).join(', ');
|
|
126
|
-
}
|
|
127
|
-
// Helper Functions
|
|
128
|
-
function getDeclarationKindName(kind) {
|
|
129
|
-
switch (kind) {
|
|
130
|
-
case ReflectionKind.Class: return 'Class';
|
|
131
|
-
case ReflectionKind.Function: return 'Function';
|
|
132
|
-
case ReflectionKind.Interface: return 'Interface';
|
|
133
|
-
case ReflectionKind.TypeAlias: return 'Type';
|
|
134
|
-
case ReflectionKind.Variable: return 'Variable';
|
|
135
|
-
default: throw new Error(`Unknown reflection kind: ${kind}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
function documentProperty(ref) {
|
|
139
|
-
let line = ` - <code>${ref.name}${resolveTypeDeclaration(ref.type)}</code>`;
|
|
140
|
-
if (ref.flags.isOptional)
|
|
141
|
-
line += ' (optional)';
|
|
142
|
-
const summary = extractSummary(ref.comment);
|
|
143
|
-
if (summary != null)
|
|
144
|
-
line += ' \n ' + summary;
|
|
145
|
-
return line;
|
|
146
|
-
}
|
|
147
|
-
function* documentVariable(ref) {
|
|
148
|
-
const prefix = ref.flags.isConst ? 'const' : 'let';
|
|
149
|
-
yield `\n## \`${prefix} ${ref.name}\``;
|
|
150
|
-
const summary = extractSummary(ref.comment);
|
|
151
|
-
if (summary != null)
|
|
152
|
-
yield summary;
|
|
153
|
-
}
|
|
154
|
-
function documentAccessor(ref) {
|
|
155
|
-
let line = ` - <code>${ref.name}${resolveTypeDeclaration(ref.type)}</code>`;
|
|
156
|
-
const summary = extractSummary(ref.comment);
|
|
157
|
-
if (summary != null)
|
|
158
|
-
line += ' \n ' + summary;
|
|
159
|
-
return line;
|
|
160
|
-
}
|
|
161
|
-
function extractSummary(comment) {
|
|
162
|
-
if (!comment)
|
|
163
|
-
return null;
|
|
164
|
-
return comment.summary.map(line => line.text).join('');
|
|
165
|
-
}
|
|
166
|
-
function* documentSummaryBlock(ref) {
|
|
167
|
-
yield '';
|
|
168
|
-
if (ref.comment) {
|
|
169
|
-
yield formatComment(ref.comment);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const { type } = ref;
|
|
173
|
-
if (type?.type === 'reflection') {
|
|
174
|
-
if (type.declaration.signatures?.length !== 1)
|
|
175
|
-
throw Error('type.declaration.signatures?.length !== 1');
|
|
176
|
-
const [signature] = type.declaration.signatures;
|
|
177
|
-
if (signature.comment) {
|
|
178
|
-
yield formatComment(signature.comment);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const sourceLink = createSourceLink(ref);
|
|
183
|
-
if (sourceLink != null)
|
|
184
|
-
yield sourceLink;
|
|
185
|
-
return;
|
|
186
|
-
function formatComment(comment) {
|
|
187
|
-
let summary = extractSummary(comment) ?? '';
|
|
188
|
-
const link = createSourceLink(ref);
|
|
189
|
-
if (link != null)
|
|
190
|
-
summary += ' ' + link;
|
|
191
|
-
return summary.replace(/\n/mg, ' \n') + '\n';
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function resolveTypeDeclaration(someType) {
|
|
195
|
-
if (!someType)
|
|
196
|
-
return '';
|
|
197
|
-
return `: ${formatTypeDeclaration(someType)}`;
|
|
198
|
-
}
|
|
199
|
-
function formatTypeDeclaration(someType) {
|
|
200
|
-
return getTypeRec(someType);
|
|
201
|
-
function getTypeRec(some) {
|
|
202
|
-
switch (some.type) {
|
|
203
|
-
case 'intrinsic':
|
|
204
|
-
return some.name;
|
|
205
|
-
case 'literal':
|
|
206
|
-
return JSON.stringify(some.value);
|
|
207
|
-
case 'reference': {
|
|
208
|
-
let result = some.name;
|
|
209
|
-
if (some.reflection)
|
|
210
|
-
result = `[${result}](#${createAnchorId(some.reflection)})`;
|
|
211
|
-
if (some.typeArguments?.length ?? 0)
|
|
212
|
-
result += '<'
|
|
213
|
-
+ (some.typeArguments ?? [])
|
|
214
|
-
.map(getTypeRec).join(',')
|
|
215
|
-
+ '>';
|
|
216
|
-
return result;
|
|
217
|
-
}
|
|
218
|
-
case 'reflection':
|
|
219
|
-
switch (some.declaration.kind) {
|
|
220
|
-
case ReflectionKind.TypeLiteral: return decodeReflectionTypeLiteral(some.declaration);
|
|
221
|
-
default:
|
|
222
|
-
console.log('declarationKindName', getDeclarationKindName(some.declaration.kind));
|
|
223
|
-
console.dir(some, { depth: 4 });
|
|
224
|
-
throw Error();
|
|
225
|
-
}
|
|
226
|
-
case 'tuple':
|
|
227
|
-
return `[${some.elements.map(getTypeRec).join(', ')}]`;
|
|
228
|
-
case 'union':
|
|
229
|
-
return some.types.map(getTypeRec).join(' | ');
|
|
230
|
-
case 'array':
|
|
231
|
-
return getTypeRec(some.elementType) + '[]';
|
|
232
|
-
default:
|
|
233
|
-
console.log(some);
|
|
234
|
-
throw Error(some.type);
|
|
235
|
-
}
|
|
236
|
-
function decodeReflectionTypeLiteral(ref) {
|
|
237
|
-
try {
|
|
238
|
-
if (ref.variant !== 'declaration')
|
|
239
|
-
throw Error();
|
|
240
|
-
if (ref.groups && !ref.signatures) {
|
|
241
|
-
if (!Array.isArray(ref.groups))
|
|
242
|
-
throw Error();
|
|
243
|
-
if (ref.groups.length !== 1)
|
|
244
|
-
throw Error();
|
|
245
|
-
const [group] = ref.groups;
|
|
246
|
-
if (group.title !== 'Properties')
|
|
247
|
-
throw Error();
|
|
248
|
-
const properties = group.children.map(r => r.escapedName + ':?');
|
|
249
|
-
return `{${properties.join(', ')}}`;
|
|
250
|
-
}
|
|
251
|
-
if (!ref.groups && ref.signatures) {
|
|
252
|
-
if (ref.signatures.length !== 1)
|
|
253
|
-
throw Error('ref.signatures.length !== 1');
|
|
254
|
-
const [signature] = ref.signatures;
|
|
255
|
-
const returnType = signature.type ? getTypeRec(signature.type) : 'void';
|
|
256
|
-
const parameters = (signature.parameters ?? [])
|
|
257
|
-
.map(p => {
|
|
258
|
-
return p.name + (p.type ? ': ' + getTypeRec(p.type) : '');
|
|
259
|
-
}).join(', ');
|
|
260
|
-
return `(${parameters}) => ${returnType}`;
|
|
261
|
-
}
|
|
262
|
-
throw Error();
|
|
263
|
-
}
|
|
264
|
-
catch (error) {
|
|
265
|
-
console.dir(ref, { depth: 3 });
|
|
266
|
-
throw error;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function createSourceLink(reference) {
|
|
272
|
-
if (!reference.sources || reference.sources.length < 1)
|
|
273
|
-
return null;
|
|
274
|
-
if (reference.sources.length > 1)
|
|
275
|
-
throw Error('ref.sources.length > 1');
|
|
276
|
-
const [source] = reference.sources;
|
|
277
|
-
return `<sup><a href="${source.url}">[src]</a></sup>`;
|
|
278
|
-
}
|
|
279
|
-
function createAnchorId(reference) {
|
|
280
|
-
return `${getDeclarationKindName(reference.kind)}_${reference.name}`.toLowerCase();
|
|
281
|
-
}
|
|
282
|
-
//# sourceMappingURL=typedoc.js.map
|
|
File without changes
|
|
File without changes
|