Files
quasar/docs/02-tecnico/game-search.md
Benito Rodríguez 2667e11284
Some checks failed
CI / lint (push) Failing after 10s
CI / test-backend (push) Has been skipped
CI / test-frontend (push) Has been skipped
CI / test-e2e (push) Has been skipped
Refactor code structure for improved readability and maintainability
2026-03-22 11:34:38 +01:00

331 lines
7.4 KiB
Markdown

# Búsqueda de Juegos
## Resumen
La funcionalidad de búsqueda de juegos permite a los usuarios buscar metadatos de juegos desde múltiples fuentes externas (IGDB, RAWG, TheGamesDB) y agregarlos a su biblioteca personal.
## Arquitectura
### Backend
#### Endpoints
##### `GET /api/metadata/search`
Busca metadatos de juegos en múltiples fuentes externas.
**Parámetros de query:**
- `q` (string, requerido): Término de búsqueda del título del juego
- `platform` (string, opcional): Plataforma para filtrar (ej. "NES", "SNES")
- `year` (number, opcional): Año de lanzamiento para filtrar (1900-2100)
**Respuesta:**
```typescript
interface EnrichedGame {
source: 'igdb' | 'rawg' | 'thegamesdb';
externalIds: {
igdb?: number;
rawg?: number;
thegamesdb?: number;
};
name: string;
title: string;
slug: string;
releaseDate?: string;
genres?: string[];
coverUrl?: string;
platforms?: PlatformInfo[];
}
```
**Ejemplo de solicitud:**
```bash
curl "http://localhost:3003/api/metadata/search?q=Sonic&platform=Genesis&year=1991"
```
##### `POST /api/games/from-metadata`
Crea un juego nuevo a partir de metadatos de búsqueda.
**Body:**
```typescript
interface CreateGameFromMetadataBody {
metadata: EnrichedGame;
overrides?: {
platformId?: string;
description?: string;
priceCents?: number;
currency?: string;
store?: string;
date?: string;
condition?: 'Loose' | 'CIB' | 'New';
};
}
```
**Respuesta:**
```typescript
interface Game {
id: string;
title: string;
slug: string;
description?: string;
releaseDate?: string;
genre?: string;
platform?: string;
year?: number;
cover?: string;
source: string;
sourceId?: string;
}
```
**Ejemplo de solicitud:**
```bash
curl -X POST http://localhost:3003/api/games/from-metadata \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"source": "igdb",
"externalIds": { "igdb": 12345 },
"name": "Sonic the Hedgehog",
"slug": "sonic-the-hedgehog",
"releaseDate": "1991-06-23",
"genres": ["Platform"],
"coverUrl": "https://example.com/cover.jpg"
},
"overrides": {
"description": "Juego clásico de SEGA",
"condition": "CIB"
}
}'
```
#### Servicios
##### `metadataService.searchGames()`
Orquesta la búsqueda en múltiples fuentes externas.
**Parámetros:**
```typescript
interface SearchGamesParams {
title: string;
platform?: string;
year?: number;
}
```
**Respuesta:** Array de `EnrichedGame[]`
**Fuentes soportadas:**
- **IGDB:** Base de datos de videojuegos más completa
- **RAWG:** API de videojuegos con datos de múltiples fuentes
- **TheGamesDB:** Base de datos comunitaria de videojuegos
### Frontend
#### Página `/games/add`
Página principal para buscar y agregar juegos a la biblioteca.
**Componentes:**
##### `SearchForm`
Formulario de búsqueda con los siguientes campos:
- **Título** (requerido): Campo de texto para el título del juego
- **Plataforma** (opcional): Dropdown con plataformas comunes
- **Año** (opcional): Campo numérico para filtrar por año
**Props:**
```typescript
interface SearchFormProps {
onSearch: (params: SearchGamesParams) => void;
isLoading?: boolean;
}
```
##### `SearchResults`
Muestra los resultados de la búsqueda en una lista.
**Props:**
```typescript
interface SearchResultsProps {
results: EnrichedGame[];
onSelectResult: (result: EnrichedGame) => void;
isLoading?: boolean;
}
```
**Características:**
- Muestra la portada del juego
- Muestra el título, año y géneros
- Indica la fuente de los datos (IGDB, RAWG, TheGamesDB)
- Botón para seleccionar un resultado
##### `GamePreviewDialog`
Dialog modal para previsualizar y editar los metadatos antes de guardar.
**Props:**
```typescript
interface GamePreviewDialogProps {
open: boolean;
game: EnrichedGame | null;
onClose: () => void;
onSave: (data: CreateGameFromMetadataInput) => void;
}
```
**Características:**
- Muestra la portada del juego
- Campos editables: título, descripción, condición, plataforma
- Botón para guardar el juego en la biblioteca
#### API Client
Funciones disponibles en `src/lib/api.ts`:
```typescript
// Buscar juegos
metadataApi.searchGames(params: SearchGamesParams): Promise<EnrichedGame[]>
// Crear juego desde metadatos
metadataApi.createGameFromMetadata(data: CreateGameFromMetadataInput): Promise<Game>
```
## Flujo de Usuario
1. El usuario navega a `/games/add`
2. Ingresa un título de búsqueda (opcionalmente plataforma y año)
3. Hace clic en "Buscar"
4. El frontend llama a `metadataApi.searchGames()`
5. El backend busca en IGDB, RAWG y TheGamesDB
6. Los resultados se muestran en `SearchResults`
7. El usuario selecciona un resultado
8. Se abre `GamePreviewDialog` con los metadatos
9. El usuario puede editar los campos según sea necesario
10. Hace clic en "Guardar"
11. El frontend llama a `metadataApi.createGameFromMetadata()`
12. El juego se crea en la base de datos
13. El usuario es redirigido a la página del juego
## Configuración
### Variables de Entorno
**Backend:**
```env
# IGDB
IGDB_CLIENT_ID=your_client_id
IGDB_CLIENT_SECRET=your_client_secret
# RAWG
RAWG_API_KEY=your_api_key
# TheGamesDB
THEGAMESDB_API_KEY=your_api_key
```
**Frontend:**
```env
NEXT_PUBLIC_API_URL=http://localhost:3003/api
```
## Tests
### Backend Tests
- `tests/services/metadataService.spec.ts`: Tests del servicio de búsqueda
- `tests/routes/metadata.spec.ts`: Tests de endpoints de metadatos
- `tests/routes/games.spec.ts`: Tests de endpoints de juegos
**Ejecutar tests:**
```bash
cd backend
yarn test
```
### Frontend Tests
- `src/components/games/__tests__/SearchForm.spec.ts`: Tests del formulario de búsqueda
- `src/components/games/__tests__/SearchResults.spec.ts`: Tests de resultados de búsqueda
- `src/components/games/__tests__/GamePreviewDialog.spec.ts`: Tests del diálogo de previsualización
**Ejecutar tests:**
```bash
cd frontend
yarn test
```
## Consideraciones de Diseño
### Múltiples Fuentes
El sistema busca en múltiples fuentes simultáneamente para maximizar la probabilidad de encontrar resultados. Cada resultado incluye:
- La fuente de los datos (`source`)
- Los IDs externos (`externalIds`) para referencia futura
### Normalización de Datos
Los datos de diferentes fuentes se normalizan a un formato común (`EnrichedGame`):
- `name` y `title` se unifican
- Las fechas se normalizan a formato ISO
- Los géneros se mapean a strings
- Las plataformas se normalizan
### Validación
- Los parámetros de búsqueda se validan con Zod
- Los datos de creación de juego se validan antes de persistir
- Los campos opcionales tienen valores por defecto apropiados
### Error Handling
- Errores de API externas no bloquean la búsqueda en otras fuentes
- Errores de validación se devuelven con mensajes claros
- Errores de red se manejan con reintentos y timeouts
## Rendimiento
- Las búsquedas en múltiples fuentes se ejecutan en paralelo
- Los resultados se cachean por un período corto
- Las imágenes se cargan de forma diferida (lazy loading)
## Seguridad
- Las claves de API se almacenan en variables de entorno
- No se exponen credenciales en el frontend
- Los inputs se validan y sanitizan
- Se implementan rate limiting en las APIs externas
## Roadmap Futuro
- [ ] Soporte para más fuentes de metadatos
- [ ] Búsqueda avanzada con filtros adicionales
- [ ] Sugerencias de búsqueda mientras se escribe
- [ ] Importación masiva desde listas externas
- [ ] Sincronización automática de metadatos