Bing Sun преди 5 години
ревизия
14b9b374c2
Подписан от: sunb GPG ключ ID: F7795F8C590626AB
променени са 1 файла, в които са добавени 197 реда и са изтрити 0 реда
  1. +197
    -0
      src/postgrest.js

+ 197
- 0
src/postgrest.js Целия файл

@@ -0,0 +1,197 @@
/* api wrapper */

// utilities
// generate downloadable csv
const download = (options={}) => {
options.filename = options.filename || 'file'

if (options.type == 'csv') {
let headers = Object.keys(options.data[0])

let body = options.data.map(row => headers.map(key => row[key]).join(',')).join('\n')

options.data = '\ufeff' + headers.join(',') + '\n' + body
options.type = 'text/csv'
} else if (options.type == 'json') {
}

let blob = new Blob([options.data], {type: options.type})
let url = URL.createObjectURL(blob)

if (options.timestamp)
options.filename = options.filename + (new Date()).toLocaleTimeString(undefined, {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false
})

let anchor = document.createElement('a')
anchor.href = url
anchor.target = '_blank'
anchor.download = `${options.filename}.csv`

anchor.click()

URL.revokeObjectURL(url)
anchor.remove()
}

// authentication model
const _make_auth = api_root => {

// members
let _login_name = '', _password = ''
let _token_payload = {}

// methods
let _token = value => {
if (value) localStorage.setItem('token', value)
return localStorage.getItem('token')
}

let _load_token_payload = _ => {
try {
_token_payload = JSON.parse(atob(_token().split('.')[1]))
} catch (e) {
console.log('failed parsing token: ', e)
}
}

let _login = _ => m.request({
method: 'POST',
url: `${api_root}/rpc/login`,
body: {
login_name: _login_name,
password: _password
}}).then(data => {
_token(data)
_load_token_payload()

// TODO set to origin page
m.route.set('/')
}).catch(e => alert(e.response.message))

// initialize
_load_token_payload()

// public methods
return {
login: _login,
signed_in: _ => _token() ? true : false,
payload: _ => _token_payload,
token: _token,
login_name: value => {
if (value) _login_name = value
return _login_name
},
password: value => {
if (value) _password = value
return _password
}
}
}

// main api
const _make_api = (api_root, need_auth=true) => {
// private state
let _root = api_root

// if auth is required
let _auth = need_auth ? _make_auth(api_root) : null

return {
// utilities
download: download,

// expose authentication module
auth: _auth,

// wrap m.request with authentication validation
request: (options = {}) => {
/* normalize arguments */
if (typeof options === 'string') {
options = {url: options}
}

/* normalize url */
if (options.url.startsWith('/'))
options.url = _root + options.url

/* normalize headers */
// 1. check if auth is required
if (need_auth) {
// insert auth header if availible
if (_auth.token()) {
options.headers = {
Authorization: 'Bearer ' + _auth.token(),
...options.headers
}
}
// route to login
else {
m.route.set('/login')
}
}

// 2. return values on Prefer
// if (['POST', 'PATCH'].includes(options.method) && options.headers && !options.headers.Prefer)
if (['POST', 'PATCH'].includes(options.method))
options.config = xhr => {
xhr.setRequestHeader('Prefer', 'return=representation')
return xhr
}

// normalize params: since options.params is an object, it cannot support
// duplicated query keys, while postgrest supports that.
//
// Simply build query string by hand.
if (options.queries) {
// build the query string
let _query_string = options.queries.map(query => {
// prepare the query kv pair and optional operator
let k = query.label
let v = query.value
let op = query.op

// return early if v is empty
if (typeof v == 'undefined' || (!v && v !== 0))
return undefined

if (op == 'like')
v = `*${v}*`
else if (op == 'like.right') {
v = `${v}*`
op = 'like'
} else if (op == 'in')
v = `(${v.join(',')})`
else if (k == 'and') {
v = '(' + v.filter(sub_query => sub_query.value == 0 || sub_query.value).map(sub_query => `${sub_query.label}.${sub_query.op}.${typeof sub_query.value == 'function' ? sub_query.value() : sub_query.value}`).join(',') + ')'
}

return {k: k, v: op ? `${op}.${v}` : v}
}).filter(query => typeof query != 'undefined').map(query => query.k + '=' + encodeURIComponent(query.v)).join('&')

// append query string to url if necessary
if (_query_string)
options.url = options.url + '?' + _query_string

delete options.queries
}

return m.request(options).catch(e => {
if (e.code === 401) {
localStorage.removeItem('token')
m.route.set('/login')
}

throw e
})
}
}
}

export default _make_api('https://api-dev.uidt.net/phanerozoic/v1', false)

Зареждане…
Отказ
Запис