graphql 1.13.10 → 2.0.2

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  3. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  4. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  5. data/lib/graphql/analysis/ast/visitor.rb +1 -1
  6. data/lib/graphql/analysis/ast.rb +0 -10
  7. data/lib/graphql/analysis.rb +0 -7
  8. data/lib/graphql/backtrace/table.rb +0 -18
  9. data/lib/graphql/backtrace/tracer.rb +1 -2
  10. data/lib/graphql/backtrace.rb +2 -8
  11. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  12. data/lib/graphql/dig.rb +1 -1
  13. data/lib/graphql/execution/errors.rb +1 -9
  14. data/lib/graphql/execution/interpreter/runtime.rb +17 -31
  15. data/lib/graphql/execution/interpreter.rb +0 -22
  16. data/lib/graphql/execution/lazy.rb +1 -1
  17. data/lib/graphql/execution/lookahead.rb +6 -13
  18. data/lib/graphql/execution/multiplex.rb +50 -107
  19. data/lib/graphql/execution.rb +11 -3
  20. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  21. data/lib/graphql/introspection/entry_points.rb +2 -15
  22. data/lib/graphql/language/document_from_schema_definition.rb +0 -17
  23. data/lib/graphql/pagination/connections.rb +2 -28
  24. data/lib/graphql/query/context.rb +97 -194
  25. data/lib/graphql/query/input_validation_result.rb +10 -1
  26. data/lib/graphql/query/validation_pipeline.rb +8 -37
  27. data/lib/graphql/query/variables.rb +22 -18
  28. data/lib/graphql/query.rb +5 -36
  29. data/lib/graphql/railtie.rb +0 -104
  30. data/lib/graphql/relay.rb +0 -15
  31. data/lib/graphql/schema/addition.rb +1 -8
  32. data/lib/graphql/schema/argument.rb +5 -26
  33. data/lib/graphql/schema/build_from_definition.rb +0 -1
  34. data/lib/graphql/schema/directive.rb +0 -21
  35. data/lib/graphql/schema/enum.rb +4 -23
  36. data/lib/graphql/schema/enum_value.rb +0 -22
  37. data/lib/graphql/schema/field.rb +70 -230
  38. data/lib/graphql/schema/input_object.rb +21 -68
  39. data/lib/graphql/schema/interface.rb +0 -25
  40. data/lib/graphql/schema/introspection_system.rb +3 -8
  41. data/lib/graphql/schema/late_bound_type.rb +2 -2
  42. data/lib/graphql/schema/list.rb +2 -7
  43. data/lib/graphql/schema/loader.rb +0 -1
  44. data/lib/graphql/schema/member/base_dsl_methods.rb +0 -5
  45. data/lib/graphql/schema/member/build_type.rb +4 -6
  46. data/lib/graphql/schema/member/has_arguments.rb +50 -24
  47. data/lib/graphql/schema/member/has_fields.rb +2 -2
  48. data/lib/graphql/schema/member/has_interfaces.rb +1 -3
  49. data/lib/graphql/schema/member/validates_input.rb +2 -2
  50. data/lib/graphql/schema/member.rb +0 -6
  51. data/lib/graphql/schema/mutation.rb +0 -9
  52. data/lib/graphql/schema/non_null.rb +1 -7
  53. data/lib/graphql/schema/object.rb +7 -42
  54. data/lib/graphql/schema/relay_classic_mutation.rb +49 -42
  55. data/lib/graphql/schema/resolver/has_payload_type.rb +11 -1
  56. data/lib/graphql/schema/resolver.rb +23 -45
  57. data/lib/graphql/schema/scalar.rb +4 -19
  58. data/lib/graphql/schema/subscription.rb +0 -7
  59. data/lib/graphql/schema/union.rb +0 -16
  60. data/lib/graphql/schema/warden.rb +2 -2
  61. data/lib/graphql/schema/wrapper.rb +0 -5
  62. data/lib/graphql/schema.rb +106 -944
  63. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  64. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  65. data/lib/graphql/static_validation/validator.rb +2 -24
  66. data/lib/graphql/static_validation.rb +0 -2
  67. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  68. data/lib/graphql/subscriptions/event.rb +1 -1
  69. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  70. data/lib/graphql/subscriptions.rb +14 -16
  71. data/lib/graphql/tracing/platform_tracing.rb +0 -23
  72. data/lib/graphql/tracing.rb +0 -1
  73. data/lib/graphql/types/relay/connection_behaviors.rb +2 -6
  74. data/lib/graphql/types/relay/default_relay.rb +0 -10
  75. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  76. data/lib/graphql/types/relay.rb +0 -2
  77. data/lib/graphql/version.rb +1 -1
  78. data/lib/graphql.rb +1 -65
  79. metadata +2 -128
  80. data/lib/graphql/analysis/analyze_query.rb +0 -98
  81. data/lib/graphql/analysis/field_usage.rb +0 -45
  82. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  83. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  84. data/lib/graphql/analysis/query_complexity.rb +0 -88
  85. data/lib/graphql/analysis/query_depth.rb +0 -43
  86. data/lib/graphql/analysis/reducer_state.rb +0 -48
  87. data/lib/graphql/argument.rb +0 -131
  88. data/lib/graphql/authorization.rb +0 -82
  89. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  90. data/lib/graphql/backwards_compatibility.rb +0 -61
  91. data/lib/graphql/base_type.rb +0 -232
  92. data/lib/graphql/boolean_type.rb +0 -2
  93. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  94. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  95. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  96. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  97. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  98. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  99. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  100. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  101. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  102. data/lib/graphql/compatibility.rb +0 -5
  103. data/lib/graphql/define/assign_argument.rb +0 -12
  104. data/lib/graphql/define/assign_connection.rb +0 -13
  105. data/lib/graphql/define/assign_enum_value.rb +0 -18
  106. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  107. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  108. data/lib/graphql/define/assign_object_field.rb +0 -42
  109. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  110. data/lib/graphql/define/instance_definable.rb +0 -240
  111. data/lib/graphql/define/no_definition_error.rb +0 -7
  112. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  113. data/lib/graphql/define/type_definer.rb +0 -31
  114. data/lib/graphql/define.rb +0 -31
  115. data/lib/graphql/deprecated_dsl.rb +0 -55
  116. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  117. data/lib/graphql/directive/include_directive.rb +0 -2
  118. data/lib/graphql/directive/skip_directive.rb +0 -2
  119. data/lib/graphql/directive.rb +0 -107
  120. data/lib/graphql/enum_type.rb +0 -133
  121. data/lib/graphql/execution/execute.rb +0 -333
  122. data/lib/graphql/execution/flatten.rb +0 -40
  123. data/lib/graphql/execution/typecast.rb +0 -50
  124. data/lib/graphql/field/resolve.rb +0 -59
  125. data/lib/graphql/field.rb +0 -226
  126. data/lib/graphql/float_type.rb +0 -2
  127. data/lib/graphql/function.rb +0 -128
  128. data/lib/graphql/id_type.rb +0 -2
  129. data/lib/graphql/input_object_type.rb +0 -138
  130. data/lib/graphql/int_type.rb +0 -2
  131. data/lib/graphql/interface_type.rb +0 -72
  132. data/lib/graphql/internal_representation/document.rb +0 -27
  133. data/lib/graphql/internal_representation/node.rb +0 -206
  134. data/lib/graphql/internal_representation/print.rb +0 -51
  135. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  136. data/lib/graphql/internal_representation/scope.rb +0 -88
  137. data/lib/graphql/internal_representation/visit.rb +0 -36
  138. data/lib/graphql/internal_representation.rb +0 -7
  139. data/lib/graphql/list_type.rb +0 -80
  140. data/lib/graphql/non_null_type.rb +0 -71
  141. data/lib/graphql/object_type.rb +0 -130
  142. data/lib/graphql/query/arguments.rb +0 -189
  143. data/lib/graphql/query/arguments_cache.rb +0 -24
  144. data/lib/graphql/query/executor.rb +0 -52
  145. data/lib/graphql/query/literal_input.rb +0 -136
  146. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  147. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  148. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  149. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  150. data/lib/graphql/query/serial_execution.rb +0 -40
  151. data/lib/graphql/relay/array_connection.rb +0 -83
  152. data/lib/graphql/relay/base_connection.rb +0 -189
  153. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  154. data/lib/graphql/relay/connection_resolve.rb +0 -43
  155. data/lib/graphql/relay/connection_type.rb +0 -54
  156. data/lib/graphql/relay/edge.rb +0 -27
  157. data/lib/graphql/relay/edge_type.rb +0 -19
  158. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  159. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  160. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  161. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  162. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  163. data/lib/graphql/relay/mutation/result.rb +0 -38
  164. data/lib/graphql/relay/mutation.rb +0 -106
  165. data/lib/graphql/relay/node.rb +0 -39
  166. data/lib/graphql/relay/page_info.rb +0 -7
  167. data/lib/graphql/relay/relation_connection.rb +0 -188
  168. data/lib/graphql/relay/type_extensions.rb +0 -32
  169. data/lib/graphql/scalar_type.rb +0 -91
  170. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  171. data/lib/graphql/schema/default_parse_error.rb +0 -10
  172. data/lib/graphql/schema/default_type_error.rb +0 -17
  173. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  174. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  175. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  176. data/lib/graphql/schema/middleware_chain.rb +0 -82
  177. data/lib/graphql/schema/possible_types.rb +0 -44
  178. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  179. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  180. data/lib/graphql/schema/traversal.rb +0 -228
  181. data/lib/graphql/schema/validation.rb +0 -313
  182. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  183. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  184. data/lib/graphql/string_type.rb +0 -2
  185. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  186. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  187. data/lib/graphql/types/relay/node_field.rb +0 -24
  188. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  189. data/lib/graphql/union_type.rb +0 -115
  190. data/lib/graphql/upgrader/member.rb +0 -937
  191. 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,13 +293,19 @@ 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)
320
303
  end
321
304
  end
322
305
 
323
- self.validates(validates)
306
+ if !validates.empty?
307
+ self.validates(validates)
308
+ end
324
309
 
325
310
  if definition_block
326
311
  if definition_block.arity == 1
@@ -338,7 +323,13 @@ module GraphQL
338
323
  # @return [Boolean, nil]
339
324
  # @see GraphQL::Subscriptions::BroadcastAnalyzer
340
325
  def broadcastable?
341
- @broadcastable
326
+ if defined?(@broadcastable)
327
+ @broadcastable
328
+ elsif @resolver_class
329
+ @resolver_class.broadcastable?
330
+ else
331
+ nil
332
+ end
342
333
  end
343
334
 
344
335
  # @param text [String]
@@ -346,6 +337,8 @@ module GraphQL
346
337
  def description(text = nil)
347
338
  if text
348
339
  @description = text
340
+ elsif @resolver_class
341
+ @description || @resolver_class.description
349
342
  else
350
343
  @description
351
344
  end
@@ -411,7 +404,12 @@ module GraphQL
411
404
  def extras(new_extras = nil)
412
405
  if new_extras.nil?
413
406
  # Read the value
414
- @extras
407
+ field_extras = @extras
408
+ if @resolver_class && @resolver_class.extras.any?
409
+ field_extras + @resolver_class.extras
410
+ else
411
+ field_extras
412
+ end
415
413
  else
