Spaces:
Sleeping
Sleeping
| // 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()); | |
| })(); | |