graphql 2.2.17 → 2.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install_generator.rb +46 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_resolver.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/subscriptions.rb +96 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +158 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +46 -19
- data/lib/graphql/dataloader/null_dataloader.rb +51 -10
- data/lib/graphql/dataloader/source.rb +20 -9
- data/lib/graphql/dataloader.rb +153 -45
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +63 -5
- data/lib/graphql/execution/interpreter/runtime.rb +321 -222
- data/lib/graphql/execution/interpreter.rb +23 -30
- data/lib/graphql/execution/lookahead.rb +18 -11
- data/lib/graphql/execution/multiplex.rb +6 -5
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +6 -11
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +20 -17
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/document_from_schema_definition.rb +64 -35
- data/lib/graphql/language/lexer.rb +72 -42
- data/lib/graphql/language/nodes.rb +93 -52
- data/lib/graphql/language/parser.rb +168 -61
- data/lib/graphql/language/printer.rb +31 -15
- data/lib/graphql/language/sanitized_printer.rb +1 -1
- data/lib/graphql/language.rb +61 -1
- data/lib/graphql/pagination/connection.rb +1 -1
- data/lib/graphql/query/context/scoped_context.rb +1 -1
- data/lib/graphql/query/context.rb +46 -47
- data/lib/graphql/query/null_context.rb +3 -5
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +2 -2
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query.rb +123 -69
- data/lib/graphql/railtie.rb +7 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +57 -8
- data/lib/graphql/schema/build_from_definition.rb +116 -49
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +107 -24
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +134 -45
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +6 -2
- data/lib/graphql/schema/input_object.rb +122 -64
- data/lib/graphql/schema/interface.rb +23 -5
- data/lib/graphql/schema/introspection_system.rb +6 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
- data/lib/graphql/schema/member/has_arguments.rb +44 -58
- data/lib/graphql/schema/member/has_dataloader.rb +62 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +26 -6
- data/lib/graphql/schema/member/has_interfaces.rb +6 -6
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +25 -8
- data/lib/graphql/schema/printer.rb +1 -0
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +29 -23
- data/lib/graphql/schema/scalar.rb +1 -6
- data/lib/graphql/schema/subscription.rb +52 -6
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +190 -20
- data/lib/graphql/schema.rb +695 -167
- data/lib/graphql/static_validation/all_rules.rb +2 -2
- data/lib/graphql/static_validation/base_visitor.rb +6 -5
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +18 -2
- data/lib/graphql/static_validation/validator.rb +6 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -3
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +13 -2
- data/lib/graphql/subscriptions/serialize.rb +1 -1
- data/lib/graphql/subscriptions.rb +7 -5
- data/lib/graphql/testing/helpers.rb +48 -16
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +1 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +5 -1
- data/lib/graphql/tracing/appoptics_tracing.rb +7 -0
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +141 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +183 -37
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +818 -0
- data/lib/graphql/tracing/platform_tracing.rb +1 -1
- data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +64 -98
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +111 -1
- data/lib/graphql/tracing.rb +31 -30
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -11
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +64 -54
- metadata +197 -22
- data/lib/graphql/analysis/ast/analyzer.rb +0 -91
- data/lib/graphql/analysis/ast/field_usage.rb +0 -82
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -182
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -94
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -93
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
data/lib/graphql/schema/enum.rb
CHANGED
|
@@ -22,9 +22,21 @@ module GraphQL
|
|
|
22
22
|
class Enum < GraphQL::Schema::Member
|
|
23
23
|
extend GraphQL::Schema::Member::ValidatesInput
|
|
24
24
|
|
|
25
|
+
# This is raised when either:
|
|
26
|
+
#
|
|
27
|
+
# - A resolver returns a value which doesn't match any of the enum's configured values;
|
|
28
|
+
# - Or, the resolver returns a value which matches a value, but that value's `authorized?` check returns false.
|
|
29
|
+
#
|
|
30
|
+
# In either case, the field should be modified so that the invalid value isn't returned.
|
|
31
|
+
#
|
|
32
|
+
# {GraphQL::Schema::Enum} subclasses get their own subclass of this error, so that bug trackers can better show where they came from.
|
|
25
33
|
class UnresolvedValueError < GraphQL::Error
|
|
26
|
-
def initialize(value:, enum:, context:)
|
|
27
|
-
fix_message =
|
|
34
|
+
def initialize(value:, enum:, context:, authorized:)
|
|
35
|
+
fix_message = if authorized == false
|
|
36
|
+
", but this value was unauthorized. Update the field or resolver to return a different value in this case (or return `nil`)."
|
|
37
|
+
else
|
|
38
|
+
", but this isn't a valid value for `#{enum.graphql_name}`. Update the field or resolver to return one of `#{enum.graphql_name}`'s values instead."
|
|
39
|
+
end
|
|
28
40
|
message = if (cp = context[:current_path]) && (cf = context[:current_field])
|
|
29
41
|
"`#{cf.path}` returned `#{value.inspect}` at `#{cp.join(".")}`#{fix_message}"
|
|
30
42
|
else
|
|
@@ -34,6 +46,8 @@ module GraphQL
|
|
|
34
46
|
end
|
|
35
47
|
end
|
|
36
48
|
|
|
49
|
+
# Raised when a {GraphQL::Schema::Enum} is defined to have no values.
|
|
50
|
+
# This can also happen when all values return false for `.visible?`.
|
|
37
51
|
class MissingValuesError < GraphQL::Error
|
|
38
52
|
def initialize(enum_type)
|
|
39
53
|
@enum_type = enum_type
|
|
@@ -43,15 +57,23 @@ module GraphQL
|
|
|
43
57
|
|
|
44
58
|
class << self
|
|
45
59
|
# Define a value for this enum
|
|
46
|
-
# @
|
|
47
|
-
# @
|
|
48
|
-
# @
|
|
49
|
-
# @
|
|
60
|
+
# @option kwargs [String, Symbol] :graphql_name the GraphQL value for this, usually `SCREAMING_CASE`
|
|
61
|
+
# @option kwargs [String] :description, the GraphQL description for this value, present in documentation
|
|
62
|
+
# @option kwargs [String] :comment, the GraphQL comment for this value, present in documentation
|
|
63
|
+
# @option kwargs [::Object] :value the translated Ruby value for this object (defaults to `graphql_name`)
|
|
64
|
+
# @option kwargs [::Object] :value_method, the method name to fetch `graphql_name` (defaults to `graphql_name.downcase`)
|
|
65
|
+
# @option kwargs [String] :deprecation_reason if this object is deprecated, include a message here
|
|
66
|
+
# @param value_method [Symbol, false] A method to generate for this value, or `false` to skip generation
|
|
50
67
|
# @return [void]
|
|
51
68
|
# @see {Schema::EnumValue} which handles these inputs by default
|
|
52
|
-
def value(*args, **kwargs, &block)
|
|
69
|
+
def value(*args, value_method: nil, **kwargs, &block)
|
|
53
70
|
kwargs[:owner] = self
|
|
54
71
|
value = enum_value_class.new(*args, **kwargs, &block)
|
|
72
|
+
|
|
73
|
+
if value_method || (value_methods && value_method != false)
|
|
74
|
+
generate_value_method(value, value_method)
|
|
75
|
+
end
|
|
76
|
+
|
|
55
77
|
key = value.graphql_name
|
|
56
78
|
prev_value = own_values[key]
|
|
57
79
|
case prev_value
|
|
@@ -71,10 +93,24 @@ module GraphQL
|
|
|
71
93
|
def enum_values(context = GraphQL::Query::NullContext.instance)
|
|
72
94
|
inherited_values = superclass.respond_to?(:enum_values) ? superclass.enum_values(context) : nil
|
|
73
95
|
visible_values = []
|
|
74
|
-
|
|
96
|
+
types = Warden.types_from_context(context)
|
|
75
97
|
own_values.each do |key, values_entry|
|
|
76
|
-
|
|
77
|
-
|
|
98
|
+
visible_value = nil
|
|
99
|
+
if values_entry.is_a?(Array)
|
|
100
|
+
values_entry.each do |v|
|
|
101
|
+
if types.visible_enum_value?(v, context)
|
|
102
|
+
if visible_value.nil?
|
|
103
|
+
visible_value = v
|
|
104
|
+
visible_values << v
|
|
105
|
+
else
|
|
106
|
+
raise DuplicateNamesError.new(
|
|
107
|
+
duplicated_name: v.path, duplicated_definition_1: visible_value.inspect, duplicated_definition_2: v.inspect
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
elsif types.visible_enum_value?(values_entry, context)
|
|
113
|
+
visible_values << values_entry
|
|
78
114
|
end
|
|
79
115
|
end
|
|
80
116
|
|
|
@@ -125,12 +161,24 @@ module GraphQL
|
|
|
125
161
|
end
|
|
126
162
|
end
|
|
127
163
|
|
|
164
|
+
def value_methods(new_value = NOT_CONFIGURED)
|
|
165
|
+
if NOT_CONFIGURED.equal?(new_value)
|
|
166
|
+
if @value_methods != nil
|
|
167
|
+
@value_methods
|
|
168
|
+
else
|
|
169
|
+
find_inherited_value(:value_methods, false)
|
|
170
|
+
end
|
|
171
|
+
else
|
|
172
|
+
@value_methods = new_value
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
128
176
|
def kind
|
|
129
177
|
GraphQL::TypeKinds::ENUM
|
|
130
178
|
end
|
|
131
179
|
|
|
132
180
|
def validate_non_null_input(value_name, ctx, max_errors: nil)
|
|
133
|
-
allowed_values = ctx.
|
|
181
|
+
allowed_values = ctx.types.enum_values(self)
|
|
134
182
|
matching_value = allowed_values.find { |v| v.graphql_name == value_name }
|
|
135
183
|
|
|
136
184
|
if matching_value.nil?
|
|
@@ -138,35 +186,55 @@ module GraphQL
|
|
|
138
186
|
else
|
|
139
187
|
nil
|
|
140
188
|
end
|
|
189
|
+
# rescue MissingValuesError
|
|
190
|
+
# nil
|
|
141
191
|
end
|
|
142
192
|
|
|
193
|
+
# Called by the runtime when a field returns a value to give back to the client.
|
|
194
|
+
# This method checks that the incoming {value} matches one of the enum's defined values.
|
|
195
|
+
# @param value [Object] Any value matching the values for this enum.
|
|
196
|
+
# @param ctx [GraphQL::Query::Context]
|
|
197
|
+
# @raise [GraphQL::Schema::Enum::UnresolvedValueError] if {value} doesn't match a configured value or if the matching value isn't authorized.
|
|
198
|
+
# @return [String] The GraphQL-ready string for {value}
|
|
143
199
|
def coerce_result(value, ctx)
|
|
144
|
-
|
|
145
|
-
all_values =
|
|
200
|
+
types = ctx.types
|
|
201
|
+
all_values = types ? types.enum_values(self) : values.each_value
|
|
146
202
|
enum_value = all_values.find { |val| val.value == value }
|
|
147
|
-
if enum_value
|
|
203
|
+
if enum_value && (was_authed = enum_value.authorized?(ctx))
|
|
148
204
|
enum_value.graphql_name
|
|
149
205
|
else
|
|
150
|
-
raise self::UnresolvedValueError.new(enum: self, value: value, context: ctx)
|
|
206
|
+
raise self::UnresolvedValueError.new(enum: self, value: value, context: ctx, authorized: was_authed)
|
|
151
207
|
end
|
|
152
208
|
end
|
|
153
209
|
|
|
210
|
+
# Called by the runtime with incoming string representations from a query.
|
|
211
|
+
# It will match the string to a configured by name or by Ruby value.
|
|
212
|
+
# @param value_name [String, Object] A string from a GraphQL query, or a Ruby value matching a `value(..., value: ...)` configuration
|
|
213
|
+
# @param ctx [GraphQL::Query::Context]
|
|
214
|
+
# @raise [GraphQL::UnauthorizedEnumValueError] if an {EnumValue} matches but returns false for `.authorized?`. Goes to {Schema.unauthorized_object}.
|
|
215
|
+
# @return [Object] The Ruby value for the matched {GraphQL::Schema::EnumValue}
|
|
154
216
|
def coerce_input(value_name, ctx)
|
|
155
|
-
all_values = ctx.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
217
|
+
all_values = ctx.types ? ctx.types.enum_values(self) : values.each_value
|
|
218
|
+
|
|
219
|
+
# This tries matching by incoming GraphQL string, then checks Ruby-defined values
|
|
220
|
+
if v = (all_values.find { |val| val.graphql_name == value_name } || all_values.find { |val| val.value == value_name })
|
|
221
|
+
if v.authorized?(ctx)
|
|
222
|
+
v.value
|
|
223
|
+
else
|
|
224
|
+
raise GraphQL::UnauthorizedEnumValueError.new(type: self, enum_value: v, context: ctx)
|
|
225
|
+
end
|
|
163
226
|
else
|
|
164
227
|
nil
|
|
165
228
|
end
|
|
166
229
|
end
|
|
167
230
|
|
|
168
231
|
def inherited(child_class)
|
|
169
|
-
child_class.
|
|
232
|
+
if child_class.name
|
|
233
|
+
# Don't assign a custom error class to anonymous classes
|
|
234
|
+
# because they would end up with names like `#<Class0x1234>::UnresolvedValueError` which messes up bug trackers
|
|
235
|
+
child_class.const_set(:UnresolvedValueError, Class.new(Schema::Enum::UnresolvedValueError))
|
|
236
|
+
end
|
|
237
|
+
child_class.class_exec { @value_methods = nil }
|
|
170
238
|
super
|
|
171
239
|
end
|
|
172
240
|
|
|
@@ -175,6 +243,21 @@ module GraphQL
|
|
|
175
243
|
def own_values
|
|
176
244
|
@own_values ||= {}
|
|
177
245
|
end
|
|
246
|
+
|
|
247
|
+
def generate_value_method(value, configured_value_method)
|
|
248
|
+
return if configured_value_method == false
|
|
249
|
+
|
|
250
|
+
value_method_name = configured_value_method || value.graphql_name.downcase
|
|
251
|
+
|
|
252
|
+
if respond_to?(value_method_name.to_sym)
|
|
253
|
+
warn "Failed to define value method for :#{value_method_name}, because " \
|
|
254
|
+
"#{value.owner.name || value.owner.graphql_name} already responds to that method. Use `value_method:` to override the method name " \
|
|
255
|
+
"or `value_method: false` to disable Enum value method generation."
|
|
256
|
+
return
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
define_singleton_method(value_method_name) { value.graphql_name }
|
|
260
|
+
end
|
|
178
261
|
end
|
|
179
262
|
|
|
180
263
|
enum_value_class(GraphQL::Schema::EnumValue)
|
|
@@ -30,10 +30,11 @@ module GraphQL
|
|
|
30
30
|
# @return [Class] The enum type that owns this value
|
|
31
31
|
attr_reader :owner
|
|
32
32
|
|
|
33
|
-
def initialize(graphql_name, desc = nil, owner:, ast_node: nil, directives: nil, description: nil, value: NOT_CONFIGURED, deprecation_reason: nil, &block)
|
|
33
|
+
def initialize(graphql_name, desc = nil, owner:, ast_node: nil, directives: nil, description: nil, comment: nil, value: NOT_CONFIGURED, deprecation_reason: nil, &block)
|
|
34
34
|
@graphql_name = graphql_name.to_s
|
|
35
35
|
GraphQL::NameValidator.validate!(@graphql_name)
|
|
36
36
|
@description = desc || description
|
|
37
|
+
@comment = comment
|
|
37
38
|
@value = value == NOT_CONFIGURED ? @graphql_name : value
|
|
38
39
|
if deprecation_reason
|
|
39
40
|
self.deprecation_reason = deprecation_reason
|
|
@@ -58,6 +59,13 @@ module GraphQL
|
|
|
58
59
|
@description
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
def comment(new_comment = nil)
|
|
63
|
+
if new_comment
|
|
64
|
+
@comment = new_comment
|
|
65
|
+
end
|
|
66
|
+
@comment
|
|
67
|
+
end
|
|
68
|
+
|
|
61
69
|
def value(new_val = nil)
|
|
62
70
|
unless new_val.nil?
|
|
63
71
|
@value = new_val
|
|
@@ -66,7 +74,7 @@ module GraphQL
|
|
|
66
74
|
end
|
|
67
75
|
|
|
68
76
|
def inspect
|
|
69
|
-
"#<#{self.class} #{path} @value=#{@value.inspect}#{description ? " @description=#{description.inspect}" : ""}>"
|
|
77
|
+
"#<#{self.class} #{path} @value=#{@value.inspect}#{description ? " @description=#{description.inspect}" : ""}#{deprecation_reason ? " @deprecation_reason=#{deprecation_reason.inspect}" : ""}>"
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
def visible?(_ctx); true; end
|
|
@@ -50,7 +50,7 @@ module GraphQL
|
|
|
50
50
|
if field.has_default_page_size? && !value.has_default_page_size_override?
|
|
51
51
|
value.default_page_size = field.default_page_size
|
|
52
52
|
end
|
|
53
|
-
if
|
|
53
|
+
if (custom_t = context.schema.connections.edge_class_for_field(@field))
|
|
54
54
|
value.edge_class = custom_t
|
|
55
55
|
end
|
|
56
56
|
value
|
|
@@ -12,7 +12,7 @@ module GraphQL
|
|
|
12
12
|
if ret_type.respond_to?(:scope_items)
|
|
13
13
|
scoped_items = ret_type.scope_items(value, context)
|
|
14
14
|
if !scoped_items.equal?(value) && !ret_type.reauthorize_scoped_objects
|
|
15
|
-
if (current_runtime_state =
|
|
15
|
+
if (current_runtime_state = Fiber[:__graphql_runtime_info]) &&
|
|
16
16
|
(query_runtime_state = current_runtime_state[context.query])
|
|
17
17
|
query_runtime_state.was_authorized_by_scope_items = true
|
|
18
18
|
end
|
data/lib/graphql/schema/field.rb
CHANGED
|
@@ -41,6 +41,32 @@ module GraphQL
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# @return [String, nil]
|
|
45
|
+
def deprecation_reason
|
|
46
|
+
super || @resolver_class&.deprecation_reason
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def directives
|
|
50
|
+
if @resolver_class && !(r_dirs = @resolver_class.directives).empty?
|
|
51
|
+
if !(own_dirs = super).empty?
|
|
52
|
+
new_dirs = own_dirs.dup
|
|
53
|
+
r_dirs.each do |r_dir|
|
|
54
|
+
if r_dir.class.repeatable? ||
|
|
55
|
+
( (r_dir_name = r_dir.graphql_name) &&
|
|
56
|
+
(!new_dirs.any? { |d| d.graphql_name == r_dir_name })
|
|
57
|
+
)
|
|
58
|
+
new_dirs << r_dir
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
new_dirs
|
|
62
|
+
else
|
|
63
|
+
r_dirs
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
super
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
44
70
|
# @return [Class] The thing this field was defined on (type, mutation, resolver)
|
|
45
71
|
attr_accessor :owner
|
|
46
72
|
|
|
@@ -69,7 +95,7 @@ module GraphQL
|
|
|
69
95
|
end
|
|
70
96
|
|
|
71
97
|
def inspect
|
|
72
|
-
"#<#{self.class} #{path}#{all_argument_definitions.
|
|
98
|
+
"#<#{self.class} #{path}#{!all_argument_definitions.empty? ? "(...)" : ""}: #{type.to_type_signature}>"
|
|
73
99
|
end
|
|
74
100
|
|
|
75
101
|
alias :mutation :resolver
|
|
@@ -94,7 +120,7 @@ module GraphQL
|
|
|
94
120
|
# @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
|
|
95
121
|
# @return [GraphQL::Schema:Field] an instance of `self`
|
|
96
122
|
# @see {.initialize} for other options
|
|
97
|
-
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
|
123
|
+
def self.from_options(name = nil, type = nil, desc = nil, comment: nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
|
98
124
|
if (resolver_class = resolver || mutation || subscription)
|
|
99
125
|
# Add a reference to that parent class
|
|
100
126
|
kwargs[:resolver_class] = resolver_class
|
|
@@ -104,6 +130,10 @@ module GraphQL
|
|
|
104
130
|
kwargs[:name] = name
|
|
105
131
|
end
|
|
106
132
|
|
|
133
|
+
if comment
|
|
134
|
+
kwargs[:comment] = comment
|
|
135
|
+
end
|
|
136
|
+
|
|
107
137
|
if !type.nil?
|
|
108
138
|
if desc
|
|
109
139
|
if kwargs[:description]
|
|
@@ -134,11 +164,16 @@ module GraphQL
|
|
|
134
164
|
Member::BuildType.to_type_name(@return_type_expr)
|
|
135
165
|
elsif @resolver_class && @resolver_class.type
|
|
136
166
|
Member::BuildType.to_type_name(@resolver_class.type)
|
|
137
|
-
|
|
167
|
+
elsif type
|
|
138
168
|
# As a last ditch, try to force loading the return type:
|
|
139
169
|
type.unwrap.name
|
|
140
170
|
end
|
|
141
|
-
|
|
171
|
+
if return_type_name
|
|
172
|
+
@connection = return_type_name.end_with?("Connection") && return_type_name != "Connection"
|
|
173
|
+
else
|
|
174
|
+
# TODO set this when type is set by method
|
|
175
|
+
false # not loaded yet?
|
|
176
|
+
end
|
|
142
177
|
else
|
|
143
178
|
@connection
|
|
144
179
|
end
|
|
@@ -195,6 +230,7 @@ module GraphQL
|
|
|
195
230
|
# @param owner [Class] The type that this field belongs to
|
|
196
231
|
# @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
|
|
197
232
|
# @param description [String] Field description
|
|
233
|
+
# @param comment [String] Field comment
|
|
198
234
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
|
199
235
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
|
200
236
|
# @param hash_key [String, Symbol] The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
|
|
@@ -219,13 +255,13 @@ module GraphQL
|
|
|
219
255
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
|
220
256
|
# @param validates [Array<Hash>] Configurations for validating this field
|
|
221
257
|
# @param 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, dynamic_introspection: false, &definition_block)
|
|
258
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, comment: 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, dynamic_introspection: false, &definition_block)
|
|
223
259
|
if name.nil?
|
|
224
260
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
|
225
261
|
end
|
|
226
262
|
if !(resolver_class)
|
|
227
|
-
if type.nil?
|
|
228
|
-
raise ArgumentError, "missing second `type` argument or
|
|
263
|
+
if type.nil? && !block_given?
|
|
264
|
+
raise ArgumentError, "missing second `type` argument, keyword `type:`, or a block containing `type(...)`"
|
|
229
265
|
end
|
|
230
266
|
end
|
|
231
267
|
@original_name = name
|
|
@@ -235,6 +271,7 @@ module GraphQL
|
|
|
235
271
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
|
236
272
|
NameValidator.validate!(@name)
|
|
237
273
|
@description = description
|
|
274
|
+
@comment = comment
|
|
238
275
|
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
|
239
276
|
|
|
240
277
|
self.deprecation_reason = deprecation_reason
|
|
@@ -290,6 +327,7 @@ module GraphQL
|
|
|
290
327
|
@ast_node = ast_node
|
|
291
328
|
@method_conflict_warning = method_conflict_warning
|
|
292
329
|
@fallback_value = fallback_value
|
|
330
|
+
@definition_block = definition_block
|
|
293
331
|
|
|
294
332
|
arguments.each do |name, arg|
|
|
295
333
|
case arg
|
|
@@ -309,28 +347,17 @@ module GraphQL
|
|
|
309
347
|
|
|
310
348
|
@extensions = EMPTY_ARRAY
|
|
311
349
|
@call_after_define = false
|
|
312
|
-
|
|
313
|
-
# but should it run after the definition block?
|
|
314
|
-
if scoped?
|
|
315
|
-
self.extension(ScopeExtension)
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
# The problem with putting this after the definition_block
|
|
319
|
-
# is that it would override arguments
|
|
320
|
-
if connection? && connection_extension
|
|
321
|
-
self.extension(connection_extension)
|
|
322
|
-
end
|
|
323
|
-
|
|
350
|
+
set_pagination_extensions(connection_extension: connection_extension)
|
|
324
351
|
# Do this last so we have as much context as possible when initializing them:
|
|
325
|
-
if extensions.
|
|
352
|
+
if !extensions.empty?
|
|
326
353
|
self.extensions(extensions)
|
|
327
354
|
end
|
|
328
355
|
|
|
329
|
-
if resolver_class && resolver_class.extensions.
|
|
356
|
+
if resolver_class && !resolver_class.extensions.empty?
|
|
330
357
|
self.extensions(resolver_class.extensions)
|
|
331
358
|
end
|
|
332
359
|
|
|
333
|
-
if directives.
|
|
360
|
+
if !directives.empty?
|
|
334
361
|
directives.each do |(dir_class, options)|
|
|
335
362
|
self.directive(dir_class, **options)
|
|
336
363
|
end
|
|
@@ -340,16 +367,29 @@ module GraphQL
|
|
|
340
367
|
self.validates(validates)
|
|
341
368
|
end
|
|
342
369
|
|
|
343
|
-
if
|
|
344
|
-
|
|
345
|
-
|
|
370
|
+
if @definition_block.nil?
|
|
371
|
+
self.extensions.each(&:after_define_apply)
|
|
372
|
+
@call_after_define = true
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Calls the definition block, if one was given.
|
|
377
|
+
# This is deferred so that references to the return type
|
|
378
|
+
# can be lazily evaluated, reducing Rails boot time.
|
|
379
|
+
# @return [self]
|
|
380
|
+
# @api private
|
|
381
|
+
def ensure_loaded
|
|
382
|
+
if @definition_block
|
|
383
|
+
if @definition_block.arity == 1
|
|
384
|
+
@definition_block.call(self)
|
|
346
385
|
else
|
|
347
|
-
|
|
386
|
+
instance_exec(self, &@definition_block)
|
|
348
387
|
end
|
|
388
|
+
self.extensions.each(&:after_define_apply)
|
|
389
|
+
@call_after_define = true
|
|
390
|
+
@definition_block = nil
|
|
349
391
|
end
|
|
350
|
-
|
|
351
|
-
self.extensions.each(&:after_define_apply)
|
|
352
|
-
@call_after_define = true
|
|
392
|
+
self
|
|
353
393
|
end
|
|
354
394
|
|
|
355
395
|
attr_accessor :dynamic_introspection
|
|
@@ -381,6 +421,20 @@ module GraphQL
|
|
|
381
421
|
end
|
|
382
422
|
end
|
|
383
423
|
|
|
424
|
+
# @param text [String]
|
|
425
|
+
# @return [String, nil]
|
|
426
|
+
def comment(text = nil)
|
|
427
|
+
if text
|
|
428
|
+
@comment = text
|
|
429
|
+
elsif !NOT_CONFIGURED.equal?(@comment)
|
|
430
|
+
@comment
|
|
431
|
+
elsif @resolver_class
|
|
432
|
+
@resolver_class.comment
|
|
433
|
+
else
|
|
434
|
+
nil
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
384
438
|
# Read extension instances from this field,
|
|
385
439
|
# or add new classes/options to be initialized on this field.
|
|
386
440
|
# Extensions are executed in the order they are added.
|
|
@@ -401,7 +455,7 @@ module GraphQL
|
|
|
401
455
|
new_extensions.each do |extension_config|
|
|
402
456
|
if extension_config.is_a?(Hash)
|
|
403
457
|
extension_class, options = *extension_config.to_a[0]
|
|
404
|
-
self.extension(extension_class, options)
|
|
458
|
+
self.extension(extension_class, **options)
|
|
405
459
|
else
|
|
406
460
|
self.extension(extension_config)
|
|
407
461
|
end
|
|
@@ -421,7 +475,7 @@ module GraphQL
|
|
|
421
475
|
# @param extension_class [Class] subclass of {Schema::FieldExtension}
|
|
422
476
|
# @param options [Hash] if provided, given as `options:` when initializing `extension`.
|
|
423
477
|
# @return [void]
|
|
424
|
-
def extension(extension_class, options
|
|
478
|
+
def extension(extension_class, **options)
|
|
425
479
|
extension_inst = extension_class.new(field: self, options: options)
|
|
426
480
|
if @extensions.frozen?
|
|
427
481
|
@extensions = @extensions.dup
|
|
@@ -442,7 +496,7 @@ module GraphQL
|
|
|
442
496
|
if new_extras.nil?
|
|
443
497
|
# Read the value
|
|
444
498
|
field_extras = @extras
|
|
445
|
-
if @resolver_class &&
|
|
499
|
+
if @resolver_class && !@resolver_class.extras.empty?
|
|
446
500
|
field_extras + @resolver_class.extras
|
|
447
501
|
else
|
|
448
502
|
field_extras
|
|
@@ -471,7 +525,7 @@ module GraphQL
|
|
|
471
525
|
if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
|
|
472
526
|
max_possible_page_size = arguments[:last]
|
|
473
527
|
end
|
|
474
|
-
elsif arguments.is_a?(GraphQL::UnauthorizedError)
|
|
528
|
+
elsif arguments.is_a?(GraphQL::ExecutionError) || arguments.is_a?(GraphQL::UnauthorizedError)
|
|
475
529
|
raise arguments
|
|
476
530
|
end
|
|
477
531
|
|
|
@@ -562,19 +616,40 @@ module GraphQL
|
|
|
562
616
|
end
|
|
563
617
|
end
|
|
564
618
|
|
|
619
|
+
def freeze
|
|
620
|
+
type
|
|
621
|
+
owner_type
|
|
622
|
+
arguments_statically_coercible?
|
|
623
|
+
connection?
|
|
624
|
+
super
|
|
625
|
+
end
|
|
626
|
+
|
|
565
627
|
class MissingReturnTypeError < GraphQL::Error; end
|
|
566
628
|
attr_writer :type
|
|
567
629
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
630
|
+
# Get or set the return type of this field.
|
|
631
|
+
#
|
|
632
|
+
# It may return nil if no type was configured or if the given definition block wasn't called yet.
|
|
633
|
+
# @param new_type [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List] A GraphQL return type
|
|
634
|
+
# @return [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List, nil] the configured type for this field
|
|
635
|
+
def type(new_type = NOT_CONFIGURED)
|
|
636
|
+
if NOT_CONFIGURED.equal?(new_type)
|
|
637
|
+
if @resolver_class
|
|
638
|
+
return_type = @return_type_expr || @resolver_class.type_expr
|
|
639
|
+
if return_type.nil?
|
|
640
|
+
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)"
|
|
641
|
+
end
|
|
642
|
+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
|
643
|
+
Member::BuildType.parse_type(return_type, null: nullable)
|
|
644
|
+
elsif !@return_type_expr.nil?
|
|
645
|
+
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
|
573
646
|
end
|
|
574
|
-
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
|
575
|
-
Member::BuildType.parse_type(return_type, null: nullable)
|
|
576
647
|
else
|
|
577
|
-
@
|
|
648
|
+
@return_type_expr = new_type
|
|
649
|
+
# If `type` is set in the definition block, then the `connection_extension: ...` given as a keyword won't be used, hmm...
|
|
650
|
+
# Also, arguments added by `connection_extension` will clobber anything previously defined,
|
|
651
|
+
# so `type(...)` should go first.
|
|
652
|
+
set_pagination_extensions(connection_extension: self.class.connection_extension)
|
|
578
653
|
end
|
|
579
654
|
rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
|
|
580
655
|
# Let this propagate up
|
|
@@ -606,7 +681,7 @@ module GraphQL
|
|
|
606
681
|
using_arg_values = false
|
|
607
682
|
end
|
|
608
683
|
|
|
609
|
-
args = context.
|
|
684
|
+
args = context.types.arguments(self)
|
|
610
685
|
args.each do |arg|
|
|
611
686
|
arg_key = arg.keyword
|
|
612
687
|
if arg_values.key?(arg_key)
|
|
@@ -679,7 +754,7 @@ module GraphQL
|
|
|
679
754
|
method_to_call = resolver_method
|
|
680
755
|
method_receiver = obj
|
|
681
756
|
# Call the method with kwargs, if there are any
|
|
682
|
-
if ruby_kwargs.
|
|
757
|
+
if !ruby_kwargs.empty?
|
|
683
758
|
obj.public_send(resolver_method, **ruby_kwargs)
|
|
684
759
|
else
|
|
685
760
|
obj.public_send(resolver_method)
|
|
@@ -699,7 +774,7 @@ module GraphQL
|
|
|
699
774
|
elsif inner_object.respond_to?(@method_sym)
|
|
700
775
|
method_to_call = @method_sym
|
|
701
776
|
method_receiver = obj.object
|
|
702
|
-
if ruby_kwargs.
|
|
777
|
+
if !ruby_kwargs.empty?
|
|
703
778
|
inner_object.public_send(@method_sym, **ruby_kwargs)
|
|
704
779
|
else
|
|
705
780
|
inner_object.public_send(@method_sym)
|
|
@@ -786,7 +861,7 @@ module GraphQL
|
|
|
786
861
|
unsatisfied_ruby_kwargs.clear
|
|
787
862
|
end
|
|
788
863
|
|
|
789
|
-
if unsatisfied_ruby_kwargs.
|
|
864
|
+
if !unsatisfied_ruby_kwargs.empty? || !unsatisfied_method_params.empty?
|
|
790
865
|
raise FieldImplementationFailed.new, <<-ERR
|
|
791
866
|
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
|
792
867
|
|
|
@@ -885,6 +960,20 @@ ERR
|
|
|
885
960
|
raise ArgumentError, "Invalid complexity for #{self.path}: #{own_complexity.inspect}"
|
|
886
961
|
end
|
|
887
962
|
end
|
|
963
|
+
|
|
964
|
+
def set_pagination_extensions(connection_extension:)
|
|
965
|
+
# This should run before connection extension,
|
|
966
|
+
# but should it run after the definition block?
|
|
967
|
+
if scoped?
|
|
968
|
+
self.extension(ScopeExtension, call_after_define: false)
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
# The problem with putting this after the definition_block
|
|
972
|
+
# is that it would override arguments
|
|
973
|
+
if connection? && connection_extension
|
|
974
|
+
self.extension(connection_extension, call_after_define: false)
|
|
975
|
+
end
|
|
976
|
+
end
|
|
888
977
|
end
|
|
889
978
|
end
|
|
890
979
|
end
|
|
@@ -32,7 +32,7 @@ module GraphQL
|
|
|
32
32
|
input_kwargs = {}
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
if input_kwargs.
|
|
35
|
+
if !input_kwargs.empty?
|
|
36
36
|
super(**input_kwargs)
|
|
37
37
|
else
|
|
38
38
|
super()
|
|
@@ -47,6 +47,7 @@ module GraphQL
|
|
|
47
47
|
def dummy
|
|
48
48
|
@dummy ||= begin
|
|
49
49
|
d = Class.new(GraphQL::Schema::Resolver)
|
|
50
|
+
d.graphql_name "#{self.graphql_name}DummyResolver"
|
|
50
51
|
d.argument_class(self.argument_class)
|
|
51
52
|
# TODO make this lazier?
|
|
52
53
|
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
|
|
@@ -135,6 +136,8 @@ module GraphQL
|
|
|
135
136
|
super || "Autogenerated input type of #{self.mutation.graphql_name}"
|
|
136
137
|
end
|
|
137
138
|
end
|
|
139
|
+
# For compatibility, in case no arguments are defined:
|
|
140
|
+
has_no_arguments(true)
|
|
138
141
|
mutation(mutation_class)
|
|
139
142
|
# these might be inherited:
|
|
140
143
|
mutation_args.each do |arg|
|
|
@@ -148,7 +151,8 @@ module GraphQL
|
|
|
148
151
|
|
|
149
152
|
def authorize_arguments(args, values)
|
|
150
153
|
# remove the `input` wrapper to match values
|
|
151
|
-
|
|
154
|
+
input_type = args.find { |a| a.graphql_name == "input" }.type.unwrap
|
|
155
|
+
input_args = context.types.arguments(input_type)
|
|
152
156
|
super(input_args, values)
|
|
153
157
|
end
|
|
154
158
|
end
|