graphql 1.8.0.pre11 → 1.8.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/schema.erb +1 -1
  3. data/lib/graphql/function.rb +2 -0
  4. data/lib/graphql/railtie.rb +1 -1
  5. data/lib/graphql/schema.rb +1 -0
  6. data/lib/graphql/schema/argument.rb +3 -2
  7. data/lib/graphql/schema/build_from_definition.rb +1 -1
  8. data/lib/graphql/schema/field.rb +96 -49
  9. data/lib/graphql/schema/interface.rb +21 -3
  10. data/lib/graphql/schema/list.rb +4 -0
  11. data/lib/graphql/schema/member/accepts_definition.rb +2 -2
  12. data/lib/graphql/schema/member/base_dsl_methods.rb +4 -0
  13. data/lib/graphql/schema/member/build_type.rb +4 -2
  14. data/lib/graphql/schema/member/has_fields.rb +1 -8
  15. data/lib/graphql/schema/mutation.rb +19 -88
  16. data/lib/graphql/schema/non_null.rb +4 -0
  17. data/lib/graphql/schema/object.rb +1 -1
  18. data/lib/graphql/schema/relay_classic_mutation.rb +14 -15
  19. data/lib/graphql/schema/resolver.rb +122 -0
  20. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  21. data/lib/graphql/subscriptions/serialize.rb +2 -0
  22. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  23. data/lib/graphql/version.rb +1 -1
  24. data/readme.md +1 -1
  25. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  26. data/spec/graphql/relay/mutation_spec.rb +5 -3
  27. data/spec/graphql/schema/build_from_definition_spec.rb +1 -1
  28. data/spec/graphql/schema/field_spec.rb +7 -24
  29. data/spec/graphql/schema/interface_spec.rb +25 -0
  30. data/spec/graphql/schema/member/accepts_definition_spec.rb +22 -0
  31. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  32. data/spec/graphql/schema/mutation_spec.rb +15 -14
  33. data/spec/graphql/schema/resolver_spec.rb +131 -0
  34. data/spec/graphql/subscriptions_spec.rb +267 -205
  35. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  36. data/spec/support/jazz.rb +6 -1
  37. data/spec/support/new_relic.rb +24 -0
  38. data/spec/support/star_trek/schema.rb +2 -2
  39. data/spec/support/star_wars/schema.rb +1 -2
  40. metadata +13 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f9824961c7be659d7f815105dce1ed73cb0524b8
4
- data.tar.gz: '08b3edfb6cc0fa00917cae9faf8c6c166e1cd2a8'
3
+ metadata.gz: f5283bf51e22ac60f8d9368d9cc19b8c6d038d8b
4
+ data.tar.gz: 147ec429661a6fbc1aaef685ba94c8a81d87910e
5
5
  SHA512:
6
- metadata.gz: 69707f9127dddff3f1039b066db1a46f1c2bd8a3b9527d4d73bd109734026da47623eb602a9988c300edef8ddf978ddc12fab355248895fcab6d37397ed7b00b
7
- data.tar.gz: 958bb3dd36b858af4273df812cdec568e463e9719efea31b1ba5249fce424259097d80c40ef70ffed61971e27b4d956287c26d82a9274a2e7df34b106fc9e6fe
6
+ metadata.gz: 06a2a8730fc1c13dc0a0d76a35b19e89dd40ad842e41618abb1b05a7f75b667eede56c106728e3e68bd531e36e29b28050b991319599b7952ac3285fb3f9be3c
7
+ data.tar.gz: 8231c7696681477decf92b0665f3e4249b308153338c8d7cf5102b7e95133b9ac7aa6156f3dddc026c4178ea9fcb25d7f181f752298d5cf38185141af653a471
@@ -21,7 +21,7 @@
21
21
  }
22
22
 
23
23
  # Object Resolution
