import * as Q from 'q' import { create as axiosCreate } from 'axios' // import { merge, isEmpty } from 'lodash'; import { StorageBag, Storage} from "@radic/util"; import md5 from "./utils/md5"; export class Api { errorMessages = { 500: `The requested resource doesn't exist!`, 502: `Server error, please try again.`, 401: `You aren't authorized to access this resource.` } $http: Axios.AxiosInstance options = { apiUrl: '', debug : false, axios : {} } cache: StorageBag requests: { [key: string]: any } = {} getParamsHash(params: { [key: string]: any }): string { if(params === undefined) return ''; let objectText = Object.keys(params).map(key => { let val = params[ key ]; if ( typeof val === 'undefined' ) { throw new Error('as this is on key ' + key) } return key + val.toString() }).join(''); return md5(objectText) } constructor(options: any = {}) { _.merge(this.options, options); this.cache = Storage.getOrCreateBag('codex.api.cache', "local"); // cache can store max of 10 (mb). clear it before then if ( parseInt(this.cache.getSize('')) >= 8 ) { this.cache.clear(); } this.$http = axiosCreate(options.axios); //interceptors this.$http.interceptors.request.use(config => { config.url = `${this.options.apiUrl}/${config.url}` return config; }, this.catchInterceptorError); this.$http.interceptors.response.use(response => { this.cache.set(response.config.url + this.getParamsHash(response.config.params), response.data, { expires: 600000 }); return response; }, this.catchInterceptorError); } resolveAndDelay(deferred, data) { setTimeout(() => deferred.resolve(data), this.options.debug ? 500 : 0); } apiCall(path, options: any = {}) { const deferred = Q.defer(); const requestKey = `${this.options.apiUrl}/${path}` + this.getParamsHash(options.params); const cachedObject = this.cache.get(requestKey, {}); //return data from cache if ( ! _.isEmpty(cachedObject) ) { deferred.resolve(cachedObject); } else { if ( this.requests[ requestKey ] === undefined ) { this.requests[ requestKey ] = this.$http.get(path, options); } this.requests[ requestKey ] .then(({ data }) => { delete this.requests[ requestKey ] deferred.resolve(data) }) //this.resolveAndDelay(deferred, data)) .catch(this.catchError); } return deferred.promise; } spreadData(result, spreadMembers) { const data = {}; spreadMembers.forEach((member, i) => { data[ member ] = result[ i ] }); return data; } get(path: string, options: any = {}) { return this.apiCall(path, options); } post(path: string, options: any) { return this.$http.post(path, options); } all(path, spreadMembers) { const deferred = Q.defer(); const apiCalls = path.map(p => this.apiCall(p)); axios.all(apiCalls) .then(result => deferred.resolve(this.spreadData(result, spreadMembers))) .catch(this.catchError); return deferred.promise; } catchInterceptorError(error) { return Promise.reject(error); } catchError(response) { let error = { code : response.status, message: response.message }; const errorMessage = this.errorMessages[ response.status ]; if ( errorMessage ) { error = { code : 500, message: errorMessage }; } Promise.reject(error); } }