Skip to content

[Mejora]: Implementación de reglas eslint #84

Description

@Scot3004

Verificaciones preliminares

Solicitud de mejora en sitio web

Contexto

A medida que el proyecto creció y se hicieron múltiples refactorings para
alcanzar 100 % de cobertura unitaria, se detectaron problemas recurrentes de
calidad de código:

  1. Uso extendido de any: muchas funciones y variables usaban any,
    lo que anulaba las ventajas de TypeScript. Los errores de tipo solo se
    descubrían en runtime o en tests E2E lentos, no en tiempo de compilación.
  2. Falta de linter configurado: no había un ESLint estructurado; cada
    archivo seguía convenciones diferentes.
  3. Inconsistencia en estilo: algunos archivos usaban ;, otros no;
    la indentación variaba entre archivos.
  4. Código generado por herramientas con estilo diferente: Playwright
    codegen genera código con ; (semicolons), pero la convención del
    proyecto es omitirlos.

Perfil del desarrollador

El mantenedor principal viene de Python, donde:

  • No existen los ; al final de sentencia
  • La legibilidad sin ruido sintáctico es un valor
  • El formateo lo resuelve una sola herramienta (black / ruff format)

En el entorno laboral se usa ; por convención de equipo. En este proyecto
personal, la preferencia es omitir semicolons para mantener el código
más limpio y cercano al estilo natural del autor.


Decisiones tomadas

1. Prohibir any@typescript-eslint/no-explicit-any: warn

Se activó la regla @typescript-eslint/no-explicit-any en nivel warn
(no error para no bloquear builds durante el refactoring gradual).

Refactoring realizado:

Se reemplazaron todos los any del código fuente con tipos explícitos:

Patrón eliminado Reemplazo
any en parámetros Interfaces dedicadas (PageData, EntryWithSlug, etc.)
as unknown as any Genéricos (DetailPageContext<T>)
any en retornos Tipos de colección de Astro (CollectionEntry<CollectionKey>)
any en tests Objetos tipados con interfaces de mock

Resultado: cero any en el código fuente (src/). El único
eslint-disable para no-explicit-any que queda está en cypress/e2e/stubs.ts,
que es código legacy pendiente de eliminación.

Regla en copilot-instructions.md:

- **Types:** Avoid `any` type; always define custom types or interfaces

Esto asegura que Copilot tampoco genere código con any.

2. Omitir semicolons — convención sin enforcement automático

Decisión: omitir ; al final de sentencias en todo el código del
proyecto.

Estado actual: la convención está documentada en copilot-instructions.md
pero no está enforceada por ESLint ni por un formateador automático. Esto
es intencional mientras se evalúan las opciones (ver sección de formateo
abajo).

Excepción conocida: el código generado por npx playwright codegen
incluye ; automáticamente. El flujo de trabajo esperado es:

  1. Generar código con playwright codegen
  2. Copiar al test
  3. Eliminar ; manualmente o con un futuro autofix

3. Indentación a 2 espacios — enforceada

'indent': ['error', 2, { SwitchCase: 1 }]

Esta regla sí está enforceada a nivel error y se aplica con --fix.


Configuración actual de ESLint

// eslint.config.js (flat config, ESLint 9)

// Plugins activos:
// - eslint-plugin-astro        → reglas para .astro
// - @typescript-eslint         → reglas para .ts
// - eslint-plugin-import       → resolución de imports
// - eslint-plugin-jsx-a11y     → accesibilidad en JSX/Astro

// Reglas clave:
{
  '@typescript-eslint/no-explicit-any': 'warn',
  '@typescript-eslint/no-unused-vars': ['error', {
    varsIgnorePattern: '^_',
    argsIgnorePattern: '^_',
    caughtErrorsIgnorePattern: '^_'
  }],
  'import/no-unresolved': 'error',
  'import/no-extraneous-dependencies': ['error', {
    devDependencies: ['cypress/**', 'tests/**', '**/*.spec.*',
                      'playwright.config.ts', 'vitest.config.ts']
  }],
  'indent': ['error', 2, { SwitchCase: 1 }]
}

Lo que falta estructurar

La configuración actual tiene reglas funcionales pero hay áreas pendientes
de organizar:

Área Estado Nota
no-explicit-any ✅ Activa (warn) Subir a error cuando se elimine Cypress
no-unused-vars ✅ Activa (error) Con ignore para _ prefixed
import/no-unresolved ✅ Activa Con módulos core de Astro configurados
indent ✅ Activa (2 espacios) Enforceada
Semicolons ❌ Sin regla Convención manual; pendiente de evaluación
Trailing commas ❌ Sin regla Pendiente
Quotes (single/double) ❌ Sin regla Pendiente
Max line length ❌ Sin regla Pendiente
Reglas para .astro frontmatter ⚠️ Parcial Solo jsx-a11y, no estilo

