graphql 2.4.8 → 2.4.11
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/graphql/backtrace/table.rb +95 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +5 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/dashboard.css +3 -0
- data/lib/graphql/dashboard/statics/dashboard.js +78 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/traces/index.html.erb +63 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +60 -0
- data/lib/graphql/dashboard.rb +142 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +64 -0
- data/lib/graphql/dataloader/active_record_source.rb +26 -0
- data/lib/graphql/dataloader/async_dataloader.rb +17 -5
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader/source.rb +2 -2
- data/lib/graphql/dataloader.rb +37 -5
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +11 -4
- data/lib/graphql/execution/interpreter/runtime.rb +60 -33
- data/lib/graphql/execution/interpreter.rb +9 -1
- data/lib/graphql/execution/multiplex.rb +0 -4
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +6 -12
- data/lib/graphql/language/parser.rb +1 -1
- data/lib/graphql/query.rb +8 -12
- data/lib/graphql/schema/enum.rb +36 -1
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/interface.rb +1 -0
- data/lib/graphql/schema/member/has_dataloader.rb +60 -0
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/object.rb +17 -8
- data/lib/graphql/schema/resolver.rb +2 -5
- data/lib/graphql/schema/validator/required_validator.rb +23 -6
- data/lib/graphql/schema/visibility/profile.rb +5 -5
- data/lib/graphql/schema/visibility.rb +14 -9
- data/lib/graphql/schema.rb +54 -28
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/serialize.rb +1 -3
- data/lib/graphql/tracing/active_support_notifications_trace.rb +6 -2
- data/lib/graphql/tracing/appoptics_trace.rb +3 -1
- data/lib/graphql/tracing/appsignal_trace.rb +6 -0
- data/lib/graphql/tracing/data_dog_trace.rb +5 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +93 -0
- data/lib/graphql/tracing/new_relic_trace.rb +147 -41
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +737 -0
- data/lib/graphql/tracing/prometheus_trace.rb +22 -0
- data/lib/graphql/tracing/scout_trace.rb +6 -0
- data/lib/graphql/tracing/sentry_trace.rb +5 -0
- data/lib/graphql/tracing/statsd_trace.rb +9 -0
- data/lib/graphql/tracing/trace.rb +125 -1
- data/lib/graphql/tracing.rb +2 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +3 -0
- metadata +148 -10
- data/lib/graphql/backtrace/inspect_result.rb +0 -38
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/schema/null_mask.rb +0 -11
| @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            module GraphQL
         | 
| 3 3 | 
             
              # Raised automatically when a field's resolve function returns `nil`
         | 
| 4 4 | 
             
              # for a non-null field.
         | 
| 5 | 
            -
              class InvalidNullError < GraphQL:: | 
| 5 | 
            +
              class InvalidNullError < GraphQL::Error
         | 
| 6 6 | 
             
                # @return [GraphQL::BaseType] The owner of {#field}
         | 
| 7 7 | 
             
                attr_reader :parent_type
         | 
| 8 8 |  | 
| @@ -12,23 +12,17 @@ module GraphQL | |
| 12 12 | 
             
                # @return [nil, GraphQL::ExecutionError] The invalid value for this field
         | 
| 13 13 | 
             
                attr_reader :value
         | 
| 14 14 |  | 
| 15 | 
            -
                 | 
| 15 | 
            +
                # @return [GraphQL::Language::Nodes::Field] the field where the error occurred
         | 
| 16 | 
            +
                attr_reader :ast_node
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def initialize(parent_type, field, value, ast_node)
         | 
| 16 19 | 
             
                  @parent_type = parent_type
         | 
| 17 20 | 
             
                  @field = field
         | 
| 18 21 | 
             
                  @value = value
         | 
| 22 | 
            +
                  @ast_node = ast_node
         | 
| 19 23 | 
             
                  super("Cannot return null for non-nullable field #{@parent_type.graphql_name}.#{@field.graphql_name}")
         | 
| 20 24 | 
             
                end
         | 
| 21 25 |  | 
| 22 | 
            -
                # @return [Hash] An entry for the response's "errors" key
         | 
| 23 | 
            -
                def to_h
         | 
| 24 | 
            -
                  { "message" => message }
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                # @deprecated always false
         | 
| 28 | 
            -
                def parent_error?
         | 
| 29 | 
            -
                  false
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
             | 
| 32 26 | 
             
                class << self
         | 
| 33 27 | 
             
                  attr_accessor :parent_class
         | 
| 34 28 |  | 
| @@ -161,7 +161,7 @@ module GraphQL | |
| 161 161 | 
             
                          expect_token(:VAR_SIGN)
         | 
| 162 162 | 
             
                          var_name = parse_name
         | 
| 163 163 | 
             
                          expect_token(:COLON)
         | 
| 164 | 
            -
                          var_type = self.type
         | 
| 164 | 
            +
                          var_type = self.type || raise_parse_error("Missing type definition for variable: $#{var_name}")
         | 
| 165 165 | 
             
                          default_value = if at?(:EQUALS)
         | 
| 166 166 | 
             
                            advance_token
         | 
| 167 167 | 
             
                            value
         | 
    
        data/lib/graphql/query.rb
    CHANGED
    
    | @@ -97,21 +97,22 @@ module GraphQL | |
| 97 97 | 
             
                # @param root_value [Object] the object used to resolve fields on the root type
         | 
| 98 98 | 
             
                # @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
         | 
| 99 99 | 
             
                # @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
         | 
| 100 | 
            -
                # @param visibility_profile [Symbol]
         | 
| 100 | 
            +
                # @param visibility_profile [Symbol] Another way to assign `context[:visibility_profile]`
         | 
| 101 101 | 
             
                def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, static_validator: nil, visibility_profile: nil, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, warden: nil, use_visibility_profile: nil)
         | 
| 102 102 | 
             
                  # Even if `variables: nil` is passed, use an empty hash for simpler logic
         | 
| 103 103 | 
             
                  variables ||= {}
         | 
| 104 104 | 
             
                  @schema = schema
         | 
