graphql 1.7.14 → 1.8.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +1 -6
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/graphql.rb +2 -0
- data/lib/graphql/argument.rb +0 -1
- data/lib/graphql/backwards_compatibility.rb +2 -3
- data/lib/graphql/base_type.rb +18 -16
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
- data/lib/graphql/define/assign_object_field.rb +5 -12
- data/lib/graphql/deprecated_dsl.rb +28 -0
- data/lib/graphql/directive.rb +0 -1
- data/lib/graphql/enum_type.rb +1 -3
- data/lib/graphql/execution.rb +0 -1
- data/lib/graphql/execution/multiplex.rb +29 -12
- data/lib/graphql/field.rb +5 -20
- data/lib/graphql/function.rb +12 -0
- data/lib/graphql/input_object_type.rb +1 -3
- data/lib/graphql/internal_representation/node.rb +14 -26
- data/lib/graphql/internal_representation/visit.rb +6 -3
- data/lib/graphql/introspection/arguments_field.rb +0 -1
- data/lib/graphql/introspection/enum_values_field.rb +0 -1
- data/lib/graphql/introspection/fields_field.rb +0 -1
- data/lib/graphql/introspection/input_fields_field.rb +0 -1
- data/lib/graphql/introspection/interfaces_field.rb +0 -1
- data/lib/graphql/introspection/of_type_field.rb +0 -1
- data/lib/graphql/introspection/possible_types_field.rb +0 -1
- data/lib/graphql/introspection/schema_field.rb +0 -1
- data/lib/graphql/introspection/type_by_name_field.rb +0 -1
- data/lib/graphql/introspection/typename_field.rb +0 -1
- data/lib/graphql/language.rb +0 -3
- data/lib/graphql/language/generation.rb +182 -3
- data/lib/graphql/language/lexer.rb +69 -144
- data/lib/graphql/language/lexer.rl +4 -15
- data/lib/graphql/language/nodes.rb +76 -136
- data/lib/graphql/language/parser.rb +621 -668
- data/lib/graphql/language/parser.y +11 -17
- data/lib/graphql/language/token.rb +3 -10
- data/lib/graphql/object_type.rb +6 -1
- data/lib/graphql/query.rb +13 -8
- data/lib/graphql/query/arguments.rb +33 -48
- data/lib/graphql/query/context.rb +1 -0
- data/lib/graphql/query/literal_input.rb +1 -4
- data/lib/graphql/relay/connection_resolve.rb +3 -0
- data/lib/graphql/relay/global_id_resolve.rb +5 -1
- data/lib/graphql/relay/relation_connection.rb +19 -14
- data/lib/graphql/schema.rb +219 -12
- data/lib/graphql/schema/argument.rb +33 -0
- data/lib/graphql/schema/build_from_definition.rb +18 -64
- data/lib/graphql/schema/enum.rb +76 -0
- data/lib/graphql/schema/field.rb +127 -0
- data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
- data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
- data/lib/graphql/schema/input_object.rb +61 -0
- data/lib/graphql/schema/interface.rb +32 -0
- data/lib/graphql/schema/loader.rb +2 -2
- data/lib/graphql/schema/member.rb +97 -0
- data/lib/graphql/schema/member/build_type.rb +106 -0
- data/lib/graphql/schema/member/has_fields.rb +56 -0
- data/lib/graphql/schema/member/instrumentation.rb +113 -0
- data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
- data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
- data/lib/graphql/schema/object.rb +65 -0
- data/lib/graphql/schema/printer.rb +266 -33
- data/lib/graphql/schema/scalar.rb +25 -0
- data/lib/graphql/schema/traversal.rb +26 -17
- data/lib/graphql/schema/union.rb +48 -0
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
- data/lib/graphql/tracing.rb +0 -1
- data/lib/graphql/tracing/platform_tracing.rb +7 -20
- data/lib/graphql/tracing/scout_tracing.rb +2 -2
- data/lib/graphql/unresolved_type_error.rb +2 -3
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +1 -22
- data/spec/dummy/log/development.log +0 -239
- data/spec/dummy/log/test.log +0 -204
- data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/generators/graphql/function_generator_spec.rb +0 -26
- data/spec/generators/graphql/loader_generator_spec.rb +0 -24
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/backtrace_spec.rb +0 -10
- data/spec/graphql/base_type_spec.rb +5 -19
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +1 -3
- data/spec/graphql/enum_type_spec.rb +5 -18
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/multiplex_spec.rb +2 -2
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +2 -15
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +0 -1
- data/spec/graphql/language/generation_spec.rb +186 -21
- data/spec/graphql/language/lexer_spec.rb +1 -21
- data/spec/graphql/language/nodes_spec.rb +12 -21
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/query/arguments_spec.rb +15 -37
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +5 -31
- data/spec/graphql/rake_task_spec.rb +1 -3
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +3 -3
- data/spec/graphql/relay/relation_connection_spec.rb +1 -65
- data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
- data/spec/graphql/schema/enum_spec.rb +60 -0
- data/spec/graphql/schema/field_spec.rb +14 -0
- data/spec/graphql/schema/input_object_spec.rb +43 -0
- data/spec/graphql/schema/interface_spec.rb +98 -0
- data/spec/graphql/schema/object_spec.rb +119 -0
- data/spec/graphql/schema/printer_spec.rb +15 -92
- data/spec/graphql/schema/scalar_spec.rb +40 -0
- data/spec/graphql/schema/union_spec.rb +35 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +25 -23
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +1 -1
- data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
- data/spec/support/dummy/schema.rb +25 -39
- data/spec/support/jazz.rb +334 -0
- data/spec/support/lazy_helpers.rb +21 -23
- data/spec/support/star_wars/data.rb +7 -6
- data/spec/support/star_wars/schema.rb +109 -142
- metadata +39 -33
- data/lib/graphql/execution/instrumentation.rb +0 -82
- data/lib/graphql/language/block_string.rb +0 -47
- data/lib/graphql/language/document_from_schema_definition.rb +0 -277
- data/lib/graphql/language/printer.rb +0 -351
- data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
- data/spec/graphql/execution/instrumentation_spec.rb +0 -165
- data/spec/graphql/language/block_string_spec.rb +0 -70
- data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
- data/spec/graphql/language/printer_spec.rb +0 -203
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module GraphQL
         | 
