graphql 2.0.12 → 2.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d299fcfe61f486f9370dac7dfcd66df417ca4697932d7861822fb12c61a5889
4
- data.tar.gz: 45e03854d6248c63f80d3b80e141a28970303516ab5f78375d9d3362b9e04ba5
3
+ metadata.gz: b8f389d3b7c8052a74ccd4bd9e8412a1fa9d93415e6caeec883b8f179a167395
4
+ data.tar.gz: f2e6ab7ba5c1e76b0c44557855ab3af55fb2b718b8de1ff6483917de603734b3
5
5
  SHA512:
6
- metadata.gz: d756a4c5213a8e17910233b0e472a037b6dad007676f5399f6192b93df53e78611915bd066ac619b59d7d44a0f35efbd7bb329cb4189246bce0c077f584b049b
7
- data.tar.gz: 277f7623f5bcc351bed49b3e95156166e16a92c3041a905f1e88399b15839eff8a0c733c16f4ae33c82213a4a47c3184d5c763e43ac2ca01a613caa419000513
6
+ metadata.gz: 10a24271a65c65a402d3243d2e43b3b257f74eb7bbc0ec13c254304bdce3122c444a41fbccf943bd3d626d301aec4b973485f742b831e8658ea252a0c95cfcfa
7
+ data.tar.gz: 9762008c699f2a53b14913e057dc31ec6c97b4203b1dd28a7a2a4fc18153d5bc200d0a95e3d2a04da80d0486131f5b1ce8d597e1ad6a7085b0766e35e0982959
@@ -401,8 +401,7 @@ module GraphQL
401
401
  end
402
402
  return_type = field_defn.type
403
403
 
404
- next_path = path.dup
405
- next_path << result_name
404
+ next_path = path + [result_name]
406
405
  next_path.freeze
407
406
 
408
407
  # This seems janky, but we need to know
@@ -768,8 +767,7 @@ module GraphQL
768
767
  set_result(selection_result, result_name, response_list)
769
768
  result_was_set = true
770
769
  end
771
- next_path = path.dup
772
- next_path << idx
770
+ next_path = path + [idx]
773
771
  this_idx = idx
774
772
  next_path.freeze
775
773
  idx += 1
@@ -4,11 +4,11 @@ module GraphQL
4
4
  class VariableValidationError < GraphQL::ExecutionError
5
5
  attr_accessor :value, :validation_result
6
6
 
7
- def initialize(variable_ast, type, value, validation_result)
7
+ def initialize(variable_ast, type, value, validation_result, msg: nil)
8
8
  @value = value
9
9
  @validation_result = validation_result
10
10
 
11
- msg = "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
11
+ msg ||= "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
12
12
 
13
13
  if problem_fields.any?
14
14
  msg += " for #{problem_fields.join(", ")}"
@@ -17,6 +17,10 @@ module GraphQL
17
17
  @provided_variables = deep_stringify(provided_variables)
18
18
  @errors = []
19
19
  @storage = ast_variables.each_with_object({}) do |ast_variable, memo|
20
+ if schema.validate_max_errors && schema.validate_max_errors <= @errors.count
21
+ add_max_errors_reached_message
22
+ break
23
+ end
20
24
  # Find the right value for this variable:
21
25
  # - First, use the value provided at runtime
22
26
  # - Then, fall back to the default value from the query string
@@ -29,8 +33,9 @@ module GraphQL
29
33
  default_value = ast_variable.default_value
30
34
  provided_value = @provided_variables[variable_name]
31
35
  value_was_provided = @provided_variables.key?(variable_name)
36
+ max_errors = schema.validate_max_errors - @errors.count if schema.validate_max_errors
32
37
  begin
33
- validation_result = variable_type.validate_input(provided_value, ctx)
38
+ validation_result = variable_type.validate_input(provided_value, ctx, max_errors: max_errors)
34
39
  if validation_result.valid?
35
40
  if value_was_provided
36
41
  # Add the variable if a value was provided
@@ -48,8 +53,7 @@ module GraphQL
48
53
  # like InputValidationResults generated by validate_non_null_input but unfortunately we don't
49
54
  # have this information available in the coerce_input call chain. Note this path is the path
50
55
  # that appears under errors.extensions.problems.path and NOT the result path under errors.path.
51
- validation_result = GraphQL::Query::InputValidationResult.new
52
- validation_result.add_problem(ex.message)
56
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
53
57
  end
54
58
 
55
59
  if !validation_result.valid?
@@ -76,6 +80,12 @@ module GraphQL
76
80
  else
77
81
  val
78
82
  end
83
+ end
84
+
85
+ def add_max_errors_reached_message
86
+ message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
87
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
88
+ errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
79
89
  end
80
90
  end
81
91
  end
@@ -15,7 +15,7 @@ module GraphQL
15
15
  puts "Validating graphql-pro v#{version}"
16
16
  puts " - Checking for graphql-pro credentials..."
17
17
 
18
- creds = `bundle config gems.graphql.pro`[/[a-z0-9]{11}:[a-z0-9]{11}/]
18
+ creds = `bundle config gems.graphql.pro --parseable`[/[a-z0-9]{11}:[a-z0-9]{11}/]
19
19
  if creds.nil?
