Module: GraphQL::StaticValidation::DefinitionDependencies

Included in:
InterpreterVisitor
Defined in:
lib/graphql/static_validation/definition_dependencies.rb

Overview

Track fragment dependencies for operations and expose the fragment definitions which are used by a given operation

Defined Under Namespace

Classes: DependencyMap, NodeWithPath

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#dependenciesObject (readonly)

Returns the value of attribute dependencies.



8
9
10
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 8

def dependencies
  @dependencies
end

Instance Method Details

#dependency_map(&block) ⇒ DependencyMap

A map of operation definitions to an array of that operation's dependencies

Returns:



69
70
71
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 69

def dependency_map(&block)
  @dependency_map ||= resolve_dependencies(&block)
end

#initializeObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 10

def initialize(*)
  super
  @defdep_node_paths = {}

  # { name => [node, ...] } pairs for fragments (although duplicate-named fragments are _invalid_, they are _possible_)
  @defdep_fragment_definitions = Hash.new{ |h, k| h[k] = [] }

  # This tracks dependencies from fragment to Node where it was used
  # { fragment_definition_name => [dependent_node, dependent_node]}
  @defdep_dependent_definitions = Hash.new { |h, k| h[k] = Set.new }

  # First-level usages of spreads within definitions
  # (When a key has an empty list as its value,
  #  we can resolve that key's dependents)
  # { definition_node => [node, node ...] }
  @defdep_immediate_dependencies = Hash.new { |h, k| h[k] = Set.new }

  # When we encounter a spread,
  # this node is the one who depends on it
  @defdep_current_parent = nil
end

#on_document(node, parent) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 32

def on_document(node, parent)
  node.definitions.each do |definition|
    if definition.is_a? GraphQL::Language::Nodes::FragmentDefinition
      @defdep_fragment_definitions[definition.name] << definition
    end
  end
  super
  @dependencies = dependency_map { |defn, spreads, frag|
    context.on_dependency_resolve_handlers.each { |h| h.call(defn, spreads, frag) }
  }
end

#on_fragment_definition(node, parent) ⇒ Object



51
52
53
54
55
56
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 51

def on_fragment_definition(node, parent)
  @defdep_node_paths[node] = NodeWithPath.new(node, context.path)
  @defdep_current_parent = node
  super
  @defdep_current_parent = nil
end

#on_fragment_spread(node, parent) ⇒ Object



58
59
60
61
62
63
64
65
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 58

def on_fragment_spread(node, parent)
  @defdep_node_paths[node] = NodeWithPath.new(node, context.path)

  # Track both sides of the dependency
  @defdep_dependent_definitions[node.name] << @defdep_current_parent
  @defdep_immediate_dependencies[@defdep_current_parent] << node
  super
end

#on_operation_definition(node, prev_node) ⇒ Object



44
45
46
47
48
49
# File 'lib/graphql/static_validation/definition_dependencies.rb', line 44

def on_operation_definition(node, prev_node)
  @defdep_node_paths[node.name] = NodeWithPath.new(node, context.path)
  @defdep_current_parent = node
  super
  @defdep_current_parent = nil
end