| 3 | 
            +
              class Schema
         | 
| 4 | 
            +
                class Member
         | 
| 5 | 
            +
                  # @api private
         | 
| 6 | 
            +
                  module BuildType
         | 
| 7 | 
            +
                    module_function
         | 
| 8 | 
            +
                    # @param type_expr [String, Class, GraphQL::BaseType]
         | 
| 9 | 
            +
                    # @return [GraphQL::BaseType]
         | 
| 10 | 
            +
                    def parse_type(type_expr, null:)
         | 
| 11 | 
            +
                      list_type = false
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                      return_type = case type_expr
         | 
| 14 | 
            +
                      when String
         | 
| 15 | 
            +
                        case type_expr
         | 
| 16 | 
            +
                        when "String"
         | 
| 17 | 
            +
                          GraphQL::STRING_TYPE
         | 
| 18 | 
            +
                        when "Int", "Integer"
         | 
| 19 | 
            +
                          GraphQL::INT_TYPE
         | 
| 20 | 
            +
                        when "Float"
         | 
| 21 | 
            +
                          GraphQL::FLOAT_TYPE
         | 
| 22 | 
            +
                        when "Boolean"
         | 
| 23 | 
            +
                          GraphQL::BOOLEAN_TYPE
         | 
| 24 | 
            +
                        when "ID"
         | 
| 25 | 
            +
                          GraphQL::ID_TYPE
         | 
| 26 | 
            +
                        when /\A\[.*\]\Z/
         | 
| 27 | 
            +
                          list_type = true
         | 
| 28 | 
            +
                          # List members are required by default
         | 
| 29 | 
            +
                          parse_type(type_expr[1..-2], null: false)
         | 
| 30 | 
            +
                        when /.*!\Z/
         | 
| 31 | 
            +
                          null = false
         | 
| 32 | 
            +
                          parse_type(type_expr[0..-2], null: true)
         | 
| 33 | 
            +
                        else
         | 
| 34 | 
            +
                          maybe_type = Object.const_get(type_expr)
         | 
| 35 | 
            +
                          case maybe_type
         | 
| 36 | 
            +
                          when GraphQL::BaseType
         | 
| 37 | 
            +
                            maybe_type
         | 
| 38 | 
            +
                          when Class
         | 
| 39 | 
            +
                            if maybe_type < GraphQL::Schema::Member
         | 
| 40 | 
            +
                              maybe_type.graphql_definition
         | 
| 41 | 
            +
                            else
         | 
| 42 | 
            +
                              raise "Unexpected class found for GraphQL type: #{type_expr} (must be GraphQL::Object)"
         | 
| 43 | 
            +
                            end
         | 
| 44 | 
            +
                          end
         | 
| 45 | 
            +
                        end
         | 
| 46 | 
            +
                      when GraphQL::BaseType
         | 
| 47 | 
            +
                        type_expr
         | 
| 48 | 
            +
                      when Array
         | 
| 49 | 
            +
                        if type_expr.length != 1
         | 
| 50 | 
            +
                          raise "Use an array of length = 1 for list types; other arrays are not supported"
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                        list_type = true
         | 
| 53 | 
            +
                        # List members are required by default
         | 
| 54 | 
            +
                        parse_type(type_expr.first, null: false)
         | 
| 55 | 
            +
                      when Class
         | 
| 56 | 
            +
                        if Class < GraphQL::Schema::Member
         | 
| 57 | 
            +
                          type_expr.graphql_definition
         | 
| 58 | 
            +
                        else
         | 
| 59 | 
            +
                          # Eg `String` => GraphQL::STRING_TYPE
         | 
| 60 | 
            +
                          parse_type(type_expr.name, null: true)
         | 
| 61 | 
            +
                        end
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                      # Apply list_type first, that way the
         | 
| 65 | 
            +
                      # .to_non_null_type applies to the list type, not the inner type
         | 
| 66 | 
            +
                      if list_type
         | 
| 67 | 
            +
                        return_type = return_type.to_list_type
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                      if !null
         | 
| 71 | 
            +
                        return_type = return_type.to_non_null_type
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 75 | 
            +
                      return_type
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    def to_type_name(something)
         | 
| 79 | 
            +
                      case something
         | 
| 80 | 
            +
                      when GraphQL::BaseType
         | 
| 81 | 
            +
                        something.unwrap.name
         | 
| 82 | 
            +
                      when Array
         | 
| 83 | 
            +
                        to_type_name(something.first)
         | 
| 84 | 
            +
                      when Module
         | 
| 85 | 
            +
                        if something < GraphQL::Schema::Member
         | 
| 86 | 
            +
                          something.graphql_name
         | 
| 87 | 
            +
                        else
         | 
| 88 | 
            +
                          something.name.split("::").last
         | 
