// ESLint (flat config) — v3-Umbau P1. // // Warum ueberhaupt: In dieses Repo schreiben nachts auch Agenten. Ohne Waechter laeuft // der Stil auseinander, und typische React-Fehler (fehlende Hook-Abhaengigkeiten, // bedingt aufgerufene Hooks) fallen erst im Betrieb auf. // // Bewusst streng bei Korrektheit, bewusst still bei Geschmack: Formatierung macht // Prettier, nicht der Linter. Regeln, die nur Meinung sind, stehen hier nicht. 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" export default tseslint.config( { ignores: ["dist", "node_modules", "*.config.js"] }, { extends: [js.configs.recommended, ...tseslint.configs.recommended], files: ["src/**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2022, globals: globals.browser, }, plugins: { "react-hooks": reactHooks, "react-refresh": reactRefresh, }, rules: { ...reactHooks.configs.recommended.rules, "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], // Die Regeln aus der React-Compiler-Generation (Plugin v7) finden im Bestand // 18 echte Stellen: setState direkt im Effekt, Ref-Zugriff waehrend des Renderns, // Komponenten im Render erzeugt. Das sind keine Fehlalarme — aber sie quer durch // 10 000 Zeilen zu beheben ist die Arbeit von Etappe P5 (Feature-Slices), nicht // von P1. Als Fehler waere das Gate ab Tag eins rot, und ein dauerhaft rotes Gate // ist kein Gate mehr ("Rot ist ein Ergebnis, kein Aergernis"). // Darum: sichtbare Warn-Liste statt stumm abgeschaltet. Beim Zerlegen eines // Bereichs wird sein Anteil mit erledigt; ist der Zaehler bei 0, kommen sie // hier auf "error" und der Rueckfall ist verbaut. "react-hooks/set-state-in-effect": "warn", "react-hooks/refs": "warn", "react-hooks/immutability": "warn", "react-hooks/static-components": "warn", // `any` ist in diesem Projekt an einigen Stellen bewusst gesetzt (Recharts-Rueckrufe, // Fehlerobjekte in catch). Warnen statt blockieren — sonst wird die Regel abgeschaltet. "@typescript-eslint/no-explicit-any": "warn", // Ungenutzte Variablen sind fast immer ein Rest von etwas Halbfertigem. // Fuehrendes _ heisst "absichtlich ungenutzt" (Rueckrufe mit fester Signatur). "@typescript-eslint/no-unused-vars": [ "error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" }, ], // Der Zaun um B-01: Geheimnisse gehoeren auf die Box, nicht in den Browser-Speicher. // Wer localStorage fuer Bedienvorlieben nutzt, ist willkommen — wer ein Passwort oder // einen Token hineinschreibt, soll hier haengen bleiben. "no-restricted-syntax": [ "error", { selector: "CallExpression[callee.object.name='localStorage'][arguments.0.value=/(?:password|passwort|token|secret|geheim|api_?key)/i]", message: "Geheimnisse gehoeren nicht in den localStorage (v3-Umbau P1, Befund B-01). " + "Auf der Box ablegen: backend/services/geheimnisse.py.", }, ], }, }, // Tests duerfen mehr: Attrappen brauchen `any`, und sie schreiben absichtlich // Geheimnisse in den localStorage, um zu beweisen, dass api() sie NICHT mitschickt. { files: ["src/**/*.test.{ts,tsx}", "src/test/**/*.ts"], rules: { "@typescript-eslint/no-explicit-any": "off", "no-restricted-syntax": "off", }, }, )