UNPKG

fluro

Version:

Promise based HTTP Fluro client for the browser and node.js

609 lines (421 loc) 25.9 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>fluro.api.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav > <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="access.html">access</a><ul class='methods'><li data-type='method'><a href="access.html#.addEventListener">addEventListener</a></li><li data-type='method'><a href="access.html#.can">can</a></li><li data-type='method'><a href="access.html#.canDeleteItem">canDeleteItem</a></li><li data-type='method'><a href="access.html#.canEditItem">canEditItem</a></li><li data-type='method'><a href="access.html#.canKnowOf">canKnowOf</a></li><li data-type='method'><a href="access.html#.canViewItem">canViewItem</a></li><li data-type='method'><a href="access.html#.has">has</a></li><li data-type='method'><a href="access.html#.isAuthor">isAuthor</a></li><li data-type='method'><a href="access.html#.removeAllListeners">removeAllListeners</a></li><li data-type='method'><a href="access.html#.removeEventListener">removeEventListener</a></li><li data-type='method'><a href="access.html#.retrieveActionableRealms">retrieveActionableRealms</a></li><li data-type='method'><a href="access.html#.retrieveCurrentSession">retrieveCurrentSession</a></li><li data-type='method'><a href="access.html#.setDefaultApplication">setDefaultApplication</a></li></ul></li><li><a href="api.html">api</a><ul class='methods'><li data-type='method'><a href="api.html#.delete">delete</a></li><li data-type='method'><a href="api.html#.generateEndpointURL">generateEndpointURL</a></li><li data-type='method'><a href="api.html#.get">get</a></li><li data-type='method'><a href="api.html#.post">post</a></li><li data-type='method'><a href="api.html#.put">put</a></li></ul></li><li><a href="app.device.html">device</a></li><li><a href="asset.html">asset</a><ul class='methods'><li data-type='method'><a href="asset.html#.avatarUrl">avatarUrl</a></li><li data-type='method'><a href="asset.html#.downloadUrl">downloadUrl</a></li><li data-type='method'><a href="asset.html#.filesize">filesize</a></li><li data-type='method'><a href="asset.html#.getUrl">getUrl</a></li><li data-type='method'><a href="asset.html#.imageUrl">imageUrl</a></li><li data-type='method'><a href="asset.html#.playerUrl">playerUrl</a></li><li data-type='method'><a href="asset.html#.posterUrl">posterUrl</a></li><li data-type='method'><a href="asset.html#.typeFromMime">typeFromMime</a></li></ul></li><li><a href="auth.html">auth</a><ul class='methods'><li data-type='method'><a href="auth.html#.addEventListener">addEventListener</a></li><li data-type='method'><a href="auth.html#.changeAccount">changeAccount</a></li><li data-type='method'><a href="auth.html#.getCurrentToken">getCurrentToken</a></li><li data-type='method'><a href="auth.html#.getCurrentUser">getCurrentUser</a></li><li data-type='method'><a href="auth.html#.impersonate">impersonate</a></li><li data-type='method'><a href="auth.html#.login">login</a></li><li data-type='method'><a href="auth.html#.logout">logout</a></li><li data-type='method'><a href="auth.html#.refreshAccessToken">refreshAccessToken</a></li><li data-type='method'><a href="auth.html#.removeAllListeners">removeAllListeners</a></li><li data-type='method'><a href="auth.html#.removeEventListener">removeEventListener</a></li><li data-type='method'><a href="auth.html#.retrieveUserFromResetToken">retrieveUserFromResetToken</a></li><li data-type='method'><a href="auth.html#.sendResetPasswordRequest">sendResetPasswordRequest</a></li><li data-type='method'><a href="auth.html#.set">set</a></li><li data-type='method'><a href="auth.html#.signup">signup</a></li><li data-type='method'><a href="auth.html#.updateUserWithToken">updateUserWithToken</a></li></ul></li><li><a href="cache.html">cache</a><ul class='methods'><li data-type='method'><a href="cache.html#.get">get</a></li><li data-type='method'><a href="cache.html#.reset">reset</a></li></ul></li><li><a href="components.html">components</a><ul class='methods'><li data-type='method'><a href="components.html#.hydrateModel">hydrateModel</a></li></ul></li><li><a href="content.html">content</a><ul class='methods'><li data-type='method'><a href="content.html#.duplicate">duplicate</a></li><li data-type='method'><a href="content.html#.external">external</a></li><li data-type='method'><a href="content.html#.filter">filter</a></li><li data-type='method'><a href="content.html#.form">form</a></li><li data-type='method'><a href="content.html#.get">get</a></li><li data-type='method'><a href="content.html#.getMultiple">getMultiple</a></li><li data-type='method'><a href="content.html#.keys">keys</a></li><li data-type='method'><a href="content.html#.list">list</a></li><li data-type='method'><a href="content.html#.query">query</a></li><li data-type='method'><a href="content.html#.related">related</a></li><li data-type='method'><a href="content.html#.retrieve">retrieve</a></li><li data-type='method'><a href="content.html#.slug">slug</a></li><li data-type='method'><a href="content.html#.submitInteraction">submitInteraction</a></li><li data-type='method'><a href="content.html#.submitPost">submitPost</a></li><li data-type='method'><a href="content.html#.thread">thread</a></li><li data-type='method'><a href="content.html#.values">values</a></li></ul></li><li><a href="date.html">date</a><ul class='methods'><li data-type='method'><a href="date.html#.countdown">countdown</a></li><li data-type='method'><a href="date.html#.dateFromID">dateFromID</a></li><li data-type='method'><a href="date.html#.formatDate">formatDate</a></li><li data-type='method'><a href="date.html#.getAge">getAge</a></li><li data-type='method'><a href="date.html#.groupEventByDate">groupEventByDate</a></li><li data-type='method'><a href="date.html#.isDifferentTimezoneThanUser">isDifferentTimezoneThanUser</a></li><li data-type='method'><a href="date.html#.isMultiDayEvent">isMultiDayEvent</a></li><li data-type='method'><a href="date.html#.localDate">localDate</a></li><li data-type='method'><a href="date.html#.militaryTimestamp">militaryTimestamp</a></li><li data-type='method'><a href="date.html#.readableEventDate">readableEventDate</a></li><li data-type='method'><a href="date.html#.readableEventTime">readableEventTime</a></li><li data-type='method'><a href="date.html#.timeago">timeago</a></li><li data-type='method'><a href="date.html#.timeline">timeline</a></li><li data-type='method'><a href="date.html#.timestampToAmPm">timestampToAmPm</a></li><li data-type='method'><a href="date.html#.timezones">timezones</a></li></ul></li><li><a href="fluro.html">fluro</a></li><li><a href="types.html">types</a><ul class='methods'><li data-type='method'><a href="types.html#.all">all</a></li><li data-type='method'><a href="types.html#.basicTypes">basicTypes</a></li><li data-type='method'><a href="types.html#.get">get</a></li><li data-type='method'><a href="types.html#.mapDefinitionItems">mapDefinitionItems</a></li><li data-type='method'><a href="types.html#.parentType">parentType</a></li><li data-type='method'><a href="types.html#.postableTypes">postableTypes</a></li><li data-type='method'><a href="types.html#.readable">readable</a></li><li data-type='method'><a href="types.html#.reloadTerminology">reloadTerminology</a></li><li data-type='method'><a href="types.html#.retrieve">retrieve</a></li><li data-type='method'><a href="types.html#.subTypes">subTypes</a></li><li data-type='method'><a href="types.html#.term">term</a></li></ul></li><li><a href="utils.html">utils</a><ul class='methods'><li data-type='method'><a href="utils.html#.arrayIDs">arrayIDs</a></li><li data-type='method'><a href="utils.html#.comma">comma</a></li><li data-type='method'><a href="utils.html#.currencySymbol">currencySymbol</a></li><li data-type='method'><a href="utils.html#.errorMessage">errorMessage</a></li><li data-type='method'><a href="utils.html#.extractFromArray">extractFromArray</a></li><li data-type='method'><a href="utils.html#.formatCurrency">formatCurrency</a></li><li data-type='method'><a href="utils.html#.getDefaultValueForField">getDefaultValueForField</a></li><li data-type='method'><a href="utils.html#.getFlattenedFields">getFlattenedFields</a></li><li data-type='method'><a href="utils.html#.getStringID">getStringID</a></li><li data-type='method'><a href="utils.html#.guid">guid</a></li><li data-type='method'><a href="utils.html#.hash">hash</a></li><li data-type='method'><a href="utils.html#.injectScript">injectScript</a></li><li data-type='method'><a href="utils.html#.machineName">machineName</a></li><li data-type='method'><a href="utils.html#.mapParameters">mapParameters</a></li><li data-type='method'><a href="utils.html#.matchInArray">matchInArray</a></li><li data-type='method'><a href="utils.html#.processCardPrioritySort">processCardPrioritySort</a></li></ul></li><li><a href="video.html">video</a><ul class='methods'><li data-type='method'><a href="video.html#.hhmmss">hhmmss</a></li><li data-type='method'><a href="video.html#.readableMilliseconds">readableMilliseconds</a></li><li data-type='method'><a href="video.html#.readableSeconds">readableSeconds</a></li></ul></li></ul> </nav> <div id="main"> <h1 class="page-title">fluro.api.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import axios from 'axios'; import _ from 'lodash'; import qs from 'qs'; import { cacheAdapterEnhancer, throttleAdapterEnhancer, Cache, } from 'axios-extensions'; const CancelToken = axios.CancelToken; /////////////////////////////////////// /** * Creates a new FluroAPI instance. * This module is a wrapper around the &lt;a href="https://www.npmjs.com/package/axios">axios&lt;/a> package. It aims to make it easier for you to connect with and consume endpoints from the Fluro REST API for more information about the available endpoints see &lt;a href="https://developer.fluro.io">Fluro REST API Documentation&lt;/a> * @alias api * @constructor * @param {FluroCore} fluro A reference to the parent instance of the FluroCore module. The FluroAPI module is usually created by a FluroCore instance that passes itself in as the first argument. */ var FluroAPI = function(fluro) { /////////////////////////////////////// // //Cache Defaults // var FIVE_MINUTES = 1000 * 60 * 5; // var CAPACITY = 100; // { maxAge: FIVE_MINUTES, max: 100 } /** * The default cache to use when requests are made from this instance * @type {LRUCache} * @access private */ var defaultCache; if (process.browser) { defaultCache = fluro.cache.get('api'); } /////////////////////////////////////// //Get the default adapter const defaultAdapter = axios.defaults.adapter // console.log('DEFAULT ADAPTER', defaultAdapter) /////////////////////////////////////// //Add our own adapter to the service let cacheAdapter = function(config) { return new Promise(function(resolve, reject) { var useCache; var cachedResponse; /////////////////////////////////////// //Don't cache action methods switch (String(config.method).toLowerCase()) { case 'post': case 'patch': case 'put': case 'delete': //Unless we've specified we want a cache if (!config.cache) { //Don't use the cache config.cache = false; } break; } /////////////////////////////////////// /////////////////////////////////////// if (config.cache === false) { //No cache so make new request } else { //Use the cache specified or the default cache useCache = config.cache || defaultCache; //If there is a cache if (useCache) { //Generate the cache key from the request var cacheKey = getCacheKeyFromConfig(config); //If we have the cachedResponse version cachedResponse = useCache.get(cacheKey); } } /////////////////////////////////////// /////////////////////////////////////// if (cachedResponse) { // console.log('FROM CACHE', config.url, cachedResponse); return resolve(cachedResponse); } // const axiosWithoutAdapter = createNewAxios(); var copy = Object.assign(config, { adapter: defaultAdapter }); // console.log('NEW ADAPTER THING', copy) // const axiosWithoutAdapter = axios(copy); return axios.request(config) .then(function(res) { // console.log('RESPONSE', res) resolve(res); }, function(err) { // console.log('ERROR', err) reject(err); }); }) } ////////////////////////////////////////////////////////////////////////////// const service = createNewAxios(cacheAdapter); ////////////////////////////////////////////////////////////////////////////// function createNewAxios(adapter) { var instance = axios.create({ paramsSerializer: params => qs.stringify(params, { arrayFormat: 'repeat' }), adapter, // adapter: throttleAdapterEnhancer(cacheAdapterEnhancer(axios.defaults.adapter, { defaultCache: defaultCache })) // adapter: throttleAdapterEnhancer(cacheAdapterEnhancer(axios.defaults.adapter, { defaultCache: defaultCache })) }); /////////////////////////////////////// instance.defaults.baseURL = fluro.apiURL; instance.defaults.headers.common.Accept = 'application/json'; instance.defaults.withCredentials = fluro.withCredentials; ///////////////////////////////////////////////////// // Add relative date and timezone to every request instance.interceptors.request.use(function(config) { config.headers['fluro-request-date'] = new Date().getTime(); if (fluro.date.defaultTimezone) { config.headers['fluro-request-timezone'] = fluro.date.defaultTimezone; } config.headers['fluro-api-version'] = '2.2.28'; // console.log('USER CONTEXT BY DEFAULT?', fluro.userContextByDefault, config.application, config.disableUserContext) //////////////////////// //We aren't using the user context by default if(!fluro.userContextByDefault) { //It's just a normal request and we haven't specified an application if (!config.application || config.disableUserContext) { return config; } } if (!fluro.app) { return config; } //////////////////////// if(fluro.app.uuid) { config.headers['fluro-app-uuid'] = fluro.app.uuid; console.log('request uuid') } //////////////////////// //There's no app or app user defined anyway if (!fluro.app.user) { return config; } //////////////////////// console.log('Request as user', fluro.app.user.firstName); config.headers['Authorization'] = `Bearer ${fluro.app.user.token}`; if(config.params &amp;&amp; config.params.access_token) { delete config.params.access_token; } return config; }); ///////////////////////////////////////////////////// instance.interceptors.response.use(function(response) { var config = response.config var cacheKey = getCacheKeyFromConfig(config); var cache = response.config.cache || defaultCache; ///////////////////////////////////////////////////// if (!cache) { return response; } ///////////////////////////////////////////////////// switch (String(config.method).toLowerCase()) { case 'put': case 'patch': case 'post': case 'delete': var idSource = { _id: (config.data || {})._id, params: config.params, url: config.url, } var ids = retrieveIDs(idSource); cache.forEach(function(value, key, cache) { if(value.data) { value = value.data; // console.log('down one level', value) } var cacheIDs = retrieveIDs({ key, value }); var crossover = _.intersection(cacheIDs, ids).length; if (crossover) { cache.del(key); // console.log('WIPE RELATED KEY', key); } }); break; default: //Save into the cache cache.set(cacheKey, response); break; } ///////////////////////////////////////////////////// return response; }, function(err) { if (axios.isCancel(err)) { console.log('Request cancelled'); return Promise.reject(err); } //Get the response status var status = _.get(err, 'response.status') || err.status; //Check the status switch (status) { case 401: //Ignore and allow fluro.auth to handle it if(fluro.app &amp;&amp; fluro.app.user) { fluro.app.user = null; } break; case 502: // case 503: case 504: //Retry //Try it again console.log(`fluro.api > ${status} connection error retrying`) return instance.request(err.config); break; case 404: break; default: //Some other error console.log('fluro.api > connection error', status, err); break; } ///////////////////////////////////////////////////// return Promise.reject(err); }) ///////////////////////////////////////////////////// return instance; } /////////////////////////////////////// /** * @name api.get * @description Makes a get http request to the Fluro REST API * @function * @param {String} path The Fluro API endpoint to request * @param {Object} config Optional parameters for the request * @example * //Make a request to get the current user session * fluro.api.get('/content/article', { * params:{ * select:'title created', * limit:10, * simple:true, * } * }) * .then(function (response) { * console.log(response); * }) * .catch(function (error) { * console.log(error); * }); */ /** * @name api.post * @description Makes a post http request to the Fluro REST API * @function * @param {String} path The Fluro API endpoint to request * @param {Object} config Optional parameters for the request * @example * * fluro.api.post('/content/article', {title:'my new article', ...}, { * //headers and other things * }) * .then(function (response) { * console.log(response); * }) * .catch(function (error) { * console.log(error); * }); */ /** * @name api.put * @description Makes a put http request to the Fluro REST API * @function * @param {String} path The Fluro API endpoint to request * @param {Object} config Optional parameters for the request * @example * * fluro.api.put('/content/article/5ca3d64dd2bb085eb9d450db', {title:'my new article', ...}, { * //headers and other things * }) * .then(function (response) { * console.log(response); * }) * .catch(function (error) { * console.log(error); * }); */ /** * @name api.delete * @description Makes a delete http request to the Fluro REST API * @function * @param {String} path The Fluro API endpoint to request * @param {Object} config Optional parameters for the request * @example * * fluro.api.delete('/content/article/5ca3d64dd2bb085eb9d450db') * .then(function (response) { * console.log(response); * }) * .catch(function (error) { * console.log(error); * }); */ /////////////////////////////////////////////////// /** * A helper function for generating an authenticated url for the current user * @param {string} endpoint The id of the asset, or the asset object you want to download * @alias api.generateEndpointURL * @param {object} params * @return {string} A full URL with relevant parameters included * @example * // returns 'https://api.fluro.io/something?access_token=2352345...' * fluro.api.generateEndpointURL('/something'); */ service.generateEndpointURL = function(path, params) { if (!path || !String(path).length) { return; } if (!params) { params = {}; } var url = `${fluro.apiURL}${path}`; //////////////////////////////////////// url = parameterDefaults(url, params); //////////////////////////////////////// //Map the parameters to a query string var queryParameters = fluro.utils.mapParameters(params); if (queryParameters.length) { url += '?' + queryParameters; } return url; } /////////////////////////////////////////////////////// function parameterDefaults(url, params) { //If we haven't requested without token if (!params.withoutToken) { //Get the current token from FluroAuth var CurrentFluroToken = fluro.auth.getCurrentToken(); //Check to see if we have a token and none has been explicity set if (!params['access_token'] &amp;&amp; CurrentFluroToken) { //Use the current token by default params['access_token'] = CurrentFluroToken; } } //////////////////////////////////// if (fluro.app &amp;&amp; fluro.app.uuid) { params['did'] = fluro.app.uuid; } return url; } ///////////////////////////////////////////////////// //Get all mongo ids from a string function retrieveIDs(data) { var dataString; if (_.isString(data)) { dataString = data; } else { dataString = JSON.stringify(data); } //Find all mongo ids included in the object var myregexp = /[0-9a-fA-F]{24}/g; var matches = dataString.match(myregexp); //Make sure the matches are unique return _.uniq(matches); } ///////////////////////////////////////////////////// function getCacheKeyFromConfig(config) { var key = _.compact([ config.method, config.url, JSON.stringify({ params: config.params, data: config.data }), fluro.app &amp;&amp; fluro.app.user ? fluro.app.user.persona : '', config.application ? 'application' :'', config.disableUserContext ? 'disableUserContext' :'', ]).join('-') // console.log('GET CACHE KEY', key) return key; } /////////////////////////////////////// service.CancelToken = CancelToken; service.axios = axios; /////////////////////////////////////// return service; } /////////////////////////////////////// /////////////////////////////////////// /////////////////////////////////////// export { CancelToken as CancelToken }; export default FluroAPI;</code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Tue Jun 29 2021 08:38:17 GMT+1000 (Australian Eastern Standard Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> </body> </html>