graphql 1.11.3 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +8 -0
  3. data/lib/generators/graphql/install_generator.rb +5 -5
  4. data/lib/generators/graphql/object_generator.rb +2 -0
  5. data/lib/generators/graphql/relay_generator.rb +63 -0
  6. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  7. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  8. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  9. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  10. data/lib/generators/graphql/templates/base_field.erb +2 -0
  11. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  12. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  13. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  14. data/lib/generators/graphql/templates/base_object.erb +2 -0
  15. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  16. data/lib/generators/graphql/templates/base_union.erb +2 -0
  17. data/lib/generators/graphql/templates/enum.erb +2 -0
  18. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  19. data/lib/generators/graphql/templates/interface.erb +2 -0
  20. data/lib/generators/graphql/templates/loader.erb +2 -0
  21. data/lib/generators/graphql/templates/mutation.erb +2 -0
  22. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  23. data/lib/generators/graphql/templates/node_type.erb +9 -0
  24. data/lib/generators/graphql/templates/object.erb +3 -1
  25. data/lib/generators/graphql/templates/query_type.erb +3 -3
  26. data/lib/generators/graphql/templates/scalar.erb +2 -0
  27. data/lib/generators/graphql/templates/schema.erb +10 -35
  28. data/lib/generators/graphql/templates/union.erb +3 -1
  29. data/lib/graphql.rb +55 -4
  30. data/lib/graphql/analysis/analyze_query.rb +7 -0
  31. data/lib/graphql/analysis/ast.rb +11 -2
  32. data/lib/graphql/analysis/ast/visitor.rb +9 -1
  33. data/lib/graphql/argument.rb +3 -3
  34. data/lib/graphql/backtrace.rb +28 -19
  35. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  36. data/lib/graphql/backtrace/table.rb +22 -2
  37. data/lib/graphql/backtrace/tracer.rb +40 -8
  38. data/lib/graphql/backwards_compatibility.rb +1 -0
  39. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  40. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  41. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  42. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  43. data/lib/graphql/dataloader.rb +197 -0
  44. data/lib/graphql/dataloader/null_dataloader.rb +21 -0
  45. data/lib/graphql/dataloader/request.rb +24 -0
  46. data/lib/graphql/dataloader/request_all.rb +22 -0
  47. data/lib/graphql/dataloader/source.rb +93 -0
  48. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  49. data/lib/graphql/define/instance_definable.rb +32 -2
  50. data/lib/graphql/define/type_definer.rb +5 -5
  51. data/lib/graphql/deprecated_dsl.rb +5 -0
  52. data/lib/graphql/enum_type.rb +2 -0
  53. data/lib/graphql/execution/errors.rb +4 -0
  54. data/lib/graphql/execution/execute.rb +7 -0
  55. data/lib/graphql/execution/interpreter.rb +20 -6
  56. data/lib/graphql/execution/interpreter/arguments.rb +57 -5
  57. data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
  58. data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
  59. data/lib/graphql/execution/interpreter/runtime.rb +251 -138
  60. data/lib/graphql/execution/multiplex.rb +20 -6
  61. data/lib/graphql/function.rb +4 -0
  62. data/lib/graphql/input_object_type.rb +2 -0
  63. data/lib/graphql/integer_decoding_error.rb +17 -0
  64. data/lib/graphql/interface_type.rb +3 -1
  65. data/lib/graphql/introspection.rb +96 -0
  66. data/lib/graphql/introspection/field_type.rb +7 -3
  67. data/lib/graphql/introspection/input_value_type.rb +6 -0
  68. data/lib/graphql/introspection/introspection_query.rb +6 -92
  69. data/lib/graphql/introspection/type_type.rb +7 -3
  70. data/lib/graphql/invalid_null_error.rb +1 -1
  71. data/lib/graphql/language/block_string.rb +24 -5
  72. data/lib/graphql/language/document_from_schema_definition.rb +50 -23
  73. data/lib/graphql/language/lexer.rb +7 -3
  74. data/lib/graphql/language/lexer.rl +7 -3
  75. data/lib/graphql/language/nodes.rb +1 -1
  76. data/lib/graphql/language/parser.rb +107 -103
  77. data/lib/graphql/language/parser.y +4 -0
  78. data/lib/graphql/language/sanitized_printer.rb +59 -26
  79. data/lib/graphql/name_validator.rb +6 -7
  80. data/lib/graphql/object_type.rb +2 -0
  81. data/lib/graphql/pagination/connection.rb +5 -1
  82. data/lib/graphql/pagination/connections.rb +15 -17
  83. data/lib/graphql/query.rb +8 -3
  84. data/lib/graphql/query/context.rb +38 -4
  85. data/lib/graphql/query/fingerprint.rb +2 -0
  86. data/lib/graphql/query/serial_execution.rb +1 -0
  87. data/lib/graphql/query/validation_pipeline.rb +4 -1
  88. data/lib/graphql/relay/array_connection.rb +2 -2
  89. data/lib/graphql/relay/base_connection.rb +7 -0
  90. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  91. data/lib/graphql/relay/connection_type.rb +1 -1
  92. data/lib/graphql/relay/mutation.rb +1 -0
  93. data/lib/graphql/relay/node.rb +3 -0
  94. data/lib/graphql/relay/range_add.rb +14 -5
  95. data/lib/graphql/relay/type_extensions.rb +2 -0
  96. data/lib/graphql/scalar_type.rb +2 -0
  97. data/lib/graphql/schema.rb +107 -38
  98. data/lib/graphql/schema/argument.rb +74 -5
  99. data/lib/graphql/schema/build_from_definition.rb +203 -86
  100. data/lib/graphql/schema/default_type_error.rb +2 -0
  101. data/lib/graphql/schema/directive.rb +76 -0
  102. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  103. data/lib/graphql/schema/directive/flagged.rb +57 -0
  104. data/lib/graphql/schema/enum.rb +3 -0
  105. data/lib/graphql/schema/enum_value.rb +12 -6
  106. data/lib/graphql/schema/field.rb +59 -24
  107. data/lib/graphql/schema/field/connection_extension.rb +11 -9
  108. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  109. data/lib/graphql/schema/input_object.rb +38 -25
  110. data/lib/graphql/schema/interface.rb +2 -1
  111. data/lib/graphql/schema/late_bound_type.rb +2 -2
  112. data/lib/graphql/schema/loader.rb +1 -0
  113. data/lib/graphql/schema/member.rb +4 -0
  114. data/lib/graphql/schema/member/base_dsl_methods.rb +1 -0
  115. data/lib/graphql/schema/member/build_type.rb +17 -7
  116. data/lib/graphql/schema/member/has_arguments.rb +70 -51
  117. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  118. data/lib/graphql/schema/member/has_directives.rb +98 -0
  119. data/lib/graphql/schema/member/has_fields.rb +2 -2
  120. data/lib/graphql/schema/member/has_validators.rb +31 -0
  121. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  122. data/lib/graphql/schema/object.rb +11 -0
  123. data/lib/graphql/schema/printer.rb +5 -4
  124. data/lib/graphql/schema/relay_classic_mutation.rb +4 -2
  125. data/lib/graphql/schema/resolver.rb +7 -0
  126. data/lib/graphql/schema/resolver/has_payload_type.rb +2 -0
  127. data/lib/graphql/schema/subscription.rb +20 -12
  128. data/lib/graphql/schema/timeout.rb +29 -15
  129. data/lib/graphql/schema/timeout_middleware.rb +2 -0
  130. data/lib/graphql/schema/unique_within_type.rb +1 -2
  131. data/lib/graphql/schema/validation.rb +10 -0
  132. data/lib/graphql/schema/validator.rb +163 -0
  133. data/lib/graphql/schema/validator/exclusion_validator.rb +31 -0
  134. data/lib/graphql/schema/validator/format_validator.rb +49 -0
  135. data/lib/graphql/schema/validator/inclusion_validator.rb +33 -0
  136. data/lib/graphql/schema/validator/length_validator.rb +57 -0
  137. data/lib/graphql/schema/validator/numericality_validator.rb +71 -0
  138. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  139. data/lib/graphql/schema/warden.rb +2 -3
  140. data/lib/graphql/static_validation.rb +1 -0
  141. data/lib/graphql/static_validation/all_rules.rb +1 -0
  142. data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
  143. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  144. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  145. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  146. data/lib/graphql/static_validation/validator.rb +31 -7
  147. data/lib/graphql/subscriptions.rb +23 -16
  148. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
  149. data/lib/graphql/tracing.rb +2 -2
  150. data/lib/graphql/tracing/appoptics_tracing.rb +12 -2
  151. data/lib/graphql/tracing/platform_tracing.rb +4 -2
  152. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  153. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  154. data/lib/graphql/types/int.rb +9 -2
  155. data/lib/graphql/types/iso_8601_date_time.rb +2 -1
  156. data/lib/graphql/types/relay.rb +11 -3
  157. data/lib/graphql/types/relay/base_connection.rb +2 -90
  158. data/lib/graphql/types/relay/base_edge.rb +2 -34
  159. data/lib/graphql/types/relay/connection_behaviors.rb +123 -0
  160. data/lib/graphql/types/relay/default_relay.rb +27 -0
  161. data/lib/graphql/types/relay/edge_behaviors.rb +42 -0
  162. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  163. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  164. data/lib/graphql/types/relay/node.rb +2 -4
  165. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  166. data/lib/graphql/types/relay/node_field.rb +1 -19
  167. data/lib/graphql/types/relay/nodes_field.rb +1 -19
  168. data/lib/graphql/types/relay/page_info.rb +2 -14
  169. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  170. data/lib/graphql/types/string.rb +7 -1
  171. data/lib/graphql/unauthorized_error.rb +1 -1
  172. data/lib/graphql/union_type.rb +2 -0
  173. data/lib/graphql/upgrader/member.rb +1 -0
  174. data/lib/graphql/upgrader/schema.rb +1 -0
  175. data/lib/graphql/version.rb +1 -1
  176. data/readme.md +1 -1
  177. metadata +38 -9
  178. data/lib/graphql/types/relay/base_field.rb +0 -22
  179. data/lib/graphql/types/relay/base_interface.rb +0 -29
  180. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -466,6 +466,10 @@ def self.parse(query_string, filename: nil, tracer: GraphQL::Tracing::NullTracer
466
466
  self.new(query_string, filename: filename, tracer: tracer).parse_document
467
467
  end
468
468
 
469
+ def self.parse_file(filename, tracer: GraphQL::Tracing::NullTracer)
470
+ self.parse(File.read(filename), filename: filename, tracer: tracer)
471
+ end
472
+
469
473
  private
470
474
 
471
475
  def next_token
@@ -19,11 +19,12 @@ module GraphQL
19
19
 
20
20
  REDACTED = "\"<REDACTED>\""
21
21
 
22
- def initialize(query)
22
+ def initialize(query, inline_variables: true)
23
23
  @query = query
24
24
  @current_type = nil
25
25
  @current_field = nil
26
26
  @current_input_type = nil
27
+ @inline_variables = inline_variables
27
28
  end
28
29
 
29
30
  # @return [String, nil] A scrubbed query string, if the query was valid.
@@ -36,15 +37,14 @@ module GraphQL
36
37
  end
37
38
 
38
39
  def print_node(node, indent: "")
39
- if node.is_a?(String)
40
- type = @current_input_type.unwrap
41
- # Replace any strings that aren't IDs or Enum values with REDACTED
42
- if type.kind.enum? || type.graphql_name == "ID"
43
- super
40
+ case node
41
+ when FalseClass, Float, Integer, String, TrueClass
42
+ if @current_argument && redact_argument_value?(@current_argument, node)
43
+ redacted_argument_value(@current_argument)
44
44
  else
45
- REDACTED
45
+ super
46
46
  end
47
- elsif node.is_a?(Array)
47
+ when Array
48
48
  old_input_type = @current_input_type
49
49
  if @current_input_type && @current_input_type.list?
50
50
  @current_input_type = @current_input_type.of_type
@@ -59,28 +59,57 @@ module GraphQL
59
59
  end
60
60
  end
61
61
 
62
+ # Indicates whether or not to redact non-null values for the given argument. Defaults to redacting all strings
63
+ # arguments but this can be customized by subclasses.
64
+ def redact_argument_value?(argument, value)
65
+ # Default to redacting any strings or custom scalars encoded as strings
66
+ type = argument.type.unwrap
67
+ value.is_a?(String) && type.kind.scalar? && (type.graphql_name == "String" || !type.default_scalar?)
68
+ end
69
+
70
+ # Returns the value to use for redacted versions of the given argument. Defaults to the
71
+ # string "<REDACTED>".
72
+ def redacted_argument_value(argument)
73
+ REDACTED
74
+ end
75
+
62
76
  def print_argument(argument)
77
+ # We won't have type information if we're recursing into a custom scalar
78
+ return super if @current_input_type && @current_input_type.kind.scalar?
79
+
63
80
  arg_owner = @current_input_type || @current_directive || @current_field
64
- arg_def = arg_owner.arguments[argument.name]
81
+ old_current_argument = @current_argument
82
+ @current_argument = arg_owner.arguments[argument.name]
65
83
 
66
84
  old_input_type = @current_input_type
67
- @current_input_type = arg_def.type.non_null? ? arg_def.type.of_type : arg_def.type
68
- res = super
85
+ @current_input_type = @current_argument.type.non_null? ? @current_argument.type.of_type : @current_argument.type
86
+
87
+ argument_value = if coerce_argument_value_to_list?(@current_input_type, argument.value)
88
+ [argument.value]
89
+ else
90
+ argument.value
91
+ end
92
+ res = "#{argument.name}: #{print_node(argument_value)}".dup
93
+
69
94
  @current_input_type = old_input_type
95
+ @current_argument = old_current_argument
70
96
  res
71
97
  end
72
98
 
73
- def print_list_type(list_type)
74
- old_input_type = @current_input_type
75
- @current_input_type = old_input_type.of_type
76
- res = super
77
- @current_input_type = old_input_type
78
- res
99
+ def coerce_argument_value_to_list?(type, value)
100
+ type.list? &&
101
+ !value.is_a?(Array) &&
102
+ !value.nil? &&
103
+ !value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
79
104
  end
80
105
 
81
106
  def print_variable_identifier(variable_id)
82
- variable_value = query.variables[variable_id.name]
83
- print_node(value_to_ast(variable_value, @current_input_type))
107
+ if @inline_variables
108
+ variable_value = query.variables[variable_id.name]
109
+ print_node(value_to_ast(variable_value, @current_input_type))
110
+ else
111
+ super
112
+ end
84
113
  end
85
114
 
86
115
  def print_field(field, indent: "")
@@ -132,10 +161,14 @@ module GraphQL
132
161
  old_type = @current_type
133
162
  @current_type = query.schema.public_send(operation_definition.operation_type)
134
163
 
135
- out = "#{indent}#{operation_definition.operation_type}".dup
136
- out << " #{operation_definition.name}" if operation_definition.name
137
- out << print_directives(operation_definition.directives)
138
- out << print_selections(operation_definition.selections, indent: indent)
164
+ if @inline_variables
165
+ out = "#{indent}#{operation_definition.operation_type}".dup
166
+ out << " #{operation_definition.name}" if operation_definition.name
167
+ out << print_directives(operation_definition.directives)
168
+ out << print_selections(operation_definition.selections, indent: indent)
169
+ else
170
+ out = super
171
+ end
139
172
 
140
173
  @current_type = old_type
141
174
  out
@@ -171,10 +204,10 @@ module GraphQL
171
204
  arguments: arguments
172
205
  )
