graphql 1.13.12 → 2.0.21
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/trace.rb +96 -0
- data/lib/graphql/backtrace/tracer.rb +2 -3
- data/lib/graphql/backtrace.rb +7 -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/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
- data/lib/graphql/execution/interpreter/resolve.rb +26 -0
- data/lib/graphql/execution/interpreter/runtime.rb +300 -222
- 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/filter.rb +7 -2
- 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 +43 -44
- data/lib/graphql/language/lexer.rb +216 -1488
- data/lib/graphql/language/nodes.rb +66 -40
- data/lib/graphql/language/parser.rb +539 -510
- data/lib/graphql/language/parser.y +53 -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 +33 -6
- data/lib/graphql/pagination/connections.rb +3 -28
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/query/context.rb +156 -196
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +1 -4
- data/lib/graphql/query/validation_pipeline.rb +12 -37
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +35 -21
- data/lib/graphql/query.rb +39 -46
- 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 +38 -47
- data/lib/graphql/schema/build_from_definition.rb +47 -21
- 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 +29 -41
- data/lib/graphql/schema/enum_value.rb +2 -25
- data/lib/graphql/schema/field/connection_extension.rb +4 -0
- data/lib/graphql/schema/field.rb +256 -349
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/input_object.rb +57 -69
- 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 +18 -9
- 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 +147 -56
- 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 -61
- data/lib/graphql/schema/member/has_fields.rb +97 -40
- data/lib/graphql/schema/member/has_interfaces.rb +49 -10
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- 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 +3 -3
- data/lib/graphql/schema/member.rb +0 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +3 -9
- 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 +43 -44
- data/lib/graphql/schema/scalar.rb +8 -23
- 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/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +37 -9
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +265 -968
- 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/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
- 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 +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +21 -2
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +42 -0
- data/lib/graphql/tracing/platform_trace.rb +109 -0
- data/lib/graphql/tracing/platform_tracing.rb +33 -43
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- 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/trace.rb +75 -0
- data/lib/graphql/tracing.rb +16 -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 +17 -74
- metadata +33 -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,14 +5,13 @@ 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
|
14
13
|
extend GraphQL::Schema::FindInheritedValue
|
15
|
-
include GraphQL::
|
14
|
+
include GraphQL::EmptyObjects
|
16
15
|
include GraphQL::Schema::Member::HasDirectives
|
17
16
|
include GraphQL::Schema::Member::HasDeprecationReason
|
18
17
|
|
@@ -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
|
|
@@ -176,6 +182,8 @@ module GraphQL
|
|
176
182
|
|
177
183
|
# @return Boolean
|
178
184
|
attr_reader :relay_node_field
|
185
|
+
# @return Boolean
|
186
|
+
attr_reader :relay_nodes_field
|
179
187
|
|
180
188
|
# @return [Boolean] Should we warn if this field's name conflicts with a built-in method?
|
181
189
|
def method_conflict_warning?
|
@@ -185,7 +193,7 @@ module GraphQL
|
|
185
193
|
# @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
|
186
194
|
# @param type [Class, GraphQL::BaseType, Array] The return type of this field
|
187
195
|
# @param owner [Class] The type that this field belongs to
|
188
|
-
# @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`
|
189
197
|
# @param description [String] Field description
|
190
198
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
191
199
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
@@ -195,10 +203,8 @@ module GraphQL
|
|
195
203
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
196
204
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
197
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.
|
198
207
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
199
|
-
# @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
|
200
|
-
# @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
|
201
|
-
# @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
|
202
208
|
# @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
|
203
209
|
# @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
|
204
210
|
# @param camelize [Boolean] If true, the field name will be camelized when building the schema
|
@@ -212,31 +218,25 @@ module GraphQL
|
|
212
218
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
213
219
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
214
220
|
# @param validates [Array<Hash>] Configurations for validating this field
|
215
|
-
# @
|
216
|
-
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_CONFIGURED, &definition_block)
|
217
223
|
if name.nil?
|
218
224
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
219
225
|
end
|
220
|
-
if !(
|
226
|
+
if !(resolver_class)
|
221
227
|
if type.nil?
|
222
228
|
raise ArgumentError, "missing second `type` argument or keyword `type:`"
|
223
229
|
end
|
224
230
|
end
|
225
|
-
if (field || function || resolve) && extras.any?
|
226
|
-
raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
|
227
|
-
end
|
228
231
|
@original_name = name
|
229
232
|
name_s = -name.to_s
|
233
|
+
|
230
234
|
@underscored_name = -Member::BuildType.underscore(name_s)
|
231
235
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
236
|
+
|
232
237
|
@description = description
|
233
|
-
if
|
234
|
-
|
235
|
-
else
|
236
|
-
@field = field
|
237
|
-
end
|
238
|
-
@function = function
|
239
|
-
@resolve = resolve
|
238
|
+
@type = @owner_type = @own_validators = @own_directives = @own_arguments = nil # these will be prepared later if necessary
|
239
|
+
|
240
240
|
self.deprecation_reason = deprecation_reason
|
241
241
|
|
242
242
|
if method && hash_key && dig
|
@@ -253,20 +253,31 @@ module GraphQL
|
|
253
253
|
end
|
254
254
|
end
|
255
255
|
|
256
|
-
# TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
|
257
256
|
method_name = method || hash_key || name_s
|
258
257
|
@dig_keys = dig
|
259
|
-
|
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
|
260
265
|
|
261
266
|
@method_str = -method_name.to_s
|
262
267
|
@method_sym = method_name.to_sym
|
263
|
-
@resolver_method = resolver_method
|
268
|
+
@resolver_method = (resolver_method || name_s).to_sym
|
264
269
|
@complexity = complexity
|
265
270
|
@return_type_expr = type
|
266
|
-
@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
|
267
278
|
@connection = connection
|
268
|
-
@
|
269
|
-
@
|
279
|
+
@max_page_size = max_page_size
|
280
|
+
@default_page_size = default_page_size
|
270
281
|
@introspection = introspection
|
271
282
|
@extras = extras
|
272
283
|
@broadcastable = broadcastable
|
@@ -277,7 +288,7 @@ module GraphQL
|
|
277
288
|
@relay_nodes_field = relay_nodes_field
|
278
289
|
@ast_node = ast_node
|
279
290
|
@method_conflict_warning = method_conflict_warning
|
280
|
-
@
|
291
|
+
@fallback_value = fallback_value
|
281
292
|
|
282
293
|
arguments.each do |name, arg|
|
283
294
|
case arg
|
@@ -314,13 +325,19 @@ module GraphQL
|
|
314
325
|
self.extensions(extensions)
|
315
326
|
end
|
316
327
|
|
328
|
+
if resolver_class && resolver_class.extensions.any?
|
329
|
+
self.extensions(resolver_class.extensions)
|
330
|
+
end
|
331
|
+
|
317
332
|
if directives.any?
|
318
333
|
directives.each do |(dir_class, options)|
|
319
334
|
self.directive(dir_class, **options)
|
320
335
|
end
|
321
336
|
end
|
322
337
|
|
323
|
-
|
338
|
+
if !validates.empty?
|
339
|
+
self.validates(validates)
|
340
|
+
end
|
324
341
|
|
325
342
|
if definition_block
|
326
343
|
if definition_block.arity == 1
|
@@ -338,7 +355,13 @@ module GraphQL
|
|
338
355
|
# @return [Boolean, nil]
|
339
356
|
# @see GraphQL::Subscriptions::BroadcastAnalyzer
|
340
357
|
def broadcastable?
|
341
|
-
@broadcastable
|
358
|
+
if !NOT_CONFIGURED.equal?(@broadcastable)
|
359
|
+
@broadcastable
|
360
|
+
elsif @resolver_class
|
361
|
+
@resolver_class.broadcastable?
|
362
|
+
else
|
363
|
+
nil
|
364
|
+
end
|
342
365
|
end
|
343
366
|
|
344
367
|
# @param text [String]
|
@@ -346,8 +369,12 @@ module GraphQL
|
|
346
369
|
def description(text = nil)
|
347
370
|
if text
|
348
371
|
@description = text
|
349
|
-
|
372
|
+
elsif !NOT_CONFIGURED.equal?(@description)
|
350
373
|
@description
|
374
|
+
elsif @resolver_class
|
375
|
+
@resolver_class.description
|
376
|
+
else
|
377
|
+
nil
|
351
378
|
end
|
352
379
|
end
|
353
380
|
|
@@ -411,7 +438,12 @@ module GraphQL
|
|
411
438
|
def extras(new_extras = nil)
|
412
439
|
if new_extras.nil?
|
413
440
|
# Read the value
|
414
|
-
@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
|
415
447
|
else
|
416
448
|
if @extras.frozen?
|
417
449
|
@extras = @extras.dup
|
@@ -439,11 +471,11 @@ module GraphQL
|
|
439
471
|
end
|
440
472
|
|
441
473
|
if max_possible_page_size.nil?
|
442
|
-
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
|
443
475
|
end
|
444
476
|
|
445
477
|
if max_possible_page_size.nil?
|
446
|
-
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`"
|
447
479
|
else
|
448
480
|
metadata_complexity = 0
|
449
481
|
lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
|
@@ -471,7 +503,13 @@ module GraphQL
|
|
471
503
|
case defined_complexity
|
472
504
|
when Proc
|
473
505
|
arguments = query.arguments_for(nodes.first, self)
|
474
|
-
|
506
|
+
if arguments.is_a?(GraphQL::ExecutionError)
|
507
|
+
return child_complexity
|
508
|
+
elsif arguments.respond_to?(:keyword_arguments)
|
509
|
+
arguments = arguments.keyword_arguments
|
510
|
+
end
|
511
|
+
|
512
|
+
defined_complexity.call(query.context, arguments, child_complexity)
|
475
513
|
when Numeric
|
476
514
|
defined_complexity + child_complexity
|
477
515
|
else
|
@@ -494,7 +532,11 @@ module GraphQL
|
|
494
532
|
when Numeric
|
495
533
|
@complexity = new_complexity
|
496
534
|
when nil
|
497
|
-
@
|
535
|
+
if @resolver_class
|
536
|
+
@complexity || @resolver_class.complexity || 1
|
537
|
+
else
|
538
|
+
@complexity || 1
|
539
|
+
end
|
498
540
|
else
|
499
541
|
raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
|
500
542
|
end
|
@@ -502,105 +544,49 @@ module GraphQL
|
|
502
544
|
|
503
545
|
# @return [Boolean] True if this field's {#max_page_size} should override the schema default.
|
504
546
|
def has_max_page_size?
|
505
|
-
@has_max_page_size
|
547
|
+
!NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
|
506
548
|
end
|
507
549
|
|
508
550
|
# @return [Integer, nil] Applied to connections if {#has_max_page_size?}
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
def to_graphql
|
515
|
-
field_defn = if @field
|
516
|
-
@field.dup
|
517
|
-
elsif @function
|
518
|
-
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
|
519
556
|
else
|
520
|
-
|
521
|
-
end
|
522
|
-
|
523
|
-
field_defn.name = @name
|
524
|
-
if @return_type_expr
|
525
|
-
field_defn.type = -> { type }
|
526
|
-
end
|
527
|
-
|
528
|
-
if @description
|
529
|
-
field_defn.description = @description
|
530
|
-
end
|
531
|
-
|
532
|
-
if self.deprecation_reason
|
533
|
-
field_defn.deprecation_reason = self.deprecation_reason
|
534
|
-
end
|
535
|
-
|
536
|
-
if @resolver_class
|
537
|
-
if @resolver_class < GraphQL::Schema::Mutation
|
538
|
-
field_defn.mutation = @resolver_class
|
539
|
-
end
|
540
|
-
field_defn.metadata[:resolver] = @resolver_class
|
541
|
-
end
|
542
|
-
|
543
|
-
if !@trace.nil?
|
544
|
-
field_defn.trace = @trace
|
545
|
-
end
|
546
|
-
|
547
|
-
if @relay_node_field
|
548
|
-
field_defn.relay_node_field = @relay_node_field
|
549
|
-
end
|
550
|
-
|
551
|
-
if @relay_nodes_field
|
552
|
-
field_defn.relay_nodes_field = @relay_nodes_field
|
557
|
+
nil
|
553
558
|
end
|
559
|
+
end
|
554
560
|
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
field_defn.resolve = self.method(:resolve_field)
|
560
|
-
field_defn.connection = connection?
|
561
|
-
field_defn.connection_max_page_size = max_page_size
|
562
|
-
field_defn.introspection = @introspection
|
563
|
-
field_defn.complexity = @complexity
|
564
|
-
field_defn.subscription_scope = @subscription_scope
|
565
|
-
field_defn.ast_node = ast_node
|
566
|
-
|
567
|
-
all_argument_definitions.each do |defn|
|
568
|
-
arg_graphql = defn.deprecated_to_graphql
|
569
|
-
field_defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
570
|
-
end
|
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
|
571
565
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
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
|
579
574
|
end
|
580
|
-
|
581
|
-
# Ok, `self` isn't a class, but this is for consistency with the classes
|
582
|
-
field_defn.metadata[:type_class] = self
|
583
|
-
field_defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(field_defn)
|
584
|
-
field_defn
|
585
575
|
end
|
586
576
|
|
587
577
|
class MissingReturnTypeError < GraphQL::Error; end
|
588
578
|
attr_writer :type
|
589
579
|
|
590
580
|
def type
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
elsif @return_type_expr.nil?
|
596
|
-
# Not enough info to determine type
|
597
|
-
message = "Can't determine the return type for #{self.path}"
|
598
|
-
if @resolver_class
|
599
|
-
message += " (it has `resolver: #{@resolver_class}`, consider configuration a `type ...` for that class)"
|
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)"
|
600
585
|
end
|
601
|
-
|
586
|
+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
587
|
+
Member::BuildType.parse_type(return_type, null: nullable)
|
602
588
|
else
|
603
|
-
Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
589
|
+
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
604
590
|
end
|
605
591
|
rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
|
606
592
|
# Let this propagate up
|
@@ -617,83 +603,47 @@ module GraphQL
|
|
617
603
|
end
|
618
604
|
end
|
619
605
|
|
620
|
-
def accessible?(context)
|
621
|
-
if @resolver_class
|
622
|
-
@resolver_class.accessible?(context)
|
623
|
-
else
|
624
|
-
true
|
625
|
-
end
|
626
|
-
end
|
627
|
-
|
628
606
|
def authorized?(object, args, context)
|
629
607
|
if @resolver_class
|
630
608
|
# The resolver _instance_ will check itself during `resolve()`
|
631
609
|
@resolver_class.authorized?(object, context)
|
632
610
|
else
|
633
|
-
if
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
if
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
application_arg_value.
|
611
|
+
if args.size > 0
|
612
|
+
if (arg_values = context[:current_arguments])
|
613
|
+
# ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
|
614
|
+
using_arg_values = true
|
615
|
+
arg_values = arg_values.argument_values
|
616
|
+
else
|
617
|
+
arg_values = args
|
618
|
+
using_arg_values = false
|
619
|
+
end
|
620
|
+
|
621
|
+
args = context.warden.arguments(self)
|
622
|
+
args.each do |arg|
|
623
|
+
arg_key = arg.keyword
|
624
|
+
if arg_values.key?(arg_key)
|
625
|
+
arg_value = arg_values[arg_key]
|
626
|
+
if using_arg_values
|
627
|
+
if arg_value.default_used?
|
628
|
+
# pass -- no auth required for default used
|
629
|
+
next
|
630
|
+
else
|
631
|
+
application_arg_value = arg_value.value
|
632
|
+
if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
|
633
|
+
application_arg_value.keyword_arguments
|
634
|
+
end
|
654
635
|
end
|
636
|
+
else
|
637
|
+
application_arg_value = arg_value
|
655
638
|
end
|
656
|
-
else
|
657
|
-
application_arg_value = arg_value
|
658
|
-
end
|
659
|
-
|
660
|
-
if !arg.authorized?(object, application_arg_value, context)
|
661
|
-
return false
|
662
|
-
end
|
663
|
-
end
|
664
|
-
end
|
665
|
-
true
|
666
|
-
end
|
667
|
-
end
|
668
639
|
|
669
|
-
|
670
|
-
|
671
|
-
# Eventually, we might hook up field instances to execution in another way. TBD.
|
672
|
-
# @see #resolve for how the interpreter hooks up to it
|
673
|
-
def resolve_field(obj, args, ctx)
|
674
|
-
ctx.schema.after_lazy(obj) do |after_obj|
|
675
|
-
# First, apply auth ...
|
676
|
-
query_ctx = ctx.query.context
|
677
|
-
# Some legacy fields can have `nil` here, not exactly sure why.
|
678
|
-
# @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
|
679
|
-
inner_obj = after_obj && after_obj.object
|
680
|
-
ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
|
681
|
-
if authorized?(inner_obj, ruby_args, query_ctx)
|
682
|
-
# Then if it passed, resolve the field
|
683
|
-
if @resolve_proc
|
684
|
-
# Might be nil, still want to call the func in that case
|
685
|
-
with_extensions(inner_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
|
686
|
-
# Pass the GraphQL args here for compatibility:
|
687
|
-
@resolve_proc.call(extended_obj, args, ctx)
|
640
|
+
if !arg.authorized?(object, application_arg_value, context)
|
641
|
+
return false
|
688
642
|
end
|
689
|
-
else
|
690
|
-
public_send_field(after_obj, ruby_args, query_ctx)
|
691
643
|
end
|
692
|
-
else
|
693
|
-
err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
|
694
|
-
query_ctx.schema.unauthorized_field(err)
|
695
644
|
end
|
696
645
|
end
|
646
|
+
true
|
697
647
|
end
|
698
648
|
end
|
699
649
|
|
@@ -702,34 +652,112 @@ module GraphQL
|
|
702
652
|
# @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
|
703
653
|
# @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
|
704
654
|
# @param ctx [GraphQL::Query::Context]
|
705
|
-
def resolve(object, args,
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
655
|
+
def resolve(object, args, query_ctx)
|
656
|
+
# Unwrap the GraphQL object to get the application object.
|
657
|
+
application_object = object.object
|
658
|
+
method_receiver = nil
|
659
|
+
method_to_call = nil
|
660
|
+
method_args = nil
|
661
|
+
|
662
|
+
Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
663
|
+
|
664
|
+
query_ctx.schema.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
|
665
|
+
if is_authorized
|
666
|
+
with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
|
667
|
+
method_args = ruby_kwargs
|
668
|
+
if @resolver_class
|
669
|
+
if obj.is_a?(GraphQL::Schema::Object)
|
670
|
+
obj = obj.object
|
671
|
+
end
|
672
|
+
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
673
|
+
end
|
712
674
|
|
713
|
-
|
675
|
+
inner_object = obj.object
|
714
676
|
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
677
|
+
if !NOT_CONFIGURED.equal?(@hash_key)
|
678
|
+
hash_value = if inner_object.is_a?(Hash)
|
679
|
+
inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
|
680
|
+
elsif inner_object.respond_to?(:[])
|
681
|
+
inner_object[@hash_key]
|
682
|
+
else
|
683
|
+
nil
|
684
|
+
end
|
685
|
+
if hash_value == false
|
686
|
+
hash_value
|
687
|
+
else
|
688
|
+
hash_value || (@fallback_value != NOT_CONFIGURED ? @fallback_value : nil)
|
689
|
+
end
|
690
|
+
elsif obj.respond_to?(resolver_method)
|
691
|
+
method_to_call = resolver_method
|
692
|
+
method_receiver = obj
|
693
|
+
# Call the method with kwargs, if there are any
|
694
|
+
if ruby_kwargs.any?
|
695
|
+
obj.public_send(resolver_method, **ruby_kwargs)
|
696
|
+
else
|
697
|
+
obj.public_send(resolver_method)
|
698
|
+
end
|
699
|
+
elsif inner_object.is_a?(Hash)
|
700
|
+
if @dig_keys
|
701
|
+
inner_object.dig(*@dig_keys)
|
702
|
+
elsif inner_object.key?(@method_sym)
|
703
|
+
inner_object[@method_sym]
|
704
|
+
elsif inner_object.key?(@method_str)
|
705
|
+
inner_object[@method_str]
|
706
|
+
elsif @fallback_value != NOT_CONFIGURED
|
707
|
+
@fallback_value
|
708
|
+
else
|
709
|
+
nil
|
710
|
+
end
|
711
|
+
elsif inner_object.respond_to?(@method_sym)
|
712
|
+
method_to_call = @method_sym
|
713
|
+
method_receiver = obj.object
|
714
|
+
if ruby_kwargs.any?
|
715
|
+
inner_object.public_send(@method_sym, **ruby_kwargs)
|
716
|
+
else
|
717
|
+
inner_object.public_send(@method_sym)
|
718
|
+
end
|
719
|
+
elsif @fallback_value != NOT_CONFIGURED
|
720
|
+
@fallback_value
|
721
|
+
else
|
722
|
+
raise <<-ERR
|
723
|
+
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
724
|
+
|
725
|
+
- `#{obj.class}##{resolver_method}`, which did not exist
|
726
|
+
- `#{inner_object.class}##{@method_sym}`, which did not exist
|
727
|
+
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
|
728
|
+
|
729
|
+
To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
|
730
|
+
ERR
|
731
|
+
end
|
720
732
|
end
|
733
|
+
else
|
734
|
+
raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
|
721
735
|
end
|
722
|
-
rescue GraphQL::UnauthorizedFieldError => err
|
723
|
-
err.field ||= self
|
724
|
-
ctx.schema.unauthorized_field(err)
|
725
|
-
rescue GraphQL::UnauthorizedError => err
|
726
|
-
ctx.schema.unauthorized_object(err)
|
727
736
|
end
|
737
|
+
rescue GraphQL::UnauthorizedFieldError => err
|
738
|
+
err.field ||= self
|
739
|
+
begin
|
740
|
+
query_ctx.schema.unauthorized_field(err)
|
741
|
+
rescue GraphQL::ExecutionError => err
|
742
|
+
err
|
743
|
+
end
|
744
|
+
rescue GraphQL::UnauthorizedError => err
|
745
|
+
begin
|
746
|
+
query_ctx.schema.unauthorized_object(err)
|
747
|
+
rescue GraphQL::ExecutionError => err
|
748
|
+
err
|
749
|
+
end
|
750
|
+
rescue ArgumentError
|
751
|
+
if method_receiver && method_to_call
|
752
|
+
assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
|
753
|
+
end
|
754
|
+
# if the line above doesn't raise, re-raise
|
755
|
+
raise
|
728
756
|
rescue GraphQL::ExecutionError => err
|
729
757
|
err
|
730
758
|
end
|
731
759
|
|
732
|
-
# @param ctx [GraphQL::Query::Context
|
760
|
+
# @param ctx [GraphQL::Query::Context]
|
733
761
|
def fetch_extra(extra_name, ctx)
|
734
762
|
if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
|
735
763
|
self.public_send(extra_name)
|
@@ -742,127 +770,6 @@ module GraphQL
|
|
742
770
|
|
743
771
|
private
|
744
772
|
|
745
|
-
NO_ARGS = {}.freeze
|
746
|
-
|
747
|
-
# Convert a GraphQL arguments instance into a Ruby-style hash.
|
748
|
-
#
|
749
|
-
# @param obj [GraphQL::Schema::Object] The object where this field is being resolved
|
750
|
-
# @param graphql_args [GraphQL::Query::Arguments]
|
751
|
-
# @param field_ctx [GraphQL::Query::Context::FieldResolutionContext]
|
752
|
-
# @return [Hash<Symbol => Any>]
|
753
|
-
def to_ruby_args(obj, graphql_args, field_ctx)
|
754
|
-
if graphql_args.any? || @extras.any?
|
755
|
-
# Splat the GraphQL::Arguments to Ruby keyword arguments
|
756
|
-
ruby_kwargs = graphql_args.to_kwargs
|
757
|
-
maybe_lazies = []
|
758
|
-
# Apply any `prepare` methods. Not great code organization, can this go somewhere better?
|
759
|
-
arguments(field_ctx).each do |name, arg_defn|
|
760
|
-
ruby_kwargs_key = arg_defn.keyword
|
761
|
-
|
762
|
-
if ruby_kwargs.key?(ruby_kwargs_key)
|
763
|
-
loads = arg_defn.loads
|
764
|
-
value = ruby_kwargs[ruby_kwargs_key]
|
765
|
-
loaded_value = if loads && !arg_defn.from_resolver?
|
766
|
-
if arg_defn.type.list?
|
767
|
-
loaded_values = value.map { |val| load_application_object(arg_defn, loads, val, field_ctx.query.context) }
|
768
|
-
field_ctx.schema.after_any_lazies(loaded_values) { |result| result }
|
769
|
-
else
|
770
|
-
load_application_object(arg_defn, loads, value, field_ctx.query.context)
|
771
|
-
end
|
772
|
-
elsif arg_defn.type.list? && value.is_a?(Array)
|
773
|
-
field_ctx.schema.after_any_lazies(value, &:itself)
|
774
|
-
else
|
775
|
-
value
|
776
|
-
end
|
777
|
-
|
778
|
-
maybe_lazies << field_ctx.schema.after_lazy(loaded_value) do |loaded_value|
|
779
|
-
prepared_value = if arg_defn.prepare
|
780
|
-
arg_defn.prepare_value(obj, loaded_value)
|
781
|
-
else
|
782
|
-
loaded_value
|
783
|
-
end
|
784
|
-
|
785
|
-
ruby_kwargs[ruby_kwargs_key] = prepared_value
|
786
|
-
end
|
787
|
-
end
|
788
|
-
end
|
789
|
-
|
790
|
-
@extras.each do |extra_arg|
|
791
|
-
ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
|
792
|
-
end
|
793
|
-
|
794
|
-
field_ctx.schema.after_any_lazies(maybe_lazies) do
|
795
|
-
ruby_kwargs
|
796
|
-
end
|
797
|
-
else
|
798
|
-
NO_ARGS
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
def public_send_field(unextended_obj, unextended_ruby_kwargs, query_ctx)
|
803
|
-
with_extensions(unextended_obj, unextended_ruby_kwargs, query_ctx) do |obj, ruby_kwargs|
|
804
|
-
begin
|
805
|
-
method_receiver = nil
|
806
|
-
method_to_call = nil
|
807
|
-
if @resolver_class
|
808
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
809
|
-
obj = obj.object
|
810
|
-
end
|
811
|
-
obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
|
812
|
-
end
|
813
|
-
|
814
|
-
# Find a way to resolve this field, checking:
|
815
|
-
#
|
816
|
-
# - A method on the type instance;
|
817
|
-
# - Hash keys, if the wrapped object is a hash;
|
818
|
-
# - A method on the wrapped object;
|
819
|
-
# - Or, raise not implemented.
|
820
|
-
#
|
821
|
-
if obj.respond_to?(@resolver_method)
|
822
|
-
method_to_call = @resolver_method
|
823
|
-
method_receiver = obj
|
824
|
-
# Call the method with kwargs, if there are any
|
825
|
-
if ruby_kwargs.any?
|
826
|
-
obj.public_send(@resolver_method, **ruby_kwargs)
|
827
|
-
else
|
828
|
-
obj.public_send(@resolver_method)
|
829
|
-
end
|
830
|
-
elsif obj.object.is_a?(Hash)
|
831
|
-
inner_object = obj.object
|
832
|
-
if @dig_keys
|
833
|
-
inner_object.dig(*@dig_keys)
|
834
|
-
elsif inner_object.key?(@method_sym)
|
835
|
-
inner_object[@method_sym]
|
836
|
-
else
|
837
|
-
inner_object[@method_str]
|
838
|
-
end
|
839
|
-
elsif obj.object.respond_to?(@method_sym)
|
840
|
-
method_to_call = @method_sym
|
841
|
-
method_receiver = obj.object
|
842
|
-
if ruby_kwargs.any?
|
843
|
-
obj.object.public_send(@method_sym, **ruby_kwargs)
|
844
|
-
else
|
845
|
-
obj.object.public_send(@method_sym)
|
846
|
-
end
|
847
|
-
else
|
848
|
-
raise <<-ERR
|
849
|
-
Failed to implement #{@owner.graphql_name}.#{@name}, tried:
|
850
|
-
|
851
|
-
- `#{obj.class}##{@resolver_method}`, which did not exist
|
852
|
-
- `#{obj.object.class}##{@method_sym}`, which did not exist
|
853
|
-
- Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
|
854
|
-
|
855
|
-
To implement this field, define one of the methods above (and check for typos)
|
856
|
-
ERR
|
857
|
-
end
|
858
|
-
rescue ArgumentError
|
859
|
-
assert_satisfactory_implementation(method_receiver, method_to_call, ruby_kwargs)
|
860
|
-
# if the line above doesn't raise, re-raise
|
861
|
-
raise
|
862
|
-
end
|
863
|
-
end
|
864
|
-
end
|
865
|
-
|
866
773
|
def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
|
867
774
|
method_defn = receiver.method(method_name)
|
868
775
|
unsatisfied_ruby_kwargs = ruby_kwargs.dup
|
@@ -893,7 +800,7 @@ module GraphQL
|
|
893
800
|
|
894
801
|
if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
|
895
802
|
raise FieldImplementationFailed.new, <<-ERR
|
896
|
-
Failed to call
|
803
|
+
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
897
804
|
|
898
805
|
#{ unsatisfied_ruby_kwargs
|
899
806
|
.map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
|