| 105 105 | 
             
                  @context = schema.context_class.new(query: self, values: context)
         | 
| 106 | 
            +
                  if visibility_profile
         | 
| 107 | 
            +
                    @context[:visibility_profile] ||= visibility_profile
         | 
| 108 | 
            +
                  end
         | 
| 106 109 |  | 
| 107 110 | 
             
                  if use_visibility_profile.nil?
         | 
| 108 111 | 
             
                    use_visibility_profile = warden ? false : schema.use_visibility_profile?
         | 
| 109 112 | 
             
                  end
         | 
| 110 113 |  | 
| 111 | 
            -
                  @visibility_profile = visibility_profile
         | 
| 112 | 
            -
             | 
| 113 114 | 
             
                  if use_visibility_profile
         | 
| 114 | 
            -
                    @visibility_profile = @schema.visibility.profile_for(@context | 
| 115 | 
            +
                    @visibility_profile = @schema.visibility.profile_for(@context)
         | 
| 115 116 | 
             
                    @warden = Schema::Warden::NullWarden.new(context: @context, schema: @schema)
         | 
| 116 117 | 
             
                  else
         | 
| 117 118 | 
             
                    @visibility_profile = nil
         | 
| @@ -127,14 +128,6 @@ module GraphQL | |
| 127 128 | 
             
                  context_tracers = (context ? context.fetch(:tracers, []) : [])
         | 
| 128 129 | 
             
                  @tracers = schema.tracers + context_tracers
         | 
| 129 130 |  | 
| 130 | 
            -
                  # Support `ctx[:backtrace] = true` for wrapping backtraces
         | 
| 131 | 
            -
                  if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
         | 
| 132 | 
            -
                    if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
         | 
| 133 | 
            -
                      context_tracers += [GraphQL::Backtrace::Tracer]
         | 
| 134 | 
            -
                      @tracers << GraphQL::Backtrace::Tracer
         | 
| 135 | 
            -
                    end
         | 
| 136 | 
            -
                  end
         | 
| 137 | 
            -
             | 
| 138 131 | 
             
                  if !context_tracers.empty? && !(schema.trace_class <= GraphQL::Tracing::CallLegacyTracers)
         | 
| 139 132 | 
             
                    raise ArgumentError, "context[:tracers] are not supported without `trace_with(GraphQL::Tracing::CallLegacyTracers)` in the schema configuration, please add it."
         | 
| 140 133 | 
             
                  end
         | 
| @@ -448,6 +441,7 @@ module GraphQL | |
| 448 441 | 
             
                  @warden ||= @schema.warden_class.new(schema: @schema, context: @context)
         | 
| 449 442 | 
             
                  parse_error = nil
         | 
| 450 443 | 
             
                  @document ||= begin
         | 
| 444 | 
            +
                    current_trace.begin_parse(query_string)
         | 
| 451 445 | 
             
                    if query_string
         | 
| 452 446 | 
             
                      GraphQL.parse(query_string, trace: self.current_trace, max_tokens: @schema.max_query_string_tokens)
         | 
| 453 447 | 
             
                    end
         | 
| @@ -455,6 +449,8 @@ module GraphQL | |
| 455 449 | 
             
                    parse_error = err
         | 
| 456 450 | 
             
                    @schema.parse_error(err, @context)
         | 
| 457 451 | 
             
                    nil
         | 
| 452 | 
            +
                  ensure
         | 
| 453 | 
            +
                    current_trace.end_parse(query_string)
         | 
| 458 454 | 
             
                  end
         | 
| 459 455 |  | 
| 460 456 | 
             
                  @fragments = {}
         | 
    
        data/lib/graphql/schema/enum.rb
    CHANGED
    
    | @@ -61,12 +61,19 @@ module GraphQL | |
| 61 61 | 
             
                    # @option kwargs [String] :description, the GraphQL description for this value, present in documentation
         | 
| 62 62 | 
             
                    # @option kwargs [String] :comment, the GraphQL comment for this value, present in documentation
         | 
| 63 63 | 
             
                    # @option kwargs [::Object] :value the translated Ruby value for this object (defaults to `graphql_name`)
         | 
| 64 | 
            +
                    # @option kwargs [::Object] :value_method, the method name to fetch `graphql_name` (defaults to `graphql_name.downcase`)
         | 
| 64 65 | 
             
                    # @option kwargs [String] :deprecation_reason if this object is deprecated, include a message here
         | 
| 66 | 
            +
                    # @param value_method [Symbol, false] A method to generate for this value, or `false` to skip generation
         | 
| 65 67 | 
             
                    # @return [void]
         | 
| 66 68 | 
             
                    # @see {Schema::EnumValue} which handles these inputs by default
         | 
| 67 | 
            -
                    def value(*args, **kwargs, &block)
         | 
| 69 | 
            +
                    def value(*args, value_method: nil, **kwargs, &block)
         | 
| 68 70 | 
             
                      kwargs[:owner] = self
         | 
| 69 71 | 
             
                      value = enum_value_class.new(*args, **kwargs, &block)
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      if value_method || (value_methods && value_method != false)
         | 
| 74 | 
            +
                        generate_value_method(value, value_method)
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
             | 
| 70 77 | 
             
                      key = value.graphql_name
         | 
| 71 78 | 
             
                      prev_value = own_values[key]
         | 
| 72 79 | 
             
                      case prev_value
         | 
| @@ -154,6 +161,18 @@ module GraphQL | |
| 154 161 | 
             
                      end
         | 
| 155 162 | 
             
                    end
         | 
| 156 163 |  | 
| 164 | 
            +
                    def value_methods(new_value = NOT_CONFIGURED)
         | 
| 165 | 
            +
                      if NOT_CONFIGURED.equal?(new_value)
         | 
| 166 | 
            +
                        if @value_methods != nil
         | 
| 167 | 
            +
                          @value_methods
         | 
| 168 | 
            +
                        else
         | 
| 169 | 
            +
                          find_inherited_value(:value_methods, false)
         | 
| 170 | 
            +
                        end
         | 
| 171 | 
            +
                      else
         | 
| 172 | 
            +
                        @value_methods = new_value
         | 
| 173 | 
            +
                      end
         | 
| 174 | 
            +
                    end
         | 
| 175 | 
            +
             | 
| 157 176 | 
             
                    def kind
         | 
| 158 177 | 
             
                      GraphQL::TypeKinds::ENUM
         | 
| 159 178 | 
             
                    end
         | 
| @@ -215,6 +234,7 @@ module GraphQL | |
| 215 234 | 
             
                        # because they would end up with names like `#<Class0x1234>::UnresolvedValueError` which messes up bug trackers
         | 
| 216 235 | 
             
                        child_class.const_set(:UnresolvedValueError, Class.new(Schema::Enum::UnresolvedValueError))
         | 
| 217 236 | 
             
                      end
         | 
| 237 | 
            +
                      child_class.class_eval { @value_methods = nil }
         | 
| 218 238 | 
             
                      super
         | 
| 219 239 | 
             
                    end
         | 
| 220 240 |  | 
| @@ -223,6 +243,21 @@ module GraphQL | |
| 223 243 | 
             
                    def own_values
         | 
| 224 244 | 
             
                      @own_values ||= {}
         | 
| 225 245 | 
             
                    end
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                    def generate_value_method(value, configured_value_method)
         | 
| 248 | 
            +
                      return if configured_value_method == false
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                      value_method_name = configured_value_method || value.graphql_name.downcase
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                      if respond_to?(value_method_name.to_sym)
         | 
| 253 | 
            +
                        warn "Failed to define value method for :#{value_method_name}, because " \
         | 
| 254 | 
            +
                          "#{value.owner.name || value.owner.graphql_name} already responds to that method. Use `value_method:` to override the method name " \
         | 
| 255 | 
            +
                          "or `value_method: false` to disable Enum value method generation."
         | 
| 256 | 
            +
                        return
         | 
| 257 | 
            +
                      end
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                      instance_eval("def #{value_method_name}; #{value.graphql_name.inspect}; end;", __FILE__, __LINE__)
         | 
| 260 | 
            +
                    end
         | 
| 226 261 | 
             
                  end
         | 
| 227 262 |  | 
| 228 263 | 
             
                  enum_value_class(GraphQL::Schema::EnumValue)
         | 
| @@ -13,6 +13,7 @@ module GraphQL | |
| 13 13 | 
             
                    include GraphQL::Schema::Member::Scoped
         | 
| 14 14 | 
             
                    include GraphQL::Schema::Member::HasAstNode
         | 
| 15 15 | 
             
                    include GraphQL::Schema::Member::HasUnresolvedTypeError
         | 
| 16 | 
            +
                    include GraphQL::Schema::Member::HasDataloader
         | 
| 16 17 | 
             
                    include GraphQL::Schema::Member::HasDirectives
         | 
| 17 18 | 
             
                    include GraphQL::Schema::Member::HasInterfaces
         | 
| 18 19 |  | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module GraphQL
         | 
| 4 | 
            +
              class Schema
         | 
| 5 | 
            +
                class Member
         | 
| 6 | 
            +
                  module HasDataloader
         | 
| 7 | 
            +
                    # @return [GraphQL::Dataloader] The dataloader for the currently-running query
         | 
| 8 | 
            +
                    def dataloader
         | 
| 9 | 
            +
                      context.dataloader
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    # A shortcut method for loading a key from a source.
         | 
| 13 | 
            +
                    # Identical to `dataloader.with(source_class, *source_args).load(load_key)`
         | 
| 14 | 
            +
                    # @param source_class [Class<GraphQL::Dataloader::Source>]
         | 
| 15 | 
            +
                    # @param source_args [Array<Object>] Any extra parameters defined in `source_class`'s `initialize` method
         | 
| 16 | 
            +
                    # @param load_key [Object] The key to look up using `def fetch`
         | 
| 17 | 
            +
                    def dataload(source_class, *source_args, load_key)
         | 
| 18 | 
            +
                      dataloader.with(source_class, *source_args).load(load_key)
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    # Find an object with ActiveRecord via {Dataloader::ActiveRecordSource}.
         | 
| 22 | 
            +
                    # @param model [Class<ActiveRecord::Base>]
         | 
| 23 | 
            +
                    # @param find_by_value [Object] Usually an `id`, might be another value if `find_by:` is also provided
         | 
| 24 | 
            +
                    # @param find_by [Symbol, String] A column name to look the record up by. (Defaults to the model's primary key.)
         | 
| 25 | 
            +
                    # @return [ActiveRecord::Base, nil]
         | 
| 26 | 
            +
                    # @example Finding a record by ID
         | 
| 27 | 
            +
                    #   dataload_record(Post, 5) # Like `Post.find(5)`, but dataloaded
         | 
| 28 | 
            +
                    # @example Finding a record by another attribute
         | 
| 29 | 
            +
                    #   dataload_record(User, "matz", find_by: :handle) # Like `User.find_by(handle: "matz")`, but dataloaded
         | 
| 30 | 
            +
                    def dataload_record(model, find_by_value, find_by: nil)
         | 
| 31 | 
            +
                      source = if find_by
         | 
| 32 | 
            +
                        dataloader.with(Dataloader::ActiveRecordSource, model, find_by: find_by)
         | 
| 33 | 
            +
                      else
         | 
| 34 | 
            +
                        dataloader.with(Dataloader::ActiveRecordSource, model)
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      source.load(find_by_value)
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    # Look up an associated record using a Rails association.
         | 
| 41 | 
            +
                    # @param association_name [Symbol] A `belongs_to` or `has_one` association. (If a `has_many` association is named here, it will be selected without pagination.)
         | 
| 42 | 
            +
                    # @param record [ActiveRecord::Base] The object that the association belongs to.
         | 
| 43 | 
            +
                    # @param scope [ActiveRecord::Relation] A scope to look up the associated record in
         | 
| 44 | 
            +
                    # @return [ActiveRecord::Base, nil] The associated record, if there is one
         | 
| 45 | 
            +
                    # @example Looking up a belongs_to on the current object
         | 
| 46 | 
            +
                    #    dataload_association(:parent) # Equivalent to `object.parent`, but dataloaded
         | 
| 47 | 
            +
                    # @example Looking up an associated record on some other object
         | 
| 48 | 
            +
                    #    dataload_association(:post, comment) # Equivalent to `comment.post`, but dataloaded
         | 
| 49 | 
            +
                    def dataload_association(record = object, association_name, scope: nil)
         | 
| 50 | 
            +
                      source = if scope
         | 
| 51 | 
            +
                        dataloader.with(Dataloader::ActiveRecordAssociationSource, association_name, scope)
         | 
| 52 | 
            +
                      else
         | 
| 53 | 
            +
                        dataloader.with(Dataloader::ActiveRecordAssociationSource, association_name)
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                      source.load(record)
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
| @@ -2,6 +2,7 @@ | |
| 2 2 | 
             
            require 'graphql/schema/member/base_dsl_methods'
         | 
| 3 3 | 
             
            require 'graphql/schema/member/graphql_type_names'
         | 
| 4 4 | 
             
            require 'graphql/schema/member/has_ast_node'
         | 
| 5 | 
            +
            require 'graphql/schema/member/has_dataloader'
         | 
| 5 6 | 
             
            require 'graphql/schema/member/has_directives'
         | 
| 6 7 | 
             
            require 'graphql/schema/member/has_deprecation_reason'
         | 
| 7 8 | 
             
            require 'graphql/schema/member/has_interfaces'
         | 
| @@ -7,6 +7,7 @@ module GraphQL | |
| 7 7 | 
             
                class Object < GraphQL::Schema::Member
         | 
| 8 8 | 
             
                  extend GraphQL::Schema::Member::HasFields
         | 
| 9 9 | 
             
                  extend GraphQL::Schema::Member::HasInterfaces
         | 
| 10 | 
            +
                  include Member::HasDataloader
         | 
| 10 11 |  | 
| 11 12 | 
             
                  # Raised when an Object doesn't have any field defined and hasn't explicitly opted out of this requirement
         | 
| 12 13 | 
             
                  class FieldsAreRequiredError < GraphQL::Error
         | 
| @@ -65,20 +66,28 @@ module GraphQL | |
| 65 66 | 
             
                    # @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
         | 
| 66 67 | 
             
                    # @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
         | 
| 67 68 | 
             
                    def authorized_new(object, context)
         | 
| 68 | 
            -
                       | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 69 | 
            +
                      context.query.current_trace.begin_authorized(self, object, context)
         | 
| 70 | 
            +
                      begin
         | 
| 71 | 
            +
                        maybe_lazy_auth_val = context.query.current_trace.authorized(query: context.query, type: self, object: object) do
         | 
| 72 | 
            +
                          begin
         | 
| 73 | 
            +
                            authorized?(object, context)
         | 
| 74 | 
            +
                          rescue GraphQL::UnauthorizedError => err
         | 
| 75 | 
            +
                            context.schema.unauthorized_object(err)
         | 
| 76 | 
            +
                          rescue StandardError => err
         | 
| 77 | 
            +
                            context.query.handle_or_reraise(err)
         | 
| 78 | 
            +
                          end
         | 
| 75 79 | 
             
                        end
         | 
| 80 | 
            +
                      ensure
         | 
| 81 | 
            +
                        context.query.current_trace.end_authorized(self, object, context, maybe_lazy_auth_val)
         | 
| 76 82 | 
             
                      end
         | 
| 77 83 |  | 
| 78 84 | 
             
                      auth_val = if context.schema.lazy?(maybe_lazy_auth_val)
         | 
| 79 85 | 
             
                        GraphQL::Execution::Lazy.new do
         | 
| 86 | 
            +
                          context.query.current_trace.begin_authorized(self, object, context)
         | 
| 80 87 | 
             
                          context.query.current_trace.authorized_lazy(query: context.query, type: self, object: object) do
         | 
| 81 | 
            -
                            context.schema.sync_lazy(maybe_lazy_auth_val)
         | 
| 88 | 
            +
                            res = context.schema.sync_lazy(maybe_lazy_auth_val)
         | 
| 89 | 
            +
                            context.query.current_trace.end_authorized(self, object, context, res)
         | 
| 90 | 
            +
                            res
         | 
| 82 91 | 
             
                          end
         | 
| 83 92 | 
             
                        end
         | 
| 84 93 | 
             
                      else
         | 
| @@ -22,11 +22,13 @@ module GraphQL | |
| 22 22 | 
             
                  include Schema::Member::GraphQLTypeNames
         | 
| 23 23 | 
             
                  # Really we only need description & comment from here, but:
         | 
| 24 24 | 
             
                  extend Schema::Member::BaseDSLMethods
         | 
| 25 | 
            +
                  extend Member::BaseDSLMethods::ConfigurationExtension
         | 
| 25 26 | 
             
                  extend GraphQL::Schema::Member::HasArguments
         | 
| 26 27 | 
             
                  extend GraphQL::Schema::Member::HasValidators
         | 
| 27 28 | 
             
                  include Schema::Member::HasPath
         | 
| 28 29 | 
             
                  extend Schema::Member::HasPath
         | 
| 29 30 | 
             
                  extend Schema::Member::HasDirectives
         | 
| 31 | 
            +
                  include Schema::Member::HasDataloader
         | 
| 30 32 |  | 
| 31 33 | 
             
                  # @param object [Object] The application object that this field is being resolved on
         | 
| 32 34 | 
             
                  # @param context [GraphQL::Query::Context]
         | 
| @@ -49,11 +51,6 @@ module GraphQL | |
| 49 51 | 
             
                  # @return [GraphQL::Query::Context]
         | 
| 50 52 | 
             
                  attr_reader :context
         | 
| 51 53 |  | 
| 52 | 
            -
                  # @return [GraphQL::Dataloader]
         | 
| 53 | 
            -
                  def dataloader
         | 
| 54 | 
            -
                    context.dataloader
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 54 | 
             
                  # @return [GraphQL::Schema::Field]
         | 
| 58 55 | 
             
                  attr_reader :field
         | 
| 59 56 |  | 
| @@ -51,19 +51,36 @@ module GraphQL | |
| 51 51 | 
             
                    end
         | 
| 52 52 |  | 
| 53 53 | 
             
                    def validate(_object, context, value)
         | 
| 54 | 
            -
                       | 
| 54 | 
            +
                      fully_matched_conditions = 0
         | 
| 55 | 
            +
                      partially_matched_conditions = 0
         | 
| 55 56 |  | 
| 56 57 | 
             
                      if !value.nil?
         | 
| 57 58 | 
             
                        @one_of.each do |one_of_condition|
         | 
| 58 59 | 
             
                          case one_of_condition
         | 
| 59 60 | 
             
                          when Symbol
         | 
| 60 61 | 
             
                            if value.key?(one_of_condition)
         | 
| 61 | 
            -
                               | 
| 62 | 
            +
                              fully_matched_conditions += 1
         | 
| 62 63 | 
             
                            end
         | 
| 63 64 | 
             
                          when Array
         | 
| 64 | 
            -
                             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 65 | 
            +
                            any_match = false
         | 
| 66 | 
            +
                            full_match = true
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                            one_of_condition.each do |k|
         | 
| 69 | 
            +
                              if value.key?(k)
         | 
| 70 | 
            +
                                any_match = true
         | 
| 71 | 
            +
                              else
         | 
| 72 | 
            +
                                full_match = false
         | 
| 73 | 
            +
                              end
         | 
| 74 | 
            +
                            end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                            partial_match = !full_match && any_match
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                            if full_match
         | 
| 79 | 
            +
                              fully_matched_conditions += 1
         | 
| 80 | 
            +
                            end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                            if partial_match
         | 
| 83 | 
            +
                              partially_matched_conditions += 1
         | 
| 67 84 | 
             
                            end
         | 
| 68 85 | 
             
                          else
         | 
| 69 86 | 
             
                            raise ArgumentError, "Unknown one_of condition: #{one_of_condition.inspect}"
         | 
| @@ -71,7 +88,7 @@ module GraphQL | |
| 71 88 | 
             
                        end
         | 
| 72 89 | 
             
                      end
         | 
| 73 90 |  | 
| 74 | 
            -
                      if  | 
| 91 | 
            +
                      if fully_matched_conditions == 1 && partially_matched_conditions == 0
         | 
| 75 92 | 
             
                        nil # OK
         | 
| 76 93 | 
             
                      else
         | 
| 77 94 | 
             
                        @message || build_message(context)
         | 
| @@ -18,7 +18,7 @@ module GraphQL | |
| 18 18 | 
             
                      if ctx.respond_to?(:types) && (types = ctx.types).is_a?(self)
         | 
| 19 19 | 
             
                        types
         | 
| 20 20 | 
             
                      else
         | 
| 21 | 
            -
                        schema.visibility.profile_for(ctx | 
| 21 | 
            +
                        schema.visibility.profile_for(ctx)
         | 
| 22 22 | 
             
                      end
         | 
| 23 23 | 
             
                    end
         | 
| 24 24 |  | 
| @@ -159,7 +159,7 @@ module GraphQL | |
| 159 159 | 
             
                            end
         | 
| 160 160 | 
             
                          end
         | 
| 161 161 | 
             
                        end
         | 
| 162 | 
            -
                        visible_f | 
| 162 | 
            +
                        visible_f&.ensure_loaded
         | 
| 163 163 | 
             
                      elsif f && @cached_visible_fields[owner][f.ensure_loaded]
         | 
| 164 164 | 
             
                        f
         | 
| 165 165 | 
             
                      else
         | 
| @@ -319,9 +319,9 @@ module GraphQL | |
| 319 319 | 
             
                      case type.kind.name
         | 
| 320 320 | 
             
                      when "INTERFACE"
         | 
| 321 321 | 
             
                        pts = []
         | 
| 322 | 
            -
                        @schema.visibility.all_interface_type_memberships[type].each do |itm|
         | 
| 323 | 
            -
                          if @cached_visible[itm] &&  | 
| 324 | 
            -
                            pts <<  | 
| 322 | 
            +
                        @schema.visibility.all_interface_type_memberships[type].each do |(itm, impl_type)|
         | 
| 323 | 
            +
                          if @cached_visible[itm] && @cached_visible[impl_type] && referenced?(impl_type)
         | 
| 324 | 
            +
                            pts << impl_type
         | 
| 325 325 | 
             
                          end
         | 
| 326 326 | 
             
                        end
         | 
| 327 327 | 
             
                        pts
         | 
| @@ -13,6 +13,10 @@ module GraphQL | |
| 13 13 | 
             
                  # @param preload [Boolean] if `true`, load the default schema profile and all named profiles immediately (defaults to `true` for `Rails.env.production?`)
         | 
| 14 14 | 
             
                  # @param migration_errors [Boolean] if `true`, raise an error when `Visibility` and `Warden` return different results
         | 
| 15 15 | 
             
                  def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails) ? Rails.env.production? : nil), migration_errors: false)
         | 
