Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ Commands:

### `generate`

You must provide either `--target` (one or more generators to run) or
`--config-file` (which supplies the targets). Running `generate` without either
exits with an error pointing you to the help output.

```
Usage: @node-core/doc-kit generate [options]

Expand Down
7 changes: 6 additions & 1 deletion bin/commands/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Command, Option } from 'commander';

import { publicGenerators } from '../../src/generators/index.mjs';
import createGenerator from '../../src/generators.mjs';
import { setConfig } from '../../src/utils/configuration/index.mjs';
import {
assertRunnableOptions,
setConfig,
} from '../../src/utils/configuration/index.mjs';
import { errorWrap } from '../utils.mjs';

const { runGenerators } = createGenerator();
Expand Down Expand Up @@ -62,6 +65,8 @@ export default new Command('generate')
.action(
errorWrap(async opts => {
const config = await setConfig(opts);
assertRunnableOptions(config);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configFile check wrong object

Medium Severity

assertRunnableOptions is run on the merged configuration from setConfig, but it still treats configFile as if it were CLI options. Merged configs never carry configFile, so that branch never applies in the generate command. Users who only pass --config-file can get an error implying they omitted it even when they did not.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 19da3ae. Configure here.


await runGenerators(config);
})
);
20 changes: 20 additions & 0 deletions src/utils/configuration/__tests__/index.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mock.module('../../loaders.mjs', {
});

const {
assertRunnableOptions,
loadConfigFile,
createConfigFromCLIOptions,
createRunConfiguration,
Expand Down Expand Up @@ -125,6 +126,25 @@ describe('config.mjs', () => {
});
});

describe('assertRunnableOptions', () => {
it('should throw when neither target nor config file is provided', () => {
assert.throws(
() => assertRunnableOptions({}),
/Either `--target` or `--config-file` must be provided/
);
});

it('should not throw when a target is provided', () => {
assert.doesNotThrow(() => assertRunnableOptions({ target: ['json'] }));
});

it('should not throw when a config file is provided', () => {
assert.doesNotThrow(() =>
assertRunnableOptions({ configFile: 'config.mjs' })
);
});
});

describe('createRunConfiguration', () => {
it('should merge config sources in correct order', async () => {
mockImportFromURL.mock.mockImplementationOnce(async () =>
Expand Down
15 changes: 15 additions & 0 deletions src/utils/configuration/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ export const createConfigFromCLIOptions = options => ({
chunkSize: options.chunkSize,
});

/**
* Asserts that the CLI was given somewhere to read generator targets from:
* either explicit `--target` flags or a `--config-file` that supplies them.
*
* @param {import('../../../bin/commands/generate.mjs').CLIOptions} options - User-provided options
*/
export const assertRunnableOptions = options => {
if (!options.target && !options.configFile) {
throw new Error(
'Either `--target` or `--config-file` must be provided. ' +
'Run `doc-kit generate --help` for usage.'
);
}
Comment thread
cursor[bot] marked this conversation as resolved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runnable guard skips input

Medium Severity

The new assertRunnableOptions gate only checks target and configFile, not input. After merge, a run can pass validation with generators set but no global.input, then fail later in the pipeline when generators call methods like flatMap on undefined input.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 19da3ae. Configure here.

};

/**
* Creates a complete run configuration by merging config file, user options, and defaults.
* Processes and validates configuration values including version coercion, changelog parsing,
Expand Down
Loading