graphql 1.13.8 → 2.0.1

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.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  3. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  4. data/lib/graphql/analysis/ast/visitor.rb +1 -1
  5. data/lib/graphql/analysis/ast.rb +0 -10
  6. data/lib/graphql/analysis.rb +0 -7
  7. data/lib/graphql/backtrace/table.rb +0 -18
  8. data/lib/graphql/backtrace/tracer.rb +1 -2
  9. data/lib/graphql/backtrace.rb +2 -8
  10. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  11. data/lib/graphql/dig.rb +1 -1
  12. data/lib/graphql/execution/errors.rb +1 -9
  13. data/lib/graphql/execution/interpreter/runtime.rb +17 -31
  14. data/lib/graphql/execution/interpreter.rb +0 -22
  15. data/lib/graphql/execution/lazy.rb +1 -1
  16. data/lib/graphql/execution/lookahead.rb +6 -13
  17. data/lib/graphql/execution/multiplex.rb +50 -107
  18. data/lib/graphql/execution.rb +11 -3
  19. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  20. data/lib/graphql/introspection/entry_points.rb +2 -15
  21. data/lib/graphql/language/document_from_schema_definition.rb +0 -17
  22. data/lib/graphql/pagination/connections.rb +2 -28
  23. data/lib/graphql/query/context.rb +97 -194
  24. data/lib/graphql/query/input_validation_result.rb +10 -1
  25. data/lib/graphql/query/validation_pipeline.rb +8 -37
  26. data/lib/graphql/query/variables.rb +22 -18
  27. data/lib/graphql/query.rb +5 -36
  28. data/lib/graphql/railtie.rb +0 -104
  29. data/lib/graphql/relay.rb +0 -15
  30. data/lib/graphql/schema/addition.rb +1 -8
  31. data/lib/graphql/schema/argument.rb +1 -25
  32. data/lib/graphql/schema/build_from_definition.rb +0 -1
  33. data/lib/graphql/schema/directive.rb +4 -21
  34. data/lib/graphql/schema/enum.rb +4 -23
  35. data/lib/graphql/schema/enum_value.rb +0 -22
  36. data/lib/graphql/schema/field.rb +75 -234
  37. data/lib/graphql/schema/input_object.rb +22 -69
  38. data/lib/graphql/schema/interface.rb +0 -25
  39. data/lib/graphql/schema/introspection_system.rb +3 -8
  40. data/lib/graphql/schema/late_bound_type.rb +2 -2
  41. data/lib/graphql/schema/list.rb +2 -7
  42. data/lib/graphql/schema/loader.rb +0 -1
  43. data/lib/graphql/schema/member/base_dsl_methods.rb +0 -5
  44. data/lib/graphql/schema/member/build_type.rb +4 -6
  45. data/lib/graphql/schema/member/has_arguments.rb +50 -24
  46. data/lib/graphql/schema/member/has_fields.rb +2 -2
  47. data/lib/graphql/schema/member/has_interfaces.rb +0 -2
  48. data/lib/graphql/schema/member/validates_input.rb +2 -2
  49. data/lib/graphql/schema/member.rb +0 -6
  50. data/lib/graphql/schema/mutation.rb +0 -9
  51. data/lib/graphql/schema/non_null.rb +1 -7
  52. data/lib/graphql/schema/object.rb +0 -40
  53. data/lib/graphql/schema/relay_classic_mutation.rb +49 -42
  54. data/lib/graphql/schema/resolver/has_payload_type.rb +1 -1
  55. data/lib/graphql/schema/resolver.rb +23 -45
  56. data/lib/graphql/schema/scalar.rb +4 -19
  57. data/lib/graphql/schema/subscription.rb +0 -7
  58. data/lib/graphql/schema/union.rb +0 -16
  59. data/lib/graphql/schema/warden.rb +2 -2
  60. data/lib/graphql/schema/wrapper.rb +0 -5
  61. data/lib/graphql/schema.rb +106 -944
  62. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  63. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  64. data/lib/graphql/static_validation/validator.rb +2 -24
  65. data/lib/graphql/static_validation.rb +0 -2
  66. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  67. data/lib/graphql/subscriptions/event.rb +1 -1
  68. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  69. data/lib/graphql/subscriptions.rb +14 -16
  70. data/lib/graphql/tracing/platform_tracing.rb +0 -23
  71. data/lib/graphql/tracing.rb +0 -1
  72. data/lib/graphql/types/relay/connection_behaviors.rb +2 -6
  73. data/lib/graphql/types/relay/default_relay.rb +0 -10
  74. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  75. data/lib/graphql/types/relay.rb +0 -2
  76. data/lib/graphql/version.rb +1 -1
  77. data/lib/graphql.rb +1 -65
  78. metadata +6 -132
  79. data/lib/graphql/analysis/analyze_query.rb +0 -98
  80. data/lib/graphql/analysis/field_usage.rb +0 -45
  81. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  82. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  83. data/lib/graphql/analysis/query_complexity.rb +0 -88
  84. data/lib/graphql/analysis/query_depth.rb +0 -43
  85. data/lib/graphql/analysis/reducer_state.rb +0 -48
  86. data/lib/graphql/argument.rb +0 -131
  87. data/lib/graphql/authorization.rb +0 -82
  88. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  89. data/lib/graphql/backwards_compatibility.rb +0 -61
  90. data/lib/graphql/base_type.rb +0 -232
  91. data/lib/graphql/boolean_type.rb +0 -2
  92. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  93. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  94. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  95. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  96. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  97. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  98. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  99. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  100. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  101. data/lib/graphql/compatibility.rb +0 -5
  102. data/lib/graphql/define/assign_argument.rb +0 -12
  103. data/lib/graphql/define/assign_connection.rb +0 -13
  104. data/lib/graphql/define/assign_enum_value.rb +0 -18
  105. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  106. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  107. data/lib/graphql/define/assign_object_field.rb +0 -42
  108. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  109. data/lib/graphql/define/instance_definable.rb +0 -240
  110. data/lib/graphql/define/no_definition_error.rb +0 -7
  111. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  112. data/lib/graphql/define/type_definer.rb +0 -31
  113. data/lib/graphql/define.rb +0 -31
  114. data/lib/graphql/deprecated_dsl.rb +0 -55
  115. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  116. data/lib/graphql/directive/include_directive.rb +0 -2
  117. data/lib/graphql/directive/skip_directive.rb +0 -2
  118. data/lib/graphql/directive.rb +0 -107
  119. data/lib/graphql/enum_type.rb +0 -133
  120. data/lib/graphql/execution/execute.rb +0 -333
  121. data/lib/graphql/execution/flatten.rb +0 -40
  122. data/lib/graphql/execution/typecast.rb +0 -50
  123. data/lib/graphql/field/resolve.rb +0 -59
  124. data/lib/graphql/field.rb +0 -226
  125. data/lib/graphql/float_type.rb +0 -2
  126. data/lib/graphql/function.rb +0 -128
  127. data/lib/graphql/id_type.rb +0 -2
  128. data/lib/graphql/input_object_type.rb +0 -138
  129. data/lib/graphql/int_type.rb +0 -2
  130. data/lib/graphql/interface_type.rb +0 -72
  131. data/lib/graphql/internal_representation/document.rb +0 -27
  132. data/lib/graphql/internal_representation/node.rb +0 -206
  133. data/lib/graphql/internal_representation/print.rb +0 -51
  134. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  135. data/lib/graphql/internal_representation/scope.rb +0 -88
  136. data/lib/graphql/internal_representation/visit.rb +0 -36
  137. data/lib/graphql/internal_representation.rb +0 -7
  138. data/lib/graphql/list_type.rb +0 -80
  139. data/lib/graphql/non_null_type.rb +0 -71
  140. data/lib/graphql/object_type.rb +0 -130
  141. data/lib/graphql/query/arguments.rb +0 -189
  142. data/lib/graphql/query/arguments_cache.rb +0 -24
  143. data/lib/graphql/query/executor.rb +0 -52
  144. data/lib/graphql/query/literal_input.rb +0 -136
  145. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  146. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  147. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  148. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  149. data/lib/graphql/query/serial_execution.rb +0 -40
  150. data/lib/graphql/relay/array_connection.rb +0 -83
  151. data/lib/graphql/relay/base_connection.rb +0 -189
  152. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  153. data/lib/graphql/relay/connection_resolve.rb +0 -43
  154. data/lib/graphql/relay/connection_type.rb +0 -41
  155. data/lib/graphql/relay/edge.rb +0 -27
  156. data/lib/graphql/relay/edge_type.rb +0 -19
  157. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  158. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  159. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  160. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  161. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  162. data/lib/graphql/relay/mutation/result.rb +0 -38
  163. data/lib/graphql/relay/mutation.rb +0 -106
  164. data/lib/graphql/relay/node.rb +0 -39
  165. data/lib/graphql/relay/page_info.rb +0 -7
  166. data/lib/graphql/relay/relation_connection.rb +0 -188
  167. data/lib/graphql/relay/type_extensions.rb +0 -32
  168. data/lib/graphql/scalar_type.rb +0 -91
  169. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  170. data/lib/graphql/schema/default_parse_error.rb +0 -10
  171. data/lib/graphql/schema/default_type_error.rb +0 -17
  172. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  173. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  174. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  175. data/lib/graphql/schema/middleware_chain.rb +0 -82
  176. data/lib/graphql/schema/possible_types.rb +0 -44
  177. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  178. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  179. data/lib/graphql/schema/traversal.rb +0 -228
  180. data/lib/graphql/schema/validation.rb +0 -313
  181. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  182. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  183. data/lib/graphql/string_type.rb +0 -2
  184. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  185. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  186. data/lib/graphql/types/relay/node_field.rb +0 -24
  187. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  188. data/lib/graphql/union_type.rb +0 -115
  189. data/lib/graphql/upgrader/member.rb +0 -937
  190. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -5,8 +5,6 @@ require "graphql/schema/field/scope_extension"
