SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
1.8 KB · 38 lines typescript
Raw Blame History
1'use client';2import { ClientApiError } from './client-api';3import type { MultiSeriesResponse } from './types';45/**6 * Browser-side helpers for the platform widgets (download builder estimate, API explorer). Same-origin `/api/v1`.7 */8export async function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {9  const res = await fetch(`/api/v1${path}`, { headers: { accept: 'application/json' }, signal });10  if (!res.ok) throw new ClientApiError(res.status, `API ${res.status}`);11  return (await res.json()) as T;12}1314/** Raw request for the API explorer: returns status, elapsed ms, byte size and the parsed/pretty body. */15export async function rawRequest(path: string, signal?: AbortSignal): Promise<{ status: number; ms: number; bytes: number; text: string; json: unknown | null; contentType: string | null }> {16  const t0 = performance.now();17  const res = await fetch(path, { headers: { accept: 'application/json' }, signal });18  const text = await res.text();19  const ms = Math.round(performance.now() - t0);20  let json: unknown | null = null;21  try {22    json = JSON.parse(text);23  } catch {24    json = null;25  }26  return { status: res.status, ms, bytes: new TextEncoder().encode(text).length, text, json, contentType: res.headers.get('content-type') };27}2829export const clientPlatform = {30  /** Series bundle for row estimates (≤ 20 countries × 12 indicators). */31  seriesBundle: (countries: string[], indicators: string[], q: { from?: number | null; to?: number | null } = {}, signal?: AbortSignal) => {32    const p = new URLSearchParams({ country: countries.join(','), indicator: indicators.join(',') });33    if (q.from != null) p.set('from', String(q.from));34    if (q.to != null) p.set('to', String(q.to));35    return getJson<MultiSeriesResponse>(`/series?${p.toString()}`, signal);36  },37};38