| 16 | 
            +
                    profiles&.each { |name, ctx|
         | 
| 17 | 
            +
                      ctx[:visibility_profile] = name
         | 
| 18 | 
            +
                      ctx.freeze
         | 
| 19 | 
            +
                    }
         | 
| 16 20 | 
             
                    schema.visibility = self.new(schema, dynamic: dynamic, preload: preload, profiles: profiles, migration_errors: migration_errors)
         | 
| 17 21 | 
             
                    if preload
         | 
| 18 22 | 
             
                      schema.visibility.preload
         | 
| @@ -81,8 +85,7 @@ module GraphQL | |
| 81 85 | 
             
                    types_to_visit.compact!
         | 
| 82 86 | 
             
                    ensure_all_loaded(types_to_visit)
         | 
| 83 87 | 
             
                    @profiles.each do |profile_name, example_ctx|
         | 
| 84 | 
            -
                       | 
| 85 | 
            -
                      prof = profile_for(example_ctx, profile_name)
         | 
| 88 | 
            +
                      prof = profile_for(example_ctx)
         | 
| 86 89 | 
             
                      prof.all_types # force loading
         | 
| 87 90 | 
             
                    end
         | 
| 88 91 | 
             
                  end
         | 
| @@ -145,7 +148,7 @@ module GraphQL | |
| 145 148 |  | 
| 146 149 | 
             
                  attr_reader :cached_profiles
         | 
