Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

pfchangs / react-relay   js

Repository URL to install this package:

Version: 0.7.1-ccinternal 

/ lib / intersectRelayQuery.js

/**
 * Copyright 2013-2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule intersectRelayQuery
 * @typechecks
 * 
 */

'use strict';

var _inherits = require('babel-runtime/helpers/inherits')['default'];

var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];

var RelayConnectionInterface = require('./RelayConnectionInterface');
var RelayQuery = require('./RelayQuery');
var RelayQueryTransform = require('./RelayQueryTransform');

var invariant = require('fbjs/lib/invariant');

/**
 * @internal
 *
 * `intersectRelayQuery(subjectNode, patternNode)` returns a node with fields in
 * `subjectNode` that also exist in `patternNode`. `patternNode` is expected to
 * be flattened (and not contain fragments).
 *
 * If any field in `patternNode` is unterminated (i.e. has no sub-fields), we
 * treat the field as though it contains every descendant sub-field.
 *
 * If `filterUnterminatedRange` is supplied, it will be invoked with any fields
 * from `subjectNode` that are connections and unterminated in `patternNode`. If
 * it returns true, the `edges` and `page_info` fields will be filtered out.
 */
function intersectRelayQuery(subjectNode, patternNode, filterUnterminatedRange) {
  filterUnterminatedRange = filterUnterminatedRange || returnsFalse;
  var visitor = new RelayQueryIntersector(filterUnterminatedRange);
  return visitor.traverse(subjectNode, patternNode);
}

var RelayQueryIntersector = (function (_RelayQueryTransform) {
  _inherits(RelayQueryIntersector, _RelayQueryTransform);

  function RelayQueryIntersector(filterUnterminatedRange) {
    _classCallCheck(this, RelayQueryIntersector);

    _RelayQueryTransform.call(this);
    this._filterUnterminatedRange = filterUnterminatedRange;
  }

  /**
   * @private
   */

  RelayQueryIntersector.prototype.traverse = function traverse(subjectNode, patternNode) {
    var _this = this;

    if (subjectNode.isScalar()) {
      // Since `patternNode` exists, `subjectNode` must be in the intersection.
      return subjectNode;
    }
    if (!hasChildren(patternNode)) {
      if (subjectNode instanceof RelayQuery.Field && subjectNode.isConnection() && this._filterUnterminatedRange(subjectNode)) {
        return filterRangeFields(subjectNode);
      }
      // Unterminated `patternNode` is the same as containing every descendant
      // sub-field, so `subjectNode` must be in the intersection.
      return subjectNode;
    }
    return subjectNode.clone(subjectNode.getChildren().map(function (subjectChild) {
      if (subjectChild instanceof RelayQuery.Fragment) {
        return _this.visit(subjectChild, patternNode);
      }
      if (subjectChild instanceof RelayQuery.Field) {
        var schemaName = subjectChild.getSchemaName();
        var patternChild;
        var patternChildren = patternNode.getChildren();
        for (var ii = 0; ii < patternChildren.length; ii++) {
          var child = patternChildren[ii];
          !(child instanceof RelayQuery.Field) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'intersectRelayQuery(): Nodes in `patternNode` must be fields.') : invariant(false) : undefined;
          if (child.getSchemaName() === schemaName) {
            patternChild = child;
            break;
          }
        }
        if (patternChild) {
          return _this.visit(subjectChild, patternChild);
        }
      }
      return null;
    }));
  };

  return RelayQueryIntersector;
})(RelayQueryTransform);

var RelayQueryRangeFilter = (function (_RelayQueryTransform2) {
  _inherits(RelayQueryRangeFilter, _RelayQueryTransform2);

  function RelayQueryRangeFilter() {
    _classCallCheck(this, RelayQueryRangeFilter);

    _RelayQueryTransform2.apply(this, arguments);
  }

  RelayQueryRangeFilter.prototype.visitField = function visitField(node) {
    var schemaName = node.getSchemaName();
    if (schemaName === RelayConnectionInterface.EDGES || schemaName === RelayConnectionInterface.PAGE_INFO) {
      return null;
    } else {
      return node;
    }
  };

  return RelayQueryRangeFilter;
})(RelayQueryTransform);

var rangeFilter = new RelayQueryRangeFilter();
function filterRangeFields(node) {
  return rangeFilter.traverse(node, undefined);
}

function returnsFalse() {
  return false;
}

function hasChildren(node) {
  return !node.getChildren().every(isGenerated);
}

function isGenerated(node) {
  return node.isGenerated();
}

module.exports = intersectRelayQuery;