-
Notifications
You must be signed in to change notification settings - Fork 2
Description
User story
See parent issue:
Usage examples
Default config only
Input
npm init @code-pushup/cliWhich configurations would you like to set up?
- JavaScript (default)
- TypeScript (strict)
- Node.js
- Angular
- Angular & NgRx
- React
- GraphQL (server)
- Jest
- Vitest
- Cypress
- Playwright
- Storybook
- React Testing Library
Output
Installs required peer dependencies:
npm install --save-dev \
eslint@^9.0.0 \
@eslint/js@^9.0.0 \
"eslint-plugin-functional@^7.0.0 || ^8.0.0 || ^9.0.0" \
eslint-plugin-import@^2.31.0 \
"eslint-plugin-promise@>=6.4.0" \
eslint-plugin-sonarjs@^1.0.4 \
"eslint-plugin-unicorn@>=50.0.0" \
"globals@>=14.0.0" \
typescript-eslint@^8.0.0Installs our config package:
npm install --save-dev @code-pushup/eslint-configCreates eslint.config.js:
import javascript from '@code-pushup/eslint-config/javascript.js';
import { defineConfig } from 'eslint/config';
export default defineConfig(...javascript);Multiple configs, with additional configuration steps
Input
npm init @code-pushup/cliWhich configurations would you like to set up?
- JavaScript (default)
- TypeScript (strict)
- Node.js
- Angular
- Angular & NgRx
- React
- GraphQL (server)
- Jest
- Vitest
- Cypress
- Playwright
- Storybook
- React Testing Library
The selected "TypeScript (strict)" configuration requires additional setup. Which tsconfig should be used?
- Enter file path: tsconfig.json
Output
Installs required peer dependencies:
npm install --save-dev \
eslint@^9.0.0 \
@eslint/js@^9.0.0 \
"eslint-plugin-functional@^7.0.0 || ^8.0.0 || ^9.0.0" \
eslint-plugin-import@^2.31.0 \
"eslint-plugin-promise@>=6.4.0" \
eslint-plugin-sonarjs@^1.0.4 \
"eslint-plugin-unicorn@>=50.0.0" \
"globals@>=14.0.0" \
typescript-eslint@^8.0.0Installs optional peer dependencies that are required by selected configs:
npm install --save-dev \
"eslint-import-resolver-typescript@^3.0.0 || ^4.0.0" \
@vitest/eslint-plugin@^1.1.9Installs our config package:
npm install --save-dev @code-pushup/eslint-configCreates eslint.config.js, including all configs and their additional setup steps:
import typescript from '@code-pushup/eslint-config/typescript.js';
import vitest from '@code-pushup/eslint-config/vitest.js';
import { defineConfig } from 'eslint/config';
export default defineConfig(
...typescript,
...vitest,
{
files: ['**/*.ts'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: 'tsconfig.json',
},
},
},
},
);Extending existing config
Input
The user has the following eslint.config.js:
import jsxA11y from 'eslint-plugin-jsx-a11y';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
export default [
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
jsxA11y.flatConfigs.recommended,
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
}
},
];The user runs npm init @code-pushup/eslint-config and selects React and React Testing Library configs.
Output
The selected configs are appended to the flat config array.
import jsxA11y from 'eslint-plugin-jsx-a11y';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import cpReact from '@code-pushup/eslint-config/react.js';
import cpReactTestingLibrary from '@code-pushup/eslint-config/react-testing-library.js';
export default [
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
jsxA11y.flatConfigs.recommended,
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
}
},
...cpReact,
...cpReactTestingLibrary,
];Implementation
In general, use the same approach as for @code-pushup/create-cli.
Acceptance criteria
- The setup wizard can be triggered by
npm initcommand. - Alternatively, the setup wizard can be imported and invoked programmatically.
- Inputs are handled as interactive user prompts by default, but may be skipped if an equivalent CLI argument is supplied.
- The setup wizard prompts the user to select a subset of the available configs.
- Configs are pre-selected in the prompt based on information from the user's current working directory.
- The
javascriptconfig is always pre-selected. - The
typescriptconfig is pre-selected if there's atsconfig.jsonfile ortypescriptis installed. - The
nodeconfig is pre-selected if any well-known backend frameworks (express,@nestjs/core,@apollo/server,fastify) or full-stack frameworks (next,@angular/ssr,nuxt,@sveltejs/kit) are installed. - The
angularconfig is pre-selected if@angular/coreis installed. - The
ngrxconfig is pre-selected if@ngrx/coreis installed. - The
reactconfig is pre-selected ifreactis installed. - The
graphqlconfig is pre-selected if one of@apollo/server,graphql-yoga, ortype-graphqlis installed. - The
jestconfig is pre-selected ifjestis installed or there's a/^jest\.config\.[cm]?[jt]s$/file. - The
vitestconfig is pre-selected ifvitestis installed or there's a/^(vite|vitest)\.config\.m?[jt]s$/file. - The
cypressconfig is pre-selected ifcypressis installed or there's a/^cypress\.config\.[cm]?[jt]s$/file. - The
playwrightconfig is pre-selected if@playwright/testis installed or there's aplaywright.config.tsfile. - The
storybookconfig is pre-selected ifstorybookis installed or there's a.storybookfolder. - The
react-testing-libraryconfig is pre-selected if@testing-library/reactis installed.
- The
- If a config with additional setup steps is selected, then there are additional user prompts.
- If
typescriptis selected, then the user should provide their tsconfig path. The default value should betsconfig.jsonor anytsconfig.*.jsonif such a file is found. - If
nodeis selected, then the user should provide their Node version source.- Their options are (in descending order of priority):
- Use .node-version file - Pre-selected if such a file exists. If selected, then
settings.node.versionis set tofs.readFileSync('.node-version', 'utf8')ineslint.config.js. - Use engines.node from package.json - Pre-selected if field exists in
package.json. - Enter Node version range - If selected, then
settings.node.versionis set to a user-submitted value.
- Use .node-version file - Pre-selected if such a file exists. If selected, then
- If the user chose to enter a version manually - or they picked another option and it doesn't exist yet at that location - they are prompted to enter a Node version range (e.g., >=24.8.0). This value is validated and written to the selected location.
- Their options are (in descending order of priority):
- If
- All required peer dependencies are installed.
- If configs with additional peer dependencies are selected, those peer dependencies are also installed.
- The
@code-pushup/eslint-configpackage is installed. - If there is no
eslint.config.js, then it is created. The selected configs are included in it. - If an
eslint.config.jsalready exists, then it is modified. The selected configs are appended to the flat config array.- If the
eslint.config.jsfile is in CommonJS format, then the user is informed that Only ESLint configs in ESM format are supported and the setup wizard terminates without making any changes. - The file modifications handle exports with or without config functions (
defineConfigortseslint.config).
- If the