| 147 150 |  | 
| 148 | 
            -
                  def profile_for(context, visibility_profile)
         | 
| 151 | 
            +
                  def profile_for(context, visibility_profile = context[:visibility_profile])
         | 
| 149 152 | 
             
                    if !@profiles.empty?
         | 
| 150 153 | 
             
                      if visibility_profile.nil?
         | 
| 151 154 | 
             
                        if @dynamic
         | 
| @@ -160,7 +163,8 @@ module GraphQL | |
| 160 163 | 
             
                      elsif !@profiles.include?(visibility_profile)
         | 
| 161 164 | 
             
                        raise ArgumentError, "`#{visibility_profile.inspect}` isn't allowed for `visibility_profile:` (must be one of #{@profiles.keys.map(&:inspect).join(", ")}). Or, add `#{visibility_profile.inspect}` to the list of profiles in the schema definition."
         | 
| 162 165 | 
             
                      else
         | 
| 163 | 
            -
                        @ | 
| 166 | 
            +
                        profile_ctx = @profiles[visibility_profile]
         | 
| 167 | 
            +
                        @cached_profiles[visibility_profile] ||= @schema.visibility_profile_class.new(name: visibility_profile, context: profile_ctx, schema: @schema)
         | 
| 164 168 | 
             
                      end
         | 
