88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import type { LinkEntry } from "../../common/lib";
|
|
|
|
const API_BASE = location.hostname == "localhost" || location.hostname == "127.0.0.1" ? "http://localhost:3001" : "";
|
|
|
|
interface ApiResponse<T> {
|
|
success: boolean;
|
|
data?: T;
|
|
error?: string;
|
|
}
|
|
|
|
function getAuthHeader() {
|
|
const password = localStorage.getItem("password");
|
|
if (!password) throw new Error("No password found in localStorage");
|
|
return { "X-Password": password };
|
|
}
|
|
|
|
async function request<T>(url: string, options: RequestInit = {}): Promise<ApiResponse<T>> {
|
|
const headers = { ...options.headers, ...getAuthHeader() };
|
|
let res: Response;
|
|
|
|
try {
|
|
res = await fetch(`${API_BASE}/api/${url}`, { ...options, headers });
|
|
} catch {
|
|
return { success: false, error: "Network error" };
|
|
}
|
|
|
|
let json = null;
|
|
try {
|
|
json = await res.json();
|
|
} catch {
|
|
return { success: false, error: `Server returned status ${res.status}` };
|
|
}
|
|
|
|
if (!res.ok) {
|
|
return {
|
|
success: false,
|
|
error: json?.error || `Request failed with status ${res.status}`
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
data: json as T
|
|
};
|
|
}
|
|
|
|
export async function login(password: string): Promise<ApiResponse<void>> {
|
|
localStorage.setItem("password", password);
|
|
const res = await request<void>(`login`, { method: "POST" });
|
|
return res;
|
|
}
|
|
|
|
export async function logout(): Promise<ApiResponse<void>> {
|
|
localStorage.removeItem("password");
|
|
return { success: true };
|
|
}
|
|
|
|
export async function getLinks(): Promise<ApiResponse<LinkEntry[]>> {
|
|
return request<LinkEntry[]>("links");
|
|
}
|
|
|
|
export async function getLink(id: string): Promise<ApiResponse<LinkEntry>> {
|
|
return request<LinkEntry>(`links/${id}`);
|
|
}
|
|
|
|
export async function createLink(link: Partial<LinkEntry>): Promise<ApiResponse<LinkEntry>> {
|
|
return request<LinkEntry>("links", {
|
|
method: "POST",
|
|
body: JSON.stringify(link),
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
}
|
|
|
|
export async function updateLink(id: string, link: Partial<LinkEntry>): Promise<ApiResponse<LinkEntry>> {
|
|
return request<LinkEntry>(`links/${id}`, {
|
|
method: "PUT",
|
|
body: JSON.stringify(link),
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
}
|
|
|
|
export async function deleteLink(id: string): Promise<ApiResponse<void>> {
|
|
return request<void>(`links/${id}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function getLinkStats(id: string): Promise<ApiResponse<{ clicks: number }>> {
|
|
return request<{ clicks: number }>(`links/${id}/stats`);
|
|
}
|