Initial InfraPulse scaffold

This commit is contained in:
Keith Smith
2026-05-22 17:36:40 -06:00
commit a707186a5e
92 changed files with 6918 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
import type {
Asset,
Incident,
Monitor,
MonitorUpdate,
NotificationChannel,
NotificationChannelCreate,
NotificationChannelUpdate,
User,
WebsiteMonitorCreate,
} from "../types/api";
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000";
export interface LoginResponse {
access_token: string;
token_type: string;
}
async function request<T>(path: string, token?: string, init: RequestInit = {}): Promise<T> {
const headers = new Headers(init.headers);
if (token) {
headers.set("Authorization", `Bearer ${token}`);
}
if (init.body && !headers.has("Content-Type")) {
headers.set("Content-Type", "application/json");
}
const response = await fetch(`${API_BASE_URL}${path}`, { ...init, headers });
if (!response.ok) {
const message = await response.text();
throw new Error(message || `Request failed with ${response.status}`);
}
if (response.status === 204) {
return undefined as T;
}
return (await response.json()) as T;
}
export async function login(email: string, password: string): Promise<LoginResponse> {
const body = new URLSearchParams();
body.set("username", email);
body.set("password", password);
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: "POST",
body,
});
if (!response.ok) {
throw new Error("Invalid email or password");
}
return (await response.json()) as LoginResponse;
}
export const api = {
me: (token: string) => request<User>("/auth/me", token),
assets: (token: string) => request<Asset[]>("/assets", token),
monitors: (token: string) => request<Monitor[]>("/monitors", token),
createWebsiteMonitor: (token: string, payload: WebsiteMonitorCreate) =>
request<Monitor>("/monitors/website", token, {
method: "POST",
body: JSON.stringify(payload),
}),
updateMonitor: (token: string, monitorId: number, payload: MonitorUpdate) =>
request<Monitor>(`/monitors/${monitorId}`, token, {
method: "PATCH",
body: JSON.stringify(payload),
}),
deleteMonitor: (token: string, monitorId: number) =>
request<void>(`/monitors/${monitorId}`, token, {
method: "DELETE",
}),
incidents: (token: string) => request<Incident[]>("/incidents", token),
acknowledgeIncident: (token: string, incidentId: number) =>
request<Incident>(`/incidents/${incidentId}/acknowledge`, token, {
method: "POST",
}),
silenceIncident: (token: string, incidentId: number, minutes = 60) =>
request<Incident>(`/incidents/${incidentId}/silence?minutes=${minutes}`, token, {
method: "POST",
}),
notificationChannels: (token: string) => request<NotificationChannel[]>("/notifications/channels", token),
createNotificationChannel: (token: string, payload: NotificationChannelCreate) =>
request<NotificationChannel>("/notifications/channels", token, {
method: "POST",
body: JSON.stringify(payload),
}),
updateNotificationChannel: (token: string, channelId: number, payload: NotificationChannelUpdate) =>
request<NotificationChannel>(`/notifications/channels/${channelId}`, token, {
method: "PATCH",
body: JSON.stringify(payload),
}),
testNotificationChannel: (token: string, channelId: number) =>
request<{ status: string; message: string }>(`/notifications/channels/${channelId}/test`, token, {
method: "POST",
}),
deleteNotificationChannel: (token: string, channelId: number) =>
request<void>(`/notifications/channels/${channelId}`, token, {
method: "DELETE",
}),
};