Decisión pendiente: formateo automático

Opciones en evaluación

A. Prettier

  • ✅ Estándar de facto en proyectos JS/TS
  • ✅ Opinionado: pocas decisiones que tomar
  • ✅ Integración con ESLint vía eslint-config-prettier
  • ❌ Requiere eslint-config-prettier para desactivar reglas conflictivas
  • ❌ Otro binario más en el toolchain
  • ❌ Formato de .astro tiene soporte limitado (plugin prettier-plugin-astro)

B. ESLint Stylistic (@stylistic/eslint-plugin)

  • ✅ Un solo tool (ESLint) para lint + formato
  • ✅ Reglas granulares: se puede activar solo semi, quotes, etc.
  • ✅ No necesita un segundo tool ni config de desactivación
  • ❌ Más reglas que configurar manualmente
  • ❌ Menos adoption que Prettier en la comunidad

C. Mantener convención manual (status quo)

  • ✅ Sin overhead de configuración
  • ✅ Copilot respeta las instrucciones de copilot-instructions.md
  • ❌ No previene inconsistencias en contribuciones manuales
  • playwright codegen genera código con estilo diferente

Estado

En pausa. No se ha tomado una decisión final sobre formateo automático.
Los tradeoffs se evaluarán cuando:

  • Se complete la eliminación de Cypress (simplifica el scope de configs)
  • Se tenga claro si se quiere Prettier o solo ESLint Stylistic
  • Se definan las reglas exactas de estilo

Por ahora, la convención se mantiene vía copilot-instructions.md y
revisión manual.


Diagrama del estado actual

┌──────────────────────────────────────────────────────────┐
│ ESLint (flat config, v9)                                 │
│                                                          │
│  ┌─────────────┐  ┌──────────────┐  ┌────────────────┐  │
│  │ @typescript- │  │ eslint-      │  │ eslint-plugin- │  │
│  │ eslint       │  │ plugin-      │  │ jsx-a11y       │  │
│  │              │  │ import       │  │                │  │
│  │ • no-any ⚠️  │  │ • unresolved │  │ • alt-text     │  │
│  │ • no-unused  │  │ • extraneous │  │ • anchor       │  │
│  │   vars ❌    │  │              │  │                │  │
│  └─────────────┘  └──────────────┘  └────────────────┘  │
│                                                          │
│  ┌─────────────┐                                         │
│  │ eslint-     │                                         │
│  │ plugin-astro│  Reglas de estilo: ❓ pendientes        │
│  │ (recommend) │  Prettier: ❓ en evaluación             │
│  └─────────────┘  @stylistic: ❓ en evaluación           │
│                                                          │
└──────────────────────────────────────────────────────────┘

Acciones futuras (cuando se retome)

  1. Decidir entre Prettier y ESLint Stylistic
  2. Definir regla de semicolons (semi: ['error', 'never'] o vía Prettier)
  3. Definir regla de quotes (quotes: ['error', 'single'] o similar)
  4. Subir no-explicit-any de warn a error
  5. Eliminar el eslint-disable en cypress/e2e/stubs.ts al borrar Cypress
  6. Evaluar si agregar @stylistic/eslint-plugin o prettier a CI
  7. Documentar la resolución final en este ADR (cambiar estado a Aceptada)

Referencias

Ventajas

Positivas

  • Cero any en producción: TypeScript detecta errores en compilación
    que antes solo aparecían en runtime.
  • Imports validados: import/no-unresolved previene imports rotos,
    especialmente con los alias de Astro (@config/*, @utils/*).
  • Accesibilidad validada: jsx-a11y detecta problemas de accesibilidad
    en componentes .astro.
  • Copilot alineado: las instrucciones en .github/copilot-instructions.md
    mantienen el código generado por IA consistente con las convenciones.

Desventajas

Deuda técnica conocida

  • Semicolons: convención manual sin enforcement automático. El código
    generado por playwright codegen necesita limpieza manual.
  • Reglas de estilo (quotes, trailing commas, etc.) sin definir.
  • Decisión Prettier vs Stylistic pendiente.
  • no-explicit-any en warn en lugar de error; subir cuando Cypress
    se elimine.
  • Configuración de ESLint podría consolidarse mejor (algunas reglas
    sueltas).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions