first commit
This commit is contained in:
commit
672f0deb6a
18 changed files with 1274 additions and 0 deletions
88
frontend/ts/api.ts
Normal file
88
frontend/ts/api.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
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`);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue