mirror of
https://github.com/Xevion/xevion.dev.git
synced 2026-01-31 20:26:28 -06:00
feat: add admin panel with project and tag management
- Full CRUD interface for projects with GitHub integration and tagging - Real-time event log with expandable metadata viewer - Reusable component library (Badge, Button, Input, Modal, Table, TagPicker) - Server-side API client with Unix socket and HTTP support - JWT-based authentication with Svelte 5 reactive stores - Settings management for social links and site identity - Remove /admin path from tarpit to allow legitimate access
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { getLogger } from "@logtape/logtape";
|
||||
import { env } from "$env/dynamic/private";
|
||||
|
||||
const logger = getLogger(["ssr", "lib", "api"]);
|
||||
|
||||
const upstreamUrl = env.UPSTREAM_URL;
|
||||
const isUnixSocket =
|
||||
upstreamUrl?.startsWith("/") || upstreamUrl?.startsWith("./");
|
||||
const baseUrl = isUnixSocket ? "http://localhost" : upstreamUrl;
|
||||
|
||||
export async function apiFetch<T>(
|
||||
path: string,
|
||||
init?: RequestInit,
|
||||
): Promise<T> {
|
||||
if (!upstreamUrl) {
|
||||
logger.error("UPSTREAM_URL environment variable not set");
|
||||
throw new Error("UPSTREAM_URL environment variable not set");
|
||||
}
|
||||
|
||||
const url = `${baseUrl}${path}`;
|
||||
const method = init?.method ?? "GET";
|
||||
|
||||
const fetchOptions: RequestInit & { unix?: string } = {
|
||||
...init,
|
||||
signal: init?.signal ?? AbortSignal.timeout(30_000),
|
||||
};
|
||||
|
||||
if (isUnixSocket) {
|
||||
fetchOptions.unix = upstreamUrl;
|
||||
}
|
||||
|
||||
logger.debug("API request", {
|
||||
method,
|
||||
url,
|
||||
path,
|
||||
isUnixSocket,
|
||||
upstreamUrl,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch(url, fetchOptions);
|
||||
|
||||
if (!response.ok) {
|
||||
logger.error("API request failed", {
|
||||
method,
|
||||
url,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
});
|
||||
throw new Error(`API error: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
logger.debug("API response", { method, url, status: response.status });
|
||||
return data;
|
||||
} catch (error) {
|
||||
logger.error("API request exception", {
|
||||
method,
|
||||
url,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user