graphql-client 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/graphql/client/query_result.rb +52 -8
 - data/lib/graphql/client.rb +131 -7
 - data/lib/graphql/language/mutator.rb +54 -0
 - data/lib/graphql/language/operation_slice.rb +40 -0
 - data/lib/graphql/relay/parser.rb +27 -0
 - metadata +5 -14
 - data/lib/graphql/client/document.rb +0 -48
 - data/lib/graphql/client/fragment.rb +0 -32
 - data/lib/graphql/client/node.rb +0 -36
 - data/lib/graphql/client/query.rb +0 -30
 - data/lib/graphql/language/nodes/inject_selection_ext.rb +0 -44
 - data/lib/graphql/language/nodes/query_result_class_ext.rb +0 -70
 - data/lib/graphql/language/nodes/replace_fragment_spread_ext.rb +0 -44
 - data/lib/graphql/language/nodes/selection_ext.rb +0 -37
 - data/lib/graphql/language/nodes/validate_ext.rb +0 -45
 - data/lib/graphql/relay/node_query.rb +0 -19
 - data/lib/graphql/schema/json_loader.rb +0 -101
 - data/lib/graphql/schema_load_json.rb +0 -10
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: cee45489051065d2c8d47c6f8c68c6b3c98d75ca
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: e462bb5c2fb1997f8679bb0fea315f8abd751539
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 9f335b9446f04fe5e684218b1f0f377b16412ac4918065ac610b2abff61d00792a461131b1ab615cd6512ba611a8dde6929af9c1b229f4a36c713e7e0983a22d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 428487913828790e402b3a3c51daceafe8c338ebabfd234d0570424c8af426bc54bfa6f8fbf306d365fd674174a5708936e8a350cce5fcdf5c6426f5d3f1bd37
         
     | 
| 
         @@ -1,15 +1,38 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
1 
     | 
    
         
             
            require "active_support/inflector"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "graphql"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "set"
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            module GraphQL
         
     | 
| 
       5 
     | 
    
         
            -
               
     | 
| 
      
 6 
     | 
    
         
            +
              class Client
         
     | 
| 
       6 
7 
     | 
    
         
             
                class QueryResult
         
     | 
| 
       7 
     | 
    
         
            -
                   
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Internal: Get QueryResult class for result of query.
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # Returns subclass of QueryResult or nil.
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def self.wrap(node, name: nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    fields = {}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    node.selections.each do |selection|
         
     | 
| 
      
 15 
     | 
    
         
            +
                      case selection
         
     | 
| 
      
 16 
     | 
    
         
            +
                      when Language::Nodes::FragmentSpread
         
     | 
| 
      
 17 
     | 
    
         
            +
                      when Language::Nodes::Field
         
     | 
| 
      
 18 
     | 
    
         
            +
                        field_name = selection.alias || selection.name
         
     | 
| 
      
 19 
     | 
    
         
            +
                        field_klass = selection.selections.any? ? wrap(selection, name: "#{name}.#{field_name}") : nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                        fields[field_name] ? fields[field_name] |= field_klass : fields[field_name] = field_klass
         
     | 
| 
      
 21 
     | 
    
         
            +
                      when Language::Nodes::InlineFragment
         
     | 
| 
      
 22 
     | 
    
         
            +
                        wrap(selection, name: name).fields.each do |fragment_name, klass|
         
     | 
| 
      
 23 
     | 
    
         
            +
                          fields[fragment_name.to_s] ? fields[fragment_name.to_s] |= klass : fields[fragment_name.to_s] = klass
         
     | 
| 
      
 24 
     | 
    
         
            +
                        end
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    define(name: name, source_node: node, fields: fields)
         
     | 
| 
       9 
29 
     | 
    
         
             
                  end
         
     | 
| 
       10 
30 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                   
     | 
| 
      
 31 
     | 
    
         
            +
                  # Internal
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def self.define(name:, source_node:, fields: {})
         
     | 
| 
       12 
33 
     | 
    
         
             
                    Class.new(self) do
         
     | 
| 
      
 34 
     | 
    
         
            +
                      @name = name
         
     | 
| 
      
 35 
     | 
    
         
            +
                      @source_node = source_node
         
     | 
| 
       13 
36 
     | 
    
         
             
                      @fields = {}
         
     | 
| 
       14 
37 
     | 
    
         | 
| 
       15 
38 
     | 
    
         
             
                      fields.each do |field, type|
         
     | 
| 
         @@ -62,8 +85,20 @@ module GraphQL 
     | 
|
| 
       62 
85 
     | 
    
         
             
                    end
         
     | 
| 
       63 
86 
     | 
    
         
             
                  end
         
     | 
| 
       64 
87 
     | 
    
         | 
| 
      
 88 
     | 
    
         
            +
                  def self.source_node
         
     | 
| 
      
 89 
     | 
    
         
            +
                    @source_node
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  def self.fields
         
     | 
| 
      
 93 
     | 
    
         
            +
                    @fields
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  def self.name
         
     | 
| 
      
 97 
     | 
    
         
            +
                    @name || super || GraphQL::Client::QueryResult.name
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
       65 
100 
     | 
    
         
             
                  def self.inspect
         
     | 
| 
       66 
     | 
    
         
            -
                    " 
     | 
| 
      
 101 
     | 
    
         
            +
                    "#<#{self.name} fields=#{@fields.keys.inspect}>"
         
     | 
| 
       67 
102 
     | 
    
         
             
                  end
         
     | 
| 
       68 
103 
     | 
    
         | 
| 
       69 
104 
     | 
    
         
             
                  def self.cast(obj)
         
     | 
| 
         @@ -71,6 +106,14 @@ module GraphQL 
     | 
|
| 
       71 
106 
     | 
    
         
             
                    when Hash
         
     | 
| 
       72 
107 
     | 
    
         
             
                      new(obj)
         
     | 
| 
       73 
108 
     | 
    
         
             
                    when QueryResult
         
     | 
| 
      
 109 
     | 
    
         
            +
                      spreads = Set.new(obj.class.source_node.selections.select { |s| s.is_a?(GraphQL::Language::Nodes::FragmentSpread) }.map(&:name))
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                      if !spreads.include?(self.source_node.name)
         
     | 
| 
      
 112 
     | 
    
         
            +
                        message = "couldn't cast #{obj.inspect} to #{self.inspect}\n\n"
         
     | 
| 
      
 113 
     | 
    
         
            +
                        suggestion = "\n  ...#{name || "YourFragment"} # SUGGESTION"
         
     | 
| 
      
 114 
     | 
    
         
            +
                        message << GraphQL::Language::Generation.generate(obj.class.source_node).sub(/\n}$/, "#{suggestion}\n}")
         
     | 
| 
      
 115 
     | 
    
         
            +
                        raise TypeError, message
         
     | 
| 
      
 116 
     | 
    
         
            +
                      end
         
     | 
| 
       74 
117 
     | 
    
         
             
                      cast(obj.to_h)
         
     | 
| 
       75 
118 
     | 
    
         
             
                    when Array
         
     | 
