/** Response interface for all API calls */ export interface ApiResponse { success: boolean; error: string; data: T; } /** * Generic API wrapper that performs a POST request with URL-encoded form data. * Returns the `data` field on success, or `undefined` on failure. * * @param url - The API endpoint URL * @param data - Key-value pairs to send as form data * @returns The response data on success, or `undefined` on failure */ export async function apiWrapper(url: string, data: Record): Promise { try { const params = new URLSearchParams(); Object.entries(data).forEach(([key, value]) => { params.append(key, String(value)); }); const response = await fetch(url, { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: "follow", referrerPolicy: "no-referrer", body: params.toString(), }); if (!response.ok) { console.error(`HTTP failed: ${response.status}`); } const payload = await response.json() as ApiResponse; if (payload.success) { return payload.data; } else { console.error(`API failed: ${payload.error}`); return undefined; } } catch (error) { console.error(`Fetch failed: ${error}`); return undefined; } } /** * Boolean API wrapper. Calls {@link apiWrapper} and returns `true` if the * response is not `undefined`, otherwise `false`. * * @param url - The API endpoint URL * @param data - Key-value pairs to send as form data * @returns `true` on success, `false` on failure */ export async function boolApiWrapper(url: string, data: Record): Promise { const rv = await apiWrapper(url, data); return rv !== undefined; }