// Browser-side reader for the same-origin GET /api/feed route. export interface FeedPage { items: unknown[]; nextCursor: string | null; } export class FeedLoadError extends Error { constructor(public readonly signedOut: boolean) { super(signedOut ? "sign_in" : "feed_unavailable"); } } export async function fetchFeedPage( cursor: string | null, fetchImpl: typeof fetch = fetch, ): Promise { const qs = new URLSearchParams({ limit: "20" }); if (cursor) qs.set("cursor", cursor); let res: Response; try { res = await fetchImpl(`/api/feed?${qs.toString()}`, { credentials: "same-origin" }); } catch { throw new FeedLoadError(false); } if (res.status === 401) throw new FeedLoadError(true); if (!res.ok) throw new FeedLoadError(false); try { const body = (await res.json()) as { items?: unknown; nextCursor?: unknown }; return { items: Array.isArray(body.items) ? body.items : [], nextCursor: typeof body.nextCursor === "string" && body.nextCursor ? body.nextCursor : null, }; } catch { throw new FeedLoadError(false); } }