text: import { __assign, __awaiter, __generator } from "tslib";
  import { visit, BREAK, } from 'graphql';
  import { invariant } from 'ts-invariant';
  import { argumentsObjectFromField, buildQueryFromSelectionSet, createFragmentMap, getFragmentDefinitions, getMainDefinition, hasDirectives, isField, isInlineFragment, mergeDeep, mergeDeepArray, removeClientSetsFromDocument, resultKeyNameFromField, shouldInclude, } from "../utilities/index.js";
  import { cacheSlot } from "../cache/index.js";
  var LocalState = (function () {
      function LocalState(_a) {
          var cache = _a.cache, client = _a.client, resolvers = _a.resolvers, fragmentMatcher = _a.fragmentMatcher;
          this.cache = cache;
          if (client) {
              this.client = client;
          }
          if (resolvers) {
              this.addResolvers(resolvers);
          }
          if (fragmentMatcher) {
              this.setFragmentMatcher(fragmentMatcher);
          }
      }
      LocalState.prototype.addResolvers = function (resolvers) {
          var _this = this;
          this.resolvers = this.resolvers || {};
          if (Array.isArray(resolvers)) {
              resolvers.forEach(function (resolverGroup) {
                  _this.resolvers = mergeDeep(_this.resolvers, resolverGroup);
              });
          }
          else {
              this.resolvers = mergeDeep(this.resolvers, resolvers);
          }
      };
      LocalState.prototype.setResolvers = function (resolvers) {
          this.resolvers = {};
          this.addResolvers(resolvers);
      };
      LocalState.prototype.getResolvers = function () {
          return this.resolvers || {};
      };
      LocalState.prototype.runResolvers = function (_a) {
          var document = _a.document, remoteResult = _a.remoteResult, context = _a.context, variables = _a.variables, _b = _a.onlyRunForcedResolvers, onlyRunForcedResolvers = _b === void 0 ? false : _b;
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_c) {
                  if (document) {
                      return [2, this.resolveDocument(document, remoteResult.data, context, variables, this.fragmentMatcher, onlyRunForcedResolvers).then(function (localResult) { return (__assign(__assign({}, remoteResult), { data: localResult.result })); })];
                  }
                  return [2, remoteResult];
              });
          });
      };
      LocalState.prototype.setFragmentMatcher = function (fragmentMatcher) {
          this.fragmentMatcher = fragmentMatcher;
      };
      LocalState.prototype.getFragmentMatcher = function () {
          return this.fragmentMatcher;
      };
      LocalState.prototype.clientQuery = function (document) {
          if (hasDirectives(['client'], document)) {
              if (this.resolvers) {
                  return document;
              }
          }
          return null;
      };
      LocalState.prototype.serverQuery = function (document) {
          return removeClientSetsFromDocument(document);
      };
      LocalState.prototype.prepareContext = function (context) {
          var cache = this.cache;
          return __assign(__assign({}, context), { cache: cache,
              getCacheKey: function (obj) {
                  return cache.identify(obj);
              } });
      };
      LocalState.prototype.addExportedVariables = function (document, variables, context) {
          if (variables === void 0) { variables = {}; }
          if (context === void 0) { context = {}; }
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_a) {
                  if (document) {
                      return [2, this.resolveDocument(document, this.buildRootValueFromCache(document, variables) || {}, this.prepareContext(context), variables).then(function (data) { return (__assign(__assign({}, variables), data.exportedVariables)); })];
                  }
                  return [2, __assign({}, variables)];
              });
          });
      };
      LocalState.prototype.shouldForceResolvers = function (document) {
          var forceResolvers = false;
          visit(document, {
              Directive: {
                  enter: function (node) {
                      if (node.name.value === 'client' && node.arguments) {
                          forceResolvers = node.arguments.some(function (arg) {
                              return arg.name.value === 'always' &&
                                  arg.value.kind === 'BooleanValue' &&
                                  arg.value.value === true;
                          });
                          if (forceResolvers) {
                              return BREAK;
                          }
                      }
                  },
              },
          });
          return forceResolvers;
      };
      LocalState.prototype.buildRootValueFromCache = function (document, variables) {
          return this.cache.diff({
              query: buildQueryFromSelectionSet(document),
              variables: variables,
              returnPartialData: true,
              optimistic: false,
          }).result;
      };
      LocalState.prototype.resolveDocument = function (document, rootValue, context, variables, fragmentMatcher, onlyRunForcedResolvers) {
          if (context === void 0) { context = {}; }
          if (variables === void 0) { variables = {}; }
          if (fragmentMatcher === void 0) { fragmentMatcher = function () { return true; }; }
          if (onlyRunForcedResolvers === void 0) { onlyRunForcedResolvers = false; }
          return __awaiter(this, void 0, void 0, function () {
              var mainDefinition, fragments, fragmentMap, definitionOperation, defaultOperationType, _a, cache, client, execContext;
              return __generator(this, function (_b) {
                  mainDefinition = getMainDefinition(document);
                  fragments = getFragmentDefinitions(document);
                  fragmentMap = createFragmentMap(fragments);
                  definitionOperation = mainDefinition
                      .operation;
                  defaultOperationType = definitionOperation
                      ? definitionOperation.charAt(0).toUpperCase() +
                          definitionOperation.slice(1)
                      : 'Query';
                  _a = this, cache = _a.cache, client = _a.client;
                  execContext = {
                      fragmentMap: fragmentMap,
                      context: __assign(__assign({}, context), { cache: cache,
                          client: client }),
                      variables: variables,
                      fragmentMatcher: fragmentMatcher,
                      defaultOperationType: defaultOperationType,
                      exportedVariables: {},
                      onlyRunForcedResolvers: onlyRunForcedResolvers,
                  };
                  return [2, this.resolveSelectionSet(mainDefinition.selectionSet, rootValue, execContext).then(function (result) { return ({
                          result: result,
                          exportedVariables: execContext.exportedVariables,
                      }); })];
              });
          });
      };
      LocalState.prototype.resolveSelectionSet = function (selectionSet, rootValue, execContext) {
          return __awaiter(this, void 0, void 0, function () {
              var fragmentMap, context, variables, resultsToMerge, execute;
              var _this = this;
              return __generator(this, function (_a) {
                  fragmentMap = execContext.fragmentMap, context = execContext.context, variables = execContext.variables;
                  resultsToMerge = [rootValue];
                  execute = function (selection) { return __awaiter(_this, void 0, void 0, function () {
                      var fragment, typeCondition;
                      return __generator(this, function (_a) {
                          if (!shouldInclude(selection, variables)) {
                              return [2];
                          }
                          if (isField(selection)) {
                              return [2, this.resolveField(selection, rootValue, execContext).then(function (fieldResult) {
                                      var _a;
                                      if (typeof fieldResult !== 'undefined') {
                                          resultsToMerge.push((_a = {},
                                              _a[resultKeyNameFromField(selection)] = fieldResult,
                                              _a));
                                      }
                                  })];
                          }
                          if (isInlineFragment(selection)) {
                              fragment = selection;
                          }
                          else {
                              fragment = fragmentMap[selection.name.value];
                              process.env.NODE_ENV === "production" ? invariant(fragment, 11) : invariant(fragment, "No fragment named " + selection.name.value);
                          }
                          if (fragment && fragment.typeCondition) {
                              typeCondition = fragment.typeCondition.name.value;
                              if (execContext.fragmentMatcher(rootValue, typeCondition, context)) {
                                  return [2, this.resolveSelectionSet(fragment.selectionSet, rootValue, execContext).then(function (fragmentResult) {
                                          resultsToMerge.push(fragmentResult);
                                      })];
                              }
                          }
                          return [2];
                      });
                  }); };
                  return [2, Promise.all(selectionSet.selections.map(execute)).then(function () {
                          return mergeDeepArray(resultsToMerge);
                      })];
              });
          });
      };
      LocalState.prototype.resolveField = function (field, rootValue, execContext) {
          return __awaiter(this, void 0, void 0, function () {
              var variables, fieldName, aliasedFieldName, aliasUsed, defaultResult, resultPromise, resolverType, resolverMap, resolve;
              var _this = this;
              return __generator(this, function (_a) {
                  variables = execContext.variables;
                  fieldName = field.name.value;
                  aliasedFieldName = resultKeyNameFromField(field);
                  aliasUsed = fieldName !== aliasedFieldName;
                  defaultResult = rootValue[aliasedFieldName] || rootValue[fieldName];
                  resultPromise = Promise.resolve(defaultResult);
                  if (!execContext.onlyRunForcedResolvers ||
                      this.shouldForceResolvers(field)) {
                      resolverType = rootValue.__typename || execContext.defaultOperationType;
                      resolverMap = this.resolvers && this.resolvers[resolverType];
                      if (resolverMap) {
                          resolve = resolverMap[aliasUsed ? fieldName : aliasedFieldName];
                          if (resolve) {
                              resultPromise = Promise.resolve(cacheSlot.withValue(this.cache, resolve, [
                                  rootValue,
                                  argumentsObjectFromField(field, variables),
                                  execContext.context,
                                  { field: field, fragmentMap: execContext.fragmentMap },
                              ]));
                          }
                      }
                  }
                  return [2, resultPromise.then(function (result) {
                          if (result === void 0) { result = defaultResult; }
                          if (field.directives) {
                              field.directives.forEach(function (directive) {
                                  if (directive.name.value === 'export' && directive.arguments) {
                                      directive.arguments.forEach(function (arg) {
                                          if (arg.name.value === 'as' && arg.value.kind === 'StringValue') {
                                              execContext.exportedVariables[arg.value.value] = result;
                                          }
                                      });
                                  }
                              });
                          }
                          if (!field.selectionSet) {
                              return result;
                          }
                          if (result == null) {
                              return result;
                          }
                          if (Array.isArray(result)) {
                              return _this.resolveSubSelectedArray(field, result, execContext);
                          }
                          if (field.selectionSet) {
                              return _this.resolveSelectionSet(field.selectionSet, result, execContext);
                          }
                      })];
              });
          });
      };
      LocalState.prototype.resolveSubSelectedArray = function (field, result, execContext) {
          var _this = this;
          return Promise.all(result.map(function (item) {
              if (item === null) {
                  return null;
              }
              if (Array.isArray(item)) {
                  return _this.resolveSubSelectedArray(field, item, execContext);
              }
              if (field.selectionSet) {
                  return _this.resolveSelectionSet(field.selectionSet, item, execContext);
              }
          }));
      };
      return LocalState;
  }());
  export { LocalState };
  //# sourceMappingURL=LocalState.js.map