Integrar nuevas entidades en una arquitectura NestJS no significa crear un módulo por cada tabla. Cuando una entidad como categories se relaciona directamente con posts en una relación many-to-many, lo más limpio es encapsularla dentro del mismo módulo y reorganizar controladores y servicios en carpetas dedicadas. Aquí verás cómo hacerlo y cómo apoyarte en IA para acelerar el CRUD sin perder buenas prácticas.
Por qué no crear un módulo por cada entidad en NestJS
Cuando usas el Resource Generator de NestJS, la herramienta crea un módulo completo por entidad. Parece ordenado, pero termina inflando el proyecto con módulos que en realidad pertenecen al mismo dominio.
En este caso, categories se relaciona con posts en una relación many-to-many: un post puede pertenecer a varias categorías y una categoría puede tener varios posts. Por eso la nueva entidad vive dentro del módulo posts, junto con sus propios controladores y servicios.
¿Cuándo conviene crear un módulo nuevo en NestJS? Cuando la entidad representa un dominio independiente. Si está acoplada a otra entidad por relaciones directas, encapsúlala dentro del módulo existente para mejorar manejabilidad y escalabilidad.
Es el mismo patrón que ya viste con user y profile: dos entidades, un solo módulo, sin duplicar controladores ni servicios innecesarios [02:15].
Cómo estructurar carpetas controllers y services dentro de un módulo
La entidad category arranca simple: un ID con primary generated column, un campo name único, y columnas de creación y actualización. Sin relaciones todavía. Recuerda usar nombres en minúscula y plural en la base de datos, esa es una convención sana de naming [04:30].
Una vez que un módulo empieza a crecer, conviene reorganizar:
- Crea una carpeta
controllers/ y mueve ahí los controladores del módulo.
- Crea una carpeta
services/ y mueve los servicios correspondientes.
- Ajusta los imports rotos por el cambio de ubicación.
- Verifica que el archivo
module.ts apunte a las nuevas rutas.
Después de mover archivos, varios imports se rompen porque las rutas cambiaron. Es normal: revisa entidades, DTOs y el módulo principal hasta que todo compile de nuevo.
Qué diferencia hay entre crear desde el servicio y crear desde su propio controller
Con profile creabas el perfil desde el método create del servicio de usuario, porque estaban anidados. Con categories es distinto: las categorías se crean por separado, los posts por separado, y luego se relacionan. Por eso category necesita su propio controller, su propio service y sus propios DTOs.
Cómo generar el CRUD de una entidad con Cursor y un buen prompt
En lugar de usar el NG Generator, puedes apoyarte en IA para autogenerar todo el CRUD a partir de una entidad bien construida. La clave está en el contexto que le das al modelo.
El prompt usa referencias con @ para apuntar a archivos concretos: el service de posts como ejemplo de servicio, el controller de posts como ejemplo de controller, y el posts.module.ts como destino. Además, le pasas la estructura de carpetas usando el comando tree -L 2 desde la terminal, que genera un mapa visual de los archivos del módulo [09:45].
¿Cómo le doy contexto de estructura a una IA para generar código? Usa tree -L 2 en la terminal para obtener el árbol de archivos, cópialo dentro del prompt y referencia los archivos con @ en Cursor. Así la IA respeta tus convenciones.
Ejecutas el prompt desde el archivo category.entity.ts para que la entidad sea el punto de entrada. La IA, en modo agent, crea automáticamente:
CreateCategoryDto y UpdateCategoryDto dentro de la carpeta de DTOs.
- El service con métodos asíncronos para create, findAll, findOne, update y remove.
- El controller con los endpoints expuestos siguiendo el patrón POST, GET, PUT y DELETE.
- El registro de ambos controladores y servicios en
posts.module.ts.
Lo interesante es que la IA detecta detalles que no le diste explícitamente. Por ejemplo, agrega @MaxLength(255) al DTO porque la entidad declara el campo name con un límite de 255 caracteres. También aplica el patrón partial type para el UpdateCategoryDto, replicando la convención que ya existía en el módulo.
Qué revisar siempre en el código generado por IA
No todo sale idéntico al estilo del proyecto. En el service generado, el método findOne no se reutilizó dentro de remove, así que si eliminas una categoría inexistente, no recibes alerta. Es un buen punto para refactorizar y mantener consistencia con el patrón merge y la reutilización de findOne que sí aplicaron en update.
Cómo probar el CRUD de categorías en Postman
Duplicar la carpeta de posts en Postman y renombrarla a categories te ahorra tiempo, ya que solo cambia el endpoint base. Las pruebas confirman que el CRUD funciona:
- GET /categories: devuelve lista vacía al inicio.
- GET /categories/:id con ID inexistente: responde con error claro indicando que la categoría no existe.
- POST /categories: si envías
title en lugar de name, el DTO rechaza la propiedad y exige name no vacío y de máximo 255 caracteres.
- PUT /categories/:id: actualiza el nombre y devuelve la categoría con la información nueva.
- DELETE /categories/:id: elimina el registro, aunque sin alerta si el ID no existe.
Con esto, posts y categories conviven en el mismo módulo, comparten contexto y quedan listos para la relación many-to-many que viene después. ¿Tú prefieres autogenerar con IA o seguir usando el Resource Generator de NestJS? Cuéntame en los comentarios.