Express + SQLite (node:sqlite, no native build step) family calendar: parent accounts with household invites, per-child calendars with save/duplicate/print, a token-gated read-only kiosk view for tablets, and polling to keep parent and kiosk views in sync. Defaults to port 3007.
30 lines
953 B
JavaScript
30 lines
953 B
JavaScript
const api = {
|
|
async request(method, path, body) {
|
|
const res = await fetch(path, {
|
|
method,
|
|
credentials: 'include',
|
|
headers: body !== undefined ? { 'Content-Type': 'application/json' } : undefined,
|
|
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
});
|
|
|
|
if (res.status === 204) return null;
|
|
|
|
let data = null;
|
|
const text = await res.text();
|
|
if (text) {
|
|
try { data = JSON.parse(text); } catch { data = null; }
|
|
}
|
|
|
|
if (!res.ok) {
|
|
const err = new Error((data && data.error) || `Request failed (${res.status})`);
|
|
err.status = res.status;
|
|
throw err;
|
|
}
|
|
return data;
|
|
},
|
|
get(path) { return this.request('GET', path); },
|
|
post(path, body) { return this.request('POST', path, body === undefined ? {} : body); },
|
|
patch(path, body) { return this.request('PATCH', path, body === undefined ? {} : body); },
|
|
del(path) { return this.request('DELETE', path); },
|
|
};
|