// Thin fetch wrapper for the Trip Plan REST API (see docs/API.md). // Same-origin, cookies included. Server errors ({error}) become thrown Errors // whose message is the server's human-readable text and `.status` the code. async function request(method, path, body) { const opts = { method, credentials: 'same-origin', headers: {}, }; if (body !== undefined) { opts.headers['Content-Type'] = 'application/json'; opts.body = JSON.stringify(body); } let res; try { res = await fetch(path, opts); } catch (networkErr) { const err = new Error('Network error — is the server running?'); err.cause = networkErr; err.status = 0; throw err; } if (res.status === 204) return null; const text = await res.text(); let data = null; if (text) { try { data = JSON.parse(text); } catch { data = null; } } if (!res.ok) { const message = (data && data.error) || `Request failed (${res.status})`; const err = new Error(message); err.status = res.status; err.body = data; throw err; } return data; } const get = (p) => request('GET', p); const post = (p, b) => request('POST', p, b); const patch = (p, b) => request('PATCH', p, b); const del = (p) => request('DELETE', p); export const api = { auth: { // Mullvad-style: create an account (server returns the one-time token). createAccount: () => post('/api/auth/account', {}), login: (token) => post('/api/auth/login', { token }), logout: () => post('/api/auth/logout'), me: () => get('/api/auth/me'), updateMe: (patchBody) => patch('/api/auth/me', patchBody), }, trips: { list: () => get('/api/trips'), create: (payload) => post('/api/trips', payload), get: (id) => get(`/api/trips/${id}`), update: (id, patchBody) => patch(`/api/trips/${id}`, patchBody), remove: (id) => del(`/api/trips/${id}`), join: (code) => post('/api/trips/join', { code }), regenerateJoinCode: (id) => post(`/api/trips/${id}/join-code`, {}), removeMember: (id, userId) => del(`/api/trips/${id}/members/${userId}`), route: (id) => get(`/api/trips/${id}/route`), costs: (id) => get(`/api/trips/${id}/costs`), }, entries: { create: (tripId, payload) => post(`/api/trips/${tripId}/entries`, payload), update: (id, patchBody) => patch(`/api/entries/${id}`, patchBody), remove: (id) => del(`/api/entries/${id}`), }, geocode: (q) => get(`/api/geocode?q=${encodeURIComponent(q)}`), airports: (q) => get(`/api/airports?q=${encodeURIComponent(q)}`), }; export default api;