UNPKG

anrom-jive-app-tools

Version:
430 lines (335 loc) 14.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ContinuousLoadJiveOSAPI = exports.ContinuousLoadJiveREST = exports.ContinuousLoader = undefined; var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _fetchPromise = require('./fetchPromise'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* * Continuous loader designed to abstract loading content lists by any asynchronous API in cases * when said API doesn't support filtering parameters by which you want to filter this content. */ var ContinuousLoader = exports.ContinuousLoader = function () { (0, _createClass3.default)(ContinuousLoader, [{ key: 'getError', // Overrideable method that gets error from API response value: function getError(asyncFunctionResponse) { return asyncFunctionResponse.error || false; } // Overrideable method that gets content list from API response }, { key: 'getList', value: function getList(asyncFunctionResponse) { return asyncFunctionResponse.list || []; } /** * Overrideable method to create new promise-returning function * @param asyncFunctionResponse * @returns {function|boolean} - should return async function (one that returns promise), * NOT promise itself */ }, { key: 'getNextAsyncFunc', value: function getNextAsyncFunc(asyncFunctionResponse) { console.warn('getNextAsyncFunc should be defined in either options or child class'); return false; } /** * Constructs a class instance * @param {function} asyncFunction - should return Promise * @param {function} filter - should return array * @param {object} [options] */ }]); function ContinuousLoader(asyncFunction, filter) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; (0, _classCallCheck3.default)(this, ContinuousLoader); var optionsDefaults = { debug: false, targetCount: 10, maxTriesPerLoad: 5, getNextAsyncFunc: this.getNextAsyncFunc.bind(this), getError: this.getError.bind(this), getList: this.getList.bind(this) }; this.options = (0, _extends3.default)({}, optionsDefaults, options); this.asyncFunction = asyncFunction; this.filter = filter; this.resultPool = []; this.endReached = false; } (0, _createClass3.default)(ContinuousLoader, [{ key: '_recursiveLoad', value: function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(resolve, reject, loadCount) { var asyncFunctionResponse, _options, getError, getList, getNextAsyncFunc, targetCount, maxTriesPerLoad, error, list, filteredList, nextAsyncFunc; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return this.asyncFunction(); case 3: asyncFunctionResponse = _context.sent; _options = this.options, getError = _options.getError, getList = _options.getList, getNextAsyncFunc = _options.getNextAsyncFunc, targetCount = _options.targetCount, maxTriesPerLoad = _options.maxTriesPerLoad; this._log('asyncFunctionResponse', asyncFunctionResponse); // catch errors error = getError(asyncFunctionResponse); if (!error) { _context.next = 9; break; } throw new Error(error); case 9: //getting list list = getList(asyncFunctionResponse); //if unfiltered list is empty - means nothing to load // returning the rest of result poll (if any) and blocking // further calls of this.loadNext if (list.length) { _context.next = 15; break; } this._log('zero items get, returning []/rest of pool'); this.endReached = true; resolve({ list: this.resultPool.splice(0), reason: 'source ended' }); return _context.abrupt('return', null); case 15: _context.next = 17; return this.filter(list, [].concat((0, _toConsumableArray3.default)(this.resultPool))); case 17: filteredList = _context.sent; this.resultPool = this.resultPool.concat(filteredList); // getting possible next poll - this should be done before first possible // contentful resolve() nextAsyncFunc = getNextAsyncFunc(asyncFunctionResponse); if (typeof nextAsyncFunc === 'function') { this.asyncFunction = nextAsyncFunc; } else { this.endReached = true; } //if pool reached target number - resolve items and remove them from pool if (!(this.resultPool.length >= targetCount)) { _context.next = 26; break; } this._log('pool reached the target count. set pause.'); resolve({ list: this.resultPool.splice(0, targetCount), reason: 'reached target count' }); this._log('(rest of pool:', this.resultPool); return _context.abrupt('return', null); case 26: loadCount++; if (!(maxTriesPerLoad > 0 && loadCount >= maxTriesPerLoad)) { _context.next = 33; break; } // if pool hasn't reached the target number, but it's last poll according to // maxTriesPerLoad this._log('max tries reached. returning what\'s found so far'); resolve({ list: this.resultPool.splice(0), reason: 'max polls reached' }); return _context.abrupt('return', null); case 33: if (this.endReached) { _context.next = 39; break; } //if pool hasn't reached target number, but there's more to load this._log('got', this.resultPool.length, 'while target is', targetCount, 'need to load one more time'); this._recursiveLoad(resolve, reject, loadCount); return _context.abrupt('return', null); case 39: this._log('no next promise available. returning pool'); resolve({ list: this.resultPool.splice(0), reason: 'source ended' }); case 41: _context.next = 46; break; case 43: _context.prev = 43; _context.t0 = _context['catch'](0); reject(_context.t0); case 46: case 'end': return _context.stop(); } } }, _callee, this, [[0, 43]]); })); function _recursiveLoad(_x2, _x3, _x4) { return _ref.apply(this, arguments); } return _recursiveLoad; }() }, { key: 'loadNext', value: function loadNext(loadOptions) { var _this = this; return new _promise2.default(function (resolve, reject) { var targetCount = _this.options.targetCount; if (_this.resultPool.length >= targetCount) { _this._log('target count found in existing pool'); resolve({ list: _this.resultPool.splice(0, targetCount), reason: 'target count exists in pool' }); return null; } if (_this.endReached) { if (_this.resultPool.length) { _this._log('no next promise available. returning pool'); resolve({ list: _this.resultPool.splice(0), reason: 'source ended' }); } else { _this._log('end was already reached before, no more polling'); resolve({ list: [], reason: 'polling finished' }); } return null; } _this._recursiveLoad(resolve, reject, 0); }); } }, { key: '_log', value: function _log() { if (this.options.debug) { var _console; (_console = console).log.apply(_console, arguments); } } }]); return ContinuousLoader; }(); var ContinuousLoadJiveREST = exports.ContinuousLoadJiveREST = function (_ContinuousLoader) { (0, _inherits3.default)(ContinuousLoadJiveREST, _ContinuousLoader); (0, _createClass3.default)(ContinuousLoadJiveREST, [{ key: 'getList', value: function getList(asyncFunctionResponse) { //this._log('REST getList') var responseContent = asyncFunctionResponse.content || asyncFunctionResponse; return responseContent.list || []; } }, { key: 'getError', value: function getError(asyncFunctionResponse) { //this._log('REST getError') if (asyncFunctionResponse.status) { switch (asyncFunctionResponse.status) { case 200: return false; case 204: return '204: No Content'; default: return asyncFunctionResponse.status; } } return false; } }, { key: 'getNextAsyncFunc', value: function getNextAsyncFunc(asyncFunctionResponse) { var responseContent = asyncFunctionResponse.content || asyncFunctionResponse; var itemsPerPage = responseContent.itemsPerPage, list = responseContent.list, links = responseContent.links; if (!responseContent.links || !responseContent.links.next || list.length < itemsPerPage && !this.options.loose) { // there's nothing to load more return false; } return this.options.createNextAsyncFunc(links.next, responseContent); } }, { key: 'createNextAsyncFunc', value: function createNextAsyncFunc(nextLink, responseContent) { var _this3 = this; return function () { var link = nextLink.split('api/core/v3')[1]; if (_this3.options.method.toLowerCase() === 'get') return (0, _fetchPromise.promiseRestGet)(link); if (_this3.options.method.toLowerCase() === 'post') return (0, _fetchPromise.promiseRestPost)(link); }; } }]); function ContinuousLoadJiveREST(asyncFunction, filter) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; (0, _classCallCheck3.default)(this, ContinuousLoadJiveREST); var _this2 = (0, _possibleConstructorReturn3.default)(this, (ContinuousLoadJiveREST.__proto__ || (0, _getPrototypeOf2.default)(ContinuousLoadJiveREST)).call(this, asyncFunction, filter, options)); var optionsDefaults = { // loose:true means that (list.length < itemsPerPage) doesn't mean list has ended. // Useful for jive REST "/activity" endpoint loose: false, method: 'get', createNextAsyncFunc: _this2.createNextAsyncFunc.bind(_this2) }; _this2.options = (0, _extends3.default)({}, optionsDefaults, _this2.options, options); return _this2; } return ContinuousLoadJiveREST; }(ContinuousLoader); var ContinuousLoadJiveOSAPI = exports.ContinuousLoadJiveOSAPI = function (_ContinuousLoader2) { (0, _inherits3.default)(ContinuousLoadJiveOSAPI, _ContinuousLoader2); function ContinuousLoadJiveOSAPI() { (0, _classCallCheck3.default)(this, ContinuousLoadJiveOSAPI); return (0, _possibleConstructorReturn3.default)(this, (ContinuousLoadJiveOSAPI.__proto__ || (0, _getPrototypeOf2.default)(ContinuousLoadJiveOSAPI)).apply(this, arguments)); } (0, _createClass3.default)(ContinuousLoadJiveOSAPI, [{ key: 'getList', value: function getList(asyncFunctionResponse) { //console.log('REST getList') var responseContent = asyncFunctionResponse.content || asyncFunctionResponse; return responseContent.list || []; } }, { key: 'getNextAsyncFunc', value: function getNextAsyncFunc(asyncFunctionResponse) { if (typeof asyncFunctionResponse.getNextPage === 'function') { return function () { return (0, _fetchPromise.promiseOsapiRequest)(asyncFunctionResponse.getNextPage); }; } return false; } }]); return ContinuousLoadJiveOSAPI; }(ContinuousLoader); exports.default = { ContinuousLoader: ContinuousLoader, ContinuousLoadJiveREST: ContinuousLoadJiveREST, ContinuousLoadJiveOSAPI: ContinuousLoadJiveOSAPI }; //# sourceMappingURL=ContinuousLoader.js.map