This repository has no description
1import { ClientResponseError, isXRPCErrorPayload, type XRPCErrorPayload } from "@atcute/client";
2import type { BobbinContext, QueryValue, XrpcRequestInit } from "./client";
3
4export const buildUrl = (
5 origin: string,
6 nsid: string,
7 params?: Record<string, QueryValue>
8): URL => {
9 const url = new URL(`/xrpc/${nsid}`, `${origin}/`);
10 if (params) {
11 for (const [key, value] of Object.entries(params)) {
12 if (value === undefined) continue;
13 if (Array.isArray(value)) {
14 for (const item of value) url.searchParams.append(key, String(item));
15 } else {
16 url.searchParams.set(key, String(value));
17 }
18 }
19 }
20 return url;
21};
22
23export const toResponseError = async (response: Response): Promise<ClientResponseError> => {
24 let data: XRPCErrorPayload = { error: "XRPCError", message: response.statusText };
25 try {
26 const body: unknown = await response.json();
27 if (isXRPCErrorPayload(body)) data = body;
28 } catch {
29 // keep the status-line fallback for non-json bodies.
30 }
31 return new ClientResponseError({ status: response.status, headers: response.headers, data });
32};
33
34export const jsonGet = async <T>(
35 ctx: BobbinContext,
36 nsid: string,
37 params?: Record<string, QueryValue>,
38 init?: XrpcRequestInit
39): Promise<T> => {
40 const response = await ctx.fetch(buildUrl(ctx.serviceUrl, nsid, params), {
41 headers: { accept: "application/json", ...init?.headers },
42 signal: init?.signal
43 });
44 if (!response.ok) throw await toResponseError(response);
45 return (await response.json()) as T;
46};
47
48export const rawGet = async (
49 ctx: BobbinContext,
50 nsid: string,
51 params?: Record<string, QueryValue>,
52 init?: XrpcRequestInit
53): Promise<Response> => {
54 const response = await ctx.fetch(buildUrl(ctx.serviceUrl, nsid, params), {
55 headers: init?.headers,
56 signal: init?.signal
57 });
58 if (!response.ok) throw await toResponseError(response);
59 return response;
60};