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
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}