blips
Version:
State management for the GraphQL heads
304 lines (239 loc) • 11.1 kB
JavaScript
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; };
function _asyncToGenerator(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"); }); }; }
import { GraphQLError, execute, subscribe, validate } from 'graphql';
import { makeExecutableSchema } from 'graphql-tools/dist/schemaGenerator';
import { PubSub, withFilter } from 'graphql-subscriptions';
import { createApolloFetch } from 'apollo-fetch';
import Clerk from 'state-clerk';
import { when, isEmpty, isType, toObservable, extendContext, getDocument, promiseBatch, validateWithoutSchema } from './utils';
export var CLIENTGRAPHQL_DEPRECATION_WARNING = ' The "graphql" method is deprecated and will be removed in the 1.0 release. Use the "fetch" method instead.';
export var CREATESTORE_DEPRECATION_WARNING = 'The "createStore" method is deprecated and will be removed in the 1.0 release. Use "new BlipsClient(...)" instead';
export var FETCH_NOT_CONFIGURED_ERROR = 'You are trying to use "BlipsClient.fetch" without it being configured.';
export var NO_SUBSCRIPTION_ERROR = 'No subscription operation defined in query';
export var LONE_SUBSCRIPTION_OPERATION_ERROR = 'Only one subscription operation is allowed per query';
export var incorrectMiddlewareOrAfterwareType = function incorrectMiddlewareOrAfterwareType() {
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'middleware/afterware';
return 'The fetch ' + name + ' must be a function or an array of functions';
};
var loggedWarnings = {};
export function BlipsClient() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
typeDefs = _ref.typeDefs,
resolvers = _ref.resolvers;
var _this = this;
var initialState = arguments[1];
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref2$variables = _ref2.variables,
variables = _ref2$variables === undefined ? {} : _ref2$variables,
_ref2$context = _ref2.context,
context = _ref2$context === undefined ? {} : _ref2$context,
_ref2$fetch = _ref2.fetch,
fetch = _ref2$fetch === undefined ? {} : _ref2$fetch;
var _pubsub = new PubSub();
var _state = void 0;
var _schema = void 0;
var _resolvers = void 0;
var _clerk = void 0;
var _context = void 0;
var _variables = void 0;
var _apolloFetch = void 0;
function _validateDocument(sourceOrDocument) {
var document = sourceOrDocument;
try {
document = getDocument(sourceOrDocument);
} catch (syntaxError) {
return { document: document, errors: [syntaxError] };
}
var errors = _schema ? validate(_schema, document) : validateWithoutSchema(document);
return _extends({ document: document }, !isEmpty(errors) && { errors: errors });
}
function _runner(fn) {
return function (document) {
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref3$variables = _ref3.variables,
variables = _ref3$variables === undefined ? {} : _ref3$variables,
_ref3$context = _ref3.context,
context = _ref3$context === undefined ? {} : _ref3$context;
var operationName = arguments[2];
var resolveFn = arguments[3];
return (0, fn)(_schema, document, {}, extendContext(_context, context), _extends({}, _variables, variables), operationName, resolveFn);
};
}
function _setUpMiddlewareOrAfterware(listOrFn, name) {
if (!listOrFn) return;
if (isType('function', listOrFn)) {
_apolloFetch.use(listOrFn);
} else if (isType('array', listOrFn)) {
for (var _iterator = listOrFn, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref4;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref4 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref4 = _i.value;
}
var middleware = _ref4;
_apolloFetch.use(middleware);
}
} else {
throw new TypeError(incorrectMiddlewareOrAfterwareType(name));
}
}
var _executor = _runner(execute);
var _subscriber = _runner(subscribe);
function _execute(operationType) {
return function (sourceOrDocument, options, operationName, resolveFn) {
var _validateDocument2 = _validateDocument(sourceOrDocument),
document = _validateDocument2.document,
errors = _validateDocument2.errors;
if (errors) return Promise.resolve({ errors: errors });
// If an operationName is provided, go ahead and execute that
if (operationName) {
return _executor(document, options, operationName, resolveFn);
}
var executableOperations = document.definitions.filter(function (definition) {
return definition.operation === operationType;
});
// If there's just one operation definition of the correct type execute it
if (executableOperations.length === 1) {
return _executor(document, options, operationName, resolveFn);
}
// otherwise:
return promiseBatch(executableOperations.map(function (operation) {
return _executor(document, options, operation.name.value, resolveFn);
}));
};
}
;(function constructor() {
// store the initial state
_state = _extends({}, initialState) || {};
// create and store the clerk instance
_clerk = new Clerk(_state);
// compute and store the resolvers
_resolvers = when(typeof resolvers === 'function', resolvers({ pubsub: _pubsub, withFilter: withFilter }), resolvers);
_schema = makeExecutableSchema({
typeDefs: typeDefs,
resolvers: _resolvers
});
// store the default variables
_variables = variables;
// compute and store the default context
_context = extendContext({
// add store to the context.
// it will not be replaced by any `store` props passed through the default options
store: _extends({}, _clerk)
}, context);
// create apolloFetch
if (fetch.uri) {
_apolloFetch = createApolloFetch({ uri: fetch.uri });
// set up middleware and afterware
_setUpMiddlewareOrAfterware(fetch.middleware, 'middleware');
_setUpMiddlewareOrAfterware(fetch.afterware, 'afterware');
}
})();
return {
/**
* returns the state object
* @return {Object}
*/
get state() {
return _state;
},
/**
* returns the schema
* @return {GraphQLSchema}
*/
get schema() {
return _schema;
},
query: _execute('query'),
mutate: _execute('mutation'),
subscribe: function () {
var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(sourceOrDocument, options, operationName, resolveFn) {
var _validateDocument3, document, errors, operations, iterator;
return regeneratorRuntime.wrap(function _callee$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_validateDocument3 = _validateDocument(sourceOrDocument), document = _validateDocument3.document, errors = _validateDocument3.errors;
if (!errors) {
_context2.next = 3;
break;
}
return _context2.abrupt('return', Promise.resolve({ errors: errors }));
case 3:
operations = document.definitions.filter(function (definition) {
return definition.operation === 'subscription';
});
if (!(operations.length < 1)) {
_context2.next = 8;
break;
}
return _context2.abrupt('return', Promise.resolve({
errors: [new GraphQLError(NO_SUBSCRIPTION_ERROR)]
}));
case 8:
if (!(operations.length > 1)) {
_context2.next = 10;
break;
}
return _context2.abrupt('return', Promise.resolve({
errors: [new GraphQLError(LONE_SUBSCRIPTION_OPERATION_ERROR)]
}));
case 10:
_context2.next = 12;
return _subscriber(document, options, operationName, resolveFn);
case 12:
iterator = _context2.sent;
return _context2.abrupt('return', toObservable(iterator));
case 14:
case 'end':
return _context2.stop();
}
}
}, _callee, _this);
}));
return function subscribe(_x5, _x6, _x7, _x8) {
return _ref5.apply(this, arguments);
};
}(),
fetch: function fetch(query) {
var _ref6 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref6$variables = _ref6.variables,
variables = _ref6$variables === undefined ? {} : _ref6$variables;
var operationName = arguments[2];
if (!_apolloFetch || !isType('function', _apolloFetch)) {
throw new Error(FETCH_NOT_CONFIGURED_ERROR);
}
return _apolloFetch({ query: query, variables: variables, operationName: operationName });
},
graphql: function graphql(query) {
var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref7$variables = _ref7.variables,
variables = _ref7$variables === undefined ? {} : _ref7$variables;
var operationName = arguments[2];
if (!loggedWarnings[CLIENTGRAPHQL_DEPRECATION_WARNING]) {
// eslint-disable-next-line
console.warn(CLIENTGRAPHQL_DEPRECATION_WARNING);
loggedWarnings[CLIENTGRAPHQL_DEPRECATION_WARNING] = true;
}
if (!_apolloFetch || !isType('function', _apolloFetch)) {
throw new Error(FETCH_NOT_CONFIGURED_ERROR);
}
return _apolloFetch({ query: query, variables: variables, operationName: operationName });
}
};
}
export function createStore() {
if (!loggedWarnings[CREATESTORE_DEPRECATION_WARNING]) {
// eslint-disable-next-line
console.warn(CREATESTORE_DEPRECATION_WARNING);
loggedWarnings[CREATESTORE_DEPRECATION_WARNING] = true;
}
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return new (Function.prototype.bind.apply(BlipsClient, [null].concat(args)))();
}