Files
bookhoard/web/src/api.ts
T

112 lines
2.6 KiB
TypeScript

import { Alpine } from "./alpine";
import { showToast } from "./toast";
function getAuthHeader(): string {
const token = localStorage.getItem("token");
return token ? `Bearer ${token}` : "";
}
async function apiGet(url: string): Promise<Response> {
return fetch(`/api${url}`, {
headers: {
Authorization: getAuthHeader(),
"Content-Type": "application/json",
},
});
}
async function apiPost(url: string, data?: unknown): Promise<Response> {
return fetch(`/api${url}`, {
method: "POST",
headers: {
Authorization: getAuthHeader(),
"Content-Type": "application/json",
},
body: data ? JSON.stringify(data) : undefined,
});
}
async function apiPut(url: string, data?: unknown): Promise<Response> {
return fetch(`/api${url}`, {
method: "PUT",
headers: {
Authorization: getAuthHeader(),
"Content-Type": "application/json",
},
body: data ? JSON.stringify(data) : undefined,
});
}
async function apiDelete<T extends object>(
url: string,
data?: T,
): Promise<Response> {
return fetch(`/api${url}`, {
method: "DELETE",
headers: {
Authorization: getAuthHeader(),
"Content-Type": "application/json",
},
body: data ? JSON.stringify(data) : undefined,
});
}
async function apiPatch(url: string, data?: unknown): Promise<Response> {
return fetch(`/api${url}`, {
method: "PATCH",
headers: {
Authorization: getAuthHeader(),
"Content-Type": "application/json",
},
body: data ? JSON.stringify(data) : undefined,
});
}
async function handleResponse<T>(response: Response): Promise<T> {
if (!response.ok) {
const errorData = await response
.json()
.catch(() => ({ error: "Unknown error" }));
throw new Error(errorData.error || `HTTP ${response.status}`);
}
return response.json();
}
async function handleVoidResponse(response: Response): Promise<void> {
if (!response.ok) {
const errorData = await response
.json()
.catch(() => ({ error: "Unknown error" }));
throw new Error(errorData.error || `HTTP ${response.status}`);
}
}
function handleError(error: unknown, context: string): void {
console.error(`${context}:`, error);
const message =
error instanceof Error ? error.message : "An unexpected error occurred";
showToast(message, "error");
}
export {
apiGet,
apiPost,
apiPut,
apiDelete,
apiPatch,
handleResponse,
handleVoidResponse,
handleError,
};
Alpine.store("api", {
get: apiGet,
post: apiPost,
put: apiPut,
delete: apiDelete,
patch: apiPatch,
handleResponse: handleResponse,
handleVoidResponse: handleVoidResponse,
handleError: handleError,
});