40 lines
1.0 KiB
JavaScript
40 lines
1.0 KiB
JavaScript
|
|
/**
|
||
|
|
* Base URL for API requests.
|
||
|
|
* In development, point to the Go backend directly (e.g., http://localhost:8080).
|
||
|
|
* In production, use the relative /api path so nginx proxies to the backend.
|
||
|
|
*/
|
||
|
|
const API_BASE = import.meta.env.VITE_API_BASE_URL || '/api';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wrapper around fetch for calling the backend API.
|
||
|
|
*
|
||
|
|
* @param {string} path - API path, e.g., `/users` or `/objects/123`.
|
||
|
|
* @param {RequestInit} [options={}] - fetch options.
|
||
|
|
* @returns {Promise<any>} Parsed JSON response.
|
||
|
|
* @throws {Error} On non-OK responses.
|
||
|
|
*/
|
||
|
|
export async function apiFetch(path, options = {}) {
|
||
|
|
const url = `${API_BASE}${path}`;
|
||
|
|
|
||
|
|
const config = {
|
||
|
|
...options,
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
...options.headers
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
if (config.body && typeof config.body === 'object' && !(config.body instanceof FormData)) {
|
||
|
|
config.body = JSON.stringify(config.body);
|
||
|
|
}
|
||
|
|
|
||
|
|
const response = await fetch(url, config);
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
const text = await response.text();
|
||
|
|
throw new Error(text || `HTTP ${response.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.json();
|
||
|
|
}
|