/**
* Client side cache for API requests (get/post)
* @namespace api
* @category api
* @module api-wrapper-cache
* @requires vue-local-storage.js
* */
import storage from '@/plugins/vue-local-storage.js'
import store from '@/store'
import { getQueryStringValue } from '@/utils/querystring'
const shouldLog =
(getQueryStringValue('verbose') || '').includes('1') ||
(getQueryStringValue('verbose') || '').includes('api')
const apiStorage = storage.fromNamespace('api')
export const apiCacheStorage = apiStorage
/**
* Tries to grab JWT from cache (two tries with 1s difference)
* @returns
*/
export function getCachedJWT(url) {
return new Promise(async (resolve, reject) => {
let tries = 0
let start = Date.now()
tryGrabJWT()
async function tryGrabJWT() {
let userInfos = (await apiStorage.localforage.getItem('user_infos')) || {}
let jwt =
userInfos.toClientToken ||
userInfos.token ||
store.state.auth.user_infos.toClientToken ||
store.state.auth.user_infos.token ||
null
if (jwt) {
resolve(jwt)
} else {
if (tries >= 5) {
console.warn(`api-cache: fail to get JWT (${url})`)
resolve(null)
} else {
//Hot-fix: Abort if logout occurs during the try period
if (window._logoutAt && window._logoutAt > start) {
reject(
new Error('LOGOUT_DETECTED_WHILE_RETRIEVING_JWT_FOR_API_REQUEST')
)
return
}
tries = tries + 1
console.warn(`api-cache: Waiting for JWT (${url})...`, tries)
setTimeout(() => tryGrabJWT(), 1000)
}
}
}
})
}
/**
* Will cache API response per URL+JWT if a cache time was specified for that URL (cache-times.json)
*
* @param {*} res
* @todo Cache also null/empty responses? (History APIs)
*/
export async function setCacheFromAPIResponse(url, res, options = {}) {
if (apiStorage.cache && !!res && apiStorage.cache.shouldCache(url)) {
let jwt =
options.jwt || (await getCachedJWT(url + ' (setCacheFromAPIResponse)'))
let isInvalidResponse =
!res.data ||
res.data.error !== undefined ||
res.data === null ||
(res.data instanceof Array && res.data.length === 0)
if (jwt && !isInvalidResponse) {
await apiStorage.cache.set(`${url}__uniq__${jwt}`, {
data: res.data,
status: res.status,
apiHeaders: res.apiHeaders,
})
shouldLog && console.log('setCacheFromAPIResponse:cache:set(done)')
} else {
shouldLog &&
console.log(
'setCacheFromAPIResponse:cache:set(skip-invalid-response)',
{
res,
url,
}
)
}
} else {
shouldLog &&
console.log('setCacheFromAPIResponse:cache:set(skip)', {
url,
hasRes: !!res,
cacheEnabled: !!apiStorage.cache,
})
}
}
/**
* Will retrieve a cached API response per URL+JWT if available (not expired)
* @param {*} url
* @param {Function} options.beforeCacheFetch Will skip cache if false (Boolean)
* @return {Object}
*/
export async function getCacheFromAPIRequestURL(
url,
options = {},
ajaxOptions = {}
) {
if (apiStorage.cache && apiStorage.cache.shouldCache(url)) {
if (options.beforeCacheFetch && options.beforeCacheFetch(url) == false) {
return null
}
let jwt =
ajaxOptions.jwt ||
(await getCachedJWT(url + ' (getCacheFromAPIRequestURL)'))
if (jwt) {
let cached = await apiStorage.cache.get(`${url}__uniq__${jwt}`)
if (cached) {
return cached
}
}
}
return null
}
Source