| 
       76 
119 
     | 
    
         
             
                      obj.map { |e| cast(e) }
         
     | 
| 
         @@ -99,7 +142,8 @@ module GraphQL 
     | 
|
| 
       99 
142 
     | 
    
         
             
                        new_fields[name] = value
         
     | 
| 
       100 
143 
     | 
    
         
             
                      end
         
     | 
| 
       101 
144 
     | 
    
         
             
                    end
         
     | 
| 
       102 
     | 
    
         
            -
                     
     | 
| 
      
 145 
     | 
    
         
            +
                    # TODO: Picking first source node seems error prone
         
     | 
| 
      
 146 
     | 
    
         
            +
                    define(name: self.name, source_node: self.source_node, fields: new_fields)
         
     | 
| 
       103 
147 
     | 
    
         
             
                  end
         
     | 
| 
       104 
148 
     | 
    
         | 
| 
       105 
149 
     | 
    
         
             
                  attr_reader :data
         
     | 
| 
         @@ -107,7 +151,7 @@ module GraphQL 
     | 
|
| 
       107 
151 
     | 
    
         | 
| 
       108 
152 
     | 
    
         
             
                  def inspect
         
     | 
| 
       109 
153 
     | 
    
         
             
                    ivars = (self.class.fields.keys - [:__typename]).map { |sym| "#{sym}=#{instance_variable_get("@#{sym}").inspect}" }
         
     | 
| 
       110 
     | 
    
         
            -
                    buf = " 
     | 
| 
      
 154 
     | 
    
         
            +
                    buf = "#<#{self.class.name}"
         
     | 
| 
       111 
155 
     | 
    
         
             
                    buf << " " << @__typename if @__typename
         
     | 
| 
       112 
156 
     | 
    
         
             
                    buf << " " << ivars.join(" ") if ivars.any?
         
     | 
| 
       113 
157 
     | 
    
         
             
                    buf << ">"
         
     | 
    
        data/lib/graphql/client.rb
    CHANGED
    
    | 
         @@ -1,14 +1,138 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "active_support/inflector"
         
     | 
| 
       1 
2 
     | 
    
         
             
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/client/document"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/client/fragment"
         
     | 
| 
       4 
     | 
    
         
            -
            require "graphql/client/node"
         
     | 
| 
       5 
3 
     | 
    
         
             
            require "graphql/client/query_result"
         
     | 
| 
       6 
     | 
    
         
            -
            require "graphql/ 
     | 
| 
      
 4 
     | 
    
         
            +
            require "graphql/language/mutator"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "graphql/language/nodes/deep_freeze_ext"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "graphql/language/operation_slice"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "graphql/relay/parser"
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
            module GraphQL
         
     | 
| 
       9 
     | 
    
         
            -
               
     | 
| 
       10 
     | 
    
         
            -
                class  
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 11 
     | 
    
         
            +
                class Error < StandardError; end
         
     | 
| 
      
 12 
     | 
    
         
            +
                class ValidationError < Error; end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :schema
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def initialize(schema:)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @schema = schema
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @definitions = []
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @document = GraphQL::Language::Nodes::Document.new(definitions: @definitions)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @document_slices = {}
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                class Definition < Module
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def initialize(node:)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @definition_node = node
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  # Internal: Get underlying operation or fragment defintion AST node for
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # definition.
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # Returns OperationDefinition or FragmentDefinition object.
         
     | 
| 
      
 32 
     | 
    
         
            +
                  attr_reader :definition_node
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  # Public: Ruby constant name of definition.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # Returns String or errors if definition was not assigned to a constant.
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @name ||= super || raise(RuntimeError, "definition must be assigned to a constant")
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  # Public: Global name of definition in client document.
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # Returns a GraphQL safe name of the Ruby constant String.
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #   "Users::UserQuery" #=> "Users__UserQuery"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # Returns String.
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def definition_name
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @definition_name ||= name.gsub("::", "__").freeze
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def new(*args)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    query_result_class.new(*args)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  private
         
     | 
| 
      
 57 
     | 
    
         
            +
                    def query_result_class
         
     | 
| 
      
 58 
     | 
    
         
            +
                      @query_result_class ||= GraphQL::Client::QueryResult.wrap(definition_node, name: name)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                class OperationDefinition < Definition
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # Public: Alias for definition name.
         
     | 
| 
      
 64 
     | 
    
         
            +
                  alias_method :operation_name, :definition_name
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                class FragmentDefinition < Definition
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def parse(str)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  str = str.gsub(/\.\.\.([a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)+)/) { |m|
         
     | 
| 
      
 72 
     | 
    
         
            +
                    const_name = $1
         
     | 
| 
      
 73 
     | 
    
         
            +
                    case fragment = ActiveSupport::Inflector.safe_constantize(const_name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    when FragmentDefinition
         
     | 
| 
      
 75 
     | 
    
         
            +
                      "...#{fragment.definition_name}"
         
     | 
| 
      
 76 
     | 
    
         
            +
                    when nil
         
     | 
| 
      
 77 
     | 
    
         
            +
                      raise NameError, "uninitialized constant #{const_name}\n#{str}"
         
     | 
| 
      
 78 
     | 
    
         
            +
                    else
         
     | 
| 
      
 79 
     | 
    
         
            +
                      raise TypeError, "expected #{const_name} to be a #{FragmentDefinition}, but was a #{fragment.class}"
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
                  }
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  doc = GraphQL::Relay::Parser.parse(str)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  mutator = GraphQL::Language::Mutator.new(doc)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  # TODO: Make this __typename injection optional
         
     | 
| 
      
 88 
     | 
    
         
            +
                  mutator.prepend_selection(GraphQL::Language::Nodes::Field.new(name: "__typename").deep_freeze)
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  definitions, renames = {}, {}
         
     | 
| 
      
 91 
     | 
    
         
            +
                  doc.definitions.each do |node|
         
     | 
| 
      
 92 
     | 
    
         
            +
                    local_name = node.name
         
     | 
| 
      
 93 
     | 
    
         
            +
                    definition = case node
         
     | 
| 
      
 94 
     | 
    
         
            +
                    when Language::Nodes::OperationDefinition
         
     | 
| 
      
 95 
     | 
    
         
            +
                      OperationDefinition.new(node: node)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    when Language::Nodes::FragmentDefinition
         
     | 
| 
      
 97 
     | 
    
         
            +
                      FragmentDefinition.new(node: node)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                    definitions[local_name] = definition
         
     | 
| 
      
 100 
     | 
    
         
            +
                    renames[local_name] = -> { definition.definition_name }
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                  mutator.rename_definitions(renames)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  doc.deep_freeze
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  self.document.definitions.concat(doc.definitions)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  if definitions[nil]
         
     | 
| 
      
 109 
     | 
    
         
            +
                    definitions[nil]
         
     | 
| 
      
 110 
     | 
    
         
            +
                  else
         
     | 
| 
      
 111 
     | 
    
         
            +
                    Module.new do
         
     | 
| 
      
 112 
     | 
    
         
            +
                      definitions.each do |name, definition|
         
     | 
| 
      
 113 
     | 
    
         
            +
                        const_set(name, definition)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                def document
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @document
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                def document_slice(operation_name)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @document_slices[operation_name] ||= Language::OperationSlice.slice(document, operation_name).deep_freeze
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                def validate!
         
     | 
| 
      
 128 
     | 
    
         
            +
                  validator = StaticValidation::Validator.new(schema: @schema)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  query = Query.new(@schema, document: document)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  validator.validate(query).fetch(:errors).each do |error|
         
     | 
| 
      
 132 
     | 
    
         
            +
                    raise ValidationError, error["message"]
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  nil
         
     | 
| 
       12 
136 
     | 
    
         
             
                end
         
     | 
| 
       13 
137 
     | 
    
         
             
              end
         
     | 
| 
       14 
138 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "graphql"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "set"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Language
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Mutator
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(document)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @document = document
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  module LazyName
         
     | 
| 
      
 12 
     | 
    
         
            +
                    def name
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @name.call
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def rename_definitions(definitions)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    rename_node = -> (node, parent) {
         
     | 
| 
      
 19 
     | 
    
         
            +
                      if name = definitions[node.name]
         
     | 
| 
      
 20 
     | 
    
         
            +
                        node.extend(LazyName) if name.is_a?(Proc)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        node.name = name
         
     | 
| 
      
 22 
     | 
    
         
            +
                      end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    visitor = Visitor.new(@document)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    visitor[Nodes::FragmentDefinition].leave << rename_node
         
     | 
| 
      
 27 
     | 
    
         
            +
                    visitor[Nodes::OperationDefinition].leave << rename_node
         
     | 
| 
      
 28 
     | 
    
         
            +
                    visitor[Nodes::FragmentSpread].leave << rename_node
         
     | 
| 
      
 29 
     | 
    
         
            +
                    visitor.visit
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def prepend_selection(selection)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    on_selections = -> (node, parent) {
         
     | 
| 
      
 36 
     | 
    
         
            +
                      return if !node.selections.any?
         
     | 
| 
      
 37 
     | 
    
         
            +
                      # TODO: Simplify if AbstractNode#eql? is implemented
         
     | 
| 
      
 38 
     | 
    
         
            +
                      existing_selections = Set.new(node.selections.map { |s| s.respond_to?(:name) ? s.name : nil }.compact)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      selections_to_prepend = [selection].reject { |s| existing_selections.include?(s.name) }
         
     | 
| 
      
 40 
     | 
    
         
            +
                      node.selections = selections_to_prepend + node.selections
         
     | 
| 
      
 41 
     | 
    
         
            +
                    }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    visitor = Visitor.new(@document)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    visitor[Nodes::Field].leave << on_selections
         
     | 
| 
      
 45 
     | 
    
         
            +
                    visitor[Nodes::FragmentDefinition].leave << on_selections
         
     | 
| 
      
 46 
     | 
    
         
            +
                    visitor[Nodes::InlineFragment].leave << on_selections
         
     | 
| 
      
 47 
     | 
    
         
            +
                    visitor[Nodes::OperationDefinition].leave << on_selections
         
     | 
| 
      
 48 
     | 
    
         
            +
                    visitor.visit
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "graphql"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Language
         
     | 
| 
      
 5 
     | 
    
         
            +
                module OperationSlice
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Public: Return's minimal document to represent operation.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Find's target operation and any fragment dependencies and returns a
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # new document with just those definitions.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # document - The Nodes::Document to find definitions.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # operation_name - The String name of Nodes::OperationDefinition
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # Returns new Nodes::Document.
         
     | 
| 
      
 15 
     | 
    
         
            +
                  def self.slice(document, operation_name)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    seen = Set.new([operation_name])
         
     | 
| 
      
 17 
     | 
    
         
            +
                    stack = [operation_name]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    while name = stack.pop
         
     | 
| 
      
 20 
     | 
    
         
            +
                      names = find_definition_fragment_spreads(document, name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      seen.merge(names)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      stack.concat(names.to_a)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    Nodes::Document.new(definitions: document.definitions.select { |node| seen.include?(node.name) })
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def self.find_definition_fragment_spreads(document, definition_name)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    definition = document.definitions.find { |node| node.name == definition_name }
         
     | 
| 
      
 30 
     | 
    
         
            +
                    spreads = Set.new
         
     | 
| 
      
 31 
     | 
    
         
            +
                    visitor = Visitor.new(definition)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    visitor[Nodes::FragmentSpread].enter << -> (node, parent) {
         
     | 
| 
      
 33 
     | 
    
         
            +
                      spreads << node.name
         
     | 
| 
      
 34 
     | 
    
         
            +
                    }
         
     | 
| 
      
 35 
     | 
    
         
            +
                    visitor.visit
         
     | 
| 
      
 36 
     | 
    
         
            +
                    spreads
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "graphql"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module GraphQL
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Relay
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Parser
         
     | 
| 
      
 6 
     | 
    
         
            +
                  ANONYMOUS_SENTINEL = "__anonymous__".freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Public: Extended GraphQL.parse that supports Relay style anonymous
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # fragments.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # TODO: See about getting support for this upstreamed to the graphql-ruby
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # gem.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # str - A GraphQL String
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # Returns a GraphQL::Language::Nodes::Document.
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def self.parse(str)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    str = str.sub(/fragment on /, "fragment #{ANONYMOUS_SENTINEL} on ")
         
     | 
| 
      
 19 
     | 
    
         
            +
                    document = GraphQL.parse(str)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    document.definitions.each do |node|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      node.name = nil if node.name == ANONYMOUS_SENTINEL
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    document
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: graphql-client
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.8
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - GitHub
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2016-09- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2016-09-06 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: activesupport
         
     | 
| 
         @@ -74,20 +74,11 @@ extra_rdoc_files: [] 
     | 
|
| 
       74 
74 
     | 
    
         
             
            files:
         
     | 
| 
       75 
75 
     | 
    
         
             
            - LICENSE
         
     | 
| 
       76 
76 
     | 
    
         
             
            - lib/graphql/client.rb
         
     | 
| 
       77 
     | 
    
         
            -
            - lib/graphql/client/document.rb
         
     | 
| 
       78 
     | 
    
         
            -
            - lib/graphql/client/fragment.rb
         
     | 
| 
       79 
     | 
    
         
            -
            - lib/graphql/client/node.rb
         
     | 
| 
       80 
     | 
    
         
            -
            - lib/graphql/client/query.rb
         
     | 
| 
       81 
77 
     | 
    
         
             
            - lib/graphql/client/query_result.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
            - lib/graphql/language/mutator.rb
         
     | 
| 
       82 
79 
     | 
    
         
             
            - lib/graphql/language/nodes/deep_freeze_ext.rb
         
     | 
| 
       83 
     | 
    
         
            -
            - lib/graphql/language/ 
     | 
| 
       84 
     | 
    
         
            -
            - lib/graphql/ 
     | 
| 
       85 
     | 
    
         
            -
            - lib/graphql/language/nodes/replace_fragment_spread_ext.rb
         
     | 
| 
       86 
     | 
    
         
            -
            - lib/graphql/language/nodes/selection_ext.rb
         
     | 
| 
       87 
     | 
    
         
            -
            - lib/graphql/language/nodes/validate_ext.rb
         
     | 
| 
       88 
     | 
    
         
            -
            - lib/graphql/relay/node_query.rb
         
     | 
| 
       89 
     | 
    
         
            -
            - lib/graphql/schema/json_loader.rb
         
     | 
| 
       90 
     | 
    
         
            -
            - lib/graphql/schema_load_json.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - lib/graphql/language/operation_slice.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - lib/graphql/relay/parser.rb
         
     | 
| 
       91 
82 
     | 
    
         
             
            homepage: 
         
     | 
| 
       92 
83 
     | 
    
         
             
            licenses:
         
     | 
| 
       93 
84 
     | 
    
         
             
            - MIT
         
     | 
| 
         @@ -1,48 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/client/fragment"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/client/node"
         
     | 
| 
       4 
     | 
    
         
            -
            require "graphql/client/query"
         
     | 
| 
       5 
     | 
    
         
            -
            require "graphql/language/nodes/deep_freeze_ext"
         
     | 
| 
       6 
     | 
    
         
            -
            require "graphql/language/nodes/inject_selection_ext"
         
     | 
| 
       7 
     | 
    
         
            -
            require "graphql/language/nodes/replace_fragment_spread_ext"
         
     | 
| 
       8 
     | 
    
         
            -
            require "graphql/language/nodes/validate_ext"
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       11 
     | 
    
         
            -
              module Client
         
     | 
| 
       12 
     | 
    
         
            -
                class Document < Node
         
     | 
| 
       13 
     | 
    
         
            -
                  def self.parse(str, schema: GraphQL::Client.schema)
         
     | 
| 
       14 
     | 
    
         
            -
                    str = str.strip
         
     | 
| 
       15 
     | 
    
         
            -
                    str, fragments = scan_interpolated_fragments(str)
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                    document = GraphQL.parse(str)
         
     | 
| 
       18 
     | 
    
         
            -
                    document = document.inject_selection(GraphQL::Language::Nodes::Field.new(name: "__typename"))
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    document.definitions.each do |definition|
         
     | 
| 
       21 
     | 
    
         
            -
                      fragments[definition.name.to_sym] = definition if definition.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
         
     | 
| 
       22 
     | 
    
         
            -
                    end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                    document = document.replace_fragment_spread(fragments)
         
     | 
| 
       25 
     | 
    
         
            -
                    document = document.replace_fragment_spread(fragments) # XXX: Multiple pass
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                    document.definitions.inject({}) do |doc, definition|
         
     | 
| 
       28 
     | 
    
         
            -
                      name = definition.name.to_sym
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                      case definition
         
     | 
| 
       31 
     | 
    
         
            -
                      when GraphQL::Language::Nodes::OperationDefinition
         
     | 
| 
       32 
     | 
    
         
            -
                        query = GraphQL::Client::Query.new(definition.deep_freeze, fragments.values).freeze
         
     | 
| 
       33 
     | 
    
         
            -
                        query.node.validate!(schema: schema) if schema
         
     | 
| 
       34 
     | 
    
         
            -
                        doc[name] = query
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                      when GraphQL::Language::Nodes::FragmentDefinition
         
     | 
| 
       37 
     | 
    
         
            -
                        definition = GraphQL::Language::Nodes::InlineFragment.new(type: definition.type, directives: definition.directives, selections: definition.selections)
         
     | 
| 
       38 
     | 
    
         
            -
                        fragment = GraphQL::Client::Fragment.new(definition.deep_freeze, fragments.values).freeze
         
     | 
| 
       39 
     | 
    
         
            -
                        fragment.node.validate!(schema: schema) if schema
         
     | 
| 
       40 
     | 
    
         
            -
                        doc[name] = fragment
         
     | 
| 
       41 
     | 
    
         
            -
                      end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                      doc
         
     | 
| 
       44 
     | 
    
         
            -
                    end
         
     | 
| 
       45 
     | 
    
         
            -
                  end
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,32 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/client/node"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/language/nodes/deep_freeze_ext"
         
     | 
| 
       4 
     | 
    
         
            -
            require "graphql/language/nodes/inject_selection_ext"
         
     | 
| 
       5 
     | 
    
         
            -
            require "graphql/language/nodes/replace_fragment_spread_ext"
         
     | 
| 
       6 
     | 
    
         
            -
            require "graphql/language/nodes/validate_ext"
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       9 
     | 
    
         
            -
              module Client
         
     | 
| 
       10 
     | 
    
         
            -
                class Fragment < Node
         
     | 
| 
       11 
     | 
    
         
            -
                  def self.parse(str, schema: GraphQL::Client.schema)
         
     | 
| 
       12 
     | 
    
         
            -
                    str = str.strip
         
     | 
| 
       13 
     | 
    
         
            -
                    str, fragments = scan_interpolated_fragments(str)
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                    if str.start_with?("fragment")
         
     | 
| 
       16 
     | 
    
         
            -
                      str = str.sub(/^fragment on /, "fragment __anonymous__ on ")
         
     | 
| 
       17 
     | 
    
         
            -
                      doc = GraphQL.parse(str)
         
     | 
| 
       18 
     | 
    
         
            -
                      doc = doc.inject_selection(GraphQL::Language::Nodes::Field.new(name: "__typename"))
         
     | 
| 
       19 
     | 
    
         
            -
                      doc = doc.replace_fragment_spread(fragments)
         
     | 
| 
       20 
     | 
    
         
            -
                      fragment = doc.definitions.first
         
     | 
| 
       21 
     | 
    
         
            -
                      node = GraphQL::Language::Nodes::InlineFragment.new(type: fragment.type, directives: fragment.directives, selections: fragment.selections)
         
     | 
| 
       22 
     | 
    
         
            -
                    else
         
     | 
| 
       23 
     | 
    
         
            -
                      raise ArgumentError, "expected string to be a fragment:\n#{str}"
         
     | 
| 
       24 
     | 
    
         
            -
                    end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                    fragment = new(node.deep_freeze, fragments.values).freeze
         
     | 
| 
       27 
     | 
    
         
            -
                    fragment.node.validate!(schema: schema) if schema
         
     | 
| 
       28 
     | 
    
         
            -
                    fragment
         
     | 
| 
       29 
     | 
    
         
            -
                  end
         
     | 
| 
       30 
     | 
    
         
            -
                end
         
     | 
| 
       31 
     | 
    
         
            -
              end
         
     | 
| 
       32 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/graphql/client/node.rb
    DELETED
    
    | 
         @@ -1,36 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "active_support/inflector"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/language/nodes/query_result_class_ext"
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       6 
     | 
    
         
            -
              module Client
         
     | 
| 
       7 
     | 
    
         
            -
                class Node
         
     | 
| 
       8 
     | 
    
         
            -
                  def self.scan_interpolated_fragments(str)
         
     | 
| 
       9 
     | 
    
         
            -
                    fragments, index = {}, 1
         
     | 
| 
       10 
     | 
    
         
            -
                    str = str.gsub(/\.\.\.([a-zA-Z0-9_]+(::[a-zA-Z0-9_]+)+)/) { |m|
         
     | 
| 
       11 
     | 
    
         
            -
                      index += 1
         
     | 
| 
       12 
     | 
    
         
            -
                      name = "__fragment#{index}__"
         
     | 
| 
       13 
     | 
    
         
            -
                      fragments[name.to_sym] = ActiveSupport::Inflector.constantize($1).node
         
     | 
| 
       14 
     | 
    
         
            -
                      "...#{name}"
         
     | 
| 
       15 
     | 
    
         
            -
                    }
         
     | 
| 
       16 
     | 
    
         
            -
                    return str, fragments
         
     | 
| 
       17 
     | 
    
         
            -
                  end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                  attr_reader :node
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                  attr_reader :fragments
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                  attr_reader :type
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                  def initialize(node, fragments)
         
     | 
| 
       26 
     | 
    
         
            -
                    @node = node
         
     | 
| 
       27 
     | 
    
         
            -
                    @fragments = fragments
         
     | 
| 
       28 
     | 
    
         
            -
                    @type = node.query_result_class(shadow: fragments)
         
     | 
| 
       29 
     | 
    
         
            -
                  end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                  def new(*args)
         
     | 
| 
       32 
     | 
    
         
            -
                    type.new(*args)
         
     | 
| 
       33 
     | 
    
         
            -
                  end
         
     | 
| 
       34 
     | 
    
         
            -
                end
         
     | 
| 
       35 
     | 
    
         
            -
              end
         
     | 
| 
       36 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/graphql/client/query.rb
    DELETED
    
    | 
         @@ -1,30 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/client/node"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/language/nodes/deep_freeze_ext"
         
     | 
| 
       4 
     | 
    
         
            -
            require "graphql/language/nodes/inject_selection_ext"
         
     | 
| 
       5 
     | 
    
         
            -
            require "graphql/language/nodes/replace_fragment_spread_ext"
         
     | 
| 
       6 
     | 
    
         
            -
            require "graphql/language/nodes/validate_ext"
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       9 
     | 
    
         
            -
              module Client
         
     | 
| 
       10 
     | 
    
         
            -
                class Query < Node
         
     | 
| 
       11 
     | 
    
         
            -
                  def self.parse(str, schema: GraphQL::Client.schema)
         
     | 
| 
       12 
     | 
    
         
            -
                    str = str.strip
         
     | 
| 
       13 
     | 
    
         
            -
                    str, fragments = scan_interpolated_fragments(str)
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                    if str.start_with?("query")
         
     | 
| 
       16 
     | 
    
         
            -
                      doc = GraphQL.parse(str)
         
     | 
| 
       17 
     | 
    
         
            -
                      doc = doc.inject_selection(GraphQL::Language::Nodes::Field.new(name: "__typename"))
         
     | 
| 
       18 
     | 
    
         
            -
                      doc = doc.replace_fragment_spread(fragments)
         
     | 
| 
       19 
     | 
    
         
            -
                      node = doc.definitions.first
         
     | 
| 
       20 
     | 
    
         
            -
                    else
         
     | 
| 
       21 
     | 
    
         
            -
                      raise ArgumentError, "expected string to be a query:\n#{str}"
         
     | 
| 
       22 
     | 
    
         
            -
                    end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                    query = new(node.deep_freeze, fragments.values).freeze
         
     | 
| 
       25 
     | 
    
         
            -
                    query.node.validate!(schema: schema) if schema
         
     | 
| 
       26 
     | 
    
         
            -
                    query
         
     | 
| 
       27 
     | 
    
         
            -
                  end
         
     | 
| 
       28 
     | 
    
         
            -
                end
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,44 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/language/nodes/selection_ext"
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       5 
     | 
    
         
            -
              module Language
         
     | 
| 
       6 
     | 
    
         
            -
                module Nodes
         
     | 
| 
       7 
     | 
    
         
            -
                  module Selections
         
     | 
| 
       8 
     | 
    
         
            -
                    def inject_selection(*selections)
         
     | 
| 
       9 
     | 
    
         
            -
                      other = self.dup
         
     | 
| 
       10 
     | 
    
         
            -
                      other.selections = selections + self.selections.map do |selection|
         
     | 
| 
       11 
     | 
    
         
            -
                        case selection
         
     | 
| 
       12 
     | 
    
         
            -
                        when Selections
         
     | 
| 
       13 
     | 
    
         
            -
                          selection.inject_selection(*selections)
         
     | 
| 
       14 
     | 
    
         
            -
                        else
         
     | 
| 
       15 
     | 
    
         
            -
                          selection
         
     | 
| 
       16 
     | 
    
         
            -
                        end
         
     | 
| 
       17 
     | 
    
         
            -
                      end
         
     | 
| 
       18 
     | 
    
         
            -
                      other
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
                  end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                  class Document < AbstractNode
         
     | 
| 
       23 
     | 
    
         
            -
                    def inject_selection(*args)
         
     | 
| 
       24 
     | 
    
         
            -
                      other = self.dup
         
     | 
| 
       25 
     | 
    
         
            -
                      other.definitions = self.definitions.map do |definition|
         
     | 
| 
       26 
     | 
    
         
            -
                        case definition
         
     | 
| 
       27 
     | 
    
         
            -
                        when Selections
         
     | 
| 
       28 
     | 
    
         
            -
                          definition.inject_selection(*args)
         
     | 
| 
       29 
     | 
    
         
            -
                        else
         
     | 
| 
       30 
     | 
    
         
            -
                          definition
         
     | 
| 
       31 
     | 
    
         
            -
                        end
         
     | 
| 
       32 
     | 
    
         
            -
                      end
         
     | 
| 
       33 
     | 
    
         
            -
                      other
         
     | 
| 
       34 
     | 
    
         
            -
                    end
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  class Field < AbstractNode
         
     | 
| 
       38 
     | 
    
         
            -
                    def inject_selection(*selections)
         
     | 
| 
       39 
     | 
    
         
            -
                      self.selections.any? ? super : self
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
              end
         
     | 
| 
       44 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,70 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/language/nodes/selection_ext"
         
     | 
| 
       3 
     | 
    
         
            -
            require "graphql/client/query_result"
         
     | 
| 
       4 
     | 
    
         
            -
            require "set"
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       7 
     | 
    
         
            -
              module Language
         
     | 
| 
       8 
     | 
    
         
            -
                module Nodes
         
     | 
| 
       9 
     | 
    
         
            -
                  module Selections
         
     | 
| 
       10 
     | 
    
         
            -
                    # Public: Get GraphQL::QueryResult class for result of query.
         
     | 
| 
       11 
     | 
    
         
            -
                    #
         
     | 
| 
       12 
     | 
    
         
            -
                    # Returns subclass of QueryResult or nil.
         
     | 
| 
       13 
     | 
    
         
            -
                    def query_result_class(**kargs)
         
     | 
| 
       14 
     | 
    
         
            -
                      GraphQL::Client::QueryResult.define(fields: selections_query_result_classes(**kargs))
         
     | 
| 
       15 
     | 
    
         
            -
                    end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                    def selection_query_result_classes(**kargs)
         
     | 
| 
       18 
     | 
    
         
            -
                      selections_query_result_classes(**kargs)
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    # Internal: Gather QueryResult classes for each selection.
         
     | 
| 
       22 
     | 
    
         
            -
                    #
         
     | 
| 
       23 
     | 
    
         
            -
                    # Returns a Hash[String => (QueryResult|nil)].
         
     | 
| 
       24 
     | 
    
         
            -
                    def selections_query_result_classes(shadow: Set.new, **kargs)
         
     | 
| 
       25 
     | 
    
         
            -
                      self.selections.inject({}) do |h, selection|
         
     | 
| 
       26 
     | 
    
         
            -
                        case selection
         
     | 
| 
       27 
     | 
    
         
            -
                        when Selection
         
     | 
| 
       28 
     | 
    
         
            -
                          if !shadow.include?(selection)
         
     | 
| 
       29 
     | 
    
         
            -
                            selection.selection_query_result_classes(shadow: shadow, **kargs).each do |name, klass|
         
     | 
| 
       30 
     | 
    
         
            -
                              h[name] ? h[name] |= klass : h[name] = klass
         
     | 
| 
       31 
     | 
    
         
            -
                            end
         
     | 
| 
       32 
     | 
    
         
            -
                          end
         
     | 
| 
       33 
     | 
    
         
            -
                          h
         
     | 
| 
       34 
     | 
    
         
            -
                        else
         
     | 
| 
       35 
     | 
    
         
            -
                          raise TypeError, "expected selection to be of type Selection, but was #{selection.class}"
         
     | 
| 
       36 
     | 
    
         
            -
                        end
         
     | 
| 
       37 
     | 
    
         
            -
                      end
         
     | 
| 
       38 
     | 
    
         
            -
                    end
         
     | 
| 
       39 
     | 
    
         
            -
                  end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                  class Field < AbstractNode
         
     | 
| 
       42 
     | 
    
         
            -
                    # Public: Get GraphQL::QueryResult class for result of query.
         
     | 
| 
       43 
     | 
    
         
            -
                    #
         
     | 
| 
       44 
     | 
    
         
            -
                    # Returns subclass of QueryResult or nil.
         
     | 
| 
       45 
     | 
    
         
            -
                    def query_result_class(**kargs)
         
     | 
| 
       46 
     | 
    
         
            -
                      if self.selections.any?
         
     | 
| 
       47 
     | 
    
         
            -
                        super
         
     | 
| 
       48 
     | 
    
         
            -
                      else
         
     | 
| 
       49 
     | 
    
         
            -
                        nil
         
     | 
| 
       50 
     | 
    
         
            -
                      end
         
     | 
| 
       51 
     | 
    
         
            -
                    end
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                    def selection_query_result_classes(**kargs)
         
     | 
| 
       54 
     | 
    
         
            -
                      name = self.alias || self.name
         
     | 
| 
       55 
     | 
    
         
            -
                      { name => query_result_class(**kargs) }
         
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
       57 
     | 
    
         
            -
                  end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                  class FragmentSpread < AbstractNode
         
     | 
| 
       60 
     | 
    
         
            -
                    def selection_query_result_classes(fragments: {}, shadow: Set.new, **kargs)
         
     | 
| 
       61 
     | 
    
         
            -
                      unless fragment = fragments[name.to_sym]
         
     | 
| 
       62 
     | 
    
         
            -
                        raise ArgumentError, "missing fragment '#{name}'"
         
     | 
| 
       63 
     | 
    
         
            -
                      end
         
     | 
| 
       64 
     | 
    
         
            -
                      return {} if shadow.include?(fragment)
         
     | 
| 
       65 
     | 
    
         
            -
                      fragment.selection_query_result_classes(fragments: fragments, shadow: shadow, **kargs)
         
     | 
| 
       66 
     | 
    
         
            -
                    end
         
     | 
| 
       67 
     | 
    
         
            -
                  end
         
     | 
| 
       68 
     | 
    
         
            -
                end
         
     | 
| 
       69 
     | 
    
         
            -
              end
         
     | 
| 
       70 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,44 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/language/nodes/selection_ext"
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       5 
     | 
    
         
            -
              module Language
         
     | 
| 
       6 
     | 
    
         
            -
                module Nodes
         
     | 
| 
       7 
     | 
    
         
            -
                  module Selections
         
     | 
| 
       8 
     | 
    
         
            -
                    def replace_fragment_spread(fragments)
         
     | 
| 
       9 
     | 
    
         
            -
                      other = self.dup
         
     | 
| 
       10 
     | 
    
         
            -
                      other.selections = self.selections.map do |selection|
         
     | 
| 
       11 
     | 
    
         
            -
                        case selection
         
     | 
| 
       12 
     | 
    
         
            -
                        when FragmentSpread
         
     | 
| 
       13 
     | 
    
         
            -
                          if fragment = fragments[selection.name.to_sym]
         
     | 
| 
       14 
     | 
    
         
            -
                            InlineFragment.new(type: fragment.type, directives: fragment.directives, selections: fragment.selections)
         
     | 
| 
       15 
     | 
    
         
            -
                          else
         
     | 
| 
       16 
     | 
    
         
            -
                            selection
         
     | 
| 
       17 
     | 
    
         
            -
                          end
         
     | 
| 
       18 
     | 
    
         
            -
                        when Selections
         
     | 
| 
       19 
     | 
    
         
            -
                          selection.replace_fragment_spread(fragments)
         
     | 
| 
       20 
     | 
    
         
            -
                        else
         
     | 
| 
       21 
     | 
    
         
            -
                          selection
         
     | 
| 
       22 
     | 
    
         
            -
                        end
         
     | 
| 
       23 
     | 
    
         
            -
                      end
         
     | 
| 
       24 
     | 
    
         
            -
                      other
         
     | 
| 
       25 
     | 
    
         
            -
                    end
         
     | 
| 
       26 
     | 
    
         
            -
                  end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                  class Document < AbstractNode
         
     | 
| 
       29 
     | 
    
         
            -
                    def replace_fragment_spread(fragments)
         
     | 
| 
       30 
     | 
    
         
            -
                      other = self.dup
         
     | 
| 
       31 
     | 
    
         
            -
                      other.definitions = self.definitions.map do |definition|
         
     | 
| 
       32 
     | 
    
         
            -
                        case definition
         
     | 
| 
       33 
     | 
    
         
            -
                        when Selections
         
     | 
| 
       34 
     | 
    
         
            -
                          definition.replace_fragment_spread(fragments)
         
     | 
| 
       35 
     | 
    
         
            -
                        else
         
     | 
| 
       36 
     | 
    
         
            -
                          definition
         
     | 
| 
       37 
     | 
    
         
            -
                        end
         
     | 
| 
       38 
     | 
    
         
            -
                      end
         
     | 
| 
       39 
     | 
    
         
            -
                      other
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
              end
         
     | 
| 
       44 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,37 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       4 
     | 
    
         
            -
              module Language
         
     | 
| 
       5 
     | 
    
         
            -
                module Nodes
         
     | 
| 
       6 
     | 
    
         
            -
                  # Public: Define shared trait for Nodes that have a "selections" collection.
         
     | 
| 
       7 
     | 
    
         
            -
                  module Selections
         
     | 
| 
       8 
     | 
    
         
            -
                  end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                  # Public: Define shared trait for Nodes that may be in a "selections" collection.
         
     | 
| 
       11 
     | 
    
         
            -
                  module Selection
         
     | 
| 
       12 
     | 
    
         
            -
                  end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                  class Field < AbstractNode
         
     | 
| 
       15 
     | 
    
         
            -
                    include Selection
         
     | 
| 
       16 
     | 
    
         
            -
                    include Selections
         
     | 
| 
       17 
     | 
    
         
            -
                  end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                  class FragmentDefinition < AbstractNode
         
     | 
| 
       20 
     | 
    
         
            -
                    include Selections
         
     | 
| 
       21 
     | 
    
         
            -
                  end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                  class FragmentSpread < AbstractNode
         
     | 
| 
       24 
     | 
    
         
            -
                    include Selection
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                  class InlineFragment < AbstractNode
         
     | 
| 
       28 
     | 
    
         
            -
                    include Selection
         
     | 
| 
       29 
     | 
    
         
            -
                    include Selections
         
     | 
| 
       30 
     | 
    
         
            -
                  end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                  class OperationDefinition < AbstractNode
         
     | 
| 
       33 
     | 
    
         
            -
                    include Selections
         
     | 
| 
       34 
     | 
    
         
            -
                  end
         
     | 
| 
       35 
     | 
    
         
            -
                end
         
     | 
| 
       36 
     | 
    
         
            -
              end
         
     | 
| 
       37 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,45 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       4 
     | 
    
         
            -
              class ValidationError < GraphQL::ExecutionError
         
     | 
| 
       5 
     | 
    
         
            -
              end
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
              module Language
         
     | 
| 
       8 
     | 
    
         
            -
                module Nodes
         
     | 
| 
       9 
     | 
    
         
            -
                  class Document < AbstractNode
         
     | 
| 
       10 
     | 
    
         
            -
                    def validate!(schema:, rules: StaticValidation::ALL_RULES)
         
     | 
| 
       11 
     | 
    
         
            -
                      validator = StaticValidation::Validator.new(schema: schema, rules: rules)
         
     | 
| 
       12 
     | 
    
         
            -
                      query = Query.new(schema, document: self)
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                      validator.validate(query).fetch(:errors).each do |error|
         
     | 
| 
       15 
     | 
    
         
            -
                        raise ValidationError, error["message"]
         
     | 
| 
       16 
     | 
    
         
            -
                      end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                      nil
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
                  end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                  class FragmentDefinition < AbstractNode
         
     | 
| 
       23 
     | 
    
         
            -
                    def validate!(schema:, **kargs)
         
     | 
| 
       24 
     | 
    
         
            -
                      document = Document.new(definitions: [self])
         
     | 
| 
       25 
     | 
    
         
            -
                      rules = StaticValidation::ALL_RULES - [StaticValidation::FragmentsAreUsed]
         
     | 
| 
       26 
     | 
    
         
            -
                      document.validate!(schema: schema, rules: rules, **kargs)
         
     | 
| 
       27 
     | 
    
         
            -
                    end
         
     | 
| 
       28 
     | 
    
         
            -
                  end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                  class OperationDefinition < AbstractNode
         
     | 
| 
       31 
     | 
    
         
            -
                    def validate!(schema:, **kargs)
         
     | 
| 
       32 
     | 
    
         
            -
                      document = Document.new(definitions: [self])
         
     | 
| 
       33 
     | 
    
         
            -
                      document.validate!(schema: schema, **kargs)
         
     | 
| 
       34 
     | 
    
         
            -
                    end
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  class InlineFragment < AbstractNode
         
     | 
| 
       38 
     | 
    
         
            -
                    def validate!(schema:, **kargs)
         
     | 
| 
       39 
     | 
    
         
            -
                      fragment = FragmentDefinition.new(name: "FooFragment", type: self.type, directives: self.directives, selections: self.selections)
         
     | 
| 
       40 
     | 
    
         
            -
                      fragment.validate!(schema: schema, **kargs)
         
     | 
| 
       41 
     | 
    
         
            -
                    end
         
     | 
| 
       42 
     | 
    
         
            -
                  end
         
     | 
| 
       43 
     | 
    
         
            -
                end
         
     | 
| 
       44 
     | 
    
         
            -
              end
         
     | 
| 
       45 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,19 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "graphql/language/nodes/deep_freeze_ext"
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       5 
     | 
    
         
            -
              module Relay
         
     | 
| 
       6 
     | 
    
         
            -
                NODE_QUERY = GraphQL.parse(<<-'GRAPHQL').definitions.first.deep_freeze
         
     | 
| 
       7 
     | 
    
         
            -
                  query($id: ID!) {
         
     | 
| 
       8 
     | 
    
         
            -
                    node(id: $id) {
         
     | 
| 
       9 
     | 
    
         
            -
                      ...NodeFragment
         
     | 
| 
       10 
     | 
    
         
            -
                    }
         
     | 
| 
       11 
     | 
    
         
            -
                  }
         
     | 
| 
       12 
     | 
    
         
            -
                GRAPHQL
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                def self.NodeQuery(fragment)
         
     | 
| 
       15 
     | 
    
         
            -
                  fragment = GraphQL::Language::Nodes::FragmentDefinition.new(name: "NodeFragment", type: fragment.type, selections: fragment.selections)
         
     | 
| 
       16 
     | 
    
         
            -
                  GraphQL::Language::Nodes::Document.new(definitions: [NODE_QUERY, fragment])
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
              end
         
     | 
| 
       19 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,101 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "graphql"
         
     | 
| 
       2 
     | 
    
         
            -
            require "json"
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            module GraphQL
         
     | 
| 
       5 
     | 
    
         
            -
              class Schema
         
     | 
| 
       6 
     | 
    
         
            -
                module JSONLoader
         
     | 
| 
       7 
     | 
    
         
            -
                  def self.define_schema(json)
         
     | 
| 
       8 
     | 
    
         
            -
                    schema = JSON.load(json).fetch("data").fetch("__schema")
         
     | 
| 
       9 
     | 
    
         
            -
                    types = Schema::JSONLoader.define_types(schema)
         
     | 
| 
       10 
     | 
    
         
            -
                    # TODO: handle schema["mutationType"]
         
     | 
| 
       11 
     | 
    
         
            -
                    # TODO: handle schema["subscriptionType"]
         
     | 
| 
       12 
     | 
    
         
            -
                    query = types.fetch(schema.fetch("queryType").fetch("name"))
         
     | 
| 
       13 
     | 
    
         
            -
                    Schema.new(query: query, types: types.values)
         
     | 
| 
       14 
     | 
    
         
            -
                  end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                  def self.define_types(schema)
         
     | 
| 
       17 
     | 
    
         
            -
                    schema.fetch("types").inject({}) do |types, type|
         
     | 
| 
       18 
     | 
    
         
            -
                      type_kind, type_name = type.fetch("kind"), type.fetch("name")
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                      if !type_name.start_with?("__")
         
     | 
| 
       21 
     | 
    
         
            -
                        case type_kind
         
     | 
| 
       22 
     | 
    
         
            -
                        when "INTERFACE"
         
     | 
| 
       23 
     | 
    
         
            -
                          types[type_name] = define_interface(types, type)
         
     | 
| 
       24 
     | 
    
         
            -
                        when "OBJECT"
         
     | 
| 
       25 
     | 
    
         
            -
                          types[type_name] = define_object(types, type)
         
     | 
| 
       26 
     | 
    
         
            -
                        when "SCALAR"
         
     | 
| 
       27 
     | 
    
         
            -
                          types[type_name] = define_scalar(types, type)
         
     | 
| 
       28 
     | 
    
         
            -
                        else
         
     | 
| 
       29 
     | 
    
         
            -
                          # TODO: handle other type kinds
         
     | 
| 
       30 
     | 
    
         
            -
                          fail NotImplementedError, type_kind + " not implemented"
         
     | 
| 
       31 
     | 
    
         
            -
                        end
         
     | 
| 
       32 
     | 
    
         
            -
                      end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                      types
         
     | 
| 
       35 
     | 
    
         
            -
                    end
         
     | 
| 
       36 
     | 
    
         
            -
                  end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                  def self.resolve_type(types, type)
         
     | 
| 
       39 
     | 
    
         
            -
                    case kind = type.fetch("kind")
         
     | 
| 
       40 
     | 
    
         
            -
                    when "INTERFACE"
         
     | 
| 
       41 
     | 
    
         
            -
                      types.fetch(type.fetch("name"))
         
     | 
| 
       42 
     | 
    
         
            -
                    when "LIST"
         
     | 
| 
       43 
     | 
    
         
            -
                      ListType.new(of_type: resolve_type(types, type.fetch("ofType")))
         
     | 
| 
       44 
     | 
    
         
            -
                    when "NON_NULL"
         
     | 
| 
       45 
     | 
    
         
            -
                      NonNullType.new(of_type: resolve_type(types, type.fetch("ofType")))
         
     | 
| 
       46 
     | 
    
         
            -
                    when "OBJECT"
         
     | 
| 
       47 
     | 
    
         
            -
                      types.fetch(type.fetch("name"))
         
     | 
| 
       48 
     | 
    
         
            -
                    when "SCALAR"
         
     | 
| 
       49 
     | 
    
         
            -
                      types.fetch(type.fetch("name"))
         
     | 
| 
       50 
     | 
    
         
            -
                    else
         
     | 
| 
       51 
     | 
    
         
            -
                      # TODO: handle other type kinds
         
     | 
| 
       52 
     | 
    
         
            -
                      fail NotImplementedError, kind + " not implemented"
         
     | 
| 
       53 
     | 
    
         
            -
                    end
         
     | 
| 
       54 
     | 
    
         
            -
                  end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                  def self.define_interface(types, type)
         
     | 
| 
       57 
     | 
    
         
            -
                    InterfaceType.define do
         
     | 
| 
       58 
     | 
    
         
            -
                      name type.fetch("name")
         
     | 
| 
       59 
     | 
    
         
            -
                    end
         
     | 
| 
       60 
     | 
    
         
            -
                  end
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                  def self.define_object(types, type)
         
     | 
| 
       63 
     | 
    
         
            -
                    ObjectType.define do
         
     | 
| 
       64 
     | 
    
         
            -
                      name type.fetch("name")
         
     | 
| 
       65 
     | 
    
         
            -
                      description type["description"]
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
                      Array(type["fields"]).each do |field_data|
         
     | 
| 
       68 
     | 
    
         
            -
                        field field_data["name"] do
         
     | 
| 
       69 
     | 
    
         
            -
                          type JSONLoader.resolve_type(types, field_data["type"])
         
     | 
| 
       70 
     | 
    
         
            -
                          description field_data["description"]
         
     | 
| 
       71 
     | 
    
         
            -
                          field_data["args"].each do |arg|
         
     | 
| 
       72 
     | 
    
         
            -
                            argument arg["name"] do
         
     | 
| 
       73 
     | 
    
         
            -
                              type JSONLoader.resolve_type(types, arg["type"])
         
     | 
| 
       74 
     | 
    
         
            -
                              description arg["description"]
         
     | 
| 
       75 
     | 
    
         
            -
                            end
         
     | 
| 
       76 
     | 
    
         
            -
                          end
         
     | 
| 
       77 
     | 
    
         
            -
                        end
         
     | 
| 
       78 
     | 
    
         
            -
                      end
         
     | 
| 
       79 
     | 
    
         
            -
                    end
         
     | 
| 
       80 
     | 
    
         
            -
                  end
         
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                  def self.define_scalar(types, type)
         
     | 
| 
       83 
     | 
    
         
            -
                    case name = type.fetch("name")
         
     | 
| 
       84 
     | 
    
         
            -
                    when "Int"
         
     | 
| 
       85 
     | 
    
         
            -
                      INT_TYPE
         
     | 
| 
       86 
     | 
    
         
            -
                    when "String"
         
     | 
| 
       87 
     | 
    
         
            -
                      STRING_TYPE
         
     | 
| 
       88 
     | 
    
         
            -
                    when "Float"
         
     | 
| 
       89 
     | 
    
         
            -
                      FLOAT_TYPE
         
     | 
| 
       90 
     | 
    
         
            -
                    when "Boolean"
         
     | 
| 
       91 
     | 
    
         
            -
                      BOOLEAN_TYPE
         
     | 
| 
       92 
     | 
    
         
            -
                    when "ID"
         
     | 
| 
       93 
     | 
    
         
            -
                      ID_TYPE
         
     | 
| 
       94 
     | 
    
         
            -
                    else
         
     | 
| 
       95 
     | 
    
         
            -
                      # TODO: handle other scalar names
         
     | 
| 
       96 
     | 
    
         
            -
                      fail NotImplementedError, name + " scalar not implemented"
         
     | 
| 
       97 
     | 
    
         
            -
                    end
         
     | 
| 
       98 
     | 
    
         
            -
                  end
         
     | 
| 
       99 
     | 
    
         
            -
                end
         
     | 
| 
       100 
     | 
    
         
            -
              end
         
     | 
| 
       101 
     | 
    
         
            -
            end
         
     |