export interface HttpError { type: 'message' | 'validation'; message?: string; errors?: { [key: string]: string[] }; statusCode?: number; originalError?: any; } export const httpClient = { async post(url: string, data: any): Promise { try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { let errorData: any = null; try { errorData = await response.json(); } catch (parseError) { errorData = await response.text(); } throw this._handleHttpError(response.status, errorData); } if (response.status === 204 || response.headers.get('content-length') === '0') { return undefined as TResponse; } return await response.json() as TResponse; } catch (error: any) { if (error && typeof error.type === 'string' && (error.type === 'message' || error.type === 'validation')) { throw error; } else { throw { type: 'message', message: 'NETWORK_ERROR_MESSAGE', originalError: error, statusCode: 0 } as HttpError; } } }, _handleHttpError(status: number, errorBody: any): HttpError { if (status === 500) { return { type: 'message', message: 'UNEXPECTED_ERROR_MESSAGE', statusCode: status, originalError: errorBody }; } if (status === 400) { if (errorBody && errorBody.errors) { return { type: 'validation', errors: errorBody.errors, statusCode: status, originalError: errorBody }; } if (typeof errorBody === 'object' && (errorBody.Message || errorBody.message)) { return { type: 'message', message: errorBody.Message || errorBody.message, statusCode: status, originalError: errorBody }; } } if (typeof errorBody === 'string') { return { type: 'message', message: errorBody, statusCode: status, originalError: errorBody }; } return { type: 'message', message: 'UNEXPECTED_ERROR_MESSAGE', statusCode: status, originalError: errorBody }; } };