Reorganize web folder structurally
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
const API_BASE = '/api';
|
||||
|
||||
export class HttpClient {
|
||||
private token: string | null = null;
|
||||
|
||||
setToken(token: string | null) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
async request<T>(endpoint: string, options: RequestInit & { timeout?: number } = {}): Promise<T> {
|
||||
const { timeout = 30_000, ...fetchOptions } = options;
|
||||
const controller = new AbortController();
|
||||
const timer = timeout > 0 ? setTimeout(() => controller.abort(), timeout) : undefined;
|
||||
|
||||
const isFormData = fetchOptions.body instanceof FormData;
|
||||
const computedHeaders: Record<string, string> = {
|
||||
...(this.token ? { Authorization: `Bearer ${this.token}` } : {}),
|
||||
...(fetchOptions.headers as Record<string, string>),
|
||||
};
|
||||
|
||||
if (!isFormData && !computedHeaders['Content-Type']) {
|
||||
computedHeaders['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch(`${API_BASE}${endpoint}`, {
|
||||
...fetchOptions,
|
||||
headers: computedHeaders,
|
||||
signal: controller.signal,
|
||||
});
|
||||
} catch (err) {
|
||||
clearTimeout(timer);
|
||||
if (err instanceof DOMException && err.name === 'AbortError') {
|
||||
throw new Error('Время ожидания запроса истекло');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
clearTimeout(timer);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
const errorMessage = errorData.error || errorData.message || 'Ошибка запроса';
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
|
||||
export const httpClient = new HttpClient();
|
||||
Reference in New Issue
Block a user