416
414
  if @extras.frozen?
417
415
  @extras = @extras.dup
@@ -494,7 +492,11 @@ module GraphQL
494
492
  when Numeric
495
493
  @complexity = new_complexity
496
494
  when nil
497
- @complexity
495
+ if @resolver_class
496
+ @complexity || @resolver_class.complexity || 1
497
+ else
498
+ @complexity || 1
499
+ end
498
500
  else
499
501
  raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
500
502
  end
@@ -502,105 +504,31 @@ module GraphQL
502
504
 
503
505
  # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
504
506
  def has_max_page_size?
505
- @has_max_page_size
507
+ @has_max_page_size || (@resolver_class && @resolver_class.has_max_page_size?)
506
508
  end
507
509
 
508
510
  # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
509
- attr_reader :max_page_size
510
-
511
- prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
512
-
513
- # @return [GraphQL::Field]
514
- def to_graphql
515
- field_defn = if @field
516
- @field.dup
517
- elsif @function
518
- GraphQL::Function.build_field(@function)
519
- else
520
- GraphQL::Field.new
521
- end
522
-
523
- field_defn.name = @name
524
- if @return_type_expr
525
- field_defn.type = -> { type }
526
- end
527
-
528
- if @description
529
- field_defn.description = @description
530
- end
531
-
532
- if self.deprecation_reason
533
- field_defn.deprecation_reason = self.deprecation_reason
534
- end
535
-
536
- if @resolver_class
537
- if @resolver_class < GraphQL::Schema::Mutation
538
- field_defn.mutation = @resolver_class
539
- end
540
- field_defn.metadata[:resolver] = @resolver_class
541
- end
542
-
543
- if !@trace.nil?
544
- field_defn.trace = @trace
545
- end
546
-
547
- if @relay_node_field
548
- field_defn.relay_node_field = @relay_node_field
549
- end
550
-
551
- if @relay_nodes_field
552
- field_defn.relay_nodes_field = @relay_nodes_field
553
- end
554
-
555
- if @legacy_edge_class
556
- field_defn.edge_class = @legacy_edge_class
557
- end
558
-
559
- field_defn.resolve = self.method(:resolve_field)
560
- field_defn.connection = connection?
561
- field_defn.connection_max_page_size = max_page_size
562
- field_defn.introspection = @introspection
563
- field_defn.complexity = @complexity
564
- field_defn.subscription_scope = @subscription_scope
565
- field_defn.ast_node = ast_node
566
-
567
- all_argument_definitions.each do |defn|
568
- arg_graphql = defn.deprecated_to_graphql
569
- field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
570
- end
571
-
572
- # Support a passed-in proc, one way or another
573
- @resolve_proc = if @resolve
574
- @resolve
575
- elsif @function
576
- @function
577
- elsif @field
578
- @field.resolve_proc
579
- end
580
-
581
- # Ok, `self` isn't a class, but this is for consistency with the classes
582
- field_defn.metadata[:type_class] = self
583
- field_defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(field_defn)
584
- field_defn
511
+ def max_page_size
512
+ @max_page_size || (@resolver_class && @resolver_class.max_page_size)
585
513
  end
