From f89037adcd97ba67cd395bb316aba63cdaab77c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Chalk?= Date: Tue, 28 May 2024 13:21:50 +0200 Subject: [PATCH] feat(plugin-eslint): support implicit configs --- packages/plugin-eslint/README.md | 4 +- packages/plugin-eslint/src/lib/config.ts | 42 ++++++++++++------- .../src/lib/nx.integration.test.ts | 6 --- .../lib/nx/projects-to-config.unit.test.ts | 8 ---- packages/plugin-eslint/src/lib/nx/utils.ts | 6 ++- packages/plugin-eslint/src/lib/runner/lint.ts | 8 ++-- .../src/lib/runner/lint.unit.test.ts | 2 - packages/plugin-eslint/src/lib/setup.ts | 9 ++-- 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/packages/plugin-eslint/README.md b/packages/plugin-eslint/README.md index e0c14a80a..5a83efcd2 100644 --- a/packages/plugin-eslint/README.md +++ b/packages/plugin-eslint/README.md @@ -43,7 +43,7 @@ Detected ESLint rules are mapped to Code PushUp audits. Audit reports are calcul 4. Add this plugin to the `plugins` array in your Code PushUp CLI config file (e.g. `code-pushup.config.js`). - Pass in the path to your ESLint config file, along with glob patterns for which files you wish to target (relative to `process.cwd()`). + Pass in the glob patterns for which files you wish to target (relative to `process.cwd()`). ```js import eslintPlugin from '@code-pushup/eslint-plugin'; @@ -52,7 +52,7 @@ Detected ESLint rules are mapped to Code PushUp audits. Audit reports are calcul // ... plugins: [ // ... - await eslintPlugin({ eslintrc: '.eslintrc.js', patterns: ['src/**/*.js'] }), + await eslintPlugin(['src/**/*.js']), ], }; ``` diff --git a/packages/plugin-eslint/src/lib/config.ts b/packages/plugin-eslint/src/lib/config.ts index d2942662d..aa14ccb12 100644 --- a/packages/plugin-eslint/src/lib/config.ts +++ b/packages/plugin-eslint/src/lib/config.ts @@ -2,21 +2,35 @@ import type { ESLint } from 'eslint'; import { type ZodType, z } from 'zod'; import { toArray } from '@code-pushup/utils'; -export const eslintTargetSchema = z.object({ - eslintrc: z.union( - [ - z.string({ description: 'Path to ESLint config file' }), - z.record(z.string(), z.unknown(), { - description: 'ESLint config object', - }) as ZodType, - ], - { description: 'ESLint config as file path or inline object' }, - ), - patterns: z.union([z.string(), z.array(z.string()).min(1)], { - description: - 'Lint target files. May contain file paths, directory paths or glob patterns', - }), +const patternsSchema = z.union([z.string(), z.array(z.string()).min(1)], { + description: + 'Lint target files. May contain file paths, directory paths or glob patterns', }); + +const eslintrcSchema = z.union( + [ + z.string({ description: 'Path to ESLint config file' }), + z.record(z.string(), z.unknown(), { + description: 'ESLint config object', + }) as ZodType, + ], + { description: 'ESLint config as file path or inline object' }, +); + +const eslintTargetObjectSchema = z.object({ + eslintrc: eslintrcSchema.optional(), + patterns: patternsSchema, +}); +type ESLintTargetObject = z.infer; + +export const eslintTargetSchema = z + .union([patternsSchema, eslintTargetObjectSchema]) + .transform( + (target): ESLintTargetObject => + typeof target === 'string' || Array.isArray(target) + ? { patterns: target } + : target, + ); export type ESLintTarget = z.infer; export const eslintPluginConfigSchema = z diff --git a/packages/plugin-eslint/src/lib/nx.integration.test.ts b/packages/plugin-eslint/src/lib/nx.integration.test.ts index 64a25f7cb..080b53a60 100644 --- a/packages/plugin-eslint/src/lib/nx.integration.test.ts +++ b/packages/plugin-eslint/src/lib/nx.integration.test.ts @@ -42,7 +42,6 @@ describe('Nx helpers', () => { it('should include eslintrc and patterns of each project', async () => { await expect(eslintConfigFromAllNxProjects()).resolves.toEqual([ { - eslintrc: './packages/cli/.eslintrc.json', patterns: [ 'packages/cli/**/*.ts', 'packages/cli/package.json', @@ -53,7 +52,6 @@ describe('Nx helpers', () => { ], }, { - eslintrc: './packages/core/.eslintrc.json', patterns: [ 'packages/core/**/*.ts', 'packages/core/package.json', @@ -64,7 +62,6 @@ describe('Nx helpers', () => { ], }, { - eslintrc: './packages/nx-plugin/.eslintrc.json', patterns: [ 'packages/nx-plugin/**/*.ts', 'packages/nx-plugin/package.json', @@ -76,7 +73,6 @@ describe('Nx helpers', () => { ], }, { - eslintrc: './packages/utils/.eslintrc.json', patterns: [ 'packages/utils/**/*.ts', 'packages/utils/package.json', @@ -118,7 +114,6 @@ describe('Nx helpers', () => { expect(targets).toEqual( expectedProjects.map( (p): ESLintTarget => ({ - eslintrc: `./packages/${p}/.eslintrc.json`, patterns: expect.arrayContaining([`packages/${p}/**/*.ts`]), }), ), @@ -148,7 +143,6 @@ describe('Nx helpers', () => { const targets = await eslintConfigFromNxProject(project); expect(targets).toEqual({ - eslintrc: `./packages/${project}/.eslintrc.json`, patterns: expect.arrayContaining([`packages/${project}/**/*.ts`]), }); }, diff --git a/packages/plugin-eslint/src/lib/nx/projects-to-config.unit.test.ts b/packages/plugin-eslint/src/lib/nx/projects-to-config.unit.test.ts index b00bca913..782f7b90f 100644 --- a/packages/plugin-eslint/src/lib/nx/projects-to-config.unit.test.ts +++ b/packages/plugin-eslint/src/lib/nx/projects-to-config.unit.test.ts @@ -68,15 +68,12 @@ describe('nxProjectsToConfig', () => { expect(config).toEqual([ { - eslintrc: './apps/client/.eslintrc.json', patterns: expect.arrayContaining(['apps/client/**/*.ts']), }, { - eslintrc: './apps/server/.eslintrc.json', patterns: expect.arrayContaining(['apps/server/**/*.ts']), }, { - eslintrc: './libs/models/.eslintrc.json', patterns: expect.arrayContaining(['libs/models/**/*.ts']), }, ]); @@ -108,7 +105,6 @@ describe('nxProjectsToConfig', () => { expect(config).toEqual([ { - eslintrc: './libs/models/.eslintrc.json', patterns: expect.arrayContaining(['libs/models/**/*.ts']), }, ]); @@ -150,11 +146,9 @@ describe('nxProjectsToConfig', () => { expect(config).toEqual([ { - eslintrc: './apps/client/.eslintrc.json', patterns: expect.arrayContaining(['apps/client/**/*.ts']), }, { - eslintrc: './apps/server/.eslintrc.json', patterns: expect.arrayContaining(['apps/server/**/*.ts']), }, ]); @@ -222,11 +216,9 @@ describe('nxProjectsToConfig', () => { 'apps/client/**/*.ts', 'apps/client/**/*.html', ]), - eslintrc: './apps/client/.eslintrc.json', }, { patterns: expect.arrayContaining(['apps/server/**/*.ts']), - eslintrc: './apps/server/.eslintrc.json', }, ] satisfies ESLintPluginConfig); }); diff --git a/packages/plugin-eslint/src/lib/nx/utils.ts b/packages/plugin-eslint/src/lib/nx/utils.ts index add141b82..2123fbdf5 100644 --- a/packages/plugin-eslint/src/lib/nx/utils.ts +++ b/packages/plugin-eslint/src/lib/nx/utils.ts @@ -29,9 +29,11 @@ export function getLintFilePatterns(project: ProjectConfiguration): string[] { : toArray(options.lintFilePatterns); } -export function getEslintConfig(project: ProjectConfiguration): string { +export function getEslintConfig( + project: ProjectConfiguration, +): string | undefined { const options = project.targets?.['lint']?.options as | { eslintConfig?: string } | undefined; - return options?.eslintConfig ?? `./${project.root}/.eslintrc.json`; + return options?.eslintConfig; } diff --git a/packages/plugin-eslint/src/lib/runner/lint.ts b/packages/plugin-eslint/src/lib/runner/lint.ts index 09c6e9740..95960a743 100644 --- a/packages/plugin-eslint/src/lib/runner/lint.ts +++ b/packages/plugin-eslint/src/lib/runner/lint.ts @@ -26,8 +26,8 @@ function executeLint({ command: 'npx', args: [ 'eslint', - `--config=${configPath}`, - '--no-eslintrc', + ...(configPath ? [`--config=${configPath}`] : []), + ...(typeof eslintrc === 'object' ? ['--no-eslintrc'] : []), '--no-error-on-unmatched-pattern', '--format=json', ...toArray(patterns).map(pattern => @@ -77,9 +77,9 @@ function loadRuleOptionsPerFile( async function withConfig( eslintrc: ESLintTarget['eslintrc'], - fn: (configPath: string) => Promise, + fn: (configPath: string | undefined) => Promise, ): Promise { - if (typeof eslintrc === 'string') { + if (typeof eslintrc !== 'object') { return fn(eslintrc); } diff --git a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts index a15407dcc..6ef803c80 100644 --- a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts @@ -96,7 +96,6 @@ describe('lint', () => { await lint(config); expect(ESLint).toHaveBeenCalledWith>({ overrideConfigFile: '.eslintrc.js', - useEslintrc: false, errorOnUnmatchedPattern: false, }); @@ -108,7 +107,6 @@ describe('lint', () => { args: [ 'eslint', '--config=.eslintrc.js', - '--no-eslintrc', '--no-error-on-unmatched-pattern', '--format=json', expect.stringContaining('**/*.js'), // wraps in quotes on Unix diff --git a/packages/plugin-eslint/src/lib/setup.ts b/packages/plugin-eslint/src/lib/setup.ts index bfd6dbd1e..bad15a4d9 100644 --- a/packages/plugin-eslint/src/lib/setup.ts +++ b/packages/plugin-eslint/src/lib/setup.ts @@ -3,10 +3,11 @@ import type { ESLintTarget } from './config'; export function setupESLint(eslintrc: ESLintTarget['eslintrc']) { return new ESLint({ - ...(typeof eslintrc === 'string' - ? { overrideConfigFile: eslintrc } - : { baseConfig: eslintrc }), - useEslintrc: false, + ...(typeof eslintrc === 'string' && { overrideConfigFile: eslintrc }), + ...(typeof eslintrc === 'object' && { + baseConfig: eslintrc, + useEslintrc: false, + }), errorOnUnmatchedPattern: false, }); }