const BASE = '/api'; export interface User { id: number; username: string; is_admin: boolean; created_at: string; updated_at: string; } export interface Image { id: number; filename: string; storage_path: string; thumbnail_path: string | null; uploaded_by: number; file_size: number; width: number; height: number; mime_type: string; created_at: string; updated_at: string; tags: string[]; } export interface ImageList { images: Image[]; total: number; } export interface Tag { tag: string; usage_count: number; } export interface ApiError { error: string; } async function request(path: string, opts: RequestInit = {}): Promise { const res = await fetch(BASE + path, { credentials: 'include', headers: opts.body instanceof FormData ? {} : { 'Content-Type': 'application/json' }, ...opts, }); if (!res.ok) { const body = await res.json().catch(() => ({ error: res.statusText })); throw new Error((body as ApiError).error || `HTTP ${res.status}`); } return res.json(); } export async function login(username: string, password: string): Promise { return request('/auth/login', { method: 'POST', body: JSON.stringify({ username, password }), }); } export async function register(username: string, password: string): Promise { return request('/auth/register', { method: 'POST', body: JSON.stringify({ username, password }), }); } export async function logout(): Promise { await request('/auth/logout', { method: 'POST' }); } export async function listImages(tags: string[] = [], page = 1, perPage = 50): Promise { const params = new URLSearchParams(); params.set('page', String(page)); params.set('per_page', String(perPage)); for (const t of tags) { params.append('tags', t); } return request(`/images?${params}`); } export async function getImage(id: number): Promise { return request(`/images/${id}`); } export function imageDownloadUrl(id: number): string { return `${BASE}/images/${id}/download`; } export function thumbnailUrl(id: number): string { return `${BASE}/images/${id}/thumbnail`; } export async function uploadImage(file: File, tags: string[]): Promise { const fd = new FormData(); fd.append('file', file); for (const t of tags) { fd.append('tags', t); } return request('/upload', { method: 'POST', body: fd }); } export async function suggestTags(query: string): Promise { return request(`/tags/suggest?q=${encodeURIComponent(query)}`); }