const API_BASE = '' // same origin, uses vite proxy in dev export function getToken() { return localStorage.getItem('oil_auth_token') || '' } export function setToken(token) { if (token) localStorage.setItem('oil_auth_token', token) else localStorage.removeItem('oil_auth_token') } function buildHeaders(extra = {}) { const headers = { 'Content-Type': 'application/json', ...extra } const token = getToken() if (token) headers['Authorization'] = 'Bearer ' + token return headers } async function request(path, opts = {}) { const headers = buildHeaders(opts.headers) const res = await fetch(API_BASE + path, { ...opts, headers }) return res } async function requestJSON(path, opts = {}) { const res = await request(path, opts) if (!res.ok) { let msg = `${res.status}` try { const body = await res.json() msg = body.detail || body.message || msg } catch {} const err = new Error(msg) err.status = res.status throw err } return res.json() } // api is callable as api(path, opts) → raw Response // AND has convenience methods: api.get(), api.post(), api.put(), api.delete() function apiFn(path, opts = {}) { return request(path, opts) } apiFn.raw = request apiFn.get = (path) => requestJSON(path) apiFn.post = (path, body) => requestJSON(path, { method: 'POST', body: JSON.stringify(body) }) apiFn.put = (path, body) => requestJSON(path, { method: 'PUT', body: JSON.stringify(body) }) apiFn.del = (path) => requestJSON(path, { method: 'DELETE' }) apiFn.delete = (path) => requestJSON(path, { method: 'DELETE' }) export const api = apiFn