// frontend/js/services/api.js var APIClientError = class extends Error { constructor(message, status, code, rawMessageFromServer) { super(message); this.name = "APIClientError"; this.status = status; this.code = code; this.rawMessageFromServer = rawMessageFromServer; } }; var apiPromiseCache = /* @__PURE__ */ new Map(); async function apiFetch(url, options = {}) { const isGetRequest = !options.method || options.method.toUpperCase() === "GET"; const cacheKey = isGetRequest && !options.noCache ? url : null; if (cacheKey && apiPromiseCache.has(cacheKey)) { return apiPromiseCache.get(cacheKey); } const token = localStorage.getItem("bearerToken"); const headers = { "Content-Type": "application/json", ...options.headers }; if (token) { headers["Authorization"] = `Bearer ${token}`; } const requestPromise = (async () => { try { const response = await fetch(url, { ...options, headers }); if (response.status === 401) { if (cacheKey) apiPromiseCache.delete(cacheKey); localStorage.removeItem("bearerToken"); if (window.location.pathname !== "/login") { window.location.href = "/login?error=\u4F1A\u8BDD\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55\u3002"; } throw new APIClientError("Unauthorized", 401, "UNAUTHORIZED", "Session expired or token is invalid."); } if (!response.ok) { let errorData = null; let rawMessage = ""; try { rawMessage = await response.text(); if (rawMessage) { errorData = JSON.parse(rawMessage); } } catch (e) { errorData = { error: { code: "UNKNOWN_FORMAT", message: rawMessage || response.statusText } }; } const code = errorData?.error?.code || "UNKNOWN_ERROR"; const messageFromServer = errorData?.error?.message || rawMessage || "No message provided by server."; const error = new APIClientError( `API request failed: ${response.status}`, response.status, code, messageFromServer ); throw error; } return response; } catch (error) { if (cacheKey) apiPromiseCache.delete(cacheKey); throw error; } })(); if (cacheKey) { apiPromiseCache.set(cacheKey, requestPromise); } return requestPromise; } async function apiFetchJson(url, options = {}) { try { const response = await apiFetch(url, options); const clonedResponse = response.clone(); const jsonData = await clonedResponse.json(); return jsonData; } catch (error) { throw error; } } export { apiFetch, apiFetchJson };