Files
quasar/plans/gestor-coleccion-plan.md

238 lines
15 KiB
Markdown

## Plan: Gestor de biblioteca de videojuegos y ROMs (Quasar)
Aplicación web self-hosted para gestionar una biblioteca de ROMs y videojuegos físicos/digitales. Permite escanear directorios de ROMs, enriquecer metadatos vía APIs públicas (IGDB, RAWG, TheGamesDB), y registrar manualmente juegos físicos/digitales con precio, condición y notas. Stack: TypeScript + React + Vite + shadcn/ui (frontend), Node.js + Fastify + TypeScript + Prisma + SQLite (backend).
**Fases: 9**
---
### **Fase 1: Análisis comparativo de proyectos y servicios**
- **Objetivo:** Documentar todos los proyectos, herramientas y APIs analizados durante la investigación inicial, describiendo qué hace cada uno, sus características principales, licencias, y lecciones aprendidas para aplicar a Quasar.
- **Archivos/Funciones a crear/modificar:**
- `docs/competitive-analysis.md` — análisis detallado de proyectos (Playnite, LaunchBox, OpenEmu, EmulationStation, RetroArch, ROMVault, etc.)
- `docs/apis-comparison.md` — comparativa de APIs (IGDB, RAWG, TheGamesDB, Screenscraper, MobyGames, PriceCharting, ITAD, eBay)
- `docs/lessons-learned.md` — patrones y mejores prácticas extraídas del análisis
- **Pasos:**
1. Crear documentos con información estructurada de la investigación inicial
2. Incluir tablas comparativas, enlaces, y conclusiones
3. Documentar patrones útiles y mejores prácticas aplicables a Quasar
---
### **Fase 2: Requisitos y diseño técnico**
- **Objetivo:** Definir arquitectura (monorepo o separado), estructura de carpetas, stack definitivo (Fastify + Prisma, SQLite), APIs a integrar (IGDB, RAWG, TheGamesDB), y documento de modelo de datos inicial.
- **Archivos/Funciones a crear/modificar:**
- `docs/requirements.md` — requisitos funcionales y no funcionales
- `docs/architecture.md` — decisiones arquitectónicas (monorepo vs multi-repo, API REST structure)
- `docs/api-integration.md` — descripción de APIs públicas a usar, endpoints, rate limits, autenticación
- `docs/data-model.md` — entidades (Game, RomFile, Platform, Purchase, Artwork)
- **Pasos:**
1. Crear documentos `docs/requirements.md`, `docs/architecture.md`, `docs/api-integration.md`, `docs/data-model.md` con contenido inicial
2. Definir estructura de carpetas y convenciones de código
3. Documentar decisiones técnicas y justificaciones
---
### **Fase 3: Backend base y modelo de datos**
- **Objetivo:** Configurar backend (Fastify + TypeScript + Prisma + SQLite), definir schema de BD (Game, RomFile, Platform, Purchase, Artwork), migraciones y seeders básicos.
- **Archivos/Funciones a crear/modificar:**
- `backend/package.json` — dependencias (fastify, prisma, @fastify/cors, dotenv, etc.)
- `backend/tsconfig.json` — configuración TypeScript backend
- `backend/src/index.ts` — servidor Fastify inicial
- `backend/prisma/schema.prisma` — modelos (Game, RomFile, Platform, Purchase, Artwork)
- `backend/prisma/migrations/` — migraciones Prisma
- `backend/src/routes/healthcheck.ts` — endpoint `/api/health`
- **Tests a escribir:**
- `backend/tests/server.spec.ts` — test del servidor (inicia y responde en `/api/health`)
- `backend/tests/models/game.spec.ts` — validaciones del modelo Game (TDD)
- `backend/tests/models/romFile.spec.ts` — validaciones del modelo RomFile
- **Pasos:**
1. Escribir tests que fallen (healthcheck endpoint, crear modelo Game y validar)
2. Configurar Fastify + Prisma, definir schema, ejecutar migración
3. Implementar endpoint `/api/health`
4. Ejecutar tests y verificar que pasan
---
### **Fase 4: Importadores y gestión de ROMs**
- **Objetivo:** Implementar servicio para escanear directorios locales, calcular checksums (CRC32/MD5/SHA1), detectar formatos (ZIP/7z/CHD), y almacenar en BD. Incluir soporte básico para DAT verification (No-Intro/Redump).
- **Archivos/Funciones a crear/modificar:**
- `backend/src/services/fsScanner.ts` — función `scanDirectory(path: string)`
- `backend/src/services/checksumService.ts` — funciones `calculateCRC32()`, `calculateMD5()`, `calculateSHA1()`
- `backend/src/services/datVerifier.ts` — función `verifyAgainstDAT(romFiles, datPath)`
- `backend/src/routes/import.ts` — endpoint `POST /api/import/scan` (body: {path})
- `backend/src/utils/archiveReader.ts` — leer contenido de ZIP/7z/CHD
- **Tests a escribir:**
- `backend/tests/services/fsScanner.spec.ts` — casos: carpeta vacía, carpeta con ROMs, carpeta con subdirectorios
- `backend/tests/services/checksumService.spec.ts` — calcular checksum de archivo fixture
- `backend/tests/services/datVerifier.spec.ts` — verificar ROM válido/inválido contra DAT fixture
- `backend/tests/routes/import.spec.ts` — test E2E de endpoint `/api/import/scan`
- **Pasos:**
1. Crear fixtures (ROMs de prueba, DAT de prueba)
2. Escribir tests que fallen (escaneo de carpeta, checksum, DAT verification)
3. Implementar `fsScanner`, `checksumService`, `datVerifier` mínimos
4. Implementar endpoint `/api/import/scan`
5. Ejecutar tests y verificar que pasan
---
### **Fase 5: Integración con APIs de metadata**
- **Objetivo:** Clientes para IGDB (OAuth Twitch), RAWG (API key), TheGamesDB (API key); lógica de matching heurística (nombre + plataforma), caché local de respuestas para evitar rate limits.
- **Archivos/Funciones a crear/modificar:**
- `backend/src/services/igdbClient.ts``searchGames(query, platform?)`, `getGameById(id)`
- `backend/src/services/rawgClient.ts``searchGames(query)`, `getGameById(id)`
- `backend/src/services/thegamesdbClient.ts``searchGames(query)`, `getGameById(id)`
- `backend/src/services/metadataService.ts``enrichGame(romFile)` (orquesta clientes, fallbacks, matching heurística)
- `backend/src/utils/cache.ts` — caché en memoria o Redis (simple LRU)
- `backend/src/routes/metadata.ts` — endpoints `GET /api/metadata/search?q=...&platform=...`, `POST /api/metadata/enrich/:romFileId`
- **Tests a escribir:**
- `backend/tests/services/igdbClient.spec.ts` — mock de respuestas IGDB, test de OAuth flow, test de búsqueda
- `backend/tests/services/rawgClient.spec.ts` — mock de respuestas RAWG
- `backend/tests/services/metadataService.spec.ts` — casos: match exacto, match parcial, sin match (fallback)
- `backend/tests/routes/metadata.spec.ts` — test E2E de endpoints metadata
- **Pasos:**
1. Escribir tests con mocks (respuestas API simuladas)
2. Implementar clientes (IGDB OAuth, RAWG key, TheGamesDB key) con retry y timeout
3. Implementar `metadataService` con lógica de matching y fallbacks
4. Implementar endpoints REST
5. Ejecutar tests y verificar que pasan
---
### **Fase 6: Frontend base (React + Vite + shadcn/ui)**
- **Objetivo:** Configurar proyecto frontend con Vite, React, TypeScript, Tailwind CSS, shadcn/ui, TanStack Query, TanStack Router. Implementar layout base (navbar, sidebar), rutas (Home, ROMs, Games, Settings) y componentes UI básicos (Button, Card, Table, Dialog de shadcn/ui).
- **Archivos/Funciones a crear/modificar:**
- `frontend/package.json` — dependencias (react, vite, @shadcn/ui, tailwindcss, @tanstack/react-router, @tanstack/react-query)
- `frontend/tsconfig.json` — configuración TypeScript frontend
- `frontend/vite.config.ts` — configuración Vite (proxy a backend, aliases, TanStack Router plugin)
- `frontend/tailwind.config.js` — configuración Tailwind para shadcn/ui
- `frontend/src/main.tsx` — entry point con QueryClientProvider y RouterProvider
- `frontend/src/routes/__root.tsx` — layout raíz con navbar y sidebar
- `frontend/src/routes/index.tsx` — ruta Home
- `frontend/src/routes/roms.tsx` — ruta ROMs
- `frontend/src/routes/games.tsx` — ruta Games
- `frontend/src/components/layout/Navbar.tsx`
- `frontend/src/components/layout/Sidebar.tsx`
- `frontend/src/lib/api.ts` — cliente HTTP base (fetch/axios wrapper)
- `frontend/src/lib/queryClient.ts` — configuración de TanStack Query
- `frontend/src/hooks/useGames.ts` — custom hook con TanStack Query para juegos
- **Tests a escribir:**
- `frontend/tests/App.spec.tsx` — renderizado de rutas (usando Vitest + React Testing Library)
- `frontend/tests/components/Navbar.spec.tsx` — navegación básica
- `tests/e2e/navigation.spec.ts` — E2E con Playwright (navegar entre páginas)
- **Pasos:**
1. Escribir tests que fallen (renderizado de App, navegación E2E)
2. Configurar Vite + React + TypeScript + Tailwind + shadcn/ui + TanStack Query
3. Implementar layout, rutas, páginas vacías, configuración de QueryClient
4. Ejecutar tests y verificar que pasan
---
### **Fase 7: Gestión manual de juegos (frontend + backend)**
- **Objetivo:** CRUD completo para juegos: crear/editar/eliminar juegos manualmente (frontend form con shadcn/ui + TanStack Query), registrar juegos físicos/digitales con campos: nombre, plataforma, precio, condición (Loose/CIB/New), fecha de compra, vendedor, notas.
- **Archivos/Funciones a crear/modificar:**
- `backend/src/routes/games.ts``GET /api/games`, `POST /api/games`, `PUT /api/games/:id`, `DELETE /api/games/:id`
- `backend/src/controllers/gamesController.ts` — lógica de CRUD
- `backend/src/validators/gameValidator.ts` — validación de input (Zod/Joi)
- `frontend/src/routes/games.tsx` — tabla de juegos con acciones (editar, eliminar)
- `frontend/src/components/games/GameForm.tsx` — formulario para crear/editar juego
- `frontend/src/components/games/GameCard.tsx` — card de vista de juego
- `frontend/src/hooks/useGames.ts` — custom hooks con TanStack Query (useGames, useCreateGame, useUpdateGame, useDeleteGame)
- `frontend/src/components/ui/*` — shadcn/ui components (Form, Input, Select, Textarea, DatePicker)
- **Tests a escribir:**
- `backend/tests/routes/games.spec.ts` — CRUD endpoints (casos: crear juego válido, crear juego con datos faltantes, actualizar, eliminar)
- `frontend/tests/routes/games.spec.tsx` — renderizado de lista, acciones
- `frontend/tests/components/GameForm.spec.tsx` — validación de formulario
- `tests/e2e/games-crud.spec.ts` — E2E completo (crear/editar/eliminar juego)
- **Pasos:**
1. Escribir tests que fallen (endpoints CRUD, renderizado de form, E2E CRUD)
2. Implementar backend endpoints y validators
3. Implementar frontend page, form, custom hooks con TanStack Query
4. Ejecutar tests y verificar que pasan
---
### **Fase 8: Integración ROMs + Metadata (UI completa)**
- **Objetivo:** Vista de ROMs escaneados en frontend, botón para scan de directorio, búsqueda/asociación de metadata (UI para seleccionar resultado de IGDB/RAWG con TanStack Query), y vincular ROM con juego. Incluir vista de artwork (covers, screenshots).
- **Archivos/Funciones a crear/modificar:**
- `frontend/src/routes/roms.tsx` — tabla de ROMs escaneados, botón "Scan Directory", acciones (asociar metadata, ver detalles)
- `frontend/src/components/roms/ScanDialog.tsx` — dialog para input de path y scan
- `frontend/src/components/roms/MetadataSearchDialog.tsx` — búsqueda y selección de metadata
- `frontend/src/components/roms/RomCard.tsx` — card con info de ROM + artwork
- `frontend/src/hooks/useRoms.ts` — custom hooks con TanStack Query (useRoms, useScanDirectory, useEnrichMetadata)
- `backend/src/routes/artwork.ts``GET /api/artwork/:gameId` (proxy/cache de imágenes)
- **Tests a escribir:**
- `frontend/tests/routes/roms.spec.tsx` — renderizado de tabla, acciones
- `frontend/tests/components/ScanDialog.spec.tsx` — submit de path, loading state
- `tests/e2e/roms-import.spec.ts` — E2E: scan → ver ROMs → asociar metadata → ver juego enriquecido
- **Pasos:**
1. Escribir tests que fallen (UI de ROMs, scan dialog, E2E import completo)
2. Implementar componentes frontend y custom hooks con TanStack Query
3. Implementar endpoint de artwork (cache/proxy)
4. Ejecutar tests y verificar que pasan
---
### **Fase 9: CI, tests E2E, docs y seguridad**
- **Objetivo:** GitHub Actions para CI (lint, tests unitarios, tests E2E con Playwright), configuración de ESLint/Prettier, docs de uso de APIs (cómo obtener keys), seguridad (env vars, .gitignore actualizado, SECURITY.md), y README completo.
- **Archivos/Funciones a crear/modificar:**
- `.github/workflows/ci.yml` — pipeline (install, lint, test, e2e)
- `.eslintrc.cjs` — ajustar para backend + frontend
- `.prettierrc` — ajustar formatos
- `README.md` — actualizar con: setup, features, screenshots, roadmap
- `SECURITY.md` — políticas de seguridad, reporte de vulnerabilidades
- `docs/API_KEYS.md` — instrucciones para obtener keys de IGDB, RAWG, TheGamesDB
- `.env.example` — template de variables de entorno
- `backend/.env.example`, `frontend/.env.example` — templates específicos
- **Tests a escribir:**
- `tests/e2e/full-flow.spec.ts` — E2E completo end-to-end (scan → enrich → crear juego manual → view)
- Asegurar que CI ejecuta todos los tests y Playwright genera reporte
- **Pasos:**
1. Configurar GitHub Actions workflow
2. Ejecutar pipeline en CI (puede fallar inicialmente)
3. Corregir issues de lint/format/tests
4. Actualizar docs (README, SECURITY, API_KEYS)
5. Ejecutar CI nuevamente y verificar que todo pasa
---
## **Preguntas abiertas resueltas** ✅
1. ✅ App web self-hosted (server + frontend separados)
2. ✅ Frontend: TypeScript + React + Vite + shadcn/ui + TanStack Query + TanStack Router
3. ✅ Solo APIs públicas: IGDB (OAuth Twitch gratuito), RAWG (API key gratuita con atribución), TheGamesDB (API key gratuita)
4. ✅ Sin integración con tiendas (Steam/GOG/PSN) en MVP; dejar preparado para futuro (campo `storeId`, `storePlatform` en modelo Game)
5. ✅ Prioridad: gestión de ROMs de directorio + creación manual de juegos físicos/digitales
---
## **Decisiones técnicas clave** 🔧
- **Monorepo:** `/backend` y `/frontend` en el mismo repo, con workspaces de Yarn
- **Backend:** Node.js + Fastify + TypeScript + Prisma + SQLite (migration a PostgreSQL posible en futuro)
- **Frontend:** React + Vite + TypeScript + Tailwind CSS + shadcn/ui + TanStack Query + TanStack Router
- **APIs de metadata:** IGDB (primary), RAWG (fallback), TheGamesDB (artwork/retro)
- **Tests:** Backend (Vitest + Supertest), Frontend (Vitest + React Testing Library), E2E (Playwright)
- **CI:** GitHub Actions con pipeline: install → lint → test → e2e
- **Seguridad:** API keys en `.env`, no commitear secrets
---
## **Roadmap futuro (fuera del MVP)** 🚀
- Integración con tiendas (Steam/GOG/PSN/Xbox) para import automático de compras
- Price tracking con PriceCharting/IsThereAnyDeal (requiere suscripción/API paga)
- Plugins/extensiones (LaunchBox export, Playnite sync)
- Sincronización en nube (opcional, con cifrado E2E)
- Soporte para multiple usuarios (autenticación/autorización)
- Mobile app (React Native o PWA)