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
JavaScript
(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 });
})));