5
5
  module GraphQL
6
6
  class Schema
7
7
  class Field
8
- include GraphQL::Schema::Member::CachedGraphQLDefinition
9
- include GraphQL::Schema::Member::AcceptsDefinition
10
8
  include GraphQL::Schema::Member::HasArguments
11
9
  include GraphQL::Schema::Member::HasAstNode
12
10
  include GraphQL::Schema::Member::HasPath
@@ -31,7 +29,13 @@ module GraphQL
31
29
  attr_reader :method_str
32
30
 
33
31
  # @return [Symbol] The method on the type to look up
34
- attr_reader :resolver_method
32
+ def resolver_method
33
+ if @resolver_class
34
+ @resolver_class.resolver_method
35
+ else
36
+ @resolver_method
37
+ end
38
+ end
35
39
 
36
40
  # @return [Class] The thing this field was defined on (type, mutation, resolver)
37
41
  attr_accessor :owner
@@ -70,7 +74,10 @@ module GraphQL
70
74
  attr_reader :trace
71
75
 
72
76
  # @return [String, nil]
73
- attr_accessor :subscription_scope
77
+ def subscription_scope
78
+ @subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
79
+ end
80
+ attr_writer :subscription_scope
74
81
 
75
82
  # Create a field instance from a list of arguments, keyword arguments, and a block.
