95 lines
2.3 KiB
JavaScript
95 lines
2.3 KiB
JavaScript
/**
|
|
* API Client
|
|
* Centralized API request handling with consistent error handling
|
|
*/
|
|
|
|
/**
|
|
* Default fetch options
|
|
*/
|
|
const DEFAULT_OPTIONS = {
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Base API request wrapper
|
|
* @param {string} url - API endpoint URL
|
|
* @param {Object} options - Fetch options
|
|
* @returns {Promise<any>} Response data
|
|
*/
|
|
async function apiRequest(url, options = {}) {
|
|
const response = await fetch(url, {
|
|
...DEFAULT_OPTIONS,
|
|
...options,
|
|
headers: {
|
|
...DEFAULT_OPTIONS.headers,
|
|
...options.headers
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text().catch(() => response.statusText);
|
|
const error = new Error(`HTTP ${response.status}: ${errorText}`);
|
|
error.status = response.status;
|
|
error.body = errorText;
|
|
throw error;
|
|
}
|
|
|
|
// Check if response has content
|
|
const contentType = response.headers.get('content-type');
|
|
if (contentType && contentType.includes('application/json')) {
|
|
return await response.json();
|
|
}
|
|
|
|
return await response.text();
|
|
}
|
|
|
|
/**
|
|
* GET request
|
|
* @param {string} url - API endpoint URL
|
|
* @returns {Promise<any>} Response data
|
|
*/
|
|
export async function apiGet(url) {
|
|
return await apiRequest(url, { method: 'GET' });
|
|
}
|
|
|
|
/**
|
|
* POST request
|
|
* @param {string} url - API endpoint URL
|
|
* @param {Object} data - Request body data
|
|
* @returns {Promise<any>} Response data
|
|
*/
|
|
export async function apiPost(url, data = null) {
|
|
const options = { method: 'POST' };
|
|
if (data !== null) {
|
|
options.body = JSON.stringify(data);
|
|
}
|
|
return await apiRequest(url, options);
|
|
}
|
|
|
|
/**
|
|
* DELETE request
|
|
* @param {string} url - API endpoint URL
|
|
* @returns {Promise<any>} Response data
|
|
*/
|
|
export async function apiDelete(url) {
|
|
return await apiRequest(url, { method: 'DELETE' });
|
|
}
|
|
|
|
/**
|
|
* Build URL with query parameters
|
|
* @param {string} baseUrl - Base URL
|
|
* @param {Object} params - Query parameters
|
|
* @returns {string} URL with query string
|
|
*/
|
|
export function buildUrl(baseUrl, params = {}) {
|
|
const url = new URL(baseUrl, window.location.origin);
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== null && value !== undefined) {
|
|
url.searchParams.append(key, value);
|
|
}
|
|
});
|
|
return url.toString();
|
|
}
|