173
206
  when "LIST"
174
- if value.respond_to?(:each)
175
- value.each { |v| value_to_ast(v, type.of_type) }
207
+ if value.is_a?(Array)
208
+ value.map { |v| value_to_ast(v, type.of_type) }
176
209
  else
177
- [value].each { |v| value_to_ast(v, type.of_type) }
210
+ [value].map { |v| value_to_ast(v, type.of_type) }
178
211
  end
179
212
  when "ENUM"
180
213
  GraphQL::Language::Nodes::Enum.new(name: value)
@@ -1,16 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
3
  class NameValidator
4
- VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
5
-
6
- def self.validate!(name)
7
- raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless valid?(name)
4
+ if !String.method_defined?(:match?)
5
+ using GraphQL::StringMatchBackport
8
6
  end
9
7
 
10
- private
8
+ VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
11
9
 
12
- def self.valid?(name)
13
- name =~ VALID_NAME_REGEX
10
+ def self.validate!(name)
11
+ name = name.is_a?(String) ? name : name.to_s
12
+ raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless name.match?(VALID_NAME_REGEX)
14
13
  end
15
14
  end
16
15
  end
@@ -2,6 +2,8 @@
2
2
  module GraphQL
3
3
  # @api deprecated
4
4
  class ObjectType < GraphQL::BaseType
