Newer
Older
gn-synapse / frontend / src / api.js
/** Тонкий клиент к API Synapse. Токен — opaque Bearer от gnexus-auth. */

const TOKEN_KEY = "synapse.access_token";

export function getToken() {
  try {
    return localStorage.getItem(TOKEN_KEY) || "";
  } catch {
    return "";
  }
}

export function setToken(token) {
  try {
    localStorage.setItem(TOKEN_KEY, token);
  } catch {
    /* приватный режим — жить без сохранения сессии */
  }
}

export function clearToken() {
  try {
    localStorage.removeItem(TOKEN_KEY);
  } catch {
    /* игнорируем */
  }
}

async function apiFetch(path, options = {}) {
  const headers = { ...(options.headers || {}) };
  const token = getToken();
  if (token) headers.Authorization = `Bearer ${token}`;
  if (options.body) headers["Content-Type"] = "application/json";

  const response = await fetch(path, { ...options, headers });
  if (!response.ok) {
    let detail = response.statusText;
    try {
      const payload = await response.json();
      if (payload.detail) detail = payload.detail;
    } catch {
      /* не JSON — берём statusText */
    }
    const error = new Error(detail);
    error.status = response.status;
    throw error;
  }
  return response.json();
}

export function healthz() {
  return apiFetch("/api/healthz");
}

/** Профиль текущего пользователя. 401 — токена нет/невалиден, 403 — роль ниже admin. */
export function adminMe() {
  return apiFetch("/api/v1/admin/me");
}