Skip to content

Commit 37945fc

Browse files
committed
feat(cli): add a configuration file option
1 parent 54c7f31 commit 37945fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+913
-568
lines changed

bin/commands/generate.mjs

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,44 @@
1-
import { cpus } from 'node:os';
2-
31
import { Command, Option } from 'commander';
4-
import { coerce } from 'semver';
52

6-
import { NODE_CHANGELOG_URL, NODE_VERSION } from '../../src/constants.mjs';
73
import { publicGenerators } from '../../src/generators/index.mjs';
84
import createGenerator from '../../src/generators.mjs';
9-
import logger from '../../src/logger/index.mjs';
10-
import { parseTypeMap } from '../../src/parsers/json.mjs';
11-
import { parseChangelog, parseIndex } from '../../src/parsers/markdown.mjs';
12-
import { DEFAULT_TYPE_MAP } from '../../src/utils/parser/constants.mjs';
5+
import { setConfig } from '../../src/utils/configuration/index.mjs';
136
import { errorWrap } from '../utils.mjs';
147

8+
const { runGenerators } = createGenerator();
9+
10+
/**
11+
* @typedef {Object} CLIOptions
12+
* @property {string[]} input
13+
* @property {string[]} target
14+
* @property {string[]} ignore
15+
* @property {string} output
16+
* @property {number} threads
17+
* @property {number} chunkSize
18+
* @property {string} version
19+
* @property {string} changelog
20+
* @property {string} gitRef
21+
* @property {string} index
22+
* @property {boolean} minify
23+
* @property {string} typeMap
24+
*/
25+
1526
export default new Command('generate')
1627
.description('Generate API docs')
28+
.addOption(new Option('--config-file <path>', 'Config file'))
29+
30+
// Options that need to be converted into a configuration
1731
.addOption(
1832
new Option(
1933
'-i, --input <patterns...>',
2034
'Input file patterns (glob)'
2135
).makeOptionMandatory()
2236
)
37+
.addOption(
38+
new Option('-t, --target <generator...>', 'Target generator(s)')
39+
.makeOptionMandatory()
40+
.choices(Object.keys(publicGenerators))
41+
)
2342
.addOption(
2443
new Option('--ignore <patterns...>', 'Ignore file patterns (glob)')
2544
)
@@ -29,63 +48,23 @@ export default new Command('generate')
2948
'-p, --threads <number>',
3049
'Number of threads to use (minimum: 1)'
3150
)
32-
.default(cpus().length)
33-
.argParser(parseInt)
3451
)
3552
.addOption(
3653
new Option(
3754
'--chunk-size <number>',
3855
'Number of items to process per worker thread (minimum: 1)'
3956
)
40-
.default(10)
41-
.argParser(parseInt)
42-
)
43-
.addOption(
44-
new Option('-v, --version <semver>', 'Target Node.js version').default(
45-
NODE_VERSION
46-
)
47-
)
48-
.addOption(
49-
new Option('-c, --changelog <url>', 'Changelog URL or path').default(
50-
NODE_CHANGELOG_URL
51-
)
52-
)
53-
.addOption(
54-
new Option('--git-ref', 'Git ref URL').default(
55-
'https://github.com/nodejs/node/tree/HEAD'
56-
)
57-
)
58-
.addOption(
59-
new Option('-t, --target <generator...>', 'Target generator(s)')
60-
.makeOptionMandatory()
61-
.choices(Object.keys(publicGenerators))
6257
)
58+
.addOption(new Option('-v, --version <semver>', 'Target Node.js version'))
59+
.addOption(new Option('-c, --changelog <url>', 'Changelog URL or path'))
60+
.addOption(new Option('--git-ref', 'Git ref URL'))
6361
.addOption(new Option('--index <url>', 'index.md URL or path'))
64-
.addOption(
65-
new Option('--type-map <url>', 'Type map URL or path').default(
66-
DEFAULT_TYPE_MAP
67-
)
68-
)
62+
.addOption(new Option('--minify', 'Minify?'))
63+
.addOption(new Option('--type-map <url>', 'Type map URL or path'))
64+
6965
.action(
7066
errorWrap(async opts => {
71-
logger.debug('Starting doc-kit', opts);
72-
73-
const { runGenerators } = createGenerator();
74-
75-
logger.debug('Starting generation', { targets: opts.target });
76-
77-
await runGenerators({
78-
generators: opts.target,
79-
input: opts.input,
80-
ignore: opts.ignore,
81-
output: opts.output,
82-
version: coerce(opts.version),
83-
releases: await parseChangelog(opts.changelog),
84-
gitRef: opts.gitRef,
85-
threads: Math.max(opts.threads, 1),
86-
chunkSize: Math.max(opts.chunkSize, 1),
87-
index: await parseIndex(opts.index),
88-
typeMap: await parseTypeMap(opts.typeMap),
89-
});
67+
const config = await setConfig(opts);
68+
await runGenerators(config);
9069
})
9170
);

