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
    
        data/lib/graphql/field.rb
    CHANGED
    
    | @@ -102,7 +102,7 @@ module GraphQL | |
| 102 102 | 
             
              # @example Calculating the complexity of a list field
         | 
| 103 103 | 
             
              #   field :items, types[ItemType] do
         | 
| 104 104 | 
             
              #     argument :limit, !types.Int
         | 
| 105 | 
            -
              #     #  | 
| 105 | 
            +
              #     # Mulitply the child complexity by the possible items on the list
         | 
| 106 106 | 
             
              #     complexity ->(ctx, args, child_complexity) { child_complexity * args[:limit] }
         | 
| 107 107 | 
             
              #   end
         | 
| 108 108 | 
             
              #
         | 
| @@ -130,8 +130,6 @@ module GraphQL | |
| 130 130 | 
             
                  :relay_node_field,
         | 
| 131 131 | 
             
                  :relay_nodes_field,
         | 
| 132 132 | 
             
                  :subscription_scope,
         | 
| 133 | 
            -
                  :trace,
         | 
| 134 | 
            -
                  :introspection,
         | 
| 135 133 | 
             
                  argument: GraphQL::Define::AssignArgument
         | 
| 136 134 |  | 
| 137 135 | 
             
                ensure_defined(
         | 
| @@ -139,8 +137,7 @@ module GraphQL | |
| 139 137 | 
             
                  :mutation, :arguments, :complexity, :function,
         | 
| 140 138 | 
             
                  :resolve, :resolve=, :lazy_resolve, :lazy_resolve=, :lazy_resolve_proc, :resolve_proc,
         | 
| 141 139 | 
             
                  :type, :type=, :name=, :property=, :hash_key=,
         | 
| 142 | 
            -
                  :relay_node_field, :relay_nodes_field, :edges?, :edge_class, :subscription_scope | 
| 143 | 
            -
                  :introspection?
         | 
| 140 | 
            +
                  :relay_node_field, :relay_nodes_field, :edges?, :edge_class, :subscription_scope
         | 
| 144 141 | 
             
                )
         | 
| 145 142 |  | 
| 146 143 | 
             
                # @return [Boolean] True if this is the Relay find-by-id field
         | 
| @@ -185,16 +182,10 @@ module GraphQL | |
| 185 182 | 
             
                attr_accessor :arguments_class
         | 
| 186 183 |  | 
| 187 184 | 
             
                attr_writer :connection
         | 
| 188 | 
            -
                attr_writer :introspection
         | 
| 189 185 |  | 
| 190 186 | 
             
                # @return [nil, String] Prefix for subscription names from this field
         | 
| 191 187 | 
             
                attr_accessor :subscription_scope
         | 
| 192 188 |  | 
| 193 | 
            -
                # @return [Boolean] True if this field should be traced. By default, fields are only traced if they are not a ScalarType or EnumType.
         | 
| 194 | 
            -
                attr_accessor :trace
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                attr_accessor :ast_node
         | 
| 197 | 
            -
             | 
| 198 189 | 
             
                # @return [Boolean]
         | 
| 199 190 | 
             
                def connection?
         | 
| 200 191 | 
             
                  @connection
         | 
| @@ -221,20 +212,14 @@ module GraphQL | |
| 221 212 | 
             
                  @connection = false
         | 
| 222 213 | 
             
                  @connection_max_page_size = nil
         | 
| 223 214 | 
             
                  @edge_class = nil
         | 
| 224 | 
            -
                  @trace = nil
         | 
| 225 | 
            -
                  @introspection = false
         | 
| 226 215 | 
             
                end
         | 
| 227 216 |  | 
| 228 217 | 
             
                def initialize_copy(other)
         | 
| 218 | 
            +
                  ensure_defined
         | 
| 229 219 | 
             
                  super
         | 
| 230 220 | 
             
                  @arguments = other.arguments.dup
         | 
| 231 221 | 
             
                end
         | 
| 232 222 |  | 
| 233 | 
            -
                # @return [Boolean] Is this field a predefined introspection field?
         | 
| 234 | 
            -
                def introspection?
         | 
