module GraphQL::Analysis::AST

Calculate the complexity of a query, using {Field#complexity} values.

A query reducer for measuring the depth of a given query.

See graphql-ruby.org/queries/ast_analysis.html for more examples.

@example Logging the depth of a query

class LogQueryDepth < GraphQL::Analysis::QueryDepth
  def result
    log("GraphQL query depth: #{@max_depth}")
  end
end

# In your Schema file:

class MySchema < GraphQL::Schema
  use GraphQL::Analysis::AST
  query_analyzer LogQueryDepth
end

# When you run the query, the depth will get logged:

Schema.execute(query_str)
# GraphQL query depth: 8

Public Instance Methods

analysis_errors(results) click to toggle source
# File lib/graphql/analysis/ast.rb, line 86
def analysis_errors(results)
  results.flatten.select { |r| r.is_a?(GraphQL::AnalysisError) }
end
analyze_multiplex(multiplex, analyzers) click to toggle source

Analyze a multiplex, and all queries within. Multiplex analyzers are ran for all queries, keeping state. Query analyzers are ran per query, without carrying state between queries.

@param multiplex [GraphQL::Execution::Multiplex] @param analyzers [Array<GraphQL::Analysis::AST::Analyzer>] @return [Array<Any>] Results from multiplex analyzers

# File lib/graphql/analysis/ast.rb, line 31
def analyze_multiplex(multiplex, analyzers)
  multiplex_analyzers = analyzers.map { |analyzer| analyzer.new(multiplex) }

  multiplex.trace("analyze_multiplex", { multiplex: multiplex }) do
    query_results = multiplex.queries.map do |query|
      if query.valid?
        analyze_query(
          query,
          query.analyzers,
          multiplex_analyzers: multiplex_analyzers
        )
      else
        []
      end
    end

    multiplex_results = multiplex_analyzers.map(&:result)
    multiplex_errors = analysis_errors(multiplex_results)

    multiplex.queries.each_with_index do |query, idx|
      query.analysis_errors = multiplex_errors + analysis_errors(query_results[idx])
    end
    multiplex_results
  end
end
analyze_query(query, analyzers, multiplex_analyzers: []) click to toggle source

@param query [GraphQL::Query] @param analyzers [Array<GraphQL::Analysis::AST::Analyzer>] @return [Array<Any>] Results from those analyzers

# File lib/graphql/analysis/ast.rb, line 60
def analyze_query(query, analyzers, multiplex_analyzers: [])
  query.trace("analyze_query", { query: query }) do
    query_analyzers = analyzers
      .map { |analyzer| analyzer.new(query) }
      .select { |analyzer| analyzer.analyze? }

    analyzers_to_run = query_analyzers + multiplex_analyzers
    if analyzers_to_run.any?
      visitor = GraphQL::Analysis::AST::Visitor.new(
        query: query,
        analyzers: analyzers_to_run
      )

      visitor.visit

      if visitor.rescued_errors.any?
        visitor.rescued_errors
      else
        query_analyzers.map(&:result)
      end
    else
      []
    end
  end
end
use(schema_class) click to toggle source
# File lib/graphql/analysis/ast.rb, line 15
def use(schema_class)
  if schema_class.analysis_engine == self
    definition_line = caller(2, 1).first
    GraphQL::Deprecation.warn("GraphQL::Analysis::AST is now the default; remove `use GraphQL::Analysis::AST` from the schema definition (#{definition_line})")
  else
    schema_class.analysis_engine = self
  end
end