24
- resolve_type -> (obj, ctx) {
24
+ resolve_type -> (type, obj, ctx) {
25
25
  # TODO: Implement this function
26
26
  # to return the correct type for `obj`
27
27
  raise(NotImplementedError)
@@ -28,6 +28,8 @@ module GraphQL
28
28
  # field :post, function: FindRecord.new(model: Post, type: PostType)
29
29
  # field :comment, function: FindRecord.new(model: Comment, type: CommentType)
30
30
  # end
31
+ #
32
+ # @see {GraphQL::Schema::Resolver} for a replacement for `GraphQL::Function`
31
33
  class Function
32
34
  # @return [Hash<String => GraphQL::Argument>] Arguments, keyed by name
33
35
  def arguments
@@ -72,7 +72,7 @@ module GraphQL
72
72
  unless File.exists?(destination_file)
73
73
  FileUtils.mkdir_p(File.dirname(destination_file))
74
74
  File.open(destination_file, 'w') do |f|
75
- f.write "class Types::BaseInterface < GraphQL::Schema::Interface\nend"
75
+ f.write "module Types::BaseInterface\n include GraphQL::Schema::Interface\nend"
76
76
  end
77
77
  end
78
78
 
@@ -29,6 +29,7 @@ require "graphql/schema/enum"
29
29
  require "graphql/schema/field"
30
30
  require "graphql/schema/input_object"
31
31
  require "graphql/schema/interface"
32
+ require "graphql/schema/resolver"
32
33
  require "graphql/schema/mutation"
33
34
  require "graphql/schema/relay_classic_mutation"
34
35
  require "graphql/schema/object"
@@ -28,9 +28,10 @@ module GraphQL
28
28
  # @param as [Symbol] Override the keyword name when passed to a method
29
29
  # @param prepare [Symbol] A method to call to tranform this argument's valuebefore sending it to field resolution
30
30
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
31
- def initialize(arg_name, type_expr, desc = nil, required:, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
31
+ def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
32
+ arg_name ||= name
32
33
  @name = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
33
- @type_expr = type_expr
34
+ @type_expr = type_expr || type
34
35
  @description = desc || description
35
36
  @null = !required
36
37
  @default_value = default_value
@@ -237,7 +237,7 @@ module GraphQL
237
237
  **kwargs,
238
238
  )
239
239
 
240
- argument.ast_node = input_object_type_definition
240
+ argument.ast_node = input_argument
241
241
 
242
242
  [
243
243
  input_argument.name,
@@ -8,7 +8,7 @@ module GraphQL
8
8
  include GraphQL::Schema::Member::HasArguments
9
9
 
10
10
  # @return [String] the GraphQL name for this field, camelized unless `camelize: false` is provided
11
- attr_reader :name
11
+ attr_accessor :name
12
12
 
13
13
  # @return [String]
14
14
  attr_accessor :description
@@ -22,9 +22,55 @@ module GraphQL
22
22
  # @return [Class] The type that this field belongs to
23
23
  attr_reader :owner
24
24
 
25
- # @return [Class, nil] The mutation this field was derived from, if there is one
26
- def mutation
27
- @mutation || @mutation_class
25
+
26
+ # @return [Class, nil] The {Schema::Resolver} this field was derived from, if there is one
27
+ def resolver
28
+ @resolver_class
29
+ end
30
+
31
+ alias :mutation :resolver
32
+
33
+ # Create a field instance from a list of arguments, keyword arguments, and a block.
34
+ #
35
+ # This method implements prioritization between the `resolver` or `mutation` defaults
36
+ # and the local overrides via other keywords.
37
+ #
38
+ # It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
39
+ # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
40
+ # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
41
+ # @return [GraphQL::Schema:Field] an instance of `self
42
+ # @see {.initialize} for other options
43
+ def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, **kwargs, &block)
44
+ if (parent_config = resolver || mutation)
45
+ # Get the parent config, merge in local overrides
46
+ kwargs = parent_config.field_options.merge(kwargs)
47
+ # Add a reference to that parent class
48
+ kwargs[:resolver_class] = parent_config
49
+ end
50
+
51
+ if name
52
+ kwargs[:name] = name
53
+ end
54
+
55
+ if !type.nil?
56
+ if type.is_a?(GraphQL::Field)
57
+ raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
58
+ end
59
+ if desc
60
+ if kwargs[:description]
61
+ raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
62
+ end
63
+
64
+ kwargs[:description] = desc
65
+ kwargs[:type] = type
66
+ elsif (kwargs[:field] || kwargs[:function] || resolver || mutation) && type.is_a?(String)
67
+ # The return type should be copied from `field` or `function`, and the second positional argument is the description
68
+ kwargs[:description] = type
69
+ else
70
+ kwargs[:type] = type
71
+ end
72
+ end
73
+ new(**kwargs, &block)
28
74
  end
29
75
 
30
76
  # @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
@@ -42,39 +88,29 @@ module GraphQL
42
88
  # @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
43
89
  # @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
44
90
  # @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
45
- # @param mutation [Class] A {Schema::Mutation} class for serving this field
46
- # @param mutation_class [Class] (Private) A {Schema::Mutation} which this field was derived from.
47
- # @param arguments [{String=>GraphQL::Schema::Arguments}] Arguments for this field (may be added in the block, also)
91
+ # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
92
+ # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
48
93
  # @param camelize [Boolean] If true, the field name will be camelized when building the schema
49
94
  # @param complexity [Numeric] When provided, set the complexity for this field
50
- def initialize(name, return_type_expr = nil, desc = nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, introspection: false, hash_key: nil, camelize: true, complexity: 1, extras: [], mutation: nil, mutation_class: nil, arguments: {}, &definition_block)
51
- if (field || function) && desc.nil? && return_type_expr.is_a?(String)
52
- # The return type should be copied from `field` or `function`, and the second positional argument is the description
53
- desc = return_type_expr
54
- return_type_expr = nil
55
- end
56
- if mutation && (return_type_expr || desc || description || function || field || !null.nil? || deprecation_reason || method || resolve || introspection || hash_key)
57
- raise ArgumentError, "when keyword `mutation:` is present, all arguments are ignored, please remove them"
95
+ # @param subscription_scope [Symbol, String] A key in `context` which will be used to scope subscription payloads
96
+ def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, introspection: false, hash_key: nil, camelize: true, complexity: 1, extras: [], resolver_class: nil, subscription_scope: nil, arguments: {}, &definition_block)
97
+
98
+ if name.nil?
99
+ raise ArgumentError, "missing first `name` argument or keyword `name:`"
58
100
  end
59
- if !(field || function || mutation)
60
- if return_type_expr.nil?
61
- raise ArgumentError, "missing positional argument `type`"
101
+ if !(field || function || mutation || resolver)
102
+ if type.nil?
103
+ raise ArgumentError, "missing second `type` argument or keyword `type:`"
62
104
  end
63
105
  if null.nil?
64
106
  raise ArgumentError, "missing keyword argument null:"
65
107
  end
66
108
  end
67
- if (field || function || resolve || resolve) && extras.any?
109
+ if (field || function || resolve || mutation) && extras.any?
68
110
  raise ArgumentError, "keyword `extras:` may only be used with method-based resolve, please remove `field:`, `function:`, `resolve:`, or `mutation:`"
69
111
  end
70
- if return_type_expr.is_a?(GraphQL::Field)
71
- raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
72
- end
73
112
  @name = camelize ? Member::BuildType.camelize(name.to_s) : name.to_s
74
- if description && desc
75
- raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{description.inspect})"
76
- end
77
- @description = description || desc
113
+ @description = description
78
114
  if field.is_a?(GraphQL::Schema::Field)