586
514
 
587
515
  class MissingReturnTypeError < GraphQL::Error; end
588
516
  attr_writer :type
589
517
 
590
518
  def type
591
- @type ||= if @function
592
- Member::BuildType.parse_type(@function.type, null: false)
593
- elsif @field
594
- Member::BuildType.parse_type(@field.type, null: false)
595
- elsif @return_type_expr.nil?
596
- # Not enough info to determine type
597
- message = "Can't determine the return type for #{self.path}"
598
- if @resolver_class
599
- message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
600
- end
601
- raise MissingReturnTypeError, message
519
+ if @resolver_class && (t = @resolver_class.type)
520
+ t
602
521
  else
603
- Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
522
+ @type ||= if @return_type_expr.nil?
523
+ # Not enough info to determine type
524
+ message = "Can't determine the return type for #{self.path}"
525
+ if @resolver_class
526
+ message += " (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
527
+ end
528
+ raise MissingReturnTypeError, message
529
+ else
530
+ Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
531
+ end
604
532
  end
605
533
  rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
606
534
  # Let this propagate up
@@ -666,37 +594,6 @@ module GraphQL
666
594
  end
667
595
  end
668
596
 
669
- # Implement {GraphQL::Field}'s resolve API.
670
- #
671
- # Eventually, we might hook up field instances to execution in another way. TBD.
672
- # @see #resolve for how the interpreter hooks up to it
673
- def resolve_field(obj, args, ctx)
674
- ctx.schema.after_lazy(obj) do |after_obj|
675
- # First, apply auth ...
676
- query_ctx = ctx.query.context
677
- # Some legacy fields can have `nil` here, not exactly sure why.
678
- # @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
679
- inner_obj = after_obj && after_obj.object
680
- ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
681
- if authorized?(inner_obj, ruby_args, query_ctx)
682
- # Then if it passed, resolve the field
683
- if @resolve_proc
684
- # Might be nil, still want to call the func in that case
685
- with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
686
- # Pass the GraphQL args here for compatibility:
687
- @resolve_proc.call(extended_obj, args, ctx)
688
- end
689
- else
690
- public_send_field(after_obj, ruby_args, query_ctx)
691
- end
692
- else
693
- err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
694
- query_ctx.schema.unauthorized_field(err)
695
- end
696
- end
697
- end
698
- end
699
-
700
597
  # This method is called by the interpreter for each field.