76
83
  #
@@ -84,21 +91,9 @@ module GraphQL
84
91
  # @return [GraphQL::Schema:Field] an instance of `self
85
92
  # @see {.initialize} for other options
86
93
  def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
87
- if kwargs[:field]
88
- if kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodeField.graphql_definition
89
- GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
90
- return GraphQL::Types::Relay::NodeField
91
- elsif kwargs[:field].is_a?(GraphQL::Field) && kwargs[:field] == GraphQL::Types::Relay::NodesField.graphql_definition
92
- GraphQL::Deprecation.warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
93
- return GraphQL::Types::Relay::NodesField
94
- end
95
- end
96
-
97
- if (parent_config = resolver || mutation || subscription)
98
- # Get the parent config, merge in local overrides
99
- kwargs = parent_config.field_options.merge(kwargs)
94
+ if (resolver_class = resolver || mutation || subscription)
100
95
  # Add a reference to that parent class
101
- kwargs[:resolver_class] = parent_config
96
+ kwargs[:resolver_class] = resolver_class
102
97
  end
103
98
 
104
99
  if name
@@ -106,9 +101,6 @@ module GraphQL
106
101
  end
107
102
 
108
103
  if !type.nil?
109
- if type.is_a?(GraphQL::Field)
110
- raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
111
- end
112
104
  if desc
113
105
  if kwargs[:description]
114
106
  raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
@@ -116,8 +108,8 @@ module GraphQL
116
108
 
117
109
  kwargs[:description] = desc
118
110
  kwargs[:type] = type
119
- elsif (kwargs[:field] || kwargs[:function] || resolver || mutation) && type.is_a?(String)
120
- # The return type should be copied from `field` or `function`, and the second positional argument is the description
111
+ elsif (resolver || mutation) && type.is_a?(String)
112
+ # The return type should be copied from the resolver, and the second positional argument is the description
121
113
  kwargs[:description] = type
122
114
  else
123
115
  kwargs[:type] = type
@@ -134,8 +126,8 @@ module GraphQL
134
126
  def connection?
135
127
  if @connection.nil?
