The Appview for the kipclip.com atproto bookmarking service
1/**
2 * Centralized API client with automatic 401 handling
3 * When a 401 response is received, the session is cleared and the user is redirected to login
4 */
5
6/**
7 * Enhanced fetch that handles 401 responses automatically
8 * Clears local session state and reloads the page to trigger login flow
9 */
10export async function apiFetch(
11 url: string,
12 options?: RequestInit,
13): Promise<Response> {
14 const response = await fetch(url, options);
15
16 // If we get a 401, the session has expired
17 if (response.status === 401) {
18 console.warn("Session expired, redirecting to login");
19
20 // Clear any local session state
21 try {
22 // Trigger a page reload which will check session and show login
23 globalThis.location.href = "/";
24 } catch (error) {
25 console.error("Failed to redirect after session expiry:", error);
26 }
27
28 // Return the response anyway for consistency
29 return response;
30 }
31
32 return response;
33}
34
35/**
36 * Helper for GET requests
37 */
38export function apiGet(url: string): Promise<Response> {
39 return apiFetch(url);
40}
41
42/**
43 * Helper for POST requests
44 */
45export function apiPost(
46 url: string,
47 body?: any,
48): Promise<Response> {
49 return apiFetch(url, {
50 method: "POST",
51 headers: {
52 "Content-Type": "application/json",
53 },
54 body: body ? JSON.stringify(body) : undefined,
55 });
56}
57
58/**
59 * Helper for PATCH requests
60 */
61export function apiPatch(
62 url: string,
63 body?: any,
64): Promise<Response> {
65 return apiFetch(url, {
66 method: "PATCH",
67 headers: {
68 "Content-Type": "application/json",
69 },
70 body: body ? JSON.stringify(body) : undefined,
71 });
72}
73
74/**
75 * Helper for PUT requests
76 */
77export function apiPut(
78 url: string,
79 body?: any,
80): Promise<Response> {
81 return apiFetch(url, {
82 method: "PUT",
83 headers: {
84 "Content-Type": "application/json",
85 },
86 body: body ? JSON.stringify(body) : undefined,
87 });
88}
89
90/**
91 * Helper for DELETE requests
92 */
93export function apiDelete(url: string): Promise<Response> {
94 return apiFetch(url, {
95 method: "DELETE",
96 });
97}