export class API { // query resolves into the JSON data produced by the application, or an exception with 'type' and 'error' properties. static async query(method, path, request) { try { const body = JSON.stringify(request) const headers = {} // Authentication is done with a bearer token. // Here provided to the backend if set. const token = localStorage.getItem('token') if (token) { headers.Authorization = `Bearer ${token}` } const res = await fetch(path, { method, headers, body }) // An HTTP communication level error occured. if (!res.ok || res.status != 200) throw new Error('HTTP error', { cause: { type: 'http', error: res, }}) // Application level response are handled here. const json = await res.json() if (!json.OK) throw new Error(json.Error, { cause: { type: 'application', application: json, }}) return json } catch (err) { // Catch any other errors from fetch. throw new Error(err.message, { cause: { type: 'http', error: err, }}) } } static hasAuthenticationToken() {//{{{ const token = localStorage.getItem('token') return token !== null && token !== '' }//}}} static authenticate(username, password) {//{{{ return new Promise((resolve, reject) => { const req = { username, password } API.query('POST', '/user/authenticate', req) .then(response => { localStorage.setItem('token', response.Token) localStorage.setItem('user', JSON.stringify(response.User)) resolve(response.User) }) .catch(e => { console.log(e.type, e.error) reject(e.error) }) }) }//}}} static logout() {//{{{ localStorage.removeItem('token') location.href = '/' }//}}} }