95 lines
2.4 KiB
TypeScript
95 lines
2.4 KiB
TypeScript
import { PUBLIC_API_BASE } from '$env/static/public';
|
|
import type { Cookies } from '@sveltejs/kit';
|
|
import { passthroughSession } from './cookies';
|
|
|
|
export class APIError extends Error {
|
|
readonly code?: string;
|
|
|
|
constructor(
|
|
readonly response: Response,
|
|
body?: { code: string; message: string }
|
|
) {
|
|
super(body?.message ?? response.statusText);
|
|
this.code = body?.code;
|
|
Object.setPrototypeOf(this, APIError.prototype);
|
|
}
|
|
}
|
|
|
|
export type Stringer = { toString(): string };
|
|
export type QuerySerializable = { [key: string | number | symbol]: Stringer | null | undefined };
|
|
|
|
export function withQuery(path: string, query?: QuerySerializable) {
|
|
return query ? `${path}?${asQueryParams(query).toString()}` : path;
|
|
}
|
|
|
|
export function asQueryParams<T extends QuerySerializable>(obj: T) {
|
|
const params = new URLSearchParams();
|
|
for (const key of Object.getOwnPropertyNames(obj)) {
|
|
const value = obj[key];
|
|
if (value == null || typeof value === 'undefined') continue;
|
|
params.append(key, value.toString());
|
|
}
|
|
return params;
|
|
}
|
|
|
|
type Body = { [key: string]: unknown } | object | void;
|
|
export async function apiCall<B extends Body>(
|
|
method: string,
|
|
path: string,
|
|
body?: B,
|
|
cookies?: Cookies
|
|
) {
|
|
const session = cookies?.get('session');
|
|
const response = await fetch(`${PUBLIC_API_BASE}/${path}`, {
|
|
method,
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
Cookie: session ? `session=${session}` : ''
|
|
}
|
|
});
|
|
if (cookies) {
|
|
passthroughSession(response, cookies);
|
|
}
|
|
if (response.ok) {
|
|
return response;
|
|
}
|
|
|
|
// Check for content
|
|
if (response.headers.get('Content-Type')?.includes('application/json')) {
|
|
const body = await response.json();
|
|
throw new APIError(response, body);
|
|
}
|
|
|
|
throw new APIError(response);
|
|
}
|
|
|
|
export async function callJSON<R, B extends Body = void>(
|
|
method: string,
|
|
path: string,
|
|
body?: B,
|
|
cookies?: Cookies
|
|
) {
|
|
return apiCall(method, path, body, cookies).then((response) => response.json() as R);
|
|
}
|
|
|
|
export async function callText<B extends Body = void>(
|
|
method: string,
|
|
path: string,
|
|
body?: B,
|
|
cookies?: Cookies
|
|
) {
|
|
return apiCall(method, path, body, cookies).then((response) => response.text());
|
|
}
|
|
|
|
export async function callBytes<B extends Body = void>(
|
|
method: string,
|
|
path: string,
|
|
body?: B,
|
|
cookies?: Cookies
|
|
) {
|
|
return apiCall(method, path, body, cookies).then((response) => response.blob());
|
|
}
|