5
+ extend Define::InstanceDefinable::DeprecatedDefine
6
+
5
7
  accepts_definitions :interfaces, :fields, :mutation, :relay_node_type, field: GraphQL::Define::AssignObjectField
6
8
  accepts_definitions implements: ->(type, *interfaces, inherit: false) { type.implements(interfaces, inherit: inherit) }
7
9
 
@@ -53,10 +53,11 @@ module GraphQL
53
53
  # @param last [Integer, nil] Limit parameter from the client, if provided
54
54
  # @param before [String, nil] A cursor for pagination, if the client provided one.
55
55
  # @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given.
56
- def initialize(items, parent: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil, edge_class: nil)
56
+ def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: :not_given, last: nil, before: nil, edge_class: nil)
57
57
  @items = items
58
58
  @parent = parent
59
59
  @context = context
60
+ @field = field
60
61
  @first_value = first
61
62
  @after_value = after
62
63
  @last_value = last
@@ -118,6 +119,9 @@ module GraphQL
118
119
  # @return [Class] A wrapper class for edges of this connection
119
120
  attr_accessor :edge_class
120
121
 
122
+ # @return [GraphQL::Schema::Field] The field this connection was returned by
123
+ attr_accessor :field
124
+
121
125
  # @return [Array<Object>] A slice of {items}, constrained by {@first_value}/{@after_value}/{@last_value}/{@before_value}