79
115
  @field_instance = field
80
116
  else
@@ -93,17 +129,26 @@ module GraphQL
93
129
  @method_str = method_name.to_s
94
130
  @method_sym = method_name.to_sym
95
131
  @complexity = complexity
96
- @return_type_expr = return_type_expr
132
+ @return_type_expr = type
97
133
  @return_type_null = null
98
134
  @connection = connection
99
135
  @max_page_size = max_page_size
100
136
  @introspection = introspection
101
137
  @extras = extras
102
- @mutation = mutation
103
- @mutation_class = mutation_class
138
+ @resolver_class = resolver_class
139
+
104
140
  # Override the default from HasArguments
105
- @own_arguments = arguments
141
+ @own_arguments = {}
142
+ arguments.each do |name, arg|
143
+ if arg.is_a?(Hash)
144
+ argument(name: name, **arg)
145
+ else
146
+ @own_arguments[name] = arg
147
+ end
148
+ end
149
+
106
150
  @owner = owner
151
+ @subscription_scope = subscription_scope
107
152
 
108
153
  if definition_block
109
154
  instance_eval(&definition_block)
@@ -142,9 +187,6 @@ module GraphQL
142
187
  # this field was previously defined and passed here, so delegate to it
143
188
  if @field_instance
144
189
  return @field_instance.to_graphql
