graphql 1.10.13 → 1.11.3
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/templates/graphql_controller.erb +11 -9
- data/lib/graphql.rb +3 -3
- data/lib/graphql/directive.rb +4 -0
- data/lib/graphql/execution/interpreter.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +6 -4
- data/lib/graphql/execution/multiplex.rb +1 -2
- data/lib/graphql/field.rb +4 -0
- data/lib/graphql/input_object_type.rb +4 -0
- data/lib/graphql/introspection/schema_type.rb +3 -3
- data/lib/graphql/invalid_null_error.rb +18 -0
- data/lib/graphql/language/nodes.rb +1 -0
- data/lib/graphql/language/visitor.rb +2 -2
- data/lib/graphql/pagination/connection.rb +18 -13
- data/lib/graphql/pagination/connections.rb +17 -4
- data/lib/graphql/query.rb +1 -2
- data/lib/graphql/schema.rb +22 -16
- data/lib/graphql/schema/build_from_definition.rb +7 -12
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
- data/lib/graphql/schema/enum_value.rb +1 -0
- data/lib/graphql/schema/field.rb +63 -77
- data/lib/graphql/schema/field/connection_extension.rb +42 -32
- data/lib/graphql/schema/loader.rb +19 -1
- data/lib/graphql/schema/member/has_arguments.rb +3 -1
- data/lib/graphql/schema/member/has_fields.rb +15 -5
- data/lib/graphql/schema/mutation.rb +4 -0
- data/lib/graphql/schema/object.rb +1 -1
- data/lib/graphql/schema/resolver.rb +20 -0
- data/lib/graphql/schema/resolver/has_payload_type.rb +2 -1
- data/lib/graphql/schema/subscription.rb +1 -1
- data/lib/graphql/schema/union.rb +29 -0
- data/lib/graphql/schema/warden.rb +0 -1
- data/lib/graphql/static_validation/literal_validator.rb +7 -7
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +2 -2
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -2
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -2
- data/lib/graphql/subscriptions.rb +41 -8
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +66 -11
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +84 -0
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
- data/lib/graphql/subscriptions/event.rb +16 -1
- data/lib/graphql/subscriptions/serialize.rb +22 -4
- data/lib/graphql/subscriptions/subscription_root.rb +3 -1
- data/lib/graphql/tracing.rb +1 -27
- data/lib/graphql/tracing/platform_tracing.rb +25 -15
- data/lib/graphql/tracing/statsd_tracing.rb +14 -14
- data/lib/graphql/version.rb +1 -1
- metadata +4 -2
@@ -45,8 +45,10 @@ module GraphQL
|
|
45
45
|
@resolve_hash[type_name_s][field_name.to_s] = resolve_fn
|
46
46
|
end
|
47
47
|
when Proc
|
48
|
-
# for example,
|
48
|
+
# for example, "resolve_type"
|
49
49
|
@resolve_hash[type_name_s] = fields
|
50
|
+
else
|
51
|
+
raise ArgumentError, "Unexpected resolve hash value for #{type_name.inspect}: #{fields.inspect} (#{fields.class})"
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
@@ -41,6 +41,7 @@ module GraphQL
|
|
41
41
|
|
42
42
|
def initialize(graphql_name, desc = nil, owner:, ast_node: nil, description: nil, value: nil, deprecation_reason: nil, &block)
|
43
43
|
@graphql_name = graphql_name.to_s
|
44
|
+
GraphQL::NameValidator.validate!(@graphql_name)
|
44
45
|
@description = desc || description
|
45
46
|
@value = value.nil? ? @graphql_name : value
|
46
47
|
@deprecation_reason = deprecation_reason
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -36,9 +36,18 @@ module GraphQL
|
|
36
36
|
# @return [Symbol] The method on the type to look up
|
37
37
|
attr_reader :resolver_method
|
38
38
|
|
39
|
-
# @return [Class] The
|
39
|
+
# @return [Class] The thing this field was defined on (type, mutation, resolver)
|
40
40
|
attr_accessor :owner
|
41
41
|
|
42
|
+
# @return [Class] The GraphQL type this field belongs to. (For fields defined on mutations, it's the payload type)
|
43
|
+
def owner_type
|
44
|
+
@owner_type ||= if owner < GraphQL::Schema::Mutation
|
45
|
+
owner.payload_type
|
46
|
+
else
|
47
|
+
owner
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
42
51
|
# @return [Symbol] the original name of the field, passed in by the user
|
43
52
|
attr_reader :original_name
|
44
53
|
|
@@ -191,9 +200,10 @@ module GraphQL
|
|
191
200
|
# @param subscription_scope [Symbol, String] A key in `context` which will be used to scope subscription payloads
|
192
201
|
# @param extensions [Array<Class, Hash<Class => Object>>] Named extensions to apply to this field (see also {#extension})
|
193
202
|
# @param trace [Boolean] If true, a {GraphQL::Tracing} tracer will measure this scalar field
|
203
|
+
# @param broadcastable [Boolean] Whether or not this field can be distributed in subscription broadcasts
|
194
204
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
195
205
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
196
|
-
def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: 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: [], 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, arguments: EMPTY_HASH, &definition_block)
|
206
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: 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: [], 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, &definition_block)
|
197
207
|
if name.nil?
|
198
208
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
199
209
|
end
|
@@ -237,8 +247,8 @@ module GraphQL
|
|
237
247
|
end
|
238
248
|
|
239
249
|
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
240
|
-
method_name = method || hash_key ||
|
241
|
-
resolver_method ||=
|
250
|
+
method_name = method || hash_key || name_s
|
251
|
+
resolver_method ||= name_s.to_sym
|
242
252
|
|
243
253
|
@method_str = method_name.to_s
|
244
254
|
@method_sym = method_name.to_sym
|
@@ -251,6 +261,7 @@ module GraphQL
|
|
251
261
|
@max_page_size = max_page_size == :not_given ? nil : max_page_size
|
252
262
|
@introspection = introspection
|
253
263
|
@extras = extras
|
264
|
+
@broadcastable = broadcastable
|
254
265
|
@resolver_class = resolver_class
|
255
266
|
@scope = scope
|
256
267
|
@trace = trace
|
@@ -295,6 +306,13 @@ module GraphQL
|
|
295
306
|
end
|
296
307
|
end
|
297
308
|
|
309
|
+
# If true, subscription updates with this field can be shared between viewers
|
310
|
+
# @return [Boolean, nil]
|
311
|
+
# @see GraphQL::Subscriptions::BroadcastAnalyzer
|
312
|
+
def broadcastable?
|
313
|
+
@broadcastable
|
314
|
+
end
|
315
|
+
|
298
316
|
# @param text [String]
|
299
317
|
# @return [String]
|
300
318
|
def description(text = nil)
|
@@ -534,7 +552,7 @@ module GraphQL
|
|
534
552
|
@resolve_proc.call(extended_obj, args, ctx)
|
535
553
|
end
|
536
554
|
else
|
537
|
-
public_send_field(after_obj, ruby_args,
|
555
|
+
public_send_field(after_obj, ruby_args, query_ctx)
|
538
556
|
end
|
539
557
|
else
|
540
558
|
err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
|
@@ -558,30 +576,7 @@ module GraphQL
|
|
558
576
|
application_object = object.object
|
559
577
|
ctx.schema.after_lazy(self.authorized?(application_object, args, ctx)) do |is_authorized|
|
560
578
|
if is_authorized
|
561
|
-
|
562
|
-
with_extensions(object, args, ctx) do |extended_obj, extended_args|
|
563
|
-
field_receiver = if @resolver_class
|
564
|
-
resolver_obj = if extended_obj.is_a?(GraphQL::Schema::Object)
|
565
|
-
extended_obj.object
|
566
|
-
else
|
567
|
-
extended_obj
|
568
|
-
end
|
569
|
-
@resolver_class.new(object: resolver_obj, context: ctx, field: self)
|
570
|
-
else
|
571
|
-
extended_obj
|
572
|
-
end
|
573
|
-
|
574
|
-
if field_receiver.respond_to?(@resolver_method)
|
575
|
-
# Call the method with kwargs, if there are any
|
576
|
-
if extended_args.any?
|
577
|
-
field_receiver.public_send(@resolver_method, **extended_args)
|
578
|
-
else
|
579
|
-
field_receiver.public_send(@resolver_method)
|
580
|
-
end
|
581
|
-
else
|
582
|
-
resolve_field_method(field_receiver, extended_args, ctx)
|
583
|
-
end
|
584
|
-
end
|
579
|
+
public_send_field(object, args, ctx)
|
585
580
|
else
|
586
581
|
err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
|
587
582
|
ctx.schema.unauthorized_field(err)
|
@@ -597,43 +592,6 @@ module GraphQL
|
|
597
592
|
err
|
598
593
|
end
|
599
594
|
|
600
|
-
# Find a way to resolve this field, checking:
|
601
|
-
#
|
602
|
-
# - Hash keys, if the wrapped object is a hash;
|
603
|
-
# - A method on the wrapped object;
|
604
|
-
# - Or, raise not implemented.
|
605
|
-
#
|
606
|
-
# This can be overridden by defining a method on the object type.
|
607
|
-
# @param obj [GraphQL::Schema::Object]
|
608
|
-
# @param ruby_kwargs [Hash<Symbol => Object>]
|
609
|
-
# @param ctx [GraphQL::Query::Context]
|
610
|
-
def resolve_field_method(obj, ruby_kwargs, ctx)
|
611
|
-
if obj.object.is_a?(Hash)
|
612
|
-
inner_object = obj.object
|
613
|
-
if inner_object.key?(@method_sym)
|
614
|
-
inner_object[@method_sym]
|
615
|
-
else
|
616
|
-
inner_object[@method_str]
|
617
|
-
end
|
618
|
-
elsif obj.object.respond_to?(@method_sym)
|
619
|
-
if ruby_kwargs.any?
|
620
|
-
obj.object.public_send(@method_sym, **ruby_kwargs)
|
621
|
-
else
|
622
|
-
obj.object.public_send(@method_sym)
|
623
|
-
end
|
624
|
-
else
|
625
|
-
raise <<-ERR
|
626
|
-
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
627
|
-
|
628
|
-
- `#{obj.class}##{@resolver_method}`, which did not exist
|
629
|
-
- `#{obj.object.class}##{@method_sym}`, which did not exist
|
630
|
-
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
|
631
|
-
|
632
|
-
To implement this field, define one of the methods above (and check for typos)
|
633
|
-
ERR
|
634
|
-
end
|
635
|
-
end
|
636
|
-
|
637
595
|
# @param ctx [GraphQL::Query::Context::FieldResolutionContext]
|
638
596
|
def fetch_extra(extra_name, ctx)
|
639
597
|
if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
|
@@ -704,24 +662,52 @@ module GraphQL
|
|
704
662
|
end
|
705
663
|
end
|
706
664
|
|
707
|
-
def public_send_field(
|
708
|
-
query_ctx
|
709
|
-
with_extensions(obj, ruby_kwargs, query_ctx) do |extended_obj, extended_args|
|
665
|
+
def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
|
666
|
+
with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
|
710
667
|
if @resolver_class
|
711
|
-
if
|
712
|
-
|
668
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
669
|
+
obj = obj.object
|
713
670
|
end
|
714
|
-
|
671
|
+
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
715
672
|
end
|
716
673
|
|
717
|
-
|
718
|
-
|
719
|
-
|
674
|
+
# Find a way to resolve this field, checking:
|
675
|
+
#
|
676
|
+
# - A method on the type instance;
|
677
|
+
# - Hash keys, if the wrapped object is a hash;
|
678
|
+
# - A method on the wrapped object;
|
679
|
+
# - Or, raise not implemented.
|
680
|
+
#
|
681
|
+
if obj.respond_to?(@resolver_method)
|
682
|
+
# Call the method with kwargs, if there are any
|
683
|
+
if ruby_kwargs.any?
|
684
|
+
obj.public_send(@resolver_method, **ruby_kwargs)
|
685
|
+
else
|
686
|
+
obj.public_send(@resolver_method)
|
687
|
+
end
|
688
|
+
elsif obj.object.is_a?(Hash)
|
689
|
+
inner_object = obj.object
|
690
|
+
if inner_object.key?(@method_sym)
|
691
|
+
inner_object[@method_sym]
|
720
692
|
else
|
721
|
-
|
693
|
+
inner_object[@method_str]
|
694
|
+
end
|
695
|
+
elsif obj.object.respond_to?(@method_sym)
|
696
|
+
if ruby_kwargs.any?
|
697
|
+
obj.object.public_send(@method_sym, **ruby_kwargs)
|
698
|
+
else
|
699
|
+
obj.object.public_send(@method_sym)
|
722
700
|
end
|
723
701
|
else
|
724
|
-
|
702
|
+
raise <<-ERR
|
703
|
+
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
704
|
+
|
705
|
+
- `#{obj.class}##{@resolver_method}`, which did not exist
|
706
|
+
- `#{obj.object.class}##{@method_sym}`, which did not exist
|
707
|
+
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
|
708
|
+
|
709
|
+
To implement this field, define one of the methods above (and check for typos)
|
710
|
+
ERR
|
725
711
|
end
|
726
712
|
end
|
727
713
|
end
|
@@ -22,39 +22,49 @@ module GraphQL
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def after_resolve(value:, object:, arguments:, context:, memo:)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
value.
|
35
|
-
|
36
|
-
value.
|
37
|
-
|
38
|
-
|
39
|
-
value.
|
25
|
+
# rename some inputs to avoid conflicts inside the block
|
26
|
+
maybe_lazy = value
|
27
|
+
value = nil
|
28
|
+
context.schema.after_lazy(maybe_lazy) do |resolved_value|
|
29
|
+
value = resolved_value
|
30
|
+
if value.is_a? GraphQL::ExecutionError
|
31
|
+
# This isn't even going to work because context doesn't have ast_node anymore
|
32
|
+
context.add_error(value)
|
33
|
+
nil
|
34
|
+
elsif value.nil?
|
35
|
+
nil
|
36
|
+
elsif value.is_a?(GraphQL::Pagination::Connection)
|
37
|
+
# update the connection with some things that may not have been provided
|
38
|
+
value.context ||= context
|
39
|
+
value.parent ||= object.object
|
40
|
+
value.first_value ||= arguments[:first]
|
41
|
+
value.after_value ||= arguments[:after]
|
42
|
+
value.last_value ||= arguments[:last]
|
43
|
+
value.before_value ||= arguments[:before]
|
44
|
+
if field.has_max_page_size? && !value.has_max_page_size_override?
|
45
|
+
value.max_page_size = field.max_page_size
|
46
|
+
end
|
47
|
+
if (custom_t = context.schema.connections.edge_class_for_field(@field))
|
48
|
+
value.edge_class = custom_t
|
49
|
+
end
|
50
|
+
value
|
51
|
+
elsif context.schema.new_connections?
|
52
|
+
wrappers = context.namespace(:connections)[:all_wrappers] ||= context.schema.connections.all_wrappers
|
53
|
+
context.schema.connections.wrap(field, object.object, value, arguments, context, wrappers: wrappers)
|
54
|
+
else
|
55
|
+
if object.is_a?(GraphQL::Schema::Object)
|
56
|
+
object = object.object
|
57
|
+
end
|
58
|
+
connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(value)
|
59
|
+
connection_class.new(
|
60
|
+
value,
|
61
|
+
arguments,
|
62
|
+
field: field,
|
63
|
+
max_page_size: field.max_page_size,
|
64
|
+
parent: object,
|
65
|
+
context: context,
|
66
|
+
)
|
40
67
|
end
|
41
|
-
value
|
42
|
-
elsif context.schema.new_connections?
|
43
|
-
wrappers = context.namespace(:connections)[:all_wrappers] ||= context.schema.connections.all_wrappers
|
44
|
-
context.schema.connections.wrap(field, value, arguments, context, wrappers: wrappers)
|
45
|
-
else
|
46
|
-
if object.is_a?(GraphQL::Schema::Object)
|
47
|
-
object = object.object
|
48
|
-
end
|
49
|
-
connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(value)
|
50
|
-
connection_class.new(
|
51
|
-
value,
|
52
|
-
arguments,
|
53
|
-
field: field,
|
54
|
-
max_page_size: field.max_page_size,
|
55
|
-
parent: object,
|
56
|
-
context: context,
|
57
|
-
)
|
58
68
|
end
|
59
69
|
end
|
60
70
|
end
|
@@ -25,8 +25,15 @@ module GraphQL
|
|
25
25
|
types[type["name"]] = type_object
|
26
26
|
end
|
27
27
|
|
28
|
+
directives = []
|
29
|
+
schema.fetch("directives", []).each do |directive|
|
30
|
+
next if GraphQL::Schema.default_directives.include?(directive.fetch("name"))
|
31
|
+
directives << define_directive(directive, type_resolver)
|
32
|
+
end
|
33
|
+
|
28
34
|
Class.new(GraphQL::Schema) do
|
29
35
|
orphan_types(types.values)
|
36
|
+
directives(directives)
|
30
37
|
|
31
38
|
def self.resolve_type(*)
|
32
39
|
raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
|
@@ -98,7 +105,7 @@ module GraphQL
|
|
98
105
|
value(
|
99
106
|
enum_value["name"],
|
100
107
|
description: enum_value["description"],
|
101
|
-
deprecation_reason: enum_value["
|
108
|
+
deprecation_reason: enum_value["deprecationReason"],
|
102
109
|
)
|
103
110
|
end
|
104
111
|
end
|
@@ -147,6 +154,16 @@ module GraphQL
|
|
147
154
|
end
|
148
155
|
end
|
149
156
|
|
157
|
+
def define_directive(directive, type_resolver)
|
158
|
+
loader = self
|
159
|
+
Class.new(GraphQL::Schema::Directive) do
|
160
|
+
graphql_name(directive["name"])
|
161
|
+
description(directive["description"])
|
162
|
+
locations(*directive["locations"].map(&:to_sym))
|
163
|
+
loader.build_arguments(self, directive["args"], type_resolver)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
150
167
|
public
|
151
168
|
|
152
169
|
def build_fields(type_defn, fields, type_resolver)
|
@@ -156,6 +173,7 @@ module GraphQL
|
|
156
173
|
field_hash["name"],
|
157
174
|
type: type_resolver.call(field_hash["type"]),
|
158
175
|
description: field_hash["description"],
|
176
|
+
deprecation_reason: field_hash["deprecationReason"],
|
159
177
|
null: true,
|
160
178
|
camelize: false,
|
161
179
|
) do
|
@@ -60,7 +60,9 @@ module GraphQL
|
|
60
60
|
|
61
61
|
# @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
|
62
62
|
def get_argument(argument_name)
|
63
|
-
|
63
|
+
a = own_arguments[argument_name]
|
64
|
+
|
65
|
+
if a || !self.is_a?(Class)
|
64
66
|
a
|
65
67
|
else
|
66
68
|
for ancestor in ancestors
|
@@ -47,20 +47,22 @@ module GraphQL
|
|
47
47
|
# A list of GraphQL-Ruby keywords.
|
48
48
|
#
|
49
49
|
# @api private
|
50
|
-
GRAPHQL_RUBY_KEYWORDS = [:context, :object, :
|
50
|
+
GRAPHQL_RUBY_KEYWORDS = [:context, :object, :raw_value]
|
51
51
|
|
52
52
|
# A list of field names that we should advise users to pick a different
|
53
53
|
# resolve method name.
|
54
54
|
#
|
55
55
|
# @api private
|
56
|
-
CONFLICT_FIELD_NAMES = Set.new(GRAPHQL_RUBY_KEYWORDS + RUBY_KEYWORDS)
|
56
|
+
CONFLICT_FIELD_NAMES = Set.new(GRAPHQL_RUBY_KEYWORDS + RUBY_KEYWORDS + Object.instance_methods)
|
57
57
|
|
58
58
|
# Register this field with the class, overriding a previous one if needed.
|
59
59
|
# @param field_defn [GraphQL::Schema::Field]
|
60
60
|
# @return [void]
|
61
|
-
def add_field(field_defn)
|
62
|
-
|
63
|
-
|
61
|
+
def add_field(field_defn, method_conflict_warning: field_defn.method_conflict_warning?)
|
62
|
+
# Check that `field_defn.original_name` equals `resolver_method` and `method_sym` --
|
63
|
+
# that shows that no override value was given manually.
|
64
|
+
if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym
|
65
|
+
warn(conflict_field_name_warning(field_defn))
|
64
66
|
end
|
65
67
|
own_fields[field_defn.name] = field_defn
|
66
68
|
nil
|
@@ -92,6 +94,14 @@ module GraphQL
|
|
92
94
|
def own_fields
|
93
95
|
@own_fields ||= {}
|
94
96
|
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
# @param [GraphQL::Schema::Field]
|
101
|
+
# @return [String] A warning to give when this field definition might conflict with a built-in method
|
102
|
+
def conflict_field_name_warning(field_defn)
|
103
|
+
"#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
|
104
|
+
end
|
95
105
|
end
|
96
106
|
end
|
97
107
|
end
|
@@ -78,6 +78,10 @@ module GraphQL
|
|
78
78
|
|
79
79
|
private
|
80
80
|
|
81
|
+
def conflict_field_name_warning(field_defn)
|
82
|
+
"#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `hash_key:` or `method:` to pick a different resolve behavior for this field (for example, `hash_key: :#{field_defn.resolver_method}_value`, and modify the return hash). Or use `method_conflict_warning: false` to suppress this warning."
|
83
|
+
end
|
84
|
+
|
81
85
|
# Override this to attach self as `mutation`
|
82
86
|
def generate_payload_type
|
83
87
|
payload_class = super
|
@@ -74,7 +74,7 @@ module GraphQL
|
|
74
74
|
# Set up a type-specific invalid null error to use when this object's non-null fields wrongly return `nil`.
|
75
75
|
# It should help with debugging and bug tracker integrations.
|
76
76
|
def inherited(child_class)
|
77
|
-
child_class.const_set(:InvalidNullError,
|
77
|
+
child_class.const_set(:InvalidNullError, GraphQL::InvalidNullError.subclass_for(child_class))
|
78
78
|
super
|
79
79
|
end
|
80
80
|
|
@@ -40,6 +40,7 @@ module GraphQL
|
|
40
40
|
@arguments_by_keyword[arg.keyword] = arg
|
41
41
|
end
|
42
42
|
@arguments_loads_as_type = self.class.arguments_loads_as_type
|
43
|
+
@prepared_arguments = nil
|
43
44
|
end
|
44
45
|
|
45
46
|
# @return [Object] The application object this field is being resolved on
|
@@ -51,6 +52,10 @@ module GraphQL
|
|
51
52
|
# @return [GraphQL::Schema::Field]
|
52
53
|
attr_reader :field
|
53
54
|
|
55
|
+
def arguments
|
56
|
+
@prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
|
57
|
+
end
|
58
|
+
|
54
59
|
# This method is _actually_ called by the runtime,
|
55
60
|
# it does some preparation and then eventually calls
|
56
61
|
# the user-defined `#resolve` method.
|
@@ -74,6 +79,7 @@ module GraphQL
|
|
74
79
|
# for that argument, or may return a lazy object
|
75
80
|
load_arguments_val = load_arguments(args)
|
76
81
|
context.schema.after_lazy(load_arguments_val) do |loaded_args|
|
82
|
+
@prepared_arguments = loaded_args
|
77
83
|
# Then call `authorized?`, which may raise or may return a lazy object
|
78
84
|
authorized_val = if loaded_args.any?
|
79
85
|
authorized?(**loaded_args)
|
@@ -250,6 +256,19 @@ module GraphQL
|
|
250
256
|
@complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
|
251
257
|
end
|
252
258
|
|
259
|
+
def broadcastable(new_broadcastable)
|
260
|
+
@broadcastable = new_broadcastable
|
261
|
+
end
|
262
|
+
|
263
|
+
# @return [Boolean, nil]
|
264
|
+
def broadcastable?
|
265
|
+
if defined?(@broadcastable)
|
266
|
+
@broadcastable
|
267
|
+
else
|
268
|
+
(superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
253
272
|
def field_options
|
254
273
|
{
|
255
274
|
type: type_expr,
|
@@ -261,6 +280,7 @@ module GraphQL
|
|
261
280
|
null: null,
|
262
281
|
complexity: complexity,
|
263
282
|
extensions: extensions,
|
283
|
+
broadcastable: broadcastable?,
|
264
284
|
}
|
265
285
|
end
|
266
286
|
|