UNPKG

@lyra/base

Version:

Lyra plugin containing the base components and roles for a Lyra configuration

165 lines (126 loc) • 5.54 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _union2 = require('lodash/union'); var _union3 = _interopRequireDefault(_union2); 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 _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _operators = require('rxjs/operators'); var _rxjs = require('rxjs'); var _client = require('part:@lyra/base/client'); var _client2 = _interopRequireDefault(_client); var _shallowEquals = require('shallow-equals'); var _shallowEquals2 = _interopRequireDefault(_shallowEquals); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function deprecatedCheck(props, propName, componentName, ...rest) { if (_react2.default.isValidElement(props[propName])) { return new Error(`Passing a React element as ${propName} to ${componentName} is deprecated. Use a function instead.`); } return _propTypes2.default.func.isRequired(props, propName, componentName, ...rest); } function createInitialState() { return { result: null, complete: false, loading: true, error: false }; } function keysEqual(object, otherObject, excludeKeys = []) { const objectKeys = Object.keys(object).filter(key => !excludeKeys.includes(key)); const otherObjectKeys = Object.keys(otherObject).filter(key => !excludeKeys.includes(key)); if (objectKeys.length !== otherObjectKeys.length) { return false; } return (0, _union3.default)(objectKeys, otherObjectKeys).every(key => object[key] === otherObject[key]); } const fetch = (query, params) => (0, _rxjs.defer)(() => _client2.default.observable.fetch(query, params)); class QueryContainer extends _react2.default.Component { constructor(...args) { var _temp; return _temp = super(...args), this.state = createInitialState(), this.refresh = () => { this.subscribe(this.props.query, this.props.params); }, _temp; } componentWillMount() { this.subscribe(this.props.query, this.props.params); } componentWillUnmount() { this.unsubscribe(); } subscribe(query, params) { this.unsubscribe(); const events$ = _client2.default.listen(query, params, { events: ['welcome', 'mutation', 'error', 'reconnect'] }).pipe((0, _operators.share)()); const welcome$ = events$.pipe((0, _operators.filter)(ev => ev.type === 'welcome')); const mutations$ = events$.pipe((0, _operators.filter)(ev => ev.type === 'mutation')); const reconnect$ = events$.pipe((0, _operators.filter)(ev => ev.type === 'reconnect'), (0, _operators.mergeMapTo)((0, _rxjs.throwError)(new Error('Connection lost. Reconnecting…')))); const docs$ = (0, _rxjs.merge)(reconnect$, welcome$.pipe((0, _operators.mergeMapTo)(fetch(query, params))), mutations$.pipe((0, _operators.auditTime)(1000), (0, _operators.switchMapTo)(fetch(query, params)))).pipe((0, _operators.map)(documents => ({ error: null, loading: false, result: { documents } })), (0, _operators.catchError)(err => (0, _rxjs.of)({ error: err, loading: false }))); this._subscription = docs$.subscribe(nextState => this.setState(nextState)); } unsubscribe() { if (this._subscription) { this._subscription.unsubscribe(); } } componentWillReceiveProps(nextProps) { const sameQuery = nextProps.query === this.props.query; const sameParams = (0, _shallowEquals2.default)(nextProps.params, this.props.params); if (!sameQuery || !sameParams) { this.setState(createInitialState()); this.subscribe(nextProps.query, nextProps.params); } } shouldComponentUpdate(nextProps, nextState) { if (!(0, _shallowEquals2.default)(this.state, nextState)) { return true; } if (nextProps.query !== this.props.query || !(0, _shallowEquals2.default)(nextProps.params, this.props.params)) { return true; } return !keysEqual(nextProps, this.props, ['mapFn', 'query', 'params']); } renderDeprecated() { return _react2.default.cloneElement(_react2.default.Children.only(this.props.children), this.props.mapFn(this.state)); } render() { var _props = this.props; const children = _props.children, mapFn = _props.mapFn, rest = _objectWithoutProperties(_props, ['children', 'mapFn']); if (_react2.default.isValidElement(children)) { return this.renderDeprecated(); } if (!children || typeof children !== 'function') { return _react2.default.createElement( 'div', null, 'Invalid usage of QueryContainer. Expected a function as its only child' ); } return children(_extends({}, rest, { onRetry: this.refresh }, mapFn(this.state))); } } exports.default = QueryContainer; QueryContainer.propTypes = { query: _propTypes2.default.string, params: _propTypes2.default.object, mapFn: _propTypes2.default.func, children: deprecatedCheck }; QueryContainer.defaultProps = { mapFn: props => props };