From c9ef75cd59ad774ca42892825df78703e5d34113 Mon Sep 17 00:00:00 2001 From: Zuri Klaschka Date: Fri, 6 Dec 2024 22:39:06 +0100 Subject: [PATCH] chore(frontend-react): Upgrade to ESLint v9 --- frontend-react/.eslintrc.cjs | 49 ----------- frontend-react/eslint.config.js | 87 +++++++++++++++++++ frontend-react/package.json | 8 +- frontend-react/pnpm-lock.yaml | 38 +++++++- .../application/hooks/use-widget-config.ts | 2 + .../model/layout-editor-model.ts | 2 +- frontend-react/src/lib/auth/controller.ts | 1 - frontend-react/tsconfig.node.json | 2 +- 8 files changed, 133 insertions(+), 56 deletions(-) delete mode 100644 frontend-react/.eslintrc.cjs create mode 100644 frontend-react/eslint.config.js diff --git a/frontend-react/.eslintrc.cjs b/frontend-react/.eslintrc.cjs deleted file mode 100644 index 29578c28..00000000 --- a/frontend-react/.eslintrc.cjs +++ /dev/null @@ -1,49 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/strict-type-checked', - 'plugin:@typescript-eslint/stylistic-type-checked', - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - 'plugin:prettier/recommended', - 'plugin:jsx-a11y/strict' - ], - parserOptions: { - ecmaFeatures: { jsx: true }, - ecmaVersion: 'latest', - sourceType: 'module', - project: ['./tsconfig.json', './tsconfig.node.json'], - tsconfigRootDir: __dirname - }, - ignorePatterns: [ - 'dist', - '.eslintrc.cjs', - 'types', - 'node_modules', - 'features' - ], - parser: '@typescript-eslint/parser', - plugins: ['eslint-plugin-tsdoc'], - // plugins: ['react-refresh'], - rules: { - 'react/no-unescaped-entities': 'off', - // 'react-refresh/only-export-components': 'off', - '@typescript-eslint/no-throw-literal': 'off', - '@typescript-eslint/no-confusing-void-expression': 'off', - '@typescript-eslint/consistent-type-definitions': 'off', - 'tsdoc/syntax': 'warn' - }, - settings: { - react: { version: 'detect' }, - // Support import aliases - 'import/resolver': { - typescript: { - projects: ['./tsconfig.json', './tsconfig.node.json'] - } - } - } -}; diff --git a/frontend-react/eslint.config.js b/frontend-react/eslint.config.js new file mode 100644 index 00000000..ab40e6ad --- /dev/null +++ b/frontend-react/eslint.config.js @@ -0,0 +1,87 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import pluginReact from 'eslint-plugin-react'; +import pluginReactHooks from 'eslint-plugin-react-hooks'; +import pluginPrettier from 'eslint-plugin-prettier/recommended'; +import pluginJsxA11y from 'eslint-plugin-jsx-a11y'; +import pluginTsDoc from 'eslint-plugin-tsdoc'; + +const TS_CONFIG = [ + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + { + languageOptions: { + parserOptions: { + // projectService: true, + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: import.meta.dirname + } + } + }, + { + rules: { + '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/no-confusing-void-expression': 'off', + '@typescript-eslint/consistent-type-definitions': 'off' + } + } +]; + +const REACT_CONFIG = [ + pluginReact.configs.flat.recommended, + pluginReact.configs.flat['jsx-runtime'], + { + rules: { + 'react/no-unescaped-entities': 'off' + } + }, + { + settings: { + react: { + version: 'detect' + } + } + }, // eslint-plugin-react-hooks: + { + files: ['src/**/*.{js,ts,jsx,tsx}'], + plugins: { + 'react-hooks': pluginReactHooks + }, + rules: { + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + ...pluginReactHooks.configs.recommended.rules + } + } +]; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { + files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'] + }, + { + languageOptions: { + globals: { + ...globals.browser + } + } + }, + pluginJs.configs.recommended, + ...TS_CONFIG, + ...REACT_CONFIG, + pluginPrettier, + pluginJsxA11y.flatConfigs.strict, + { + plugins: { + tsdoc: pluginTsDoc + }, + rules: { + 'tsdoc/syntax': 'warn' + } + }, + { + ignores: ['dist', 'types', 'node_modules', 'features', 'eslint.config.js'] + } +]; diff --git a/frontend-react/package.json b/frontend-react/package.json index 2631c05a..88add3f5 100644 --- a/frontend-react/package.json +++ b/frontend-react/package.json @@ -78,7 +78,7 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint": "eslint . --report-unused-disable-directives --max-warnings 0", "test": "vitest --ui", "style": "prettier --write .", "preview": "vite preview", @@ -110,6 +110,7 @@ }, "devDependencies": { "@cucumber/cucumber": "^11.1.0", + "@eslint/js": "^9.16.0", "@types/node": "^20.17.9", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", @@ -123,9 +124,9 @@ "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-react-refresh": "^0.4.16", + "eslint-plugin-react-hooks": "^5.1.0-rc.1", "eslint-plugin-tsdoc": "^0.4.0", + "globals": "^15.13.0", "happy-dom": "^15.11.7", "prettier": "3.4.2", "react": "^19.0.0", @@ -135,6 +136,7 @@ "typedoc-plugin-mdn-links": "^4.0.3", "typedoc-plugin-zod": "^1.3.0", "typescript": "^5.7.2", + "typescript-eslint": "^8.17.0", "vite": "^6.0.3", "vite-plugin-banner": "^0.8.0", "vitest": "^2.1.8" diff --git a/frontend-react/pnpm-lock.yaml b/frontend-react/pnpm-lock.yaml index d9f96793..3e336556 100644 --- a/frontend-react/pnpm-lock.yaml +++ b/frontend-react/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@cucumber/cucumber': specifier: ^11.1.0 version: 11.1.0 + '@eslint/js': + specifier: ^9.16.0 + version: 9.16.0 '@types/node': specifier: ^20.17.9 version: 20.17.9 @@ -88,7 +91,7 @@ importers: specifier: ^7.37.2 version: 7.37.2(eslint@9.16.0) eslint-plugin-react-hooks: - specifier: ^5.1.0 + specifier: ^5.1.0-rc.1 version: 5.1.0(eslint@9.16.0) eslint-plugin-react-refresh: specifier: ^0.4.16 @@ -96,6 +99,9 @@ importers: eslint-plugin-tsdoc: specifier: ^0.4.0 version: 0.4.0 + globals: + specifier: ^15.13.0 + version: 15.13.0 happy-dom: specifier: ^15.11.7 version: 15.11.7 @@ -123,6 +129,9 @@ importers: typescript: specifier: ^5.7.2 version: 5.7.2 + typescript-eslint: + specifier: ^8.17.0 + version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) vite: specifier: ^6.0.3 version: 6.0.3(@types/node@20.17.9)(sass@1.82.0)(yaml@2.6.1) @@ -1619,6 +1628,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@15.13.0: + resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} + engines: {node: '>=18'} + globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -2641,6 +2654,16 @@ packages: peerDependencies: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x + typescript-eslint@8.17.0: + resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + typescript@5.7.2: resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} @@ -4431,6 +4454,8 @@ snapshots: globals@14.0.0: {} + globals@15.13.0: {} + globalthis@1.0.3: dependencies: define-properties: 1.2.1 @@ -5469,6 +5494,17 @@ snapshots: typescript: 5.7.2 yaml: 2.6.1 + typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) + eslint: 9.16.0 + optionalDependencies: + typescript: 5.7.2 + transitivePeerDependencies: + - supports-color + typescript@5.7.2: {} uc.micro@2.1.0: {} diff --git a/frontend-react/src/lib/application/hooks/use-widget-config.ts b/frontend-react/src/lib/application/hooks/use-widget-config.ts index 512623a7..0b720e94 100644 --- a/frontend-react/src/lib/application/hooks/use-widget-config.ts +++ b/frontend-react/src/lib/application/hooks/use-widget-config.ts @@ -8,6 +8,8 @@ import { widgetConfigContext } from '../../widget'; * @returns The widget configuration retrieved from the widgetConfigContext. * @throws Error Throws an error if useWidgetConfig is not used within a WidgetConfigProvider. */ +// The type is safe due to the surrounding application structure. +// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters export function useWidgetConfig(): T { const widgetConfig = useContext(widgetConfigContext); if (!widgetConfig) { diff --git a/frontend-react/src/lib/application/routes/dashboard-editor/layout-editor/model/layout-editor-model.ts b/frontend-react/src/lib/application/routes/dashboard-editor/layout-editor/model/layout-editor-model.ts index e19af338..28d2ad22 100644 --- a/frontend-react/src/lib/application/routes/dashboard-editor/layout-editor/model/layout-editor-model.ts +++ b/frontend-react/src/lib/application/routes/dashboard-editor/layout-editor/model/layout-editor-model.ts @@ -358,7 +358,7 @@ export function resizeGrid( if (columns < 1 || rows < 1) { throw new InvalidBoundsError( - `Invalid grid size while resizing the grid. Must be at least 1x1, got ${columns}x${rows}` + `Invalid grid size while resizing the grid. Must be at least 1x1, got ${columns.toString()}x${rows.toString()}` ); } diff --git a/frontend-react/src/lib/auth/controller.ts b/frontend-react/src/lib/auth/controller.ts index ce41d973..5c9c560e 100644 --- a/frontend-react/src/lib/auth/controller.ts +++ b/frontend-react/src/lib/auth/controller.ts @@ -83,7 +83,6 @@ export async function login( setUser({ natsUrl, username }); setNatsConnection(nc); - // eslint-disable-next-line @typescript-eslint/no-deprecated setAutoLoginCredentials({ natsUrl, username, diff --git a/frontend-react/tsconfig.node.json b/frontend-react/tsconfig.node.json index 7882f544..95f78b48 100644 --- a/frontend-react/tsconfig.node.json +++ b/frontend-react/tsconfig.node.json @@ -8,5 +8,5 @@ "strictNullChecks": true, "resolveJsonModule": true }, - "include": ["vite.config.ts", "package.json"] + "include": ["vite.config.ts", "eslint.config.js", "package.json"] }