@lyra/base
Version:
Lyra plugin containing the base components and roles for a Lyra configuration
165 lines (126 loc) • 5.54 kB
JavaScript
;
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
};