UNPKG

apollo-progressive-fragment-matcher

Version:

A smart alternative to the introspection fragment matcher.

202 lines (161 loc) 7.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProgressiveFragmentMatcher = void 0; var _apolloLink = require("apollo-link"); var _invariant = _interopRequireDefault(require("invariant")); var _transform = require("./transform"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var defaultOptions = { strategy: 'introspection' // 'introspection' | 'extension' }; var strategies = { /** * Uses GraphQL extensions to share possibleTypes from server to client. * * Upsides: fast. * Downsides: requires server contol (add extension). */ extension: { link: function link() { var _this = this; return new _apolloLink.ApolloLink(function (operation, forward) { // enable possible types fetching. operation.extensions.possibleTypes = true; return forward(operation).map(function (result) { if (result.extensions && result.extensions.possibleTypes) { var types = result.extensions.possibleTypes; for (var type in types) { if (types.hasOwnProperty(type) && !_this.possibleTypesMap[type]) { _this.possibleTypesMap[type] = types[type]; } } } return result; }); }); } }, /** * Alters operations to send small and specific introespection requests. * * Upsides: easy to use. * Downsides: query manipulation (might be slow). */ introspection: { link: function link() { var _this2 = this; return new _apolloLink.ApolloLink(function (operation, forward) { var originalQuery = operation.query; var _addTypeIntrospection = (0, _transform.addTypeIntrospections)(originalQuery, { possibleTypes: _this2.possibleTypesMap }), types = _addTypeIntrospection.types, query = _addTypeIntrospection.query; operation.query = query; // enable possible types fetching. return forward(operation).map(function (result) { operation.query = originalQuery; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = types[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var type = _step.value; var alias = "__".concat(type, "__"); if (!_this2.possibleTypesMap[type]) { _this2.possibleTypesMap[type] = []; } if (result.data[alias] && result.data[alias].possibleTypes) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = result.data[alias].possibleTypes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var name = _step2.value.name; _this2.possibleTypesMap[name] = _this2.possibleTypesMap[name] || []; if (!_this2.possibleTypesMap[name].includes(type)) { _this2.possibleTypesMap[name].push(type); } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return != null) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return result; }); }); } } }; var ProgressiveFragmentMatcher = /*#__PURE__*/ function () { function ProgressiveFragmentMatcher(options) { _classCallCheck(this, ProgressiveFragmentMatcher); var _defaultOptions$optio = _objectSpread({}, defaultOptions, options), name = _defaultOptions$optio.strategy; if (!strategies[name]) { var strategyNames = Object.keys(strategies).map(function (name) { return "\"".concat(name, "\""); }).join(', '); throw new Error("ProgressiveFragmentMatcher: unknown strategy \"".concat(name, "\" (must be one of ").concat(strategyNames, ").")); } var strategy = strategies[name]; // initiate type map. this.possibleTypesMap = {}; this.match = this.match.bind(this); // set strategy based methods. this.link = strategy.link.bind(this); } _createClass(ProgressiveFragmentMatcher, [{ key: "match", value: function match(idValue, typeCondition, context) { var obj = context.store.get(idValue.id); if (!obj) { // https://github.com/apollographql/apollo-client/pull/4620 return idValue.id === 'ROOT_QUERY'; } (0, _invariant.default)(obj.__typename, "Cannot match fragment because __typename property is missing: ".concat(JSON.stringify(obj))); if (obj.__typename === typeCondition) { return true; } var possibleTypes = this.possibleTypesMap[obj.__typename]; if (possibleTypes && possibleTypes.indexOf(typeCondition) > -1) { return true; } return false; } }]); return ProgressiveFragmentMatcher; }(); exports.ProgressiveFragmentMatcher = ProgressiveFragmentMatcher;