122
126
  def nodes
123
127
  raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`"
@@ -6,20 +6,13 @@ module GraphQL
6
6
  #
7
7
  # Attach as a plugin.
8
8
  #
9
- # @example Using new default connections
10
- # class MySchema < GraphQL::Schema
11
- # use GraphQL::Pagination::Connections
12
- # end
13
- #
14
9
  # @example Adding a custom wrapper
15
10
  # class MySchema < GraphQL::Schema
16
- # use GraphQL::Pagination::Connections
17
11
  # connections.add(MyApp::SearchResults, MyApp::SearchResultsConnection)
18
12
  # end
19
13
  #
20
14
  # @example Removing default connection support for arrays (they can still be manually wrapped)
21
15
  # class MySchema < GraphQL::Schema
22
- # use GraphQL::Pagination::Connections
23
16
  # connections.delete(Array)
24
17
  # end
25
18
  #
@@ -29,14 +22,10 @@ module GraphQL
29
22
  end
30
23
 
31
24
  def self.use(schema_defn)
32
- if schema_defn.is_a?(Class)
33
- schema_defn.connections = self.new(schema: schema_defn)
34
- else
35
- # Unwrap a `.define` object
36
- schema_defn = schema_defn.target
37
- schema_defn.connections = self.new(schema: schema_defn)
38
- schema_defn.class.connections = schema_defn.connections
25
+ if schema_defn.plugins.any? { |(plugin, args)| plugin == self }
26
+ warn("#{self} is now the default, remove `use #{self}` from #{caller(2,1).first}")
39
27
  end