136
128
  # Provide default based on type name
137
- return_type_name = if (contains_type = @field || @function)
138
- Member::BuildType.to_type_name(contains_type.type)
129
+ return_type_name = if @resolver_class && @resolver_class.type
130
+ Member::BuildType.to_type_name(@resolver_class.type)
139
131
  elsif @return_type_expr
140
132
  Member::BuildType.to_type_name(@return_type_expr)
141
133
  else
@@ -196,9 +188,6 @@ module GraphQL
196
188
  # @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
197
189
  # @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
198
190
  # @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
199
- # @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
200
- # @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
201
- # @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
202
191
  # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
203
192
  # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
204
193
  # @param camelize [Boolean] If true, the field name will be camelized when building the schema
@@ -212,31 +201,20 @@ module GraphQL
212
201
  # @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
213
202
  # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
214
203
  # @param validates [Array<Hash>] Configurations for validating this field
215
- # @param legacy_edge_class [Class, nil] (DEPRECATED) If present, pass this along to the legacy field definition
216
- def initialize(type: nil, name: nil, owner: nil, null: true, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, legacy_edge_class: nil, &definition_block)
204
+ def initialize(type: nil, name: nil, owner: nil, null: true, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, &definition_block)
217
205
  if name.nil?
218
206
  raise ArgumentError, "missing first `name` argument or keyword `name:`"
219
207
  end
220
- if !(field || function || resolver_class)
208
+ if !(resolver_class)
221
209
  if type.nil?
222
210
  raise ArgumentError, "missing second `type` argument or keyword `type:`"
223
211
  end
224
212
  end
225
- if (field || function || resolve) && extras.any?
226
- raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
227
- end
228
213
  @original_name = name
229
214
  name_s = -name.to_s
230
215
  @underscored_name = -Member::BuildType.underscore(name_s)
231
216
  @name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
232
217
  @description = description
233
- if field.is_a?(GraphQL::Schema::Field)
234
- raise ArgumentError, "Instead of passing a field as `field:`, use `add_field(field)` to add an already-defined field."
235
- else
236
- @field = field
237
- end
238
- @function = function
239
- @resolve = resolve
240
218
  self.deprecation_reason = deprecation_reason
241
219
 
242
220
  if method && hash_key && dig
@@ -269,7 +247,9 @@ module GraphQL
269
247
  @max_page_size = max_page_size == :not_given ? nil : max_page_size
270
248
  @introspection = introspection
271
249
  @extras = extras
272
- @broadcastable = broadcastable
250
+ if !broadcastable.nil?
251
+ @broadcastable = broadcastable
252
+ end
273
253
  @resolver_class = resolver_class
274
254
  @scope = scope
275
255
  @trace = trace
@@ -277,7 +257,6 @@ module GraphQL
277
257
  @relay_nodes_field = relay_nodes_field
278
258
  @ast_node = ast_node
279
259
  @method_conflict_warning = method_conflict_warning
280
- @legacy_edge_class = legacy_edge_class
281
260
 
282
261
  arguments.each do |name, arg|
283
262
  case arg
@@ -314,6 +293,10 @@ module GraphQL
314
293
  self.extensions(extensions)
315
294
  end
316
295
 
296
+ if resolver_class && resolver_class.extensions.any?
297
+ self.extensions(resolver_class.extensions)
298
+ end
299
+
317
300
  if directives.any?
318
301
  directives.each do |(dir_class, options)|
319
302
  self.directive(dir_class, **options)
@@ -338,7 +321,13 @@ module GraphQL
338
321
  # @return [Boolean, nil]
339
322
  # @see GraphQL::Subscriptions::BroadcastAnalyzer
340
323
  def broadcastable?
341
- @broadcastable
324
+ if defined?(@broadcastable)
325
+ @broadcastable
326
+ elsif @resolver_class
327
+ @resolver_class.broadcastable?
328
+ else
329
+ nil
330
+ end
342
331
  end
343
332
 
344
333
  # @param text [String]
@@ -346,6 +335,8 @@ module GraphQL
346
335
  def description(text = nil)
347
336
  if text
348
337
  @description = text
338
+ elsif @resolver_class
339
+ @description || @resolver_class.description
349
340
  else
350
341
  @description
351
342
  end
@@ -411,7 +402,12 @@ module GraphQL
411
402
  def extras(new_extras = nil)
412
403
  if new_extras.nil?
413
404
  # Read the value
