import js from '@eslint/js' 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'] }, // ─── Base: JS + TS strict ──────────────────────────────────────────────────── { extends: [js.configs.recommended, ...tseslint.configs.recommended], files: ['**/*.{ts,tsx}'], plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh, }, rules: { ...reactHooks.configs.recommended.rules, 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], // ── Regla estructural crítica ───────────────────────────────────────── // Repositorios solo pueden llamarse desde stores. // Cualquier import de persistence/repositories en código que no sea src/store/** // falla el lint con un mensaje explicativo. 'no-restricted-imports': [ 'error', { patterns: [ { group: ['*/persistence/repositories*', '../persistence/repositories*', '@/persistence/repositories*'], message: 'Los repositorios solo deben llamarse desde stores (src/store/**). ' + 'Usá el store correspondiente (useProcessStore, useSimulationStore, etc.).', }, ], }, ], // ── Reglas ajustadas al proyecto ───────────────────────────────────── // any en bordes con librerías sin tipos (bpmn-js, jsPDF, autotable) está // permitido por CLAUDE.md — se reporta como warning, no error. '@typescript-eslint/no-explicit-any': 'warn', // Funciones auxiliares definidas dentro de componentes (ej: Th en ActivitiesTable, // handlers en BpmnCanvas) son un patrón aceptado en este codebase. El riesgo de // reset de estado no aplica porque son funciones sin estado propio. 'react-hooks/static-components': 'off', // setState síncrono en useEffect con condicional deliberado (sincronización de // estado local con props/store). Los efectos están correctamente dependenciados. 'react-hooks/set-state-in-effect': 'off', // Cálculos de posición en pdf-export.ts usan y como variable acumulativa; // el patrón y += delta → doc.addPage() → y = PDF.margin es intencional // (separa visualmente las secciones del cálculo aunque no use el valor final). 'no-useless-assignment': 'warn', }, }, // ─── Override: src/store/** puede importar repositories ────────────────────── { files: ['src/store/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': 'off', }, }, // ─── Override: features/import puede importar repositories (operación de // importación inicial — no hay estado de simulación previo que invalidar) ── { files: ['src/features/import/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': 'off', }, }, // ─── Override: features/report usa repos en modo read-only (useReportData) ─── { files: ['src/features/report/useReportData.ts'], rules: { 'no-restricted-imports': 'off', }, }, // ─── Override: tests e2e y integración pueden importar repos directamente ──── { files: ['tests/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': 'off', }, }, )