Class: GraphQL::Stitching::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/stitching/request.rb

Constant Summary collapse

SUPPORTED_OPERATIONS =
["query", "mutation"].freeze
SKIP_INCLUDE_DIRECTIVE =
/@(?:skip|include)/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(supergraph, document, operation_name: nil, variables: nil, context: nil) ⇒ Request

Creates a new supergraph request.

Parameters:

  • supergraph (Supergraph)

    supergraph instance that resolves the request.

  • document (String, GraphQL::Language::Nodes::Document)

    the request string or parsed AST.

  • operation_name (String, nil) (defaults to: nil)

    operation name selected for the request.

  • variables (Hash, nil) (defaults to: nil)

    input variables for the request.

  • context (Hash, nil) (defaults to: nil)

    a contextual object passed through resolver flows.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/graphql/stitching/request.rb', line 30

def initialize(supergraph, document, operation_name: nil, variables: nil, context: nil)
  @supergraph = supergraph
  @string = nil
  @digest = nil
  @normalized_string = nil
  @normalized_digest = nil
  @operation = nil
  @operation_directives = nil
  @variable_definitions = nil
  @fragment_definitions = nil
  @plan = nil

  @document = if document.is_a?(String)
    @string = document
    GraphQL.parse(document)
  else
    document
  end

  @operation_name = operation_name
  @variables = variables || {}
  @context = context || GraphQL::Stitching::EMPTY_OBJECT
end

Instance Attribute Details

#contextHash (readonly)

Returns contextual object passed through resolver flows.

Returns:

  • (Hash)

    contextual object passed through resolver flows.



22
23
24
# File 'lib/graphql/stitching/request.rb', line 22

def context
  @context
end

#documentGraphQL::Language::Nodes::Document (readonly)

Returns the parsed GraphQL AST document.

Returns:

  • (GraphQL::Language::Nodes::Document)

    the parsed GraphQL AST document.



13
14
15
# File 'lib/graphql/stitching/request.rb', line 13

def document
  @document
end

#operation_nameString (readonly)

Returns operation name selected for the request.

Returns:

  • (String)

    operation name selected for the request.



19
20
21
# File 'lib/graphql/stitching/request.rb', line 19

def operation_name
  @operation_name
end

#supergraphSupergraph (readonly)

Returns supergraph instance that resolves the request.

Returns:

  • (Supergraph)

    supergraph instance that resolves the request.



10
11
12
# File 'lib/graphql/stitching/request.rb', line 10

def supergraph
  @supergraph
end

#variablesHash (readonly)

Returns input variables for the request.

Returns:

  • (Hash)

    input variables for the request.



16
17
18
# File 'lib/graphql/stitching/request.rb', line 16

def variables
  @variables
end

Instance Method Details

#digestString

Returns a digest of the original document string. Generally faster but less consistent.

Returns:

  • (String)

    a digest of the original document string. Generally faster but less consistent.



65
66
67
# File 'lib/graphql/stitching/request.rb', line 65

def digest
  @digest ||= Digest::SHA2.hexdigest(string)
end

#execute(raw: false) ⇒ Hash

Executes the request and returns the rendered response.

Parameters:

  • raw (Boolean) (defaults to: false)

    specifies the result should be unshaped without pruning or null bubbling. Useful for debugging.

Returns:

  • (Hash)

    the rendered GraphQL response with "data" and "errors" sections.



153
154
155
# File 'lib/graphql/stitching/request.rb', line 153

def execute(raw: false)
  GraphQL::Stitching::Executor.new(self).perform(raw: raw)
end

#fragment_definitionsHash<String, GraphQL::Language::Nodes::FragmentDefinition>

Returns:

  • (Hash<String, GraphQL::Language::Nodes::FragmentDefinition>)


109
110
111
112
113
# File 'lib/graphql/stitching/request.rb', line 109

def fragment_definitions
  @fragment_definitions ||= @document.definitions.each_with_object({}) do |d, memo|
    memo[d.name] = d if d.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
  end
end

#normalized_digestString

Returns a digest of the normalized document string. Slower but more consistent.