| 165 169 | 
             
                    elsif context.is_a?(Query::NullContext)
         | 
| 166 170 | 
             
                      top_level_profile
         | 
| @@ -222,7 +226,9 @@ module GraphQL | |
| 222 226 | 
             
                          elsif member.respond_to?(:interface_type_memberships)
         | 
| 223 227 | 
             
                            member.interface_type_memberships.each do |itm|
         | 
| 224 228 | 
             
                              @all_references[itm.abstract_type] << member
         | 
| 225 | 
            -
                               | 
| 229 | 
            +
                              # `itm.object_type` may not actually be `member` if this implementation
         | 
| 230 | 
            +
                              # is inherited from a superclass
         | 
| 231 | 
            +
                              @interface_type_memberships[itm.abstract_type] << [itm, member]
         | 
| 226 232 | 
             
                            end
         | 
| 227 233 | 
             
                          elsif member < GraphQL::Schema::Union
         | 
| 228 234 | 
             
                            @unions_for_references << member
         | 
| @@ -271,13 +277,12 @@ module GraphQL | |
| 271 277 |  | 
| 272 278 | 
             
                    # TODO: somehow don't iterate over all these,
         | 
| 273 279 | 
             
                    # only the ones that may have been modified
         | 
| 274 | 
            -
                    @interface_type_memberships.each do |int_type,  | 
