import { ClientResponseError, isXRPCErrorPayload, type XRPCErrorPayload } from "@atcute/client"; import type { BobbinContext, QueryValue, XrpcRequestInit } from "$lib/api/client"; export const buildUrl = ( origin: string, nsid: string, params?: Record ): URL => { const url = new URL(`/xrpc/${nsid}`, `${origin}/`); if (params) { for (const [key, value] of Object.entries(params)) { if (value === undefined) continue; if (Array.isArray(value)) { for (const item of value) url.searchParams.append(key, String(item)); } else { url.searchParams.set(key, String(value)); } } } return url; }; export const toResponseError = async (response: Response): Promise => { let data: XRPCErrorPayload = { error: "XRPCError", message: response.statusText }; try { const body: unknown = await response.json(); if (isXRPCErrorPayload(body)) data = body; } catch { // keeps the status-line fallback for non-json bodies } return new ClientResponseError({ status: response.status, headers: response.headers, data }); }; export const jsonGet = async ( ctx: BobbinContext, nsid: string, params?: Record, init?: XrpcRequestInit ): Promise => { const response = await ctx.fetch(buildUrl(ctx.serviceUrl, nsid, params), { headers: { accept: "application/json", ...init?.headers }, signal: init?.signal }); if (!response.ok) throw await toResponseError(response); return (await response.json()) as T; }; export const jsonPost = async ( ctx: BobbinContext, nsid: string, body: unknown, init?: XrpcRequestInit ): Promise => { const response = await ctx.fetch(buildUrl(ctx.serviceUrl, nsid), { method: "POST", headers: { "content-type": "application/json", accept: "application/json", ...init?.headers }, body: JSON.stringify(body), signal: init?.signal }); if (!response.ok) throw await toResponseError(response); return (await response.json()) as T; }; export const rawGet = async ( ctx: BobbinContext, nsid: string, params?: Record, init?: XrpcRequestInit ): Promise => { const response = await ctx.fetch(buildUrl(ctx.serviceUrl, nsid, params), { headers: init?.headers, signal: init?.signal }); if (!response.ok) throw await toResponseError(response); return response; };