UNPKG

react-apollo-graphql

Version:

Get rid of decorators and use Apollo GraphQL queries and mutations in the simple and readable way.

599 lines (487 loc) 20.7 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('prop-types')) : typeof define === 'function' && define.amd ? define(['exports', 'react', 'prop-types'], factory) : (factory((global.GraphQL = global.GraphQL || {}),global.React,global.PropTypes)); }(this, (function (exports,React,PropTypes) { 'use strict'; var React__default = 'default' in React ? React['default'] : React; PropTypes = 'default' in PropTypes ? PropTypes['default'] : PropTypes; var asyncToGenerator = function (fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 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 inherits = function (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; }; var possibleConstructorReturn = function (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; }; var getDataFromTree$$1 = function () { var _ref = asyncToGenerator(regeneratorRuntime.mark(function _callee(element) { var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var Component, props, childContext, child, instance, promises; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: // get type of element Component = element.type; // a functional stateless component or a class if (!(typeof Component === 'function')) { _context.next = 24; break; } // create props props = _extends({}, Component.defaultProps, element.props); childContext = context; child = void 0; if (!(Component.prototype && Component.prototype.isReactComponent)) { _context.next = 19; break; } instance = new Component(props, context); // In case the user doesn't pass these to super in the constructor instance.props = instance.props || props; instance.context = instance.context || context; // Override setState to just change the state, not queue up an update. // (we can't do the default React thing as we aren't mounted "properly" // however, we don't need to re-render as well only support setState in // componentWillMount, which happens *before* render). instance.setState = function (state, cb) { if (typeof state === 'function') { instance.state = _extends({}, instance.state, state(instance.state)); } else { instance.state = _extends({}, instance.state, state); } if (typeof cb === 'function') { cb(); } }; if (instance.componentWillMount) { instance.componentWillMount(); } if (instance.getChildContext) { childContext = _extends({}, context, instance.getChildContext()); } // is this GraphQL component? if (!(element.type === GraphQL)) { _context.next = 15; break; } _context.next = 15; return Promise.all(instance.getObservers().map(function (observer) { return new Promise(function (resolve, reject) { try { var subscription = observer.subscribe({ next: function next(data) { subscription.unsubscribe(); resolve(); }, error: function error() { subscription.unsubscribe(); resolve(); } }); } catch (e) { reject(e); } }); })); case 15: // now call render, we have everything resolved and updated so it should return a child // then call this function on child child = instance.render(); if (element.type === GraphQL) { // unmount GraphQL component so we can clean up subscriptipns instance.componentWillUnmount(); } _context.next = 20; break; case 19: // just a stateless functional child = Component(props, context); case 20: _context.next = 22; return getDataFromTree$$1(child, childContext); case 22: _context.next = 29; break; case 24: if (!(element.props && element.props.children)) { _context.next = 29; break; } promises = []; React.Children.forEach(element.props.children, function (child) { if (child) { promises.push(getDataFromTree$$1(child, context)); } }); _context.next = 29; return Promise.all(promises); case 29: case 'end': return _context.stop(); } } }, _callee, this); })); return function getDataFromTree$$1(_x2) { return _ref.apply(this, arguments); }; }(); // 1 = loading // 2 = setVariables // 3 = fetchMore // 4 = refetch // 6 = poll // 7 = ready // 8 = error var babelPluginFlowReactPropTypes_proptype_DocumentNode = require('graphql').babelPluginFlowReactPropTypes_proptype_DocumentNode || require('prop-types').any; // this is query result from client.query() or client.watchQuery().subscribe({ next }); // TODO determine data field by loading property, so // if loading is false and error is null, then data should be defined as user expects them // if loading is true then data could be nullable // if loading is false and error is Error, then data could be nullable (user can use partial render fir example) // this is current query result (state) of subscription if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_QueryResult', { value: require('prop-types').shape({ data: require('prop-types').any.isRequired, loading: require('prop-types').bool.isRequired, networkStatus: require('prop-types').any.isRequired, stale: require('prop-types').bool.isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_CurrentQueryResult', { value: require('prop-types').shape({ data: require('prop-types').any.isRequired, error: require('prop-types').any, loading: require('prop-types').bool.isRequired, networkStatus: require('prop-types').any.isRequired, partial: require('prop-types').bool }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_Observer', { value: require('prop-types').shape({ complete: require('prop-types').func, error: require('prop-types').func, next: require('prop-types').func }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_Subscription', { value: require('prop-types').shape({ unsubscribe: require('prop-types').func.isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_UpdateQueryOptions', { value: require('prop-types').shape({ variables: require('prop-types').object }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_ModifiableWatchQueryOptions', { value: require('prop-types').shape({ fetchPolicy: require('prop-types').any, notifyOnNetworkStatusChange: require('prop-types').bool, pollInterval: require('prop-types').number, reducer: require('prop-types').any, variables: require('prop-types').shape({}) }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_FetchMoreOptions', { value: require('prop-types').shape({ query: babelPluginFlowReactPropTypes_proptype_DocumentNode, updateQuery: require('prop-types').func.isRequired, variables: require('prop-types').any.isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_SubscribeToMoreOptions', { value: require('prop-types').shape({ document: babelPluginFlowReactPropTypes_proptype_DocumentNode, variables: require('prop-types').shape({}), updateQuery: require('prop-types').func, onError: require('prop-types').func }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_ObservableQuery', { value: require('prop-types').shape({ currentResult: require('prop-types').func.isRequired, fetchMore: require('prop-types').func.isRequired, getLastResult: require('prop-types').func.isRequired, subscribe: require('prop-types').func.isRequired, refetch: require('prop-types').func.isRequired, result: require('prop-types').func.isRequired, setOptions: require('prop-types').func.isRequired, setVariables: require('prop-types').func.isRequired, subscribeToMore: require('prop-types').func.isRequired, startPolling: require('prop-types').func.isRequired, stopPolling: require('prop-types').func.isRequired, updateQuery: require('prop-types').func.isRequired, variables: require('prop-types').shape({}).isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_PureQueryOptions', { value: require('prop-types').shape({ query: babelPluginFlowReactPropTypes_proptype_DocumentNode, variables: require('prop-types').shape({}) }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_MutationQueryReducersMap', { value: require('prop-types').shape({}) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_OperationResultReducerMap', { value: require('prop-types').shape({}) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_DataProxyReadQueryOptions', { value: require('prop-types').shape({ query: babelPluginFlowReactPropTypes_proptype_DocumentNode, variables: require('prop-types').shape({}) }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_DataProxyReadFragmentOptions', { value: require('prop-types').shape({ id: require('prop-types').string.isRequired, fragment: babelPluginFlowReactPropTypes_proptype_DocumentNode, fragmentName: require('prop-types').string, variables: require('prop-types').shape({}) }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_DataProxyWriteQueryOptions', { value: require('prop-types').shape({ data: require('prop-types').any.isRequired, query: babelPluginFlowReactPropTypes_proptype_DocumentNode, variables: require('prop-types').shape({}) }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_DataProxyWriteFragmentOptions', { value: require('prop-types').shape({ data: require('prop-types').any.isRequired, id: require('prop-types').string.isRequired, fragment: babelPluginFlowReactPropTypes_proptype_DocumentNode, fragmentName: require('prop-types').string, variables: require('prop-types').object }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_DataProxy', { value: require('prop-types').shape({ readQuery: require('prop-types').func.isRequired, readFragment: require('prop-types').func.isRequired, writeQuery: require('prop-types').func.isRequired, writeFragment: require('prop-types').func.isRequired }) }); var ApolloError = function (_Error) { inherits(ApolloError, _Error); function ApolloError() { classCallCheck(this, ApolloError); return possibleConstructorReturn(this, _Error.apply(this, arguments)); } return ApolloError; }(Error); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_ApolloClient', { value: require('prop-types').shape({ mutate: require('prop-types').func.isRequired, watchQuery: require('prop-types').func.isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_QueryInitializerOptions', { value: require('prop-types').shape({ hasVariablesChanged: require('prop-types').func.isRequired }) }); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_Queries', { value: require('prop-types').shape({}) }); // not used because of // https://github.com/facebook/flow/issues/3986 // add server side render // on server we have only 1 pass, so we can halt execution on all queries passed to GraphQL // then wait for them to resolve, and call render function and repeat these steps // until we have no more queries to process var GraphQL = function (_React$Component) { inherits(GraphQL, _React$Component); function GraphQL() { var _temp, _this, _ret; classCallCheck(this, GraphQL); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.hasMount = false, _this.observers = {}, _this.state = {}, _this.subscriptions = {}, _this.componentWillReceiveProps = function (nextProps) { // call hasVariablesChanged on all observable queries // and call setVariables() on them if they did not return false Object.keys(_this.observers).forEach(function (key) { var variables = _this.observers[key].options.hasVariablesChanged(_this.props, nextProps); if (variables === false) { return; } if (variables === true) { throw new Error('hasVariablesChanged can\'t return true'); } _this.observers[key].observer.setVariables(variables); }); }, _this.getClient = function () { var clientFromContext = _this.context.client; var clientFromProps = _this.props.client; if (clientFromContext) { return clientFromContext; } else if (clientFromProps) { return clientFromProps; } throw new Error('Please specify apollo client using client prop or provide it using <ApolloProvider />.'); }, _this.getObservers = function () { return Object.keys(_this.observers).map(function (key) { return _this.observers[key].observer; }); }, _this.updateResults = function (key, result) { if (!_this.hasMount) { return; } _this.setState(function (state) { var _babelHelpers$extends; return _extends({}, state, (_babelHelpers$extends = {}, _babelHelpers$extends[key] = result, _babelHelpers$extends)); }); }, _temp), possibleConstructorReturn(_this, _ret); } // somehow this is bug /* static defaultProps = { mutations: {}, queries: {}, };*/ GraphQL.prototype.componentWillMount = function componentWillMount() { var _this2 = this; this.hasMount = true; var props = this.props; var _props = this.props, _props$mutations = _props.mutations, mutations = _props$mutations === undefined ? {} : _props$mutations, _props$queries = _props.queries, queries = _props$queries === undefined ? {} : _props$queries, render = _props.render; var client = this.getClient(); // now process queries in props and assign subscriptions to internal state // so we can ubsubscribe from them on unmount // alse create state so we can update this component's state in response // to observable changes var results = Object.keys(queries).reduce(function (state, key) { var _babelHelpers$extends2; var options = { hasVariablesChanged: function hasVariablesChanged() { return false; } }; // now call query initializer with component's props and client var observer = queries[key](client, props, { hasVariablesChanged: function hasVariablesChanged(fn) { if (typeof fn !== 'function') { throw new Error('hasVariablesChanged for query ' + key + ' must be a function'); } options.hasVariablesChanged = fn; } }); _this2.observers[key] = { options: options, observer: observer }; // subscribe to changes var subscription = observer.subscribe({ next: function next() { return _this2.updateResults(key, observer.currentResult()); }, error: function error() { return _this2.updateResults(key, observer.currentResult()); } }); _this2.subscriptions[key] = subscription; return _extends({}, state, (_babelHelpers$extends2 = {}, _babelHelpers$extends2[key] = observer.currentResult(), _babelHelpers$extends2)); }, {}); this.setState(results); }; GraphQL.prototype.componentWillUnmount = function componentWillUnmount() { var _this3 = this; this.hasMount = false; // unsubscribe from all subscriptions Object.keys(this.subscriptions).forEach(function (key) { _this3.observers[key].observer.stopPolling(); _this3.subscriptions[key].unsubscribe(); }); this.subscriptions = {}; }; GraphQL.prototype.render = function render() { var _this4 = this; var _props2 = this.props, _props2$mutations = _props2.mutations, mutations = _props2$mutations === undefined ? {} : _props2$mutations, render = _props2.render; var client = this.getClient(); // process mutation initializers var initializedMutations = Object.keys(mutations).reduce(function (res, key) { var _babelHelpers$extends3; return _extends({}, res, (_babelHelpers$extends3 = {}, _babelHelpers$extends3[key] = mutations[key](client, _this4.props), _babelHelpers$extends3)); }, {}); return render(this.state, initializedMutations, this.props); }; return GraphQL; }(React__default.Component); GraphQL.contextTypes = { client: PropTypes.object }; GraphQL.propTypes = { client: require('prop-types').any, mutations: require('prop-types').any, queries: require('prop-types').any, render: require('prop-types').func.isRequired }; exports['default'] = GraphQL; exports.getDataFromTree = getDataFromTree$$1; Object.defineProperty(exports, '__esModule', { value: true }); })));