Files
quasar/frontend/src/lib/api.ts
Benito Rodríguez 571ac97f00 feat: implement ROMs management UI (Phase 8)
Backend (Phase 8.1):
- Add ROMs endpoints: GET, GET/:id, PUT/:id/game, DELETE
- Add metadata search endpoint using IGDB/RAWG/TGDB
- Implement RomsController with ROM CRUD logic
- Add 12 comprehensive ROM endpoint tests
- Configure Vitest to run tests sequentially (threads: false)
- Auto-apply Prisma migrations in test setup

Frontend (Phase 8.2 + 8.3):
- Create ROM types: RomFile, Artwork, EnrichedGame
- Extend API client with roms and metadata namespaces
- Implement 5 custom hooks with TanStack Query
- Create ScanDialog, MetadataSearchDialog, RomCard components
- Rewrite roms.tsx page with table and all actions
- Add 37 comprehensive component and page tests

All 122 tests passing: 63 backend + 59 frontend
Lint: 0 errors, only unused directive warnings
2026-02-12 19:52:59 +01:00

65 lines
1.7 KiB
TypeScript

import { Game, CreateGameInput, UpdateGameInput } from '../types/game';
import { RomFile, EnrichedGame, ScanResult } from '../types/rom';
const API_BASE = '/api';
async function request<T>(endpoint: string, options?: RequestInit): Promise<T> {
const response = await fetch(`${API_BASE}${endpoint}`, {
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
...options,
});
if (!response.ok) {
throw new Error(`API error: ${response.status} ${response.statusText}`);
}
return response.json();
}
export const api = {
games: {
list: () => request<Game[]>('/games'),
create: (data: CreateGameInput) =>
request<Game>('/games', {
method: 'POST',
body: JSON.stringify(data),
}),
update: (id: string, data: UpdateGameInput) =>
request<Game>(`/games/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
}),
delete: (id: string) =>
request<void>(`/games/${id}`, {
method: 'DELETE',
}),
},
roms: {
list: () => request<RomFile[]>('/roms'),
getById: (id: string) => request<RomFile>(`/roms/${id}`),
linkGame: (romId: string, gameId: string) =>
request<RomFile>(`/roms/${romId}/game`, {
method: 'PUT',
body: JSON.stringify({ gameId }),
}),
delete: (id: string) => request<void>(`/roms/${id}`, { method: 'DELETE' }),
},
metadata: {
search: (query: string) =>
request<EnrichedGame[]>('/metadata/search?q=' + encodeURIComponent(query)),
},
import: {
scan: (dir: string) =>
request<ScanResult>('/import/scan', {
method: 'POST',
body: JSON.stringify({ dir }),
}),
},
};