{"id":31952384,"url":"https://github.com/alcandev/book-inventory-react-vite-nest-postgres","last_synced_at":"2025-12-30T19:19:37.264Z","repository":{"id":311099574,"uuid":"1042328388","full_name":"AlcanDev/book-inventory-react-vite-nest-postgres","owner":"AlcanDev","description":"Full-stack book inventory management system using React + Vite (frontend) and NestJS + PostgreSQL (backend). Features JWT auth, advanced filtering (incl. availability), pagination, CSV export, auditing, Swagger docs, image upload with Multer (local storage), and Docker Compose deployment.","archived":false,"fork":false,"pushed_at":"2025-09-12T15:50:41.000Z","size":337,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-12T18:24:43.241Z","etag":null,"topics":["auditing","csv-export","docker","docker-compose","file-upload","filtering","jest","jwt","multer","nestjs","nginx","openapi","pagination","postgresql","react","sequelize","spa","swagger","typescript","vite"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlcanDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-21T20:56:20.000Z","updated_at":"2025-09-12T16:04:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"52112904-138b-46aa-a3d4-14c83e10ab04","html_url":"https://github.com/AlcanDev/book-inventory-react-vite-nest-postgres","commit_stats":null,"previous_names":["alcandev/cmpc-libros-fullstack"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AlcanDev/book-inventory-react-vite-nest-postgres","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlcanDev%2Fbook-inventory-react-vite-nest-postgres","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlcanDev%2Fbook-inventory-react-vite-nest-postgres/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlcanDev%2Fbook-inventory-react-vite-nest-postgres/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlcanDev%2Fbook-inventory-react-vite-nest-postgres/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlcanDev","download_url":"https://codeload.github.com/AlcanDev/book-inventory-react-vite-nest-postgres/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlcanDev%2Fbook-inventory-react-vite-nest-postgres/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018714,"owners_count":26086605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditing","csv-export","docker","docker-compose","file-upload","filtering","jest","jwt","multer","nestjs","nginx","openapi","pagination","postgresql","react","sequelize","spa","swagger","typescript","vite"],"created_at":"2025-10-14T13:14:01.465Z","updated_at":"2025-10-14T13:14:05.809Z","avatar_url":"https://github.com/AlcanDev.png","language":"TypeScript","readme":"# CMPC-libros – Sistema de Gestión de Libros Fullstack\n\n![web capture](./docs/web.png)\n_Captura principal de la aplicación mostrando la interfaz de gestión de libros_\n\n## 🚀 Puesta en marcha rápida\n\n1. **Configurar variables de entorno** (automático con valores por defecto):\n\n   ```bash\n   # El archivo .env del backend se crea automáticamente con valores seguros\n   # No requiere configuración manual\n   ```\n\n2. **Levantar todo el stack con un solo comando**:\n\n   ```bash\n   docker compose up --build\n   ```\n\n3. **Acceder a los servicios**:\n\n   - 🌐 **Frontend**: http://localhost:8080\n   - 📚 **Backend/API**: http://localhost:3000/api\n   - 📖 **Swagger Docs**: http://localhost:3000/api/docs\n   - ❤️ **Health Check**: http://localhost:3000/api/health\n\n4. **Credenciales de prueba**:\n\n   - **Email**: `admin@cmpc.local`\n   - **Password**: `admin1234`\n\n5. **Para apagar**:\n\n   ```bash\n   docker compose down\n   ```\n\n6. **Para limpiar volúmenes** (destructivo - elimina imágenes y datos):\n   ```bash\n   docker compose down -v\n   ```\n\n## ✨ Características implementadas\n\n### 🔐 **Autenticación y Seguridad**\n\n- ✅ JWT con protección de rutas\n- ✅ Middleware de autenticación\n- ✅ CORS configurado\n- ✅ Validación de datos con pipes\n\n### 📚 **Gestión de Libros**\n\n- ✅ CRUD completo (Create, Read, Update, Delete)\n- ✅ Soft-delete con auditoría\n- ✅ Filtros avanzados (título, autor, editorial, género, disponibilidad)\n- ✅ Búsqueda con debounce (300ms)\n- ✅ Paginación server-side\n- ✅ Ordenamiento multi-campo\n- ✅ Exportación CSV manteniendo filtros\n- ✅ **Subida de imágenes con Multer** (almacenamiento local persistente)\n- ✅ **Visualización de imágenes** en tabla, detalles y formularios\n\n### 🎨 **Frontend Moderno**\n\n- ✅ React 18 + TypeScript + Vite\n- ✅ UI responsive y moderna\n- ✅ Tipado estricto\n- ✅ Contexto de autenticación\n- ✅ Manejo de estados con hooks\n- ✅ Formularios con validación\n\n### 🏗️ **Backend Robusto**\n\n- ✅ NestJS + TypeScript\n- ✅ PostgreSQL + Sequelize ORM\n- ✅ Interceptors de logging y transformación\n- ✅ Filtros globales de excepciones\n- ✅ Swagger/OpenAPI documentación\n- ✅ Health checks\n\n### 🧪 **Testing y Calidad**\n\n- ✅ **Cobertura de tests: 91.61%** (objetivo ≥80%)\n- ✅ Tests unitarios con Jest\n- ✅ Tests de integración\n- ✅ Linting y formateo automático\n\n### 🐳 **DevOps y Deployment**\n\n- ✅ Docker Compose orquestación\n- ✅ Multi-stage builds optimizados\n- ✅ Health checks en todos los servicios\n- ✅ Variables de entorno configuradas\n- ✅ Nginx para servir frontend\n- ✅ Single command deployment\n- ✅ **Volúmenes persistentes** para imágenes y base de datos\n\n## 🛠️ **Stack Tecnológico**\n\n**Frontend**: React 18 + TypeScript + Vite + CSS Modules  \n**Backend**: NestJS + TypeScript + PostgreSQL + Sequelize  \n**Auth**: JWT + bcrypt  \n**Docs**: Swagger/OpenAPI  \n**DevOps**: Docker + Docker Compose + Nginx  \n**Testing**: Jest + Supertest\n\n---\n\n## Objetivo\n\nDigitalizar procesos de inventario para una tienda de libros (CMPC-libros), con:\n\n- CRUD de libros (título, autor, editorial, precio, disponibilidad, género, imagen)\n- Autenticación JWT\n- Filtros avanzados, orden multi-campo, paginación server-side, búsqueda con debounce\n- Exportación CSV\n- Soft-delete, logging/auditoría\n- Tests (≥ 80% cobertura)\n- Despliegue local con Docker\n\n---\n\n## Estructura\n\n```text\n.\n├─ cmpc-libros-frontend/   # React + Vite (Nginx)\n├─ cmpc-libros-backend/    # NestJS + Sequelize\n└─ docker-compose.yml      # Orquestación local\n```\n\n---\n\n## Requisitos\n\n- Docker 20+ y Docker Compose 2+\n- Puertos libres: `3000` (API), `8080` (Web), `5432` (DB)\n\n---\n\n## Variables de entorno\n\n### Backend (`cmpc-libros-backend/.env`)\n\n```env\nPORT=3000\nNODE_ENV=development\n\n# JWT\nJWT_SECRET=supersecretchangeme-pon-uno-largo\nJWT_EXPIRES_IN=1d\n\n# DB\nDB_HOST=postgres\nDB_PORT=5432\nDB_NAME=cmpc_libros\nDB_USER=cmpc\nDB_PASS=cmpc_password\n\n# Logging\nLOG_LEVEL=debug\n\n# CORS (coma-separado si hay múltiples orígenes)\nCORS_ORIGINS=http://localhost:8080\n```\n\n### Frontend (ARG en build)\n\n- `VITE_API_BASE_URL` (por defecto `http://localhost:3000/api`)\n\n---\n\n## Puesta en marcha (Docker)\n\n1. Crear `.env` del backend (puedes copiar desde `.env.example` y ajustar valores):\n\n   ```bash\n   cp cmpc-libros-backend/.env.example cmpc-libros-backend/.env\n   ```\n\n2. Levantar todo el stack:\n   ```bash\n   docker compose up --build\n   ```\n\n### Servicios\n\n- **DB**: `postgres:16-alpine`\n- **migration**: corre `pgcrypto`, migrations y seeds una sola vez\n- **backend**: NestJS en `http://localhost:3000/api` (Swagger: `/api/docs`)\n- **frontend**: SPA en `http://localhost:8080`\n\nPara apagar:\n\n```bash\ndocker compose down\n```\n\nPara limpiar volúmenes (destructivo):\n\n```bash\ndocker compose down -v\n```\n\n---\n\n## API (Swagger)\n\n- Documentación Swagger: `http://localhost:3000/api/docs`\n- Autorización: **Bearer Token (JWT)**\n\n### Endpoints destacados (resumen)\n\n- `POST /api/auth/login` – login JWT\n- `GET /api/auth/me` – perfil usuario autenticado\n- `GET /api/books` – listado con filtros/orden/paginación (query params)\n- `GET /api/books/:id` – detalle de libro específico\n- `POST /api/books` – alta\n- `PATCH /api/books/:id` – edición\n- `DELETE /api/books/:id` – soft delete\n- `POST /api/upload/book-image` – subida de imagen (multipart/form-data)\n- `GET /api/books/export` – CSV con filtros\n- `GET /api/health` – health check\n\n---\n\n## Modelo de datos (relacional)\n\n- **users**(id UUID, email, passwordHash, role)\n- **books**(id UUID, title, author, publisher, price, available, genre, imageUrl, deletedAt)\n- **audit_logs**(id UUID, userId, action, entity, entityId, payload, createdAt)\n\n**Índices sugeridos**\n\n- `books(title)`, `books(author)`, `books(publisher)`, `books(genre)`, compuestos por filtros frecuentes.\n\n\u003e `gen_random_uuid()` requiere la extensión **pgcrypto** (migration incluida).\n\n---\n\n## Decisiones de diseño\n\n- **NestJS modular** (principios SOLID): módulos `auth`, `users`, `books`, `audit`.\n- **Sequelize + transactions** para operaciones críticas.\n- **Interceptors**: logging y transformación estándar `{ success, data }`.\n- **Filtros**: manejo centralizado de errores.\n- **Soft delete**: `deletedAt` / `paranoid` en modelos.\n\n---\n\n## Frontend (React + Vite)\n\n- Ruteo protegido, contexto de auth.\n- Búsqueda con debounce, filtros y orden en servidor.\n- Subida de imagen por URL (`imageUrl`) – extensible a S3 o storage local.\n- Tabla paginada; formulario con validaciones reactivas.\n\n---\n\n## Tests\n\n- **Backend**: unit tests (servicios/controladores/estrategias JWT) con Jest.  \n  Meta ≥ 80% cobertura (algunos archivos originales estaban truncados y deben completarse).\n\n---\n\n## Despliegue productivo\n\n- Usar **variables seguras** (secrets) y `NODE_ENV=production`.\n- **Pinned images** / build reproducible.\n- Ajustar `CORS_ORIGINS` y `VITE_API_BASE_URL`.\n- Ejecutar **migraciones** en job CI/CD previo a `backend`.\n- **Logs** a STDOUT (integrable con ELK/CloudWatch).\n\n---\n\n## 🎯 **Funcionalidades Completadas**\n\n### ✅ **Sistema de Imágenes**\n\n- **Subida**: Endpoint `/api/upload/book-image` con Multer\n- **Almacenamiento**: Local con volumen Docker persistente\n- **Validación**: Tipos (JPEG, PNG, WebP), tamaño máximo 5MB\n- **Visualización**: Miniaturas en tabla, imagen completa en detalles y edición\n- **URLs**: Servidas estáticamente desde `/uploads/books/`\n\n### ✅ **Filtros Avanzados**\n\n- **Búsqueda**: Texto libre en título, autor, editorial\n- **Filtros específicos**: Género, editorial, autor, disponibilidad\n- **Funcionalidad**: Todos los filtros funcionan correctamente\n- **UI**: Select de disponibilidad con opciones \"Todos\", \"Disponible\", \"No disponible\"\n\n### ✅ **Persistencia de Datos**\n\n- **Base de datos**: Volumen `pgdata` para PostgreSQL\n- **Imágenes**: Volumen `uploads` para archivos subidos\n- **Beneficio**: Los datos persisten entre reinicios de contenedores\n\n---\n\n## Cómo probar ahora mismo\n\n1. Crea `cmpc-libros-backend/.env` (ver sección de variables).\n2. Ejecuta:\n\n```bash\ndocker compose up --build\n```\n\n- Frontend: http://localhost:8080\n- Backend/API: http://localhost:3000/api\n- Swagger Docs: http://localhost:3000/api/docs\n- Health: http://localhost:3000/api/health\n\n**Usuario seed (si seeder activo):** `admin@cmpc.local` / `admin1234`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falcandev%2Fbook-inventory-react-vite-nest-postgres","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falcandev%2Fbook-inventory-react-vite-nest-postgres","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falcandev%2Fbook-inventory-react-vite-nest-postgres/lists"}