7.4 KiB
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 juegoplatform(string, opcional): Plataforma para filtrar (ej. "NES", "SNES")year(number, opcional): Año de lanzamiento para filtrar (1900-2100)
Respuesta:
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:
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:
interface CreateGameFromMetadataBody {
metadata: EnrichedGame;
overrides?: {
platformId?: string;
description?: string;
priceCents?: number;
currency?: string;
store?: string;
date?: string;
condition?: 'Loose' | 'CIB' | 'New';
};
}
Respuesta:
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:
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:
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:
interface SearchFormProps {
onSearch: (params: SearchGamesParams) => void;
isLoading?: boolean;
}
SearchResults
Muestra los resultados de la búsqueda en una lista.
Props:
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:
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:
// Buscar juegos
metadataApi.searchGames(params: SearchGamesParams): Promise<EnrichedGame[]>
// Crear juego desde metadatos
metadataApi.createGameFromMetadata(data: CreateGameFromMetadataInput): Promise<Game>
Flujo de Usuario
- El usuario navega a
/games/add - Ingresa un título de búsqueda (opcionalmente plataforma y año)
- Hace clic en "Buscar"
- El frontend llama a
metadataApi.searchGames() - El backend busca en IGDB, RAWG y TheGamesDB
- Los resultados se muestran en
SearchResults - El usuario selecciona un resultado
- Se abre
GamePreviewDialogcon los metadatos - El usuario puede editar los campos según sea necesario
- Hace clic en "Guardar"
- El frontend llama a
metadataApi.createGameFromMetadata() - El juego se crea en la base de datos
- El usuario es redirigido a la página del juego
Configuración
Variables de Entorno
Backend:
# 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:
NEXT_PUBLIC_API_URL=http://localhost:3003/api
Tests
Backend Tests
tests/services/metadataService.spec.ts: Tests del servicio de búsquedatests/routes/metadata.spec.ts: Tests de endpoints de metadatostests/routes/games.spec.ts: Tests de endpoints de juegos
Ejecutar tests:
cd backend
yarn test
Frontend Tests
src/components/games/__tests__/SearchForm.spec.ts: Tests del formulario de búsquedasrc/components/games/__tests__/SearchResults.spec.ts: Tests de resultados de búsquedasrc/components/games/__tests__/GamePreviewDialog.spec.ts: Tests del diálogo de previsualización
Ejecutar tests:
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):
nameytitlese 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