| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { API_V1, CREDENTIALS } from "../apiContract"; |
| import type { PageEnvelope } from "../ui/types"; |
|
|
| export type PageResult = |
| | { ok: true; page: PageEnvelope } |
| | { ok: false; status: number; code: string; message: string }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| async function asError(res: Response): Promise<PageResult> { |
| let code = ""; |
| let message = ""; |
| try { |
| const body = (await res.json()) as { error?: { code?: string; message?: string } }; |
| code = String(body?.error?.code ?? ""); |
| message = String(body?.error?.message ?? ""); |
| } catch { |
| |
| } |
| if (res.status >= 500) { |
| return { ok: false, status: res.status, code: code || "server_error", |
| message: "Something went wrong on our side. Try again in a moment." }; |
| } |
| const fallback = |
| res.status === 401 ? "Your session has ended. Sign in again." |
| : res.status === 403 ? "This account does not have access to that." |
| : res.status === 404 ? "That page does not exist." |
| : "That request could not be completed."; |
| return { ok: false, status: res.status, code: code || String(res.status), |
| message: message || fallback }; |
| } |
|
|
| export async function fetchPage( |
| key: string, |
| params: Record<string, string> = {} |
| ): Promise<PageResult> { |
| const q = new URLSearchParams(params).toString(); |
| const url = `${API_V1}/pages/${encodeURIComponent(key)}${q ? `?${q}` : ""}`; |
| try { |
| const res = await fetch(url, { credentials: CREDENTIALS }); |
| if (!res.ok) return asError(res); |
| const page = (await res.json()) as PageEnvelope; |
| |
| |
| if (!page || typeof page !== "object" || !Array.isArray(page.blocks)) { |
| return { ok: false, status: 200, code: "bad_envelope", |
| message: "The server sent a page this client could not read." }; |
| } |
| return { ok: true, page }; |
| } catch { |
| |
| return { ok: false, status: 0, code: "offline", |
| message: "The server could not be reached." }; |
| } |
| } |
|
|