| 280 | 
            +
                    @interface_type_memberships.each do |int_type, type_membership_pairs|
         | 
| 275 281 | 
             
                      referers = @all_references[int_type].select { |r| r.is_a?(GraphQL::Schema::Field) }
         | 
| 276 282 | 
             
                      if !referers.empty?
         | 
| 277 | 
            -
                         | 
| 278 | 
            -
                          implementor_type = type_membership.object_type
         | 
| 283 | 
            +
                        type_membership_pairs.each do |(type_membership, impl_type)|
         | 
| 279 284 | 
             
                          # Add new items only:
         | 
| 280 | 
            -
                          @all_references[ | 
| 285 | 
            +
                          @all_references[impl_type] |= referers
         | 
| 281 286 | 
             
                        end
         | 
| 282 287 | 
             
                      end
         | 
| 283 288 | 
             
                    end
         | 
    
        data/lib/graphql/schema.rb
    CHANGED
    
    | @@ -7,7 +7,6 @@ require "graphql/schema/find_inherited_value" | |
| 7 7 | 
             
            require "graphql/schema/finder"
         | 
| 8 8 | 
             
            require "graphql/schema/introspection_system"
         | 
| 9 9 | 
             
            require "graphql/schema/late_bound_type"
         | 
| 10 | 
            -
            require "graphql/schema/null_mask"
         | 
| 11 10 | 
             
            require "graphql/schema/timeout"
         | 
| 12 11 | 
             
            require "graphql/schema/type_expression"
         | 
| 13 12 | 
             
            require "graphql/schema/unique_within_type"
         | 
| @@ -167,9 +166,6 @@ module GraphQL | |
| 167 166 | 
             
                      mods.each { |mod| new_class.include(mod) }
         | 
| 168 167 | 
             
                      new_class.include(DefaultTraceClass)
         | 
| 169 168 | 
             
                      trace_mode(:default, new_class)
         | 
| 170 | 
            -
                      backtrace_class = Class.new(new_class)
         | 
| 171 | 
            -
                      backtrace_class.include(GraphQL::Backtrace::Trace)
         | 
| 172 | 
            -
                      trace_mode(:default_backtrace, backtrace_class)
         | 
| 173 169 | 
             
                    end
         | 
| 174 170 | 
             
                    trace_class_for(:default, build: true)
         | 
| 175 171 | 
             
                  end
         | 
| @@ -216,11 +212,6 @@ module GraphQL | |
| 216 212 | 
             
                      const_set(:DefaultTrace, Class.new(base_class) do
         | 
| 217 213 | 
             
                        include DefaultTraceClass
         | 
| 218 214 | 
             
                      end)
         | 
| 219 | 
            -
                    when :default_backtrace
         | 
| 220 | 
            -
                      schema_base_class = trace_class_for(:default, build: true)
         | 
| 221 | 
            -
                      const_set(:DefaultTraceBacktrace, Class.new(schema_base_class) do
         | 
| 222 | 
            -
                        include(GraphQL::Backtrace::Trace)
         | 
| 223 | 
            -
                      end)
         | 
| 224 215 | 
             
                    else
         | 
| 225 216 | 
             
                      # First, see if the superclass has a custom-defined class for this.
         | 
| 226 217 | 
             
                      # Then, if it doesn't, use this class's default trace
         | 
| @@ -1118,6 +1109,9 @@ module GraphQL | |
| 1118 1109 | 
             
                    }
         | 
