API de lista de compras desarrollada con NestJS, GraphQL, TypeORM y PostgreSQL
Una aplicación moderna de lista de compras que permite a los usuarios gestionar sus compras de manera eficiente. Desarrollada con tecnologías de vanguardia como NestJS para el backend, GraphQL para las consultas flexibles, y PostgreSQL como base de datos.
- ✅ Registro y autenticación de usuarios con JWT
- ✅ Sistema de roles (Usuario, Admin, SuperAdmin)
- ✅ Encriptación segura de contraseñas con bcrypt
- ✅ Validación de tokens y protección de rutas
- ✅ Crear, leer, actualizar y eliminar items
- ✅ Especificar unidades de medida para cada item
- ✅ Búsqueda y paginación de items
- ✅ Asociación de items con usuarios
- ✅ Crear listas de compras personalizadas
- ✅ Agregar items a las listas con cantidades específicas
- ✅ Marcar items como completados
- ✅ Búsqueda y filtrado de listas
- ✅ API GraphQL con schema automático
- ✅ Base de datos PostgreSQL con TypeORM
- ✅ Validación de datos con class-validator
- ✅ Configuración de entorno con validaciones
- ✅ Sistema de seeds para datos de prueba
- ✅ Documentación automática con Swagger
src/
├── 🔐 auth/ # Autenticación y autorización
├── 🛠️ common/ # Utilidades compartidas
├── ⚙️ config/ # Configuraciones
├── 🗄️ database/ # Configuración de base de datos
├── 🌐 envs/ # Variables de entorno
├── 📊 graphql/ # Configuración GraphQL
├── 📦 modules/ # Módulos de negocio
│ ├── 👤 users/ # Gestión de usuarios
│ ├── 🛍️ items/ # Gestión de items
│ ├── 📝 lists/ # Gestión de listas
│ └── 🔗 item-lists/ # Relación items-listas
└── 🌱 seed/ # Datos de prueba
- id: UUID
- fullName: string
- email: string (único)
- password: string (encriptado)
- roles: UserRole[]
- isActive: boolean
- createdAt: Date
- updatedAt: Date- id: UUID
- name: string
- description?: string
- unitOfMeasurement: string
- userId: UUID (FK)- id: UUID
- name: string
- userId: UUID (FK)- id: UUID
- listId: UUID (FK)
- itemId: UUID (FK)
- quantity: number
- isCompleted: boolean| Tecnología | Versión | Propósito |
|---|---|---|
| NestJS | ^11.0.1 | Framework backend modular |
| GraphQL | ^16.11.0 | API query language flexible |
| TypeORM | ^0.3.26 | ORM para PostgreSQL |
| PostgreSQL | - | Base de datos relacional |
| JWT | ^11.0.0 | Autenticación stateless |
| bcrypt | ^6.0.0 | Encriptación de contraseñas |
| class-validator | ^0.14.2 | Validación de datos |
| Joi | ^18.0.1 | Validación de configuración |
- Node.js (≥ 18.x)
- PostgreSQL (≥ 13.x)
- npm o yarn
- Clona el repositorio
git clone <repository-url>
cd anylist_nest_graphql- Instala las dependencias
npm install- Configura las variables de entorno
# Copia el archivo de ejemplo
cp .env.example .env
# Edita el archivo .env con tu configuración
ENVIRONMENT=development
PORT=3000
JWT_SECRET=tu_super_secreto_jwt
DB_HOST=localhost
DB_PORT=5432
DB_USER=tu_usuario
DB_PASSWORD=tu_contraseña
DB_NAME=anylist_db- Configura la base de datos
# Crea la base de datos en PostgreSQL
createdb anylist_db# Iniciar en modo desarrollo (recarga automática)
npm run start:dev
# Iniciar en modo debug
npm run start:debug# Compilar el proyecto
npm run build
# Ejecutar en producción
npm run start:prod# Ejecutar seeds desde GraphQL Playground
mutation {
executeSeed
}# Tests unitarios
npm run test
# Tests en modo watch
npm run test:watch
# Tests e2e
npm run test:e2e
# Cobertura de tests
npm run test:covUna vez iniciado el servidor, puedes acceder a:
- GraphQL Playground:
http://localhost:3000/graphql - Swagger Documentation:
http://localhost:3000/api/docs
La aplicación incluye endpoints REST para autenticación además de GraphQL:
POST /api/auth/singup
Content-Type: application/json
{
"fullName": "Juan Perez",
"email": "juan@example.com",
"password": "Password123"
}Respuesta:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "uuid-del-usuario",
"fullName": "Juan Perez",
"email": "juan@example.com",
"roles": ["user"],
"isActive": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}POST /api/auth/login
Content-Type: application/json
{
"email": "juan@example.com",
"password": "Password123"
}Respuesta:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "uuid-del-usuario",
"fullName": "Juan Perez",
"email": "juan@example.com",
"roles": ["user"],
"isActive": true
}
}📌 Nota: Para consultas GraphQL que requieren autenticación, incluye el token JWT en el header:
Authorization: Bearer tu_token_jwt_aqui
# Crear usuario (Solo Admin)
mutation {
createUser(createUserInput: {
fullName: "Juan Perez"
email: "juan@example.com"
password: "Password123"
}) {
id
fullName
email
roles
}
}
# Obtener todos los usuarios (Solo Admin)
query {
users {
id
fullName
email
roles
isActive
}
}# Crear un item
mutation {
createItem(createItemInput: {
name: "Leche"
unitOfMeasurement: "litros"
description: "Leche entera"
}) {
id
name
unitOfMeasurement
}
}
# Crear una lista
mutation {
createList(createListInput: {
name: "Lista del Supermercado"
}) {
id
name
user {
fullName
}
}
}
# Agregar item a lista
mutation {
createItemList(createItemListInput: {
listId: "uuid-de-lista"
itemId: "uuid-de-item"
quantity: 2
isCompleted: false
}) {
id
quantity
isCompleted
item {
name
}
list {
name
}
}
}La aplicación implementa un sistema híbrido que combina:
- 🌐 Endpoints REST: Para registro e inicio de sesión (
/api/auth/*) - 📊 GraphQL: Para todas las demás operaciones CRUD
-
Registro/Login → Usar endpoints REST para obtener JWT
-
Operaciones → Usar GraphQL con el token JWT en headers
-
Headers requeridos:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json
| Rol | Permisos |
|---|---|
| User | Ver y gestionar sus propios items y listas |
| Admin | Gestionar usuarios + permisos de User |
| SuperAdmin | Todos los permisos del sistema |
- 🌐 Público: Consultas sin autenticación
- 🔒 Usuario Autenticado: Requiere JWT válido
- 🔑 Solo Administradores: Requiere rol Admin/SuperAdmin
| Script | Descripción |
|---|---|
npm run start |
Inicia la aplicación |
npm run start:dev |
Modo desarrollo con recarga automática |
npm run start:debug |
Modo debug |
npm run start:prod |
Modo producción |
npm run build |
Compila el proyecto |
npm run lint |
Ejecuta ESLint |
npm run format |
Formatea código con Prettier |
npm run test |
Ejecuta tests unitarios |
npm run test:e2e |
Ejecuta tests end-to-end |
Error de conexión a base de datos
# Verificar que PostgreSQL esté ejecutándose
pg_isready
# Verificar variables de entorno
echo $DB_HOST $DB_PORT $DB_USER $DB_NAMEError JWT_SECRET
# Asegurar que JWT_SECRET esté configurado en .env
JWT_SECRET=tu_super_secreto_jwt_muy_largo_y_seguroError de puerto en uso
# Cambiar puerto en .env o terminar proceso
PORT=3001
# o
lsof -ti:3000 | xargs kill- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
Este proyecto está bajo la Licencia UNLICENSED - ver el archivo LICENSE para más detalles.
- Andrés Felipe Perdomo - Desarrollo inicial - TuGitHub
- NestJS - Framework Node.js progresivo
- GraphQL - Lenguaje de consulta para APIs
- TypeORM - ORM para TypeScript y JavaScript
- PostgreSQL - Sistema de base de datos relacional