331 lines
7.4 KiB
Markdown
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
|