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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphQL
|
|
4
|
+
class Schema
|
|
5
|
+
class Member
|
|
6
|
+
# @api public
|
|
7
|
+
# Shared methods for working with {Dataloader} inside GraphQL runtime objects.
|
|
8
|
+
module HasDataloader
|
|
9
|
+
# @return [GraphQL::Dataloader] The dataloader for the currently-running query
|
|
10
|
+
def dataloader
|
|
11
|
+
context.dataloader
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# A shortcut method for loading a key from a source.
|
|
15
|
+
# Identical to `dataloader.with(source_class, *source_args).load(load_key)`
|
|
16
|
+
# @param source_class [Class<GraphQL::Dataloader::Source>]
|
|
17
|
+
# @param source_args [Array<Object>] Any extra parameters defined in `source_class`'s `initialize` method
|
|
18
|
+
# @param load_key [Object] The key to look up using `def fetch`
|
|
19
|
+
def dataload(source_class, *source_args, load_key)
|
|
20
|
+
dataloader.with(source_class, *source_args).load(load_key)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Find an object with ActiveRecord via {Dataloader::ActiveRecordSource}.
|
|
24
|
+
# @param model [Class<ActiveRecord::Base>]
|
|
25
|
+
# @param find_by_value [Object] Usually an `id`, might be another value if `find_by:` is also provided
|
|
26
|
+
# @param find_by [Symbol, String] A column name to look the record up by. (Defaults to the model's primary key.)
|
|
27
|
+
# @return [ActiveRecord::Base, nil]
|
|
28
|
+
# @example Finding a record by ID
|
|
29
|
+
# dataload_record(Post, 5) # Like `Post.find(5)`, but dataloaded
|
|
30
|
+
# @example Finding a record by another attribute
|
|
31
|
+
# dataload_record(User, "matz", find_by: :handle) # Like `User.find_by(handle: "matz")`, but dataloaded
|
|
32
|
+
def dataload_record(model, find_by_value, find_by: nil)
|
|
33
|
+
source = if find_by
|
|
34
|
+
dataloader.with(Dataloader::ActiveRecordSource, model, find_by: find_by)
|
|
35
|
+
else
|
|
36
|
+
dataloader.with(Dataloader::ActiveRecordSource, model)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
source.load(find_by_value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Look up an associated record using a Rails association (via {Dataloader::ActiveRecordAssociationSource})
|
|
43
|
+
# @param association_name [Symbol] A `belongs_to` or `has_one` association. (If a `has_many` association is named here, it will be selected without pagination.)
|
|
44
|
+
# @param record [ActiveRecord::Base] The object that the association belongs to.
|
|
45
|
+
# @param scope [ActiveRecord::Relation] A scope to look up the associated record in
|
|
46
|
+
# @return [ActiveRecord::Base, nil] The associated record, if there is one
|
|
47
|
+
# @example Looking up a belongs_to on the current object
|
|
48
|
+
# dataload_association(:parent) # Equivalent to `object.parent`, but dataloaded
|
|
49
|
+
# @example Looking up an associated record on some other object
|
|
50
|
+
# dataload_association(comment, :post) # Equivalent to `comment.post`, but dataloaded
|
|
51
|
+
def dataload_association(record = object, association_name, scope: nil)
|
|
52
|
+
source = if scope
|
|
53
|
+
dataloader.with(Dataloader::ActiveRecordAssociationSource, association_name, scope)
|
|
54
|
+
else
|
|
55
|
+
dataloader.with(Dataloader::ActiveRecordAssociationSource, association_name)
|
|
56
|
+
end
|
|
57
|
+
source.load(record)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -18,6 +18,21 @@ module GraphQL
|
|
|
18
18
|
directive(GraphQL::Schema::Directive::Deprecated, reason: text)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def self.extended(child_class)
|
|
23
|
+
super
|
|
24
|
+
child_class.extend(ClassMethods)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def deprecation_reason(new_reason = NOT_CONFIGURED)
|
|
29
|
+
if NOT_CONFIGURED.equal?(new_reason)
|
|
30
|
+
super()
|
|
31
|
+
else
|
|
32
|
+
self.deprecation_reason = new_reason
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
21
36
|
end
|
|
22
37
|
end
|
|
23
38
|
end
|
|
@@ -55,14 +55,14 @@ module GraphQL
|
|
|
55
55
|
else
|
|
56
56
|
GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
57
57
|
end
|
|
58
|
-
if inherited_directives.
|
|
58
|
+
if !inherited_directives.empty? && directives
|
|
59
59
|
dirs = []
|
|
60
60
|
merge_directives(dirs, inherited_directives)
|
|
61
61
|
merge_directives(dirs, directives)
|
|
62
62
|
dirs
|
|
63
63
|
elsif directives
|
|
64
64
|
directives
|
|
65
|
-
elsif inherited_directives.
|
|
65
|
+
elsif !inherited_directives.empty?
|
|
66
66
|
inherited_directives
|
|
67
67
|
else
|
|
68
68
|
GraphQL::EmptyObjects::EMPTY_ARRAY
|
|
@@ -71,7 +71,7 @@ module GraphQL
|
|
|
71
71
|
dirs = nil
|
|
72
72
|
schema_member.ancestors.reverse_each do |ancestor|
|
|
73
73
|
if ancestor.respond_to?(:own_directives) &&
|
|
74
|
-
(anc_dirs = ancestor.own_directives).
|
|
74
|
+
!(anc_dirs = ancestor.own_directives).empty?
|
|
75
75
|
dirs ||= []
|
|
76
76
|
merge_directives(dirs, anc_dirs)
|
|
77
77
|
end
|
|
@@ -91,7 +91,7 @@ module GraphQL
|
|
|
91
91
|
private
|
|
92
92
|
|
|
93
93
|
# Modify `target` by adding items from `dirs` such that:
|
|
94
|
-
# - Any name conflict is
|
|
94
|
+
# - Any name conflict is overridden by the incoming member of `dirs`
|
|
95
95
|
# - Any other member of `dirs` is appended
|
|
96
96
|
# @param target [Array<GraphQL::Schema::Directive>]
|
|
97
97
|
# @param dirs [Array<GraphQL::Schema::Directive>]
|
|
@@ -79,6 +79,18 @@ module GraphQL
|
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
+
# @param new_has_no_fields [Boolean] Call with `true` to make this Object type ignore the requirement to have any defined fields.
|
|
83
|
+
# @return [void]
|
|
84
|
+
def has_no_fields(new_has_no_fields)
|
|
85
|
+
@has_no_fields = new_has_no_fields
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @return [Boolean] `true` if `has_no_fields(true)` was configued
|
|
90
|
+
def has_no_fields?
|
|
91
|
+
@has_no_fields
|
|
92
|
+
end
|
|
93
|
+
|
|
82
94
|
# @return [Hash<String => GraphQL::Schema::Field, Array<GraphQL::Schema::Field>>] Fields defined on this class _specifically_, not parent classes
|
|
83
95
|
def own_fields
|
|
84
96
|
@own_fields ||= {}
|
|
@@ -99,11 +111,12 @@ module GraphQL
|
|
|
99
111
|
module InterfaceMethods
|
|
100
112
|
def get_field(field_name, context = GraphQL::Query::NullContext.instance)
|
|
101
113
|
warden = Warden.from_context(context)
|
|
114
|
+
skip_visible = context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Visibility::Profile)
|
|
102
115
|
for ancestor in ancestors
|
|
103
116
|
if ancestor.respond_to?(:own_fields) &&
|
|
104
117
|
(f_entry = ancestor.own_fields[field_name]) &&
|
|
105
|
-
(
|
|
106
|
-
return
|
|
118
|
+
(skip_visible || (f_entry = Warden.visible_entry?(:visible_field?, f_entry, context, warden)))
|
|
119
|
+
return f_entry
|
|
107
120
|
end
|
|
108
121
|
end
|
|
109
122
|
nil
|
|
@@ -120,7 +133,7 @@ module GraphQL
|
|
|
120
133
|
# Choose the most local definition that passes `.visible?` --
|
|
121
134
|
# stop checking for fields by name once one has been found.
|
|
122
135
|
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
|
123
|
-
visible_fields[field_name] = f
|
|
136
|
+
visible_fields[field_name] = f.ensure_loaded
|
|
124
137
|
end
|
|
125
138
|
end
|
|
126
139
|
end
|
|
@@ -134,13 +147,14 @@ module GraphQL
|
|
|
134
147
|
# Objects need to check that the interface implementation is visible, too
|
|
135
148
|
warden = Warden.from_context(context)
|
|
136
149
|
ancs = ancestors
|
|
150
|
+
skip_visible = context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Visibility::Profile)
|
|
137
151
|
i = 0
|
|
138
152
|
while (ancestor = ancs[i])
|
|
139
153
|
if ancestor.respond_to?(:own_fields) &&
|
|
140
154
|
visible_interface_implementation?(ancestor, context, warden) &&
|
|
141
155
|
(f_entry = ancestor.own_fields[field_name]) &&
|
|
142
|
-
(
|
|
143
|
-
return
|
|
156
|
+
(skip_visible || (f_entry = Warden.visible_entry?(:visible_field?, f_entry, context, warden)))
|
|
157
|
+
return (skip_visible ? f_entry : f_entry.ensure_loaded)
|
|
144
158
|
end
|
|
145
159
|
i += 1
|
|
146
160
|
end
|
|
@@ -153,17 +167,22 @@ module GraphQL
|
|
|
153
167
|
warden = Warden.from_context(context)
|
|
154
168
|
# Local overrides take precedence over inherited fields
|
|
155
169
|
visible_fields = {}
|
|
170
|
+
had_any_fields_at_all = false
|
|
156
171
|
for ancestor in ancestors
|
|
157
172
|
if ancestor.respond_to?(:own_fields) && visible_interface_implementation?(ancestor, context, warden)
|
|
158
173
|
ancestor.own_fields.each do |field_name, fields_entry|
|
|
174
|
+
had_any_fields_at_all = true
|
|
159
175
|
# Choose the most local definition that passes `.visible?` --
|
|
160
176
|
# stop checking for fields by name once one has been found.
|
|
161
177
|
if !visible_fields.key?(field_name) && (f = Warden.visible_entry?(:visible_field?, fields_entry, context, warden))
|
|
162
|
-
visible_fields[field_name] = f
|
|
178
|
+
visible_fields[field_name] = f.ensure_loaded
|
|
163
179
|
end
|
|
164
180
|
end
|
|
165
181
|
end
|
|
166
182
|
end
|
|
183
|
+
if !had_any_fields_at_all && !has_no_fields?
|
|
184
|
+
warn(GraphQL::Schema::Object::FieldsAreRequiredError.new(self).message + "\n\nThis will raise an error in a future GraphQL-Ruby version.")
|
|
185
|
+
end
|
|
167
186
|
visible_fields
|
|
168
187
|
end
|
|
169
188
|
end
|
|
@@ -186,6 +205,7 @@ module GraphQL
|
|
|
186
205
|
subclass.class_exec do
|
|
187
206
|
@own_fields ||= nil
|
|
188
207
|
@field_class ||= nil
|
|
208
|
+
@has_no_fields ||= false
|
|
189
209
|
end
|
|
190
210
|
end
|
|
191
211
|
|
|
@@ -8,8 +8,8 @@ module GraphQL
|
|
|
8
8
|
new_memberships = []
|
|
9
9
|
new_interfaces.each do |int|
|
|
10
10
|
if int.is_a?(Module)
|
|
11
|
-
unless int.include?(GraphQL::Schema::Interface)
|
|
12
|
-
raise "#{int} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules."
|
|
11
|
+
unless int.include?(GraphQL::Schema::Interface) && !int.is_a?(Class)
|
|
12
|
+
raise "#{int.respond_to?(:graphql_name) ? "#{int.graphql_name} (#{int})" : int.inspect} cannot be implemented since it's not a GraphQL Interface. Use `include` for plain Ruby modules."
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
new_memberships << int.type_membership_class.new(int, self, **options)
|
|
@@ -24,7 +24,7 @@ module GraphQL
|
|
|
24
24
|
implements(next_interface)
|
|
25
25
|
end
|
|
26
26
|
elsif int.is_a?(String) || int.is_a?(GraphQL::Schema::LateBoundType)
|
|
27
|
-
if options.
|
|
27
|
+
if !options.empty?
|
|
28
28
|
raise ArgumentError, "`implements(...)` doesn't support options with late-loaded types yet. Remove #{options} and open an issue to request this feature."
|
|
29
29
|
end
|
|
30
30
|
new_memberships << int
|
|
@@ -73,13 +73,13 @@ module GraphQL
|
|
|
73
73
|
def interfaces(context = GraphQL::Query::NullContext.instance)
|
|
74
74
|
visible_interfaces = super
|
|
75
75
|
inherited_interfaces = superclass.interfaces(context)
|
|
76
|
-
if visible_interfaces.
|
|
77
|
-
if inherited_interfaces.
|
|
76
|
+
if !visible_interfaces.empty?
|
|
77
|
+
if !inherited_interfaces.empty?
|
|
78
78
|
visible_interfaces.concat(inherited_interfaces)
|
|
79
79
|
visible_interfaces.uniq!
|
|
80
80
|
end
|
|
81
81
|
visible_interfaces
|
|
82
|
-
elsif inherited_interfaces.
|
|
82
|
+
elsif !inherited_interfaces.empty?
|
|
83
83
|
inherited_interfaces
|
|
84
84
|
else
|
|
85
85
|
EmptyObjects::EMPTY_ARRAY
|
|
@@ -7,7 +7,11 @@ module GraphQL
|
|
|
7
7
|
module HasUnresolvedTypeError
|
|
8
8
|
private
|
|
9
9
|
def add_unresolved_type_error(child_class)
|
|
10
|
-
child_class.
|
|
10
|
+
if child_class.name # Don't set this for anonymous classes
|
|
11
|
+
child_class.const_set(:UnresolvedTypeError, Class.new(GraphQL::UnresolvedTypeError))
|
|
12
|
+
else
|
|
13
|
+
child_class.const_set(:UnresolvedTypeError, UnresolvedTypeError)
|
|
14
|
+
end
|
|
11
15
|
end
|
|
12
16
|
end
|
|
13
17
|
end
|
|
@@ -76,7 +76,7 @@ module GraphQL
|
|
|
76
76
|
|
|
77
77
|
private
|
|
78
78
|
|
|
79
|
-
# If one of
|
|
79
|
+
# If one of these values is accessed, initialize all the instance variables to retain
|
|
80
80
|
# a consistent object shape.
|
|
81
81
|
def initialize_relay_metadata
|
|
82
82
|
if !defined?(@connection_type)
|
|
@@ -4,21 +4,34 @@ module GraphQL
|
|
|
4
4
|
class Schema
|
|
5
5
|
class Member
|
|
6
6
|
module TypeSystemHelpers
|
|
7
|
-
def initialize(
|
|
7
|
+
def initialize(...)
|
|
8
8
|
super
|
|
9
9
|
@to_non_null_type ||= nil
|
|
10
10
|
@to_list_type ||= nil
|
|
11
11
|
end
|
|
12
|
-
ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
|
|
13
12
|
|
|
14
13
|
# @return [Schema::NonNull] Make a non-null-type representation of this type
|
|
15
14
|
def to_non_null_type
|
|
16
|
-
@to_non_null_type
|
|
15
|
+
@to_non_null_type || begin
|
|
16
|
+
t = GraphQL::Schema::NonNull.new(self)
|
|
17
|
+
if frozen?
|
|
18
|
+
t
|
|
19
|
+
else
|
|
20
|
+
@to_non_null_type = t
|
|
21
|
+
end
|
|
22
|
+
end
|
|
17
23
|
end
|
|
18
24
|
|
|
19
25
|
# @return [Schema::List] Make a list-type representation of this type
|
|
20
26
|
def to_list_type
|
|
21
|
-
@to_list_type
|
|
27
|
+
@to_list_type || begin
|
|
28
|
+
t = GraphQL::Schema::List.new(self)
|
|
29
|
+
if frozen?
|
|
30
|
+
t
|
|
31
|
+
else
|
|
32
|
+
@to_list_type = t
|
|
33
|
+
end
|
|
34
|
+
end
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
# @return [Boolean] true if this is a non-nullable type. A nullable list of non-nullables is considered nullable.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
require 'graphql/schema/member/base_dsl_methods'
|
|
3
3
|
require 'graphql/schema/member/graphql_type_names'
|
|
4
4
|
require 'graphql/schema/member/has_ast_node'
|
|
5
|
+
require 'graphql/schema/member/has_dataloader'
|
|
5
6
|
require 'graphql/schema/member/has_directives'
|
|
6
7
|
require 'graphql/schema/member/has_deprecation_reason'
|
|
7
8
|
require 'graphql/schema/member/has_interfaces'
|
|
@@ -62,6 +62,13 @@ module GraphQL
|
|
|
62
62
|
extend GraphQL::Schema::Member::HasFields
|
|
63
63
|
extend GraphQL::Schema::Resolver::HasPayloadType
|
|
64
64
|
|
|
65
|
+
# @api private
|
|
66
|
+
def call_resolve(_args_hash)
|
|
67
|
+
# Clear any cached values from `loads` or authorization:
|
|
68
|
+
dataloader.clear_cache
|
|
69
|
+
super
|
|
70
|
+
end
|
|
71
|
+
|
|
65
72
|
class << self
|
|
66
73
|
def visible?(context)
|
|
67
74
|
true
|
|
@@ -7,6 +7,15 @@ module GraphQL
|
|
|
7
7
|
class Object < GraphQL::Schema::Member
|
|
8
8
|
extend GraphQL::Schema::Member::HasFields
|
|
9
9
|
extend GraphQL::Schema::Member::HasInterfaces
|
|
10
|
+
include Member::HasDataloader
|
|
11
|
+
|
|
12
|
+
# Raised when an Object doesn't have any field defined and hasn't explicitly opted out of this requirement
|
|
13
|
+
class FieldsAreRequiredError < GraphQL::Error
|
|
14
|
+
def initialize(object_type)
|
|
15
|
+
message = "Object types must have fields, but #{object_type.graphql_name} doesn't have any. Define a field for this type, remove it from your schema, or add `has_no_fields(true)` to its definition."
|
|
16
|
+
super(message)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
10
19
|
|
|
11
20
|
# @return [Object] the application object this type is wrapping
|
|
12
21
|
attr_reader :object
|
|
@@ -57,20 +66,28 @@ module GraphQL
|
|
|
57
66
|
# @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
|
|
58
67
|
# @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
|
|
59
68
|
def authorized_new(object, context)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
context.query.current_trace.begin_authorized(self, object, context)
|
|
70
|
+
begin
|
|
71
|
+
maybe_lazy_auth_val = context.query.current_trace.authorized(query: context.query, type: self, object: object) do
|
|
72
|
+
begin
|
|
73
|
+
authorized?(object, context)
|
|
74
|
+
rescue GraphQL::UnauthorizedError => err
|
|
75
|
+
context.schema.unauthorized_object(err)
|
|
76
|
+
rescue StandardError => err
|
|
77
|
+
context.query.handle_or_reraise(err)
|
|
78
|
+
end
|
|
67
79
|
end
|
|
80
|
+
ensure
|
|
81
|
+
context.query.current_trace.end_authorized(self, object, context, maybe_lazy_auth_val)
|
|
68
82
|
end
|
|
69
83
|
|
|
70
84
|
auth_val = if context.schema.lazy?(maybe_lazy_auth_val)
|
|
71
85
|
GraphQL::Execution::Lazy.new do
|
|
86
|
+
context.query.current_trace.begin_authorized(self, object, context)
|
|
72
87
|
context.query.current_trace.authorized_lazy(query: context.query, type: self, object: object) do
|
|
73
|
-
context.schema.sync_lazy(maybe_lazy_auth_val)
|
|
88
|
+
res = context.schema.sync_lazy(maybe_lazy_auth_val)
|
|
89
|
+
context.query.current_trace.end_authorized(self, object, context, res)
|
|
90
|
+
res
|
|
74
91
|
end
|
|
75
92
|
end
|
|
76
93
|
else
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module GraphQL
|
|
3
|
+
class Schema
|
|
4
|
+
module RactorShareable
|
|
5
|
+
def self.extended(schema_class)
|
|
6
|
+
schema_class.extend(SchemaExtension)
|
|
7
|
+
schema_class.freeze_schema
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module SchemaExtension
|
|
11
|
+
|
|
12
|
+
def freeze_error_handlers(handlers)
|
|
13
|
+
handlers[:subclass_handlers].default_proc = nil
|
|
14
|
+
handlers[:subclass_handlers].each do |_class, subclass_handlers|
|
|
15
|
+
freeze_error_handlers(subclass_handlers)
|
|
16
|
+
end
|
|
17
|
+
Ractor.make_shareable(handlers)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def freeze_schema
|
|
21
|
+
# warm some ivars:
|
|
22
|
+
default_analysis_engine
|
|
23
|
+
default_execution_strategy
|
|
24
|
+
GraphQL.default_parser
|
|
25
|
+
default_logger
|
|
26
|
+
freeze_error_handlers(error_handlers)
|
|
27
|
+
# TODO: this freezes errors of parent classes which could cause trouble
|
|
28
|
+
parent_class = superclass
|
|
29
|
+
while parent_class.respond_to?(:error_handlers)
|
|
30
|
+
freeze_error_handlers(parent_class.error_handlers)
|
|
31
|
+
parent_class = parent_class.superclass
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
own_tracers.freeze
|
|
35
|
+
@frozen_tracers = tracers.freeze
|
|
36
|
+
own_trace_modes.each do |m|
|
|
37
|
+
trace_options_for(m)
|
|
38
|
+
build_trace_mode(m)
|
|
39
|
+
end
|
|
40
|
+
build_trace_mode(:default)
|
|
41
|
+
Ractor.make_shareable(@trace_options_for_mode)
|
|
42
|
+
Ractor.make_shareable(own_trace_modes)
|
|
43
|
+
Ractor.make_shareable(own_multiplex_analyzers)
|
|
44
|
+
@frozen_multiplex_analyzers = Ractor.make_shareable(multiplex_analyzers)
|
|
45
|
+
Ractor.make_shareable(own_query_analyzers)
|
|
46
|
+
@frozen_query_analyzers = Ractor.make_shareable(query_analyzers)
|
|
47
|
+
Ractor.make_shareable(own_plugins)
|
|
48
|
+
own_plugins.each do |(plugin, options)|
|
|
49
|
+
Ractor.make_shareable(plugin)
|
|
50
|
+
Ractor.make_shareable(options)
|
|
51
|
+
end
|
|
52
|
+
@frozen_plugins = Ractor.make_shareable(plugins)
|
|
53
|
+
Ractor.make_shareable(own_references_to)
|
|
54
|
+
@frozen_directives = Ractor.make_shareable(directives)
|
|
55
|
+
|
|
56
|
+
Ractor.make_shareable(visibility)
|
|
57
|
+
Ractor.make_shareable(introspection_system)
|
|
58
|
+
extend(FrozenMethods)
|
|
59
|
+
|
|
60
|
+
Ractor.make_shareable(self)
|
|
61
|
+
superclass.respond_to?(:freeze_schema) && superclass.freeze_schema
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module FrozenMethods
|
|
65
|
+
def tracers; @frozen_tracers; end
|
|
66
|
+
def multiplex_analyzers; @frozen_multiplex_analyzers; end
|
|
67
|
+
def query_analyzers; @frozen_query_analyzers; end
|
|
68
|
+
def plugins; @frozen_plugins; end
|
|
69
|
+
def directives; @frozen_directives; end
|
|
70
|
+
|
|
71
|
+
# This actually accumulates info during execution...
|
|
72
|
+
# How to support it?
|
|
73
|
+
def lazy?(_obj); false; end
|
|
74
|
+
def sync_lazy(obj); obj; end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -8,6 +8,7 @@ module GraphQL
|
|
|
8
8
|
# - Arguments, via `.argument(...)` helper, which will be applied to the field.
|
|
9
9
|
# - Return type, via `.type(..., null: ...)`, which will be applied to the field.
|
|
10
10
|
# - Description, via `.description(...)`, which will be applied to the field
|
|
11
|
+
# - Comment, via `.comment(...)`, which will be applied to the field
|
|
11
12
|
# - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
|
|
12
13
|
# - `#object` and `#context` accessors for use during `#resolve`.
|
|
13
14
|
#
|
|
@@ -19,12 +20,15 @@ module GraphQL
|
|
|
19
20
|
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
|
|
20
21
|
class Resolver
|
|
21
22
|
include Schema::Member::GraphQLTypeNames
|
|
22
|
-
# Really we only need description from here, but:
|
|
23
|
+
# Really we only need description & comment from here, but:
|
|
23
24
|
extend Schema::Member::BaseDSLMethods
|
|
24
25
|
extend GraphQL::Schema::Member::HasArguments
|
|
25
26
|
extend GraphQL::Schema::Member::HasValidators
|
|
26
27
|
include Schema::Member::HasPath
|
|
27
28
|
extend Schema::Member::HasPath
|
|
29
|
+
extend Schema::Member::HasDirectives
|
|
30
|
+
include Schema::Member::HasDataloader
|
|
31
|
+
extend Schema::Member::HasDeprecationReason
|
|
28
32
|
|
|
29
33
|
# @param object [Object] The application object that this field is being resolved on
|
|
30
34
|
# @param context [GraphQL::Query::Context]
|
|
@@ -35,7 +39,7 @@ module GraphQL
|
|
|
35
39
|
@field = field
|
|
36
40
|
# Since this hash is constantly rebuilt, cache it for this call
|
|
37
41
|
@arguments_by_keyword = {}
|
|
38
|
-
|
|
42
|
+
context.types.arguments(self.class).each do |arg|
|
|
39
43
|
@arguments_by_keyword[arg.keyword] = arg
|
|
40
44
|
end
|
|
41
45
|
@prepared_arguments = nil
|
|
@@ -47,11 +51,6 @@ module GraphQL
|
|
|
47
51
|
# @return [GraphQL::Query::Context]
|
|
48
52
|
attr_reader :context
|
|
49
53
|
|
|
50
|
-
# @return [GraphQL::Dataloader]
|
|
51
|
-
def dataloader
|
|
52
|
-
context.dataloader
|
|
53
|
-
end
|
|
54
|
-
|
|
55
54
|
# @return [GraphQL::Schema::Field]
|
|
56
55
|
attr_reader :field
|
|
57
56
|
|
|
@@ -65,7 +64,7 @@ module GraphQL
|
|
|
65
64
|
# @api private
|
|
66
65
|
def resolve_with_support(**args)
|
|
67
66
|
# First call the ready? hook which may raise
|
|
68
|
-
raw_ready_val = if args.
|
|
67
|
+
raw_ready_val = if !args.empty?
|
|
69
68
|
ready?(**args)
|
|
70
69
|
else
|
|
71
70
|
ready?
|
|
@@ -86,7 +85,7 @@ module GraphQL
|
|
|
86
85
|
@prepared_arguments = loaded_args
|
|
87
86
|
Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
|
|
88
87
|
# Then call `authorized?`, which may raise or may return a lazy object
|
|
89
|
-
raw_authorized_val = if loaded_args.
|
|
88
|
+
raw_authorized_val = if !loaded_args.empty?
|
|
90
89
|
authorized?(**loaded_args)
|
|
91
90
|
else
|
|
92
91
|
authorized?
|
|
@@ -103,11 +102,7 @@ module GraphQL
|
|
|
103
102
|
end
|
|
104
103
|
elsif authorized_val
|
|
105
104
|
# Finally, all the hooks have passed, so resolve it
|
|
106
|
-
|
|
107
|
-
public_send(self.class.resolve_method, **loaded_args)
|
|
108
|
-
else
|
|
109
|
-
public_send(self.class.resolve_method)
|
|
110
|
-
end
|
|
105
|
+
call_resolve(loaded_args)
|
|
111
106
|
else
|
|
112
107
|
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
|
113
108
|
end
|
|
@@ -117,6 +112,15 @@ module GraphQL
|
|
|
117
112
|
end
|
|
118
113
|
end
|
|
119
114
|
|
|
115
|
+
# @api private {GraphQL::Schema::Mutation} uses this to clear the dataloader cache
|
|
116
|
+
def call_resolve(args_hash)
|
|
117
|
+
if !args_hash.empty?
|
|
118
|
+
public_send(self.class.resolve_method, **args_hash)
|
|
119
|
+
else
|
|
120
|
+
public_send(self.class.resolve_method)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
120
124
|
# Do the work. Everything happens here.
|
|
121
125
|
# @return [Object] An object corresponding to the return type
|
|
122
126
|
def resolve(**args)
|
|
@@ -146,7 +150,7 @@ module GraphQL
|
|
|
146
150
|
# @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
|
|
147
151
|
def authorized?(**inputs)
|
|
148
152
|
arg_owner = @field # || self.class
|
|
149
|
-
args =
|
|
153
|
+
args = context.types.arguments(arg_owner)
|
|
150
154
|
authorize_arguments(args, inputs)
|
|
151
155
|
end
|
|
152
156
|
|
|
@@ -163,7 +167,7 @@ module GraphQL
|
|
|
163
167
|
private
|
|
164
168
|
|
|
165
169
|
def authorize_arguments(args, inputs)
|
|
166
|
-
args.
|
|
170
|
+
args.each do |argument|
|
|
167
171
|
arg_keyword = argument.keyword
|
|
168
172
|
if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
|
|
169
173
|
auth_result = argument.authorized?(self, arg_value, context)
|
|
@@ -176,10 +180,9 @@ module GraphQL
|
|
|
176
180
|
elsif auth_result == false
|
|
177
181
|
return auth_result
|
|
178
182
|
end
|
|
179
|
-
else
|
|
180
|
-
true
|
|
181
183
|
end
|
|
182
184
|
end
|
|
185
|
+
true
|
|
183
186
|
end
|
|
184
187
|
|
|
185
188
|
def load_arguments(args)
|
|
@@ -202,7 +205,7 @@ module GraphQL
|
|
|
202
205
|
end
|
|
203
206
|
|
|
204
207
|
# Avoid returning a lazy if none are needed
|
|
205
|
-
if prepare_lazies.
|
|
208
|
+
if !prepare_lazies.empty?
|
|
206
209
|
GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
|
|
207
210
|
else
|
|
208
211
|
prepared_args
|
|
@@ -388,7 +391,7 @@ module GraphQL
|
|
|
388
391
|
if superclass.respond_to?(:extensions)
|
|
389
392
|
s_exts = superclass.extensions
|
|
390
393
|
if own_exts
|
|
391
|
-
if s_exts.
|
|
394
|
+
if !s_exts.empty?
|
|
392
395
|
own_exts + s_exts
|
|
393
396
|
else
|
|
394
397
|
own_exts
|
|
@@ -401,11 +404,14 @@ module GraphQL
|
|
|
401
404
|
end
|
|
402
405
|
end
|
|
403
406
|
|
|
407
|
+
def inherited(child_class)
|
|
408
|
+
child_class.description(description)
|
|
409
|
+
super
|
|
410
|
+
end
|
|
411
|
+
|
|
404
412
|
private
|
|
405
413
|
|
|
406
|
-
|
|
407
|
-
@own_extensions
|
|
408
|
-
end
|
|
414
|
+
attr_reader :own_extensions
|
|
409
415
|
end
|
|
410
416
|
end
|
|
411
417
|
end
|
|
@@ -50,12 +50,7 @@ module GraphQL
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
if coerced_result.nil?
|
|
53
|
-
|
|
54
|
-
""
|
|
55
|
-
else
|
|
56
|
-
" #{GraphQL::Language.serialize(value)}"
|
|
57
|
-
end
|
|
58
|
-
Query::InputValidationResult.from_problem("Could not coerce value#{str_value} to #{graphql_name}")
|
|
53
|
+
Query::InputValidationResult.from_problem("Could not coerce value #{GraphQL::Language.serialize(value)} to #{graphql_name}")
|
|
59
54
|
elsif coerced_result.is_a?(GraphQL::CoercionError)
|
|
60
55
|
Query::InputValidationResult.from_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
|
|
61
56
|
else
|