File size: 3,450 Bytes
ec85693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d0f773
ec85693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// script.js
(function () {
    const isLocal = /^(localhost|127\.0\.0\.1)$/.test(location.hostname);
  
    // Current page querystring utilities
    const qs = new URLSearchParams(location.search);
  
    // Optional API base override: ?api=http://localhost:9000
    const override = qs.get("api");
    const saved = localStorage.getItem("API_BASE");
  
    const baseRaw =
      override ||
      saved ||
      // Local dev -> FastAPI on 8000; Prod -> same origin
      (isLocal ? "http://localhost:8000" : location.origin);
  
    if (override) localStorage.setItem("API_BASE", override);
  
    let API_BASE = baseRaw.replace(/\/$/, ""); // trim trailing slash
  
    function buildUrl(path, params) {
      // allow absolute URLs
      const full =
        /^https?:\/\//i.test(path)
          ? path
          : API_BASE + (path.startsWith("/") ? path : "/" + path);
  
      const url = new URL(full);
      console.log("Calling api :",url);
      if (params && typeof params === "object") {
        for (const [k, v] of Object.entries(params)) {
          if (v === undefined || v === null) continue;
          if (Array.isArray(v)) {
            v.forEach((val) => url.searchParams.append(k, String(val)));
          } else {
            url.searchParams.set(k, String(v));
          }
        }
      }
      return url.toString();
    }
  
    async function http(method, path, { params, data, headers, ...rest } = {}) {
      const url = buildUrl(path, params);
      const init = {
        method,
        headers: { Accept: "application/json", ...(headers || {}) },
        ...rest,
      };
  
      if (data instanceof FormData) {
        init.body = data; // let browser set multipart boundary
      } else if (data !== undefined) {
        init.body = JSON.stringify(data);
        init.headers["Content-Type"] = "application/json";
      }
  
      const res = await fetch(url, init);
      if (!res.ok) {
        const text = await res.text();
        throw new Error(`${method} ${url} failed (${res.status}) - ${text}`);
      }
  
      const ct = res.headers.get("content-type") || "";
      return ct.includes("application/json") ? res.json() : res.text();
    }
  
    // ---- Expose globals (usable from any page) ----
    window.API_BASE = API_BASE;
    window.setApiBase = (url) => {
      if (!url) return;
      const norm = url.replace(/\/$/, "");
      localStorage.setItem("API_BASE", norm);
      API_BASE = norm;
      window.API_BASE = norm;
    };
  
    // Build URL: api(path, params?)
    window.api = (path, params) => buildUrl(path, params);
  
    // Simple HTTP helpers
    window.apiGet = (path, params, options) =>
      http("GET", path, { params, ...(options || {}) });
    window.apiPost = (path, data, options) =>
      http("POST", path, { data, ...(options || {}) });
    window.apiPut = (path, data, options) =>
      http("PUT", path, { data, ...(options || {}) });
    window.apiDelete = (path, params, options) =>
      http("DELETE", path, { params, ...(options || {}) });
    window.apiUpload = (path, formData, params, options) =>
      http("POST", path, { params, data: formData, ...(options || {}) });
  
    // Query helpers for the *current page* (read-only)
    window.qs = qs; // URLSearchParams instance
    window.getQueryParam = (name, defVal = null) =>
      qs.has(name) ? qs.get(name) : defVal;
    window.getAllQueryParams = () => Object.fromEntries(qs.entries());
  })();