20
20
  puts " #{ex} failed, please set with `bundle config gems.graphql.pro $MY_CREDENTIALS`"
21
21
  exit(1)
@@ -18,8 +18,14 @@ module GraphQL
18
18
  # @return [GraphQL::Schema::Field, Class] The field or input object this argument belongs to
19
19
  attr_reader :owner
20
20
 
21
- # @return [Symbol] A method to call to transform this value before sending it to field resolution method
22
- attr_reader :prepare
21
+ # @param new_prepare [Method, Proc]
22
+ # @return [Symbol] A method or proc to call to transform this value before sending it to field resolution method
23
+ def prepare(new_prepare = NO_DEFAULT)
24
+ if new_prepare != NO_DEFAULT
25
+ @prepare = new_prepare
26
+ end
27
+ @prepare
28
+ end
23
29
 
24
30
  # @return [Symbol] This argument's name in Ruby keyword arguments
25
31
  attr_reader :keyword
@@ -96,8 +102,14 @@ module GraphQL
96
102
  "#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
97
103
  end
98
104
 
105
+ # @param default_value [Object] The value to use when the client doesn't provide one
99
106
  # @return [Object] the value used when the client doesn't provide a value for this argument
100
- attr_reader :default_value
107
+ def default_value(new_default_value = NO_DEFAULT)
108
+ if new_default_value != NO_DEFAULT
109
+ @default_value = new_default_value
110
+ end
111
+ @default_value
112
+ end
101
113
 
102
114
  # @return [Boolean] True if this argument has a default value
103
115
  def default_value?
@@ -122,7 +122,7 @@ module GraphQL
122
122
  GraphQL::TypeKinds::ENUM
123
123
  end
124
124
 
125
- def validate_non_null_input(value_name, ctx)
125
+ def validate_non_null_input(value_name, ctx, max_errors: nil)
126
126
  allowed_values = ctx.warden.enum_values(self)
127
127
  matching_value = allowed_values.find { |v| v.graphql_name == value_name }
128
128
 
@@ -666,7 +666,18 @@ module GraphQL
666
666
  inner_object = obj.object
667
667
 
668
668
  if defined?(@hash_key)
669
- inner_object[@hash_key] || inner_object[@hash_key_str] || (@fallback_value != :not_given ? @fallback_value : nil)
669
+ hash_value = if inner_object.is_a?(Hash)
670
+ inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
671
+ elsif inner_object.respond_to?(:[])
672
+ inner_object[@hash_key]
673
+ else
674
+ nil
675
+ end
676
+ if hash_value == false
677
+ hash_value
678
+ else
679
+ hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
680
+ end
670
681
  elsif obj.respond_to?(resolver_method)
671
682
  method_to_call = resolver_method
672
683
  method_receiver = obj
@@ -679,16 +690,6 @@ module GraphQL
679
690
  elsif inner_object.is_a?(Hash)
680
691
  if @dig_keys
681
692
  inner_object.dig(*@dig_keys)
682
- elsif defined?(@hash_key)
683
- if inner_object.key?(@hash_key)
684
- inner_object[@hash_key]
685
- elsif inner_object.key?(@hash_key_str)
686
- inner_object[@hash_key_str]
687
- elsif @fallback_value != :not_given
688
- @fallback_value
689
- else
690
- nil
691
- end
692
693
  elsif inner_object.key?(@method_sym)
693
694
  inner_object[@method_sym]
694
695
  elsif inner_object.key?(@method_str)
@@ -126,7 +126,7 @@ module GraphQL
126
126
  # @api private
127
127
  INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
128
128
 
129
- def validate_non_null_input(input, ctx)
129
+ def validate_non_null_input(input, ctx, max_errors: nil)
130
130
  warden = ctx.warden
131
131
 
132
132
  if input.is_a?(Array)
@@ -45,16 +45,24 @@ module GraphQL
45
45
  end
46
46
  end
47
47
 
48
- def validate_non_null_input(value, ctx)
49
- result = nil
48
+ def validate_non_null_input(value, ctx, max_errors: nil)
49
+ result = GraphQL::Query::InputValidationResult.new
50
50
  ensure_array(value).each_with_index do |item, index|
51
51
  item_result = of_type.validate_input(item, ctx)
52
- if !item_result.valid?
53
- result ||= GraphQL::Query::InputValidationResult.new
52
+ unless item_result.valid?
53
+ if max_errors
54
+ if max_errors == 0
55
+ add_max_errros_reached_message(result)
56
+ break
57
+ end
58
+
59
+ max_errors -= 1
60
+ end
61
+
54
62
  result.merge_result!(index, item_result)
55
63
  end
56
64
  end
57
- result
65
+ result.valid? ? nil : result
58
66
  end
59
67
 
60
68
  private
@@ -67,6 +75,12 @@ module GraphQL
67
75
  [value]
68
76
  end
69
77
  end