28
+ schema_defn.connections = self.new(schema: schema_defn)
40
29
  end
41
30
 
42
31
  def initialize(schema:)
@@ -63,9 +52,7 @@ module GraphQL
63
52
  all_wrappers
64
53
  end
65
54
 
66
- # Used by the runtime to wrap values in connection wrappers.
67
- # @api Private
68
- def wrap(field, parent, items, arguments, context, wrappers: all_wrappers)
55
+ def wrapper_for(items, wrappers: all_wrappers)
69
56
  impl = nil
70
57
 
71
58
  items.class.ancestors.each { |cls|
@@ -73,6 +60,16 @@ module GraphQL
73
60
  break if impl
74
61
  }
75
62
 
63
+ impl
64
+ end
65
+
66
+ # Used by the runtime to wrap values in connection wrappers.
67
+ # @api Private
68
+ def wrap(field, parent, items, arguments, context)
69
+ return items if GraphQL::Execution::Interpreter::RawValue === items
70
+ wrappers = context ? context.namespace(:connections)[:all_wrappers] : all_wrappers
71
+ impl = wrapper_for(items, wrappers: wrappers)
72
+
76
73
  if impl.nil?
77
74
  raise ImplementationMissingError, "Couldn't find a connection wrapper for #{items.class} during #{field.path} (#{items.inspect})"