145
- elsif @mutation
146
- field_inst = @mutation.graphql_field
147
- return field_inst.to_graphql
148
190
  end
149
191
 
150
192
 
@@ -181,8 +223,11 @@ module GraphQL
181
223
  field_defn.deprecation_reason = @deprecation_reason
182
224
  end
183
225
 
184
- if @mutation_class
185
- field_defn.mutation = @mutation_class
226
+ if @resolver_class
227
+ if @resolver_class < GraphQL::Schema::Mutation
228
+ field_defn.mutation = @resolver_class
229
+ end
230
+ field_defn.metadata[:resolver] = @resolver_class
186
231
  end
187
232
 
188
233
  field_defn.resolve = self.method(:resolve_field)
@@ -190,6 +235,7 @@ module GraphQL
190
235
  field_defn.connection_max_page_size = @max_page_size
191
236
  field_defn.introspection = @introspection
192
237
  field_defn.complexity = @complexity
238
+ field_defn.subscription_scope = @subscription_scope
193
239
 
194
240
  # apply this first, so it can be overriden below
195
241
  if @connection
@@ -207,6 +253,15 @@ module GraphQL
207
253
  field_defn.arguments[arg_graphql.name] = arg_graphql
208
254
  end
209
255
 
256
+ # Support a passed-in proc, one way or another
257
+ @resolve_proc = if @resolve
258
+ @resolve
259
+ elsif @function
260
+ @function
261
+ elsif @field
262
+ @field.resolve_proc
263
+ end
264
+
210
265
  # Ok, `self` isn't a class, but this is for consistency with the classes
211
266
  field_defn.metadata[:type_class] = self
212
267
 
@@ -223,22 +278,14 @@ module GraphQL
223
278
  #
224
279
  # Eventually, we might hook up field instances to execution in another way. TBD.
225
280
  def resolve_field(obj, args, ctx)
226
- if @resolve || @function || @field
227
- # Support a passed-in proc, one way or another
228
- prev_resolve = if @resolve
229
- @resolve
230
- elsif @function
231
- @function
232
- elsif @field
233
- @field.resolve_proc
234
- end
235
-
281
+ if @resolve_proc
236
282
  # Might be nil, still want to call the func in that case
237
283
  inner_obj = obj && obj.object
238
- prev_resolve.call(inner_obj, args, ctx)
239
- elsif @mutation_class
240
- mutation_inst = @mutation_class.new(object: obj, arguments: args, context: ctx.query.context)
241
- public_send_field(mutation_inst, args, ctx)
284
+ @resolve_proc.call(inner_obj, args, ctx)
285
+ elsif @resolver_class
286
+ inner_obj = obj && obj.object
287
+ singleton_inst = @resolver_class.new(object: inner_obj, context: ctx.query.context)
288
+ public_send_field(singleton_inst, args, ctx)
242
289
  else
243
290
  public_send_field(obj, args, ctx)
244
291
  end
@@ -22,12 +22,22 @@ module GraphQL
22
22
  if !child_class.is_a?(Class)
23
23
  # In this case, it's been included into another interface.
24
24
  # This is how interface inheritance is implemented
25
- child_class.const_set(:DefinitionMethods, Module.new)
26
- child_class.extend(child_class::DefinitionMethods)
25
+
26
+ # Use an instance variable to tell whether it's been included previously or not;
27
+ # You can't use constant detection because constants are brought into scope
28
+ # by `include`, which has already happened at this point.
29
+ if !child_class.instance_variable_defined?(:@_definition_methods)
30
+ defn_methods_module = Module.new
31
+ child_class.instance_variable_set(:@_definition_methods, defn_methods_module)
32
+ child_class.const_set(:DefinitionMethods, defn_methods_module)
33
+ child_class.extend(child_class::DefinitionMethods)
34
+ end
35
+
27
36
  # We need this before we can call `own_interfaces`
28
37
  child_class.extend(Schema::Interface::DefinitionMethods)
38
+
29
39
  child_class.own_interfaces << self
30
- child_class.own_interfaces.each do |interface_defn|
40
+ child_class.interfaces.each do |interface_defn|
31
41
  child_class.extend(interface_defn::DefinitionMethods)