| 1119 1110 | 
             
                  end
         | 
| 1120 1111 |  | 
| 1112 | 
            +
                  # @api private
         | 
| 1113 | 
            +
                  attr_accessor :using_backtrace
         | 
| 1114 | 
            +
             | 
| 1121 1115 | 
             
                  # @api private
         | 
| 1122 1116 | 
             
                  def handle_or_reraise(context, err)
         | 
| 1123 1117 | 
             
                    handler = Execution::Errors.find_handler_for(self, err.class)
         | 
| @@ -1131,6 +1125,10 @@ module GraphQL | |
| 1131 1125 | 
             
                      end
         | 
| 1132 1126 | 
             
                      handler[:handler].call(err, obj, args, context, field)
         | 
| 1133 1127 | 
             
                    else
         | 
| 1128 | 
            +
                      if (context[:backtrace] || using_backtrace) && !err.is_a?(GraphQL::ExecutionError)
         | 
| 1129 | 
            +
                        err = GraphQL::Backtrace::TracedError.new(err, context)
         | 
| 1130 | 
            +
                      end
         | 
| 1131 | 
            +
             | 
| 1134 1132 | 
             
                      raise err
         | 
| 1135 1133 | 
             
                    end
         | 
| 1136 1134 | 
             
                  end
         | 
| @@ -1300,7 +1298,10 @@ module GraphQL | |
| 1300 1298 | 
             
                  def type_error(type_error, ctx)
         | 
| 1301 1299 | 
             
                    case type_error
         | 
| 1302 1300 | 
             
                    when GraphQL::InvalidNullError
         | 
| 1303 | 
            -
                       | 
| 1301 | 
            +
                      execution_error = GraphQL::ExecutionError.new(type_error.message, ast_node: type_error.ast_node)
         | 
| 1302 | 
            +
                      execution_error.path = ctx[:current_path]
         | 
| 1303 | 
            +
             | 
| 1304 | 
            +
                      ctx.errors << execution_error
         | 
| 1304 1305 | 
             
                    when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
         | 
| 1305 1306 | 
             
                      raise type_error
         | 
| 1306 1307 | 
             
                    when GraphQL::IntegerDecodingError
         | 
| @@ -1368,6 +1369,16 @@ module GraphQL | |
| 1368 1369 | 
             
                    }.freeze
         | 
| 1369 1370 | 
             
                  end
         | 
| 1370 1371 |  | 
| 1372 | 
            +
                  # @return [GraphQL::Tracing::DetailedTrace] if it has been configured for this schema
         | 
| 1373 | 
            +
                  attr_accessor :detailed_trace
         | 
| 1374 | 
            +
             | 
| 1375 | 
            +
                  # @param query [GraphQL::Query, GraphQL::Execution::Multiplex] Called with a multiplex when multiple queries are executed at once (with {.multiplex})
         | 
| 1376 | 
            +
                  # @return [Boolean] When `true`, save a detailed trace for this query.
         | 
| 1377 | 
            +
                  # @see Tracing::DetailedTrace DetailedTrace saves traces when this method returns true
         | 
| 1378 | 
            +
                  def detailed_trace?(query)
         | 
| 1379 | 
            +
                    raise "#{self} must implement `def.detailed_trace?(query)` to use DetailedTrace. Implement this method in your schema definition."
         | 
| 1380 | 
            +
                  end
         | 
| 1381 | 
            +
             | 
| 1371 1382 | 
             
                  def tracer(new_tracer, silence_deprecation_warning: false)
         | 
| 1372 1383 | 
             
                    if !silence_deprecation_warning
         | 
| 1373 1384 | 
             
                      warn("`Schema.tracer(#{new_tracer.inspect})` is deprecated; use module-based `trace_with` instead. See: https://graphql-ruby.org/queries/tracing.html")
         | 
| @@ -1385,14 +1396,22 @@ module GraphQL | |
| 1385 1396 | 
             
                    find_inherited_value(:tracers, EMPTY_ARRAY) + own_tracers
         | 
| 1386 1397 | 
             
                  end
         | 
| 1387 1398 |  | 
| 1388 | 
            -
                  # Mix `trace_mod` into this schema's `Trace` class so that its methods
         | 
| 1389 | 
            -
                  # | 
| 1399 | 
            +
                  # Mix `trace_mod` into this schema's `Trace` class so that its methods will be called at runtime.
         | 
| 1400 | 
            +
                  #
         | 
| 1401 | 
            +
                  # You can attach a module to run in only _some_ circumstances by using `mode:`. When a module is added with `mode:`,
         | 
| 1402 | 
            +
                  # it will only run for queries with a matching `context[:trace_mode]`.
         | 
| 1403 | 
            +
                  #
         | 
| 1404 | 
            +
                  # Any custom trace modes _also_ include the default `trace_with ...` modules (that is, those added _without_ any particular `mode: ...` configuration).
         | 
| 1405 | 
            +
                  #
         | 
| 1406 | 
            +
                  # @example Adding a trace in a special mode
         | 
| 1407 | 
            +
                  #   # only runs when `query.context[:trace_mode]` is `:special`
         | 
| 1408 | 
            +
                  #   trace_with SpecialTrace, mode: :special
         | 
| 1390 1409 | 
             
                  #
         | 