78
75
  end
@@ -81,6 +78,7 @@ module GraphQL
81
78
  items,
82
79
  context: context,
83
80
  parent: parent,
81
+ field: field,
84
82
  max_page_size: field.max_page_size || context.schema.default_max_page_size,
85
83
  first: arguments[:first],
86
84
  after: arguments[:after],
@@ -88,6 +88,7 @@ module GraphQL
88
88
  schema = schema.graphql_definition
89
89
  end
90
90
  @schema = schema
91
+ @interpreter = @schema.interpreter?
91
92
  @filter = schema.default_filter.merge(except: except, only: only)
92
93
  @context = schema.context_class.new(query: self, object: root_value, values: context)
93
94
  @warden = warden
@@ -148,7 +149,11 @@ module GraphQL
148
149
  @query_string ||= (document ? document.to_query_string : nil)
149
150
  end
150
151
 
151
- def_delegators :@schema, :interpreter?
152
+ def interpreter?
153
+ @interpreter
154
+ end
155
+
156
+ attr_accessor :multiplex
152
157
 
153
158
  def subscription_update?
154
159
  @subscription_topic && subscription?
@@ -259,9 +264,9 @@ module GraphQL
259
264
  # - Variables inlined to the query
260
265
  # - Strings replaced with `<REDACTED>`
261
266
  # @return [String, nil] Returns nil if the query is invalid.
262
- def sanitized_query_string
267
+ def sanitized_query_string(inline_variables: true)
263
268
  with_prepared_ast {
264
- GraphQL::Language::SanitizedPrinter.new(self).sanitized_query_string
269
+ GraphQL::Language::SanitizedPrinter.new(self, inline_variables: inline_variables).sanitized_query_string
265
270
  }
266
271
  end
267
272
 
@@ -34,7 +34,7 @@ module GraphQL
34
34
  # Remove this child from the result value
35
35
  # (used for null propagation and skip)
36
36
  # @api private
37
- def delete(child_ctx)
37
+ def delete_child(child_ctx)
38
38
  @value.delete(child_ctx.key)
39
39
  end
40
40
 
@@ -158,6 +158,10 @@ module GraphQL
158
158
  @scoped_context = {}
159
159
  end
160
160
 
161
+ def dataloader
162
+ @dataloader ||= query.multiplex.dataloader
163
+ end
164
+
161
165
  # @api private
162
166
  attr_writer :interpreter
163
167
 
@@ -167,8 +171,10 @@ module GraphQL
167
171
  # @api private
168
172
  attr_accessor :scoped_context
169
173
 
170
- def_delegators :@provided_values, :[]=
171
- def_delegators :to_h, :fetch, :dig
174
+ def []=(key, value)
175
+ @provided_values[key] = value
176
+ end
177
+
172
178
  def_delegators :@query, :trace, :interpreter?
173
179
 
174
180
  # @!method []=(key, value)
@@ -180,6 +186,34 @@ module GraphQL
180
186
  @provided_values[key]
181
187
  end
182
188
 
