spb/drive Public
SPB Drive — self-hosted personal cloud drive (files, previews, sharing) on the MacLustr cluster.
JavaScript 82.7%
CSS 10.6%
Nunjucks 3.6%
Shell 1.8%
SQL 1.3%
1/**2 * ─────────────────────────────────────────────3 * SPB Drive — Personal Cloud Drive4 * ─────────────────────────────────────────────5 * Author : Simon-Pierre Boucher6 * Contact : contact@spboucher.ai7 * File : src/web/assets/js/api.js8 * Purpose : JSON API client — CSRF header, error normalization9 * License : MIT © Simon-Pierre Boucher10 * ─────────────────────────────────────────────11 */1213/** Perform an API call; throws Error with .code on failure. */14export async function api(path, { method = 'GET', body, raw = false } = {}) {15 const headers = {};16 if (method !== 'GET' && method !== 'HEAD') headers['x-spbdrive-csrf'] = '1';17 if (body !== undefined) headers['content-type'] = 'application/json';18 const res = await fetch(path, {19 method,20 headers,21 body: body !== undefined ? JSON.stringify(body) : undefined,22 credentials: 'same-origin',23 });24 if (res.status === 401) {25 location.href = `/login?next=${encodeURIComponent(location.pathname)}`;26 throw new Error('unauthorized');27 }28 if (raw) return res;29 const data = res.headers.get('content-type')?.includes('json') ? await res.json() : null;30 if (!res.ok) {31 const err = new Error(data?.error?.message ?? `HTTP ${res.status}`);32 err.code = data?.error?.code ?? 'http_error';33 err.status = res.status;34 throw err;35 }36 return data;37}3839export const getJSON = (path) => api(path);40export const post = (path, body) => api(path, { method: 'POST', body });41export const patch = (path, body) => api(path, { method: 'PATCH', body });42export const del = (path) => api(path, { method: 'DELETE' });43