701
598
  # You can extend it in your base field classes.
702
599
  # @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
@@ -729,7 +626,7 @@ module GraphQL
729
626
  err
730
627
  end
731
628
 
732
- # @param ctx [GraphQL::Query::Context::FieldResolutionContext]
629
+ # @param ctx [GraphQL::Query::Context]
733
630
  def fetch_extra(extra_name, ctx)
734
631
  if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
735
632
  self.public_send(extra_name)
@@ -742,63 +639,6 @@ module GraphQL
742
639
 
743
640
  private
744
641
 
745
- NO_ARGS = {}.freeze
746
-
747
- # Convert a GraphQL arguments instance into a Ruby-style hash.
748
- #
749
- # @param obj [GraphQL::Schema::Object] The object where this field is being resolved
750
- # @param graphql_args [GraphQL::Query::Arguments]
751
- # @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
752
- # @return [Hash<Symbol => Any>]
753
- def to_ruby_args(obj, graphql_args, field_ctx)
754
- if graphql_args.any? || @extras.any?
755
- # Splat the GraphQL::Arguments to Ruby keyword arguments
756
- ruby_kwargs = graphql_args.to_kwargs
757
- maybe_lazies = []
758
- # Apply any `prepare` methods. Not great code organization, can this go somewhere better?
759
- arguments(field_ctx).each do |name, arg_defn|
760
- ruby_kwargs_key = arg_defn.keyword
761
-
762
- if ruby_kwargs.key?(ruby_kwargs_key)
763
- loads = arg_defn.loads
764
- value = ruby_kwargs[ruby_kwargs_key]
765
- loaded_value = if loads && !arg_defn.from_resolver?
766
- if arg_defn.type.list?
767
- loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
768
- field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
769
- else
770
- load_application_object(arg_defn, loads, value, field_ctx.query.context)
771
- end
772
- elsif arg_defn.type.list? && value.is_a?(Array)
773
- field_ctx.schema.after_any_lazies(value, &:itself)
774
- else
775
- value
776
- end
777
-
778
- maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
779
- prepared_value = if arg_defn.prepare
780
- arg_defn.prepare_value(obj, loaded_value)
781
- else
782
- loaded_value
783
- end
784
-
785
- ruby_kwargs[ruby_kwargs_key] = prepared_value
786
- end
787
- end
788
- end
789
-
790
- @extras.each do |extra_arg|
791
- ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
792
- end
793
-
794
- field_ctx.schema.after_any_lazies(maybe_lazies) do
795
- ruby_kwargs
796
- end
797
- else
798
- NO_ARGS
799
- end
800
- end
801
-
802
642
  def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
803
643
  with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
804
644
  begin
@@ -818,14 +658,14 @@ module GraphQL
818
658
  # - A method on the wrapped object;
819
659
  # - Or, raise not implemented.
820
660
  #
821
- if obj.respond_to?(@resolver_method)
822
- method_to_call = @resolver_method
661
+ if obj.respond_to?(resolver_method)
662
+ method_to_call = resolver_method
823
663
  method_receiver = obj
824
664
  # Call the method with kwargs, if there are any
825
665
  if ruby_kwargs.any?
826
- obj.public_send(@resolver_method, **ruby_kwargs)
666
+ obj.public_send(resolver_method, **ruby_kwargs)
827
667
  else
828
- obj.public_send(@resolver_method)
668
+ obj.public_send(resolver_method)
829
669
  end
830
670
  elsif obj.object.is_a?(Hash)
831
671
  inner_object = obj.object
@@ -848,7 +688,7 @@ module GraphQL
848
688
  raise <<-ERR
849
689
  Failed to implement #{@owner.graphql_name}.#{@name}, tried:
850
690
 
851
- - `#{obj.class}##{@resolver_method}`, which did not exist
691
+ - `#{obj.class}##{resolver_method}`, which did not exist
852
692
  - `#{obj.object.class}##{@method_sym}`, which did not exist
853
693
  - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
854
694
 
@@ -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
@@ -83,7 +59,6 @@ module GraphQL
83
59
  # Authorize each argument (but this doesn't apply if `prepare` is implemented):
84
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