// src/utils/api.ts // Standard JSON headers for all API responses const JSON_HEADERS = { 'Content-Type': 'application/json' } as const; /** * Base function to create consistent API responses * All other response helpers use this internally */ export function createAPIResponse(data: any, status: number = 200, additionalHeaders?: Record): Response { const headers = additionalHeaders ? { ...JSON_HEADERS, ...additionalHeaders } : JSON_HEADERS; return new Response(JSON.stringify(data), { status, headers }); } /** * Success responses (2xx status codes) */ export const apiResponse = { // 200 - Success with data success: (data: any = { success: true }): Response => createAPIResponse(data, 200), // 201 - Created (for contribution submissions, uploads, etc.) created: (data: any = { success: true }): Response => createAPIResponse(data, 201), // 202 - Accepted (for async operations) accepted: (data: any = { success: true, message: 'Request accepted for processing' }): Response => createAPIResponse(data, 202) }; /** * Client error responses (4xx status codes) */ export const apiError = { // 400 - Bad Request badRequest: (message: string = 'Bad request', details?: string[]): Response => createAPIResponse({ success: false, error: message, ...(details && { details }) }, 400), // 401 - Unauthorized unauthorized: (message: string = 'Authentication required'): Response => createAPIResponse({ success: false, error: message }, 401), // 403 - Forbidden forbidden: (message: string = 'Access denied'): Response => createAPIResponse({ success: false, error: message }, 403), // 404 - Not Found notFound: (message: string = 'Resource not found'): Response => createAPIResponse({ success: false, error: message }, 404), // 422 - Unprocessable Entity (validation errors) validation: (message: string = 'Validation failed', details?: string[]): Response => createAPIResponse({ success: false, error: message, ...(details && { details }) }, 422), // 429 - Rate Limited rateLimit: (message: string = 'Rate limit exceeded. Please wait before trying again.'): Response => createAPIResponse({ success: false, error: message }, 429) }; /** * Server error responses (5xx status codes) */ export const apiServerError = { // 500 - Internal Server Error internal: (message: string = 'Internal server error'): Response => createAPIResponse({ success: false, error: message }, 500), // 502 - Bad Gateway (external service issues) badGateway: (message: string = 'External service error'): Response => createAPIResponse({ success: false, error: message }, 502), // 503 - Service Unavailable unavailable: (message: string = 'Service temporarily unavailable'): Response => createAPIResponse({ success: false, error: message }, 503), // 504 - Gateway Timeout timeout: (message: string = 'Request timeout'): Response => createAPIResponse({ success: false, error: message }, 504) }; /** * Specialized response helpers for common patterns */ export const apiSpecial = { // JSON parsing error invalidJSON: (): Response => apiError.badRequest('Invalid JSON in request body'), // Missing required fields missingRequired: (fields: string[]): Response => apiError.badRequest(`Missing required fields: ${fields.join(', ')}`), // Empty request body emptyBody: (): Response => apiError.badRequest('Request body cannot be empty'), // File upload responses uploadSuccess: (data: { url: string; filename: string; size: number; storage: string }): Response => apiResponse.created(data), uploadFailed: (error: string): Response => apiServerError.internal(`Upload failed: ${error}`), // Contribution responses contributionSuccess: (data: { prUrl?: string; branchName?: string; message: string }): Response => apiResponse.created({ success: true, ...data }), contributionFailed: (error: string): Response => apiServerError.internal(`Contribution failed: ${error}`) }; export const apiWithHeaders = { // Success with custom headers (e.g., Set-Cookie) successWithHeaders: (data: any, headers: Record): Response => createAPIResponse(data, 200, headers), // Redirect response redirect: (location: string, temporary: boolean = true): Response => new Response(null, { status: temporary ? 302 : 301, headers: { 'Location': location } }) }; export async function handleAPIRequest( operation: () => Promise, errorMessage: string = 'Request processing failed' ): Promise { try { return await operation(); } catch (error) { console.error(`API Error: ${errorMessage}:`, error); return apiServerError.internal(errorMessage); } } export const createAuthErrorResponse = apiError.unauthorized; export const createBadRequestResponse = apiError.badRequest; export const createSuccessResponse = apiResponse.success;