414
- @extras
405
+ field_extras = @extras
406
+ if @resolver_class && @resolver_class.extras.any?
407
+ field_extras + @resolver_class.extras
408
+ else
409
+ field_extras
410
+ end
415
411
  else
416
412
  if @extras.frozen?
417
413
  @extras = @extras.dup
@@ -428,11 +424,14 @@ module GraphQL
428
424
  elsif connection?
429
425
  arguments = query.arguments_for(nodes.first, self)
430
426
  max_possible_page_size = nil
431
- if arguments[:first]
432
- max_possible_page_size = arguments[:first]
433
- end
434
- if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
435
- max_possible_page_size = arguments[:last]
427
+ if arguments.respond_to?(:[]) # It might have been an error
428
+ if arguments[:first]
429
+ max_possible_page_size = arguments[:first]
430
+ end
431
+
432
+ if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
433
+ max_possible_page_size = arguments[:last]
434
+ end
436
435
  end
437
436
 
438
437
  if max_possible_page_size.nil?
@@ -491,7 +490,11 @@ module GraphQL
491
490
  when Numeric
492
491
  @complexity = new_complexity
493
492
  when nil
494
- @complexity
493
+ if @resolver_class
494
+ @complexity || @resolver_class.complexity || 1
495
+ else
496
+ @complexity || 1
497
+ end
495
498
  else
496
499
  raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
497
500
  end
@@ -499,105 +502,31 @@ module GraphQL
499
502
 
500
503
  # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
501
504
  def has_max_page_size?
502
- @has_max_page_size
505
+ @has_max_page_size || (@resolver_class && @resolver_class.has_max_page_size?)
503
506
  end
504
507
 
505
508
  # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
506
- attr_reader :max_page_size
507
-
508
- prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
509
-
510
- # @return [GraphQL::Field]
511
- def to_graphql
512
- field_defn = if @field
513
- @field.dup
514
- elsif @function
515
- GraphQL::Function.build_field(@function)
516
- else
517
- GraphQL::Field.new
518
- end
519
-
520
- field_defn.name = @name
521
- if @return_type_expr
522
- field_defn.type = -> { type }
523
- end
524
-
525
- if @description
526
- field_defn.description = @description
527
- end
528
-
529
- if self.deprecation_reason
530
- field_defn.deprecation_reason = self.deprecation_reason
531
- end
532
-
533
- if @resolver_class
534
- if @resolver_class < GraphQL::Schema::Mutation
535
- field_defn.mutation = @resolver_class
536
- end
537
- field_defn.metadata[:resolver] = @resolver_class
538
- end
539
-
540
- if !@trace.nil?
541
- field_defn.trace = @trace
542
- end
543
-
544
- if @relay_node_field
545
- field_defn.relay_node_field = @relay_node_field
546
- end
547
-
548
- if @relay_nodes_field
549
- field_defn.relay_nodes_field = @relay_nodes_field
550
- end
551
-
552
- if @legacy_edge_class
553
- field_defn.edge_class = @legacy_edge_class
554
- end
555
-
556
- field_defn.resolve = self.method(:resolve_field)
557
- field_defn.connection = connection?
558
- field_defn.connection_max_page_size = max_page_size
559
- field_defn.introspection = @introspection
560
- field_defn.complexity = @complexity
561
- field_defn.subscription_scope = @subscription_scope
562
- field_defn.ast_node = ast_node
563
-
564
- all_argument_definitions.each do |defn|
565
- arg_graphql = defn.deprecated_to_graphql
566
- field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
567
- end
568
-
569
- # Support a passed-in proc, one way or another
570
- @resolve_proc = if @resolve
571
- @resolve
572
- elsif @function
573
- @function
574
- elsif @field
575
- @field.resolve_proc
576
- end
577
-
578
- # Ok, `self` isn't a class, but this is for consistency with the classes
579
- field_defn.metadata[:type_class] = self
580
- field_defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(field_defn)
581
- field_defn
509
+ def max_page_size
510
+ @max_page_size || (@resolver_class && @resolver_class.max_page_size)
582
511
  end
583
512
 
584
513
  class MissingReturnTypeError < GraphQL::Error; end
585
514
  attr_writer :type
586
515
 
587
516
  def type
588
- @type ||= if @function
589
- Member::BuildType.parse_type(@function.type, null: false)
590
- elsif @field
591
- Member::BuildType.parse_type(@field.type, null: false)
592
- elsif @return_type_expr.nil?
593
- # Not enough info to determine type
594
- message = "Can't determine the return type for #{self.path}"
595
- if @resolver_class
596
- message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
597
- end
598
- raise MissingReturnTypeError, message
517
+ if @resolver_class && (t = @resolver_class.type)
518
+ t
599
519
  else
