# Architecture Rules Estas reglas son obligatorias para cualquier refactor posterior. Están pensadas para mantener boundaries claros, reducir acoplamiento y preservar comportamiento durante la migración. ## TypeScript - No usar `any`. - Usar `unknown` solo en boundaries. - Normalizar `unknown` inmediatamente al entrar al dominio. - No duplicar tipos entre extension y browser. - Todo replicant nuevo debe tener schema y tipo generado. - Regenerar tipos siempre desde schemas. ## Boundaries NodeCG - No acceder directamente a replicants fuera de `nodecg/browser` o `nodecg/extension`. - No usar `nodecg.sendMessage` directo en componentes o composables de feature. - No usar `nodecg.Replicant` directo fuera de la capa `nodecg`. - No depender de `nodecg` global salvo dentro del boundary correspondiente. - Centralizar nombres de replicants en `replicantNames`. - Centralizar nombres de messages en una capa de messages. ## Shared y Dominio - `shared/domain` solo puede contener funciones puras, tipos, normalizadores y mapping. - `shared/domain` no puede importar Vue. - `shared/domain` no puede importar NodeCG. - `shared/domain` no puede acceder al DOM. - Preferir funciones puras para normalización, parsing, derivación y mapping. - Validar o normalizar datos externos al cruzar boundaries. ## Dashboard - Los stores mantienen estado de aplicación y sync con replicants. - Los stores no deben contener UI compleja. - Las vistas no deben implementar features completos. - Los componentes deben ser pequeños y orientados a UI. - Los composables de feature no deben hablar directamente con NodeCG. - Toda lógica de negocio debe vivir en dominio, services o stores según corresponda. ## Extension - `extension/modules` debe contener handlers pequeños registrados desde bootstrap explícito. - No mezclar FS, HTTP, replicants, downloads y parsing en el mismo módulo. - Todo handler NodeCG debe declarar claramente qué message escucha y qué replicants toca. - Todo acceso a `nodecg.listenFor`, `nodecg.Replicant`, `nodecg.mount` y logging debe pasar por `nodecg/extension`. ## Packs - Pack registry, manifests, downloads y estado instalado deben compartir tipos comunes. - Todo replicant de packs debe tener schema. - Mantener nombres y defaults actuales durante la migración. - Validar manifests en el boundary antes de exponerlos al dominio o UI. - No mantener estado mutable de módulo opaco para packs instalados. - No usar `ref` de Vue dentro de shared. ## Integraciones - Providers como Start.gg y Challonge deben compartir patrón de OAuth, session polling y parsing. - Cada provider debe tener cliente propio y normalizadores propios. - El flujo OAuth debe apoyarse en `oauth-server.ts` cuando aplique. - Todo timer o polling debe tener cleanup. - Todo listener debe tener cleanup. ## Graphics y Overlays - Los overlays se refactorizan al final. - Primero preservar píxel y comportamiento; después limpiar internals. - No cambiar CSS, SVG, posiciones o markup sensible sin baseline visual. - Extraer view models antes de deduplicar layout. - Helpers compartidos de flags, score animation y text fitting deben vivir en `graphics/shared`. ## Side Effects - No side effects en imports salvo bootstrap explícito. - No estado mutable de módulo salvo singleton justificado y documentado. - Todo timer/listener debe registrar cleanup. - No wrappers vacíos. - No inventar un patrón si una función simple basta. ## Naming | Elemento | Regla | Ejemplo | | --- | --- | --- | | Replicants | `camelCase`, constantes en `replicantNames` | `graphicsSettings` | | Messages | Namespaced por dominio | `packs:download` | | Stores | `useStore` | `useScoreboardStore` | | Services | `createService` o `createClient` | `createPackService` | | View models | `useViewModel` | `useScoreboardOverlayViewModel` | ## Compatibilidad - Mantener comportamiento público durante la migración. - Mantener nombres públicos hasta completar el refactor. - No romper overlays sin baseline visual y verificación. - Priorizar eliminar legacy muerto antes que envolverlo.