commit
This commit is contained in:
109
public/assets/js/api.js
Normal file
109
public/assets/js/api.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// assets/js/api.js
|
||||
const API = "api.php";
|
||||
|
||||
/** ---- intern: Hilfen ---- */
|
||||
function withTs(url) {
|
||||
const sep = url.includes("?") ? "&" : "?";
|
||||
return `${url}${sep}t=${Date.now()}`; // no-store Absicherung
|
||||
}
|
||||
|
||||
async function parseJsonSafe(res) {
|
||||
const text = await res.text();
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
console.error("API: invalid JSON", { status: res.status, text });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ... oberer Teil unverändert ...
|
||||
|
||||
/** zentraler Fetch-Wrapper: Credentials, no-store, 401→Login */
|
||||
async function apiFetch(url, init = {}) {
|
||||
const res = await fetch(withTs(url), {
|
||||
credentials: "include",
|
||||
cache: "no-store",
|
||||
...init,
|
||||
});
|
||||
if (res.status === 401) {
|
||||
window.location.href = "/login.php";
|
||||
throw new Error("unauthorized");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** ---- Public API ---- */
|
||||
|
||||
/**
|
||||
* Action-Call:
|
||||
* - apiAction('auth.me')
|
||||
* - apiAction('sections.list', { method:'GET', data:{ template_id: 123 } })
|
||||
* - apiAction('templates.create', { method:'POST', data:{ name:'...' } })
|
||||
*/
|
||||
export async function apiAction(
|
||||
action,
|
||||
{ method = "GET", data = null, headers = {} } = {}
|
||||
) {
|
||||
let url = `${API}?action=${encodeURIComponent(action)}`;
|
||||
const init = { method, headers: { ...headers } };
|
||||
|
||||
// GET/HEAD → data als Query-String anhängen (kein Body!)
|
||||
if ((method === "GET" || method === "HEAD") && data && typeof data === "object") {
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
if (v !== undefined && v !== null) params.append(k, String(v));
|
||||
}
|
||||
const qs = params.toString();
|
||||
if (qs) url += `&${qs}`;
|
||||
} else if (data != null) {
|
||||
init.headers["Content-Type"] = "application/json";
|
||||
init.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
const res = await apiFetch(url, init);
|
||||
return await parseJsonSafe(res);
|
||||
}
|
||||
|
||||
// ... Rest (apiList, apiCreate, apiUpdate, apiDelete, toast) unverändert ...
|
||||
|
||||
/**
|
||||
* Listen-Helper für Ressourcen – ruft `${res}.list` auf.
|
||||
* Optional kannst du query-Objekte mitgeben, z.B. { template_id: 123 } für sections.
|
||||
*/
|
||||
export async function apiList(res, query = {}) {
|
||||
const q = new URLSearchParams(query);
|
||||
const qs = q.toString() ? `&${q.toString()}` : "";
|
||||
const r = await apiAction(`${res}.list`, { method: "GET" });
|
||||
// Falls du query serverseitig brauchst (z.B. template_id), nutze eine Action-Variante:
|
||||
// return await apiAction(`${res}.list`, { method:"GET", data: query });
|
||||
return r?.items ?? [];
|
||||
}
|
||||
|
||||
/** GET by id: nur nutzen, wenn du eine `${res}.get`-Action hast */
|
||||
export async function apiGet(res, id) {
|
||||
return await apiAction(`${res}.get`, { method: "GET", data: { id } });
|
||||
}
|
||||
|
||||
/** CREATE / UPDATE / DELETE – sprechen `${res}.create|update|delete` an */
|
||||
export async function apiCreate(res, payload) {
|
||||
return await apiAction(`${res}.create`, { method: "POST", data: payload });
|
||||
}
|
||||
|
||||
export async function apiUpdate(res, id, payload) {
|
||||
return await apiAction(`${res}.update`, { method: "POST", data: { id, ...payload } });
|
||||
}
|
||||
|
||||
export async function apiDelete(res, id) {
|
||||
return await apiAction(`${res}.delete`, { method: "POST", data: { id } });
|
||||
}
|
||||
|
||||
/** optionaler Toast-Fallback (keine harte Abhängigkeit) */
|
||||
export function toast(msg, ok = true, opts = {}) {
|
||||
if (window.Toast?.show) {
|
||||
window.Toast.show(msg, { type: ok ? "success" : "error", duration: 2200, ...opts });
|
||||
} else {
|
||||
(ok ? console.log : console.error)(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user