class GraphQL::Client::Definition
Definitions are constructed by Client.parse
and wrap a parsed AST of the query string as well as hold references to any external query definition dependencies.
Definitions MUST be assigned to a constant.
Constants
- EMPTY_SET
Attributes
Internal: Get associated owner GraphQL::Client
instance.
Internal: Get underlying operation or fragment definition AST node for definition.
Returns OperationDefinition
or FragmentDefinition
object.
Public: Get document with only the definitions needed to perform this operation.
Returns GraphQL::Language::Nodes::Document with one OperationDefinition
and any FragmentDefinition
dependencies.
Internal root schema class for definition. Returns GraphQL::Client::Schema::ObjectType
or GraphQL::Client::Schema::PossibleTypes
.
Internal: Get original document that created this definition, without any additional dependencies.
Returns GraphQL::Language::Nodes::Document.
Public: Returns the Ruby source filename and line number containing this definition was not defined in Ruby.
Returns Array pair of [String, Fixnum].
Public Class Methods
# File lib/graphql/client/definition.rb, line 17 def self.for(ast_node:, **kargs) case ast_node when Language::Nodes::OperationDefinition OperationDefinition.new(ast_node: ast_node, **kargs) when Language::Nodes::FragmentDefinition FragmentDefinition.new(ast_node: ast_node, **kargs) else raise TypeError, "expected node to be a definition type, but was #{ast_node.class}" end end
# File lib/graphql/client/definition.rb, line 28 def initialize(client:, document:, source_document:, ast_node:, source_location:) @client = client @document = document @source_document = source_document @definition_node = ast_node @source_location = source_location definition_type = case ast_node when GraphQL::Language::Nodes::OperationDefinition case ast_node.operation_type when "mutation" @client.schema.mutation when "subscription" @client.schema.subscription when "query", nil @client.schema.query else raise "Unexpected operation_type: #{ast_node.operation_type}" end when GraphQL::Language::Nodes::FragmentDefinition @client.get_type(ast_node.type.name) else raise "Unexpected ast_node: #{ast_node}" end @schema_class = client.types.define_class(self, [ast_node], definition_type) # Clear cache only needed during initialization @indexes = nil end
Public Instance Methods
Public: Global name of definition in client document.
Returns a GraphQL
safe name of the Ruby constant String.
"Users::UserQuery" #=> "Users__UserQuery"
Returns String.
# File lib/graphql/client/definition.rb, line 86 def definition_name return @definition_name if defined?(@definition_name) if name @definition_name = name.gsub("::", "__").freeze else "#{self.class.name}_#{object_id}".gsub("::", "__").freeze end end
Internal: Nodes AST indexes.
# File lib/graphql/client/definition.rb, line 148 def indexes @indexes ||= begin visitor = GraphQL::Language::Visitor.new(document) definitions = index_node_definitions(visitor) spreads = index_spreads(visitor) visitor.visit { definitions: definitions, spreads: spreads } end end
# File lib/graphql/client/definition.rb, line 109 def new(obj, errors = Errors.new) case schema_class when GraphQL::Client::Schema::PossibleTypes case obj when NilClass obj else cast_object(obj) end when GraphQL::Client::Schema::ObjectType::WithDefinition case obj when schema_class.klass if obj._definer == schema_class obj else cast_object(obj) end when nil nil when Hash schema_class.new(obj, errors) else cast_object(obj) end when GraphQL::Client::Schema::ObjectType case obj when nil, schema_class obj when Hash schema_class.new(obj, errors) else cast_object(obj) end else raise TypeError, "unexpected #{schema_class}" end end
Private Instance Methods
# File lib/graphql/client/definition.rb, line 160 def cast_object(obj) if obj.class.is_a?(GraphQL::Client::Schema::ObjectType) unless obj._spreads.include?(definition_node.name) raise TypeError, "#{definition_node.name} is not included in #{obj.source_definition.name}" end schema_class.cast(obj.to_h, obj.errors) else raise TypeError, "unexpected #{obj.class}" end end
# File lib/graphql/client/definition.rb, line 187 def flatten_spreads(node) spreads = [] node.selections.each do |selection| case selection when Language::Nodes::FragmentSpread spreads << selection when Language::Nodes::InlineFragment spreads.concat(flatten_spreads(selection)) else # Do nothing, not a spread end end spreads end
# File lib/graphql/client/definition.rb, line 202 def index_node_definitions(visitor) current_definition = nil enter_definition = ->(node, _parent) { current_definition = node } leave_definition = ->(node, _parent) { current_definition = nil } visitor[GraphQL::Language::Nodes::FragmentDefinition].enter << enter_definition visitor[GraphQL::Language::Nodes::FragmentDefinition].leave << leave_definition visitor[GraphQL::Language::Nodes::OperationDefinition].enter << enter_definition visitor[GraphQL::Language::Nodes::OperationDefinition].leave << leave_definition definitions = {} on_node = ->(node, _parent) { definitions[node] = current_definition } visitor[GraphQL::Language::Nodes::Field] << on_node visitor[GraphQL::Language::Nodes::FragmentDefinition] << on_node visitor[GraphQL::Language::Nodes::InlineFragment] << on_node visitor[GraphQL::Language::Nodes::OperationDefinition] << on_node definitions end
# File lib/graphql/client/definition.rb, line 173 def index_spreads(visitor) spreads = {} on_node = ->(node, _parent) do node_spreads = flatten_spreads(node).map(&:name) spreads[node] = node_spreads.empty? ? EMPTY_SET : Set.new(node_spreads).freeze end visitor[GraphQL::Language::Nodes::Field] << on_node visitor[GraphQL::Language::Nodes::FragmentDefinition] << on_node visitor[GraphQL::Language::Nodes::OperationDefinition] << on_node spreads end