eslint.config.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export default defineConfig([
7777
},
7878
},
7979
],
80-
'jsdoc/require-param': 'error',
8180
},
8281
},
8382
// Override rules for test files to disable JSDoc rules

src/constants.mjs

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/generators.mjs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ const generatorsLogger = logger.child('generators');
1212
* Creates a generator orchestration system that manages the execution of
1313
* documentation generators in dependency order, with support for parallel
1414
* processing and streaming results.
15-
*
16-
* @returns {{ runGenerators: (options: GeneratorOptions) => Promise<unknown[]> }}
1715
*/
1816
const createGenerator = () => {
1917
/** @type {{ [key: string]: Promise<unknown> | AsyncGenerator }} */
@@ -48,9 +46,9 @@ const createGenerator = () => {
4846
* Schedules a generator and its dependencies for execution.
4947
*
5048
* @param {string} generatorName - Generator to schedule
51-
* @param {GeneratorOptions} options - Runtime options
49+
* @param {import('./utils/configuration/types').Configuration} configuration - Runtime options
5250
*/
53-
const scheduleGenerator = (generatorName, options) => {
51+
const scheduleGenerator = (generatorName, configuration) => {
5452
if (generatorName in cachedGenerators) {
5553
return;
5654
}
@@ -59,7 +57,7 @@ const createGenerator = () => {
5957

6058
// Schedule dependency first
6159
if (dependsOn && !(dependsOn in cachedGenerators)) {
62-
scheduleGenerator(dependsOn, options);
60+
scheduleGenerator(dependsOn, configuration);
6361
}
6462

6563
generatorsLogger.debug(`Scheduling "${generatorName}"`, {
@@ -75,10 +73,10 @@ const createGenerator = () => {
7573

7674
// Create parallel worker for streaming generators
7775
const worker = processChunk
78-
? createParallelWorker(generatorName, pool, options)
76+
? createParallelWorker(generatorName, pool, configuration)
7977
: null;
8078

81-
const result = await generate(dependencyInput, { ...options, worker });
79+
const result = await generate(dependencyInput, worker);
8280

8381
// For streaming generators, "Completed" is logged when collection finishes
8482
// (in streamingCache.getOrCollect), not here when the generator returns
@@ -93,11 +91,11 @@ const createGenerator = () => {
9391
/**
9492
* Runs all requested generators with their dependencies.
9593
*
96-
* @param {GeneratorOptions} options - Runtime options
94+
* @param {import('./utils/configuration/types').Configuration} options - Runtime options
9795
* @returns {Promise<unknown[]>} Results of all requested generators
9896
*/
99-
const runGenerators = async options => {
100-
const { generators, threads } = options;
97+
const runGenerators = async configuration => {
98+
const { target: generators, threads } = configuration;
10199

102100
generatorsLogger.debug(`Starting pipeline`, {
103101
generators: generators.join(', '),
@@ -109,7 +107,7 @@ const createGenerator = () => {
109107

110108
// Schedule all generators
111109
for (const name of generators) {
112-
scheduleGenerator(name, options);
110+
scheduleGenerator(name, configuration);
113111
}
114112

115113
// Start all collections in parallel (don't await sequentially)

src/generators/addon-verify/index.mjs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ import {
1212
isBuildableSection,
1313
normalizeSectionName,
1414
} from './utils/section.mjs';
15+
import getConfig from '../../utils/configuration/index.mjs';
1516

1617
/**
1718
* This generator generates a file list from code blocks extracted from
1819
* `doc/api/addons.md` to facilitate C++ compilation and JavaScript runtime
1920
* validations.
2021
*
21-
* @typedef {Array<ApiDocMetadataEntry>} Input
22-
*
23-
* @type {GeneratorMetadata<Input, string>}
22+
* @type {import('./types').Generator}
2423
*/
2524
export default {
2625
name: 'addon-verify',
@@ -34,11 +33,10 @@ export default {
3433

3534
/**
3635
* Generates a file list from code blocks.
37-
*
38-
* @param {Input} input
39-
* @param {Partial<GeneratorOptions>} options
4036
*/
41-
async generate(input, { output }) {
37+
async generate(input) {
38+
const { 'addon-verify': config } = getConfig();
39+
4240
const sectionsCodeBlocks = input.reduce((addons, node) => {
4341
const sectionName = node.heading.data.name;
4442

@@ -72,19 +70,19 @@ export default {
7270
.flatMap(async ([sectionName, codeBlocks], index) => {
7371
const files = generateFileList(codeBlocks);
7472

75-
if (output) {
73+
if (config.output) {
7674
const normalizedSectionName = normalizeSectionName(sectionName);
7775

7876
const folderName = generateSectionFolderName(
7977
normalizedSectionName,
8078
index
8179
);
8280

83-
await mkdir(join(output, folderName), { recursive: true });
81+
await mkdir(join(config.output, folderName), { recursive: true });
8482

8583
for (const file of files) {
8684
await writeFile(
87-
join(output, folderName, file.name),
85+
join(config.output, folderName, file.name),
8886
file.content
8987
);
9088
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type Generator = GeneratorMetadata<
2+
{},
3+
Generate<Array<ApiDocMetadataEntry>, Promise<Record<string, string>>>
4+
>;

src/generators/api-links/index.mjs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import { basename, join } from 'node:path';
66
import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs';
77
import { extractExports } from './utils/extractExports.mjs';
88
import { findDefinitions } from './utils/findDefinitions.mjs';
9+
import getConfig from '../../utils/configuration/index.mjs';
10+
import {
11+
GITHUB_BLOB_URL,
12+
populate,
13+
} from '../../utils/configuration/templates.mjs';
914

1015
/**
1116
* This generator is responsible for mapping publicly accessible functions in
@@ -15,9 +20,7 @@ import { findDefinitions } from './utils/findDefinitions.mjs';
1520
* source files. It outputs a `apilinks.json` file into the specified output
1621
* directory.
1722
*
18-
* @typedef {Array<JsProgram>} Input
19-
*
20-
* @type {GeneratorMetadata<Input, Record<string, string>>}
23+
* @type {import('./types').Generator}
2124
*/
2225
export default {
2326
name: 'api-links',
@@ -33,11 +36,9 @@ export default {
3336

3437
/**
3538
* Generates the `apilinks.json` file.
36-
*
37-
* @param {Input} input
38-
* @param {Partial<GeneratorOptions>} options
3939
*/
40-
async generate(input, { output, gitRef }) {
40+
async generate(input) {
41+
const { 'api-links': config } = getConfig();
4142
/**
4243
* @type Record<string, string>
4344
*/
@@ -61,7 +62,7 @@ export default {
6162

6263
checkIndirectReferences(program, exports, nameToLineNumberMap);
6364

64-
const fullGitUrl = `${gitRef}/lib/${baseName}.js`;
65+
const fullGitUrl = `${populate(GITHUB_BLOB_URL)}/lib/${baseName}.js`;
6566

6667
// Add the exports we found in this program to our output
6768
Object.keys(nameToLineNumberMap).forEach(key => {
@@ -71,10 +72,15 @@ export default {
7172
});
7273
});
7374

74-
if (output) {
75-
const out = join(output, 'apilinks.json');
75+
if (config.output) {
76+
const out = join(config.output, 'apilinks.json');
7677

77-
await writeFile(out, JSON.stringify(definitions));
78+
await writeFile(
79+
out,
80+
config.minify
81+
? JSON.stringify(definitions)
82+
: JSON.stringify(definitions, null, 2)
83+
);
7884
}
7985

8086
return definitions;

src/generators/api-links/types.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ export interface ProgramExports {
33
identifiers: Array<string>;
44
indirects: Record<string, string>;
55
}
6+
7+
export type Generator = GeneratorMetadata<
8+
{},
9+
Generate<undefined, Promise<Record<string, string>>>
10+
>;

0 commit comments

Comments
 (0)