600
- Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
520
+ @type ||= if @return_type_expr.nil?
521
+ # Not enough info to determine type
522
+ message = "Can't determine the return type for #{self.path}"
523
+ if @resolver_class
524
+ message += " (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
525
+ end
526
+ raise MissingReturnTypeError, message
527
+ else
528
+ Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
529
+ end
601
530
  end
602
531
  rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
603
532
  # Let this propagate up
@@ -663,37 +592,6 @@ module GraphQL
663
592
  end
664
593
  end
665
594
 
666
- # Implement {GraphQL::Field}'s resolve API.
667
- #
668
- # Eventually, we might hook up field instances to execution in another way. TBD.
669
- # @see #resolve for how the interpreter hooks up to it
670
- def resolve_field(obj, args, ctx)
671
- ctx.schema.after_lazy(obj) do |after_obj|
672
- # First, apply auth ...
673
- query_ctx = ctx.query.context
674
- # Some legacy fields can have `nil` here, not exactly sure why.
675
- # @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
676
- inner_obj = after_obj && after_obj.object
677
- ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
678
- if authorized?(inner_obj, ruby_args, query_ctx)
679
- # Then if it passed, resolve the field
680
- if @resolve_proc
681
- # Might be nil, still want to call the func in that case
682
- with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
683
- # Pass the GraphQL args here for compatibility:
684
- @resolve_proc.call(extended_obj, args, ctx)
685
- end
686
- else
687
- public_send_field(after_obj, ruby_args, query_ctx)
688
- end
689
- else
690
- err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
691
- query_ctx.schema.unauthorized_field(err)
692
- end
693
- end
694
- end
695
- end
696
-
697
595
  # This method is called by the interpreter for each field.
698
596
  # You can extend it in your base field classes.
699
597
  # @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
@@ -726,7 +624,7 @@ module GraphQL
726
624
  err
727
625
  end
728
626
 
729
- # @param ctx [GraphQL::Query::Context::FieldResolutionContext]
627
+ # @param ctx [GraphQL::Query::Context]
730
628
  def fetch_extra(extra_name, ctx)
731
629
  if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
732
630
  self.public_send(extra_name)
@@ -739,63 +637,6 @@ module GraphQL
739
637
 
740
638
  private
741
639
 
742
- NO_ARGS = {}.freeze
743
-
744
- # Convert a GraphQL arguments instance into a Ruby-style hash.
745
- #
746
- # @param obj [GraphQL::Schema::Object] The object where this field is being resolved
747
- # @param graphql_args [GraphQL::Query::Arguments]
748
- # @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
749
- # @return [Hash<Symbol => Any>]
750
- def to_ruby_args(obj, graphql_args, field_ctx)
751
- if graphql_args.any? || @extras.any?
752
- # Splat the GraphQL::Arguments to Ruby keyword arguments
753
- ruby_kwargs = graphql_args.to_kwargs
754
- maybe_lazies = []
755
- # Apply any `prepare` methods. Not great code organization, can this go somewhere better?
756
- arguments(field_ctx).each do |name, arg_defn|
757
- ruby_kwargs_key = arg_defn.keyword
758
-
759
- if ruby_kwargs.key?(ruby_kwargs_key)
760
- loads = arg_defn.loads
761
- value = ruby_kwargs[ruby_kwargs_key]
762
- loaded_value = if loads && !arg_defn.from_resolver?
763
- if arg_defn.type.list?
764
- loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
765
- field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
766
- else
767
- load_application_object(arg_defn, loads, value, field_ctx.query.context)
768
- end
769
- elsif arg_defn.type.list? && value.is_a?(Array)
770
- field_ctx.schema.after_any_lazies(value, &:itself)
771
- else
772
- value
773
- end
774
-
775
- maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
776
- prepared_value = if arg_defn.prepare
777
- arg_defn.prepare_value(obj, loaded_value)
778
- else
779
- loaded_value
780
- end
781
-
782
- ruby_kwargs[ruby_kwargs_key] = prepared_value
783
- end
784
- end
785
- end
786
-
787
- @extras.each do |extra_arg|
788
- ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
789
- end
790
-
791
- field_ctx.schema.after_any_lazies(maybe_lazies) do
792
- ruby_kwargs
793
- end
794
- else
795
- NO_ARGS
796
- end
797
- end
798
-
799
640
  def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
800
641
  with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
801
642
  begin
