new system prototype
This commit is contained in:
93
website/js/api.js
Normal file
93
website/js/api.js
Normal file
@ -0,0 +1,93 @@
|
||||
const API_BASE = '../api';
|
||||
|
||||
function getToken() {
|
||||
return localStorage.getItem('qdb_token');
|
||||
}
|
||||
|
||||
async function apiFetch(endpoint, options = {}) {
|
||||
const token = getToken();
|
||||
const headers = options.headers || {};
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||
if (!(options.body instanceof FormData)) {
|
||||
headers['Content-Type'] = 'application/json; charset=UTF-8';
|
||||
}
|
||||
|
||||
// Strip .php suffix for clean URLs
|
||||
const cleanEndpoint = endpoint.replace(/\.php(\?|$)/, '$1');
|
||||
const res = await fetch(`${API_BASE}/${cleanEndpoint}`, { ...options, headers });
|
||||
|
||||
if (res.status === 401 || res.status === 403) {
|
||||
const json = await res.json().catch(() => ({}));
|
||||
const errMsg = json.error?.message || json.error || '';
|
||||
if (res.status === 401 || errMsg === 'Invalid or expired token') {
|
||||
localStorage.removeItem('qdb_token');
|
||||
localStorage.removeItem('qdb_user');
|
||||
localStorage.removeItem('qdb_role');
|
||||
window.location.hash = '#/login';
|
||||
throw new Error('Session expired');
|
||||
}
|
||||
throw new Error(errMsg || 'Permission denied');
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap the unified response envelope:
|
||||
* {"ok": true, "data": ...} -> returns { success: true, ...data }
|
||||
* {"ok": false, "error": ...} -> returns { success: false, error: message }
|
||||
* Also supports legacy format for backward compat.
|
||||
*/
|
||||
function unwrap(json) {
|
||||
if (typeof json.ok === 'boolean') {
|
||||
if (json.ok) {
|
||||
const d = json.data || {};
|
||||
return { success: true, ...(Array.isArray(d) ? { items: d } : d) };
|
||||
}
|
||||
return { success: false, error: json.error?.message || 'Unknown error' };
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
export async function apiGet(endpoint) {
|
||||
const res = await apiFetch(endpoint);
|
||||
return unwrap(await res.json());
|
||||
}
|
||||
|
||||
export async function apiPost(endpoint, body) {
|
||||
const res = await apiFetch(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
return unwrap(await res.json());
|
||||
}
|
||||
|
||||
export async function apiPut(endpoint, body) {
|
||||
const res = await apiFetch(endpoint, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
return unwrap(await res.json());
|
||||
}
|
||||
|
||||
export async function apiPatch(endpoint, body) {
|
||||
const res = await apiFetch(endpoint, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
return unwrap(await res.json());
|
||||
}
|
||||
|
||||
export async function apiDelete(endpoint, body) {
|
||||
const res = await apiFetch(endpoint, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
return unwrap(await res.json());
|
||||
}
|
||||
|
||||
export function apiDownloadUrl(endpoint) {
|
||||
const token = getToken();
|
||||
const cleanEndpoint = endpoint.replace(/\.php(\?|$)/, '$1');
|
||||
return `${API_BASE}/${cleanEndpoint}${cleanEndpoint.includes('?') ? '&' : '?'}token=${encodeURIComponent(token)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user