Skip to content

Migrate ESLint to flat config so ESLint 9 can land - #1325

Merged
Rupesh-ark merged 1 commit into
mainfrom
devill/eslint-flat-config
Aug 10, 2026
Merged

Migrate ESLint to flat config so ESLint 9 can land#1325
Rupesh-ark merged 1 commit into
mainfrom
devill/eslint-flat-config

Conversation

@devill

@devill devill commented Aug 4, 2026

Copy link
Copy Markdown
Member

Closes #1324.

pnpm run lint still ran ESLint 8.57.1, which is no longer supported, and #1302 (the Dependabot bump to ESLint 9) cannot land because ESLint 9 removed .eslintrc and .eslintignore.

This replaces both with a single eslint.config.js, porting the existing extends, plugins, parser, env, rules and settings to their flat-config equivalents at the plugin versions already installed — nothing needed upgrading first. eslint moves to ^9, @eslint/js is promoted from a transitive dependency to a direct devDependency, and globals is added.

Behaviour is preserved

pnpm run lint reports zero problems both before and after, over the same files:

files linted problems
ESLint 8.57.1 + .eslintrc 127 (19 .js, 99 .ts, 9 .tsx) 0
ESLint 9.39.5 + eslint.config.js 129 (20 .js, 1 .cjs, 99 .ts, 9 .tsx) 0

No file loses coverage. The two added are eslint.config.js itself and jest-svelte-transformer.cjs — flat config lints .cjs by default, where ESLint 8's eslint . did not.

Three deliberate adjustments keep the reported problem set unchanged:

  • Flat config lints dotfiles that .eslintrc skipped by default, so the jsdom stub .empty_module.js is added to ignores.
  • Flat config defaults reportUnusedDisableDirectives to warn; it is pinned back to off.
  • /* eslint-env es2020 */ is no longer supported, so it is dropped from jest.setup.js — those globals now come from languageOptions.globals.

Testing

pnpm run lint is green, and pnpm test passes 43 suites / 903 tests (1 todo).

Replace `.eslintrc` and `.eslintignore` with a single `eslint.config.js`,
porting the existing extends, plugins, parser, env, rules and settings to
their flat-config equivalents at the already-installed plugin versions:

- `eslint:recommended` -> `@eslint/js` `js.configs.recommended`
- `plugin:jest/recommended` -> `configs['flat/recommended']`
- `plugin:unicorn/recommended` -> `configs['flat/recommended']`
- `plugin:react/recommended` -> `configs.flat.recommended`
- `plugin:@typescript-eslint/recommended` -> `configs['flat/recommended']`
- `plugin:prettier/recommended` -> `eslint-plugin-prettier/recommended`

`env: { node, browser, es6 }` becomes `languageOptions.globals`, and the
seven `.eslintignore` entries become an `ignores` block.

Bump `eslint` to ^9, promote `@eslint/js` to a direct devDependency, and
add `globals`.

The migration is behaviour-preserving -- `pnpm run lint` reports the same
(zero) problems before and after across the same files:

- Flat config lints dotfiles that `.eslintrc` skipped by default, so the
  jsdom stub `.empty_module.js` is added to `ignores` to stay unlinted.
- Flat config defaults `reportUnusedDisableDirectives` to "warn"; pin it
  back to "off" to match the previous default.
- Drop the now-unsupported `/* eslint-env es2020 */` comment from
  `jest.setup.js`; its globals are covered by `languageOptions.globals`.

`pnpm run lint` and `pnpm test` (43 suites / 903 passed) are green on
ESLint 9.

@Rupesh-ark Rupesh-ark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@Rupesh-ark
Rupesh-ark merged commit 5e9a2c9 into main Aug 10, 2026
5 checks passed
@Rupesh-ark
Rupesh-ark deleted the devill/eslint-flat-config branch August 10, 2026 12:46
tbsvttr added a commit to tbsvttr/boardgame.io that referenced this pull request Aug 18, 2026
The ESLint major hold was added in boardgameio#1323 because .eslintrc could not survive
ESLint 9, and boardgameio#1324 asked for it to come out once flat config landed. boardgameio#1325
landed flat config, but taking the hold out now would let ESLint 10 in, and
that is a harder stop than the one it replaces: eslint-plugin-react 7.37.5 is
the plugin's latest release, peers `^9.7`, and throws on 10 —

    TypeError: Error while loading rule 'react/display-name':
      contextOrFilename.getFilename is not a function

So the hold stays and its rationale is rewritten to say what actually blocks
it, and what would unblock it.

Two neighbours of eslint were never covered and can each redden the weekly
grouped pull request on their own, since a group is only as mergeable as its
worst member:

  * @eslint/js 10.0.1 resolves against eslint 9 without complaint, then turns
    on rules 9 ships no baseline for — `eslint .` goes from 0 problems to 7
    (preserve-caught-error x4, no-useless-assignment x3).
  * eslint-plugin-unicorn 65.0.0, the highest that resolves against ESLint 9,
    reports 24 problems. Several autofixes are not cosmetic: unicorn/prefer-https
    rewrites `http://example.com` to `https://` inside the CORS fixtures whose
    tests assert those origins are rejected, and unicorn/prefer-queue-microtask
    swaps `process.nextTick` for `queueMicrotask`, which schedules differently.

Both are deliberate, documented holds with an exit condition rather than
silent pins.
tbsvttr added a commit to tbsvttr/boardgame.io that referenced this pull request Aug 18, 2026
boardgameio#1325 deleted .eslintrc, but the commands section still sends agents there to
find out how linting is configured.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate to ESLint flat config, so ESLint 9 can land

2 participants