@@ -815,14 +656,14 @@ module GraphQL
815
656
  # - A method on the wrapped object;
816
657
  # - Or, raise not implemented.
817
658
  #
818
- if obj.respond_to?(@resolver_method)
819
- method_to_call = @resolver_method
659
+ if obj.respond_to?(resolver_method)
660
+ method_to_call = resolver_method
820
661
  method_receiver = obj
821
662
  # Call the method with kwargs, if there are any
822
663
  if ruby_kwargs.any?
823
- obj.public_send(@resolver_method, **ruby_kwargs)
664
+ obj.public_send(resolver_method, **ruby_kwargs)
824
665
  else
825
- obj.public_send(@resolver_method)
666
+ obj.public_send(resolver_method)
826
667
  end
827
668
  elsif obj.object.is_a?(Hash)
828
669
  inner_object = obj.object
@@ -845,7 +686,7 @@ module GraphQL
845
686
  raise <<-ERR
846
687
  Failed to implement #{@owner.graphql_name}.#{@name}, tried:
847
688
 
848
- - `#{obj.class}##{@resolver_method}`, which did not exist
689
+ - `#{obj.class}##{resolver_method}`, which did not exist
849
690
  - `#{obj.object.class}##{@method_sym}`, which did not exist
850
691
  - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
851
692
 
@@ -2,7 +2,6 @@
2
2
  module GraphQL
3
3
  class Schema
4
4
  class InputObject < GraphQL::Schema::Member
5
- extend GraphQL::Schema::Member::AcceptsDefinition
6
5
  extend Forwardable
7
6
  extend GraphQL::Schema::Member::HasArguments
8
7
  extend GraphQL::Schema::Member::HasArguments::ArgumentObjectLoader
@@ -13,49 +12,28 @@ module GraphQL
13
12
 
14
13
  # @return [GraphQL::Query::Context] The context for this query
15
14
  attr_reader :context
16
- # @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
15
+ # @return [GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
17
16
  attr_reader :arguments
18
17
 
19
18
  # Ruby-like hash behaviors, read-only
20
19
  def_delegators :@ruby_style_hash, :keys, :values, :each, :map, :any?, :empty?
21
20
 
22
- def initialize(arguments = nil, ruby_kwargs: nil, context:, defaults_used:)
21
+ def initialize(arguments, ruby_kwargs:, context:, defaults_used:)
23
22
  @context = context
24
- if ruby_kwargs
25
- @ruby_style_hash = ruby_kwargs
26
- @arguments = arguments
27
- else
28
- @arguments = self.class.arguments_class.new(arguments, context: context, defaults_used: defaults_used)
29
- # Symbolized, underscored hash:
30
- @ruby_style_hash = @arguments.to_kwargs
31
- end
23
+ @ruby_style_hash = ruby_kwargs
24
+ @arguments = arguments
32
25
  # Apply prepares, not great to have it duplicated here.
33
- maybe_lazies = []
34
26
  self.class.arguments(context).each_value do |arg_defn|
35
27
  ruby_kwargs_key = arg_defn.keyword
36
-
37
28
  if @ruby_style_hash.key?(ruby_kwargs_key)
38
- loads = arg_defn.loads
39
- # Resolvers do this loading themselves;
40
- # With the interpreter, it's done during `coerce_arguments`
41
- if loads && !arg_defn.from_resolver? && !context.interpreter?
42
- value = @ruby_style_hash[ruby_kwargs_key]
43
- loaded_value = arg_defn.load_and_authorize_value(self, value, context)
44
- maybe_lazies << context.schema.after_lazy(loaded_value) do |loaded_value|
45
- overwrite_argument(ruby_kwargs_key, loaded_value)
46
- end
47
- end
48
-
49
29
  # Weirdly, procs are applied during coercion, but not methods.
50
30
  # Probably because these methods require a `self`.
51
- if arg_defn.prepare.is_a?(Symbol) || context.nil? || !context.interpreter?
31
+ if arg_defn.prepare.is_a?(Symbol) || context.nil?
52
32
  prepared_value = arg_defn.prepare_value(self, @ruby_style_hash[ruby_kwargs_key])
53
33
  overwrite_argument(ruby_kwargs_key, prepared_value)
54
34
  end
55
35
  end
56
36
  end
57
-
58
- @maybe_lazies = maybe_lazies
59
37
  end
60
38
 
61
39
  def to_h
@@ -68,12 +46,10 @@ module GraphQL
68
46
 
69
47
  def prepare
70
48
  if @context
