SPB Git forge
15commits 1branches 0releases
29.7 MBsize
maindefault branch
10 days agolast push
TypeScript 36.3% Python 31.8% Go 18% JavaScript 9.8% Shell 1.9% SQL 1.4% CSS 0.5%
1.6 KB · 56 lines typescript
Raw Blame History
1'use client';23/** Tiny client for /api/admin/* — token lives in sessionStorage only and travels as X-IP-Admin-Token. */4const KEY = 'ip.admin-token';56export function getAdminToken(): string {7  try {8    return window.sessionStorage.getItem(KEY) ?? '';9  } catch {10    return '';11  }12}13export function setAdminToken(token: string) {14  try {15    if (token) window.sessionStorage.setItem(KEY, token);16    else window.sessionStorage.removeItem(KEY);17  } catch {18    /* ignore */19  }20}2122export class AdminError extends Error {23  constructor(24    public status: number,25    public body: unknown,26  ) {27    super(status === 401 ? 'Unauthorized' : `Admin API error ${status}`);28  }29}3031export async function adminFetch<T>(path: string, init?: { method?: string; body?: unknown; params?: Record<string, string | number | undefined> }): Promise<T> {32  const qs = init?.params33    ? '?' +34      Object.entries(init.params)35        .filter(([, v]) => v !== undefined && v !== '')36        .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)37        .join('&')38    : '';39  const res = await fetch(`/api/admin${path}${qs}`, {40    method: init?.method ?? 'GET',41    headers: { 'X-IP-Admin-Token': getAdminToken(), ...(init?.body !== undefined ? { 'Content-Type': 'application/json' } : {}) },42    body: init?.body !== undefined ? JSON.stringify(init.body) : undefined,43    cache: 'no-store',44  });45  if (!res.ok) {46    let body: unknown = null;47    try {48      body = await res.json();49    } catch {50      /* no body */51    }52    throw new AdminError(res.status, body);53  }54  return (await res.json()) as T;55}56