| 1391 1410 | 
             
                  # @param trace_mod [Module] A module that implements tracing methods
         | 
| 1392 1411 | 
             
                  # @param mode [Symbol] Trace module will only be used for this trade mode
         | 
| 1393 1412 | 
             
                  # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
         | 
| 1394 1413 | 
             
                  # @return [void]
         | 
| 1395 | 
            -
                  # @see GraphQL::Tracing::Trace for available tracing methods
         | 
| 1414 | 
            +
                  # @see GraphQL::Tracing::Trace Tracing::Trace for available tracing methods
         | 
| 1396 1415 | 
             
                  def trace_with(trace_mod, mode: :default, **options)
         | 
| 1397 1416 | 
             
                    if mode.is_a?(Array)
         | 
| 1398 1417 | 
             
                      mode.each { |m| trace_with(trace_mod, mode: m, **options) }
         | 
| @@ -1442,29 +1461,36 @@ module GraphQL | |
| 1442 1461 | 
             
                  #
         | 
| 1443 1462 | 
             
                  # If no `mode:` is given, then {default_trace_mode} will be used.
         | 
| 1444 1463 | 
             
                  #
         | 
| 1464 | 
            +
                  # If this schema is using {Tracing::DetailedTrace} and {.detailed_trace?} returns `true`, then
         | 
| 1465 | 
            +
                  # DetailedTrace's mode will override the passed-in `mode`.
         | 
| 1466 | 
            +
                  #
         | 
| 1445 1467 | 
             
                  # @param mode [Symbol] Trace modules for this trade mode will be included
         | 
| 1446 1468 | 
             
                  # @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
         | 
| 1447 1469 | 
             
                  # @return [Tracing::Trace]
         | 
| 1448 1470 | 
             
                  def new_trace(mode: nil, **options)
         | 
| 1449 | 
            -
                     | 
| 1450 | 
            -
             | 
| 1451 | 
            -
             | 
| 1452 | 
            -
             | 
| 1453 | 
            -
             | 
| 1454 | 
            -
             | 
| 1455 | 
            -
             | 
| 1456 | 
            -
             | 
| 1457 | 
            -
             | 
| 1458 | 
            -
                        own_trace_modes[:default_backtrace] ||= build_trace_mode(:default_backtrace)
         | 
| 1459 | 
            -
                        options_trace_mode = :default
         | 
| 1460 | 
            -
                        :default_backtrace
         | 
| 1471 | 
            +
                    should_sample = if detailed_trace
         | 
| 1472 | 
            +
                      if (query = options[:query])
         | 
| 1473 | 
            +
                        detailed_trace?(query)
         | 
| 1474 | 
            +
                      elsif (multiplex = options[:multiplex])
         | 
| 1475 | 
            +
                        if multiplex.queries.length == 1
         | 
| 1476 | 
            +
                          detailed_trace?(multiplex.queries.first)
         | 
| 1477 | 
            +
                        else
         | 
| 1478 | 
            +
                          detailed_trace?(multiplex)
         | 
| 1479 | 
            +
                        end
         | 
| 1461 1480 | 
             
                      end
         | 
| 1462 1481 | 
             
                    else
         | 
| 1463 | 
            -
                       | 
| 1482 | 
            +
                      false
         | 
| 1483 | 
            +
                    end
         | 
| 1484 | 
            +
             | 
| 1485 | 
            +
                    if should_sample
         | 
| 1486 | 
            +
                      mode = detailed_trace.trace_mode
         | 
| 1487 | 
            +
                    else
         | 
| 1488 | 
            +
                      target = options[:query] || options[:multiplex]
         | 
| 1489 | 
            +
                      mode ||= target && target.context[:trace_mode]
         | 
| 1464 1490 | 
             
                    end
         | 
| 1465 1491 |  | 
| 1466 | 
            -
                     | 
| 1467 | 
            -
                    base_trace_options = trace_options_for( | 
| 1492 | 
            +
                    trace_mode = mode || default_trace_mode
         | 
| 1493 | 
            +
                    base_trace_options = trace_options_for(trace_mode)
         | 
| 1468 1494 | 
             
                    trace_options = base_trace_options.merge(options)
         | 
| 1469 1495 | 
             
                    trace_class_for_mode = trace_class_for(trace_mode, build: true)
         | 
| 1470 1496 | 
             
                    trace_class_for_mode.new(**trace_options)
         | 
| @@ -27,6 +27,8 @@ module GraphQL | |
| 27 27 | 
             
                  # @param max_errors [Integer] Maximum number of errors before aborting validation. Any positive number will limit the number of errors. Defaults to nil for no limit.
         | 
| 28 28 | 
             
                  # @return [Array<Hash>]
         | 
| 29 29 | 
             
                  def validate(query, validate: true, timeout: nil, max_errors: nil)
         | 
| 30 | 
            +
                    errors = nil
         | 
| 31 | 
            +
                    query.current_trace.begin_validate(query, validate)
         | 
| 30 32 | 
             
                    query.current_trace.validate(validate: validate, query: query) do
         | 
| 31 33 | 
             
                      begin_t = Time.now
         | 
| 32 34 | 
             
                      errors = if validate == false
         | 
| @@ -58,10 +60,13 @@ module GraphQL | |
| 58 60 | 
             
                      }
         | 
| 59 61 | 
             
                    end
         | 
| 60 62 | 
             
                  rescue GraphQL::ExecutionError => e
         | 
| 63 | 
            +
                    errors = [e]
         | 
| 61 64 | 
             
                    {
         | 
| 62 65 | 
             
                      remaining_timeout: nil,
         | 
| 63 | 
            -
                      errors:  | 
| 66 | 
            +
                      errors: errors,
         | 
| 64 67 | 
             
                    }
         | 
| 68 | 
            +
                  ensure
         | 
| 69 | 
            +
                    query.current_trace.end_validate(query, validate, errors)
         | 
| 65 70 | 
             
                  end
         | 
| 66 71 |  | 
| 67 72 | 
             
                  # Invoked when static validation times out.
         |