71
- @context.schema.after_any_lazies(@maybe_lazies) do
72
- object = @context[:current_object]
73
- # Pass this object's class with `as` so that messages are rendered correctly from inherited validators
74
- Schema::Validator.validate!(self.class.validators, object, @context, @ruby_style_hash, as: self.class)
75
- self
76
- end
49
+ object = @context[:current_object]
50
+ # Pass this object's class with `as` so that messages are rendered correctly from inherited validators
51
+ Schema::Validator.validate!(self.class.validators, object, @context, @ruby_style_hash, as: self.class)
52
+ self
77
53
  else
78
54
  self
79
55
  end
@@ -81,9 +57,8 @@ module GraphQL
81
57
 
82
58
  def self.authorized?(obj, value, ctx)
83
59
  # Authorize each argument (but this doesn't apply if `prepare` is implemented):
84
- if value.is_a?(InputObject)
60
+ if value.respond_to?(:key?)
85
61
  arguments(ctx).each do |_name, input_obj_arg|
86
- input_obj_arg = input_obj_arg.type_class
87
62
  if value.key?(input_obj_arg.keyword) &&
88
63
  !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
89
64
  return false
@@ -132,9 +107,6 @@ module GraphQL
132
107
  end
133
108
 
134
109
  class << self
135
- # @return [Class<GraphQL::Arguments>]
136
- attr_accessor :arguments_class
137
-
138
110
  def argument(*args, **kwargs, &block)
139
111
  argument_defn = super(*args, **kwargs, &block)
140
112
  # Add a method access
@@ -147,25 +119,6 @@ module GraphQL
147
119
  argument_defn
148
120
  end
149
121
 
150
- prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
151
-
152
- def to_graphql
153
- type_defn = GraphQL::InputObjectType.new
154
- type_defn.name = graphql_name
155
- type_defn.description = description
156
- type_defn.metadata[:type_class] = self
157
- type_defn.mutation = mutation
158
- type_defn.ast_node = ast_node
159
- all_argument_definitions.each do |arg|
160
- type_defn.arguments[arg.graphql_definition(silence_deprecation_warning: true).name] = arg.graphql_definition(silence_deprecation_warning: true) # rubocop:disable Development/ContextIsPassedCop -- legacy-related
161
- end
162
- # Make a reference to a classic-style Arguments class
163
- self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
164
- # But use this InputObject class at runtime
165
- type_defn.arguments_class = self
166
- type_defn
167
- end
168
-
169
122
  def kind
170
123
  GraphQL::TypeKinds::INPUT_OBJECT
171
124
  end
@@ -174,19 +127,15 @@ module GraphQL
174
127
  INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
175
128
 
176
129
  def validate_non_null_input(input, ctx)
177
- result = GraphQL::Query::InputValidationResult.new
178
-
179
130
  warden = ctx.warden
180
131
 
181
132
  if input.is_a?(Array)
182
- result.add_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
183
- return result
133
+ return GraphQL::Query::InputValidationResult.from_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
184
134
  end
185
135
 
186
136
  if !(input.respond_to?(:to_h) || input.respond_to?(:to_unsafe_h))
187
137
  # We're not sure it'll act like a hash, so reject it:
188
- result.add_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
189
- return result
138
+ return GraphQL::Query::InputValidationResult.from_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
190
139
  end
191
140
 
192
141
  # Inject missing required arguments
@@ -198,18 +147,22 @@ module GraphQL
198
147
  m
199
148
  end
200
149
 
201
-
150
+ result = nil
202
151
  [input, missing_required_inputs].each do |args_to_validate|
203
152
  args_to_validate.each do |argument_name, value|
204
153
  argument = warden.get_argument(self, argument_name)
205
154
  # Items in the input that are unexpected
206
- unless argument
155
+ if argument.nil?
156
+ result ||= Query::InputValidationResult.new
207
157
  result.add_problem("Field is not defined on #{self.graphql_name}", [argument_name])
208
- next
158
+ else
159
+ # Items in the input that are expected, but have invalid values
160
+ argument_result = argument.type.validate_input(value, ctx)
161
+ result ||= Query::InputValidationResult.new
162
+ if !argument_result.valid?
163
+ result.merge_result!(argument_name, argument_result)
164
+ end
209
165
  end
210
- # Items in the input that are expected, but have invalid values
211
- argument_result = argument.type.validate_input(value, ctx)
212
- result.merge_result!(argument_name, argument_result) unless argument_result.valid?
213
166
  end
214
167
  end
215
168