From 9c5f834334133bee7e8544cbce21046143c7578c Mon Sep 17 00:00:00 2001 From: gnezim Date: Tue, 14 Apr 2026 22:01:10 +0300 Subject: [PATCH] Migrate ESLint to flat config for v9 compatibility Replaces the FlatCompat shim (which loaded .eslintrc.cjs via @eslint/eslintrc and emitted deprecation warnings) with a native ESLint 9 flat config. Adds typescript-eslint meta-package as the flat-config entrypoint and pins @eslint/js to v9 to satisfy the eslint@9 peer range. Rule set is preserved verbatim from the Phase 1A-1 plan (Task 4). --- .eslintignore | 6 ---- .eslintrc.cjs | 34 ----------------------- eslint.config.js | 72 ++++++++++++++++++++++++++++++------------------ package.json | 2 ++ pnpm-lock.yaml | 24 ++++++++++++++++ 5 files changed, 71 insertions(+), 67 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.cjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 4fbf2560..00000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -dist/ -node_modules/ -ClientApp/ -wwwroot/ -*.cjs -pnpm-lock.yaml diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 7e9c86bc..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,34 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 2023, - sourceType: "module", - project: "./tsconfig.json", - ecmaFeatures: { jsx: true }, - }, - plugins: ["@typescript-eslint", "unused-imports"], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - ], - rules: { - "@typescript-eslint/no-unused-vars": "off", - "unused-imports/no-unused-imports": "error", - "unused-imports/no-unused-vars": [ - "warn", - { - vars: "all", - varsIgnorePattern: "^_", - args: "after-used", - argsIgnorePattern: "^_", - }, - ], - "@typescript-eslint/consistent-type-imports": ["error", { prefer: "type-imports" }], - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-non-null-assertion": "warn", - "no-console": ["warn", { allow: ["warn", "error"] }], - }, - ignorePatterns: ["dist/", "node_modules/", "ClientApp/", "wwwroot/", "*.cjs"], -}; diff --git a/eslint.config.js b/eslint.config.js index e713e787..fbf01305 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,37 +1,55 @@ -// ESLint v9 flat-config shim that loads the legacy `.eslintrc.cjs` via FlatCompat. -// The plan (`docs/superpowers/plans/2026-04-14-phase-1a1-skeleton.md`, Task 4) -// specifies `.eslintrc.cjs` verbatim, but ESLint v9 requires a flat config file -// to be present. This shim preserves the plan's rule set without modifying -// package.json's `lint` script. A future batch can migrate fully to flat config. - -import { FlatCompat } from "@eslint/eslintrc"; +// ESLint v9 flat config. Mirrors the rule set from +// docs/superpowers/plans/2026-04-14-phase-1a1-skeleton.md (Task 4). import js from "@eslint/js"; -import { createRequire } from "node:module"; -import { fileURLToPath } from "node:url"; -import path from "node:path"; - -const require = createRequire(import.meta.url); -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const legacyConfig = require("./.eslintrc.cjs"); - -const compat = new FlatCompat({ - baseDirectory: __dirname, - resolvePluginsRelativeTo: __dirname, - recommendedConfig: js.configs.recommended, -}); +import tseslint from "typescript-eslint"; +import unusedImports from "eslint-plugin-unused-imports"; export default [ { ignores: [ - "dist/", - "node_modules/", - "ClientApp/", - "wwwroot/", + "dist/**", + "node_modules/**", + "ClientApp/**", + "wwwroot/**", "**/*.cjs", "pnpm-lock.yaml", ], }, - ...compat.config(legacyConfig), + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ["src/**/*.{ts,tsx}"], + languageOptions: { + parser: tseslint.parser, + parserOptions: { + ecmaVersion: 2023, + sourceType: "module", + project: "./tsconfig.json", + ecmaFeatures: { jsx: true }, + }, + }, + plugins: { + "unused-imports": unusedImports, + }, + rules: { + "@typescript-eslint/no-unused-vars": "off", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": [ + "warn", + { + vars: "all", + varsIgnorePattern: "^_", + args: "after-used", + argsIgnorePattern: "^_", + }, + ], + "@typescript-eslint/consistent-type-imports": [ + "error", + { prefer: "type-imports" }, + ], + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-non-null-assertion": "warn", + "no-console": ["warn", { allow: ["warn", "error"] }], + }, + }, ]; diff --git a/package.json b/package.json index b572bf1a..a74b0469 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "zod": "^3.23.0" }, "devDependencies": { + "@eslint/js": "^9.39.4", "@types/node": "^24.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", @@ -31,6 +32,7 @@ "eslint": "^9.0.0", "eslint-plugin-unused-imports": "^4.0.0", "typescript": "^5.5.0", + "typescript-eslint": "^8.58.2", "vite": "^6.0.0", "vitest": "^3.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7149907..107c1a8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^3.23.0 version: 3.25.76 devDependencies: + '@eslint/js': + specifier: ^9.39.4 + version: 9.39.4 '@types/node': specifier: ^24.0.0 version: 24.12.2 @@ -33,6 +36,9 @@ importers: typescript: specifier: ^5.5.0 version: 5.9.3 + typescript-eslint: + specifier: ^8.58.2 + version: 8.58.2(eslint@9.39.4)(typescript@5.9.3) vite: specifier: ^6.0.0 version: 6.4.2(@types/node@24.12.2) @@ -927,6 +933,13 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + typescript-eslint@8.58.2: + resolution: {integrity: sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -1835,6 +1848,17 @@ snapshots: dependencies: prelude-ls: 1.2.1 + typescript-eslint@8.58.2(eslint@9.39.4)(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@9.39.4)(typescript@5.9.3) + eslint: 9.39.4 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + typescript@5.9.3: {} undici-types@7.16.0: {}