Backend CRM
API REST + WebSockets construida con NestJS 11 para un sistema CRM multi-tenant con mensajería en tiempo real.
Stack
| Tecnología | Versión | Uso |
|---|---|---|
| NestJS | 11.0.1 | Framework principal |
| MongoDB + Mongoose | 9.4.1 | Base de datos |
| Socket.io | — | WebSockets (módulo chat) |
| Passport + JWT | — | Autenticación |
| @nestjs/swagger | — | Documentación OpenAPI |
| Bull / BullMQ | — | Colas de trabajo |
| Redis | — | Caché / sesiones |
| AWS SDK v3 (S3) | — | Almacenamiento de archivos (MinIO compatible) |
| class-validator | — | Validación de DTOs |
| Jest | — | Tests unitarios e integración |
Arquitectura general
src/
├── main.ts # Bootstrap + configuración global
├── app.module.ts # Módulo raíz
├── bootstrap/ # Utilidades de arranque
├── config/ # Variables de entorno tipadas
└── app/
├── core/ # Infraestructura transversal
│ ├── constants/
│ ├── decorators/
│ ├── filters/
│ ├── guards/
│ ├── interceptors/
│ ├── interfaces/
│ ├── storage/
│ ├── translate/
│ └── utils/
└── modules/ # Módulos de negocio
├── auth/
├── user/
├── tenant/
├── api-key/
├── module/
├── role/
├── permission/
├── role-permission/
├── message/
├── contact/
├── ticket/
├── file/
├── label/
├── quick-response/
└── chat/
Patrón de módulo estándar
Todos los módulos de negocio siguen el mismo patrón:
module/
├── module.module.ts # Contenedor DI
├── models/model.model.ts # Schema Mongoose
├── repositories/ # Capa de acceso a datos
├── services/ # Lógica de negocio + tests
├── controllers/ # Endpoints HTTP/WS + tests
├── dtos/ # Validación de entrada
├── domain/ # Objetos de dominio
└── interfaces/ # Tipos TypeScript
Formato de respuesta global
Todas las respuestas pasan por el ResponseInterceptor:
// POST / PATCH / DELETE
{
"statusCode": 200,
"status": "success",
"message": "OK",
"data": { ... }
}
// GET (listado)
{
"statusCode": 200,
"status": "success",
"message": "OK",
"data": {
"results": [],
"meta": { "total": 0, "page": 1, "limit": 10 }
}
}
Multi-tenancy
Cada recurso está asociado a un tenantId. Los clientes externos se autentican con API Keys que tienen fecha de expiración y un whitelist de dominios.