78
+
79
+ def add_max_errros_reached_message(result)
80
+ message = "Too many errors processing list variable, max validation error limit reached. Execution aborted"
81
+ item_result = GraphQL::Query::InputValidationResult.from_problem(message)
82
+ result.merge_result!(nil, item_result)
83
+ end
70
84
  end
71
85
  end
72
86
  end
@@ -8,11 +8,11 @@ module GraphQL
8
8
  validate_input(val, ctx).valid?
9
9
  end
10
10
 
11
- def validate_input(val, ctx)
11
+ def validate_input(val, ctx, max_errors: nil)
12
12
  if val.nil?
13
13
  Query::InputValidationResult::VALID
14
14
  else
15
- validate_non_null_input(val, ctx) || Query::InputValidationResult::VALID
15
+ validate_non_null_input(val, ctx, max_errors: max_errors) || Query::InputValidationResult::VALID
16
16
  end
17
17
  end
18
18
 
@@ -31,13 +31,13 @@ module GraphQL
31
31
  "#<#{self.class.name} @of_type=#{@of_type.inspect}>"
32
32
  end
33
33
 
34
- def validate_input(value, ctx)
34
+ def validate_input(value, ctx, max_errors: nil)
35
35
  if value.nil?
36
36
  result = GraphQL::Query::InputValidationResult.new
37
37
  result.add_problem("Expected value to not be null")
38
38
  result
39
39
  else
40
- of_type.validate_input(value, ctx)
40
+ of_type.validate_input(value, ctx, max_errors: max_errors)
41
41
  end
42
42
  end
43
43
 
@@ -40,7 +40,7 @@ module GraphQL
40
40
  @default_scalar ||= false
41
41
  end
42
42
 
43
- def validate_non_null_input(value, ctx)
43
+ def validate_non_null_input(value, ctx, max_errors: nil)
44
44
  coerced_result = begin
45
45
  coerce_input(value, ctx)
46
46
  rescue GraphQL::CoercionError => err
@@ -30,10 +30,10 @@ module GraphQL
30
30
  }.tap { |h| h["path"] = path unless path.nil? }
31
31
  end
32
32
 
33
- private
34
-
35
33
  attr_reader :nodes
36
34
 
35
+ private
36
+
37
37
  def locations
38
38
  nodes.map do |node|
39
39
  h = {"line" => node.line, "column" => node.col}
@@ -9,11 +9,17 @@ module GraphQL
9
9
 
10
10
  def on_directive(node, parent)
11
11
  if !@directive_names.include?(node.name)
12
- add_error(GraphQL::StaticValidation::DirectivesAreDefinedError.new(
13
- "Directive @#{node.name} is not defined",
14
- nodes: node,
15
- directive: node.name
16
- ))
12
+ @directives_are_defined_errors_by_name ||= {}
13
+ error = @directives_are_defined_errors_by_name[node.name] ||= begin
14
+ err = GraphQL::StaticValidation::DirectivesAreDefinedError.new(
15
+ "Directive @#{node.name} is not defined",
16
+ nodes: [],
17
+ directive: node.name
18
+ )
19
+ add_error(err)
20
+ err
21
+ end
22
+ error.nodes << node
17
23
  else
18
24
  super
19
25
  end
@@ -34,12 +34,18 @@ module GraphQL
34
34
  used_directives = {}
35
35
  node.directives.each do |ast_directive|
36
36
  directive_name = ast_directive.name
37
- if used_directives[directive_name]
38
- add_error(GraphQL::StaticValidation::UniqueDirectivesPerLocationError.new(
39
- "The directive \"#{directive_name}\" can only be used once at this location.",
40
- nodes: [used_directives[directive_name], ast_directive],
41
- directive: directive_name,
42
- ))
37
+ if (first_node = used_directives[directive_name])
38
+ @directives_are_unique_errors_by_first_node ||= {}
39
+ err = @directives_are_unique_errors_by_first_node[first_node] ||= begin
40
+ error = GraphQL::StaticValidation::UniqueDirectivesPerLocationError.new(
41
+ "The directive \"#{directive_name}\" can only be used once at this location.",
42
+ nodes: [used_directives[directive_name]],
43
+ directive: directive_name,
44
+ )
45
+ add_error(error)
46
+ error
47
+ end
48
+ err.nodes << ast_directive
43
49
  elsif !((dir_defn = context.schema_directives[directive_name]) && dir_defn.repeatable?)
44
50
  used_directives[directive_name] = ast_directive
45
51
  end
@@ -62,11 +62,8 @@ module GraphQL
62
62
  # @return [void]
63
63
  def trigger(event_name, args, object, scope: nil, context: {})
64
64
  # Make something as context-like as possible, even though there isn't a current query:
65
- context = @schema.context_class.new(
66
- query: GraphQL::Query.new(@schema, "", validate: false),
67
- object: nil,
68
- values: context
69
- )
65
+ dummy_query = GraphQL::Query.new(@schema, "", validate: false, context: context)
66
+ context = dummy_query.context
70
67
  event_name = event_name.to_s
71
68
 
72
69
  # Try with the verbatim input first:
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.0.12"
3
+ VERSION = "2.0.13"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.12
4
+ version: 2.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-19 00:00:00.000000000 Z
11
+ date: 2022-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips