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