99 lines
3 KiB
JavaScript
99 lines
3 KiB
JavaScript
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, } })
|
|
}
|
|
}
|
|
|
|
// Sends a block of binary data to server.
|
|
static async upload(uuid, data, sentBytes, metadata) {
|
|
try {
|
|
const path = `/sync/file/upload/${uuid}`
|
|
const headers = {
|
|
'X-File-Sent-Bytes': sentBytes,
|
|
'X-File-Total-Bytes': metadata.size,
|
|
}
|
|
|
|
// Metadata is needed for the database.
|
|
// No need to send it every block.
|
|
if (sentBytes === 0) {
|
|
headers['X-File-Name'] = metadata.name
|
|
headers['X-File-Size'] = metadata.size
|
|
headers['X-File-Type'] = metadata.type
|
|
headers['X-File-Modified'] = metadata.modified
|
|
}
|
|
|
|
// 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: 'POST', headers, body: data })
|
|
// 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.
|
|
console.error(err)
|
|
throw new Error(err, { 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 = '/'
|
|
}//}}}
|
|
}
|