docs: añadir plan de refactor técnico 2025-11-01

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
main
brobert 2 months ago
parent fd64cbd67d
commit a104b69065

@ -0,0 +1,229 @@
# Plan de Refactor Técnico — 2025-11-01
Este documento describe un plan de refactor seguro, incremental y medible para estabilizar tipado, reducir duplicación, mejorar estructura y preparar la base para evolución a largo plazo. Se prioriza no añadir dependencias externas y mantener el comportamiento actual cubierto por tests.
## Objetivos
- Reducir duplicación (fechas/horas, validaciones, helpers de tests, cripto).
- Endurecer tipado y contratos en TypeScript (mientras mantenemos compatibilidad).
- Clarificar capas (utils compartidos, servicios, API web, UI SvelteKit, tests).
- Estabilizar convenciones (UTC, formato SQLite, alias/imports, nombres).
- Mantener comportamiento: cambios sin funcionalidad nueva, validados por tests.
## Hallazgos clave (del diagnóstico inicial)
- Archivos grandes:
- apps/web/src/lib/ui/data/TaskItem.svelte ~911 LOC (punto caliente claro).
- Varias páginas Svelte de 250335 LOC (AppShell, /app, /app/groups, etc.).
- Duplicación evidente:
- Formateo SQL-UTC con `toISOString().replace('T',' ').replace('Z','')` aparece 35+ veces en app y tests.
- `normalizeTime` duplicado en API y page.server.
- `ymdUTC` y `addMonthsUTC` definidas 3 veces en rutas ICS y también en tests.
- `sha256Hex` reimplementado en múltiples tests pese a existir en `src/utils/crypto.ts`.
- SimulatedResponseQueue replicado en varios tests.
- Tipado/infra:
- tsc falla en apps/web por `$lib` y `./$types` (faltan tipos generados SvelteKit) y por DOM (navigator/document) y Bun types (HeadersInit/fetch).
- apps/web/vite.config.ts incompatibilidad de tipos (UserConfig).
- Errores “unknown” por resultados de SQLite (faltan tipos/casts).
- Inconsistencias null vs undefined (p. ej., groupColor, whatsapp utils).
- Cobertura mejorable:
- webhook-manager (~32%), maintenance (~17%), contacts (~26%), onboarding (~30%), response-queue (~50%).
- Organización:
- Inyección de DB mediante propiedades estáticas dispersas; funcional pero frágil. Falta un “locator” central.
## Fase 1 — Diagnóstico asistido
Comandos a ejecutar para obtener una foto objetiva (no añaden dependencias):
```bash
git ls-files '*.ts' '*.tsx' '*.svelte' | xargs wc -l | sort -nr | head -n 30
```
```bash
git grep -n "toISOString().replace('T', ' ').replace('Z', '')"
```
```bash
git grep -n "normalizeTime(" && git grep -n "ymdUTC(" && git grep -n "addMonthsUTC(" && git grep -n "isValidYmd("
```
```bash
git grep -n "sha256Hex(" && git grep -n "SimulatedResponseQueue"
```
```bash
bunx tsc --noEmit --pretty false
```
```bash
bun test --coverage
```
Resultados esperados después del refactor: disminución drástica de duplicados, tsc limpio por paquete, y cobertura estable o al alza.
## Fase 2 — Plan de refactor por lotes (PRs pequeñas y seguras)
Cada lote incluye objetivo, cambios, métricas y comprobaciones. Mantener tests verdes en cada paso.
### Lote 0 — Infra de typecheck (preparación)
- Objetivo:
- Separar el chequeo de tipos por paquete (core vs web) para aislar errores de SvelteKit/Bun/DOM.
- Cambios:
- Scripts: `typecheck:core` (tsc -p tsconfig.core.json), `typecheck:web` (apps/web: svelte-kit sync + tsc).
- En raíz, excluir apps/web del typecheck general si hace falta hasta que esté sincronizado.
- Ajustar lib/types: en core, definir tipos mínimos para HeadersInit/fetch si no se quiere añadir bun-types; en web, asegurar DOM y tipos SvelteKit (via `svelte-kit sync`).
- Revisar apps/web/vite.config.ts para que encaje con tipos `UserConfig`.
- Métricas:
- `bunx tsc --noEmit` limpio por paquete.
- Desaparecen errores `$lib` y `./$types` tras `svelte-kit sync`.
- Comprobaciones:
- `cd apps/web && bunx svelte-kit sync && bunx tsc --noEmit`.
### Lote 1 — Utilidades de fecha/hora y validaciones
- Objetivo:
- Centralizar y unificar: SQL-UTC, validadores YMD y HH:mm, utilidades ICS (ymdUTC, addMonthsUTC).
- Cambios:
- Crear helpers canónicos (por ejemplo, `toIsoSqlUTC`, `isValidYmd`, `normalizeTime`, `ymdUTC`, `addMonthsUTC`) en un módulo compartido (core o shared) y exportarlos también para web si aplica.
- Reemplazar todas las ocurrencias del patrón `toISOString().replace(...)`.
- Unificar las 3 rutas ICS para usar las mismas utilidades.
- Métricas:
- `git grep "toISOString().replace('T', ' ').replace('Z', '')"` → 1 referencia (en el helper) o 0 si se encapsula internamente.
- `git grep "ymdUTC("` y `"addMonthsUTC("` solo en helpers + imports.
- Comprobaciones:
- Tests ICS y API siguen verdes.
### Lote 2 — Helpers de test y cripto
- Objetivo:
- Eliminar duplicación en tests.
- Cambios:
- Reemplazar implementaciones locales de `sha256Hex` por import desde `src/utils/crypto`.
- Centralizar SimulatedResponseQueue en `tests/helpers/queue.ts` y reusarlo.
- Unificar helpers de fechas en tests (`toIsoSql`, `ymdUTC`, `addDays`) en `tests/helpers/dates.ts`.
- Métricas:
- `git grep -n "async function sha256Hex"` en tests → 0.
- `git grep -n "SimulatedResponseQueue"` → 1 implementación única.
- Comprobaciones:
- `bun test --coverage` estable o mejor.
### Lote 3 — Tipos y endurecimiento suave
- Objetivo:
- Bajar ruido de TS con cambios mínimos, sin funcionalidad nueva.
- Cambios:
- Resolver `undefined` vs `null` en utils como groupColor/whatsapp.
- Corregir `HeadersInit`/`fetch` en servicios (group-sync, webhook-manager, contacts) para encajar con tipos.
- Añadir refinamientos y cheques donde TS marca “posiblemente undefined”.
- Tipar resultados de SQLite `.get()`/`.all()` en tests y servicios.
- Métricas:
- `bunx tsc --noEmit` limpio en core.
- Comprobaciones:
- Tests verdes.
### Lote 4 — ICS central y rutas homogéneas
- Objetivo:
- Consolidar construcción de ICS (escape, folding, etag) en un módulo central.
- Cambios:
- Mover `ymdUTC`/`addMonthsUTC` al módulo `apps/web/src/lib/server/ics.ts` y usarlos desde aggregate/group/personal.
- Mantener helpers de escape/folding/etag en el mismo módulo.
- Métricas:
- `git grep -n "function ymdUTC"` y `"function addMonthsUTC"` solo en ics.ts.
- Comprobaciones:
- Tests ICS (`tests/web/ics.*`) verdes.
### Lote 5 — Svelte: dividir componentes grandes
- Objetivo:
- Reducir complejidad de UI; mejorar mantenibilidad.
- Cambios:
- Dividir `TaskItem.svelte` (~911 LOC) en subcomponentes: Header/Status, Assignees, DueBadge, Actions, Metadata, etc.
- Revisar `AppShell` y `/app/+page` para separar lógica de datos y presentación (stores y load).
- Métricas:
- `TaskItem.svelte` < 300 LOC.
- Comprobaciones:
- Pruebas E2E web verdes.
### Lote 6 — DB Locator / DI ligera
- Objetivo:
- Simplificar inyección de DB en runtime y tests.
- Cambios:
- Crear un “dbLocator” (getDb/setDb) central y migrar servicios a usarlo progresivamente, manteniendo compatibilidad con propiedades estáticas mientras dura la transición.
- Unificar `resolveDbAbsolutePath` entre core y web (una sola fuente).
- Métricas:
- Sin cambios de comportamiento; tests de servicios verdes.
### Lote 7 — Cobertura en módulos flojos
- Objetivo:
- Aumentar cobertura en módulos con lógica y baja cobertura (webhook-manager, maintenance, contacts, onboarding, response-queue).
- Cambios:
- Añadir pruebas de ramas de error y caminos menos transitados.
- Métricas:
- Cobertura de líneas > 80% en esos módulos.
## Convenciones acordadas
- Fechas/horas:
- Persistir en UTC en SQLite con formato ISO-SQL “YYYY-MM-DD HH:MM:SS[.SSS]”.
- Un solo helper para serializar/deserializar timestamps.
- Validadores canónicos: YMD (YYYY-MM-DD), HH:mm (0023:0059).
- Tipado:
- TS estricto por módulos de forma incremental: `strict`, `noImplicitAny`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes` (activación progresiva).
- Resultados SQLite tipados (interfaces pequeñas y casts controlados).
- Organización:
- Helpers compartidos (fecha/validaciones/cripto) en módulo único (o shared).
- Tests reusan helpers de `tests/helpers`.
- SvelteKit:
- `svelte-kit sync` antes de `tsc` para generar tipos.
- Rutas ICS homogéneas con helpers de `lib/server/ics`.
## Riesgos y mitigación
- Fechas/UTC: posibles regresiones en límites y recordatorios.
- Mitigación: snapshots/fixtures antes/después de serializaciones, comparar salidas ICS.
- DI de DB: transición puede generar inconsistencias si se mezcla estático/locator.
- Mitigación: migración gradual y adaptador de compatibilidad temporal.
- Tipado estricto: ruido inicial.
- Mitigación: endurecer flags por paquete/módulo en varias PRs pequeñas.
## Métricas de aceptación por lote
- Tests verdes y sin cambios funcionales.
- Reducción de duplicados medible (git grep antes/después).
- `bunx tsc --noEmit` limpio en el ámbito del lote.
- Cobertura estable o en subida en módulos afectados.
## Siguientes pasos prácticos
1) Estabilizar typecheck (Lote 0):
- Alinear tsconfig raíz y web, y Vite config.
- Ejecutar:
```bash
cd apps/web && bunx svelte-kit sync && bunx tsc --noEmit --pretty false
```
2) Unificar fechas/validaciones (Lote 1) y reemplazar duplicados.
3) Centralizar helpers de tests y cripto (Lote 2).
4) Endurecer tipos en core (Lote 3).
5) Consolidar ICS (Lote 4).
6) Dividir TaskItem y revisar AppShell (Lote 5).
7) DI ligera para DB (Lote 6).
8) Aumentar cobertura en módulos flojos (Lote 7).
## Información adicional a recopilar (para Lote 0)
- tsconfig.json (raíz)
- apps/web/tsconfig.json
- apps/web/vite.config.ts
Con estos 3 archivos podremos definir cambios mínimos para tener un typecheck limpio por paquetes sin introducir dependencias externas.
Loading…
Cancel
Save