32
42
  end
33
43
  elsif child_class < GraphQL::Schema::Object
@@ -76,12 +86,20 @@ module GraphQL
76
86
  def own_interfaces
77
87
  @own_interfaces ||= []
78
88
  end
89
+
90
+ def interfaces
91
+ own_interfaces + (own_interfaces.map { |i| i.own_interfaces }).flatten
92
+ end
79
93
  end
80
94
 
81
95
  # Extend this _after_ `DefinitionMethods` is defined, so it will be used
82
96
  extend GraphQL::Schema::Member::AcceptsDefinition
83
97
 
84
98
  extend DefinitionMethods
99
+
100
+ def unwrap
101
+ self
102
+ end
85
103
  end
86
104
  end
87
105
  end
@@ -23,6 +23,10 @@ module GraphQL
23
23
  def kind
24
24
  GraphQL::TypeKinds::LIST
25
25
  end
26
+
27
+ def unwrap
28
+ @of_type.unwrap
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -69,7 +69,7 @@ module GraphQL
69
69
  if args.any?
70
70
  instance_variable_set(ivar_name, args)
71
71
  end
72
- instance_variable_get(ivar_name)
72
+ instance_variable_get(ivar_name) || (superclass.respond_to?(name) ? superclass.public_send(name) : nil)
73
73
  end
74
74
 
75
75
  define_method(name) do |*args|
@@ -86,7 +86,7 @@ module GraphQL
86
86
  if args.any?
87
87
  instance_variable_set(ivar_name, args)
88
88
  end
89
- instance_variable_get(ivar_name)
89
+ instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name))
90
90
  end
91
91
  end
92
92
  end
@@ -76,6 +76,10 @@ module GraphQL
76
76
  @graphql_name || find_inherited_method(:overridden_graphql_name, nil)
77
77
  end
78
78
 
79
+ def unwrap
80
+ self
81
+ end
82
+
79
83
  private
80
84
 
81
85
  def find_inherited_method(method_name, default_value)
@@ -101,13 +101,15 @@ module GraphQL
101
101
  when Array
102
102
  to_type_name(something.first)
103
103
  when Module
104
- if something < GraphQL::Schema::Member
104
+ if something.respond_to?(:graphql_name)
105
105
  something.graphql_name
106
106
  else
107
- something.name.split("::").last
107
+ to_type_name(something.name)
108
108
  end
109
109
  when String
110
110
  something.gsub(/\]\[\!/, "").split("::").last
111
+ when GraphQL::Schema::NonNull, GraphQL::Schema::List
112
+ to_type_name(something.unwrap)
111
113
  else
112
114
  raise "Unhandled to_type_name input: #{something} (#{something.class})"
113
115
  end
@@ -49,7 +49,7 @@ module GraphQL
49
49
  # @see {GraphQL::Schema::Field#initialize} for method signature
50
50
  # @return [void]
51
51
  def field(*args, **kwargs, &block)
52
- field_defn = build_field(*args, **kwargs, &block)
52
+ field_defn = field_class.from_options(*args, owner: self, **kwargs, &block)
53
53
  add_field(field_defn)
54
54
  nil
55
55
  end
@@ -103,13 +103,6 @@ module GraphQL
103
103
  end
104
104
 
105
105
  private
106
-
107
- # Initialize a field with this class's field class, but don't attach it.
108
- def build_field(*args, **kwargs, &block)
109
- kwargs[:owner] = self
110
- field_class.new(*args, **kwargs, &block)
111
- end
112
-
113
106
  # Find the magic module for holding super methods,
114
107
  # and add a field named `method_name` for implementing the field
115
108
  # called `field_name`.
@@ -58,51 +58,16 @@ module GraphQL
58
58
  # }
59
59
  # GRAPHQL
60
60
  #
61
- class Mutation < GraphQL::Schema::Member
61
+ class Mutation < GraphQL::Schema::Resolver
62
62
  extend GraphQL::Schema::Member::HasFields
