graphql 1.13.17 → 2.0.20
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +3 -17
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/graphql/analysis/ast/field_usage.rb +3 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +43 -36
- data/lib/graphql/analysis/ast.rb +2 -12
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/table.rb +2 -20
- data/lib/graphql/backtrace/tracer.rb +2 -3
- data/lib/graphql/backtrace.rb +2 -8
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/dataloader/source.rb +9 -0
- data/lib/graphql/dataloader.rb +4 -1
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/errors.rb +12 -82
- data/lib/graphql/execution/interpreter/resolve.rb +26 -0
- data/lib/graphql/execution/interpreter/runtime.rb +159 -120
- data/lib/graphql/execution/interpreter.rb +187 -78
- data/lib/graphql/execution/lazy.rb +7 -21
- data/lib/graphql/execution/lookahead.rb +44 -40
- data/lib/graphql/execution/multiplex.rb +3 -174
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +2 -15
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +13 -6
- data/lib/graphql/introspection.rb +4 -3
- data/lib/graphql/language/document_from_schema_definition.rb +18 -35
- data/lib/graphql/language/lexer.rb +216 -1488
- data/lib/graphql/language/nodes.rb +65 -39
- data/lib/graphql/language/parser.rb +376 -364
- data/lib/graphql/language/parser.y +49 -44
- data/lib/graphql/language/printer.rb +37 -21
- data/lib/graphql/language/visitor.rb +191 -83
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +4 -2
- data/lib/graphql/pagination/connection.rb +31 -4
- data/lib/graphql/pagination/connections.rb +3 -28
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/query/context.rb +155 -196
- data/lib/graphql/query/input_validation_result.rb +1 -1
- data/lib/graphql/query/null_context.rb +0 -3
- data/lib/graphql/query/validation_pipeline.rb +10 -34
- data/lib/graphql/query/variables.rb +7 -20
- data/lib/graphql/query.rb +32 -42
- data/lib/graphql/railtie.rb +0 -104
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +29 -1
- data/lib/graphql/relay/range_add.rb +9 -20
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/schema/addition.rb +7 -9
- data/lib/graphql/schema/argument.rb +36 -43
- data/lib/graphql/schema/build_from_definition.rb +32 -18
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +12 -23
- data/lib/graphql/schema/enum.rb +28 -39
- data/lib/graphql/schema/enum_value.rb +5 -25
- data/lib/graphql/schema/field/connection_extension.rb +4 -0
- data/lib/graphql/schema/field.rb +237 -339
- data/lib/graphql/schema/input_object.rb +56 -67
- data/lib/graphql/schema/interface.rb +0 -35
- data/lib/graphql/schema/introspection_system.rb +3 -8
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +0 -6
- data/lib/graphql/schema/loader.rb +1 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -19
- data/lib/graphql/schema/member/build_type.rb +5 -7
- data/lib/graphql/schema/member/has_arguments.rb +146 -55
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -59
- data/lib/graphql/schema/member/has_fields.rb +17 -4
- data/lib/graphql/schema/member/has_interfaces.rb +49 -10
- data/lib/graphql/schema/member/has_validators.rb +31 -5
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/member/validates_input.rb +1 -1
- data/lib/graphql/schema/member.rb +0 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +1 -7
- data/lib/graphql/schema/object.rb +15 -52
- data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
- data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
- data/lib/graphql/schema/resolver.rb +41 -42
- data/lib/graphql/schema/scalar.rb +7 -22
- data/lib/graphql/schema/subscription.rb +0 -7
- data/lib/graphql/schema/timeout.rb +24 -28
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +10 -17
- data/lib/graphql/schema/warden.rb +34 -8
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +241 -973
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +4 -21
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/error.rb +2 -2
- data/lib/graphql/static_validation/literal_validator.rb +19 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +3 -25
- data/lib/graphql/static_validation.rb +0 -2
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
- data/lib/graphql/subscriptions/event.rb +3 -8
- data/lib/graphql/subscriptions/instrumentation.rb +0 -51
- data/lib/graphql/subscriptions.rb +32 -20
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +231 -0
- data/lib/graphql/tracing/appsignal_trace.rb +71 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +41 -0
- data/lib/graphql/tracing/platform_trace.rb +107 -0
- data/lib/graphql/tracing/platform_tracing.rb +26 -40
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing.rb +136 -40
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/iso_8601_date.rb +4 -1
- data/lib/graphql/types/iso_8601_date_time.rb +4 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +29 -27
- data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +13 -74
- metadata +30 -133
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -232
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -255
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -55
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -107
- data/lib/graphql/enum_type.rb +0 -133
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -260
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -54
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -39
- data/lib/graphql/relay/global_id_resolve.rb +0 -17
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/member/accepts_definition.rb +0 -164
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -31
- data/lib/graphql/types/relay/node_field.rb +0 -24
- data/lib/graphql/types/relay/nodes_field.rb +0 -43
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
data/lib/graphql/schema/field.rb
CHANGED
@@ -5,9 +5,8 @@ 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
|
9
|
+
include GraphQL::Schema::Member::HasArguments::FieldConfigured
|
11
10
|
include GraphQL::Schema::Member::HasAstNode
|
12
11
|
include GraphQL::Schema::Member::HasPath
|
13
12
|
include GraphQL::Schema::Member::HasValidators
|
@@ -30,8 +29,17 @@ module GraphQL
|
|
30
29
|
# @return [String] Method or hash key on the underlying object to look up
|
31
30
|
attr_reader :method_str
|
32
31
|
|
32
|
+
attr_reader :hash_key
|
33
|
+
attr_reader :dig_keys
|
34
|
+
|
33
35
|
# @return [Symbol] The method on the type to look up
|
34
|
-
|
36
|
+
def resolver_method
|
37
|
+
if @resolver_class
|
38
|
+
@resolver_class.resolver_method
|
39
|
+
else
|
40
|
+
@resolver_method
|
41
|
+
end
|
42
|
+
end
|
35
43
|
|
36
44
|
# @return [Class] The thing this field was defined on (type, mutation, resolver)
|
37
45
|
attr_accessor :owner
|
@@ -70,7 +78,10 @@ module GraphQL
|
|
70
78
|
attr_reader :trace
|
71
79
|
|
72
80
|
# @return [String, nil]
|
73
|
-
|
81
|
+
def subscription_scope
|
82
|
+
@subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
|
83
|
+
end
|
84
|
+
attr_writer :subscription_scope
|
74
85
|
|
75
86
|
# Create a field instance from a list of arguments, keyword arguments, and a block.
|
76
87
|
#
|
@@ -84,21 +95,9 @@ module GraphQL
|
|
84
95
|
# @return [GraphQL::Schema:Field] an instance of `self
|
85
96
|
# @see {.initialize} for other options
|
86
97
|
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
87
|
-
if
|
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)
|
98
|
+
if (resolver_class = resolver || mutation || subscription)
|
100
99
|
# Add a reference to that parent class
|
101
|
-
kwargs[:resolver_class] =
|
100
|
+
kwargs[:resolver_class] = resolver_class
|
102
101
|
end
|
103
102
|
|
104
103
|
if name
|
@@ -106,9 +105,6 @@ module GraphQL
|
|
106
105
|
end
|
107
106
|
|
108
107
|
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
108
|
if desc
|
113
109
|
if kwargs[:description]
|
114
110
|
raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
|
@@ -116,8 +112,8 @@ module GraphQL
|
|
116
112
|
|
117
113
|
kwargs[:description] = desc
|
118
114
|
kwargs[:type] = type
|
119
|
-
elsif (
|
120
|
-
# The return type should be copied from
|
115
|
+
elsif (resolver || mutation) && type.is_a?(String)
|
116
|
+
# The return type should be copied from the resolver, and the second positional argument is the description
|
121
117
|
kwargs[:description] = type
|
122
118
|
else
|
123
119
|
kwargs[:type] = type
|
@@ -134,10 +130,10 @@ module GraphQL
|
|
134
130
|
def connection?
|
135
131
|
if @connection.nil?
|
136
132
|
# Provide default based on type name
|
137
|
-
return_type_name = if
|
138
|
-
Member::BuildType.to_type_name(contains_type.type)
|
139
|
-
elsif @return_type_expr
|
133
|
+
return_type_name = if @return_type_expr
|
140
134
|
Member::BuildType.to_type_name(@return_type_expr)
|
135
|
+
elsif @resolver_class && @resolver_class.type
|
136
|
+
Member::BuildType.to_type_name(@resolver_class.type)
|
141
137
|
else
|
142
138
|
# As a last ditch, try to force loading the return type:
|
143
139
|
type.unwrap.name
|
@@ -153,8 +149,18 @@ module GraphQL
|
|
153
149
|
if !@scope.nil?
|
154
150
|
# The default was overridden
|
155
151
|
@scope
|
152
|
+
elsif @return_type_expr
|
153
|
+
# Detect a list return type, but don't call `type` since that may eager-load an otherwise lazy-loaded type
|
154
|
+
@return_type_expr.is_a?(Array) ||
|
155
|
+
(@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) ||
|
156
|
+
connection?
|
157
|
+
elsif @resolver_class
|
158
|
+
resolver_type = @resolver_class.type_expr
|
159
|
+
resolver_type.is_a?(Array) ||
|
160
|
+
(resolver_type.is_a?(String) && resolver_type.include?("[")) ||
|
161
|
+
connection?
|
156
162
|
else
|
157
|
-
|
163
|
+
false
|
158
164
|
end
|
159
165
|
end
|
160
166
|
|
@@ -187,7 +193,7 @@ module GraphQL
|
|
187
193
|
# @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
|
188
194
|
# @param type [Class, GraphQL::BaseType, Array] The return type of this field
|
189
195
|
# @param owner [Class] The type that this field belongs to
|
190
|
-
# @param null [Boolean] `true` if this field may return `null`, `false` if it is never `null`
|
196
|
+
# @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
|
191
197
|
# @param description [String] Field description
|
192
198
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
193
199
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
@@ -197,10 +203,8 @@ module GraphQL
|
|
197
203
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
198
204
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
199
205
|
# @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
|
206
|
+
# @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
|
200
207
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
201
|
-
# @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
|
202
|
-
# @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
|
203
|
-
# @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
|
204
208
|
# @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
|
205
209
|
# @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
|
206
210
|
# @param camelize [Boolean] If true, the field name will be camelized when building the schema
|
@@ -214,31 +218,25 @@ module GraphQL
|
|
214
218
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
215
219
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
216
220
|
# @param validates [Array<Hash>] Configurations for validating this field
|
217
|
-
# @
|
218
|
-
def initialize(type: nil, name: nil, owner: nil, null:
|
221
|
+
# @fallback_value [Object] A fallback value if the method is not defined
|
222
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, 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: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: :not_given, &definition_block)
|
219
223
|
if name.nil?
|
220
224
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
221
225
|
end
|
222
|
-
if !(
|
226
|
+
if !(resolver_class)
|
223
227
|
if type.nil?
|
224
228
|
raise ArgumentError, "missing second `type` argument or keyword `type:`"
|
225
229
|
end
|
226
230
|
end
|
227
|
-
if (field || function || resolve) && extras.any?
|
228
|
-
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:`"
|
229
|
-
end
|
230
231
|
@original_name = name
|
231
232
|
name_s = -name.to_s
|
233
|
+
|
232
234
|
@underscored_name = -Member::BuildType.underscore(name_s)
|
233
235
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
236
|
+
|
234
237
|
@description = description
|
235
|
-
if
|
236
|
-
|
237
|
-
else
|
238
|
-
@field = field
|
239
|
-
end
|
240
|
-
@function = function
|
241
|
-
@resolve = resolve
|
238
|
+
@type = @owner_type = @own_validators = @own_directives = @own_arguments = nil # these will be prepared later if necessary
|
239
|
+
|
242
240
|
self.deprecation_reason = deprecation_reason
|
243
241
|
|
244
242
|
if method && hash_key && dig
|
@@ -255,20 +253,31 @@ module GraphQL
|
|
255
253
|
end
|
256
254
|
end
|
257
255
|
|
258
|
-
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
259
256
|
method_name = method || hash_key || name_s
|
260
257
|
@dig_keys = dig
|
261
|
-
|
258
|
+
if hash_key
|
259
|
+
@hash_key = hash_key
|
260
|
+
@hash_key_str = hash_key.to_s
|
261
|
+
else
|
262
|
+
@hash_key = NOT_CONFIGURED
|
263
|
+
@hash_key_str = NOT_CONFIGURED
|
264
|
+
end
|
262
265
|
|
263
266
|
@method_str = -method_name.to_s
|
264
267
|
@method_sym = method_name.to_sym
|
265
|
-
@resolver_method = resolver_method
|
268
|
+
@resolver_method = (resolver_method || name_s).to_sym
|
266
269
|
@complexity = complexity
|
267
270
|
@return_type_expr = type
|
268
|
-
@return_type_null = null
|
271
|
+
@return_type_null = if !null.nil?
|
272
|
+
null
|
273
|
+
elsif resolver_class
|
274
|
+
nil
|
275
|
+
else
|
276
|
+
true
|
277
|
+
end
|
269
278
|
@connection = connection
|
270
|
-
@
|
271
|
-
@
|
279
|
+
@max_page_size = max_page_size
|
280
|
+
@default_page_size = default_page_size
|
272
281
|
@introspection = introspection
|
273
282
|
@extras = extras
|
274
283
|
@broadcastable = broadcastable
|
@@ -279,7 +288,7 @@ module GraphQL
|
|
279
288
|
@relay_nodes_field = relay_nodes_field
|
280
289
|
@ast_node = ast_node
|
281
290
|
@method_conflict_warning = method_conflict_warning
|
282
|
-
@
|
291
|
+
@fallback_value = fallback_value
|
283
292
|
|
284
293
|
arguments.each do |name, arg|
|
285
294
|
case arg
|
@@ -316,13 +325,19 @@ module GraphQL
|
|
316
325
|
self.extensions(extensions)
|
317
326
|
end
|
318
327
|
|
328
|
+
if resolver_class && resolver_class.extensions.any?
|
329
|
+
self.extensions(resolver_class.extensions)
|
330
|
+
end
|
331
|
+
|
319
332
|
if directives.any?
|
320
333
|
directives.each do |(dir_class, options)|
|
321
334
|
self.directive(dir_class, **options)
|
322
335
|
end
|
323
336
|
end
|
324
337
|
|
325
|
-
|
338
|
+
if !validates.empty?
|
339
|
+
self.validates(validates)
|
340
|
+
end
|
326
341
|
|
327
342
|
if definition_block
|
328
343
|
if definition_block.arity == 1
|
@@ -340,7 +355,13 @@ module GraphQL
|
|
340
355
|
# @return [Boolean, nil]
|
341
356
|
# @see GraphQL::Subscriptions::BroadcastAnalyzer
|
342
357
|
def broadcastable?
|
343
|
-
@broadcastable
|
358
|
+
if !NOT_CONFIGURED.equal?(@broadcastable)
|
359
|
+
@broadcastable
|
360
|
+
elsif @resolver_class
|
361
|
+
@resolver_class.broadcastable?
|
362
|
+
else
|
363
|
+
nil
|
364
|
+
end
|
344
365
|
end
|
345
366
|
|
346
367
|
# @param text [String]
|
@@ -348,8 +369,12 @@ module GraphQL
|
|
348
369
|
def description(text = nil)
|
349
370
|
if text
|
350
371
|
@description = text
|
351
|
-
|
372
|
+
elsif !NOT_CONFIGURED.equal?(@description)
|
352
373
|
@description
|
374
|
+
elsif @resolver_class
|
375
|
+
@resolver_class.description
|
376
|
+
else
|
377
|
+
nil
|
353
378
|
end
|
354
379
|
end
|
355
380
|
|
@@ -413,7 +438,12 @@ module GraphQL
|
|
413
438
|
def extras(new_extras = nil)
|
414
439
|
if new_extras.nil?
|
415
440
|
# Read the value
|
416
|
-
@extras
|
441
|
+
field_extras = @extras
|
442
|
+
if @resolver_class && @resolver_class.extras.any?
|
443
|
+
field_extras + @resolver_class.extras
|
444
|
+
else
|
445
|
+
field_extras
|
446
|
+
end
|
417
447
|
else
|
418
448
|
if @extras.frozen?
|
419
449
|
@extras = @extras.dup
|
@@ -441,11 +471,11 @@ module GraphQL
|
|
441
471
|
end
|
442
472
|
|
443
473
|
if max_possible_page_size.nil?
|
444
|
-
max_possible_page_size = max_page_size || query.schema.default_max_page_size
|
474
|
+
max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
|
445
475
|
end
|
446
476
|
|
447
477
|
if max_possible_page_size.nil?
|
448
|
-
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `max_page_size` or `default_max_page_size`"
|
478
|
+
raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
|
449
479
|
else
|
450
480
|
metadata_complexity = 0
|
451
481
|
lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
|
@@ -502,7 +532,11 @@ module GraphQL
|
|
502
532
|
when Numeric
|
503
533
|
@complexity = new_complexity
|
504
534
|
when nil
|
505
|
-
@
|
535
|
+
if @resolver_class
|
536
|
+
@complexity || @resolver_class.complexity || 1
|
537
|
+
else
|
538
|
+
@complexity || 1
|
539
|
+
end
|
506
540
|
else
|
507
541
|
raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
|
508
542
|
end
|
@@ -510,105 +544,49 @@ module GraphQL
|
|
510
544
|
|
511
545
|
# @return [Boolean] True if this field's {#max_page_size} should override the schema default.
|
512
546
|
def has_max_page_size?
|
513
|
-
@has_max_page_size
|
547
|
+
!NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
|
514
548
|
end
|
515
549
|
|
516
550
|
# @return [Integer, nil] Applied to connections if {#has_max_page_size?}
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
def to_graphql
|
523
|
-
field_defn = if @field
|
524
|
-
@field.dup
|
525
|
-
elsif @function
|
526
|
-
GraphQL::Function.build_field(@function)
|
551
|
+
def max_page_size
|
552
|
+
if !NOT_CONFIGURED.equal?(@max_page_size)
|
553
|
+
@max_page_size
|
554
|
+
elsif @resolver_class && @resolver_class.has_max_page_size?
|
555
|
+
@resolver_class.max_page_size
|
527
556
|
else
|
528
|
-
|
529
|
-
end
|
530
|
-
|
531
|
-
field_defn.name = @name
|
532
|
-
if @return_type_expr
|
533
|
-
field_defn.type = -> { type }
|
557
|
+
nil
|
534
558
|
end
|
559
|
+
end
|
535
560
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
if self.deprecation_reason
|
541
|
-
field_defn.deprecation_reason = self.deprecation_reason
|
542
|
-
end
|
543
|
-
|
544
|
-
if @resolver_class
|
545
|
-
if @resolver_class < GraphQL::Schema::Mutation
|
546
|
-
field_defn.mutation = @resolver_class
|
547
|
-
end
|
548
|
-
field_defn.metadata[:resolver] = @resolver_class
|
549
|
-
end
|
550
|
-
|
551
|
-
if !@trace.nil?
|
552
|
-
field_defn.trace = @trace
|
553
|
-
end
|
554
|
-
|
555
|
-
if @relay_node_field
|
556
|
-
field_defn.relay_node_field = @relay_node_field
|
557
|
-
end
|
558
|
-
|
559
|
-
if @relay_nodes_field
|
560
|
-
field_defn.relay_nodes_field = @relay_nodes_field
|
561
|
-
end
|
562
|
-
|
563
|
-
if @legacy_edge_class
|
564
|
-
field_defn.edge_class = @legacy_edge_class
|
565
|
-
end
|
566
|
-
|
567
|
-
field_defn.resolve = self.method(:resolve_field)
|
568
|
-
field_defn.connection = connection?
|
569
|
-
field_defn.connection_max_page_size = max_page_size
|
570
|
-
field_defn.introspection = @introspection
|
571
|
-
field_defn.complexity = @complexity
|
572
|
-
field_defn.subscription_scope = @subscription_scope
|
573
|
-
field_defn.ast_node = ast_node
|
574
|
-
|
575
|
-
all_argument_definitions.each do |defn|
|
576
|
-
arg_graphql = defn.deprecated_to_graphql
|
577
|
-
field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
578
|
-
end
|
561
|
+
# @return [Boolean] True if this field's {#default_page_size} should override the schema default.
|
562
|
+
def has_default_page_size?
|
563
|
+
!NOT_CONFIGURED.equal?(@default_page_size) || (@resolver_class && @resolver_class.has_default_page_size?)
|
564
|
+
end
|
579
565
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
566
|
+
# @return [Integer, nil] Applied to connections if {#has_default_page_size?}
|
567
|
+
def default_page_size
|
568
|
+
if !NOT_CONFIGURED.equal?(@default_page_size)
|
569
|
+
@default_page_size
|
570
|
+
elsif @resolver_class && @resolver_class.has_default_page_size?
|
571
|
+
@resolver_class.default_page_size
|
572
|
+
else
|
573
|
+
nil
|
587
574
|
end
|
588
|
-
|
589
|
-
# Ok, `self` isn't a class, but this is for consistency with the classes
|
590
|
-
field_defn.metadata[:type_class] = self
|
591
|
-
field_defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(field_defn)
|
592
|
-
field_defn
|
593
575
|
end
|
594
576
|
|
595
577
|
class MissingReturnTypeError < GraphQL::Error; end
|
596
578
|
attr_writer :type
|
597
579
|
|
598
580
|
def type
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
elsif @return_type_expr.nil?
|
604
|
-
# Not enough info to determine type
|
605
|
-
message = "Can't determine the return type for #{self.path}"
|
606
|
-
if @resolver_class
|
607
|
-
message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
|
581
|
+
if @resolver_class
|
582
|
+
return_type = @return_type_expr || @resolver_class.type_expr
|
583
|
+
if return_type.nil?
|
584
|
+
raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
|
608
585
|
end
|
609
|
-
|
586
|
+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
587
|
+
Member::BuildType.parse_type(return_type, null: nullable)
|
610
588
|
else
|
611
|
-
Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
589
|
+
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
612
590
|
end
|
613
591
|
rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
|
614
592
|
# Let this propagate up
|
@@ -625,14 +603,6 @@ module GraphQL
|
|
625
603
|
end
|
626
604
|
end
|
627
605
|
|
628
|
-
def accessible?(context)
|
629
|
-
if @resolver_class
|
630
|
-
@resolver_class.accessible?(context)
|
631
|
-
else
|
632
|
-
true
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
606
|
def authorized?(object, args, context)
|
637
607
|
if @resolver_class
|
638
608
|
# The resolver _instance_ will check itself during `resolve()`
|
@@ -646,62 +616,33 @@ module GraphQL
|
|
646
616
|
arg_values = args
|
647
617
|
using_arg_values = false
|
648
618
|
end
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
if
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
application_arg_value.
|
619
|
+
if args.size > 0
|
620
|
+
args = context.warden.arguments(self)
|
621
|
+
args.each do |arg|
|
622
|
+
arg_key = arg.keyword
|
623
|
+
if arg_values.key?(arg_key)
|
624
|
+
arg_value = arg_values[arg_key]
|
625
|
+
if using_arg_values
|
626
|
+
if arg_value.default_used?
|
627
|
+
# pass -- no auth required for default used
|
628
|
+
next
|
629
|
+
else
|
630
|
+
application_arg_value = arg_value.value
|
631
|
+
if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
|
632
|
+
application_arg_value.keyword_arguments
|
633
|
+
end
|
662
634
|
end
|
635
|
+
else
|
636
|
+
application_arg_value = arg_value
|
663
637
|
end
|
664
|
-
else
|
665
|
-
application_arg_value = arg_value
|
666
|
-
end
|
667
|
-
|
668
|
-
if !arg.authorized?(object, application_arg_value, context)
|
669
|
-
return false
|
670
|
-
end
|
671
|
-
end
|
672
|
-
end
|
673
|
-
true
|
674
|
-
end
|
675
|
-
end
|
676
638
|
|
677
|
-
|
678
|
-
|
679
|
-
# Eventually, we might hook up field instances to execution in another way. TBD.
|
680
|
-
# @see #resolve for how the interpreter hooks up to it
|
681
|
-
def resolve_field(obj, args, ctx)
|
682
|
-
ctx.schema.after_lazy(obj) do |after_obj|
|
683
|
-
# First, apply auth ...
|
684
|
-
query_ctx = ctx.query.context
|
685
|
-
# Some legacy fields can have `nil` here, not exactly sure why.
|
686
|
-
# @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
|
687
|
-
inner_obj = after_obj && after_obj.object
|
688
|
-
ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
|
689
|
-
if authorized?(inner_obj, ruby_args, query_ctx)
|
690
|
-
# Then if it passed, resolve the field
|
691
|
-
if @resolve_proc
|
692
|
-
# Might be nil, still want to call the func in that case
|
693
|
-
with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
|
694
|
-
# Pass the GraphQL args here for compatibility:
|
695
|
-
@resolve_proc.call(extended_obj, args, ctx)
|
639
|
+
if !arg.authorized?(object, application_arg_value, context)
|
640
|
+
return false
|
696
641
|
end
|
697
|
-
else
|
698
|
-
public_send_field(after_obj, ruby_args, query_ctx)
|
699
642
|
end
|
700
|
-
else
|
701
|
-
err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
|
702
|
-
query_ctx.schema.unauthorized_field(err)
|
703
643
|
end
|
704
644
|
end
|
645
|
+
true
|
705
646
|
end
|
706
647
|
end
|
707
648
|
|
@@ -710,34 +651,112 @@ module GraphQL
|
|
710
651
|
# @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
|
711
652
|
# @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
|
712
653
|
# @param ctx [GraphQL::Query::Context]
|
713
|
-
def resolve(object, args,
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
654
|
+
def resolve(object, args, query_ctx)
|
655
|
+
# Unwrap the GraphQL object to get the application object.
|
656
|
+
application_object = object.object
|
657
|
+
method_receiver = nil
|
658
|
+
method_to_call = nil
|
659
|
+
method_args = nil
|
660
|
+
|
661
|
+
Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
662
|
+
|
663
|
+
query_ctx.schema.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
|
664
|
+
if is_authorized
|
665
|
+
with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
|
666
|
+
method_args = ruby_kwargs
|
667
|
+
if @resolver_class
|
668
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
669
|
+
obj = obj.object
|
670
|
+
end
|
671
|
+
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
672
|
+
end
|
720
673
|
|
721
|
-
|
674
|
+
inner_object = obj.object
|
722
675
|
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
676
|
+
if !NOT_CONFIGURED.equal?(@hash_key)
|
677
|
+
hash_value = if inner_object.is_a?(Hash)
|
678
|
+
inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
|
679
|
+
elsif inner_object.respond_to?(:[])
|
680
|
+
inner_object[@hash_key]
|
681
|
+
else
|
682
|
+
nil
|
683
|
+
end
|
684
|
+
if hash_value == false
|
685
|
+
hash_value
|
686
|
+
else
|
687
|
+
hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
|
688
|
+
end
|
689
|
+
elsif obj.respond_to?(resolver_method)
|
690
|
+
method_to_call = resolver_method
|
691
|
+
method_receiver = obj
|
692
|
+
# Call the method with kwargs, if there are any
|
693
|
+
if ruby_kwargs.any?
|
694
|
+
obj.public_send(resolver_method, **ruby_kwargs)
|
695
|
+
else
|
696
|
+
obj.public_send(resolver_method)
|
697
|
+
end
|
698
|
+
elsif inner_object.is_a?(Hash)
|
699
|
+
if @dig_keys
|
700
|
+
inner_object.dig(*@dig_keys)
|
701
|
+
elsif inner_object.key?(@method_sym)
|
702
|
+
inner_object[@method_sym]
|
703
|
+
elsif inner_object.key?(@method_str)
|
704
|
+
inner_object[@method_str]
|
705
|
+
elsif @fallback_value != :not_given
|
706
|
+
@fallback_value
|
707
|
+
else
|
708
|
+
nil
|
709
|
+
end
|
710
|
+
elsif inner_object.respond_to?(@method_sym)
|
711
|
+
method_to_call = @method_sym
|
712
|
+
method_receiver = obj.object
|
713
|
+
if ruby_kwargs.any?
|
714
|
+
inner_object.public_send(@method_sym, **ruby_kwargs)
|
715
|
+
else
|
716
|
+
inner_object.public_send(@method_sym)
|
717
|
+
end
|
718
|
+
elsif @fallback_value != :not_given
|
719
|
+
@fallback_value
|
720
|
+
else
|
721
|
+
raise <<-ERR
|
722
|
+
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
723
|
+
|
724
|
+
- `#{obj.class}##{resolver_method}`, which did not exist
|
725
|
+
- `#{inner_object.class}##{@method_sym}`, which did not exist
|
726
|
+
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
|
727
|
+
|
728
|
+
To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
|
729
|
+
ERR
|
730
|
+
end
|
728
731
|
end
|
732
|
+
else
|
733
|
+
raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
|
729
734
|
end
|
730
|
-
rescue GraphQL::UnauthorizedFieldError => err
|
731
|
-
err.field ||= self
|
732
|
-
ctx.schema.unauthorized_field(err)
|
733
|
-
rescue GraphQL::UnauthorizedError => err
|
734
|
-
ctx.schema.unauthorized_object(err)
|
735
735
|
end
|
736
|
+
rescue GraphQL::UnauthorizedFieldError => err
|
737
|
+
err.field ||= self
|
738
|
+
begin
|
739
|
+
query_ctx.schema.unauthorized_field(err)
|
740
|
+
rescue GraphQL::ExecutionError => err
|
741
|
+
err
|
742
|
+
end
|
743
|
+
rescue GraphQL::UnauthorizedError => err
|
744
|
+
begin
|
745
|
+
query_ctx.schema.unauthorized_object(err)
|
746
|
+
rescue GraphQL::ExecutionError => err
|
747
|
+
err
|
748
|
+
end
|
749
|
+
rescue ArgumentError
|
750
|
+
if method_receiver && method_to_call
|
751
|
+
assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
|
752
|
+
end
|
753
|
+
# if the line above doesn't raise, re-raise
|
754
|
+
raise
|
736
755
|
rescue GraphQL::ExecutionError => err
|
737
756
|
err
|
738
757
|
end
|
739
758
|
|
740
|
-
# @param ctx [GraphQL::Query::Context
|
759
|
+
# @param ctx [GraphQL::Query::Context]
|
741
760
|
def fetch_extra(extra_name, ctx)
|
742
761
|
if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
|
743
762
|
self.public_send(extra_name)
|
@@ -750,127 +769,6 @@ module GraphQL
|
|
750
769
|
|
751
770
|
private
|
752
771
|
|
753
|
-
NO_ARGS = {}.freeze
|
754
|
-
|
755
|
-
# Convert a GraphQL arguments instance into a Ruby-style hash.
|
756
|
-
#
|
757
|
-
# @param obj [GraphQL::Schema::Object] The object where this field is being resolved
|
758
|
-
# @param graphql_args [GraphQL::Query::Arguments]
|
759
|
-
# @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
|
760
|
-
# @return [Hash<Symbol => Any>]
|
761
|
-
def to_ruby_args(obj, graphql_args, field_ctx)
|
762
|
-
if graphql_args.any? || @extras.any?
|
763
|
-
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
764
|
-
ruby_kwargs = graphql_args.to_kwargs
|
765
|
-
maybe_lazies = []
|
766
|
-
# Apply any `prepare` methods. Not great code organization, can this go somewhere better?
|
767
|
-
arguments(field_ctx).each do |name, arg_defn|
|
768
|
-
ruby_kwargs_key = arg_defn.keyword
|
769
|
-
|
770
|
-
if ruby_kwargs.key?(ruby_kwargs_key)
|
771
|
-
loads = arg_defn.loads
|
772
|
-
value = ruby_kwargs[ruby_kwargs_key]
|
773
|
-
loaded_value = if loads && !arg_defn.from_resolver?
|
774
|
-
if arg_defn.type.list?
|
775
|
-
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
|
776
|
-
field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
|
777
|
-
else
|
778
|
-
load_application_object(arg_defn, loads, value, field_ctx.query.context)
|
779
|
-
end
|
780
|
-
elsif arg_defn.type.list? && value.is_a?(Array)
|
781
|
-
field_ctx.schema.after_any_lazies(value, &:itself)
|
782
|
-
else
|
783
|
-
value
|
784
|
-
end
|
785
|
-
|
786
|
-
maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
|
787
|
-
prepared_value = if arg_defn.prepare
|
788
|
-
arg_defn.prepare_value(obj, loaded_value)
|
789
|
-
else
|
790
|
-
loaded_value
|
791
|
-
end
|
792
|
-
|
793
|
-
ruby_kwargs[ruby_kwargs_key] = prepared_value
|
794
|
-
end
|
795
|
-
end
|
796
|
-
end
|
797
|
-
|
798
|
-
@extras.each do |extra_arg|
|
799
|
-
ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
|
800
|
-
end
|
801
|
-
|
802
|
-
field_ctx.schema.after_any_lazies(maybe_lazies) do
|
803
|
-
ruby_kwargs
|
804
|
-
end
|
805
|
-
else
|
806
|
-
NO_ARGS
|
807
|
-
end
|
808
|
-
end
|
809
|
-
|
810
|
-
def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
|
811
|
-
with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
|
812
|
-
begin
|
813
|
-
method_receiver = nil
|
814
|
-
method_to_call = nil
|
815
|
-
if @resolver_class
|
816
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
817
|
-
obj = obj.object
|
818
|
-
end
|
819
|
-
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
820
|
-
end
|
821
|
-
|
822
|
-
# Find a way to resolve this field, checking:
|
823
|
-
#
|
824
|
-
# - A method on the type instance;
|
825
|
-
# - Hash keys, if the wrapped object is a hash;
|
826
|
-
# - A method on the wrapped object;
|
827
|
-
# - Or, raise not implemented.
|
828
|
-
#
|
829
|
-
if obj.respond_to?(@resolver_method)
|
830
|
-
method_to_call = @resolver_method
|
831
|
-
method_receiver = obj
|
832
|
-
# Call the method with kwargs, if there are any
|
833
|
-
if ruby_kwargs.any?
|
834
|
-
obj.public_send(@resolver_method, **ruby_kwargs)
|
835
|
-
else
|
836
|
-
obj.public_send(@resolver_method)
|
837
|
-
end
|
838
|
-
elsif obj.object.is_a?(Hash)
|
839
|
-
inner_object = obj.object
|
840
|
-
if @dig_keys
|
841
|
-
inner_object.dig(*@dig_keys)
|
842
|
-
elsif inner_object.key?(@method_sym)
|
843
|
-
inner_object[@method_sym]
|
844
|
-
else
|
845
|
-
inner_object[@method_str]
|
846
|
-
end
|
847
|
-
elsif obj.object.respond_to?(@method_sym)
|
848
|
-
method_to_call = @method_sym
|
849
|
-
method_receiver = obj.object
|
850
|
-
if ruby_kwargs.any?
|
851
|
-
obj.object.public_send(@method_sym, **ruby_kwargs)
|
852
|
-
else
|
853
|
-
obj.object.public_send(@method_sym)
|
854
|
-
end
|
855
|
-
else
|
856
|
-
raise <<-ERR
|
857
|
-
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
858
|
-
|
859
|
-
- `#{obj.class}##{@resolver_method}`, which did not exist
|
860
|
-
- `#{obj.object.class}##{@method_sym}`, which did not exist
|
861
|
-
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
|
862
|
-
|
863
|
-
To implement this field, define one of the methods above (and check for typos)
|
864
|
-
ERR
|
865
|
-
end
|
866
|
-
rescue ArgumentError
|
867
|
-
assert_satisfactory_implementation(method_receiver, method_to_call, ruby_kwargs)
|
868
|
-
# if the line above doesn't raise, re-raise
|
869
|
-
raise
|
870
|
-
end
|
871
|
-
end
|
872
|
-
end
|
873
|
-
|
874
772
|
def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
|
875
773
|
method_defn = receiver.method(method_name)
|
876
774
|
unsatisfied_ruby_kwargs = ruby_kwargs.dup
|
@@ -901,7 +799,7 @@ module GraphQL
|
|
901
799
|
|
902
800
|
if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
|
903
801
|
raise FieldImplementationFailed.new, <<-ERR
|
904
|
-
Failed to call
|
802
|
+
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
905
803
|
|
906
804
|
#{ unsatisfied_ruby_kwargs
|
907
805
|
.map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
|