Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -415,6 +415,42 @@ class MetadataService {
|
||||
|
||||
## Configuración y despliegue
|
||||
|
||||
### Configuración de variables de entorno
|
||||
|
||||
Para configurar las credenciales de las APIs externas en Quasar, sigue estos pasos:
|
||||
|
||||
#### 1. Archivo `.env`
|
||||
|
||||
El archivo [`backend/.env`](../../backend/.env) contiene las variables de entorno necesarias. Este archivo **NO** debe ser commiteado al repositorio (ya está incluido en [`.gitignore`](../../.gitignore)).
|
||||
|
||||
#### 2. Variables requeridas
|
||||
|
||||
Añade las siguientes variables a tu archivo [`backend/.env`](../../backend/.env):
|
||||
|
||||
```bash
|
||||
# IGDB (Internet Game Database)
|
||||
IGDB_CLIENT_ID=your_igdb_client_id_here
|
||||
IGDB_CLIENT_SECRET=your_igdb_client_secret_here
|
||||
|
||||
# RAWG Video Games Database
|
||||
RAWG_API_KEY=your_rawg_api_key_here
|
||||
|
||||
# TheGamesDB
|
||||
THEGAMESDB_API_KEY=your_thegamesdb_api_key_here
|
||||
```
|
||||
|
||||
#### 3. Archivo de ejemplo
|
||||
|
||||
El archivo [`backend/.env.example`](../../backend/.env.example) contiene todas las variables de entorno disponibles con sus descripciones. Úsalo como referencia cuando configures tu entorno.
|
||||
|
||||
#### 4. Instrucciones detalladas por API
|
||||
|
||||
Consulte la sección [Obtención de claves](#obtención-de-claves) para instrucciones detalladas sobre cómo obtener cada credencial:
|
||||
|
||||
- **IGDB**: [https://dev.twitch.tv/console](https://dev.twitch.tv/console)
|
||||
- **RAWG**: [https://rawg.io/apicreate](https://rawg.io/apicreate)
|
||||
- **TheGamesDB**: [https://thegamesdb.net/api.php](https://thegamesdb.net/api.php)
|
||||
|
||||
### Testing Without Real Keys
|
||||
|
||||
Para desarrollo/testing:
|
||||
|
||||
330
docs/02-tecnico/game-search.md
Normal file
330
docs/02-tecnico/game-search.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user