Skip to content

Commit 7ca8e29

Browse files
committed
refactor(create-cli): modularize yargs parser
1 parent f6d3701 commit 7ca8e29

3 files changed

Lines changed: 90 additions & 45 deletions

File tree

packages/create-cli/src/index.ts

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#! /usr/bin/env node
2-
import yargs from 'yargs';
32
import { hideBin } from 'yargs/helpers';
43
import { axeSetupBinding } from '@code-pushup/axe-plugin';
54
import { coverageSetupBinding } from '@code-pushup/coverage-plugin';
@@ -8,13 +7,8 @@ import { jsPackagesSetupBinding } from '@code-pushup/js-packages-plugin';
87
import { jsDocsSetupBinding } from '@code-pushup/jsdocs-plugin';
98
import { lighthouseSetupBinding } from '@code-pushup/lighthouse-plugin';
109
import { typescriptSetupBinding } from '@code-pushup/typescript-plugin';
11-
import { parsePluginSlugs, validatePluginSlugs } from './lib/setup/plugins.js';
12-
import {
13-
CI_PROVIDERS,
14-
CONFIG_FILE_FORMATS,
15-
type PluginSetupBinding,
16-
SETUP_MODES,
17-
} from './lib/setup/types.js';
10+
import { yargsCli } from './lib/setup/cli-args.js';
11+
import type { PluginSetupBinding } from './lib/setup/types.js';
1812
import { runSetupWizard } from './lib/setup/wizard.js';
1913

2014
const bindings: PluginSetupBinding[] = [
@@ -27,42 +21,6 @@ const bindings: PluginSetupBinding[] = [
2721
jsDocsSetupBinding,
2822
];
2923

30-
const argv = await yargs(hideBin(process.argv))
31-
.option('dry-run', {
32-
type: 'boolean',
33-
default: false,
34-
describe: 'Preview changes without writing files',
35-
})
36-
.option('yes', {
37-
alias: 'y',
38-
type: 'boolean',
39-
default: false,
40-
describe: 'Skip prompts and use defaults',
41-
})
42-
.option('config-format', {
43-
type: 'string',
44-
choices: CONFIG_FILE_FORMATS,
45-
describe: 'Config file format (default: auto-detected from project)',
46-
})
47-
.option('plugins', {
48-
type: 'string',
49-
describe: 'Comma-separated plugin slugs to include (e.g. eslint,coverage)',
50-
coerce: parsePluginSlugs,
51-
})
52-
.option('mode', {
53-
type: 'string',
54-
choices: SETUP_MODES,
55-
describe: 'Setup mode (default: auto-detected from project)',
56-
})
57-
.option('ci', {
58-
type: 'string',
59-
choices: CI_PROVIDERS,
60-
describe: 'CI/CD integration (github, gitlab, or none)',
61-
})
62-
.check(parsed => {
63-
validatePluginSlugs(bindings, parsed.plugins);
64-
return true;
65-
})
66-
.parse();
24+
const argv = await yargsCli(bindings).parse(hideBin(process.argv));
6725

6826
await runSetupWizard(bindings, argv);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import yargs, { type Argv } from 'yargs';
2+
import { parsePluginSlugs, validatePluginSlugs } from './plugins.js';
3+
import {
4+
CI_PROVIDERS,
5+
CONFIG_FILE_FORMATS,
6+
type PluginSetupBinding,
7+
SETUP_MODES,
8+
} from './types.js';
9+
10+
export function yargsCli(bindings: PluginSetupBinding[]): Argv {
11+
return yargs()
12+
.scriptName('create-cli')
13+
.usage('$0 [options]')
14+
.parserConfiguration({ 'dot-notation': false })
15+
.option('dry-run', {
16+
type: 'boolean',
17+
default: false,
18+
describe: 'Preview changes without writing files',
19+
})
20+
.option('yes', {
21+
alias: 'y',
22+
type: 'boolean',
23+
default: false,
24+
describe: 'Skip prompts and use defaults',
25+
})
26+
.option('config-format', {
27+
type: 'string',
28+
choices: CONFIG_FILE_FORMATS,
29+
describe: 'Config file format (default: auto-detected from project)',
30+
})
31+
.option('plugins', {
32+
type: 'string',
33+
describe:
34+
'Comma-separated plugin slugs to include (e.g. eslint,coverage)',
35+
coerce: parsePluginSlugs,
36+
})
37+
.option('mode', {
38+
type: 'string',
39+
choices: SETUP_MODES,
40+
describe: 'Setup mode (default: auto-detected from project)',
41+
})
42+
.option('ci', {
43+
type: 'string',
44+
choices: CI_PROVIDERS,
45+
describe: 'CI/CD integration (github, gitlab, or none)',
46+
})
47+
.check(parsed => {
48+
validatePluginSlugs(bindings, parsed.plugins);
49+
return true;
50+
})
51+
.help()
52+
.version();
53+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { yargsCli } from './cli-args.js';
2+
import type { PluginSetupBinding } from './types.js';
3+
4+
const bareBindings: PluginSetupBinding[] = [
5+
{
6+
slug: 'eslint',
7+
title: 'ESLint',
8+
packageName: '@code-pushup/eslint-plugin',
9+
generateConfig: () => ({ imports: [], pluginInit: [] }),
10+
},
11+
];
12+
13+
describe('yargsCli', () => {
14+
it('should expose --eslint.patterns as a flat key', async () => {
15+
const argv = await yargsCli(bareBindings).parse([
16+
'--eslint.patterns',
17+
'src',
18+
]);
19+
20+
expect(argv['eslint.patterns']).toBe('src');
21+
});
22+
23+
it('should expose --no-eslint.categories as a flat false', async () => {
24+
const argv = await yargsCli(bareBindings).parse(['--no-eslint.categories']);
25+
26+
expect(argv['eslint.categories']).toBeFalse();
27+
});
28+
29+
it('should expose --eslint.categories without a value as a flat true', async () => {
30+
const argv = await yargsCli(bareBindings).parse(['--eslint.categories']);
31+
32+
expect(argv['eslint.categories']).toBeTrue();
33+
});
34+
});

0 commit comments

Comments
 (0)