chore: Migrate to eslint 10 - #1447
Merged
Merged
Conversation
Replaces eslint-plugin-import with eslint-plugin-import-x, and drops FlatCompat in favour of the plugins' native flat configs. eslint-plugin-import cannot run under eslint 10: import/order calls SourceCode#getTokenOrCommentBefore/After, which v10 removed. Upstream support was merged in June 2026 but is still unreleased, so we move to the maintained fork instead. Every import/* rule becomes import-x/*, including in eslint-disable comments. no-cycle's disableScc option is not in import-x's schema; it defaulted to false, so dropping it changes nothing. @eslint/eslintrc goes with the eslintrc format itself. The two compat.extends() calls become import-x's flatConfigs.typescript and jest's flat/recommended. We take only settings and rules from the former, because it registers import-x itself and v10 rejects a redefinition. jest is now registered alongside the other plugins so that eslint-disable jest/* comments still resolve in every file, as the global plugin:jest/recommended extend used to allow. globals becomes an explicit dependency, having previously arrived transitively via @eslint/eslintrc. The root .eslintrc.json was already dead after the flat config move, and v10 would not read it anyway. Four source fixes, all verified against an eslint 9 baseline so that the migration adds no new lint output: - no-useless-assignment is new in v10's recommended set, and correctly flags the unread initialiser in readContract. - import-x/no-named-as-default: the supports-color default import shadowed that module's own named export. Renamed the binding rather than the import style, since forceColour depends on load order. - jest/no-export now fires on case-core's jest test helper. This is upstream: plugin v29 broadened the rule to trigger on describe, where v28 only triggered on test. Added the same file-level disable the sibling helper in contract-case-jest already carries. - import-x resolves case-connector-proto's barrel to the generated .d.ts files and then reports the `export type *` lines as duplicate exports missing an extension, neither of which eslint-plugin-import did. Scoped both rules off for that file rather than change a published package's type surface. Co-Authored-By: Claude Opus 5 <[email protected]>
TimothyJones
enabled auto-merge (squash)
September 14, 2026 04:44
TimothyJones
disabled auto-merge
September 15, 2026 01:18
TimothyJones
enabled auto-merge (squash)
September 15, 2026 01:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrates the workspace to ESLint 10: the shared
eslint-config-case-maintainerpackage, and each of the 18 packages that consume it.The blocker: eslint-plugin-import
[email protected]cannot run under ESLint 10.import/ordercallsSourceCode#getTokenOrCommentBefore/After, which v10 removed, and that rule iserrorin our config — so it crashes rather than merely warning about peer ranges. Upstream support was merged in June 2026 but is still unreleased.This PR moves to
eslint-plugin-import-x@4, which declares ESLint 10 support and has all 44import/*rules we use. Every rule and settings key becomesimport-x/*, in the config and ineslint-disablecomments.no-cycle'sdisableSccoption isn't in import-x's schema; it defaulted tofalse, so dropping it changes nothing.If
eslint-plugin-importdoes ship v10 support later, moving back is a mechanical rename plus restoringdisableScc— but import-x is actively maintained and already there, so there's no pressure to.Config changes
@eslint/eslintrc/FlatCompat— the eslintrc format is gone in v10. The twocompat.extends()calls now use native flat configs: import-x'sflatConfigs.typescriptand jest'sflat/recommended. We take onlysettingsandrulesfrom the former, since it registersimport-xitself and v10 rejects a redefinition.jestis now registered alongside the other plugins, soeslint-disable jest/*comments still resolve in every file the way the globalplugin:jest/recommendedextend allowed.@eslint/jsto ^10,@typescript-eslint/*to ^8.70,eslint-plugin-jestto ^29.globalsas an explicit dependency — it had been arriving transitively via@eslint/eslintrc.eslint: ^10as a peer dependency;engines.node→>=22.13.0to match ESLint 10's floor. CI already runs 22.x/24.x/26.x..eslintrc.json, dead since the flat-config move and unreadable by v10 regardless.Source fixes
Four, each a real finding rather than a silencing:
no-useless-assignment(new in v10's recommended set) correctly flagslet content = ''inreadContract— the initialiser is never read.import-x/no-named-as-default:import supportsColor from 'supports-color'shadowed that module's own named export. Renamed the binding rather than switching import style, sinceforceColourdepends on load order.jest/no-exportoncase-core's jest test helper. Upstream change, not ours: plugin v29 broadened the rule to trigger ondescribe, where v28 only triggered ontest. Added the same file-level disable the sibling helper incontract-case-jestalready carries.case-connector-proto/src/index.d.ts: import-x resolves the barrel to the generated.d.tsfiles and then reports theexport type *lines as duplicate exports missing an extension — neither of whicheslint-plugin-importdid. Scoped both rules off for that one file rather than change a published package's type surface, since a297ce9 added those lines deliberately.Verification
nx run-many -t lint— 18/18 projects passnx run-many -t build— 20/20 passnx run-many -t test— full suite passesnx run-many -t format:check— cleanTo be sure the migration adds no new lint output, I ran ESLint 9 against a worktree of clean
mainand compared. The remaining warnings — 1jest/expect-expect, 1jest/no-disabled-tests, 8 unused-disable-directives — are present in that baseline at identical counts. That baseline is also how finding 3 was confirmed as upstream rather than a side effect of restructuring the jest config.Generated docs examples are unaffected: the extractor strips
eslint-disablecomments, so no regeneration is needed.🤖 Generated with Claude Code