Returns:

  • (String)

    a digest of the normalized document string. Slower but more consistent.



70
71
72
# File 'lib/graphql/stitching/request.rb', line 70

def normalized_digest
  @normalized_digest ||= Digest::SHA2.hexdigest(normalized_string)
end

#normalized_stringString

Returns a print of the parsed AST document with consistent whitespace.

Returns:

  • (String)

    a print of the parsed AST document with consistent whitespace.



60
61
62
# File 'lib/graphql/stitching/request.rb', line 60

def normalized_string
  @normalized_string ||= @document.to_query_string
end

#operationGraphQL::Language::Nodes::OperationDefinition

Returns The selected root operation for the request.

Returns:

  • (GraphQL::Language::Nodes::OperationDefinition)

    The selected root operation for the request.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/graphql/stitching/request.rb', line 75

def operation
  @operation ||= begin
    operation_defs = @document.definitions.select do |d|
      next unless d.is_a?(GraphQL::Language::Nodes::OperationDefinition)
      next unless SUPPORTED_OPERATIONS.include?(d.operation_type)
      @operation_name ? d.name == @operation_name : true
    end

    if operation_defs.length < 1
      raise GraphQL::ExecutionError, "Invalid root operation for given name and operation type."
    elsif operation_defs.length > 1
      raise GraphQL::ExecutionError, "An operation name is required when sending multiple operations."
    end

    operation_defs.first
  end
end

#operation_directivesString

Returns A string of directives applied to the root operation. These are passed through in all subgraph requests.

Returns:

  • (String)

    A string of directives applied to the root operation. These are passed through in all subgraph requests.



94
95
96
97
98
99
# File 'lib/graphql/stitching/request.rb', line 94

def operation_directives
  @operation_directives ||= if operation.directives.any?
    printer = GraphQL::Language::Printer.new
    operation.directives.map { printer.print(_1) }.join(" ")
  end
end

#plan(new_plan = nil) ⇒ Plan

Gets and sets the query plan for the request. Assigned query plans may pull from cache.

Parameters:

  • new_plan (Plan, nil) (defaults to: nil)

    a cached query plan for the request.

Returns:

  • (Plan)

    query plan for the request.



141
142
143
144
145
146
147
148
# File 'lib/graphql/stitching/request.rb', line 141

def plan(new_plan = nil)
  if new_plan
    raise StitchingError, "Plan must be a `GraphQL::Stitching::Plan`." unless new_plan.is_a?(Plan)
    @plan = new_plan
  else
    @plan ||= GraphQL::Stitching::Planner.new(self).perform
  end
end

#prepare!Object

Prepares the request for stitching by rendering variable defaults and applying @skip/@include conditionals.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/graphql/stitching/request.rb', line 121

def prepare!
  operation.variables.each do |v|
    @variables[v.name] = v.default_value if @variables[v.name].nil? && !v.default_value.nil?
  end

  if @string.nil? || @string.match?(SKIP_INCLUDE_DIRECTIVE)
    SkipInclude.render(@document, @variables) do |modified_ast|
      @document = modified_ast
      @string = @normalized_string = nil
      @digest = @normalized_digest = nil
      @operation = @operation_directives = @variable_definitions = @plan = nil
    end
  end

  self
end

#stringString

Returns the original document string, or a print of the parsed AST document.

Returns:

  • (String)

    the original document string, or a print of the parsed AST document.



55
56
57
# File 'lib/graphql/stitching/request.rb', line 55

def string
  @string || normalized_string
end

#validateObject

Validates the request using the combined supergraph schema.



116
117
118
# File 'lib/graphql/stitching/request.rb', line 116

def validate
  @supergraph.schema.validate(@document, context: @context)
end

#variable_definitionsHash<String, GraphQL::Language::Nodes::AbstractNode>

Returns:

  • (Hash<String, GraphQL::Language::Nodes::AbstractNode>)


102
103
104
105
106
# File 'lib/graphql/stitching/request.rb', line 102

def variable_definitions
  @variable_definitions ||= operation.variables.each_with_object({}) do |v, memo|
    memo[v.name] = v.type
  end
end