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 atb-59-theme-editor 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}