lib/graphql/schema/printer.rb in graphql-1.3.0 vs lib/graphql/schema/printer.rb in graphql-1.4.0
- old
+ new
@@ -9,75 +9,96 @@
#
module Printer
extend self
# Return a GraphQL schema string for the defined types in the schema
+ # @param context [Hash]
+ # @param only [<#call(member, ctx)>]
+ # @param except [<#call(member, ctx)>]
# @param schema [GraphQL::Schema]
- def print_schema(schema)
- print_filtered_schema(schema, lambda { |n| !is_spec_directive(n) }, method(:is_defined_type))
+ def print_schema(schema, context: nil, only: nil, except: nil)
+ blacklist = if only
+ ->(m, ctx) { !(IS_USER_DEFINED_MEMBER.call(m) && only.call(m, ctx)) }
+ elsif except
+ ->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) || except.call(m, ctx) }
+ else
+ ->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) }
+ end
+
+ warden = GraphQL::Schema::Warden.new(blacklist, schema: schema, context: context)
+
+ print_filtered_schema(schema, warden: warden)
end
# Return the GraphQL schema string for the introspection type system
def print_introspection_schema
- query_root = ObjectType.define do
- name "Root"
- end
+ query_root = ObjectType.define(name: "Root")
schema = GraphQL::Schema.define(query: query_root)
- print_filtered_schema(schema, method(:is_spec_directive), method(:is_introspection_type))
+ blacklist = ->(m, ctx) { m == query_root }
+
+ warden = GraphQL::Schema::Warden.new(blacklist, schema: schema, context: nil)
+
+ print_filtered_schema(schema, warden: warden)
end
private
- def print_filtered_schema(schema, directive_filter, type_filter)
- directives = schema.directives.values.select{ |directive| directive_filter.call(directive) }
- directive_definitions = directives.map{ |directive| print_directive(directive) }
+ # By default, these are included in a schema printout
+ IS_USER_DEFINED_MEMBER = ->(member) {
+ case member
+ when GraphQL::BaseType
+ !member.introspection?
+ when GraphQL::Directive
+ !member.default_directive?
+ else
+ true
+ end
+ }
- types = schema.types.values.select{ |type| type_filter.call(type) }.sort_by(&:name)
- type_definitions = types.map{ |type| print_type(type) }
+ private_constant :IS_USER_DEFINED_MEMBER
- [print_schema_definition(schema)].compact
+ def print_filtered_schema(schema, warden:)
+ directive_definitions = warden.directives.map { |directive| print_directive(warden, directive) }
+
+ printable_types = warden.types.reject(&:default_scalar?)
+
+ type_definitions = printable_types
+ .sort_by(&:name)
+ .map { |type| print_type(warden, type) }
+
+ [print_schema_definition(warden, schema)].compact
.concat(directive_definitions)
.concat(type_definitions).join("\n\n")
end
- def print_schema_definition(schema)
+ def print_schema_definition(warden, schema)
if (schema.query.nil? || schema.query.name == 'Query') &&
(schema.mutation.nil? || schema.mutation.name == 'Mutation') &&
(schema.subscription.nil? || schema.subscription.name == 'Subscription')
return
end
operations = [:query, :mutation, :subscription].map do |operation_type|
object_type = schema.public_send(operation_type)
- " #{operation_type}: #{object_type.name}\n" if object_type
+ # Special treatment for the introspection schema, which prints `{ query: "Root" }`
+ if object_type && (warden.get_type(object_type.name) || (object_type.name == "Root" && schema.query == object_type))
+ " #{operation_type}: #{object_type.name}\n"
+ else
+ nil
+ end
end.compact.join
"schema {\n#{operations}}"
end
- BUILTIN_SCALARS = Set.new(["String", "Boolean", "Int", "Float", "ID"])
- private_constant :BUILTIN_SCALARS
-
- def is_spec_directive(directive)
- ['skip', 'include', 'deprecated'].include?(directive.name)
+ def print_type(warden, type)
+ TypeKindPrinters::STRATEGIES.fetch(type.kind).print(warden, type)
end
- def is_introspection_type(type)
- type.name.start_with?("__")
+ def print_directive(warden, directive)
+ TypeKindPrinters::DirectivePrinter.print(warden, directive)
end
- def is_defined_type(type)
- !is_introspection_type(type) && !BUILTIN_SCALARS.include?(type.name)
- end
-
- def print_type(type)
- TypeKindPrinters::STRATEGIES.fetch(type.kind).print(type)
- end
-
- def print_directive(directive)
- TypeKindPrinters::DirectivePrinter.print(directive)
- end
-
module TypeKindPrinters
module DeprecatedPrinter
def print_deprecated(field_or_enum_value)
return unless field_or_enum_value.deprecation_reason
@@ -101,21 +122,20 @@
end
end
module ArgsPrinter
include DescriptionPrinter
- def print_args(field, indentation = '')
- return if field.arguments.empty?
+ def print_args(warden, field, indentation = '')
+ arguments = warden.arguments(field)
+ return if arguments.empty?
- field_arguments = field.arguments.values
-
- if field_arguments.all?{ |arg| !arg.description }
- return "(#{field_arguments.map{ |arg| print_input_value(arg) }.join(", ")})"
+ if arguments.all?{ |arg| !arg.description }
+ return "(#{arguments.map{ |arg| print_input_value(arg) }.join(", ")})"
end
out = "(\n".dup
- out << field_arguments.map.with_index{ |arg, i|
+ out << arguments.map.with_index{ |arg, i|
"#{print_description(arg, " #{indentation}", i == 0)} #{indentation}"\
"#{print_input_value(arg)}"
}.join("\n")
out << "\n#{indentation})"
end
@@ -167,88 +187,94 @@
module FieldPrinter
include DeprecatedPrinter
include ArgsPrinter
include DescriptionPrinter
- def print_fields(type)
- type.all_fields.map.with_index { |field, i|
+ def print_fields(warden, type)
+ fields = warden.fields(type)
+ fields.map.with_index { |field, i|
"#{print_description(field, ' ', i == 0)}"\
- " #{field.name}#{print_args(field, ' ')}: #{field.type}#{print_deprecated(field)}"
+ " #{field.name}#{print_args(warden, field, ' ')}: #{field.type}#{print_deprecated(field)}"
}.join("\n")
end
end
class DirectivePrinter
extend ArgsPrinter
extend DescriptionPrinter
- def self.print(directive)
+ def self.print(warden, directive)
"#{print_description(directive)}"\
- "directive @#{directive.name}#{print_args(directive)} "\
+ "directive @#{directive.name}#{print_args(warden, directive)} "\
"on #{directive.locations.join(' | ')}"
end
end
class ScalarPrinter
extend DescriptionPrinter
- def self.print(type)
+ def self.print(warden, type)
"#{print_description(type)}"\
"scalar #{type.name}"
end
end
class ObjectPrinter
extend FieldPrinter
extend DescriptionPrinter
- def self.print(type)
- if type.interfaces.any?
- implementations = " implements #{type.interfaces.map(&:to_s).join(", ")}"
+ def self.print(warden, type)
+ interfaces = warden.interfaces(type)
+ if interfaces.any?
+ implementations = " implements #{interfaces.map(&:to_s).join(", ")}"
else
implementations = nil
end
"#{print_description(type)}"\
"type #{type.name}#{implementations} {\n"\
- "#{print_fields(type)}\n"\
+ "#{print_fields(warden, type)}\n"\
"}"
end
end
class InterfacePrinter
extend FieldPrinter
extend DescriptionPrinter
- def self.print(type)
+ def self.print(warden, type)
"#{print_description(type)}"\
- "interface #{type.name} {\n#{print_fields(type)}\n}"
+ "interface #{type.name} {\n#{print_fields(warden, type)}\n}"
end
end
class UnionPrinter
extend DescriptionPrinter
- def self.print(type)
+ def self.print(warden, type)
+ possible_types = warden.possible_types(type)
"#{print_description(type)}"\
- "union #{type.name} = #{type.possible_types.map(&:to_s).join(" | ")}"
+ "union #{type.name} = #{possible_types.map(&:to_s).join(" | ")}"
end
end
class EnumPrinter
extend DeprecatedPrinter
extend DescriptionPrinter
- def self.print(type)
- values = type.values.values.map{ |v| " #{v.name}#{print_deprecated(v)}" }.join("\n")
- values = type.values.values.map.with_index { |v, i|
+ def self.print(warden, type)
+ enum_values = warden.enum_values(type)
+
+ values = enum_values.map.with_index { |v, i|
"#{print_description(v, ' ', i == 0)}"\
" #{v.name}#{print_deprecated(v)}"
}.join("\n")
+
"#{print_description(type)}"\
"enum #{type.name} {\n#{values}\n}"
end
end
class InputObjectPrinter
extend FieldPrinter
extend DescriptionPrinter
- def self.print(type)
- fields = type.input_fields.values.map.with_index{ |field, i|
+ def self.print(warden, type)
+ arguments = warden.arguments(type)
+ fields = arguments.map.with_index{ |field, i|
"#{print_description(field, " ", i == 0)}"\
" #{print_input_value(field)}"
}.join("\n")
"#{print_description(type)}"\
"input #{type.name} {\n#{fields}\n}"