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