You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
taskbot/docs/2025-11-01-plan-refactor-te...

260 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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 (Completada)
Comandos ejecutados con éxito el 2025-11-01; a continuación se conservan para referencia y repetibilidad:
```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.
## Progreso
- 2025-11-01:
- Documento creado y versionado (commit a104b69).
- Diagnóstico ejecutado (wc -l, git grep, tsc, coverage) y hallazgos consolidados en este documento.
- Pendiente iniciar Lote 0 (Infra de typecheck): a la espera de revisar tsconfig raíz, apps/web/tsconfig y apps/web/vite.config.
- 2025-11-02:
- Lote 1 completado: util canónica de fechas/UTC creada (src/utils/datetime.ts) y wrapper web (apps/web/src/lib/server/datetime.ts); migración de rutas ICS y reemplazos en producción (hooks, login, complete/uncomplete, calendar tokens, dev-seed, response-queue, maintenance, group-sync, migrator).
- Commits relevantes: f4f7d95, 882f5c9, c1f12ff, df27161, a0f35b8.
- Tests verdes. Cobertura actual: 85.91% funciones / 82.12% líneas.
- 2025-11-07:
- Lote 0 completado: scripts `typecheck:core` y `typecheck:web` configurados y verificados. Se utiliza `tsconfig.core.json` para aislar el typecheck del core con reglas laxas, mientras que la web usa su propia configuración de SvelteKit. Los shims en `src/types/shims.d.ts` resuelven conflictos de tipos entre Bun y el DOM.
- Verificación exitosa: `bun run typecheck:core` y `bun run typecheck:web` se ejecutan sin errores.
- 2025-11-09:
- Lote 2 completado: centralización de helpers de tests (sha256Hex, toIsoSql), unificación de SimulatedResponseQueue y helpers ICS (ymdUTC, addDays) en tests.
- Commits relevantes: 77e318e, 1ad36ee, y este commit.
- 2025-11-10:
- Lote 3 completado: endurecimiento de tipos (noImplicitAny, exactOptionalPropertyTypes, strictNullChecks), centralización de normalizeTime y tipado ligero de SQLite en servicios; inclusión de servicios en typecheck; limpieza de as any en puntos clave.
- Verificación: typecheck core/web limpios y tests verdes.
- Lote 4 completado: ICS central y rutas homogéneas; rate limiting por token; títulos “Wtask.org Tareas Personal/Grupo/Agregado” y PRODID “-/Wtask.org//ICS 1.0//ES”; eventos de día completo; ETag/304 y Cache-Control; actualización de last_used_at solo en 200.
- Commit relevante: 234053c.
## Estado actual (2025-11-10)
- Fase 1 — Diagnóstico asistido: Completada.
- Fase 2 — Plan de refactor por lotes: En curso.
- Lote 0 — Infra de typecheck: Completado.
- Lote 1 — Utilidades de fecha/hora y validaciones: Completado.
- Lote 2 — Helpers de test y cripto: Completado.
- Lote 3 — Tipos y endurecimiento suave: Completado.
- Lote 4 — ICS central y rutas homogéneas: Completado.
- Lote 5 — Svelte: dividir componentes grandes: Pendiente.
- Lote 6 — DB Locator / DI ligera: Pendiente.
- Lote 7 — Cobertura en módulos flojos: Pendiente.
## 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) - Completado
- 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 - Completado
- 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 - Completado
- 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 - Completado
- 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 - Completado
- 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): **Completado**.
2) Unificar fechas/validaciones (Lote 1): **Completado**.
3) Centralizar helpers de tests y cripto (Lote 2): **Completado**.
4) Endurecer tipos en core (Lote 3): **Completado**.
5) Consolidar ICS (Lote 4): **Completado**.
6) Dividir TaskItem y revisar AppShell (Lote 5): **Siguiente**.
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.