| 89 | 
            +
                        end
         | 
| 90 | 
            +
                      when String
         | 
| 91 | 
            +
                        something.gsub(/\]\[\!/, "").split("::").last
         | 
| 92 | 
            +
                      else
         | 
| 93 | 
            +
                        raise "Unhandled to_type_name input: #{something} (#{something.class})"
         | 
| 94 | 
            +
                      end
         | 
| 95 | 
            +
                    end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    def underscore(string)
         | 
| 98 | 
            +
                      string
         | 
| 99 | 
            +
                        .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
         | 
| 100 | 
            +
                        .gsub(/([a-z\d])([A-Z])/,'\1_\2')     # someThing -> some_Thing
         | 
| 101 | 
            +
                        .downcase
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module GraphQL
         | 
| 3 | 
            +
              class Schema
         | 
| 4 | 
            +
                class Member
         | 
| 5 | 
            +
                  # Shared code for Object and Interface
         | 
| 6 | 
            +
                  module HasFields
         | 
| 7 | 
            +
                    # Add a field to this object or interface with the given definition
         | 
| 8 | 
            +
                    # @see {GraphQL::Schema::Field#initialize} for method signature
         | 
| 9 | 
            +
                    # @return [void]
         | 
| 10 | 
            +
                    def field(*args, &block)
         | 
| 11 | 
            +
                      field_defn = field_class.new(*args, &block)
         | 
| 12 | 
            +
                      add_field(field_defn)
         | 
| 13 | 
            +
                      nil
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    # @return [Array<GraphQL::Schema::Field>] Fields on this object, including inherited fields
         | 
| 17 | 
            +
                    def fields
         | 
| 18 | 
            +
                      all_fields = own_fields
         | 
| 19 | 
            +
                      inherited_fields = (superclass.is_a?(HasFields) ? superclass.fields : [])
         | 
| 20 | 
            +
                      # Remove any inherited fields which were overridden on this class:
         | 
| 21 | 
            +
                      inherited_fields.each do |inherited_f|
         | 
| 22 | 
            +
                        if all_fields.none? {|f| f.name == inherited_f.name}
         | 
| 23 | 
            +
                          all_fields << inherited_f
         | 
| 24 | 
            +
                        end
         | 
| 25 | 
            +
                      end
         | 
| 26 | 
            +
                      all_fields
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    # Register this field with the class, overriding a previous one if needed
         | 
| 30 | 
            +
                    # @param field_defn [GraphQL::Schema::Field]
         | 
| 31 | 
            +
                    # @return [void]
         | 
| 32 | 
            +
                    def add_field(field_defn)
         | 
| 33 | 
            +
                      fields.reject! {|f| f.name == field_defn.name}
         | 
| 34 | 
            +
                      own_fields << field_defn
         | 
| 35 | 
            +
                      nil
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    # @return [Class] The class to initialize when adding fields to this kind of schema member
         | 
| 39 | 
            +
                    def field_class(new_field_class = nil)
         | 
| 40 | 
            +
                      if new_field_class
         | 
| 41 | 
            +
                        @field_class = new_field_class
         | 
| 42 | 
            +
                      else
         | 
| 43 | 
            +
                        @field_class || superclass.field_class
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    private
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    # @return [Array<GraphQL::Schema::Field>] Fields defined on this class _specifically_, not parent classes
         | 
| 50 | 
            +
                    def own_fields
         | 
| 51 | 
            +
                      @own_fields ||= []
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,113 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            # test_via: ../object.rb
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module GraphQL
         | 
| 5 | 
            +
              class Schema
         | 
| 6 | 
            +
                class Member
         | 
| 7 | 
            +
                  module Instrumentation
         | 
| 8 | 
            +
                    module_function
         | 
| 9 | 
            +
                    def instrument(type, field)
         | 
| 10 | 
            +
                      return_type = field.type.unwrap
         | 
| 11 | 
            +
                      if return_type.metadata[:object_class] ||
         | 
| 12 | 
            +
                          return_type.is_a?(GraphQL::InterfaceType) ||
         | 
| 13 | 
            +
                          (return_type.is_a?(GraphQL::UnionType) && return_type.possible_types.any? { |t| t.metadata[:object_class] })
         | 
| 14 | 
            +
                        field = apply_proxy(field)
         | 
| 15 | 
            +
                      end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      field
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def before_query(query)
         | 
| 21 | 
            +
                      # Get the root type for this query
         | 
| 22 | 
            +
                      root_node = query.irep_selection
         | 
| 23 | 
            +
                      if root_node.nil?
         | 
| 24 | 
            +
                        # It's an invalid query, nothing to do here
         | 
| 25 | 
            +
                      else
         | 
| 26 | 
            +
                        root_type = query.irep_selection.return_type
         | 
| 27 | 
            +
                        # If it has a wrapper, apply it
         | 
| 28 | 
            +
                        wrapper_class = root_type.metadata[:object_class]
         | 
| 29 | 
            +
                        if wrapper_class
         | 
| 30 | 
            +
                          new_root_value = wrapper_class.new(query.root_value, query.context)
         | 
| 31 | 
            +
                          query.root_value = new_root_value
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    def after_query(_query)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    private
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    module_function
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    def apply_proxy(field)
         | 
| 44 | 
            +
                      resolve_proc = field.resolve_proc
         | 
| 45 | 
            +
                      lazy_resolve_proc = field.lazy_resolve_proc
         | 
| 46 | 
            +
                      inner_return_type = field.type.unwrap
         | 
| 47 | 
            +
                      depth = list_depth(field.type)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      field.redefine(
         | 
| 50 | 
            +
                        resolve: ProxiedResolve.new(inner_resolve: resolve_proc, list_depth: depth, inner_return_type: inner_return_type),
         | 
| 51 | 
            +
                        lazy_resolve: ProxiedResolve.new(inner_resolve: lazy_resolve_proc, list_depth: depth, inner_return_type: inner_return_type),
         | 
| 52 | 
            +
                      )
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    def list_depth(type, starting_at = 0)
         | 
| 56 | 
            +
                      case type
         | 
| 57 | 
            +
                      when GraphQL::ListType
         | 
| 58 | 
            +
                        list_depth(type.of_type, starting_at + 1)
         | 
| 59 | 
            +
                      when GraphQL::NonNullType
         | 
| 60 | 
            +
                        list_depth(type.of_type, starting_at)
         | 
| 61 | 
            +
                      else
         | 
| 62 | 
            +
                        starting_at
         | 
| 63 | 
            +
                      end
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    class ProxiedResolve
         | 
| 67 | 
            +
                      def initialize(inner_resolve:, list_depth:, inner_return_type:)
         | 
| 68 | 
            +
                        @inner_resolve = inner_resolve
         | 
| 69 | 
            +
                        @inner_return_type = inner_return_type
         | 
| 70 | 
            +
                        @list_depth = list_depth
         | 
| 71 | 
            +
                      end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      def call(obj, args, ctx)
         | 
| 74 | 
            +
                        result = @inner_resolve.call(obj, args, ctx)
         | 
| 75 | 
            +
                        if ctx.schema.lazy?(result)
         | 
| 76 | 
            +
                          # Wrap it later
         | 
| 77 | 
            +
                          result
         | 
| 78 | 
            +
                        elsif ctx.skip == result
         | 
| 79 | 
            +
                          result
         | 
| 80 | 
            +
                        else
         | 
| 81 | 
            +
                          proxy_to_depth(result, @list_depth, @inner_return_type, ctx)
         | 
| 82 | 
            +
                        end
         | 
| 83 | 
            +
                      end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      private
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                      def proxy_to_depth(obj, depth, type, ctx)
         | 
| 88 | 
            +
                        if depth > 0
         | 
| 89 | 
            +
                          obj.map { |inner_obj| proxy_to_depth(inner_obj, depth - 1, type, ctx) }
         | 
| 90 | 
            +
                        elsif obj.nil?
         | 
| 91 | 
            +
                          obj
         | 
| 92 | 
            +
                        else
         | 
| 93 | 
            +
                          concrete_type = case type
         | 
| 94 | 
            +
                          when GraphQL::UnionType, GraphQL::InterfaceType
         | 
| 95 | 
            +
                            ctx.query.resolve_type(type, obj)
         | 
| 96 | 
            +
                          when GraphQL::ObjectType
         | 
| 97 | 
            +
                            type
         | 
| 98 | 
            +
                          else
         | 
| 99 | 
            +
                            raise "unexpected proxying type #{type} for #{obj} at #{ctx.owner_type}.#{ctx.field.name}"
         | 
| 100 | 
            +
                          end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                          if concrete_type && (object_class = concrete_type.metadata[:object_class])
         | 
| 103 | 
            +
                            object_class.new(obj, ctx)
         | 
| 104 | 
            +
                          else
         | 
| 105 | 
            +
                            obj
         | 
| 106 | 
            +
                          end
         | 
| 107 | 
            +
                        end
         | 
| 108 | 
            +
                      end
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module GraphQL
         | 
| 3 | 
            +
              class Schema
         | 
| 4 | 
            +
                class Member
         | 
| 5 | 
            +
                  # Wraps a {Schema::Member} as a list type.
         | 
| 6 | 
            +
                  # @see {Schema::Member#to_list_type}
         | 
| 7 | 
            +
                  # @api private
         | 
| 8 | 
            +
                  class ListTypeProxy
         | 
| 9 | 
            +
                    include GraphQL::Schema::Member::CachedGraphQLDefinition
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize(member)
         | 
| 12 | 
            +
                      @member = member
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def to_graphql
         | 
| 16 | 
            +
                      @member.graphql_definition.to_list_type
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module GraphQL
         | 
| 3 | 
            +
              class Schema
         | 
| 4 | 
            +
                class Member
         | 
| 5 | 
            +
                  # Wraps a {Schema::Member} when it is required.
         | 
| 6 | 
            +
                  # @see {Schema::Member#to_non_null_type}
         | 
| 7 | 
            +
                  # @api private
         | 
| 8 | 
            +
                  class NonNullTypeProxy
         | 
| 9 | 
            +
                    include GraphQL::Schema::Member::CachedGraphQLDefinition
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize(member)
         | 
| 12 | 
            +
                      @member = member
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def to_graphql
         | 
| 16 | 
            +
                      @member.graphql_definition.to_non_null_type
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module GraphQL
         | 
| 4 | 
            +
              class Schema
         | 
| 5 | 
            +
                class Object < GraphQL::Schema::Member
         | 
| 6 | 
            +
                  attr_reader :object
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(object, context)
         | 
| 9 | 
            +
                    @object = object
         | 
| 10 | 
            +
                    @context = context
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  extend GraphQL::Schema::Member::HasFields
         | 
| 13 | 
            +
                  field_class GraphQL::Schema::Field
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  class << self
         | 
| 16 | 
            +
                    def implements(*new_interfaces)
         | 
| 17 | 
            +
                      new_interfaces.each do |int|
         | 
| 18 | 
            +
                        if int.is_a?(Class) && int < GraphQL::Schema::Interface
         | 
| 19 | 
            +
                          # Add the graphql field defns
         | 
| 20 | 
            +
                          int.fields.each do |field|
         | 
| 21 | 
            +
                            add_field(field)
         | 
| 22 | 
            +
                          end
         | 
| 23 | 
            +
                          # And call the implemented hook
         | 
| 24 | 
            +
                          int.apply_implemented(self)
         | 
| 25 | 
            +
                        else
         | 
| 26 | 
            +
                          int.all_fields.each do |f|
         | 
| 27 | 
            +
                            field(f.name, field: f)
         | 
| 28 | 
            +
                          end
         | 
| 29 | 
            +
                        end
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                      own_interfaces.concat(new_interfaces)
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def interfaces
         | 
| 35 | 
            +
                      own_interfaces + (superclass <= GraphQL::Schema::Object ? superclass.interfaces : [])
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def own_interfaces
         | 
| 39 | 
            +
                      @own_interfaces ||= []
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    # @return [GraphQL::ObjectType]
         | 
| 43 | 
            +
                    def to_graphql
         | 
| 44 | 
            +
                      obj_type = GraphQL::ObjectType.new
         | 
| 45 | 
            +
                      obj_type.name = graphql_name
         | 
| 46 | 
            +
                      obj_type.description = description
         | 
| 47 | 
            +
                      obj_type.interfaces = interfaces
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      fields.each do |field_inst|
         | 
| 50 | 
            +
                        field_defn = field_inst.graphql_definition
         | 
| 51 | 
            +
                        obj_type.fields[field_defn.name] = field_defn
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      obj_type.metadata[:object_class] = self
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      obj_type
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def global_id_field(field_name)
         | 
| 60 | 
            +
                      field field_name, "ID", null: false, resolve: GraphQL::Relay::GlobalIdResolve.new(type: self)
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
            end
         | 
| @@ -36,7 +36,7 @@ module GraphQL | |
| 36 36 | 
             
                #   printer = GraphQL::Schema::Printer.new(MySchema)
         | 
| 37 37 | 
             
                #   puts printer.print_type(post_type)
         | 
| 38 38 | 
             
                #
         | 
| 39 | 
            -
                class Printer | 
| 39 | 
            +
                class Printer
         | 
| 40 40 | 
             
                  attr_reader :schema, :warden
         | 
| 41 41 |  | 
| 42 42 | 
             
                  # @param schema [GraphQL::Schema]
         | 
| @@ -45,32 +45,21 @@ module GraphQL | |
| 45 45 | 
             
                  # @param except [<#call(member, ctx)>]
         | 
| 46 46 | 
             
                  # @param introspection [Boolean] Should include the introspection types in the string?
         | 
| 47 47 | 
             
                  def initialize(schema, context: nil, only: nil, except: nil, introspection: false)
         | 
| 48 | 
            -
                    @document_from_schema = GraphQL::Language::DocumentFromSchemaDefinition.new(
         | 
| 49 | 
            -
                      schema,
         | 
| 50 | 
            -
                      context: context,
         | 
| 51 | 
            -
                      only: only,
         | 
| 52 | 
            -
                      except: except,
         | 
| 53 | 
            -
                      include_introspection_types: introspection,
         | 
| 54 | 
            -
                    )
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                    @document = @document_from_schema.document
         | 
| 57 | 
            -
             | 
| 58 48 | 
             
                    @schema = schema
         | 
| 49 | 
            +
                    @context = context
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    blacklist = build_blacklist(only, except, introspection: introspection)
         | 
| 52 | 
            +
                    filter = GraphQL::Filter.new(except: blacklist)
         | 
| 53 | 
            +
                    @warden = GraphQL::Schema::Warden.new(filter, schema: @schema, context: @context)
         | 
| 59 54 | 
             
                  end
         | 
| 60 55 |  | 
| 61 56 | 
             
                  # Return the GraphQL schema string for the introspection type system
         | 
| 62 57 | 
             
                  def self.print_introspection_schema
         | 
| 63 58 | 
             
                    query_root = ObjectType.define(name: "Root")
         | 
| 64 59 | 
             
                    schema = GraphQL::Schema.define(query: query_root)
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                     | 
| 67 | 
            -
             | 
| 68 | 
            -
                      except: ->(member, _) { member.name == "Root" },
         | 
| 69 | 
            -
                      include_introspection_types: true,
         | 
| 70 | 
            -
                      include_built_in_directives: true,
         | 
| 71 | 
            -
                    ).document
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                    introspection_schema_ast.to_query_string(printer: IntrospectionPrinter.new)
         | 
| 60 | 
            +
                    blacklist = ->(m, ctx) { m == query_root }
         | 
| 61 | 
            +
                    printer = new(schema, except: blacklist, introspection: true)
         | 
| 62 | 
            +
                    printer.print_schema
         | 
| 74 63 | 
             
                  end
         | 
| 75 64 |  | 
| 76 65 | 
             
                  # Return a GraphQL schema string for the defined types in the schema
         | 
| @@ -85,33 +74,277 @@ module GraphQL | |
| 85 74 |  | 
| 86 75 | 
             
                  # Return a GraphQL schema string for the defined types in the schema
         | 
| 87 76 | 
             
                  def print_schema
         | 
| 88 | 
            -
                     | 
| 77 | 
            +
                    directive_definitions = warden.directives.map { |directive| print_directive(directive) }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    printable_types = warden.types.reject(&:default_scalar?)
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    type_definitions = printable_types
         | 
