feat: lodge server, client and admin

This commit is contained in:
hh committed 2026-09-19 23:33:24 +02:00
commit 95fc50e2c2
84 files changed
+7625

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
import { env } from "$env/dynamic/public";
const BASE = env.PUBLIC_API_BASE_URL ?? "/api";
export class ApiError extends Error {
status: number;
constructor(status: number, message: string) {
super(message);
this.status = status;
this.name = "ApiError";
}
}
type Json = Record<string, unknown> | unknown[];
const send = async (
method: string,
path: string,
body?: Json
): Promise<Response> => {
const init: RequestInit = { credentials: "include", method };
if (body !== undefined) {
init.headers = { "Content-Type": "application/json" };
init.body = JSON.stringify(body);
}
const res = await fetch(BASE + path, init);
if (!res.ok) {
const detail = (await res.text()).trim();
throw new ApiError(res.status, detail || res.statusText);
}
return res;
};
const request = async <T>(
method: string,
path: string,
body?: Json
): Promise<T> => {
const res = await send(method, path, body);
if (res.status === 204) {
return undefined as T;
}
return (await res.json()) as T;
};
export const api = {
bytes: async (path: string) =>
new Uint8Array(await (await send("GET", path)).arrayBuffer()),
del: <T>(path: string) => request<T>("DELETE", path),
events: () => new EventSource(`${BASE}/events`, { withCredentials: true }),
get: <T>(path: string) => request<T>("GET", path),
post: <T>(path: string, body?: Json) => request<T>("POST", path, body),
};