| 235 | 
            -
                  @introspection
         | 
| 236 | 
            -
                end
         | 
| 237 | 
            -
             | 
| 238 223 | 
             
                # Get a value for this field
         | 
| 239 224 | 
             
                # @example resolving a field value
         | 
| 240 225 | 
             
                #   field.resolve(obj, args, ctx)
         | 
| @@ -290,8 +275,8 @@ module GraphQL | |
| 290 275 | 
             
                  "<Field name:#{name || "not-named"} desc:#{description} resolve:#{resolve_proc}>"
         | 
| 291 276 | 
             
                end
         | 
| 292 277 |  | 
| 293 | 
            -
                # If {#resolve} returned  | 
| 294 | 
            -
                # this method will be called later  | 
| 278 | 
            +
                # If {#resolve} returned and object which should be handled lazily,
         | 
| 279 | 
            +
                # this method will be called later force the object to return its value.
         | 
| 295 280 | 
             
                # @param obj [Object] The {#resolve}-provided object, registered with {Schema#lazy_resolve}
         | 
| 296 281 | 
             
                # @param args [GraphQL::Query::Arguments] Arguments to this field
         | 
| 297 282 | 
             
                # @param ctx [GraphQL::Query::Context] Context for this field
         | 
    
        data/lib/graphql/function.rb
    CHANGED
    
    | @@ -97,6 +97,18 @@ module GraphQL | |
| 97 97 | 
             
                    end
         | 
| 98 98 | 
             
                  end
         | 
| 99 99 |  | 
| 100 | 
            +
                  def build_field(function)
         | 
| 101 | 
            +
                    GraphQL::Field.define(
         | 
| 102 | 
            +
                      arguments: function.arguments,
         | 
| 103 | 
            +
                      complexity: function.complexity,
         | 
| 104 | 
            +
                      type: function.type,
         | 
| 105 | 
            +
                      resolve: function,
         | 
| 106 | 
            +
                      description: function.description,
         | 
| 107 | 
            +
                      function: function,
         | 
| 108 | 
            +
                      deprecation_reason: function.deprecation_reason,
         | 
| 109 | 
            +
                    )
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
             | 
| 100 112 | 
             
                  # Class-level reader/writer which is inherited
         | 
| 101 113 | 
             
                  # @api private
         | 
| 102 114 | 
             
                  def self.inherited_value(name)
         | 
| @@ -84,7 +84,6 @@ module GraphQL | |
| 84 84 |  | 
| 85 85 | 
             
                def coerce_non_null_input(value, ctx)
         | 
| 86 86 | 
             
                  input_values = {}
         | 
| 87 | 
            -
                  defaults_used = Set.new
         | 
| 88 87 |  | 
| 89 88 | 
             
                  arguments.each do |input_key, input_field_defn|
         | 
| 90 89 | 
             
                    field_value = value[input_key]
         | 
| @@ -94,11 +93,10 @@ module GraphQL | |
| 94 93 | 
             
                      input_values[input_key] = input_field_defn.prepare(coerced_value, ctx)
         | 
| 95 94 | 
             
                    elsif input_field_defn.default_value?
         | 
| 96 95 | 
             
                      input_values[input_key] = input_field_defn.default_value
         | 
| 97 | 
            -
                      defaults_used << input_key
         | 
| 98 96 | 
             
                    end
         | 
| 99 97 | 
             
                  end
         | 
| 100 98 |  | 
| 101 | 
            -
                  arguments_class.new(input_values,  | 
| 99 | 
            +
                  arguments_class.new(input_values, context: ctx)
         | 
| 102 100 | 
             
                end
         | 
| 103 101 |  | 
| 104 102 | 
             
                # @api private
         | 
| @@ -4,12 +4,6 @@ module GraphQL | |
| 4 4 | 
             
                class Node
         | 
| 5 5 | 
             
                  # @api private
         | 
| 6 6 | 
             
                  DEFAULT_TYPED_CHILDREN = Proc.new { |h, k| h[k] = {} }
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  # A specialized, reusable object for leaf nodes.
         | 
| 9 | 
            -
                  NO_TYPED_CHILDREN = Hash.new({}.freeze)
         | 
| 10 | 
            -
                  def NO_TYPED_CHILDREN.dup; self; end;
         | 
| 11 | 
            -
                  NO_TYPED_CHILDREN.freeze
         | 
| 12 | 
            -
             | 
| 13 7 | 
             
                  # @return [String] the name this node has in the response
         | 
| 14 8 | 
             
                  attr_reader :name
         | 
| 15 9 |  | 
| @@ -22,9 +16,9 @@ module GraphQL | |
| 22 16 | 
             
                  # This value is derived from {#scoped_children} after the rewrite is finished.
         | 
| 23 17 | 
             
                  # @return [Hash<GraphQL::ObjectType, Hash<String => Node>>]
         | 
| 24 18 | 
             
                  def typed_children
         | 
| 25 | 
            -
                    @ | 
| 19 | 
            +
                    @typed_childen ||= begin
         | 
| 20 | 
            +
                      new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
         | 
| 26 21 | 
             
                      if @scoped_children.any?
         | 
| 27 | 
            -
                        new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
         | 
| 28 22 | 
             
                        all_object_types = Set.new
         | 
| 29 23 | 
             
                        scoped_children.each_key { |t| all_object_types.merge(@query.possible_types(t)) }
         | 
| 30 24 | 
             
                        # Remove any scoped children which don't follow this return type
         | 
| @@ -33,11 +27,8 @@ module GraphQL | |
| 33 27 | 
             
                        all_object_types.each do |t|
         | 
| 34 28 | 
             
                          new_tc[t] = get_typed_children(t)
         | 
| 35 29 | 
             
                        end
         | 
| 36 | 
            -
                        new_tc
         | 
| 37 | 
            -
                      else
         | 
| 38 | 
            -
                        NO_TYPED_CHILDREN
         | 
| 39 30 | 
             
                      end
         | 
| 40 | 
            -
             | 
| 31 | 
            +
                      new_tc
         | 
| 41 32 | 
             
                    end
         | 
| 42 33 | 
             
                  end
         | 
| 43 34 |  | 
| @@ -134,20 +125,17 @@ module GraphQL | |
| 134 125 | 
             
                      @ast_nodes |= new_parent.ast_nodes
         | 
| 135 126 | 
             
                      @definitions |= new_parent.definitions
         | 
| 136 127 | 
             
                    end
         | 
| 137 | 
            -
                     | 
| 138 | 
            -
                     | 
| 139 | 
            -
                       | 
| 140 | 
            -
                       | 
| 141 | 
            -
                         | 
| 142 | 
            -
                         | 
| 143 | 
            -
                           | 
| 144 | 
            -
                           | 
| 145 | 
            -
                            prev_node | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
                            else
         | 
| 149 | 
            -
                              prev_fields[name] = new_node
         | 
| 150 | 
            -
                            end
         | 
| 128 | 
            +
                    scope ||= Scope.new(@query, @return_type.unwrap)
         | 
| 129 | 
            +
                    new_parent.scoped_children.each do |obj_type, new_fields|
         | 
| 130 | 
            +
                      inner_scope = scope.enter(obj_type)
         | 
| 131 | 
            +
                      inner_scope.each do |scoped_type|
         | 
| 132 | 
            +
                        prev_fields = @scoped_children[scoped_type]
         | 
| 133 | 
            +
                        new_fields.each do |name, new_node|
         | 
| 134 | 
            +
                          prev_node = prev_fields[name]
         | 
| 135 | 
            +
                          if prev_node
         | 
| 136 | 
            +
                            prev_node.deep_merge_node(new_node)
         | 
| 137 | 
            +
                          else
         | 
| 138 | 
            +
                            prev_fields[name] = new_node
         | 
| 151 139 | 
             
                          end
         | 
| 152 140 | 
             
                        end
         | 
| 153 141 | 
             
                      end
         | 
| @@ -24,9 +24,12 @@ module GraphQL | |
| 24 24 | 
             
                  # visiting the node itself and each of its typed children.
         | 
| 25 25 | 
             
                  def each_node(node)
         | 
| 26 26 | 
             
                    yield(node)
         | 
| 27 | 
            -
                    node.typed_children. | 
| 28 | 
            -
                       | 
| 29 | 
            -
             | 
| 27 | 
            +
                    if node.typed_children.any?
         | 
| 28 | 
            +
                      visit_block = Proc.new
         | 
| 29 | 
            +
                      node.typed_children.each do |obj_type, children|
         | 
| 30 | 
            +
                        children.each do |name, node|
         | 
| 31 | 
            +
                          each_node(node, &visit_block)
         | 
| 32 | 
            +
                        end
         | 
| 30 33 | 
             
                      end
         | 
| 31 34 | 
             
                    end
         | 
| 32 35 | 
             
                  end
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 | 
             
            GraphQL::Introspection::EnumValuesField = GraphQL::Field.define do
         | 
| 3 3 | 
             
              type types[!GraphQL::Introspection::EnumValueType]
         | 
| 4 | 
            -
              introspection true
         | 
| 5 4 | 
             
              argument :includeDeprecated, types.Boolean, default_value: false
         | 
| 6 5 | 
             
              resolve ->(object, arguments, context) do
         | 
| 7 6 | 
             
                if !object.kind.enum?
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 | 
             
            GraphQL::Introspection::FieldsField = GraphQL::Field.define do
         | 
| 3 3 | 
             
              type -> { types[!GraphQL::Introspection::FieldType] }
         | 
| 4 | 
            -
              introspection true
         | 
| 5 4 | 
             
              argument :includeDeprecated, GraphQL::BOOLEAN_TYPE, default_value: false
         | 
| 6 5 | 
             
              resolve ->(object, arguments, context) {
         | 
| 7 6 | 
             
                return nil if !object.kind.fields?
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 | 
             
            GraphQL::Introspection::InterfacesField = GraphQL::Field.define do
         | 
| 3 3 | 
             
              type -> { types[!GraphQL::Introspection::TypeType] }
         | 
| 4 | 
            -
              introspection true
         | 
| 5 4 | 
             
              resolve ->(target, a, ctx) {
         | 
| 6 5 | 
             
                if target.kind == GraphQL::TypeKinds::OBJECT
         | 
| 7 6 | 
             
                  ctx.warden.interfaces(target)
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 | 
             
            GraphQL::Introspection::PossibleTypesField = GraphQL::Field.define do
         | 
| 3 3 | 
             
              type -> { types[!GraphQL::Introspection::TypeType] }
         | 
| 4 | 
            -
              introspection true
         | 
| 5 4 | 
             
              resolve ->(target, args, ctx) {
         | 
| 6 5 | 
             
                if target.kind.resolves?
         | 
| 7 6 | 
             
                  ctx.warden.possible_types(target)
         | 
    
        data/lib/graphql/language.rb
    CHANGED
    
    | @@ -1,8 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            require "graphql/language/block_string"
         | 
| 3 | 
            -
            require "graphql/language/printer"
         | 
| 4 2 | 
             
            require "graphql/language/definition_slice"
         | 
| 5 | 
            -
            require "graphql/language/document_from_schema_definition"
         | 
| 6 3 | 
             
            require "graphql/language/generation"
         | 
| 7 4 | 
             
            require "graphql/language/lexer"
         | 
| 8 5 | 
             
            require "graphql/language/nodes"
         | 
| @@ -14,10 +14,189 @@ module GraphQL | |
| 14 14 | 
             
                  #
         | 
| 15 15 | 
             
                  # @param node [GraphQL::Language::Nodes::AbstractNode] an AST node to recursively stringify
         | 
| 16 16 | 
             
                  # @param indent [String] Whitespace to add to each printed node
         | 
| 17 | 
            -
                  # @param printer [GraphQL::Language::Printer] An optional custom printer for printing AST nodes. Defaults to GraphQL::Language::Printer
         | 
| 18 17 | 
             
                  # @return [String] Valid GraphQL for `node`
         | 
| 19 | 
            -
                  def generate(node, indent: "" | 
| 20 | 
            -
                     | 
| 18 | 
            +
                  def generate(node, indent: "")
         | 
| 19 | 
            +
                    case node
         | 
| 20 | 
            +
                    when Nodes::Document
         | 
| 21 | 
            +
                      node.definitions.map { |d| generate(d) }.join("\n\n")
         | 
| 22 | 
            +
                    when Nodes::Argument
         | 
| 23 | 
            +
                      "#{node.name}: #{generate(node.value)}".dup
         | 
| 24 | 
            +
                    when Nodes::Directive
         | 
| 25 | 
            +
                      out = "@#{node.name}".dup
         | 
| 26 | 
            +
                      out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
         | 
| 27 | 
            +
                      out
         | 
| 28 | 
            +
                    when Nodes::Enum
         | 
| 29 | 
            +
                      "#{node.name}".dup
         | 
| 30 | 
            +
                    when Nodes::NullValue
         | 
| 31 | 
            +
                      "null".dup
         | 
| 32 | 
            +
                    when Nodes::Field
         | 
| 33 | 
            +
                      out = "#{indent}".dup
         | 
| 34 | 
            +
                      out << "#{node.alias}: " if node.alias
         | 
| 35 | 
            +
                      out << "#{node.name}"
         | 
| 36 | 
            +
                      out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
         | 
| 37 | 
            +
                      out << generate_directives(node.directives)
         | 
| 38 | 
            +
                      out << generate_selections(node.selections, indent: indent)
         | 
| 39 | 
            +
                      out
         | 
| 40 | 
            +
                    when Nodes::FragmentDefinition
         | 
| 41 | 
            +
                      out = "#{indent}fragment #{node.name}".dup
         | 
| 42 | 
            +
                      if node.type
         | 
| 43 | 
            +
                        out << " on #{generate(node.type)}"
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
                      out << generate_directives(node.directives)
         | 
| 46 | 
            +
                      out << generate_selections(node.selections, indent: indent)
         | 
| 47 | 
            +
                      out
         | 
| 48 | 
            +
                    when Nodes::FragmentSpread
         | 
| 49 | 
            +
                      out = "#{indent}...#{node.name}".dup
         | 
| 50 | 
            +
                      out << generate_directives(node.directives)
         | 
| 51 | 
            +
                      out
         | 
| 52 | 
            +
                    when Nodes::InlineFragment
         | 
| 53 | 
            +
                      out = "#{indent}...".dup
         | 
| 54 | 
            +
                      if node.type
         | 
| 55 | 
            +
                        out << " on #{generate(node.type)}"
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                      out << generate_directives(node.directives)
         | 
| 58 | 
            +
                      out << generate_selections(node.selections, indent: indent)
         | 
| 59 | 
            +
                      out
         | 
| 60 | 
            +
                    when Nodes::InputObject
         | 
| 61 | 
            +
                      generate(node.to_h)
         | 
| 62 | 
            +
                    when Nodes::ListType
         | 
| 63 | 
            +
                      "[#{generate(node.of_type)}]".dup
         | 
| 64 | 
            +
                    when Nodes::NonNullType
         | 
| 65 | 
            +
                      "#{generate(node.of_type)}!".dup
         | 
| 66 | 
            +
                    when Nodes::OperationDefinition
         | 
| 67 | 
            +
                      out = "#{indent}#{node.operation_type}".dup
         | 
| 68 | 
            +
                      out << " #{node.name}" if node.name
         | 
| 69 | 
            +
                      out << "(#{node.variables.map { |v| generate(v) }.join(", ")})" if node.variables.any?
         | 
| 70 | 
            +
                      out << generate_directives(node.directives)
         | 
| 71 | 
            +
                      out << generate_selections(node.selections, indent: indent)
         | 
| 72 | 
            +
                      out
         | 
| 73 | 
            +
                    when Nodes::TypeName
         | 
| 74 | 
            +
                      "#{node.name}".dup
         | 
| 75 | 
            +
                    when Nodes::VariableDefinition
         | 
| 76 | 
            +
                      out = "$#{node.name}: #{generate(node.type)}".dup
         | 
| 77 | 
            +
                      out << " = #{generate(node.default_value)}" unless node.default_value.nil?
         | 
| 78 | 
            +
                      out
         | 
| 79 | 
            +
                    when Nodes::VariableIdentifier
         | 
| 80 | 
            +
                      "$#{node.name}".dup
         | 
| 81 | 
            +
                    when Nodes::SchemaDefinition
         | 
| 82 | 
            +
                      if (node.query.nil? || node.query == 'Query') &&
         | 
| 83 | 
            +
                         (node.mutation.nil? || node.mutation == 'Mutation') &&
         | 
| 84 | 
            +
                         (node.subscription.nil? || node.subscription == 'Subscription')
         | 
| 85 | 
            +
                        return
         | 
| 86 | 
            +
                      end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      out = "schema {\n".dup
         | 
| 89 | 
            +
                      out << "  query: #{node.query}\n" if node.query
         | 
| 90 | 
            +
                      out << "  mutation: #{node.mutation}\n" if node.mutation
         | 
| 91 | 
            +
                      out << "  subscription: #{node.subscription}\n" if node.subscription
         | 
| 92 | 
            +
                      out << "}"
         | 
| 93 | 
            +
                    when Nodes::ScalarTypeDefinition
         | 
| 94 | 
            +
                      out = generate_description(node)
         | 
| 95 | 
            +
                      out << "scalar #{node.name}"
         | 
| 96 | 
            +
                      out << generate_directives(node.directives)
         | 
| 97 | 
            +
                    when Nodes::ObjectTypeDefinition
         | 
| 98 | 
            +
                      out = generate_description(node)
         | 
| 99 | 
            +
                      out << "type #{node.name}"
         | 
| 100 | 
            +
                      out << generate_directives(node.directives)
         | 
| 101 | 
            +
                      out << " implements " << node.interfaces.map(&:name).join(", ") unless node.interfaces.empty?
         | 
| 102 | 
            +
                      out << generate_field_definitions(node.fields)
         | 
| 103 | 
            +
                    when Nodes::InputValueDefinition
         | 
| 104 | 
            +
                      out = "#{node.name}: #{generate(node.type)}".dup
         | 
| 105 | 
            +
                      out << " = #{generate(node.default_value)}" unless node.default_value.nil?
         | 
| 106 | 
            +
                      out << generate_directives(node.directives)
         | 
| 107 | 
            +
                    when Nodes::FieldDefinition
         | 
| 108 | 
            +
                      out = node.name.dup
         | 
| 109 | 
            +
                      unless node.arguments.empty?
         | 
| 110 | 
            +
                        out << "(" << node.arguments.map{ |arg| generate(arg) }.join(", ") << ")"
         | 
| 111 | 
            +
                      end
         | 
| 112 | 
            +
                      out << ": #{generate(node.type)}"
         | 
| 113 | 
            +
                      out << generate_directives(node.directives)
         | 
| 114 | 
            +
                    when Nodes::InterfaceTypeDefinition
         | 
| 115 | 
            +
                      out = generate_description(node)
         | 
| 116 | 
            +
                      out << "interface #{node.name}"
         | 
| 117 | 
            +
                      out << generate_directives(node.directives)
         | 
| 118 | 
            +
                      out << generate_field_definitions(node.fields)
         | 
| 119 | 
            +
                    when Nodes::UnionTypeDefinition
         | 
| 120 | 
            +
                      out = generate_description(node)
         | 
| 121 | 
            +
                      out << "union #{node.name}"
         | 
| 122 | 
            +
                      out << generate_directives(node.directives)
         | 
| 123 | 
            +
                      out << " = " + node.types.map(&:name).join(" | ")
         | 
| 124 | 
            +
                    when Nodes::EnumTypeDefinition
         | 
| 125 | 
            +
                      out = generate_description(node)
         | 
| 126 | 
            +
                      out << "enum #{node.name}#{generate_directives(node.directives)} {\n"
         | 
| 127 | 
            +
                      node.values.each.with_index do |value, i|
         | 
| 128 | 
            +
                        out << generate_description(value, indent: '  ', first_in_block: i == 0)
         | 
| 129 | 
            +
                        out << generate(value)
         | 
| 130 | 
            +
                      end
         | 
| 131 | 
            +
                      out << "}"
         | 
| 132 | 
            +
                    when Nodes::EnumValueDefinition
         | 
| 133 | 
            +
                      out = "  #{node.name}".dup
         | 
| 134 | 
            +
                      out << generate_directives(node.directives)
         | 
| 135 | 
            +
                      out << "\n"
         | 
| 136 | 
            +
                    when Nodes::InputObjectTypeDefinition
         | 
| 137 | 
            +
                      out = generate_description(node)
         | 
| 138 | 
            +
                      out << "input #{node.name}"
         | 
| 139 | 
            +
                      out << generate_directives(node.directives)
         | 
| 140 | 
            +
                      out << " {\n"
         | 
| 141 | 
            +
                      node.fields.each.with_index do |field, i|
         | 
| 142 | 
            +
                        out << generate_description(field, indent: '  ', first_in_block: i == 0)
         | 
| 143 | 
            +
                        out << "  #{generate(field)}\n"
         | 
| 144 | 
            +
                      end
         | 
| 145 | 
            +
                      out << "}"
         | 
| 146 | 
            +
                    when Nodes::DirectiveDefinition
         | 
| 147 | 
            +
                      out = generate_description(node)
         | 
| 148 | 
            +
                      out << "directive @#{node.name}"
         | 
| 149 | 
            +
                      out << "(#{node.arguments.map { |a| generate(a) }.join(", ")})" if node.arguments.any?
         | 
| 150 | 
            +
                      out << " on #{node.locations.join(' | ')}"
         | 
| 151 | 
            +
                    when Nodes::AbstractNode
         | 
| 152 | 
            +
                      node.to_query_string(indent: indent)
         | 
| 153 | 
            +
                    when FalseClass, Float, Integer, NilClass, String, TrueClass
         | 
| 154 | 
            +
                      GraphQL::Language.serialize(node)
         | 
| 155 | 
            +
                    when Array
         | 
| 156 | 
            +
                      "[#{node.map { |v| generate(v) }.join(", ")}]".dup
         | 
| 157 | 
            +
                    when Hash
         | 
| 158 | 
            +
                      "{#{node.map { |k, v| "#{k}: #{generate(v)}" }.join(", ")}}".dup
         | 
| 159 | 
            +
                    else
         | 
| 160 | 
            +
                      raise TypeError
         | 
| 161 | 
            +
                    end
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  private
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                  def generate_directives(directives)
         | 
| 167 | 
            +
                    if directives.any?
         | 
| 168 | 
            +
                      directives.map { |d| " #{generate(d)}" }.join
         | 
| 169 | 
            +
                    else
         | 
| 170 | 
            +
                      ""
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
                  end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                  def generate_selections(selections, indent: "")
         | 
| 175 | 
            +
                    if selections.any?
         | 
| 176 | 
            +
                      out = " {\n".dup
         | 
| 177 | 
            +
                      selections.each do |selection|
         | 
| 178 | 
            +
                        out << generate(selection, indent: indent + "  ") << "\n"
         | 
| 179 | 
            +
                      end
         | 
| 180 | 
            +
                      out << "#{indent}}"
         | 
| 181 | 
            +
                    else
         | 
| 182 | 
            +
                      ""
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  def generate_description(node, indent: '', first_in_block: true)
         | 
| 187 | 
            +
                    return ''.dup unless node.description
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                    description = indent != '' && !first_in_block ? "\n".dup : "".dup
         | 
| 190 | 
            +
                    description << GraphQL::Language::Comments.commentize(node.description, indent: indent)
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                  def generate_field_definitions(fields)
         | 
| 194 | 
            +
                    out = " {\n".dup
         | 
| 195 | 
            +
                    fields.each.with_index do |field, i|
         | 
| 196 | 
            +
                      out << generate_description(field, indent: '  ', first_in_block: i == 0)
         | 
| 197 | 
            +
                      out << "  #{generate(field)}\n"
         | 
| 198 | 
            +
                    end
         | 
| 199 | 
            +
                    out << "}"
         | 
| 21 200 | 
             
                  end
         | 
| 22 201 | 
             
                end
         | 
| 23 202 | 
             
              end
         |