UNPKG

data-provider-temporary

Version:

Library that helps with server-to-client synchronization of data

280 lines (227 loc) 10.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.withRefetch = withRefetch; exports.withDataProviders = withDataProviders; var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _DataProvider = require('./DataProvider'); var _DataProvider2 = _interopRequireDefault(_DataProvider); var _util = require('./util'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function call(list) { var fn = list[0]; var args = list.slice(1); return fn.apply(undefined, _toConsumableArray(args)); } var idg = new _util.IdGenerator(); var dataProviders = {}; function fetch(dpRef) { var found = null; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _lodash2.default.values(dataProviders)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var dp = _step.value; if (dp.ref === dpRef) { if (found != null) { throw new Error('Multiple data providers with the same ref=' + dpRef); } found = dp; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } if (found == null) { throw new Error('No data provider ref=' + dpRef); } return found.fetch(); } function withRefetch() { return function (Component) { return function (_React$Component) { _inherits(ComponentWithRefetch, _React$Component); function ComponentWithRefetch() { _classCallCheck(this, ComponentWithRefetch); return _possibleConstructorReturn(this, (ComponentWithRefetch.__proto__ || Object.getPrototypeOf(ComponentWithRefetch)).apply(this, arguments)); } _createClass(ComponentWithRefetch, [{ key: 'render', value: function render() { var _this2 = this; return _react2.default.createElement(Component, _extends({ refetch: function refetch(dpRef) { // Make sure context is updated (shouldComponentUpdate of some // parent component might prevent it from being updated) _this2.forceUpdate(); fetch(dpRef); } }, this.props)); } }]); return ComponentWithRefetch; }(_react2.default.Component); }; } function withDataProviders(getConfig) { return function (Component) { var _class, _temp; return _temp = _class = function (_React$Component2) { _inherits(ComponentWithDataProviders, _React$Component2); function ComponentWithDataProviders() { _classCallCheck(this, ComponentWithDataProviders); return _possibleConstructorReturn(this, (ComponentWithDataProviders.__proto__ || Object.getPrototypeOf(ComponentWithDataProviders)).apply(this, arguments)); } _createClass(ComponentWithDataProviders, [{ key: 'getChildContext', value: function getChildContext() { return { dataProviders: _extends({}, this.context.dataProviders, this.dataProviders) }; } }, { key: 'componentWillMount', value: function componentWillMount() { this.id = idg.next(); this.dataProviders = {}; this.handleUpdate(this.props); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { // Make sure context is updated (shouldComponentUpdate of some parent // component might prevent it from being updated) this.forceUpdate(); this.handleUpdate(nextProps); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { for (var dpId in this.dataProviders) { dataProviders[dpId].removeUser(this.id); } } }, { key: 'handleUpdate', value: function handleUpdate(props) { var _this4 = this; var newDataProviders = {}; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { var _loop = function _loop() { var dpConfig = _step2.value; var ref = dpConfig.ref, rawGetData = dpConfig.getData, rawOnData = dpConfig.onData, initialData = dpConfig.initialData, polling = dpConfig.polling, needed = dpConfig.needed; // Look for data provider with this ref among data providers of this // component and data providers of its DOM ancestors var dpId = _lodash2.default.findKey(_extends({}, _this4.context.dataProviders, _this4.dataProviders), function (dpRef) { return _lodash2.default.isEqual(dpRef, ref); }); var dp = void 0; if (dpId == null) { (0, _util.assert)(rawOnData != null && rawGetData != null, 'Parameters onData, getData have to be provided, if data' + ('provider was not defined yet. See DP ' + ref)); dpId = idg.next(); dataProviders[dpId] = new _DataProvider2.default({ id: dpId, ref: ref, rawOnData: rawOnData, onData: function onData(data) { call(rawOnData)(ref, data, _this4.context.dispatch); _this4.forceUpdate(); }, initialData: initialData }); } dp = dataProviders[dpId]; // Changing onData for existing data provider is not currently // supported (0, _util.assert)(rawOnData == null || _lodash2.default.isEqual(rawOnData, dp.rawOnData), 'Provided onData for DP ' + ref + '\n' + rawOnData + '\n' + ('is not equal to previous onData\n' + dp.rawOnData)); // If the data provider was already defined in some DOM ancestor, // require equality on getData (i.e. there can be only one definition // of getData for any tuple of (ref, moment in time, DOM node)) if (_lodash2.default.has(_this4.context.dataProviders, dpId)) { (0, _util.assert)(rawGetData == null || _lodash2.default.isEqual(rawGetData, dp.rawGetData), 'Provided getData for DP ' + ref + '\n' + rawGetData + '\n' + ('is not equal to previous getData\n' + dp.rawGetData)); } dp.updateUser(_this4.id, { polling: polling, needed: needed, rawGetData: rawGetData, getData: function getData() { return call(rawGetData); } }); newDataProviders[dpId] = dp.ref; }; for (var _iterator2 = getConfig(props)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _loop(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } for (var dpId in this.dataProviders) { if (!_lodash2.default.has(newDataProviders, dpId)) { dataProviders[dpId].removeUser(this.id); } } this.dataProviders = newDataProviders; this.forceUpdate(); } }, { key: 'render', value: function render() { var _this5 = this; var show = _lodash2.default.keys(this.dataProviders).every(function (id) { var dp = dataProviders[id]; return !dp.userConfigs[_this5.id].needed || dp.loaded; }); return show ? _react2.default.createElement(Component, this.props) : null; } }]); return ComponentWithDataProviders; }(_react2.default.Component), _class.contextTypes = { dispatch: _propTypes2.default.func.isRequired, dataProviders: _propTypes2.default.object }, _class.childContextTypes = { dataProviders: _propTypes2.default.object }, _temp; }; }