import js from '@eslint/js'; import globals from 'globals'; import reactHooks from 'eslint-plugin-react-hooks'; import reactRefresh from 'eslint-plugin-react-refresh'; import tseslint from 'typescript-eslint'; // Flat config scoped to the React client. The point is enforcement of the two // rules that catch real React bugs — rules-of-hooks (conditional hooks) and // exhaustive-deps (stale closures) — which nothing previously checked. Server // code (CommonJS Node) is out of scope here; `npm run check:server` covers it. export default [ { ignores: ['dist/**', 'node_modules/**', 'coverage/**', 'client/**/*.test.*'] }, { files: ['client/**/*.{js,jsx}'], languageOptions: { ecmaVersion: 2023, sourceType: 'module', globals: { ...globals.browser }, parserOptions: { ecmaFeatures: { jsx: true } }, }, plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh, }, rules: { ...js.configs.recommended.rules, // The two that matter most for correctness: 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', // HMR safety (Vite fast-refresh); allow non-component constant exports. 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], // Keep the js-recommended noise as warnings so hook signal isn't drowned out. 'no-unused-vars': ['warn', { varsIgnorePattern: '^[A-Z_]', argsIgnorePattern: '^_' }], 'no-empty': ['warn', { allowEmptyCatch: true }], }, }, { // TypeScript files: same react-hooks/react-refresh enforcement, via the // TS parser. TS itself handles undefined identifiers + unused vars, so the // core rules that don't understand types are swapped for their TS-aware // equivalents. (Not the full typescript-eslint recommended set — this keeps // the signal focused on the same correctness rules as the JS config.) files: ['client/**/*.{ts,tsx}'], languageOptions: { parser: tseslint.parser, ecmaVersion: 2023, sourceType: 'module', globals: { ...globals.browser }, parserOptions: { ecmaFeatures: { jsx: true } }, }, plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh, '@typescript-eslint': tseslint.plugin, }, rules: { 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], 'no-undef': 'off', // TypeScript checks this 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': ['warn', { varsIgnorePattern: '^[A-Z_]', argsIgnorePattern: '^_' }], 'no-empty': ['warn', { allowEmptyCatch: true }], }, }, ];