UNPKG

react-apollo-graphql

Version:

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

644 lines (497 loc) 25.6 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('prop-types'), require('babel-runtime/regenerator')) : typeof define === 'function' && define.amd ? define(['exports', 'react', 'prop-types', 'babel-runtime/regenerator'], factory) : (factory((global.GraphQL = {}),global.React,global.PropTypes,global._regeneratorRuntime)); }(this, (function (exports,React,PropTypes,_regeneratorRuntime) { 'use strict'; var React__default = 'default' in React ? React['default'] : React; PropTypes = PropTypes && PropTypes.hasOwnProperty('default') ? PropTypes['default'] : PropTypes; _regeneratorRuntime = _regeneratorRuntime && _regeneratorRuntime.hasOwnProperty('default') ? _regeneratorRuntime['default'] : _regeneratorRuntime; 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: if (!(element == null)) { _context.next = 2; break; } return _context.abrupt('return'); case 2: // get type of element Component = element.type; // a functional stateless component or a class if (!(typeof Component === 'function')) { _context.next = 26; break; } // create props props = _extends({}, Component.defaultProps, element.props); childContext = context; child = void 0; if (!(Component.prototype && Component.prototype.isReactComponent)) { _context.next = 21; 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 = 17; break; } _context.next = 17; return Promise.all(instance.getObservers().map(function (observer) { observer.stopPolling(); return new Promise(function (resolve, reject) { try { observer.result().then(function () { return resolve(); }, function () { return resolve(); }); } catch (e) { reject(e); } }); })); case 17: // 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 = 22; break; case 21: // just a stateless functional child = Component(props, context); case 22: _context.next = 24; return getDataFromTree$$1(child, childContext); case 24: _context.next = 31; break; case 26: if (!(element.props && element.props.children)) { _context.next = 31; break; } promises = []; React.Children.forEach(element.props.children, function (child) { if (child) { promises.push(getDataFromTree$$1(child, context)); } }); _context.next = 31; return Promise.all(promises); case 31: case 'end': return _context.stop(); } } }, _callee, this); })); return function getDataFromTree$$1(_x2) { return _ref.apply(this, arguments); }; }(); var babelPluginFlowReactPropTypes_proptype_DocumentNode = require('graphql').babelPluginFlowReactPropTypes_proptype_DocumentNode || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_WatchQueryOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_WatchQueryOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_UpdateQueryOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_UpdateQueryOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_Subscription = require('apollo-client').babelPluginFlowReactPropTypes_proptype_Subscription || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_SubscribeToMoreOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_SubscribeToMoreOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ObservableQuery = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ObservableQuery || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_NetworkStatus = require('apollo-client').babelPluginFlowReactPropTypes_proptype_NetworkStatus || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ModifiableWatchQueryOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ModifiableWatchQueryOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_FetchPolicy = require('apollo-client').babelPluginFlowReactPropTypes_proptype_FetchPolicy || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_FetchMoreQueryOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_FetchMoreQueryOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_FetchMoreOptions = require('apollo-client').babelPluginFlowReactPropTypes_proptype_FetchMoreOptions || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ApolloQueryResult = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ApolloQueryResult || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ApolloExecutionResult = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ApolloExecutionResult || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ApolloError = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ApolloError || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ApolloCurrentResult = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ApolloCurrentResult || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_ApolloClient = require('apollo-client').babelPluginFlowReactPropTypes_proptype_ApolloClient || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_FragmentInitializerResult = require('prop-types').oneOfType([typeof T === 'function' ? require('prop-types').instanceOf(T) : require('prop-types').any, require('prop-types').oneOf([false])]); if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_FragmentInitializerResult', { value: babelPluginFlowReactPropTypes_proptype_FragmentInitializerResult, configurable: true }); var babelPluginFlowReactPropTypes_proptype_FragmentResult = typeof T === 'function' ? require('prop-types').instanceOf(T) : require('prop-types').any; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_FragmentResult', { value: babelPluginFlowReactPropTypes_proptype_FragmentResult, configurable: true }); var babelPluginFlowReactPropTypes_proptype_QueryResult = babelPluginFlowReactPropTypes_proptype_ApolloQueryResult === require('prop-types').any ? {} : babelPluginFlowReactPropTypes_proptype_ApolloQueryResult; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_QueryResult', { value: babelPluginFlowReactPropTypes_proptype_QueryResult, configurable: true }); var babelPluginFlowReactPropTypes_proptype_MutationResult = babelPluginFlowReactPropTypes_proptype_ApolloExecutionResult === require('prop-types').any ? {} : babelPluginFlowReactPropTypes_proptype_ApolloExecutionResult; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_MutationResult', { value: babelPluginFlowReactPropTypes_proptype_MutationResult, configurable: true }); var babelPluginFlowReactPropTypes_proptype_CurrentQueryResult = { data: typeof T === 'function' ? require('prop-types').instanceOf(T).isRequired : require('prop-types').any.isRequired, error: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType) : require('prop-types').any, loading: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, networkStatus: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, partial: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType) : require('prop-types').any }; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_CurrentQueryResult', { value: babelPluginFlowReactPropTypes_proptype_CurrentQueryResult, configurable: true }); var babelPluginFlowReactPropTypes_proptype_ReactApolloGraphQLObservableQuery = { options: typeof babelPluginFlowReactPropTypes_proptype_WatchQueryOptions === 'function' ? babelPluginFlowReactPropTypes_proptype_WatchQueryOptions.isRequired ? babelPluginFlowReactPropTypes_proptype_WatchQueryOptions.isRequired : babelPluginFlowReactPropTypes_proptype_WatchQueryOptions : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_WatchQueryOptions).isRequired, queryId: require('prop-types').string.isRequired, variables: require('prop-types').shape({}).isRequired, result: require('prop-types').func.isRequired, currentResult: require('prop-types').func.isRequired, getLastResult: require('prop-types').func.isRequired, refetch: require('prop-types').func.isRequired, fetchMore: require('prop-types').func.isRequired, subscribeToMore: require('prop-types').func.isRequired, setOptions: require('prop-types').func.isRequired, setVariables: require('prop-types').func.isRequired, updateQuery: require('prop-types').func.isRequired, stopPolling: require('prop-types').func.isRequired, startPolling: require('prop-types').func.isRequired }; /* * Helper type used if you need to annotate type for arguments passed from render queries arg */ if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_ReactApolloGraphQLObservableQuery', { value: babelPluginFlowReactPropTypes_proptype_ReactApolloGraphQLObservableQuery, configurable: true }); var babelPluginFlowReactPropTypes_proptype_ResultTypeToResultObject = { data: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, error: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, loading: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, networkStatus: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired, observer: require('prop-types').shape({ options: typeof babelPluginFlowReactPropTypes_proptype_WatchQueryOptions === 'function' ? babelPluginFlowReactPropTypes_proptype_WatchQueryOptions.isRequired ? babelPluginFlowReactPropTypes_proptype_WatchQueryOptions.isRequired : babelPluginFlowReactPropTypes_proptype_WatchQueryOptions : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_WatchQueryOptions).isRequired, queryId: require('prop-types').string.isRequired, variables: require('prop-types').shape({}).isRequired, result: require('prop-types').func.isRequired, currentResult: require('prop-types').func.isRequired, getLastResult: require('prop-types').func.isRequired, refetch: require('prop-types').func.isRequired, fetchMore: require('prop-types').func.isRequired, subscribeToMore: require('prop-types').func.isRequired, setOptions: require('prop-types').func.isRequired, setVariables: require('prop-types').func.isRequired, updateQuery: require('prop-types').func.isRequired, stopPolling: require('prop-types').func.isRequired, startPolling: require('prop-types').func.isRequired }).isRequired, partial: typeof $PropertyType === 'function' ? require('prop-types').instanceOf($PropertyType).isRequired : require('prop-types').any.isRequired }; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_ResultTypeToResultObject', { value: babelPluginFlowReactPropTypes_proptype_ResultTypeToResultObject, configurable: true }); var babelPluginFlowReactPropTypes_proptype_QueryInitializerOptions = { hasVariablesChanged: require('prop-types').func.isRequired }; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_QueryInitializerOptions', { value: babelPluginFlowReactPropTypes_proptype_QueryInitializerOptions, configurable: true }); var babelPluginFlowReactPropTypes_proptype_Queries = {}; if (typeof exports !== 'undefined') Object.defineProperty(exports, 'babelPluginFlowReactPropTypes_proptype_Queries', { value: babelPluginFlowReactPropTypes_proptype_Queries, configurable: true }); // 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(props, context) { classCallCheck(this, GraphQL); var _this = possibleConstructorReturn(this, _React$Component.call(this, props, context)); _initialiseProps.call(_this); var _this$props = _this.props, _this$props$fetchers = _this$props.fetchers, fetchers = _this$props$fetchers === undefined ? {} : _this$props$fetchers, _this$props$fragments = _this$props.fragments, fragments = _this$props$fragments === undefined ? {} : _this$props$fragments, _this$props$mutations = _this$props.mutations, mutations = _this$props$mutations === undefined ? {} : _this$props$mutations, _this$props$queries = _this$props.queries, queries = _this$props$queries === undefined ? {} : _this$props$queries, render = _this$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 Object.keys(queries).forEach(function (key) { 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; } }); _this.observers[key] = { options: options, observer: observer }; // subscribe to changes var subscription = observer.subscribe({ next: function next() { return _this.forceRerender(); }, error: function error() { return _this.forceRerender(); } }); _this.subscriptions[key] = subscription; }); _this.initializeFetchers(fetchers, _this.props); _this.initializeMutations(mutations, _this.props); _this.fetchFragments(fragments, _this.props); return _this; } // somehow this is bug /* static defaultProps = { mutations: {}, queries: {}, };*/ GraphQL.prototype.componentWillMount = function componentWillMount() { this.hasMount = true; }; GraphQL.prototype.componentWillUnmount = function componentWillUnmount() { var _this2 = this; this.hasMount = false; // unsubscribe from all subscriptions Object.keys(this.subscriptions).forEach(function (key) { _this2.observers[key].observer.stopPolling(); _this2.subscriptions[key].unsubscribe(); }); this.subscriptions = {}; }; GraphQL.prototype.render = function render() { var _this3 = this; var _props = this.props, _props$fetchers = _props.fetchers, fetchers = _props$fetchers === undefined ? {} : _props$fetchers, render = _props.render; var client = this.getClient(); var queries = Object.keys(this.observers).reduce(function (res, key) { var _babelHelpers$extends; return _extends({}, res, (_babelHelpers$extends = {}, _babelHelpers$extends[key] = _extends({ observer: _this3.observers[key].observer }, _this3.observers[key].observer.currentResult()), _babelHelpers$extends)); }, {}); return render(queries, this.mutations, this.fetchers, this.fragments, this.props); }; return GraphQL; }(React__default.Component); GraphQL.contextTypes = { client: PropTypes.object }; var _initialiseProps = function _initialiseProps() { var _this4 = this; this.fragments = {}; this.fragmentsProps = {}; this.fetchers = {}; this.hasMount = false; this.mutations = {}; this.observers = {}; 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(_this4.observers).forEach(function (key) { var variables = _this4.observers[key].options.hasVariablesChanged(_this4.props, nextProps); if (variables === false) { return; } if (variables === true) { throw new Error('hasVariablesChanged can\'t return true'); } _this4.observers[key].observer.setVariables(variables); }); // reinitialize mutations _this4.initializeMutations(nextProps.mutations, nextProps); // reinitialize fetchers _this4.initializeFetchers(nextProps.fetchers, nextProps); // fetch fragments _this4.fetchFragments(nextProps.fragments, nextProps); }; this.getClient = function () { var clientFromContext = _this4.context.client; var clientFromProps = _this4.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(_this4.observers).map(function (key) { return _this4.observers[key].observer; }); }; this.fetchFragments = function () { var fragments = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var props = arguments[1]; var client = _this4.getClient(); _this4.fragments = Object.keys(fragments).reduce(function (results, fragmentName) { var _babelHelpers$extends2; var previousProps = _this4.fragmentsProps[fragmentName]; var previousData = _this4.fragments[fragmentName]; var data = null; try { data = fragments[fragmentName](client, previousProps, props); // use previous data if props used as variables in fragments have not changed if (data === false) { data = previousData; } } catch (e) { if (process.env.NODE_ENV !== 'production') { console.error(e); } } return _extends({}, results, (_babelHelpers$extends2 = {}, _babelHelpers$extends2[fragmentName] = data, _babelHelpers$extends2)); }, {}); }; this.initializeFetchers = function () { var fetchers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var props = arguments[1]; var client = _this4.getClient(); _this4.fetchers = Object.keys(fetchers).reduce(function (initialized, fetcherName) { var _babelHelpers$extends3; return _extends({}, initialized, (_babelHelpers$extends3 = {}, _babelHelpers$extends3[fetcherName] = fetchers[fetcherName](client, props), _babelHelpers$extends3)); }, {}); }; this.initializeMutations = function () { var mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var props = arguments[1]; var client = _this4.getClient(); _this4.mutations = Object.keys(mutations).reduce(function (initialized, mutationName) { var _babelHelpers$extends4; return _extends({}, initialized, (_babelHelpers$extends4 = {}, _babelHelpers$extends4[mutationName] = mutations[mutationName](client, props), _babelHelpers$extends4)); }, {}); }; this.forceRerender = function () { if (!_this4.hasMount) { return; } _this4.setState({}); }; }; GraphQL.propTypes = { client: typeof ApolloClient === 'function' ? require('prop-types').instanceOf(ApolloClient) : require('prop-types').any, fetchers: typeof F === 'function' ? require('prop-types').instanceOf(F) : require('prop-types').any, fragments: typeof FR === 'function' ? require('prop-types').instanceOf(FR) : require('prop-types').any, mutations: typeof M === 'function' ? require('prop-types').instanceOf(M) : require('prop-types').any, queries: typeof Q === 'function' ? require('prop-types').instanceOf(Q) : require('prop-types').any, render: require('prop-types').func.isRequired }; exports['default'] = GraphQL; exports.getDataFromTree = getDataFromTree$$1; Object.defineProperty(exports, '__esModule', { value: true }); })));