189
+ def delete(key)
190
+ if @scoped_context.key?(key)
191
+ @scoped_context.delete(key)
192
+ else
193
+ @provided_values.delete(key)
194
+ end
195
+ end
196
+
197
+ UNSPECIFIED_FETCH_DEFAULT = Object.new
198
+
199
+ def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
200
+ if @scoped_context.key?(key)
201
+ @scoped_context[key]
202
+ elsif @provided_values.key?(key)
203
+ @provided_values[key]
204
+ elsif default != UNSPECIFIED_FETCH_DEFAULT
205
+ default
206
+ elsif block_given?
207
+ yield(self, key)
208
+ else
209
+ raise KeyError.new(key: key)
210
+ end
211
+ end
212
+
213
+ def dig(key, *other_keys)
214
+ @scoped_context.key?(key) ? @scoped_context.dig(key, *other_keys) : @provided_values.dig(key, *other_keys)
215
+ end
216
+
183
217
  def to_h
184
218
  @provided_values.merge(@scoped_context)
185
219
  end
@@ -293,7 +327,7 @@ module GraphQL
293
327
  end
294
328
  when GraphQL::Execution::Execute::SKIP
295
329
  @parent.skipped = true
296
- @parent.delete(self)
330
+ @parent.delete_child(self)
297
331
  else
298
332
  @value = new_value
299
333
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest/sha2'
4
+
3
5
  module GraphQL
4
6
  class Query
5
7
  # @api private
@@ -16,6 +16,7 @@ module GraphQL
16
16
  # @param query_object [GraphQL::Query] the query object for this execution
17
17
  # @return [Hash] a spec-compliant GraphQL result, as a hash
18
18
  def execute(ast_operation, root_type, query_object)
19
+ warn "#{self.class} will be removed in GraphQL-Ruby 2.0, please upgrade to the Interpreter: https://graphql-ruby.org/queries/interpreter.html"
19
20
  operation_resolution.resolve(
20
21
  query_object.irep_selection,
21
22
  root_type,
@@ -72,7 +72,7 @@ module GraphQL
72
72
  elsif @operation_name_error
73
73
  @validation_errors << @operation_name_error
74
74
  else
75
- validation_result = @schema.static_validator.validate(@query, validate: @validate)
75
+ validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout)
76
76
  @validation_errors.concat(validation_result[:errors])
77
77
  @internal_representation = validation_result[:irep]
78
78
 
@@ -90,6 +90,9 @@ module GraphQL
90
90
  end
91
91
 
92
92
  @valid = @validation_errors.empty?
93
+ rescue SystemStackError => err
94
+ @valid = false
95
+ @schema.query_stack_error(@query, err)
93
96
  end
94
97
 
95
98
  # If there are max_* values, add them,
@@ -31,8 +31,6 @@ module GraphQL
31
31
  end
32
32
  end
33
33
 
34
- private
35
-
36
34
  def first
37
35
  @first ||= begin
38
36
  capped = limit_pagination_argument(arguments[:first], max_page_size)
@@ -47,6 +45,8 @@ module GraphQL
47
45
  @last ||= limit_pagination_argument(arguments[:last], max_page_size)
48
46
  end
49
47
 
48
+ private
49
+
50
50
  # apply first / last limit results
51
51
  def paged_nodes
52
52
  @paged_nodes ||= begin
@@ -59,6 +59,13 @@ module GraphQL
59
59
  # @param parent [Object] The object which this collection belongs to
60
60
  # @param context [GraphQL::Query::Context] The context from the field being resolved
61
61
  def initialize(nodes, arguments, field: nil, max_page_size: nil, parent: nil, context: nil)
62
+ warn "GraphQL::Relay::BaseConnection (used for #{self.class}) will be removed from GraphQL-Ruby 2.0, use GraphQL::Pagination::Connections instead: https://graphql-ruby.org/pagination/overview.html"
63
+
64
+ deprecated_caller = caller(0, 10).find { |c| !c.include?("lib/graphql") }
65
+ if deprecated_caller
66
+ warn " -> called from #{deprecated_caller}"
67
+ end
68
+
62
69
  @context = context
63
70
  @nodes = nodes
64
71
  @arguments = arguments