/** * API client utilities for repository operations * Provides centralized API call functions with error handling and logging */ import { get } from 'svelte/store'; import { userStore } from '$lib/stores/user-store.js'; import logger from '$lib/services/logger.js'; /** * Builds API headers with user pubkey for authenticated requests */ export function buildApiHeaders(): Record { const headers: Record = {}; const currentUser = get(userStore); const currentUserPubkeyHex = currentUser?.userPubkeyHex; if (currentUserPubkeyHex) { headers['X-User-Pubkey'] = currentUserPubkeyHex; logger.debug({ pubkey: currentUserPubkeyHex.substring(0, 16) + '...' }, '[API] Sending X-User-Pubkey header'); } return headers; } /** * Makes an API request with error handling and logging */ export async function apiRequest( url: string, options: RequestInit = {} ): Promise { const headers = { ...buildApiHeaders(), ...options.headers, 'Content-Type': 'application/json', }; logger.debug({ url, method: options.method || 'GET' }, '[API] Making request'); try { const response = await fetch(url, { ...options, headers, credentials: 'same-origin', }); if (!response.ok) { let errorMessage = `API request failed: ${response.status} ${response.statusText}`; try { const errorData = await response.json(); if (errorData.message) { errorMessage = errorData.message; } else if (errorData.error) { errorMessage = errorData.error; } } catch { try { const text = await response.text(); if (text) { errorMessage = text.substring(0, 200); } } catch { // Ignore parsing errors } } // 404s are expected when repo isn't cloned - log as debug, not error if (response.status === 404) { logger.debug({ url, status: response.status, error: errorMessage }, '[API] Request failed (404 - expected for uncloned repos)'); } else { logger.error({ url, status: response.status, error: errorMessage }, '[API] Request failed'); } throw new Error(errorMessage); } const data = await response.json(); logger.debug({ url }, '[API] Request successful'); return data as T; } catch (err) { logger.error({ url, error: err }, '[API] Request error'); throw err; } } /** * Makes a POST request */ export async function apiPost( url: string, body: unknown ): Promise { return apiRequest(url, { method: 'POST', body: JSON.stringify(body), }); } /** * Makes a PUT request */ export async function apiPut( url: string, body: unknown ): Promise { return apiRequest(url, { method: 'PUT', body: JSON.stringify(body), }); } /** * Makes a DELETE request */ export async function apiDelete(url: string): Promise { return apiRequest(url, { method: 'DELETE', }); }