class GraphQL::Schema::IntrospectionSystem

Attributes

possible_types[R]
types[R]

Public Class Methods

new(schema) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 7
def initialize(schema)
  @schema = schema
  @class_based = !!@schema.is_a?(Class)
  @built_in_namespace = GraphQL::Introspection
  @custom_namespace = if @class_based
    schema.introspection || @built_in_namespace
  else
    schema.introspection_namespace || @built_in_namespace
  end

  type_defns = [
    load_constant(:SchemaType),
    load_constant(:TypeType),
    load_constant(:FieldType),
    load_constant(:DirectiveType),
    load_constant(:EnumValueType),
    load_constant(:InputValueType),
    load_constant(:TypeKindEnum),
    load_constant(:DirectiveLocationEnum)
  ]
  @types = {}
  @possible_types = {}
  type_defns.each do |t|
    @types[t.graphql_name] = t
    @possible_types[t.graphql_name] = [t]
  end
  @entry_point_fields =
    if schema.disable_introspection_entry_points?
      {}
    else
      entry_point_fields = get_fields_from_class(class_sym: :EntryPoints)
      entry_point_fields.delete('__schema') if schema.disable_schema_introspection_entry_point?
      entry_point_fields.delete('__type') if schema.disable_type_introspection_entry_point?
      entry_point_fields
    end
  @dynamic_fields = get_fields_from_class(class_sym: :DynamicFields)
end

Public Instance Methods

dynamic_field(name:) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 57
def dynamic_field(name:)
  @dynamic_fields[name]
end
dynamic_fields() click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 53
def dynamic_fields
  @dynamic_fields.values
end
entry_point(name:) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 49
def entry_point(name:)
  @entry_point_fields[name]
end
entry_points() click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 45
def entry_points
  @entry_point_fields.values
end
resolve_late_bindings() click to toggle source

The introspection system is prepared with a bunch of LateBoundTypes. Replace those with the objects that they refer to, since LateBoundTypes aren't handled at runtime.

@api private @return void

# File lib/graphql/schema/introspection_system.rb, line 67
def resolve_late_bindings
  @types.each do |name, t|
    if t.kind.fields?
      t.fields.each do |_name, field_defn|
        field_defn.type = resolve_late_binding(field_defn.type)
      end
    end
  end

  @entry_point_fields.each do |name, f|
    f.type = resolve_late_binding(f.type)
  end

  @dynamic_fields.each do |name, f|
    f.type = resolve_late_binding(f.type)
  end
  nil
end

Private Instance Methods

dup_type_class(type_class) click to toggle source

This is probably not 100% robust – but it has to be good enough to avoid modifying the built-in introspection types

# File lib/graphql/schema/introspection_system.rb, line 135
def dup_type_class(type_class)
  type_name = type_class.graphql_name
  Class.new(type_class) do
    # This won't be inherited like other things will
    graphql_name(type_name)

    if type_class.kind.fields?
      type_class.fields.each do |_name, field_defn|
        dup_field = field_defn.dup
        dup_field.owner = self
        add_field(dup_field)
      end
    end
  end
end
get_fields_from_class(class_sym:) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 117
def get_fields_from_class(class_sym:)
  object_type_defn = load_constant(class_sym)

  if object_type_defn.is_a?(Module)
    object_type_defn.fields
  else
    extracted_field_defns = {}
    object_class = object_type_defn.metadata[:type_class]
    object_type_defn.all_fields.each do |field_defn|
      inner_resolve = field_defn.resolve_proc
      resolve_with_instantiate = PerFieldProxyResolve.new(object_class: object_class, inner_resolve: inner_resolve)
      extracted_field_defns[field_defn.name] = field_defn.redefine(resolve: resolve_with_instantiate)
    end
    extracted_field_defns
  end
end
load_constant(class_name) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 104
def load_constant(class_name)
  const = @custom_namespace.const_get(class_name)
  if @class_based
    dup_type_class(const)
  else
    # Use `.to_graphql` to get a freshly-made version, not shared between schemas
    const.deprecated_to_graphql
  end
rescue NameError
  # Dup the built-in so that the cached fields aren't shared
  dup_type_class(@built_in_namespace.const_get(class_name))
end
resolve_late_binding(late_bound_type) click to toggle source
# File lib/graphql/schema/introspection_system.rb, line 88
def resolve_late_binding(late_bound_type)
  case late_bound_type
  when GraphQL::Schema::LateBoundType
    @schema.get_type(late_bound_type.name)
  when GraphQL::Schema::List, GraphQL::ListType
    resolve_late_binding(late_bound_type.of_type).to_list_type
  when GraphQL::Schema::NonNull, GraphQL::NonNullType
    resolve_late_binding(late_bound_type.of_type).to_non_null_type
  when Module
    # It's a normal type -- no change required
    late_bound_type
  else
    raise "Invariant: unexpected type: #{late_bound_type} (#{late_bound_type.class})"
  end
end