From 6f0e0a5abb39c06db07c9539a42ed7b8a1998e55 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 13 Jun 2025 17:28:33 +0200 Subject: [PATCH 1/2] save --- eslint.config.js | 35 +++ src/frontend/apps/e2e/.eslintrc.js | 9 - .../e2e/__tests__/app-impress/auth.setup.ts | 4 +- src/frontend/apps/e2e/eslint.config.js | 102 +++++++ src/frontend/apps/e2e/package.json | 3 +- src/frontend/apps/impress/eslint.config.js | 8 + .../apps/impress/jest/mocks/ComponentMock.js | 2 - src/frontend/apps/impress/package.json | 1 + src/frontend/eslint.config.js | 16 ++ src/frontend/package.json | 2 +- .../packages/eslint-config-impress/base.js | 105 ++++++++ .../eslint-config-impress/eslint.config.js | 135 ++++++++++ .../eslint-config-impress/jest-flat.js | 145 ++++++++++ .../eslint-config-impress/next-flat.js | 212 +++++++++++++++ .../eslint-config-impress/package.json | 18 +- .../eslint-config-impress/playwright-flat.js | 127 +++++++++ src/frontend/yarn.lock | 249 +++++++++++------- 17 files changed, 1062 insertions(+), 111 deletions(-) create mode 100644 eslint.config.js delete mode 100644 src/frontend/apps/e2e/.eslintrc.js create mode 100644 src/frontend/apps/e2e/eslint.config.js create mode 100644 src/frontend/apps/impress/eslint.config.js create mode 100644 src/frontend/eslint.config.js create mode 100644 src/frontend/packages/eslint-config-impress/base.js create mode 100644 src/frontend/packages/eslint-config-impress/eslint.config.js create mode 100644 src/frontend/packages/eslint-config-impress/jest-flat.js create mode 100644 src/frontend/packages/eslint-config-impress/next-flat.js create mode 100644 src/frontend/packages/eslint-config-impress/playwright-flat.js diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..df31a3506 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,35 @@ +// Root-level ESLint configuration for the monorepo +// Individual apps should have their own eslint.config.js files + +export default [ + // Global ignores for the entire monorepo + { + ignores: [ + '**/node_modules/**', + '**/dist/**', + '**/build/**', + '**/coverage/**', + '**/.next/**', + '**/out/**', + '**/public/**', + '**/static/**', + '**/*.min.js', + '**/bundle*.js', + '**/vendor/**', + '**/test-results/**', + '**/playwright-report/**', + '**/screenshots/**', + '**/report/**', + '**/save/**', + '**/yarn-error.log', + '**/data/**', + '**/docs/**', + '**/docker/**', + '**/env.d/**', + '**/gitlint/**', + '**/helm/**', + '**/crowdin/**', + '**/bin/**', + ], + }, +]; diff --git a/src/frontend/apps/e2e/.eslintrc.js b/src/frontend/apps/e2e/.eslintrc.js deleted file mode 100644 index 46f10c31d..000000000 --- a/src/frontend/apps/e2e/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - root: true, - extends: ['impress/playwright'], - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - ignorePatterns: ['node_modules'], -}; diff --git a/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts index a6e18985c..8d22960db 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts @@ -45,11 +45,11 @@ const saveStorageState = async ( }; async function globalSetup(config: FullConfig) { - /* eslint-disable @typescript-eslint/no-non-null-assertion */ + const chromeConfig = config.projects.find((p) => p.name === 'chromium')!; const firefoxConfig = config.projects.find((p) => p.name === 'firefox')!; const webkitConfig = config.projects.find((p) => p.name === 'webkit')!; - /* eslint-enable @typescript-eslint/no-non-null-assertion */ + await saveStorageState(chromeConfig); await saveStorageState(webkitConfig); diff --git a/src/frontend/apps/e2e/eslint.config.js b/src/frontend/apps/e2e/eslint.config.js new file mode 100644 index 000000000..e4f493dc1 --- /dev/null +++ b/src/frontend/apps/e2e/eslint.config.js @@ -0,0 +1,102 @@ +import js from '@eslint/js'; +import tsEslint from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import playwright from 'eslint-plugin-playwright'; + +export default [ + // Base JavaScript config + js.configs.recommended, + + // TypeScript configuration + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + project: './tsconfig.json', + }, + }, + plugins: { + '@typescript-eslint': tsEslint, + }, + rules: { + ...tsEslint.configs.recommended.rules, + '@typescript-eslint/no-unused-vars': ['error', { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }], + 'no-console': 'off', + }, + }, + + // Playwright test configuration + { + files: ['**/*.spec.ts', '**/*.test.ts', '__tests__/**/*.ts'], + plugins: { + playwright, + }, + rules: { + ...playwright.configs.recommended.rules, + 'playwright/no-skipped-test': 'warn', + 'playwright/no-conditional-expect': 'warn', + 'playwright/no-conditional-in-test': 'warn', + 'playwright/no-wait-for-timeout': 'warn', + 'playwright/expect-expect': 'warn', + 'playwright/no-networkidle': 'warn', + 'playwright/no-force-option': 'warn', + }, + }, + + // Global configuration for all files + { + languageOptions: { + ecmaVersion: 2022, + sourceType: 'module', + globals: { + // Node.js globals + console: 'readonly', + process: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + global: 'readonly', + setTimeout: 'readonly', + setInterval: 'readonly', + clearTimeout: 'readonly', + clearInterval: 'readonly', + require: 'readonly', + module: 'readonly', + exports: 'readonly', + NodeJS: 'readonly', + // Browser globals that might be accessed in tests + window: 'readonly', + document: 'readonly', + navigator: 'readonly', + location: 'readonly', + localStorage: 'readonly', + sessionStorage: 'readonly', + fetch: 'readonly', + }, + }, + rules: { + 'no-undef': 'error', + 'no-unsafe-optional-chaining': 'warn', + }, + }, + + // Ignore patterns + { + ignores: [ + 'node_modules/**', + 'test-results/**', + 'playwright-report/**', + 'screenshots/**', + 'report/**', + 'save/**', + '*.log', + '**/*.min.js', + ], + }, +]; diff --git a/src/frontend/apps/e2e/package.json b/src/frontend/apps/e2e/package.json index 93d0094d5..e2c747797 100644 --- a/src/frontend/apps/e2e/package.json +++ b/src/frontend/apps/e2e/package.json @@ -2,8 +2,9 @@ "name": "app-e2e", "version": "3.3.0", "private": true, + "type": "module", "scripts": { - "lint": "eslint . --ext .ts", + "lint": "eslint . --config ./eslint.config.js", "install-playwright": "playwright install --with-deps", "test": "playwright test", "test:ui": "yarn test --ui", diff --git a/src/frontend/apps/impress/eslint.config.js b/src/frontend/apps/impress/eslint.config.js new file mode 100644 index 000000000..3ebb4f03d --- /dev/null +++ b/src/frontend/apps/impress/eslint.config.js @@ -0,0 +1,8 @@ +import impressNextFlat from 'eslint-config-impress/next-flat'; + +export default [ + ...impressNextFlat, + { + ignores: ['node_modules/**', '.eslintrc.js', 'service-worker.js', '.next/**', 'out/**', 'build/**'], + }, +]; diff --git a/src/frontend/apps/impress/jest/mocks/ComponentMock.js b/src/frontend/apps/impress/jest/mocks/ComponentMock.js index 812a08b1c..20f078c0b 100644 --- a/src/frontend/apps/impress/jest/mocks/ComponentMock.js +++ b/src/frontend/apps/impress/jest/mocks/ComponentMock.js @@ -1,5 +1,3 @@ -import React from 'react'; - export const ComponentMock = () => { return
My component mocked
; }; diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json index 8fb4dc3c5..5ba244360 100644 --- a/src/frontend/apps/impress/package.json +++ b/src/frontend/apps/impress/package.json @@ -2,6 +2,7 @@ "name": "app-impress", "version": "3.3.0", "private": true, + "type": "module", "scripts": { "dev": "next dev", "build": "prettier --check . && yarn stylelint && next build", diff --git a/src/frontend/eslint.config.js b/src/frontend/eslint.config.js new file mode 100644 index 000000000..2569a36ad --- /dev/null +++ b/src/frontend/eslint.config.js @@ -0,0 +1,16 @@ +// Root ESLint config for the frontend workspace +export default [ + { + ignores: [ + 'node_modules/**', + 'build/**', + 'dist/**', + '.next/**', + 'out/**', + // Let individual apps handle their own configs + 'apps/**', + 'packages/**', + 'servers/**', + ], + }, +]; diff --git a/src/frontend/package.json b/src/frontend/package.json index 91e2f711f..d0905dbf9 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -33,7 +33,7 @@ "@types/react-dom": "19.1.6", "@typescript-eslint/eslint-plugin": "8.33.1", "@typescript-eslint/parser": "8.33.1", - "eslint": "8.57.0", + "eslint": "9.28.0", "react": "19.1.0", "react-dom": "19.1.0", "typescript": "5.8.3", diff --git a/src/frontend/packages/eslint-config-impress/base.js b/src/frontend/packages/eslint-config-impress/base.js new file mode 100644 index 000000000..6bc731371 --- /dev/null +++ b/src/frontend/packages/eslint-config-impress/base.js @@ -0,0 +1,105 @@ +import js from '@eslint/js'; +import typescript from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import prettier from 'eslint-config-prettier'; +import importPlugin from 'eslint-plugin-import'; +import react from 'eslint-plugin-react'; + +const globalRules = { + 'block-scoped-var': 'error', + curly: ['error', 'all'], + 'import/no-duplicates': ['error', { considerQueryString: false }], + 'import/order': [ + 'error', + { + alphabetize: { + order: 'asc', + }, + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: '@/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + 'newlines-between': 'always', + warnOnUnassignedImports: true, + }, + ], + 'no-alert': 'error', + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-var': 'error', + 'react/jsx-curly-brace-presence': [ + 'error', + { props: 'never', children: 'never', propElementValues: 'always' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], +}; + +export default [ + js.configs.recommended, + prettier, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + import: importPlugin, + react, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: globalRules, + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + plugins: { + '@typescript-eslint': typescript, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + ...globalRules, + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'no-unused-vars': 'off', + }, + }, + { + ignores: ['node_modules/**'], + }, +]; diff --git a/src/frontend/packages/eslint-config-impress/eslint.config.js b/src/frontend/packages/eslint-config-impress/eslint.config.js new file mode 100644 index 000000000..7f2f0c048 --- /dev/null +++ b/src/frontend/packages/eslint-config-impress/eslint.config.js @@ -0,0 +1,135 @@ +import js from '@eslint/js'; +import typescript from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import prettierConfig from 'eslint-config-prettier'; +import importPlugin from 'eslint-plugin-import'; +import react from 'eslint-plugin-react'; + +const globalRules = { + 'block-scoped-var': 'error', + curly: ['error', 'all'], + 'import/no-duplicates': ['error', { considerQueryString: false }], + 'import/order': [ + 'error', + { + alphabetize: { + order: 'asc', + }, + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: '@/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + 'newlines-between': 'always', + warnOnUnassignedImports: true, + }, + ], + 'no-alert': 'error', + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-var': 'error', + 'react/jsx-curly-brace-presence': [ + 'error', + { props: 'never', children: 'never', propElementValues: 'always' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], +}; + +export default [ + js.configs.recommended, + prettierConfig, + { + files: ['**/*.js', '**/*.jsx'], + plugins: { + import: importPlugin, + react, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: globalRules, + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + plugins: { + '@typescript-eslint': typescript, + import: importPlugin, + react, + }, + settings: { + react: { + version: 'detect', + }, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + ecmaFeatures: { + jsx: true, + }, + }, + }, + rules: { + ...globalRules, + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-unused-vars': 'off', // Turn off base rule as it conflicts with TypeScript rule + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, + { + files: ['**/*.cjs', '*.cjs', '.eslintrc.js', 'common.js', 'jest.js', 'next.js', 'playwright.js'], + languageOptions: { + ecmaVersion: 2022, + sourceType: 'commonjs', + globals: { + require: 'readonly', + module: 'readonly', + exports: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + }, + }, + rules: { + ...globalRules, + 'import/no-duplicates': 'off', // Turn off for CommonJS files as they may not support ES6 imports + 'import/order': 'off', + }, + }, + { + ignores: ['node_modules/**'], + }, +]; diff --git a/src/frontend/packages/eslint-config-impress/jest-flat.js b/src/frontend/packages/eslint-config-impress/jest-flat.js new file mode 100644 index 000000000..907bfff41 --- /dev/null +++ b/src/frontend/packages/eslint-config-impress/jest-flat.js @@ -0,0 +1,145 @@ +import js from '@eslint/js'; +import typescript from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import prettier from 'eslint-config-prettier'; +import importPlugin from 'eslint-plugin-import'; +import jest from 'eslint-plugin-jest'; +import react from 'eslint-plugin-react'; +import testingLibrary from 'eslint-plugin-testing-library'; + +const globalRules = { + 'block-scoped-var': 'error', + curly: ['error', 'all'], + 'import/no-duplicates': ['error', { considerQueryString: false }], + 'import/order': [ + 'error', + { + alphabetize: { + order: 'asc', + }, + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: '@/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + 'newlines-between': 'always', + warnOnUnassignedImports: true, + }, + ], + 'no-alert': 'error', + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-var': 'error', + 'react/jsx-curly-brace-presence': [ + 'error', + { props: 'never', children: 'never', propElementValues: 'always' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], +}; + +export default [ + js.configs.recommended, + prettier, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + import: importPlugin, + react, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: globalRules, + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + plugins: { + '@typescript-eslint': typescript, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], + }, + }, + { + files: ['**/*.spec.*', '**/*.test.*', '**/__mock__/**/*'], + plugins: { + jest, + 'testing-library': testingLibrary, + }, + rules: { + ...globalRules, + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + 'testing-library/no-await-sync-events': [ + 'error', + { eventModules: ['fire-event'] }, + ], + 'testing-library/await-async-events': [ + 'error', + { + eventModule: 'userEvent', + }, + ], + 'testing-library/no-manual-cleanup': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'react/display-name': 0, + 'jest/expect-expect': 'error', + '@typescript-eslint/unbound-method': 'off', + 'jest/unbound-method': 'error', + 'react/react-in-jsx-scope': 'off', + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'no-unused-vars': 'off', + }, + }, + { + ignores: ['node_modules/**'], + }, +]; diff --git a/src/frontend/packages/eslint-config-impress/next-flat.js b/src/frontend/packages/eslint-config-impress/next-flat.js new file mode 100644 index 000000000..8b519bcea --- /dev/null +++ b/src/frontend/packages/eslint-config-impress/next-flat.js @@ -0,0 +1,212 @@ +import js from '@eslint/js'; +import tanstackQuery from '@tanstack/eslint-plugin-query'; +import typescript from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import prettierConfig from 'eslint-config-prettier'; +import importPlugin from 'eslint-plugin-import'; +import jsxA11y from 'eslint-plugin-jsx-a11y'; +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; + +const globalRules = { + 'block-scoped-var': 'error', + curly: ['error', 'all'], + 'import/no-duplicates': ['error', { considerQueryString: false }], + 'import/order': [ + 'error', + { + alphabetize: { + order: 'asc', + }, + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: '@/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + 'newlines-between': 'always', + warnOnUnassignedImports: true, + }, + ], + 'no-alert': 'error', + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-var': 'error', + 'react/jsx-curly-brace-presence': [ + 'error', + { props: 'never', children: 'never', propElementValues: 'always' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], +}; + +export default [ + js.configs.recommended, + prettierConfig, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + '@tanstack/query': tanstackQuery, + 'jsx-a11y': jsxA11y, + import: importPlugin, + react, + 'react-hooks': reactHooks, + }, + settings: { + react: { + version: 'detect', + }, + 'jsx-a11y': { + polymorphicPropName: 'as', + components: { + Input: 'input', + Button: 'button', + Box: 'div', + Text: 'span', + Select: 'select', + }, + }, + }, + rules: { + ...globalRules, + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'error', + 'react/react-in-jsx-scope': 'off', // Not needed in modern React + }, + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { + // Browser globals + window: 'readonly', + document: 'readonly', + console: 'readonly', + fetch: 'readonly', + localStorage: 'readonly', + sessionStorage: 'readonly', + navigator: 'readonly', + location: 'readonly', + history: 'readonly', + setTimeout: 'readonly', + clearTimeout: 'readonly', + setInterval: 'readonly', + clearInterval: 'readonly', + addEventListener: 'readonly', + removeEventListener: 'readonly', + Image: 'readonly', + createImageBitmap: 'readonly', + structuredClone: 'readonly', + // Node.js globals + process: 'readonly', + Buffer: 'readonly', + global: 'readonly', + NodeJS: 'readonly', + // React + React: 'readonly', + JSX: 'readonly', + }, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + plugins: { + '@typescript-eslint': typescript, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-unused-vars': 'off', // Turn off base rule as it conflicts with TypeScript rule + }, + }, + { + files: ['**/*.spec.*', '**/*.test.*', '**/__mock__/**/*'], + languageOptions: { + globals: { + jest: 'readonly', + describe: 'readonly', + it: 'readonly', + test: 'readonly', + expect: 'readonly', + beforeEach: 'readonly', + afterEach: 'readonly', + beforeAll: 'readonly', + afterAll: 'readonly', + }, + }, + rules: { + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + 'react/display-name': 0, + 'react/react-in-jsx-scope': 'off', + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, + { + files: ['**/service-worker.js', '**/service-worker.ts', '**/sw.js', '**/sw.ts'], + languageOptions: { + globals: { + self: 'readonly', + caches: 'readonly', + ServiceWorkerGlobalScope: 'readonly', + trustedTypes: 'readonly', + clients: 'readonly', + registration: 'readonly', + skipWaiting: 'readonly', + importScripts: 'readonly', + }, + }, + }, + { + files: ['**/*.config.js', '**/*.config.ts', '**/next.config.js', '**/stylelint.config.js'], + languageOptions: { + globals: { + module: 'readonly', + exports: 'readonly', + require: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + }, + }, + }, + { + ignores: ['node_modules/**', '.next/**', 'out/**', 'build/**'], + }, +]; diff --git a/src/frontend/packages/eslint-config-impress/package.json b/src/frontend/packages/eslint-config-impress/package.json index 968bc9894..abce60c9f 100644 --- a/src/frontend/packages/eslint-config-impress/package.json +++ b/src/frontend/packages/eslint-config-impress/package.json @@ -2,10 +2,24 @@ "name": "eslint-config-impress", "version": "3.3.0", "license": "MIT", + "type": "module", + "main": "./eslint.config.js", + "exports": { + ".": "./eslint.config.js", + "./base": "./base.js", + "./next": "./next.js", + "./next-flat": "./next-flat.js", + "./jest": "./jest.js", + "./jest-flat": "./jest-flat.js", + "./playwright": "./playwright.js", + "./playwright-flat": "./playwright-flat.js" + }, "scripts": { - "lint": "eslint --ext .js ." + "lint": "eslint ." }, "dependencies": { + "@eslint/eslintrc": "3.2.0", + "@eslint/js": "9.28.0", "@next/eslint-plugin-next": "15.3.3", "@tanstack/eslint-plugin-query": "5.78.0", "@typescript-eslint/eslint-plugin": "*", @@ -18,6 +32,8 @@ "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-playwright": "2.2.0", "eslint-plugin-prettier": "5.4.1", + "eslint-plugin-react": "*", + "eslint-plugin-react-hooks": "*", "eslint-plugin-testing-library": "7.4.0", "prettier": "3.5.3" } diff --git a/src/frontend/packages/eslint-config-impress/playwright-flat.js b/src/frontend/packages/eslint-config-impress/playwright-flat.js new file mode 100644 index 000000000..d50165641 --- /dev/null +++ b/src/frontend/packages/eslint-config-impress/playwright-flat.js @@ -0,0 +1,127 @@ +import js from '@eslint/js'; +import nextPlugin from '@next/eslint-plugin-next'; +import typescript from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; +import prettier from 'eslint-config-prettier'; +import importPlugin from 'eslint-plugin-import'; +import playwright from 'eslint-plugin-playwright'; +import react from 'eslint-plugin-react'; + +const globalRules = { + 'block-scoped-var': 'error', + curly: ['error', 'all'], + 'import/no-duplicates': ['error', { considerQueryString: false }], + 'import/order': [ + 'error', + { + alphabetize: { + order: 'asc', + }, + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ + { + pattern: '@/**', + group: 'internal', + }, + ], + pathGroupsExcludedImportTypes: ['builtin'], + 'newlines-between': 'always', + warnOnUnassignedImports: true, + }, + ], + 'no-alert': 'error', + 'no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'no-var': 'error', + 'react/jsx-curly-brace-presence': [ + 'error', + { props: 'never', children: 'never', propElementValues: 'always' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], +}; + +export default [ + js.configs.recommended, + prettier, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + '@next/next': nextPlugin, + import: importPlugin, + react, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: { + ...globalRules, + '@next/next/no-html-link-for-pages': 'off', + }, + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + plugins: { + '@typescript-eslint': typescript, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, + ], + 'sort-imports': [ + 'error', + { + ignoreDeclarationSort: true, + }, + ], + '@typescript-eslint/no-unsafe-member-access': 'off', + }, + }, + { + files: ['**/*.spec.*', '**/*.test.*', '**/__mock__/**/*'], + plugins: { + playwright, + }, + rules: { + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'no-unused-vars': 'off', + }, + }, + { + ignores: ['node_modules/**'], + }, +]; diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index f2757f1ac..067870161 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -1480,30 +1480,86 @@ dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint/config-array@^0.20.0": + version "0.20.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.1.tgz#454f89be82b0e5b1ae872c154c7e2f3dd42c3979" + integrity sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.2.1": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.3.tgz#39d6da64ed05d7662659aa7035b54cd55a9f3672" + integrity sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg== + +"@eslint/core@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.14.0.tgz#326289380968eaf7e96f364e1e4cf8f3adf2d003" + integrity sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.0.tgz#8fc04709a7b9a179d9f7d93068fc000cb8c5603d" + integrity sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.28.0": + version "9.28.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.28.0.tgz#7822ccc2f8cae7c3cd4f902377d520e9ae03f844" + integrity sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg== + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.3.1": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz#0cad96b134d23a653348e3342f485636b5ef4732" + integrity sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg== + dependencies: + "@eslint/core" "^0.15.0" + levn "^0.4.1" "@floating-ui/core@^1.7.0": version "1.7.0" @@ -1673,24 +1729,33 @@ uuid "^11.0.3" ws "^8.5.0" -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@img/sharp-darwin-arm64@0.34.1": version "0.34.1" @@ -2229,7 +2294,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -6850,7 +6915,7 @@ "@typescript-eslint/types" "8.33.1" eslint-visitor-keys "^4.2.0" -"@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": +"@ungap/structured-clone@^1.0.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== @@ -7116,11 +7181,16 @@ acorn-walk@^8.0.2, acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2: version "8.14.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -8187,7 +8257,7 @@ cross-env@7.0.3: dependencies: cross-spawn "^7.0.1" -cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -8510,13 +8580,6 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - docx@9.5.0, docx@^9.0.2: version "9.5.0" resolved "https://registry.yarnpkg.com/docx/-/docx-9.5.0.tgz#586990c4ecf1c7e83290529997b33f2c029bbe68" @@ -9035,12 +9098,12 @@ eslint-plugin-prettier@5.4.1: prettier-linter-helpers "^1.0.0" synckit "^0.11.7" -eslint-plugin-react-hooks@^5.0.0: +eslint-plugin-react-hooks@*, eslint-plugin-react-hooks@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz#1be0080901e6ac31ce7971beed3d3ec0a423d9e3" integrity sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg== -eslint-plugin-react@^7.37.0: +eslint-plugin-react@*, eslint-plugin-react@^7.37.0: version "7.37.5" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz#2975511472bdda1b272b34d779335c9b0e877065" integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== @@ -9080,15 +9143,15 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^8.3.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -9098,65 +9161,67 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@*, eslint@8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@*, eslint@9.28.0: + version "9.28.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.28.0.tgz#b0bcbe82a16945a40906924bea75e8b4980ced7d" + integrity sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.20.0" + "@eslint/config-helpers" "^0.2.1" + "@eslint/core" "^0.14.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.28.0" + "@eslint/plugin-kit" "^0.3.1" + "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" - cross-spawn "^7.0.2" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^8.3.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== +espree@^10.0.1, espree@^10.3.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== dependencies: - acorn "^8.9.0" + acorn "^8.15.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" + eslint-visitor-keys "^4.2.1" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: +esquery@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== @@ -9400,12 +9465,12 @@ file-entry-cache@^10.1.0: dependencies: flat-cache "^6.1.9" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" filelist@^1.0.4: version "1.0.4" @@ -9454,14 +9519,13 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" flat-cache@^6.1.9: version "6.1.9" @@ -9784,13 +9848,18 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0, globals@^13.23.0: +globals@^13.23.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -10538,11 +10607,6 @@ is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-plain-obj@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" @@ -11316,7 +11380,7 @@ jszip@^3.10.1: readable-stream "~2.3.6" setimmediate "^1.0.5" -keyv@^4.5.3: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -12122,7 +12186,7 @@ minimalistic-assert@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -14989,11 +15053,6 @@ text-decoder@^1.1.0: dependencies: b4a "^1.6.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - through2@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" From a7d0fc977e35d2c13b7eb813d50d7832e04460e4 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 13 Jun 2025 17:54:17 +0200 Subject: [PATCH 2/2] save2 --- src/frontend/apps/impress/.eslintrc.js | 14 ----- src/frontend/apps/impress/eslint.config.js | 58 +++++++++++++++++++ src/frontend/apps/impress/next.config.js | 6 +- src/frontend/packages/i18n/.eslintrc.js | 11 ---- src/frontend/packages/i18n/eslint.config.js | 43 ++++++++++++++ src/frontend/packages/i18n/package.json | 2 +- src/frontend/servers/y-provider/.eslintrc.cjs | 17 ------ .../servers/y-provider/eslint.config.js | 55 ++++++++++++++++++ src/frontend/servers/y-provider/package.json | 2 +- 9 files changed, 161 insertions(+), 47 deletions(-) delete mode 100644 src/frontend/apps/impress/.eslintrc.js delete mode 100644 src/frontend/packages/i18n/.eslintrc.js create mode 100644 src/frontend/packages/i18n/eslint.config.js delete mode 100644 src/frontend/servers/y-provider/.eslintrc.cjs create mode 100644 src/frontend/servers/y-provider/eslint.config.js diff --git a/src/frontend/apps/impress/.eslintrc.js b/src/frontend/apps/impress/.eslintrc.js deleted file mode 100644 index f2dbec761..000000000 --- a/src/frontend/apps/impress/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - root: true, - extends: ['impress/next'], - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - settings: { - next: { - rootDir: __dirname, - }, - }, - ignorePatterns: ['node_modules', '.eslintrc.js', 'service-worker.js'], -}; diff --git a/src/frontend/apps/impress/eslint.config.js b/src/frontend/apps/impress/eslint.config.js index 3ebb4f03d..15e51e1f5 100644 --- a/src/frontend/apps/impress/eslint.config.js +++ b/src/frontend/apps/impress/eslint.config.js @@ -1,8 +1,66 @@ import impressNextFlat from 'eslint-config-impress/next-flat'; +import jest from 'eslint-plugin-jest'; export default [ ...impressNextFlat, { ignores: ['node_modules/**', '.eslintrc.js', 'service-worker.js', '.next/**', 'out/**', 'build/**'], }, + { + // Additional browser and DOM globals for Next.js app + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + languageOptions: { + globals: { + // DOM and HTML globals + HTMLElement: 'readonly', + HTMLDivElement: 'readonly', + SVGSVGElement: 'readonly', + Event: 'readonly', + KeyboardEvent: 'readonly', + MessageEvent: 'readonly', + + // Web APIs + Request: 'readonly', + Response: 'readonly', + RequestInit: 'readonly', + Headers: 'readonly', + Blob: 'readonly', + File: 'readonly', + FormData: 'readonly', + URL: 'readonly', + URLSearchParams: 'readonly', + TextDecoder: 'readonly', + TextEncoder: 'readonly', + DOMParser: 'readonly', + IntersectionObserver: 'readonly', + + // Service Worker globals + ServiceWorkerGlobalScope: 'readonly', + BodyInit: 'readonly', + self: 'readonly', + }, + }, + rules: { + // Allow some flexibility for escape characters in regex + 'no-useless-escape': 'warn', + // Allow redeclaring for legitimate cases + 'no-redeclare': 'warn', + }, + }, + { + // Jest configuration for test files + files: ['**/*.test.js', '**/*.test.ts', '**/*.test.tsx', '**/__tests__/**/*'], + plugins: { + jest, + }, + languageOptions: { + globals: { + ...jest.environments.globals.globals, + }, + }, + rules: { + ...jest.configs.recommended.rules, + 'jest/no-conditional-expect': 'warn', + }, + }, ]; diff --git a/src/frontend/apps/impress/next.config.js b/src/frontend/apps/impress/next.config.js index 862b4fafc..612312d45 100644 --- a/src/frontend/apps/impress/next.config.js +++ b/src/frontend/apps/impress/next.config.js @@ -1,6 +1,6 @@ -const crypto = require('crypto'); +import crypto from 'crypto'; -const { InjectManifest } = require('workbox-webpack-plugin'); +import { InjectManifest } from 'workbox-webpack-plugin'; const buildId = crypto.randomBytes(256).toString('hex').slice(0, 8); @@ -62,4 +62,4 @@ const nextConfig = { }, }; -module.exports = nextConfig; +export default nextConfig; diff --git a/src/frontend/packages/i18n/.eslintrc.js b/src/frontend/packages/i18n/.eslintrc.js deleted file mode 100644 index 475c786bc..000000000 --- a/src/frontend/packages/i18n/.eslintrc.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - root: true, - extends: ['impress/jest', 'plugin:import/recommended'], - parserOptions: { - sourceType: 'module', - ecmaVersion: 'latest', - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - ignorePatterns: ['node_modules'], -}; diff --git a/src/frontend/packages/i18n/eslint.config.js b/src/frontend/packages/i18n/eslint.config.js new file mode 100644 index 000000000..939d4873b --- /dev/null +++ b/src/frontend/packages/i18n/eslint.config.js @@ -0,0 +1,43 @@ +import impressJestFlat from 'eslint-config-impress/jest-flat'; + +export default [ + ...impressJestFlat, + { + ignores: ['node_modules/**'], + }, + { + // Node.js globals for .mjs files + files: ['**/*.mjs', '**/*.js'], + languageOptions: { + globals: { + console: 'readonly', + process: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + global: 'readonly', + module: 'readonly', + require: 'readonly', + exports: 'readonly', + }, + }, + }, + { + // Jest globals for test files + files: ['**/*.test.js', '**/*.test.ts', '**/__tests__/**/*'], + languageOptions: { + globals: { + describe: 'readonly', + test: 'readonly', + it: 'readonly', + expect: 'readonly', + beforeAll: 'readonly', + beforeEach: 'readonly', + afterAll: 'readonly', + afterEach: 'readonly', + jest: 'readonly', + console: 'readonly', + }, + }, + }, +]; diff --git a/src/frontend/packages/i18n/package.json b/src/frontend/packages/i18n/package.json index 2a65b8836..762317a46 100644 --- a/src/frontend/packages/i18n/package.json +++ b/src/frontend/packages/i18n/package.json @@ -8,7 +8,7 @@ "format-deploy": "yarn format-deploy:impress", "format-deploy:impress": "node ./format-deploy.mjs --app=impress --output=../../apps/impress/src/i18n/translations.json", "format-rebuild-fr:impress": "node ./rebuild-translations.mjs --language=fr --app=impress --output=../../apps/impress/src/i18n/translations.json", - "lint": "eslint --ext .js,.ts,.mjs .", + "lint": "eslint --config ./eslint.config.js .", "test": "jest" }, "dependencies": { diff --git a/src/frontend/servers/y-provider/.eslintrc.cjs b/src/frontend/servers/y-provider/.eslintrc.cjs deleted file mode 100644 index 9e0dff2ab..000000000 --- a/src/frontend/servers/y-provider/.eslintrc.cjs +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - root: true, - extends: ['impress/jest', 'impress/next'], - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - settings: { - next: { - rootDir: __dirname, - }, - }, - rules: { - '@next/next/no-html-link-for-pages': 'off', - }, - ignorePatterns: ['node_modules'], -}; diff --git a/src/frontend/servers/y-provider/eslint.config.js b/src/frontend/servers/y-provider/eslint.config.js new file mode 100644 index 000000000..1d59027a2 --- /dev/null +++ b/src/frontend/servers/y-provider/eslint.config.js @@ -0,0 +1,55 @@ +import impressJestFlat from 'eslint-config-impress/jest-flat'; + +export default [ + ...impressJestFlat, + { + ignores: ['node_modules/**', 'dist/**'], + }, + { + // Node.js server globals + files: ['**/*.js', '**/*.ts'], + languageOptions: { + globals: { + // Node.js globals + console: 'readonly', + process: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + global: 'readonly', + module: 'readonly', + require: 'readonly', + exports: 'readonly', + setTimeout: 'readonly', + setInterval: 'readonly', + clearTimeout: 'readonly', + clearInterval: 'readonly', + NodeJS: 'readonly', + }, + }, + rules: { + 'no-unused-vars': ['error', { + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + }], + 'no-empty': 'warn', + }, + }, + { + // Jest globals for test files + files: ['**/*.test.js', '**/*.test.ts', '**/__tests__/**/*'], + languageOptions: { + globals: { + jest: 'readonly', + describe: 'readonly', + test: 'readonly', + it: 'readonly', + expect: 'readonly', + beforeAll: 'readonly', + beforeEach: 'readonly', + afterAll: 'readonly', + afterEach: 'readonly', + }, + }, + }, +]; diff --git a/src/frontend/servers/y-provider/package.json b/src/frontend/servers/y-provider/package.json index 719417aab..d21aea716 100644 --- a/src/frontend/servers/y-provider/package.json +++ b/src/frontend/servers/y-provider/package.json @@ -9,7 +9,7 @@ "build": "tsc -p tsconfig.build.json && tsc-alias", "dev": "cross-env COLLABORATION_LOGGING=true && nodemon --config nodemon.json", "start": "node ./dist/start-server.js", - "lint": "eslint . --ext .ts", + "lint": "eslint --config ./eslint.config.js .", "test": "jest" }, "engines": {