| async function parseApiError(response){ |
| const text=await response.text(); |
| try{ |
| const data=JSON.parse(text); |
| if(data.detail){ |
| if(typeof data.detail==='string')return data.detail; |
| return JSON.stringify(data.detail); |
| } |
| if(data.error)return String(data.error); |
| return JSON.stringify(data); |
| }catch(_){ |
| return text||`HTTP ${response.status}`; |
| } |
| } |
| function withCacheBust(path){ |
| const sep=path.includes("?")?"&":"?"; |
| return `${path}${sep}_=${Date.now()}`; |
| } |
| async function apiGet(path){ |
| const r=await fetch(withCacheBust(path),{cache:"no-store",headers:{"Accept":"application/json","Cache-Control":"no-cache"}}); |
| if(!r.ok)throw new Error(await parseApiError(r)); |
| return r.json(); |
| } |
| async function apiPost(path,body){ |
| const r=await fetch(path,{method:"POST",cache:"no-store",headers:{"Content-Type":"application/json","Accept":"application/json","Cache-Control":"no-cache"},body:JSON.stringify(body||{})}); |
| if(!r.ok)throw new Error(await parseApiError(r)); |
| return r.json(); |
| } |
|
|
|
|
| async function apiDelete(path,body){ |
| const hasBody=body&&Object.keys(body).length>0; |
| const headers={"Accept":"application/json","Cache-Control":"no-cache"}; |
| if(hasBody)headers["Content-Type"]="application/json"; |
| const r=await fetch(withCacheBust(path),{method:"DELETE",cache:"no-store",headers,body:hasBody?JSON.stringify(body):undefined}); |
| if(!r.ok)throw new Error(await parseApiError(r)); |
| return r.json(); |
| } |
|
|