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...

12 KiB

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:

git ls-files '*.ts' '*.tsx' '*.svelte' | xargs wc -l | sort -nr | head -n 30
git grep -n "toISOString().replace('T', ' ').replace('Z', '')"
git grep -n "normalizeTime(" && git grep -n "ymdUTC(" && git grep -n "addMonthsUTC(" && git grep -n "isValidYmd("
git grep -n "sha256Hex(" && git grep -n "SimulatedResponseQueue"
bunx tsc --noEmit --pretty false
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.
    • Lote 5 completado: división de TaskItem en subcomponentes (SVGs a iconos, TaskDueBadge, TaskAssignees, TaskCompleteButton, TaskActions, TaskText, TaskMeta); sin cambios funcionales; tests verdes y typecheck web limpio.

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: Completado.
    • 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): Completado.
  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.