diff --git a/packages/next/lib/eslint/runLintCheck.ts b/packages/next/lib/eslint/runLintCheck.ts index 33b63b9492a2f9a..8a50e8fab71e701 100644 --- a/packages/next/lib/eslint/runLintCheck.ts +++ b/packages/next/lib/eslint/runLintCheck.ts @@ -25,6 +25,14 @@ type Config = { rules: { [key: string]: Array } } +// 0 is off, 1 is warn, 2 is error. See https://eslint.org/docs/user-guide/configuring/rules#configuring-rules +const VALID_SEVERITY = ['off', 'warn', 'error'] as const +type Severity = typeof VALID_SEVERITY[number] + +function isValidSeverity(severity: string): severity is Severity { + return VALID_SEVERITY.includes(severity as Severity) +} + const requiredPackages = [ { file: 'eslint', pkg: 'eslint' }, { file: 'eslint-config-next', pkg: 'eslint-config-next' }, @@ -126,6 +134,7 @@ async function lint( let eslint = new ESLint(options) let nextEslintPluginIsEnabled = false + const nextRulesEnabled = new Map() const pagesDirRules = ['@next/next/no-html-link-for-pages'] for (const configFile of [eslintrcFile, pkgJsonPath]) { @@ -137,6 +146,23 @@ async function lint( if (completeConfig.plugins?.includes('@next/next')) { nextEslintPluginIsEnabled = true + for (const [name, [severity]] of Object.entries(completeConfig.rules)) { + if (!name.startsWith('@next/next/')) { + continue + } + if ( + typeof severity === 'number' && + severity >= 0 && + severity < VALID_SEVERITY.length + ) { + nextRulesEnabled.set(name, VALID_SEVERITY[severity]) + } else if ( + typeof severity === 'string' && + isValidSeverity(severity) + ) { + nextRulesEnabled.set(name, severity) + } + } break } } @@ -210,6 +236,7 @@ async function lint( nextEslintPluginErrorsCount: formattedResult.totalNextPluginErrorCount, nextEslintPluginWarningsCount: formattedResult.totalNextPluginWarningCount, + nextRulesEnabled: Object.fromEntries(nextRulesEnabled), }, } } catch (err) { diff --git a/packages/next/telemetry/events/build.ts b/packages/next/telemetry/events/build.ts index e68bbda1dd6d6f2..f7cb5f3e1ac7aba 100644 --- a/packages/next/telemetry/events/build.ts +++ b/packages/next/telemetry/events/build.ts @@ -34,6 +34,9 @@ export type EventLintCheckCompleted = { nextEslintPluginVersion?: string | null nextEslintPluginErrorsCount?: number nextEslintPluginWarningsCount?: number + nextRulesEnabled: { + [ruleName: `@next/next/${string}`]: 'off' | 'warn' | 'error' + } } export function eventLintCheckCompleted(event: EventLintCheckCompleted): { diff --git a/test/integration/telemetry/test/index.test.js b/test/integration/telemetry/test/index.test.js index ba86d775b31f3cc..1a76922190af182 100644 --- a/test/integration/telemetry/test/index.test.js +++ b/test/integration/telemetry/test/index.test.js @@ -529,7 +529,7 @@ describe('Telemetry CLI', () => { }) await fs.remove(path.join(appDir, '.eslintrc')) - const event1 = /NEXT_LINT_CHECK_COMPLETED[\s\S]+?{([\s\S]+?)}/ + const event1 = /NEXT_LINT_CHECK_COMPLETED[\s\S]+?{([\s\S}]+?)^}/m .exec(stderr) .pop() @@ -541,6 +541,8 @@ describe('Telemetry CLI', () => { expect(event1).toMatch(/"nextEslintPluginVersion": ".*?\..*?\..*?"/) expect(event1).toMatch(/"nextEslintPluginErrorsCount": \d{1,}/) expect(event1).toMatch(/"nextEslintPluginWarningsCount": \d{1,}/) + expect(event1).toMatch(`"nextRulesEnabled": {`) + expect(event1).toMatch(/"@next\/next\/.+?": "(off|warn|error)"/) const event2 = /NEXT_BUILD_FEATURE_USAGE[\s\S]+?{([\s\S]+?)}/ .exec(stderr) @@ -594,7 +596,7 @@ describe('Telemetry CLI', () => { }) await fs.remove(path.join(appDir, '.eslintrc')) - const event1 = /NEXT_LINT_CHECK_COMPLETED[\s\S]+?{([\s\S]+?)}/ + const event1 = /NEXT_LINT_CHECK_COMPLETED[\s\S]+?{([\s\S]+?)^}/m .exec(stderr) .pop() @@ -606,6 +608,8 @@ describe('Telemetry CLI', () => { expect(event1).toMatch(/"nextEslintPluginVersion": ".*?\..*?\..*?"/) expect(event1).toMatch(/"nextEslintPluginErrorsCount": \d{1,}/) expect(event1).toMatch(/"nextEslintPluginWarningsCount": \d{1,}/) + expect(event1).toMatch(`"nextRulesEnabled": {`) + expect(event1).toMatch(/"@next\/next\/.+?": "(off|warn|error)"/) }) it('emits telemery for usage of image, script & dynamic', async () => {