import { clearAuthState, fetchWithAuth } from '../../auth-session.js'; const DEFAULT_API_ERROR = 'Не удалось выполнить запрос'; const UNAUTHORIZED_ERROR = 'Требуется повторный вход в систему'; export class ApiRequestError extends Error { constructor(message, { data = null, status = 0 } = {}) { super(message); this.name = 'ApiRequestError'; this.data = data; this.status = status; } } export async function requestJson( endpoint, { errorMessage = DEFAULT_API_ERROR, headers: initialHeaders, json, ...options } = {}, { fetchImpl = fetchWithAuth, onUnauthorized = () => window.location.replace('/') } = {} ) { if (typeof endpoint !== 'string' || !endpoint.startsWith('/api/')) { throw new ApiRequestError('Разрешены только same-origin запросы к API'); } const headers = new Headers(initialHeaders || {}); headers.set('Accept', 'application/json'); let body = options.body; if (json !== undefined) { headers.set('Content-Type', 'application/json'); body = JSON.stringify(json); } const response = await fetchImpl(endpoint, { ...options, body, headers }); const data = await readResponseData(response); if (response.status === 401) { clearAuthState(); onUnauthorized(); throw new ApiRequestError(UNAUTHORIZED_ERROR, { data, status: response.status }); } if (!response.ok) { throw new ApiRequestError(errorMessage, { data, status: response.status }); } return data; } export const apiClient = Object.freeze({ delete: (endpoint, options = {}, dependencies) => requestJson( endpoint, { ...options, method: 'DELETE' }, dependencies ), get: (endpoint, options = {}, dependencies) => requestJson( endpoint, { ...options, method: 'GET' }, dependencies ), post: (endpoint, json, options = {}, dependencies) => requestJson( endpoint, { ...options, json, method: 'POST' }, dependencies ), put: (endpoint, json, options = {}, dependencies) => requestJson( endpoint, { ...options, json, method: 'PUT' }, dependencies ) }); async function readResponseData(response) { if (response.status === 204) { return null; } const text = await response.text(); if (!text) { return null; } const contentType = response.headers.get('Content-Type') || ''; if (!contentType.includes('application/json')) { return text; } try { return JSON.parse(text); } catch (error) { return null; } }