Backend moderno construido con NestJS y TypeScript que integra persistencia en PostgreSQL, cache con Redis, colas de trabajo, seguridad y generación de resúmenes con IA.
- Node.js recomandado v24.13.0 (LTS)
- npm o yarn
- Docker (para ejecutar Redis)
- Cuenta en Supabase (PostgreSQL gratuito)
- API Key de Google Gemini (para IA)
git clone https://github.com/npminit-dev/contactship-mini
cd contactship-mininpm installCrear un archivo .env en la raíz del proyecto:
# Servidor
PORT=3000
# Seguridad
API_KEY=your-secret-api-key-here
# Base de datos (Supabase PostgreSQL)
DB_HOST=xxxx.supabase.co
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_db_password
DB_NAME=postgres
# Cache (Redis)
REDIS_HOST=localhost
REDIS_PORT=6379
# IA (Google Gemini)
GEMINI_API_KEY=your_gemini_api_keydocker run -d --name redis -p 6379:6379 redis:latestnpm run start:dev✅ La API estará disponible en: http://localhost:3000
Todos los endpoints requieren el header:
x-api-key: your-secret-api-key-here
Incluir este header en todas las solicitudes HTTP.
POST /create-lead
x-api-key: your-api-key
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phone": "+1234567890"
}Respuesta (201):
{
"id": "uuid",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phone": "+1234567890",
"source": "manual",
"summary": null,
"nextAction": null,
"createdAt": "2025-01-15T10:30:00.000Z"
}GET /leads
x-api-key: your-api-keyRespuesta (200): Array de leads (ordenados por fecha descendente)
GET /leads/{id}
x-api-key: your-api-keyNota: Este endpoint utiliza cache Redis con TTL de 1 minuto.
Respuesta (200): Lead individual
POST /leads/{id}/summarize
x-api-key: your-api-keyParámetros opcionales:
force=true- Regenerar resumen aunque ya exista
Respuesta (200):
{
"status": "queued"
}Una vez procesado (asincrónico):
{
"summary": "Professional summary of the lead...",
"next_action": "Schedule a follow-up call.",
"status": "already_generated"
}El sistema sincroniza automáticamente leads desde Random User Generator cada 5 segundos.
Características:
- Importa 10 nuevos registros por ejecución
- Evita duplicados validando emails únicos en la base de datos
- Logs detallados de leads agregados vs. duplicados
| Componente | Tecnología |
|---|---|
| Framework | NestJS v11 + TypeScript |
| Base de datos | PostgreSQL (Supabase) |
| ORM | TypeORM |
| Cache | Redis + cache-manager |
| Colas | Bull (Redis-backed) |
| IA | Google Gemini API |
| Scheduler | @nestjs/schedule (CRON) |
| Validación | class-validator + DTOs |
- Entidad
Leadcon UUIDs como PK - Campos: nombre, email (único), teléfono, source (manual/external), summary, nextAction
- Sincronización automática de esquema (solo desarrollo)
- Redis con TTL de 1 minuto para detalle de leads
- Invalidación automática tras procesamiento de resúmenes
- Bull queue para procesamiento asincrónico de resúmenes
- Reintentos automáticos: 3 intentos con backoff de 5 segundos
- No bloquea respuestas HTTP
- Integración con Google Gemini 3-Flash
- Formato estricto:
{ summary: string, next_action: string } - Validaciones en el prompt para evitar hallucinations
- API Key en header
x-api-key - Guard global en todos los endpoints
- Validación de DTOs con whitelist activada
- CRON job cada minuto
- Deduplicación por email
- Logging de operaciones (added/skipped)
- Logger contextualizado en servicios críticos
- Excepciones HTTP específicas (NotFoundException, ConflictException, etc.)
- Manejo de errores en jobs con reintentos
src/
├── main.ts # Entry point
├── app.module.ts # Módulo raíz
├── app.controller.ts # Controller principal
├── app.service.ts # Service principal
├── types.ts # Tipos compartidos
├── common/
│ └── guards/
│ └── api-key.guard.ts # Validación de API Key
├── leads/
│ ├── lead.entity.ts # Entidad Lead (TypeORM)
│ ├── leads.service.ts # Lógica de leads
│ ├── leads.controller.ts # Endpoints HTTP
│ ├── leads.module.ts # Módulo de leads
│ ├── dto/
│ │ └── create-lead.dto.ts # DTO con validaciones
│ ├── ai/
│ │ └── ai.service.ts # Servicio de IA (Gemini)
│ └── jobs/
│ └── summarize-lead.processor.ts # Processor para Bull queue
└── sync/
├── sync.service.ts # Servicio de sincronización
└── sync.module.ts # Módulo de sync
Todas las variables se cargan desde .env usando @nestjs/config:
| Variable | Descripción | Ejemplo |
|---|---|---|
PORT |
Puerto del servidor | 3000 |
API_KEY |
Clave para autenticación | abc123xyz |
DB_HOST |
Host de PostgreSQL | proyecto.supabase.co |
DB_PORT |
Puerto de DB | 5432 |
DB_USER |
Usuario de DB | postgres |
DB_PASSWORD |
Contraseña de DB | password |
DB_NAME |
Nombre de DB | postgres |
REDIS_HOST |
Host de Redis | localhost |
REDIS_PORT |
Puerto de Redis | 6379 |
GEMINI_API_KEY |
API Key de Google Gemini | sk-... |
# Tests unitarios
npm run test
# Tests con coverage
npm run test:cov
# Tests E2E
npm run test:e2e
# Watch mode
npm run test:watchnpm run start # Producción
npm run start:dev # Desarrollo con watch
npm run start:debug # Debug mode
npm run start:prod # Ejecutar dist compilado
npm run build # Compilar TypeScript
npm run lint # Linting con ESLint
npm run format # Formatear código con Prettier- synchronize: true solo está habilitado en desarrollo
- Las migraciones manuales serían recomendables en producción
- El email está configurado como único para evitar duplicados
- TTL de 1 minuto balancead entre freshness y performance
- Se invalida automáticamente tras procesar resúmenes
- Implementado con cache-manager + redis-store
- Bull utiliza Redis como broker
- Estrategia de reintentos: 3 intentos con backoff exponencial de 5 segundos
- Logging detallado de cada procesamiento
- Usa Google Gemini 3-Flash (rápido y económico)
- Prompt diseñado para evitar información inventada
- Validación estricta de formato JSON en respuestas
- Ejecuta cada minuto (configurable en sync.service.ts)
- Descarga 10 registros por ejecución
- Deduplicación case-insensitive de emails
# Verifica que Redis esté corriendo
docker ps | grep redis
# Si no está, inicia Redis
docker run -d --name redis -p 6379:6379 redis:latest- Verifica que el header
x-api-keyesté presente en la solicitud - Verifica que coincida con el valor en
.env
- El email ya existe en la base de datos
- Los emails son únicos por diseño
- Asegúrate de que las credenciales de Supabase en
.envsean correctas - Verifica conectividad a internet
- Revisa los logs de la consola
UNLICENSED
- API Key en lugar de JWT - Simplicidad para la prueba, sin necesidad de renovación de tokens
- Queue asincrónica para IA - Evita timeouts en resúmenes largos
- Cache con TTL corto - Balance entre datos frescos y reducción de carga
- Deduplicación en BD - Constraint único + validación en servicio
- CRON cada minuto - Frecuencia alta para demostración; recomendable ajustar en producción
- Gemini 3-Flash - Modelo rápido y económico para este caso de uso
Desarrollado como prueba técnica de NestJS + TypeScript.