File size: 2,375 Bytes
444223c
f1aecd4
d135b0e
 
f1aecd4
d135b0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1aecd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68e4eca
 
 
 
 
 
 
a7114c1
 
 
 
 
f1aecd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31cf797
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const API_BASE = import.meta.env.VITE_API_BASE_URL || (import.meta.env.DEV ? "http://localhost:8000" : "");

const inFlightRequests = new Map();

export const apiRequest = async (endpoint, method = "GET", body = null) => {
    // Deduplicate concurrent in-flight GET requests
    if (method === "GET" && !body) {
        if (inFlightRequests.has(endpoint)) {
            return inFlightRequests.get(endpoint);
        }
        const promise = (async () => {
            try {
                return await _performRequest(endpoint, method, body);
            } finally {
                inFlightRequests.delete(endpoint);
            }
        })();
        inFlightRequests.set(endpoint, promise);
        return promise;
    }

    return _performRequest(endpoint, method, body);
};

const _performRequest = async (endpoint, method = "GET", body = null) => {
    const token = localStorage.getItem("token");
    const headers = {};

    if (!(body instanceof FormData)) {
        headers["Content-Type"] = "application/json";
    }

    if (token) {
        headers["Authorization"] = `Bearer ${token}`;
    }

    const response = await fetch(API_BASE + endpoint, {
        method,
        headers,
        body: body instanceof FormData ? body : body ? JSON.stringify(body) : null,
    });

    // If unauthorized, clear stale token and redirect to login
    if (response.status === 401 && endpoint !== "/auth/login" && endpoint !== "/auth/me") {
        localStorage.removeItem("token");
        window.location.href = "/login";
        return { detail: "Session expired" };
    }

    // 204 No Content — nothing to parse
    if (response.status === 204) {
        return { ok: true };
    }

    return response.json();
};

export const loginRequest = async (email, password) => {
    const formData = new URLSearchParams();
    formData.append("username", email);
    formData.append("password", password);

    const response = await fetch(API_BASE + "/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: formData,
    });

    return response.json();
};

export const demoLoginRequest = async () => {
    const response = await fetch(API_BASE + "/auth/demo-login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
    });

    return response.json();
};