Skip to content

Commit 222fea3

Browse files
authored
feat(cli): split cli into sub commands (#250)
1 parent 1e18d5f commit 222fea3

File tree

12 files changed

+648
-171
lines changed

12 files changed

+648
-171
lines changed

README.md

+71-16
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,79 @@ Local invocation:
2929
$ npx api-docs-tooling --help
3030
```
3131

32-
```sh
33-
Usage: api-docs-tooling [options]
32+
```
33+
Usage: api-docs-tooling [options] [command]
3434
35-
CLI tool to generate API documentation of a Node.js project.
35+
CLI tool to generate and lint Node.js API documentation
3636
3737
Options:
38-
-i, --input [patterns...] Specify input file patterns using glob syntax
39-
--ignore [patterns...] Specify which input files to ignore using glob syntax
40-
-o, --output <path> Specify the relative or absolute output directory
41-
-v, --version <semver> Specify the target version of Node.js, semver compliant (default: "v22.11.0")
42-
-c, --changelog <url> Specify the path (file: or https://) to the CHANGELOG.md file (default:
43-
"https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md")
44-
-t, --target [mode...] Set the processing target modes (choices: "json-simple", "legacy-html", "legacy-html-all",
45-
"man-page", "legacy-json", "legacy-json-all", "addon-verify", "api-links", "orama-db")
46-
--disable-rule [rule...] Disable a specific linter rule (choices: "invalid-change-version",
47-
"missing-change-version", "missing-introduced-in", default: [])
48-
--lint-dry-run Run linter in dry-run mode (default: false)
49-
--git-ref A git ref/commit URL pointing to Node.js
50-
-r, --reporter [reporter] Specify the linter reporter (choices: "console", "github", default: "console")
38+
-h, --help display help for command
39+
40+
Commands:
41+
generate [options] Generate API docs
42+
lint [options] Run linter independently
43+
interactive Launch guided CLI wizard
44+
list <types> List the given type
45+
help [command] display help for command
46+
```
47+
48+
### `generate`
49+
50+
```
51+
Usage: api-docs-tooling generate [options]
52+
53+
Generate API docs
54+
55+
Options:
56+
-i, --input <patterns...> Input file patterns (glob)
57+
--ignore [patterns...] Ignore patterns (comma-separated)
58+
-o, --output <dir> Output directory
59+
-p, --threads <number> (default: "12")
60+
-v, --version <semver> Target Node.js version (default: "v22.14.0")
61+
-c, --changelog <url> Changelog URL or path (default: "https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md")
62+
--git-ref <url> Git ref/commit URL (default: "https://github.com/nodejs/node/tree/HEAD")
63+
-t, --target [modes...] Target generator modes (choices: "json-simple", "legacy-html", "legacy-html-all", "man-page", "legacy-json", "legacy-json-all", "addon-verify", "api-links", "orama-db")
64+
--no-lint Skip lint before generate
5165
-h, --help display help for command
5266
```
67+
68+
### `lint`
69+
70+
```
71+
Usage: api-docs-tooling lint [options]
72+
73+
Run linter independently
74+
75+
Options:
76+
-i, --input <patterns...> Input file patterns (glob)
77+
--ignore [patterns...] Ignore patterns (comma-separated)
78+
--disable-rule [rules...] Disable linter rules (choices: "duplicate-stability-nodes", "invalid-change-version", "missing-introduced-in")
79+
--dry-run Dry run mode (default: false)
80+
-r, --reporter <reporter> Linter reporter to use
81+
-h, --help display help for command
82+
```
83+
84+
### `interactive`
85+
86+
```
87+
Usage: api-docs-tooling interactive [options]
88+
89+
Launch guided CLI wizard
90+
91+
Options:
92+
-h, --help display help for command
93+
```
94+
95+
### `list`
96+
97+
```
98+
Usage: api-docs-tooling list [options] <types>
99+
100+
List the given type
101+
102+
Arguments:
103+
types The type to list (choices: "generators", "rules", "reporters")
104+
105+
Options:
106+
-h, --help display help for command
107+
```

bin/cli.mjs

+38-146
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,53 @@
11
#!/usr/bin/env node
22

3-
import { resolve } from 'node:path';
43
import process from 'node:process';
5-
import { cpus } from 'node:os';
4+
import { Argument, Command, Option } from 'commander';
65

7-
import { Command, Option } from 'commander';
6+
import interactive from './commands/interactive.mjs';
7+
import list, { types } from './commands/list.mjs';
8+
import commands from './commands/index.mjs';
89

9-
import { coerce } from 'semver';
10-
import { DOC_NODE_CHANGELOG_URL, DOC_NODE_VERSION } from '../src/constants.mjs';
11-
import createGenerator from '../src/generators.mjs';
12-
import { publicGenerators } from '../src/generators/index.mjs';
13-
import createLinter from '../src/linter/index.mjs';
14-
import reporters from '../src/linter/reporters/index.mjs';
15-
import rules from '../src/linter/rules/index.mjs';
16-
import createMarkdownLoader from '../src/loaders/markdown.mjs';
17-
import createMarkdownParser from '../src/parsers/markdown.mjs';
18-
import createNodeReleases from '../src/releases.mjs';
19-
20-
const availableGenerators = Object.keys(publicGenerators);
21-
22-
const program = new Command();
23-
24-
program
10+
const program = new Command()
2511
.name('api-docs-tooling')
26-
.description('CLI tool to generate API documentation of a Node.js project.')
27-
.addOption(
28-
new Option(
29-
'-i, --input [patterns...]',
30-
'Specify input file patterns using glob syntax'
31-
).makeOptionMandatory()
32-
)
33-
.addOption(
34-
new Option(
35-
'--ignore [patterns...]',
36-
'Specify which input files to ignore using glob syntax'
37-
)
38-
)
39-
.addOption(
40-
new Option(
41-
'-o, --output <path>',
42-
'Specify the relative or absolute output directory'
43-
)
44-
)
45-
.addOption(
46-
new Option(
47-
'-v, --version <semver>',
48-
'Specify the target version of Node.js, semver compliant'
49-
).default(DOC_NODE_VERSION)
50-
)
51-
.addOption(
52-
new Option(
53-
'-c, --changelog <url>',
54-
'Specify the path (file: or https://) to the CHANGELOG.md file'
55-
).default(DOC_NODE_CHANGELOG_URL)
56-
)
57-
.addOption(
58-
new Option(
59-
'-t, --target [mode...]',
60-
'Set the processing target modes'
61-
).choices(availableGenerators)
62-
)
63-
.addOption(
64-
new Option('--disable-rule [rule...]', 'Disable a specific linter rule')
65-
.choices(Object.keys(rules))
66-
.default([])
67-
)
68-
.addOption(
69-
new Option('--lint-dry-run', 'Run linter in dry-run mode').default(false)
70-
)
71-
.addOption(
72-
new Option('--git-ref', 'A git ref/commit URL pointing to Node.js').default(
73-
'https://github.com/nodejs/node/tree/HEAD'
74-
)
75-
)
76-
.addOption(
77-
new Option('-r, --reporter [reporter]', 'Specify the linter reporter')
78-
.choices(Object.keys(reporters))
79-
.default('console')
80-
)
81-
.addOption(
82-
new Option(
83-
'-p, --threads <number>',
84-
'The maximum number of threads to use. Set to 1 to disable parallelism'
85-
).default(Math.max(1, cpus().length - 1))
86-
)
87-
.parse(process.argv);
88-
89-
/**
90-
* @typedef {keyof publicGenerators} Target A list of the available generator names.
91-
*
92-
* @typedef {Object} Options
93-
* @property {Array<string>|string} input Specifies the glob/path for input files.
94-
* @property {string} output Specifies the directory where output files will be saved.
95-
* @property {Target[]} target Specifies the generator target mode.
96-
* @property {string} version Specifies the target Node.js version.
97-
* @property {string} changelog Specifies the path to the Node.js CHANGELOG.md file.
98-
* @property {string[]} disableRule Specifies the linter rules to disable.
99-
* @property {boolean} lintDryRun Specifies whether the linter should run in dry-run mode.
100-
* @property {boolean} useGit Specifies whether the parser should execute optional git commands. (Should only be used within a git repo)
101-
* @property {keyof reporters} reporter Specifies the linter reporter.
102-
*
103-
* @name ProgramOptions
104-
* @type {Options}
105-
* @description The return type for values sent to the program from the CLI.
106-
*/
107-
const {
108-
input,
109-
ignore,
110-
output,
111-
target = [],
112-
version,
113-
changelog,
114-
disableRule,
115-
lintDryRun,
116-
gitRef,
117-
reporter,
118-
threads,
119-
} = program.opts();
12+
.description('CLI tool to generate and lint Node.js API documentation');
12013

121-
const linter = createLinter(lintDryRun, disableRule);
14+
// Registering generate and lint commands
15+
commands.forEach(({ name, description, options, action }) => {
16+
const cmd = program.command(name).description(description);
12217

123-
const { loadFiles } = createMarkdownLoader();
124-
const { parseApiDocs } = createMarkdownParser();
18+
// Add options to the command
19+
Object.values(options).forEach(({ flags, desc, prompt }) => {
20+
const option = new Option(flags.join(', '), desc).default(
21+
prompt.initialValue
22+
);
12523

126-
const apiDocFiles = await loadFiles(input, ignore);
24+
if (prompt.required) {
25+
option.makeOptionMandatory();
26+
}
12727

128-
const parsedApiDocs = await parseApiDocs(apiDocFiles);
28+
if (prompt.type === 'multiselect') {
29+
option.choices(prompt.options.map(({ value }) => value));
30+
}
12931

130-
const { runGenerators } = createGenerator(parsedApiDocs);
131-
132-
// Retrieves Node.js release metadata from a given Node.js version and CHANGELOG.md file
133-
const { getAllMajors } = createNodeReleases(changelog);
32+
cmd.addOption(option);
33+
});
13434

135-
// Runs the Linter on the parsed API docs
136-
linter.lintAll(parsedApiDocs);
35+
// Set the action for the command
36+
cmd.action(action);
37+
});
13738

138-
if (target) {
139-
await runGenerators({
140-
// A list of target modes for the API docs parser
141-
generators: target,
142-
// Resolved `input` to be used
143-
input: input,
144-
// Resolved `output` path to be used
145-
output: output && resolve(output),
146-
// Resolved SemVer of current Node.js version
147-
version: coerce(version),
148-
// A list of all Node.js major versions with LTS status
149-
releases: await getAllMajors(),
150-
// An URL containing a git ref URL pointing to the commit or ref that was used
151-
// to generate the API docs. This is used to link to the source code of the
152-
gitRef,
153-
// How many threads should be used
154-
threads,
155-
});
156-
}
39+
// Register the interactive command
40+
program
41+
.command('interactive')
42+
.description('Launch guided CLI wizard')
43+
.action(interactive);
15744

158-
// Reports Lint Content
159-
linter.report(reporter);
45+
// Register the list command
46+
program
47+
.command('list')
48+
.addArgument(new Argument('<types>', 'The type to list').choices(types))
49+
.description('List the given type')
50+
.action(list);
16051

161-
process.exitCode = Number(linter.hasError());
52+
// Parse and execute command-line arguments
53+
program.parse(process.argv);

0 commit comments

Comments
 (0)