module GraphQL::FragmentCache

Plugin definition

Plugin definition

Constants

VERSION

Attributes

cache_store[R]
default_options[RW]
namespace[RW]

Public Class Methods

cache_store=(store) click to toggle source
# File lib/graphql/fragment_cache.rb, line 41
def cache_store=(store)
  unless store.respond_to?(:read)
    raise ArgumentError, "Store must implement #read(key) method"
  end

  unless store.respond_to?(:write)
    raise ArgumentError, "Store must implement #write(key, val, **options) method"
  end

  @cache_store = store
end
configure() { |self| ... } click to toggle source
# File lib/graphql/fragment_cache.rb, line 37
def configure
  yield self
end
graphql_ruby_1_12_or_later?() click to toggle source
# File lib/graphql/fragment_cache.rb, line 53
def graphql_ruby_1_12_or_later?
  Gem::Dependency.new("graphql", ">= 1.12.0").match?("graphql", GraphQL::VERSION)
end
use(schema_defn, options = {}) click to toggle source
# File lib/graphql/fragment_cache.rb, line 27
def use(schema_defn, options = {})
  verify_interpreter_and_analysis!(schema_defn)

  schema_defn.tracer(Schema::Tracer)
  schema_defn.instrument(:query, Schema::Instrumentation)
  schema_defn.extend(Schema::Patch)

  GraphQL::Pagination::Connections.prepend(Connections::Patch)
end

Private Class Methods

verify_interpreter_and_analysis!(schema_defn) click to toggle source
# File lib/graphql/fragment_cache.rb, line 59
def verify_interpreter_and_analysis!(schema_defn)
  if graphql_ruby_1_12_or_later?
    unless schema_defn.interpreter?
      raise StandardError,
        "GraphQL::Execution::Execute should not be enabled for fragment caching"
    end

    unless schema_defn.analysis_engine == GraphQL::Analysis::AST
      raise StandardError,
        "GraphQL::Analysis should not be enabled for fragment caching"
    end
  else
    unless schema_defn.interpreter?
      raise StandardError,
        "GraphQL::Execution::Interpreter should be enabled for fragment caching"
    end

    unless schema_defn.analysis_engine == GraphQL::Analysis::AST
      raise StandardError,
        "GraphQL::Analysis::AST should be enabled for fragment caching"
    end
  end
end

Public Instance Methods

alias?(_) click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 39
def alias?(_)
  false
end
alias_selection(name, selected_type: @selected_type, arguments: nil) click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 56
def alias_selection(name, selected_type: @selected_type, arguments: nil)
  return alias_selections[name] if alias_selections.key?(name)

  alias_node = lookup_alias_node(ast_nodes, name)
  return ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD unless alias_node

  next_field_name = alias_node.name

  # From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
  next_field_defn = get_class_based_field(selected_type, next_field_name)

  alias_selections[name] =
    if next_field_defn
      next_nodes = []
      arguments = @query.arguments_for(alias_node, next_field_defn)
      arguments = arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) ? arguments.keyword_arguments : arguments
      @ast_nodes.each do |ast_node|
        ast_node.selections.each do |selection|
          find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
        end
      end

      if next_nodes.any?
        ::GraphQL::Execution::Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
      else
        ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
      end
    else
      ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
    end
end
alias_selections() click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 88
def alias_selections
  return @alias_selections if defined?(@alias_selections)
  @alias_selections ||= {}
end
lookup_alias_node(nodes, name) click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 93
def lookup_alias_node(nodes, name)
  return if nodes.empty?

  nodes.find do |node|
    if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
      node = @query.fragments[node.name]
      raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
    end

    return node if node.alias?(name)
    child = lookup_alias_node(node.children, name)
    return child if child
  end
end
selection_with_alias(name, **kwargs) click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 51
def selection_with_alias(name, **kwargs)
  return selection(name, **kwargs) if selects?(name, **kwargs)
  alias_selection(name, **kwargs)
end
to_selections_key() click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 20
def to_selections_key
  map { |val|
    children = val.selections.empty? ? "" : "[#{val.selections.to_selections_key}]"

    field_name = val.field.name
    field_alias = val.ast_nodes.map(&:alias).join
    field_name = "#{field_alias}:#{field_name}" unless field_alias.empty?

    unless val.arguments.empty?
      args = val.arguments.map { "#{_1}:#{traverse_argument(_2)}" }.sort.join(",")
      field_name += "(#{args})"
    end

    "#{field_name}#{children}"
  }.join(".")
end
traverse_argument(argument) click to toggle source
# File lib/graphql/fragment_cache/cache_key_builder.rb, line 14
def traverse_argument(argument)
  return argument unless argument.is_a?(GraphQL::Schema::InputObject)

  "{#{argument.map { "#{_1}:#{traverse_argument(_2)}" }.sort.join(",")}}"
end