| 82 | 
            +
                      .sort_by(&:name)
         | 
| 83 | 
            +
                      .map { |type| print_type(type) }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                    [print_schema_definition].compact
         | 
| 86 | 
            +
                                             .concat(directive_definitions)
         | 
| 87 | 
            +
                                             .concat(type_definitions).join("\n\n")
         | 
| 89 88 | 
             
                  end
         | 
| 90 89 |  | 
| 91 90 | 
             
                  def print_type(type)
         | 
| 92 | 
            -
                     | 
| 93 | 
            -
                    print(node)
         | 
| 91 | 
            +
                    TypeKindPrinters::STRATEGIES.fetch(type.kind).print(warden, type)
         | 
| 94 92 | 
             
                  end
         | 
| 95 93 |  | 
| 96 | 
            -
                   | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 94 | 
            +
                  private
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  # By default, these are included in a schema printout
         | 
| 97 | 
            +
                  IS_USER_DEFINED_MEMBER = ->(member) {
         | 
| 98 | 
            +
                    case member
         | 
| 99 | 
            +
                    when GraphQL::BaseType
         | 
| 100 | 
            +
                      !member.introspection?
         | 
| 101 | 
            +
                    when GraphQL::Directive
         | 
| 102 | 
            +
                      !member.default_directive?
         | 
| 103 | 
            +
                    else
         | 
| 104 | 
            +
                      true
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  }
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  private_constant :IS_USER_DEFINED_MEMBER
         | 
| 99 109 |  | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 110 | 
            +
                  def build_blacklist(only, except, introspection:)
         | 
| 111 | 
            +
                    if introspection
         | 
| 112 | 
            +
                      if only
         | 
| 113 | 
            +
                        ->(m, ctx) { !only.call(m, ctx) }
         | 
| 114 | 
            +
                      elsif except
         | 
| 115 | 
            +
                        except
         | 
| 102 116 | 
             
                      else
         | 
| 103 | 
            -
                         | 
| 117 | 
            +
                        ->(m, ctx) { false }
         | 
| 104 118 | 
             
                      end
         | 
| 105 119 | 
             
                    else
         | 
| 106 | 
            -
                       | 
| 120 | 
            +
                      if only
         | 
| 121 | 
            +
                        ->(m, ctx) { !(IS_USER_DEFINED_MEMBER.call(m) && only.call(m, ctx)) }
         | 
| 122 | 
            +
                      elsif except
         | 
| 123 | 
            +
                        ->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) || except.call(m, ctx) }
         | 
| 124 | 
            +
                      else
         | 
| 125 | 
            +
                        ->(m, ctx) { !IS_USER_DEFINED_MEMBER.call(m) }
         | 
| 126 | 
            +
                      end
         | 
| 107 127 | 
             
                    end
         | 
| 108 128 | 
             
                  end
         | 
| 109 129 |  | 
| 110 | 
            -
                   | 
| 111 | 
            -
                     | 
| 112 | 
            -
             | 
| 130 | 
            +
                  def print_schema_definition
         | 
| 131 | 
            +
                    if (schema.query.nil? || schema.query.name == 'Query') &&
         | 
| 132 | 
            +
                       (schema.mutation.nil? || schema.mutation.name == 'Mutation') &&
         | 
| 133 | 
            +
                       (schema.subscription.nil? || schema.subscription.name == 'Subscription')
         | 
| 134 | 
            +
                      return
         | 
| 113 135 | 
             
                    end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    operations = [:query, :mutation, :subscription].map do |operation_type|
         | 
| 138 | 
            +
                      object_type = schema.public_send(operation_type)
         | 
| 139 | 
            +
                      # Special treatment for the introspection schema, which prints `{ query: "Root" }`
         | 
| 140 | 
            +
                      if object_type && (warden.get_type(object_type.name) || (object_type.name == "Root" && schema.query == object_type))
         | 
| 141 | 
            +
                        "  #{operation_type}: #{object_type.name}\n"
         | 
| 142 | 
            +
                      else
         | 
| 143 | 
            +
                        nil
         | 
| 144 | 
            +
                      end
         | 
| 145 | 
            +
                    end.compact.join
         | 
| 146 | 
            +
                    "schema {\n#{operations}}"
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  def print_directive(directive)
         | 
| 150 | 
            +
                    TypeKindPrinters::DirectivePrinter.print(warden, directive)
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  module TypeKindPrinters
         | 
| 154 | 
            +
                    module DeprecatedPrinter
         | 
| 155 | 
            +
                      def print_deprecated(field_or_enum_value)
         | 
| 156 | 
            +
                        return unless field_or_enum_value.deprecation_reason
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                        case field_or_enum_value.deprecation_reason
         | 
| 159 | 
            +
                        when nil
         | 
| 160 | 
            +
                          ''
         | 
| 161 | 
            +
                        when '', GraphQL::Directive::DEFAULT_DEPRECATION_REASON
         | 
| 162 | 
            +
                          ' @deprecated'
         | 
| 163 | 
            +
                        else
         | 
| 164 | 
            +
                          " @deprecated(reason: #{field_or_enum_value.deprecation_reason.to_s.inspect})"
         | 
| 165 | 
            +
                        end
         | 
| 166 | 
            +
                      end
         | 
| 167 | 
            +
                    end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                    module DescriptionPrinter
         | 
| 170 | 
            +
                      def print_description(definition, indentation='', first_in_block=true)
         | 
| 171 | 
            +
                        return '' unless definition.description
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                        description = indentation != '' && !first_in_block ? "\n".dup : "".dup
         | 
