238 lines
15 KiB
Markdown
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)
|