vue-data/src/core/http-client.ts

98 lines
2.4 KiB
TypeScript

export interface HttpError {
type: 'message' | 'validation';
message?: string;
errors?: { [key: string]: string[] };
statusCode?: number;
originalError?: any;
}
export const httpClient = {
async post<TResponse = any>(url: string, data: any): Promise<TResponse> {
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
};
}
};