Files
quasar/frontend/src/lib/api.ts
Benito Rodríguez 3096a9b472
Some checks failed
CI / lint (push) Failing after 7s
CI / test-backend (push) Has been skipped
CI / test-frontend (push) Has been skipped
CI / test-e2e (push) Has been skipped
feat: improve type definitions and refactor API responses for better type safety
2026-03-18 19:37:23 +01:00

244 lines
5.7 KiB
TypeScript

const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api';
// Tipos para relaciones del juego
export interface Artwork {
id: string;
type: string;
sourceUrl: string;
localPath?: string;
width?: number;
height?: number;
fetchedAt: string;
}
export interface Purchase {
id: string;
priceCents: number;
currency: string;
store?: string;
date: string;
receiptPath?: string;
}
export interface GamePlatform {
id: string;
platform: {
id: string;
name: string;
slug: string;
generation?: number;
};
}
export interface Tag {
id: string;
name: string;
}
// Tipos para metadatos de búsqueda
export interface MetadataGame {
id?: number;
name: string;
slug?: string;
releaseDate?: string;
genres?: string[];
platforms?: PlatformInfo[];
coverUrl?: string;
source?: string;
}
export interface PlatformInfo {
id?: number;
name?: string;
abbreviation?: string;
slug?: string;
}
export interface Game {
id: string;
title: string;
slug: string;
description?: string;
releaseDate?: string;
genre?: string;
platform?: string;
year?: number;
cover?: string;
source: string;
sourceId?: string;
// Campos específicos de ROM (si source = "rom")
romPath?: string;
romFilename?: string;
romSize?: number;
romChecksum?: string;
romFormat?: string;
romHashes?: string;
// IDs de integraciones externas
igdbId?: number;
rawgId?: number;
thegamesdbId?: number;
// Metadatos adicionales
metadata?: string;
// Timestamps
addedAt?: string;
lastSeenAt?: string;
createdAt: string;
updatedAt: string;
// Relaciones
artworks?: Artwork[];
purchases?: Purchase[];
gamePlatforms?: GamePlatform[];
tags?: Tag[];
}
export interface CreateGameInput {
title: string;
slug?: string;
description?: string;
releaseDate?: string;
genre?: string;
platform?: string;
year?: number;
cover?: string;
source?: string;
sourceId?: string;
platformId?: string;
priceCents?: number;
currency?: string;
store?: string;
date?: string;
condition?: 'Loose' | 'CIB' | 'New';
}
export interface UpdateGameInput {
title?: string;
slug?: string;
description?: string;
releaseDate?: string;
genre?: string;
platform?: string;
year?: number;
cover?: string;
source?: string;
sourceId?: string;
platformId?: string;
priceCents?: number;
currency?: string;
store?: string;
date?: string;
condition?: 'Loose' | 'CIB' | 'New';
}
export interface ImportRequest {
directory: string;
recursive?: boolean;
}
export interface ImportResult {
success: boolean;
message: string;
imported: number;
errors: string[];
}
export const gamesApi = {
getAll: async (): Promise<Game[]> => {
const response = await fetch(`${API_BASE}/games`);
if (!response.ok) {
throw new Error(`Error fetching games: ${response.statusText}`);
}
return response.json();
},
getById: async (id: string): Promise<Game> => {
const response = await fetch(`${API_BASE}/games/${id}`);
if (!response.ok) {
throw new Error(`Error fetching game: ${response.statusText}`);
}
return response.json();
},
getBySource: async (source: string): Promise<Game[]> => {
const response = await fetch(`${API_BASE}/games/source/${source}`);
if (!response.ok) {
throw new Error(`Error fetching games by source: ${response.statusText}`);
}
return response.json();
},
create: async (data: CreateGameInput): Promise<Game> => {
const response = await fetch(`${API_BASE}/games`, {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(`Error creating game: ${response.statusText}`);
}
return response.json();
},
update: async (id: string, data: UpdateGameInput): Promise<Game> => {
const response = await fetch(`${API_BASE}/games/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(`Error updating game: ${response.statusText}`);
}
return response.json();
},
delete: async (id: string): Promise<void> => {
const response = await fetch(`${API_BASE}/games/${id}`, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error(`Error deleting game: ${response.statusText}`);
}
},
};
export const importApi = {
start: async (data: ImportRequest): Promise<ImportResult> => {
const response = await fetch(`${API_BASE}/import`, {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(`Error starting import: ${response.statusText}`);
}
return response.json();
},
};
export const metadataApi = {
searchIGDB: async (query: string): Promise<MetadataGame[]> => {
const response = await fetch(`${API_BASE}/metadata/igdb/search?q=${encodeURIComponent(query)}`);
if (!response.ok) {
throw new Error(`Error searching IGDB: ${response.statusText}`);
}
return response.json();
},
searchRAWG: async (query: string): Promise<MetadataGame[]> => {
const response = await fetch(`${API_BASE}/metadata/rawg/search?q=${encodeURIComponent(query)}`);
if (!response.ok) {
throw new Error(`Error searching RAWG: ${response.statusText}`);
}
return response.json();
},
searchTheGamesDB: async (query: string): Promise<MetadataGame[]> => {
const response = await fetch(
`${API_BASE}/metadata/thegamesdb/search?q=${encodeURIComponent(query)}`
);
if (!response.ok) {
throw new Error(`Error searching TheGamesDB: ${response.statusText}`);
}
return response.json();
},
};