- shadcn liefert zur Laufzeit nichts: gebraucht wird nur shadcn/tailwind.css beim Bauen (am PC und im CI, beide mit npm ci inkl. devDependencies). Also devDependency; 325 Pakete im Lockfile haengen ausschliesslich daran und sind jetzt "dev". - @testing-library/user-event war nirgends benutzt: entfernt. - Dialog/Sheet: ungenutzte Trigger/Close/Footer und "use client" raus. - test/setup.ts: ResizeObserver-Attrappe fuer Recharts und Kraftgraph entfernt - beide gibt es nicht mehr, und Radix' Dialog misst nichts. - eslint.config.js: Die vier React-Compiler-Regeln sollten laut Kommentar auf "error", sobald ihr Zaehler 0 ist. Er ist 0 - jetzt error. Veraltete Zahlen und "Recharts" im Kommentar korrigiert. - lib/utils.ts bleibt (Ziel von components.json fuer die shadcn-CLI), jetzt mit Kommentar. - Lockfile: npm 11.17 traegt sechs optionale wasm32-Unterpakete zusaetzlich ein, auch ohne diese Aenderung; die sind wieder raus, damit der Diff nur das Gewollte zeigt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
81 lines
3.3 KiB
JavaScript
81 lines
3.3 KiB
JavaScript
// 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): setState direkt im Effekt,
|
|
// Ref-Zugriff waehrend des Renderns, Komponenten im Render erzeugt. Im alten Bestand
|
|
// (10 000 Zeilen) fanden sie 18 Stellen und liefen darum als Warnung, mit der Abmachung:
|
|
// Ist der Zaehler bei 0, kommen sie auf "error" und der Rueckfall ist verbaut.
|
|
// Mit dem Box-Wart-Umbau (09/2026) stand der Zaehler bei 0 — also jetzt "error".
|
|
"react-hooks/set-state-in-effect": "error",
|
|
"react-hooks/refs": "error",
|
|
"react-hooks/immutability": "error",
|
|
"react-hooks/static-components": "error",
|
|
|
|
// `any` kommt im Bestand nicht mehr vor (Stand 09/2026). Warnen statt blockieren, damit
|
|
// eine bewusst gesetzte Ausnahme (z. B. ein Fehlerobjekt in catch) das Gate nicht rot macht.
|
|
"@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",
|
|
},
|
|
},
|
|
)
|