waffensachkunde
Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.
| 1 | import js from '@eslint/js'; |
| 2 | import { defineConfig, globalIgnores } from 'eslint/config'; |
| 3 | import prettierAus from 'eslint-config-prettier'; |
| 4 | import jsxA11y from 'eslint-plugin-jsx-a11y'; |
| 5 | import reactHooks from 'eslint-plugin-react-hooks'; |
| 6 | import reactRefresh from 'eslint-plugin-react-refresh'; |
| 7 | import globals from 'globals'; |
| 8 | import tseslint from 'typescript-eslint'; |
| 9 | |
| 10 | export default defineConfig([ |
| 11 | globalIgnores([ |
| 12 | 'out/**', |
| 13 | 'dist/**', |
| 14 | 'release/**', |
| 15 | 'build/**', |
| 16 | 'node_modules/**', |
| 17 | 'coverage/**', |
| 18 | 'playwright-report/**', |
| 19 | 'test-results/**', |
| 20 | ]), |
| 21 | |
| 22 | js.configs.recommended, |
| 23 | |
| 24 | // ── Typbewusste Regeln (nur für TypeScript-Dateien) ────────────────── |
| 25 | { |
| 26 | files: ['**/*.{ts,tsx}'], |
| 27 | extends: [tseslint.configs.strictTypeChecked, tseslint.configs.stylisticTypeChecked], |
| 28 | languageOptions: { |
| 29 | parserOptions: { |
| 30 | projectService: true, |
| 31 | tsconfigRootDir: import.meta.dirname, |
| 32 | }, |
| 33 | }, |
| 34 | }, |
| 35 | |
| 36 | /* Diese Konfigurationsdatei selbst wird ohne Typinformationen geprüft: |
| 37 | mehrere ESLint-Plugins liefern keine Typdeklarationen mit, was sonst |
| 38 | nur Rauschen aus `no-unsafe-*` erzeugen würde. */ |
| 39 | { |
| 40 | files: ['**/*.{js,mjs,cjs}'], |
| 41 | languageOptions: { |
| 42 | globals: { ...globals.node }, |
| 43 | }, |
| 44 | }, |
| 45 | |
| 46 | // ── Main- und Preload-Prozess (Node-Umgebung) ──────────────────────── |
| 47 | { |
| 48 | files: ['src/main/**/*.ts', 'src/preload/**/*.ts', 'e2e/**/*.ts', '*.config.ts'], |
| 49 | languageOptions: { |
| 50 | globals: { ...globals.node }, |
| 51 | }, |
| 52 | }, |
| 53 | |
| 54 | // ── Renderer (Browser-Umgebung, React) ─────────────────────────────── |
| 55 | { |
| 56 | files: ['src/renderer/**/*.{ts,tsx}', 'tests/**/*.{ts,tsx}'], |
| 57 | languageOptions: { |
| 58 | globals: { ...globals.browser }, |
| 59 | }, |
| 60 | plugins: { |
| 61 | 'react-hooks': reactHooks, |
| 62 | 'react-refresh': reactRefresh, |
| 63 | }, |
| 64 | rules: { |
| 65 | ...reactHooks.configs.recommended.rules, |
| 66 | 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], |
| 67 | }, |
| 68 | }, |
| 69 | |
| 70 | /* Der Renderer läuft in der Sandbox und hat keinerlei Node-Zugriff. |
| 71 | tsconfig.web.json lädt die Node-Typen trotzdem mit – `AnwendungsInfo` |
| 72 | in src/shared/ipc.ts benennt die Plattform als `NodeJS.Platform`. |
| 73 | Diese Regel verhindert, dass dadurch versehentlich Node-APIs in |
| 74 | Renderer-Code landen, die erst zur Laufzeit knallen würden. */ |
| 75 | { |
| 76 | files: ['src/renderer/**/*.{ts,tsx}'], |
| 77 | rules: { |
| 78 | 'no-restricted-imports': [ |
| 79 | 'error', |
| 80 | { |
| 81 | patterns: [ |
| 82 | { |
| 83 | group: ['node:*', 'fs', 'path', 'child_process', 'electron'], |
| 84 | message: |
| 85 | 'Der Renderer hat keinen Node-Zugriff. Bitte einen typisierten IPC-Kanal in src/shared/ipc.ts ergänzen.', |
| 86 | }, |
| 87 | ], |
| 88 | }, |
| 89 | ], |
| 90 | }, |
| 91 | }, |
| 92 | |
| 93 | /* ── Barrierefreiheit ──────────────────────────────────────────────── |
| 94 | `jsx-a11y` ist hier keine Kür: Barrierefreiheit ist Definition of Done. |
| 95 | Deshalb der strikte Regelsatz – Verstöße sind Fehler, keine Warnungen. */ |
| 96 | { |
| 97 | files: ['src/renderer/**/*.tsx', 'tests/**/*.tsx'], |
| 98 | plugins: { 'jsx-a11y': jsxA11y }, |
| 99 | rules: jsxA11y.flatConfigs.strict.rules, |
| 100 | }, |
| 101 | |
| 102 | // ── Tests ──────────────────────────────────────────────────────────── |
| 103 | { |
| 104 | files: ['tests/**/*.{ts,tsx}', 'e2e/**/*.ts'], |
| 105 | rules: { |
| 106 | // In Tests sind bewusste Nicht-Null-Zusicherungen praktikabel. |
| 107 | '@typescript-eslint/no-non-null-assertion': 'off', |
| 108 | }, |
| 109 | }, |
| 110 | |
| 111 | /* ── Die Konsolenwache darf niemand versehentlich umgehen ──────────── |
| 112 | `e2e/konsolenwache.ts` hängt an `test` zwei automatische Fixtures, die |
| 113 | jede Konsolenausgabe der laufenden Anwendung auffangen. Wer `test` |
| 114 | wieder direkt von `@playwright/test` bezieht, bekommt sie nicht – und |
| 115 | zwar lautlos: Die Suite läuft grün weiter und hört nur eben nicht mehr |
| 116 | zu. Genau diese Art von stiller Lücke war der Grund, warum der |
| 117 | CSP-Konsolenfehler jahrelang unbemerkt bei jedem Start auflief. */ |
| 118 | { |
| 119 | files: ['e2e/**/*.spec.ts'], |
| 120 | rules: { |
| 121 | 'no-restricted-imports': [ |
| 122 | 'error', |
| 123 | { |
| 124 | paths: [ |
| 125 | { |
| 126 | name: '@playwright/test', |
| 127 | importNames: ['test'], |
| 128 | message: |
| 129 | '`test` bitte aus ./konsolenwache beziehen – nur darüber hört jemand die Konsole der Anwendung ab.', |
| 130 | }, |
| 131 | ], |
| 132 | }, |
| 133 | ], |
| 134 | }, |
| 135 | }, |
| 136 | |
| 137 | // ── Projektweite Verschärfungen ────────────────────────────────────── |
| 138 | { |
| 139 | files: ['**/*.{ts,tsx}'], |
| 140 | rules: { |
| 141 | '@typescript-eslint/consistent-type-imports': [ |
| 142 | 'error', |
| 143 | { prefer: 'type-imports', fixStyle: 'inline-type-imports' }, |
| 144 | ], |
| 145 | '@typescript-eslint/no-unused-vars': [ |
| 146 | 'error', |
| 147 | { |
| 148 | argsIgnorePattern: '^_', |
| 149 | varsIgnorePattern: '^_', |
| 150 | caughtErrors: 'all', |
| 151 | caughtErrorsIgnorePattern: '^_', |
| 152 | }, |
| 153 | ], |
| 154 | 'no-console': ['warn', { allow: ['warn', 'error', 'info'] }], |
| 155 | eqeqeq: ['error', 'always', { null: 'ignore' }], |
| 156 | }, |
| 157 | }, |
| 158 | |
| 159 | // Muss zuletzt stehen: schaltet alle Regeln ab, die mit Prettier kollidieren. |
| 160 | prettierAus, |
| 161 | ]); |