| 174 | 
            +
                        description << GraphQL::Language::Comments.commentize(definition.description, indent: indentation)
         | 
| 175 | 
            +
                      end
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                    module ArgsPrinter
         | 
| 179 | 
            +
                      include DescriptionPrinter
         | 
| 180 | 
            +
                      def print_args(warden, field, indentation = '')
         | 
| 181 | 
            +
                        arguments = warden.arguments(field)
         | 
| 182 | 
            +
                        return if arguments.empty?
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                        if arguments.all?{ |arg| !arg.description }
         | 
| 185 | 
            +
                          return "(#{arguments.map{ |arg| print_input_value(arg) }.join(", ")})"
         | 
| 186 | 
            +
                        end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                        out = "(\n".dup
         | 
| 189 | 
            +
                        out << arguments.sort_by(&:name).map.with_index{ |arg, i|
         | 
| 190 | 
            +
                          "#{print_description(arg, "  #{indentation}", i == 0)}  #{indentation}"\
         | 
| 191 | 
            +
                          "#{print_input_value(arg)}"
         | 
| 192 | 
            +
                        }.join("\n")
         | 
| 193 | 
            +
                        out << "\n#{indentation})"
         | 
| 194 | 
            +
                      end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                      def print_input_value(arg)
         | 
| 197 | 
            +
                        if arg.default_value?
         | 
| 198 | 
            +
                          default_string = " = #{print_value(arg.default_value, arg.type)}"
         | 
| 199 | 
            +
                        else
         | 
| 200 | 
            +
                          default_string = nil
         | 
| 201 | 
            +
                        end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                        "#{arg.name}: #{arg.type.to_s}#{default_string}"
         | 
| 204 | 
            +
                      end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                      def print_value(value, type)
         | 
| 207 | 
            +
                        case type
         | 
| 208 | 
            +
                        when FLOAT_TYPE
         | 
| 209 | 
            +
                          return 'null' if value.nil?
         | 
| 210 | 
            +
                          value.to_f.inspect
         | 
| 211 | 
            +
                        when INT_TYPE
         | 
| 212 | 
            +
                          return 'null' if value.nil?
         | 
| 213 | 
            +
                          value.to_i.inspect
         | 
| 214 | 
            +
                        when BOOLEAN_TYPE
         | 
| 215 | 
            +
                          return 'null' if value.nil?
         | 
| 216 | 
            +
                          (!!value).inspect
         | 
| 217 | 
            +
                        when ScalarType, ID_TYPE, STRING_TYPE
         | 
| 218 | 
            +
                          return 'null' if value.nil?
         | 
| 219 | 
            +
                          value.to_s.inspect
         | 
| 220 | 
            +
                        when EnumType
         | 
| 221 | 
            +
                          return 'null' if value.nil?
         | 
| 222 | 
            +
                          type.coerce_isolated_result(value)
         | 
| 223 | 
            +
                        when InputObjectType
         | 
| 224 | 
            +
                          return 'null' if value.nil?
         | 
| 225 | 
            +
                          fields = value.to_h.map{ |field_name, field_value|
         | 
| 226 | 
            +
                            field_type = type.input_fields.fetch(field_name.to_s).type
         | 
| 227 | 
            +
                            "#{field_name}: #{print_value(field_value, field_type)}"
         | 
| 228 | 
            +
                          }.join(", ")
         | 
| 229 | 
            +
                          "{#{fields}}"
         | 
| 230 | 
            +
                        when NonNullType
         | 
| 231 | 
            +
                          print_value(value, type.of_type)
         | 
| 232 | 
            +
                        when ListType
         | 
| 233 | 
            +
                          return 'null' if value.nil?
         | 
| 234 | 
            +
                          "[#{value.to_a.map{ |v| print_value(v, type.of_type) }.join(", ")}]"
         | 
| 235 | 
            +
                        else
         | 
| 236 | 
            +
                          raise NotImplementedError, "Unexpected value type #{type.inspect}"
         | 
| 237 | 
            +
                        end
         | 
| 238 | 
            +
                      end
         | 
| 239 | 
            +
                    end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                    module FieldPrinter
         | 
| 242 | 
            +
                      include DeprecatedPrinter
         | 
| 243 | 
            +
                      include ArgsPrinter
         | 
| 244 | 
            +
                      include DescriptionPrinter
         | 
| 245 | 
            +
                      def print_fields(warden, type)
         | 
| 246 | 
            +
                        fields = warden.fields(type)
         | 
| 247 | 
            +
                        fields.sort_by(&:name).map.with_index { |field, i|
         | 
| 248 | 
            +
                          "#{print_description(field, '  ', i == 0)}"\
         | 
| 249 | 
            +
                          "  #{field.name}#{print_args(warden, field, '  ')}: #{field.type}#{print_deprecated(field)}"
         | 
| 250 | 
            +
                        }.join("\n")
         | 
| 251 | 
            +
                      end
         | 
| 252 | 
            +
                    end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                    class DirectivePrinter
         | 
| 255 | 
            +
                      extend ArgsPrinter
         | 
| 256 | 
            +
                      extend DescriptionPrinter
         | 
| 257 | 
            +
                      def self.print(warden, directive)
         | 
| 258 | 
            +
                        "#{print_description(directive)}"\
         | 
| 259 | 
            +
                        "directive @#{directive.name}#{print_args(warden, directive)} "\
         | 
| 260 | 
            +
                        "on #{directive.locations.join(' | ')}"
         | 
