-
Notifications
You must be signed in to change notification settings - Fork 921
Description
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
Migrate from the legacy .eslintrc configuration (with @rushstack/eslint-patch for module resolution) to ESLint 9's flat config format (eslint.config.mjs). This removes the rushstack workaround entirely, as flat config resolves plugins via direct imports — the exact problem rushstack was patching around.
Complexity: Medium
Target branch: develop
Context
The project currently uses @rushstack/eslint-patch/modern-module-resolution in the root .eslintrc.js to work around ESLint's legacy plugin resolution issues. The actual ESLint configuration lives in packages/kolibri-format/.eslintrc.js and is loaded programmatically by packages/kolibri-format/index.js using the ESLint Node.js API (new ESLint({ baseConfig, resolvePluginsRelativeTo })).
Key files involved:
.eslintrc.js(root) — requires rushstack patch, delegates to kolibri-formatpackages/kolibri-format/.eslintrc.js— all rules, plugins, extendspackages/kolibri-format/index.js— programmatic ESLint API usagepackages/eslint-plugin-kolibri/— custom lint rules (CJS, exportsrulesobject)
kolibri-format is also consumed by projects outside this monorepo that may provide their own ESLint config, so the host-project config lookup pattern must be preserved.
Original issue context
The issue that motivated rushstack/eslint has some recent updates:
Hi folks! Just an update that the new ESLint configuration has now been enabled as an experiment. This new config system eliminates the special treatment of shared configs so that you can include plugins as direct dependencies.
Originally posted by @MisRob in #9698 (comment)
The Change
Upgrade from ESLint 8 to ESLint 9 and convert the configuration from legacy .eslintrc format to flat config (eslint.config.mjs).
Key changes:
- Replace
.eslintrc.jsfiles witheslint.config.mjsfiles using ESM imports - Replace
eslint-plugin-importwitheslint-plugin-import-x(the maintained fork with native flat config support) - Update
packages/kolibri-format/index.jsto load the new config viaawait import()and use ESLint 9's API (which removesresolvePluginsRelativeTo— no longer needed since flat config resolves plugins via direct imports) - Remove
@rushstack/eslint-patchfrom rootpackage.json - Strict 1:1 rule parity — no rule additions, removals, or severity changes. The only rule name changes are the mechanical
import/→import-x/rename.
eslint-plugin-kolibri and eslint-plugin-small-import need no changes — their CJS rules exports work as flat config plugins as-is.
Out of Scope
- Changing, adding, or removing any lint rules (beyond the
import/→import-x/rename) - Modernizing
eslint-plugin-kolibrito ESM - Converting
kolibri-format/index.jsto ESM - Upgrading other linting tools (prettier, stylelint)
Acceptance Criteria
General
-
@rushstack/eslint-patchis removed from rootpackage.json - Root
.eslintrc.jsis replaced byeslint.config.mjs -
packages/kolibri-format/.eslintrc.jsis replaced byeslint.config.mjs -
packages/kolibri-format/index.jsuses ESLint 9 API withawait import()for config loading - Host-project config lookup is preserved (check for
eslint.config.mjsin host project, fall back to own) -
eslint-plugin-importis replaced byeslint-plugin-import-x - All existing lint rules produce identical results — no new warnings or errors introduced
Testing
-
pre-commit run lint-frontend --all-filesoutput is identical before and after migration -
eslint-plugin-kolibritests pass - Manual smoke test: deliberate
import-x/rule violations (duplicate imports, wrong order, missing newline after imports) are caught
References
AI usage
This issue was restructured from a rough initial description using Claude Code. The design decisions (ESLint version, config format, plugin choices, migration approach) were made collaboratively through iterative Q&A, drawing on findings from a previous contributor's implementation attempt documented in the issue comments. The acceptance criteria and scope were reviewed and confirmed by a human maintainer.