63
- extend GraphQL::Schema::Member::HasArguments
64
-
65
- # @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
66
- # @param context [GraphQL::Query::Context]
67
- def initialize(object:, context:, arguments:)
68
- @object = object
69
- @context = context
70
- end
71
-
72
- # @return [Object] the root value of the operation
73
- attr_reader :object
74
-
75
- # @return [GraphQL::Query::Context]
76
- attr_reader :context
77
-
78
- # Do the work. Everything happens here.
79
- # @return [Hash] A key for each field in the return type
80
- # @return [Object] An object corresponding to the return type
81
- def resolve(**args)
82
- raise NotImplementedError, "#{self.class.name}#resolve should execute side effects and return a Symbol-keyed hash"
83
- end
84
-
85
- # This is a hook for classes to intercept resolution.
86
- # @see RelayClassicMutation for usage
87
- def resolve_mutation(args)
88
- resolve(args)
89
- end
90
63
 
91
64
  class << self
92
- def inherited(base)
93
- base.null(null)
94
- super
95
- end
96
-
97
- # Override the method from HasFields to support `field: Mutation.field`, for backwards compat.
98
- #
99
- # If called without any arguments, returns a `GraphQL::Field`.
100
- # @see {GraphQL::Schema::Member::HasFields.field} for default behavior
65
+ # Override this method to handle legacy-style usages of `MyMutation.field`
101
66
  def field(*args, &block)
102
- if args.none? && !block_given?
103
- graphql_field.graphql_definition
67
+ if args.none?
68
+ raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
104
69
  else
105
- super(*args, &block)
70
+ super
106
71
  end
107
72
  end
108
73
 
@@ -118,20 +83,8 @@ module GraphQL
118
83
  @payload_type ||= generate_payload_type
119
84
  end
120
85
 
121
- # @return [GraphQL::Schema::Field] The generated field instance for this mutation
122
- # @see {GraphQL::Schema::Field}'s `mutation:` option, don't call this directly
123
- def graphql_field
124
- @graphql_field ||= generate_field
125
- end
126
-
127
- # @param new_name [String, nil] if present, override the class name to set this value
128
- # @return [String] The name of this mutation in the GraphQL schema (used for naming derived types and fields)
129
- def graphql_name(new_name = nil)
130
- if new_name
131
- @graphql_name = new_name
132
- end
133
- @graphql_name ||= self.name.split("::").last
134
- end
86
+ alias :type :payload_type
87
+ alias :type_expr :payload_type
135
88
 
136
89
  # An object class to use for deriving payload types
137
90
  # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
@@ -143,23 +96,22 @@ module GraphQL
143
96
  @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
144
97
  end
145
98
 
146
- # Additional info injected into {#resolve}
147
- # @see {GraphQL::Schema::Field#extras}
148
- def extras(new_extras = nil)
149
- if new_extras
150
- @extras = new_extras
99
+ def field_class(new_class = nil)
100
+ if new_class
101
+ @field_class = new_class
102
+ else
103
+ @field_class || find_inherited_method(:field_class, GraphQL::Schema::Field)
151
104
  end
152
- @extras || []
153
105
  end
154
106
 
155
- # Specifies whether or not the mutation is nullable. Defaults to `true`
156
- # @param allow_null [Boolean] Whether or not the response can be null
157
- def null(allow_null = nil)
158
- unless allow_null.nil?
159
- @null = allow_null
107
+ # An object class to use for deriving return types
108
+ # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
109
+ # @return [Class]
110
+ def object_class(new_class = nil)
111
+ if new_class
112
+ @object_class = new_class
160
113
  end
161
-
162
- @null.nil? ? true : @null
114
+ @object_class || (superclass.respond_to?(:object_class) ? superclass.object_class : GraphQL::Schema::Object)
163
115
  end
164
116
 
165
117
  private
@@ -180,27 +132,6 @@ module GraphQL
180
132
  end
181
133
  end
182
134
  end
183
-
184
- # This name will be used for the {.graphql_field}.
185
- def field_name
186
- graphql_name.sub(/^[A-Z]/, &:downcase)
187
- end
188
-
189
- # Build an instance of {.field_class} which will be used to execute this mutation.
190
- # To customize field generation, override this method.
191
- def generate_field
192
- # TODO support deprecation_reason
193
- self.field_class.new(
194
- field_name,
195
- payload_type,
196
- description,
197
- extras: extras,
198
- method: :resolve_mutation,
199
- mutation_class: self,
200
- arguments: arguments,
201
- null: null,
202
- )
203
- end
204
135
  end
205
136
  end
206
137
  end