| 261 | 
            +
                      end
         | 
| 262 | 
            +
                    end
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                    class ScalarPrinter
         | 
| 265 | 
            +
                      extend DescriptionPrinter
         | 
| 266 | 
            +
                      def self.print(warden, type)
         | 
| 267 | 
            +
                        "#{print_description(type)}"\
         | 
| 268 | 
            +
                        "scalar #{type.name}"
         | 
| 269 | 
            +
                      end
         | 
| 270 | 
            +
                    end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                    class ObjectPrinter
         | 
| 273 | 
            +
                      extend FieldPrinter
         | 
| 274 | 
            +
                      extend DescriptionPrinter
         | 
| 275 | 
            +
                      def self.print(warden, type)
         | 
| 276 | 
            +
                        interfaces = warden.interfaces(type)
         | 
| 277 | 
            +
                        if interfaces.any?
         | 
| 278 | 
            +
                          implementations = " implements #{interfaces.sort_by(&:name).map(&:to_s).join(", ")}"
         | 
| 279 | 
            +
                        else
         | 
| 280 | 
            +
                          implementations = nil
         | 
| 281 | 
            +
                        end
         | 
| 282 | 
            +
             | 
| 283 | 
            +
                        "#{print_description(type)}"\
         | 
| 284 | 
            +
                        "type #{type.name}#{implementations} {\n"\
         | 
| 285 | 
            +
                        "#{print_fields(warden, type)}\n"\
         | 
| 286 | 
            +
                        "}"
         | 
| 287 | 
            +
                      end
         | 
| 288 | 
            +
                    end
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                    class InterfacePrinter
         | 
| 291 | 
            +
                      extend FieldPrinter
         | 
| 292 | 
            +
                      extend DescriptionPrinter
         | 
| 293 | 
            +
                      def self.print(warden, type)
         | 
| 294 | 
            +
                        "#{print_description(type)}"\
         | 
| 295 | 
            +
                        "interface #{type.name} {\n#{print_fields(warden, type)}\n}"
         | 
| 296 | 
            +
                      end
         | 
| 297 | 
            +
                    end
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                    class UnionPrinter
         | 
| 300 | 
            +
                      extend DescriptionPrinter
         | 
| 301 | 
            +
                      def self.print(warden, type)
         | 
| 302 | 
            +
                        possible_types = warden.possible_types(type)
         | 
| 303 | 
            +
                        "#{print_description(type)}"\
         | 
| 304 | 
            +
                        "union #{type.name} = #{possible_types.sort_by(&:name).map(&:to_s).join(" | ")}"
         | 
| 305 | 
            +
                      end
         | 
| 306 | 
            +
                    end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                    class EnumPrinter
         | 
| 309 | 
            +
                      extend DeprecatedPrinter
         | 
| 310 | 
            +
                      extend DescriptionPrinter
         | 
| 311 | 
            +
                      def self.print(warden, type)
         | 
| 312 | 
            +
                        enum_values = warden.enum_values(type)
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                        values = enum_values.sort_by(&:name).map.with_index { |v, i|
         | 
| 315 | 
            +
                          "#{print_description(v, '  ', i == 0)}"\
         | 
| 316 | 
            +
                          "  #{v.name}#{print_deprecated(v)}"
         | 
| 317 | 
            +
                        }.join("\n")
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                        "#{print_description(type)}"\
         | 
| 320 | 
            +
                        "enum #{type.name} {\n#{values}\n}"
         | 
| 321 | 
            +
                      end
         | 
| 322 | 
            +
                    end
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                    class InputObjectPrinter
         | 
| 325 | 
            +
                      extend FieldPrinter
         | 
| 326 | 
            +
                      extend DescriptionPrinter
         | 
| 327 | 
            +
                      def self.print(warden, type)
         | 
| 328 | 
            +
                        arguments = warden.arguments(type)
         | 
| 329 | 
            +
                        fields = arguments.sort_by(&:name).map.with_index{ |field, i|
         | 
| 330 | 
            +
                          "#{print_description(field, "  ", i == 0)}"\
         | 
| 331 | 
            +
                          "  #{print_input_value(field)}"
         | 
| 332 | 
            +
                        }.join("\n")
         | 
| 333 | 
            +
                        "#{print_description(type)}"\
         | 
| 334 | 
            +
                        "input #{type.name} {\n#{fields}\n}"
         | 
| 335 | 
            +
                      end
         | 
| 336 | 
            +
                    end
         | 
| 337 | 
            +
             | 
| 338 | 
            +
                    STRATEGIES = {
         | 
| 339 | 
            +
                      GraphQL::TypeKinds::SCALAR =>       ScalarPrinter,
         | 
| 340 | 
            +
                      GraphQL::TypeKinds::OBJECT =>       ObjectPrinter,
         | 
| 341 | 
            +
                      GraphQL::TypeKinds::INTERFACE =>    InterfacePrinter,
         | 
| 342 | 
            +
                      GraphQL::TypeKinds::UNION =>        UnionPrinter,
         | 
| 343 | 
            +
                      GraphQL::TypeKinds::ENUM =>         EnumPrinter,
         | 
| 344 | 
            +
                      GraphQL::TypeKinds::INPUT_OBJECT => InputObjectPrinter,
         | 
| 345 | 
            +
                    }
         | 
| 114 346 | 
             
                  end
         | 
| 347 | 
            +
                  private_constant :TypeKindPrinters
         | 
| 115 348 | 
             
                end
         | 
| 116 349 | 
             
              end
         | 
| 117 350 | 
             
            end
         |