diff --git a/docs/2025-11-01-plan-refactor-tecnico.md b/docs/2025-11-01-plan-refactor-tecnico.md new file mode 100644 index 0000000..c99f261 --- /dev/null +++ b/docs/2025-11-01-plan-refactor-tecnico.md @@ -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 250–335 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 (00–23:00–59). + +- 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.