WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
at a7fd628b7be3e4367a8e63adbc3625421440302c 43 lines 1.3 kB view raw
1import { loadConfig } from "./config.js"; 2 3const config = loadConfig(); 4 5/** 6 * Fetches from the AppView API and returns parsed JSON. 7 * 8 * Throws two distinct error shapes that callers must classify: 9 * - `"AppView network error: ..."` — AppView is unreachable; callers should 10 * return 503 so the user knows to retry. 11 * - `"AppView API error: N ..."` — AppView returned a non-ok HTTP status; 12 * callers should map to an appropriate response (404, 400, 500, etc.). 13 */ 14export async function fetchApi<T>( 15 path: string, 16 options?: { cookieHeader?: string } 17): Promise<T> { 18 const url = `${config.appviewUrl}/api${path}`; 19 const headers: Record<string, string> = {}; 20 if (options?.cookieHeader) { 21 headers["Cookie"] = options.cookieHeader; 22 } 23 let res: Response; 24 try { 25 res = await fetch(url, { headers }); 26 } catch (error) { 27 throw new Error( 28 `AppView network error: ${error instanceof Error ? error.message : String(error)}` 29 ); 30 } 31 if (!res.ok) { 32 throw new Error(`AppView API error: ${res.status} ${res.statusText}`); 33 } 34 let parsed: T; 35 try { 36 parsed = (await res.json()) as T; 37 } catch (error) { 38 throw new Error( 39 `AppView response error: invalid JSON from ${path} (${error instanceof Error ? error.message : String(error)})` 40 ); 41 } 42 return parsed; 43}