fluro
Version:
Promise based HTTP Fluro client for the browser and node.js
609 lines (421 loc) • 25.9 kB
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 <a href="https://www.npmjs.com/package/axios">axios</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 <a href="https://developer.fluro.io">Fluro REST API Documentation</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 && 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 && 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'] && CurrentFluroToken) {
//Use the current token by default
params['access_token'] = CurrentFluroToken;
}
}
////////////////////////////////////
if (fluro.app && 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 && 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>