- Introduced `.lintrc` for managing vertical spacing rules in the codebase. - Updated `eslint.config.mjs` to integrate the new spacing rules with ESLint. - Created documentation on code formatting and spacing guidelines in `formato-y-espaciado-del-codigo.md`. - Implemented tests in `spacing.test.mjs` to ensure spacing rules are enforced correctly without altering syntax.
328 lines
26 KiB
Markdown
328 lines
26 KiB
Markdown
# Instrucciones de Metis Desk
|
|
|
|
## Alcance y entorno
|
|
|
|
Proyecto independiente de factuges-erp. Se conserva su estilo, no sus funcionalidades ni dependencias locales.
|
|
El repositorio vive en `/home/david/dev/metis-desk`, en WSL2 Ubuntu-24.04.
|
|
Ejecutar las herramientas del proyecto dentro de WSL con bash, nunca desde Windows, rutas UNC o /mnt/c.
|
|
Antes de modificar código: comprobar pwd, git status --short, node --version y pnpm --version.
|
|
Usar Node.js 24.x y la versión de PNPM fijada en package.json.
|
|
No imprimir, copiar ni versionar .env locales o secretos.
|
|
|
|
`packages/shadcn-ui` contiene código de terceros/vendor. No refactorizar, reformatear, reorganizar ni modificar su implementación salvo instrucción explícita del usuario. Puede consultarse su API pública para integrarlo desde código propio.
|
|
|
|
## Convenciones
|
|
|
|
El espaciado vertical se define en `.lintrc`, cargado por `eslint.config.mjs`. Separar funciones, clases y métodos con una línea vacía; mantener agrupadas propiedades y firmas de sobrecarga. `pnpm format` combina Biome con estas reglas. Véase [formato y espaciado](docs/formato-y-espaciado-del-codigo.md).
|
|
|
|
- Código e identificadores en inglés; comentarios, TSDoc y documentación en castellano.
|
|
- Ficheros y directorios en kebab-case. Clases, tipos e interfaces en PascalCase.
|
|
- Variables, funciones y métodos en camelCase; constantes globales en UPPER_SNAKE_CASE.
|
|
- Interfaces con prefijo I cuando el área ya siga esa convención.
|
|
- Documentación en /docs, con nombres de ficheros en castellano.
|
|
- Comentarios que expliquen decisiones, riesgos o contratos, nunca que repitan el código.
|
|
- Mantener es y en para textos de interfaz; no insertar literales en áreas con i18n.
|
|
- Utilizar siempre llaves en if, else, for, while y estructuras equivalentes, incluso cuando el bloque contenga una sola instrucción.
|
|
|
|
## Disciplina
|
|
|
|
Aplicar SOLID, Clean Code, DRY, KISS, YAGNI, SSOT, fail fast y programación defensiva.
|
|
Priorizar claridad y explicitud frente a abstracción prematura.
|
|
Cambios incrementales y acotados. No renombrar, reformatear o mover código ajeno a la tarea.
|
|
No crear capas, factories, genéricos, eventos, contenedores DI ni repositorios base sin necesidad real.
|
|
Justificar cada nueva dependencia. Preferir APIs nativas cuando basten.
|
|
No añadir supresiones de TypeScript o Biome sin justificación.
|
|
No eliminar legado sin buscar y clasificar sus referencias en todo el monorepo.
|
|
|
|
## TypeScript y asincronía
|
|
|
|
- Importar tipos explícitamente con import type en la cabecera.
|
|
- No usar import("...").Tipo en código ordinario.
|
|
- Evitar any, assertions y non-null assertions salvo garantías verificables.
|
|
- Inferir DTOs de schemas Zod; no duplicarlos mediante interfaces.
|
|
- Usar unions para conjuntos cerrados y mantener switches exhaustivos.
|
|
- No usar Partial si el contrato ya representa la opcionalidad.
|
|
- No usar el operador void para descartar promesas.
|
|
- Toda promesa se espera, se devuelve o gestiona su error expresamente.
|
|
- No dejar promesas flotantes ni capturas que oculten fallos.
|
|
- Comprobar el contrato del callback antes de convertirlo a async.
|
|
- Usar Result para fallos de negocio y Maybe para ausencia semántica cuando se implementen esas operaciones.
|
|
- Collection solo cuando el conjunto necesite comportamiento de dominio; no introducir estos patrones sin consumidores.
|
|
|
|
## Arquitectura y contratos
|
|
|
|
Las fuentes normativas se consultan, no se duplican:
|
|
|
|
- [Capas del servidor](docs/arquitectura/capas-del-servidor.md)
|
|
- [Composición de módulos](docs/arquitectura/composicion-de-modulos.md)
|
|
- [Flujo HTTP](docs/arquitectura/flujo-http.md)
|
|
- [Contratos HTTP](docs/arquitectura/contratos-http.md)
|
|
- [Pruebas](docs/arquitectura/pruebas.md)
|
|
- [Modelo DDD e identificadores](docs/arquitectura/modelo-ddd-e-identificadores.md)
|
|
- [Estructura web por entidades y operaciones](docs/estructura-web-por-entidades-y-operaciones.md)
|
|
|
|
## Seguridad y persistencia
|
|
|
|
- Priorizar un diseño de BD normalizado, con columnas y tablas relacionadas. No almacenar valores en JSON salvo necesidad estricta; en ese caso plantearlo al usuario antes de implementarlo. JSON como formato de transporte HTTP no sustituye el diseño relacional.
|
|
|
|
- Menor privilegio y validación de toda entrada externa.
|
|
- Autenticación y autorización antes de acceder a datos de clientes.
|
|
- El cliente atendido no es el tenant de la empresa que presta soporte.
|
|
- Verificar siempre permisos y pertenencia; no confiar en companyId enviado por el navegador.
|
|
- No exponer SQL, stacks, datos sensibles o credenciales en respuestas ni logs.
|
|
- Registrar identificadores de petición y resultados suficientes para diagnosticar fallos.
|
|
- MariaDB y Sequelize v6 para persistencia; ORM exclusivamente en Infrastructure.
|
|
- Consultas parametrizadas, transacciones para cambios atómicos y restricciones en base de datos.
|
|
- Migraciones explícitas; no usar sync({ alter: true }) como sustituto.
|
|
- Toda entidad de negocio, incluidas las entidades internas de un agregado, tiene identidad UniqueID (UUID v7 para nuevas entidades), siguiendo factuges-erp.
|
|
- Declarar Value Objects, DomainEntity y AggregateRoot según docs/arquitectura/modelo-ddd-e-identificadores.md.
|
|
- Mantener semántica de create, rehydrate y update según la arquitectura.
|
|
- Comparar cambios de dominio semánticamente, no mediante JSON.stringify.
|
|
- Añadir idempotencia donde una repetición pueda producir efectos duplicados.
|
|
|
|
## Frontend
|
|
|
|
Todo código web nuevo de módulos, entidades y operaciones debe seguir [la estructura web por entidades y operaciones](docs/estructura-web-por-entidades-y-operaciones.md): `modules/<module>/src/web/<entity>/<operation>/`, con ámbitos `shared` según sus consumidores e índices únicamente donde haya contenido exportable para otras unidades. Esta guía es la fuente normativa de la organización interna del frontend; no cambia las capas del servidor ni la implementación vendor.
|
|
|
|
React, TanStack Query, Tailwind y shadcn/ui (Base UI, estilo Vega). Los componentes compartidos viven en @repo/shadcn-ui. Incorporar TanStack Table y React Hook Form cuando haya consumidores.
|
|
Estado remoto en TanStack Query; claves centralizadas e invalidación explícita después de mutaciones.
|
|
No duplicar estado remoto ni usar efectos para derivar valores calculables durante render.
|
|
Mantener accesibilidad y estados de carga, error, vacío y acciones deshabilitadas.
|
|
Separar componentes por responsabilidades reales, sin fragmentar JSX trivial.
|
|
Antes de crear o modificar pantallas, reconocer activamente patrones visuales y de interacción comunes entre ellas, así como componentes repetidos dentro de una misma pantalla. Aplicar soluciones coherentes a todos los casos equivalentes, conservando las necesidades propias de cada entidad.
|
|
Reutilizar y extender la biblioteca visual existente antes de duplicar estructura, estilos o comportamiento. Extraer componentes compartidos cuando haya repetición real: cabeceras, listados, formularios modales, grupos de campos, selectores con alta, estados y ayuda contextual.
|
|
Construir progresivamente una biblioteca visual básica con contratos claros, accesibilidad, textos traducibles y composición sencilla. Mantener los componentes genéricos independientes de entidades, DTO, consultas y endpoints de Metis Desk; el módulo consumidor aporta datos, textos y acciones. Documentar patrones y componentes en docs/componentes-de-interfaz.md y en el estándar correspondiente.
|
|
Preparar esa independencia para poder agrupar o extraer posteriormente componentes en un paquete reutilizable en otras aplicaciones. Aprovechar @repo/shadcn-ui y crear abstracciones conforme aparezcan consumidores reales.
|
|
Las pantallas de listado de entidades siguen [el patrón de listados](docs/patron-de-listados-de-entidades.md), reutilizando los componentes comunes de @repo/shadcn-ui.
|
|
Los listados no muestran formularios de alta ni edición junto a los datos. El alta se inicia con un botón en la cabecera, a la derecha; formularios en modal shadcn/ui como norma general, con anchura y desplazamiento adaptados a su contenido. La edición se abre mediante una acción explícita, siguiendo el mismo criterio. Mantener foco, cierre por teclado, cancelación y errores dentro del formulario. Incluir ayuda contextual con finalidad, ámbito y ejemplos, sin rellenar los campos automáticamente. En formularios, colocar la ayuda en la parte inferior, inmediatamente antes del pie del modal con Guardar y Cancelar.
|
|
|
|
## Validación y entrega
|
|
|
|
Ejecutar pnpm typecheck, pnpm lint, pnpm test, pnpm check y pnpm build en cambios transversales.
|
|
Preferir comprobaciones dirigidas al paquete cuando sean suficientes.
|
|
Añadir pruebas de comportamiento observable: válidos, inválidos, límites e idempotencia cuando corresponda.
|
|
Tests deterministas, sin esperas arbitrarias ni desactivaciones.
|
|
Informar cambios, archivos principales, comandos ejecutados, resultados y pendientes reales.
|
|
No afirmar validaciones no ejecutadas ni ocultar fallos conocidos.
|
|
|
|
Precedencia: instrucciones actuales del usuario, AGENTS.md más cercano, este archivo y convenciones existentes.
|
|
|
|
|
|
## Buenas prácticas de implementación
|
|
|
|
Estas reglas complementan las convenciones y documentos de arquitectura existentes. Antes de introducir un patrón nuevo, comprobar cómo resuelve el repositorio casos equivalentes y mantener coherencia con ellos.
|
|
|
|
### Idioma
|
|
|
|
- Responder, explicar decisiones, documentar cambios y redactar comentarios y TSDoc en castellano.
|
|
- Mantener código, identificadores, nombres de tipos, funciones, variables, componentes, hooks y ficheros en inglés.
|
|
- No traducir nombres de APIs, bibliotecas, protocolos ni conceptos técnicos cuando su denominación habitual esté en inglés.
|
|
- Los mensajes destinados al usuario final deben pasar por el sistema de internacionalización cuando corresponda.
|
|
|
|
### TypeScript
|
|
|
|
- Mantener TypeScript en modo estricto y resolver los errores de tipos en su origen; no debilitarlos para conseguir que compile.
|
|
- Preferir inferencia cuando el tipo sea evidente y anotaciones explícitas cuando formen parte de un contrato público o mejoren realmente la comprensión.
|
|
- Usar `unknown` para datos cuyo tipo todavía no haya sido validado. No sustituir `unknown` por `any` para evitar realizar narrowing.
|
|
- Validar todos los datos procedentes de fronteras externas: HTTP, base de datos cuando corresponda, variables de entorno, almacenamiento, mensajes, APIs externas y datos serializados.
|
|
- No considerar un cast `as Tipo` como validación.
|
|
- Preferir narrowing, type guards, schemas y discriminated unions frente a assertions.
|
|
- Preferir `satisfies` cuando se quiera comprobar que un valor cumple un contrato conservando su inferencia concreta.
|
|
- Evitar enums cuando una unión de literales o un objeto constante tipado represente mejor un conjunto cerrado.
|
|
- Hacer exhaustivos los `switch` sobre discriminated unions mediante `never` cuando sea útil.
|
|
- Evitar parámetros booleanos cuyo significado no resulte evidente en la llamada; utilizar opciones o tipos semánticos cuando mejoren la legibilidad.
|
|
- No crear tipos contenedores, aliases o genéricos que solamente oculten otro tipo sin aportar semántica.
|
|
- No duplicar tipos que puedan derivarse de una única fuente normativa.
|
|
- Mantener la opcionalidad exacta del dominio: distinguir cuando sea relevante entre propiedad ausente, `undefined` y `null`.
|
|
- Preferir estructuras inmutables cuando los datos no deban modificarse.
|
|
- No capturar excepciones únicamente para volver a lanzarlas sin aportar contexto, conversión o recuperación.
|
|
- No usar excepciones como flujo normal para resultados de negocio esperables.
|
|
- Las funciones deben tener contratos claros y evitar efectos laterales inesperados.
|
|
|
|
### Node.js
|
|
|
|
- No bloquear el event loop con operaciones síncronas de I/O dentro de rutas, servicios ejecutados por petición o procesos concurrentes.
|
|
- Preferir APIs asíncronas para filesystem, red, criptografía y procesos externos cuando formen parte del flujo de ejecución normal.
|
|
- Toda operación externa susceptible de quedar bloqueada debe disponer de timeout cuando la API utilizada lo permita.
|
|
- Utilizar `AbortSignal` o mecanismos equivalentes cuando sea necesario propagar cancelación.
|
|
- No dispersar accesos a `process.env` por la aplicación. Cargar, validar y normalizar la configuración en un punto definido durante el arranque.
|
|
- Fallar durante el arranque si falta configuración imprescindible, en lugar de descubrirla durante una petición.
|
|
- No mantener estado mutable global dependiente de una petición.
|
|
- No almacenar en memoria información cuya persistencia o coherencia dependa de varias instancias del servidor.
|
|
- Gestionar explícitamente el cierre ordenado de recursos persistentes cuando corresponda: servidor HTTP, conexiones de base de datos, colas y otros recursos externos.
|
|
- No ocultar `unhandledRejection`, `uncaughtException` ni errores de infraestructura para mantener artificialmente el proceso funcionando.
|
|
|
|
### Express
|
|
|
|
- Mantener las rutas y controladores pequeños.
|
|
- El controlador HTTP traduce entre HTTP y la aplicación; no contiene lógica de negocio.
|
|
- No acceder directamente al ORM desde routers o controladores salvo que la arquitectura documentada establezca expresamente otra cosa.
|
|
- Validar `params`, `query`, `headers` y `body` en la frontera HTTP antes de utilizarlos.
|
|
- No confiar en tipos TypeScript para considerar válidos datos recibidos por HTTP.
|
|
- Centralizar la transformación de errores a respuestas HTTP.
|
|
- No repetir bloques `try/catch` en cada handler si el mecanismo de errores de Express ya propaga correctamente los rechazos.
|
|
- Distinguir errores esperables de aplicación, errores de validación, autenticación/autorización, conflictos y errores inesperados de infraestructura.
|
|
- No enviar al cliente mensajes internos de excepciones, SQL, stack traces ni detalles de implementación.
|
|
- Una petición debe producir una única respuesta. Evitar ramas que puedan continuar después de enviar la respuesta.
|
|
- Los middleware deben tener una responsabilidad concreta y efectos explícitos.
|
|
- No utilizar middleware global para comportamiento que solo pertenece a una ruta o módulo.
|
|
- Mantener la composición de routers, middleware, controladores, casos de uso y repositorios según la arquitectura documentada del proyecto.
|
|
|
|
### React 19
|
|
|
|
- Los componentes y hooks deben ser puros durante render.
|
|
- No producir efectos laterales durante render.
|
|
- No modificar props, estado, valores recibidos por hooks ni objetos pertenecientes a renders anteriores.
|
|
- No llamar componentes como funciones ordinarias; renderizarlos mediante JSX.
|
|
- Respetar estrictamente las Rules of Hooks.
|
|
- No utilizar hooks condicionalmente ni después de retornos que hagan variar su orden entre renders.
|
|
|
|
#### Organización de componentes
|
|
|
|
- Como norma general, cada fichero `.tsx` contiene un único componente React principal.
|
|
- No agrupar varios componentes funcionales relevantes en un mismo fichero por comodidad.
|
|
- Extraer un componente a su propio fichero cuando tenga props propias, estado, hooks, lógica de interacción, lógica de renderizado significativa o una responsabilidad identificable.
|
|
- Un subcomponente privado solo puede permanecer en el mismo fichero cuando sea pequeño, puramente presentacional, inseparable del componente principal y no dificulte la lectura.
|
|
- Si aparecen varios subcomponentes privados en el mismo fichero, reconsiderar la descomposición y extraerlos.
|
|
- No crear componentes únicamente para reducir el número de líneas de JSX. Extraer por responsabilidad, semántica o reutilización real.
|
|
- Evitar componentes monolíticos que mezclen consulta de datos, estado complejo, transformación de datos y grandes bloques de presentación.
|
|
- Mantener próximos entre sí el componente y los elementos que sean exclusivamente suyos, sin convertir los directorios en estructuras artificialmente profundas.
|
|
|
|
#### Estado y efectos
|
|
|
|
- Mantener el estado mínimo necesario.
|
|
- No guardar en estado valores que puedan calcularse correctamente a partir de props, estado existente o datos de consulta durante render.
|
|
- No utilizar `useEffect` para sincronizar un estado React con otro estado React.
|
|
- No utilizar `useEffect` para responder a una acción concreta del usuario; ejecutar esa lógica desde el event handler correspondiente.
|
|
- Utilizar efectos para sincronización real con sistemas externos, suscripciones, APIs imperativas del navegador u otros recursos externos.
|
|
- Todo efecto que cree una suscripción, listener, temporizador o recurso debe realizar su cleanup correspondiente.
|
|
- Diseñar efectos de forma que soporten correctamente montaje, desmontaje y nueva ejecución.
|
|
- No introducir `useMemo` o `useCallback` por defecto. Utilizarlos cuando exista una razón concreta de rendimiento, estabilidad referencial requerida por un contrato o evidencia obtenida mediante profiling.
|
|
- No duplicar en estado local datos gestionados por TanStack Query salvo que exista una necesidad explícita de edición local temporal.
|
|
- No copiar props a estado salvo que exista una semántica concreta que lo justifique.
|
|
- Preferir estado local al componente que lo consume y elevarlo únicamente cuando varios consumidores necesiten compartirlo.
|
|
|
|
#### Hooks
|
|
|
|
- Un custom hook debe encapsular comportamiento React reutilizable o una responsabilidad React claramente identificable.
|
|
- No crear hooks como simple sustitución de funciones normales.
|
|
- No crear hooks genéricos anticipando reutilización futura sin consumidores reales.
|
|
- Mantener los hooks independientes de detalles visuales cuando sea posible.
|
|
- No ocultar efectos importantes o llamadas remotas dentro de hooks con nombres ambiguos.
|
|
|
|
#### Componentes visuales
|
|
|
|
- Los componentes presentacionales no deben conocer endpoints, Express, Sequelize ni detalles de persistencia.
|
|
- Los componentes reutilizables no deben depender directamente de DTOs específicos de Metis Desk cuando puedan expresarse mediante props más pequeñas y semánticas.
|
|
- Preferir composición mediante `children` y props explícitas frente a componentes con multitud de flags booleanos.
|
|
- Evitar componentes con muchas variantes booleanas que produzcan combinaciones de estados difíciles de comprender.
|
|
- Mantener accesibilidad semántica: elemento HTML correcto, etiquetas, relaciones entre controles, navegación por teclado y foco.
|
|
- No implementar manualmente primitivas que shadcn/ui o Base UI ya proporcionen adecuadamente.
|
|
|
|
#### Diálogos, modales y ventanas emergentes
|
|
|
|
- Páginas y listados no deben implementar directamente el contenido de ventanas modales funcionales. Los diálogos de alta, edición, confirmación, selección o detalle son componentes independientes.
|
|
- Toda ventana modal, cuadro de diálogo o formulario modal con contenido y responsabilidad propios debe extraerse a un componente React independiente y vivir en su propio fichero `.tsx`.
|
|
- Esta regla se aplica especialmente a componentes construidos con primitivas de shadcn/ui como `Dialog`, `AlertDialog`, `Sheet`, `Drawer` o componentes propios como `FormDialog`, pero no depende del nombre concreto utilizado.
|
|
- Si un bloque representa una interacción modal reconocible por sí misma —por ejemplo alta, edición, confirmación, selección, detalle, ayuda o cambio de estado— debe considerarse un componente independiente.
|
|
- El componente padre debe encargarse de decidir cuándo se abre el diálogo y de suministrarle los datos o callbacks necesarios, evitando contener internamente todo el JSX del modal.
|
|
- El componente del diálogo debe encapsular su estructura visual y la lógica de interacción que le pertenezca.
|
|
- No mantener grandes bloques de JSX de `DialogContent`, formularios completos o confirmaciones dentro del fichero de una página o listado cuando puedan identificarse como una unidad funcional independiente.
|
|
- Los formularios que se muestran dentro de un diálogo pueden separarse además en un componente propio cuando tengan suficiente entidad, reutilización o complejidad.
|
|
- No extraer a otro fichero un `Dialog` trivial cuyo único contenido sea un mensaje mínimo sin lógica, estado, formulario ni responsabilidad propia, salvo que forme parte de un patrón reutilizado.
|
|
- Antes de crear un diálogo nuevo, comprobar si ya existe un componente equivalente o un patrón común reutilizable en el proyecto.
|
|
|
|
### Formularios
|
|
|
|
- Mantener una única fuente de verdad para cada campo.
|
|
- Utilizar React Hook Form cuando el formulario tenga complejidad suficiente y siguiendo los patrones existentes del repositorio.
|
|
- Utilizar schemas Zod como fuente normativa de validación cuando corresponda.
|
|
- No duplicar manualmente reglas de validación entre schema, formulario y llamada HTTP.
|
|
- Mostrar errores junto al contexto que los origina.
|
|
- Diferenciar errores de campo, errores globales del formulario y errores inesperados del servidor.
|
|
- Evitar envíos duplicados y reflejar visualmente estados pendientes.
|
|
- No limpiar o cerrar un formulario hasta confirmar que la operación que lo requiere se ha completado correctamente.
|
|
|
|
### Acceso a datos en frontend
|
|
|
|
- Centralizar query keys y mantenerlas estables.
|
|
- Las funciones de acceso a API no deben depender de componentes React.
|
|
- No realizar `fetch` directamente dentro de componentes si el módulo dispone de una capa de API o query establecida.
|
|
- No utilizar `useEffect` como sustituto de TanStack Query para cargar datos remotos.
|
|
- Después de una mutación, actualizar o invalidar únicamente las queries afectadas con una estrategia explícita.
|
|
- No invalidar indiscriminadamente toda la caché para evitar razonar sobre dependencias.
|
|
- Gestionar explícitamente estados de carga inicial, actualización, error, ausencia de datos y permisos insuficientes.
|
|
|
|
### Estructura de ficheros
|
|
|
|
- Cada fichero debe tener una responsabilidad reconocible.
|
|
- Evitar ficheros genéricos como `utils.ts`, `helpers.ts`, `common.ts`, `types.ts` o `constants.ts` convertidos en cajones de sastre.
|
|
- Ubicar utilidades, tipos y constantes junto al dominio o funcionalidad a la que pertenecen.
|
|
- Extraerlos a una ubicación compartida únicamente cuando existan consumidores reales en diferentes áreas.
|
|
- No crear ficheros `index.ts` o barrels indiscriminadamente.
|
|
- Evitar barrels que oculten dependencias, provoquen ciclos de importación o dificulten localizar el origen de un símbolo.
|
|
- No crear directorios con un único fichero sin que aporten una frontera conceptual útil.
|
|
- No reorganizar carpetas solamente por preferencia personal durante una tarea no relacionada.
|
|
|
|
### Funciones y responsabilidades
|
|
|
|
- Preferir funciones pequeñas con una responsabilidad definida, pero no fragmentar una operación sencilla en multitud de funciones triviales.
|
|
- Los nombres deben describir intención, no implementación accidental.
|
|
- Una función que realiza una consulta no debe modificar estado salvo que su contrato lo indique claramente.
|
|
- Separar cálculo puro de I/O cuando esa separación mejore pruebas y razonamiento.
|
|
- Reducir anidamiento mediante retornos tempranos cuando mejoren la legibilidad.
|
|
- No utilizar retornos tempranos que oculten invariantes o hagan difícil seguir el flujo.
|
|
- No crear parámetros, opciones o extensibilidad que ningún consumidor necesite actualmente.
|
|
|
|
### Dependencias
|
|
|
|
- Antes de añadir una dependencia, comprobar si el proyecto o la plataforma ya resuelven el problema.
|
|
- No instalar una biblioteca por una única función trivial que pueda implementarse claramente con APIs estándar.
|
|
- No sustituir una dependencia ya establecida por otra equivalente sin una razón explícita.
|
|
- Comprobar compatibilidad con las versiones reales de Node.js, React, TypeScript y demás dependencias del repositorio.
|
|
- No asumir APIs de una versión distinta a la instalada.
|
|
|
|
### Errores y observabilidad
|
|
|
|
- Los errores deben conservar causa y contexto suficiente para poder diagnosticarlos.
|
|
- No registrar el mismo error repetidamente en todas las capas.
|
|
- Registrar el error en la capa responsable de observarlo o resolverlo.
|
|
- No registrar tokens, contraseñas, cookies, cuerpos sensibles ni credenciales.
|
|
- No utilizar `console.log` como mecanismo permanente de observabilidad cuando exista infraestructura de logging.
|
|
- Los mensajes de error internos deben ser útiles para diagnóstico; los destinados al usuario no deben revelar detalles internos.
|
|
|
|
### Pruebas
|
|
|
|
- Probar comportamiento observable y contratos, no detalles internos de implementación.
|
|
- No escribir tests cuyo único objetivo sea aumentar cobertura.
|
|
- Evitar mocks cuando pueda utilizarse una dependencia real rápida y determinista o un fake sencillo.
|
|
- Mockear fronteras externas, no cada función interna.
|
|
- Mantener los tests legibles y con preparación mínima.
|
|
- Cada corrección de un bug reproducible debe considerar una prueba que falle antes de la corrección y pase después.
|
|
- Para lógica con estados cerrados, cubrir los casos relevantes y los límites, no solamente el camino feliz.
|
|
|
|
### Criterio antes de escribir código
|
|
|
|
Antes de implementar:
|
|
|
|
1. Buscar implementaciones equivalentes dentro del repositorio.
|
|
2. Consultar la documentación normativa del proyecto aplicable.
|
|
3. Identificar qué capa es responsable del comportamiento.
|
|
4. Comprobar si ya existe un componente, hook, schema, utilidad, Value Object o servicio reutilizable.
|
|
5. Elegir la solución más pequeña que respete los contratos existentes.
|
|
6. Evitar introducir una abstracción nueva si un patrón existente resuelve adecuadamente el problema.
|
|
|
|
Durante la implementación:
|
|
|
|
- No ampliar el alcance para corregir cuestiones no relacionadas.
|
|
- Si se detecta una mejora ajena a la tarea, mencionarla al finalizar en lugar de modificarla automáticamente.
|
|
- No alterar APIs públicas, contratos HTTP, schemas, migraciones o comportamiento compartido como efecto secundario accidental.
|
|
- No crear compatibilidad hacia atrás que nadie haya solicitado cuando se pueda actualizar de forma controlada a todos los consumidores.
|
|
- No dejar código muerto, implementaciones alternativas comentadas ni TODO vagos.
|
|
|
|
Al finalizar:
|
|
|
|
- Revisar el diff completo, no únicamente los ficheros editados individualmente.
|
|
- Comprobar que no se hayan introducido duplicaciones, componentes excesivamente grandes, varios componentes relevantes por fichero, imports no usados, casts innecesarios ni efectos React evitables.
|
|
- Ejecutar las validaciones apropiadas para el alcance real del cambio.
|