graphql 2.0.32 → 2.5.22
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/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -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/query_depth.rb +58 -0
- 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/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -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/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -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 +24 -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 +96 -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 +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- 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 +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +363 -434
- data/lib/graphql/execution/interpreter.rb +91 -164
- data/lib/graphql/execution/lookahead.rb +105 -31
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +711 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +70 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +20 -6
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +26 -17
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +90 -61
- data/lib/graphql/language/lexer.rb +319 -193
- data/lib/graphql/language/nodes.rb +136 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +23 -83
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +30 -1
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +82 -144
- data/lib/graphql/query/null_context.rb +15 -18
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +126 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- 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 +75 -9
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -60
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +15 -49
- data/lib/graphql/schema/field/scope_extension.rb +23 -7
- data/lib/graphql/schema/field.rb +245 -118
- data/lib/graphql/schema/field_extension.rb +34 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +116 -60
- data/lib/graphql/schema/interface.rb +34 -16
- data/lib/graphql/schema/introspection_system.rb +8 -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 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -2
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +99 -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 +115 -15
- data/lib/graphql/schema/member/has_interfaces.rb +26 -12
- 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/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +34 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +90 -32
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -10
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- data/lib/graphql/schema/unique_within_type.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 +275 -103
- data/lib/graphql/schema.rb +950 -210
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/literal_validator.rb +6 -7
- 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 +5 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- 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 +21 -5
- data/lib/graphql/static_validation/validator.rb +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- 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 +21 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +21 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -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 +7 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- 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/active_record_backend.rb +74 -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 +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -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 +864 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- 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 +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +112 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +44 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -0
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +71 -54
- data/readme.md +12 -2
- metadata +233 -37
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- 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 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- 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/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
data/lib/graphql/schema/field.rb
CHANGED
|
@@ -8,6 +8,7 @@ module GraphQL
|
|
|
8
8
|
include GraphQL::Schema::Member::HasArguments
|
|
9
9
|
include GraphQL::Schema::Member::HasArguments::FieldConfigured
|
|
10
10
|
include GraphQL::Schema::Member::HasAstNode
|
|
11
|
+
include GraphQL::Schema::Member::HasAuthorization
|
|
11
12
|
include GraphQL::Schema::Member::HasPath
|
|
12
13
|
include GraphQL::Schema::Member::HasValidators
|
|
13
14
|
extend GraphQL::Schema::FindInheritedValue
|
|
@@ -41,6 +42,32 @@ module GraphQL
|
|
|
41
42
|
end
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# @return [String, nil]
|
|
46
|
+
def deprecation_reason
|
|
47
|
+
super || @resolver_class&.deprecation_reason
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def directives
|
|
51
|
+
if @resolver_class && !(r_dirs = @resolver_class.directives).empty?
|
|
52
|
+
if !(own_dirs = super).empty?
|
|
53
|
+
new_dirs = own_dirs.dup
|
|
54
|
+
r_dirs.each do |r_dir|
|
|
55
|
+
if r_dir.class.repeatable? ||
|
|
56
|
+
( (r_dir_name = r_dir.graphql_name) &&
|
|
57
|
+
(!new_dirs.any? { |d| d.graphql_name == r_dir_name })
|
|
58
|
+
)
|
|
59
|
+
new_dirs << r_dir
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
new_dirs
|
|
63
|
+
else
|
|
64
|
+
r_dirs
|
|
65
|
+
end
|
|
66
|
+
else
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
44
71
|
# @return [Class] The thing this field was defined on (type, mutation, resolver)
|
|
45
72
|
attr_accessor :owner
|
|
46
73
|
|
|
@@ -69,7 +96,7 @@ module GraphQL
|
|
|
69
96
|
end
|
|
70
97
|
|
|
71
98
|
def inspect
|
|
72
|
-
"#<#{self.class} #{path}#{all_argument_definitions.
|
|
99
|
+
"#<#{self.class} #{path}#{!all_argument_definitions.empty? ? "(...)" : ""}: #{type.to_type_signature}>"
|
|
73
100
|
end
|
|
74
101
|
|
|
75
102
|
alias :mutation :resolver
|
|
@@ -83,48 +110,6 @@ module GraphQL
|
|
|
83
110
|
end
|
|
84
111
|
attr_writer :subscription_scope
|
|
85
112
|
|
|
86
|
-
# Create a field instance from a list of arguments, keyword arguments, and a block.
|
|
87
|
-
#
|
|
88
|
-
# This method implements prioritization between the `resolver` or `mutation` defaults
|
|
89
|
-
# and the local overrides via other keywords.
|
|
90
|
-
#
|
|
91
|
-
# It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
|
|
92
|
-
# @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
|
|
93
|
-
# @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
|
|
94
|
-
# @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
|
|
95
|
-
# @return [GraphQL::Schema:Field] an instance of `self`
|
|
96
|
-
# @see {.initialize} for other options
|
|
97
|
-
def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
|
|
98
|
-
if (resolver_class = resolver || mutation || subscription)
|
|
99
|
-
# Add a reference to that parent class
|
|
100
|
-
kwargs[:resolver_class] = resolver_class
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
if name
|
|
104
|
-
kwargs[:name] = name
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
if !type.nil?
|
|
108
|
-
if desc
|
|
109
|
-
if kwargs[:description]
|
|
110
|
-
raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
kwargs[:description] = desc
|
|
114
|
-
kwargs[:type] = type
|
|
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
|
|
117
|
-
kwargs[:description] = type
|
|
118
|
-
else
|
|
119
|
-
kwargs[:type] = type
|
|
120
|
-
end
|
|
121
|
-
if type.is_a?(Class) && type < GraphQL::Schema::Mutation
|
|
122
|
-
raise ArgumentError, "Use `field #{name.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
new(**kwargs, &block)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
113
|
# Can be set with `connection: true|false` or inferred from a type name ending in `*Connection`
|
|
129
114
|
# @return [Boolean] if true, this field will be wrapped with Relay connection behavior
|
|
130
115
|
def connection?
|
|
@@ -134,11 +119,16 @@ module GraphQL
|
|
|
134
119
|
Member::BuildType.to_type_name(@return_type_expr)
|
|
135
120
|
elsif @resolver_class && @resolver_class.type
|
|
136
121
|
Member::BuildType.to_type_name(@resolver_class.type)
|
|
137
|
-
|
|
122
|
+
elsif type
|
|
138
123
|
# As a last ditch, try to force loading the return type:
|
|
139
124
|
type.unwrap.name
|
|
140
125
|
end
|
|
141
|
-
|
|
126
|
+
if return_type_name
|
|
127
|
+
@connection = return_type_name.end_with?("Connection") && return_type_name != "Connection"
|
|
128
|
+
else
|
|
129
|
+
# TODO set this when type is set by method
|
|
130
|
+
false # not loaded yet?
|
|
131
|
+
end
|
|
142
132
|
else
|
|
143
133
|
@connection
|
|
144
134
|
end
|
|
@@ -195,6 +185,7 @@ module GraphQL
|
|
|
195
185
|
# @param owner [Class] The type that this field belongs to
|
|
196
186
|
# @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
|
|
197
187
|
# @param description [String] Field description
|
|
188
|
+
# @param comment [String] Field comment
|
|
198
189
|
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
|
|
199
190
|
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
|
|
200
191
|
# @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`)
|
|
@@ -202,6 +193,11 @@ module GraphQL
|
|
|
202
193
|
# @param resolver_method [Symbol] The method on the type to call to resolve this field (defaults to `name`)
|
|
203
194
|
# @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
|
|
204
195
|
# @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
|
|
196
|
+
# @param resolve_static [Symbol, true, nil] Used by {Schema.execute_next} to produce a single value, shared by all objects which resolve this field. Called on the owner type class with `context, **arguments`
|
|
197
|
+
# @param resolve_batch [Symbol, true, nil] Used by {Schema.execute_next} map `objects` to a same-sized Array of results. Called on the owner type class with `objects, context, **arguments`.
|
|
198
|
+
# @param resolve_each [Symbol, true, nil] Used by {Schema.execute_next} to get a value value for each item. Called on the owner type class with `object, context, **arguments`.
|
|
199
|
+
# @param resolve_legacy_instance_method [Symbol, true, nil] Used by {Schema.execute_next} to get a value value for each item. Calls an instance method on the object type class.
|
|
200
|
+
# @param dataload [Class, Hash] Shorthand for making dataloader calls
|
|
205
201
|
# @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
202
|
# @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
|
|
207
203
|
# @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
|
|
@@ -218,14 +214,19 @@ module GraphQL
|
|
|
218
214
|
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
|
|
219
215
|
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
|
|
220
216
|
# @param validates [Array<Hash>] Configurations for validating this field
|
|
221
|
-
# @fallback_value [Object] A fallback value if the method is not defined
|
|
222
|
-
|
|
217
|
+
# @param fallback_value [Object] A fallback value if the method is not defined
|
|
218
|
+
# @param dynamic_introspection [Boolean] (Private, used by GraphQL-Ruby)
|
|
219
|
+
# @param relay_node_field [Boolean] (Private, used by GraphQL-Ruby)
|
|
220
|
+
# @param relay_nodes_field [Boolean] (Private, used by GraphQL-Ruby)
|
|
221
|
+
# @param extras [Array<:ast_node, :parent, :lookahead, :owner, :execution_errors, :graphql_name, :argument_details, Symbol>] Extra arguments to be injected into the resolver for this field
|
|
222
|
+
# @param definition_block [Proc] an additional block for configuring the field. Receive the field as a block param, or, if no block params are defined, then the block is `instance_eval`'d on the new {Field}.
|
|
223
|
+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, comment: NOT_CONFIGURED, deprecation_reason: nil, method: nil, resolve_legacy_instance_method: nil, resolve_static: nil, resolve_each: nil, resolve_batch: 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, dataload: 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
224
|
if name.nil?
|
|
224
225
|
raise ArgumentError, "missing first `name` argument or keyword `name:`"
|
|
225
226
|
end
|
|
226
227
|
if !(resolver_class)
|
|
227
|
-
if type.nil?
|
|
228
|
-
raise ArgumentError, "missing second `type` argument or
|
|
228
|
+
if type.nil? && !block_given?
|
|
229
|
+
raise ArgumentError, "missing second `type` argument, keyword `type:`, or a block containing `type(...)`"
|
|
229
230
|
end
|
|
230
231
|
end
|
|
231
232
|
@original_name = name
|
|
@@ -235,6 +236,7 @@ module GraphQL
|
|
|
235
236
|
@name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
|
|
236
237
|
NameValidator.validate!(@name)
|
|
237
238
|
@description = description
|
|
239
|
+
@comment = comment
|
|
238
240
|
@type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
|
|
239
241
|
|
|
240
242
|
self.deprecation_reason = deprecation_reason
|
|
@@ -266,7 +268,38 @@ module GraphQL
|
|
|
266
268
|
@method_str = -method_name.to_s
|
|
267
269
|
@method_sym = method_name.to_sym
|
|
268
270
|
@resolver_method = (resolver_method || name_s).to_sym
|
|
271
|
+
|
|
272
|
+
if resolve_static
|
|
273
|
+
@execution_next_mode = :resolve_static
|
|
274
|
+
@execution_next_mode_key = resolve_static == true ? @method_sym : resolve_static
|
|
275
|
+
elsif resolve_batch
|
|
276
|
+
@execution_next_mode = :resolve_batch
|
|
277
|
+
@execution_next_mode_key = resolve_batch == true ? @method_sym : resolve_batch
|
|
278
|
+
elsif resolve_each
|
|
279
|
+
@execution_next_mode = :resolve_each
|
|
280
|
+
@execution_next_mode_key = resolve_each == true ? @method_sym : resolve_each
|
|
281
|
+
elsif hash_key
|
|
282
|
+
@execution_next_mode = :hash_key
|
|
283
|
+
@execution_next_mode_key = hash_key
|
|
284
|
+
elsif dig
|
|
285
|
+
@execution_next_mode = :dig
|
|
286
|
+
@execution_next_mode_key = dig
|
|
287
|
+
elsif resolver_class
|
|
288
|
+
@execution_next_mode = :resolver_class
|
|
289
|
+
@execution_next_mode_key = resolver_class
|
|
290
|
+
elsif resolve_legacy_instance_method
|
|
291
|
+
@execution_next_mode = :resolve_legacy_instance_method
|
|
292
|
+
@execution_next_mode_key = resolve_legacy_instance_method == true ? @method_sym : resolve_legacy_instance_method
|
|
293
|
+
elsif dataload
|
|
294
|
+
@execution_next_mode = :dataload
|
|
295
|
+
@execution_next_mode_key = dataload
|
|
296
|
+
else
|
|
297
|
+
@execution_next_mode = :direct_send
|
|
298
|
+
@execution_next_mode_key = @method_sym
|
|
299
|
+
end
|
|
300
|
+
|
|
269
301
|
@complexity = complexity
|
|
302
|
+
@dynamic_introspection = dynamic_introspection
|
|
270
303
|
@return_type_expr = type
|
|
271
304
|
@return_type_null = if !null.nil?
|
|
272
305
|
null
|
|
@@ -289,6 +322,7 @@ module GraphQL
|
|
|
289
322
|
@ast_node = ast_node
|
|
290
323
|
@method_conflict_warning = method_conflict_warning
|
|
291
324
|
@fallback_value = fallback_value
|
|
325
|
+
@definition_block = definition_block
|
|
292
326
|
|
|
293
327
|
arguments.each do |name, arg|
|
|
294
328
|
case arg
|
|
@@ -308,28 +342,17 @@ module GraphQL
|
|
|
308
342
|
|
|
309
343
|
@extensions = EMPTY_ARRAY
|
|
310
344
|
@call_after_define = false
|
|
311
|
-
|
|
312
|
-
# but should it run after the definition block?
|
|
313
|
-
if scoped?
|
|
314
|
-
self.extension(ScopeExtension)
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
# The problem with putting this after the definition_block
|
|
318
|
-
# is that it would override arguments
|
|
319
|
-
if connection? && connection_extension
|
|
320
|
-
self.extension(connection_extension)
|
|
321
|
-
end
|
|
322
|
-
|
|
345
|
+
set_pagination_extensions(connection_extension: NOT_CONFIGURED.equal?(connection_extension) ? self.class.connection_extension : connection_extension)
|
|
323
346
|
# Do this last so we have as much context as possible when initializing them:
|
|
324
|
-
if extensions.
|
|
347
|
+
if !extensions.empty?
|
|
325
348
|
self.extensions(extensions)
|
|
326
349
|
end
|
|
327
350
|
|
|
328
|
-
if resolver_class && resolver_class.extensions.
|
|
351
|
+
if resolver_class && !resolver_class.extensions.empty?
|
|
329
352
|
self.extensions(resolver_class.extensions)
|
|
330
353
|
end
|
|
331
354
|
|
|
332
|
-
if directives.
|
|
355
|
+
if !directives.empty?
|
|
333
356
|
directives.each do |(dir_class, options)|
|
|
334
357
|
self.directive(dir_class, **options)
|
|
335
358
|
end
|
|
@@ -339,18 +362,36 @@ module GraphQL
|
|
|
339
362
|
self.validates(validates)
|
|
340
363
|
end
|
|
341
364
|
|
|
342
|
-
if
|
|
343
|
-
|
|
344
|
-
|
|
365
|
+
if @definition_block.nil?
|
|
366
|
+
self.extensions.each(&:after_define_apply)
|
|
367
|
+
@call_after_define = true
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# @api private
|
|
372
|
+
attr_reader :execution_next_mode_key, :execution_next_mode
|
|
373
|
+
|
|
374
|
+
# Calls the definition block, if one was given.
|
|
375
|
+
# This is deferred so that references to the return type
|
|
376
|
+
# can be lazily evaluated, reducing Rails boot time.
|
|
377
|
+
# @return [self]
|
|
378
|
+
# @api private
|
|
379
|
+
def ensure_loaded
|
|
380
|
+
if @definition_block
|
|
381
|
+
if @definition_block.arity == 1
|
|
382
|
+
@definition_block.call(self)
|
|
345
383
|
else
|
|
346
|
-
|
|
384
|
+
instance_exec(self, &@definition_block)
|
|
347
385
|
end
|
|
386
|
+
self.extensions.each(&:after_define_apply)
|
|
387
|
+
@call_after_define = true
|
|
388
|
+
@definition_block = nil
|
|
348
389
|
end
|
|
349
|
-
|
|
350
|
-
self.extensions.each(&:after_define_apply)
|
|
351
|
-
@call_after_define = true
|
|
390
|
+
self
|
|
352
391
|
end
|
|
353
392
|
|
|
393
|
+
attr_accessor :dynamic_introspection
|
|
394
|
+
|
|
354
395
|
# If true, subscription updates with this field can be shared between viewers
|
|
355
396
|
# @return [Boolean, nil]
|
|
356
397
|
# @see GraphQL::Subscriptions::BroadcastAnalyzer
|
|
@@ -378,6 +419,20 @@ module GraphQL
|
|
|
378
419
|
end
|
|
379
420
|
end
|
|
380
421
|
|
|
422
|
+
# @param text [String]
|
|
423
|
+
# @return [String, nil]
|
|
424
|
+
def comment(text = nil)
|
|
425
|
+
if text
|
|
426
|
+
@comment = text
|
|
427
|
+
elsif !NOT_CONFIGURED.equal?(@comment)
|
|
428
|
+
@comment
|
|
429
|
+
elsif @resolver_class
|
|
430
|
+
@resolver_class.comment
|
|
431
|
+
else
|
|
432
|
+
nil
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
381
436
|
# Read extension instances from this field,
|
|
382
437
|
# or add new classes/options to be initialized on this field.
|
|
383
438
|
# Extensions are executed in the order they are added.
|
|
@@ -398,7 +453,7 @@ module GraphQL
|
|
|
398
453
|
new_extensions.each do |extension_config|
|
|
399
454
|
if extension_config.is_a?(Hash)
|
|
400
455
|
extension_class, options = *extension_config.to_a[0]
|
|
401
|
-
self.extension(extension_class, options)
|
|
456
|
+
self.extension(extension_class, **options)
|
|
402
457
|
else
|
|
403
458
|
self.extension(extension_config)
|
|
404
459
|
end
|
|
@@ -418,7 +473,7 @@ module GraphQL
|
|
|
418
473
|
# @param extension_class [Class] subclass of {Schema::FieldExtension}
|
|
419
474
|
# @param options [Hash] if provided, given as `options:` when initializing `extension`.
|
|
420
475
|
# @return [void]
|
|
421
|
-
def extension(extension_class, options
|
|
476
|
+
def extension(extension_class, **options)
|
|
422
477
|
extension_inst = extension_class.new(field: self, options: options)
|
|
423
478
|
if @extensions.frozen?
|
|
424
479
|
@extensions = @extensions.dup
|
|
@@ -439,7 +494,7 @@ module GraphQL
|
|
|
439
494
|
if new_extras.nil?
|
|
440
495
|
# Read the value
|
|
441
496
|
field_extras = @extras
|
|
442
|
-
if @resolver_class &&
|
|
497
|
+
if @resolver_class && !@resolver_class.extras.empty?
|
|
443
498
|
field_extras + @resolver_class.extras
|
|
444
499
|
else
|
|
445
500
|
field_extras
|
|
@@ -468,6 +523,8 @@ module GraphQL
|
|
|
468
523
|
if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
|
|
469
524
|
max_possible_page_size = arguments[:last]
|
|
470
525
|
end
|
|
526
|
+
elsif arguments.is_a?(GraphQL::ExecutionError) || arguments.is_a?(GraphQL::UnauthorizedError)
|
|
527
|
+
raise arguments
|
|
471
528
|
end
|
|
472
529
|
|
|
473
530
|
if max_possible_page_size.nil?
|
|
@@ -480,41 +537,24 @@ module GraphQL
|
|
|
480
537
|
metadata_complexity = 0
|
|
481
538
|
lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
|
|
482
539
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
540
|
+
lookahead.selections.each do |next_lookahead|
|
|
541
|
+
# this includes `pageInfo`, `nodes` and `edges` and any custom fields
|
|
542
|
+
# TODO this doesn't support procs yet -- unlikely to need it.
|
|
543
|
+
metadata_complexity += next_lookahead.field.complexity
|
|
544
|
+
if next_lookahead.name != :nodes && next_lookahead.name != :edges
|
|
545
|
+
# subfields, eg, for pageInfo -- assumes no subselections
|
|
546
|
+
metadata_complexity += next_lookahead.selections.size
|
|
547
|
+
end
|
|
490
548
|
end
|
|
491
549
|
|
|
492
|
-
nodes_edges_complexity = 0
|
|
493
|
-
nodes_edges_complexity += 1 if lookahead.selects?(:edges)
|
|
494
|
-
nodes_edges_complexity += 1 if lookahead.selects?(:nodes)
|
|
495
|
-
|
|
496
550
|
# Possible bug: selections on `edges` and `nodes` are _both_ multiplied here. Should they be?
|
|
497
|
-
items_complexity = child_complexity - metadata_complexity
|
|
498
|
-
|
|
499
|
-
|
|
551
|
+
items_complexity = child_complexity - metadata_complexity
|
|
552
|
+
subfields_complexity = (max_possible_page_size * items_complexity) + metadata_complexity
|
|
553
|
+
# Apply this field's own complexity
|
|
554
|
+
apply_own_complexity_to(subfields_complexity, query, nodes)
|
|
500
555
|
end
|
|
501
556
|
else
|
|
502
|
-
|
|
503
|
-
case defined_complexity
|
|
504
|
-
when Proc
|
|
505
|
-
arguments = query.arguments_for(nodes.first, self)
|
|
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)
|
|
513
|
-
when Numeric
|
|
514
|
-
defined_complexity + child_complexity
|
|
515
|
-
else
|
|
516
|
-
raise("Invalid complexity: #{defined_complexity.inspect} on #{path} (#{inspect})")
|
|
517
|
-
end
|
|
557
|
+
apply_own_complexity_to(child_complexity, query, nodes)
|
|
518
558
|
end
|
|
519
559
|
end
|
|
520
560
|
|
|
@@ -574,19 +614,40 @@ module GraphQL
|
|
|
574
614
|
end
|
|
575
615
|
end
|
|
576
616
|
|
|
617
|
+
def freeze
|
|
618
|
+
type
|
|
619
|
+
owner_type
|
|
620
|
+
arguments_statically_coercible?
|
|
621
|
+
connection?
|
|
622
|
+
super
|
|
623
|
+
end
|
|
624
|
+
|
|
577
625
|
class MissingReturnTypeError < GraphQL::Error; end
|
|
578
626
|
attr_writer :type
|
|
579
627
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
628
|
+
# Get or set the return type of this field.
|
|
629
|
+
#
|
|
630
|
+
# It may return nil if no type was configured or if the given definition block wasn't called yet.
|
|
631
|
+
# @param new_type [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List] A GraphQL return type
|
|
632
|
+
# @return [Module, GraphQL::Schema::NonNull, GraphQL::Schema::List, nil] the configured type for this field
|
|
633
|
+
def type(new_type = NOT_CONFIGURED)
|
|
634
|
+
if NOT_CONFIGURED.equal?(new_type)
|
|
635
|
+
if @resolver_class
|
|
636
|
+
return_type = @return_type_expr || @resolver_class.type_expr
|
|
637
|
+
if return_type.nil?
|
|
638
|
+
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)"
|
|
639
|
+
end
|
|
640
|
+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
|
641
|
+
Member::BuildType.parse_type(return_type, null: nullable)
|
|
642
|
+
elsif !@return_type_expr.nil?
|
|
643
|
+
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
|
|
585
644
|
end
|
|
586
|
-
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
|
|
587
|
-
Member::BuildType.parse_type(return_type, null: nullable)
|
|
588
645
|
else
|
|
589
|
-
@
|
|
646
|
+
@return_type_expr = new_type
|
|
647
|
+
# If `type` is set in the definition block, then the `connection_extension: ...` given as a keyword won't be used, hmm...
|
|
648
|
+
# Also, arguments added by `connection_extension` will clobber anything previously defined,
|
|
649
|
+
# so `type(...)` should go first.
|
|
650
|
+
set_pagination_extensions(connection_extension: self.class.connection_extension)
|
|
590
651
|
end
|
|
591
652
|
rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
|
|
592
653
|
# Let this propagate up
|
|
@@ -603,6 +664,13 @@ module GraphQL
|
|
|
603
664
|
end
|
|
604
665
|
end
|
|
605
666
|
|
|
667
|
+
def authorizes?(context)
|
|
668
|
+
method(:authorized?).owner != GraphQL::Schema::Field || (
|
|
669
|
+
(args = context.types.arguments(self)) &&
|
|
670
|
+
(args.any? { |a| a.authorizes?(context) })
|
|
671
|
+
)
|
|
672
|
+
end
|
|
673
|
+
|
|
606
674
|
def authorized?(object, args, context)
|
|
607
675
|
if @resolver_class
|
|
608
676
|
# The resolver _instance_ will check itself during `resolve()`
|
|
@@ -618,7 +686,7 @@ module GraphQL
|
|
|
618
686
|
using_arg_values = false
|
|
619
687
|
end
|
|
620
688
|
|
|
621
|
-
args = context.
|
|
689
|
+
args = context.types.arguments(self)
|
|
622
690
|
args.each do |arg|
|
|
623
691
|
arg_key = arg.keyword
|
|
624
692
|
if arg_values.key?(arg_key)
|
|
@@ -659,7 +727,7 @@ module GraphQL
|
|
|
659
727
|
method_to_call = nil
|
|
660
728
|
method_args = nil
|
|
661
729
|
|
|
662
|
-
Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
|
730
|
+
@own_validators && Schema::Validator.validate!(validators, application_object, query_ctx, args)
|
|
663
731
|
|
|
664
732
|
query_ctx.query.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
|
|
665
733
|
if is_authorized
|
|
@@ -691,7 +759,7 @@ module GraphQL
|
|
|
691
759
|
method_to_call = resolver_method
|
|
692
760
|
method_receiver = obj
|
|
693
761
|
# Call the method with kwargs, if there are any
|
|
694
|
-
if ruby_kwargs.
|
|
762
|
+
if !ruby_kwargs.empty?
|
|
695
763
|
obj.public_send(resolver_method, **ruby_kwargs)
|
|
696
764
|
else
|
|
697
765
|
obj.public_send(resolver_method)
|
|
@@ -701,7 +769,7 @@ module GraphQL
|
|
|
701
769
|
inner_object.dig(*@dig_keys)
|
|
702
770
|
elsif inner_object.key?(@method_sym)
|
|
703
771
|
inner_object[@method_sym]
|
|
704
|
-
elsif inner_object.key?(@method_str)
|
|
772
|
+
elsif inner_object.key?(@method_str) || !inner_object.default_proc.nil?
|
|
705
773
|
inner_object[@method_str]
|
|
706
774
|
elsif @fallback_value != NOT_CONFIGURED
|
|
707
775
|
@fallback_value
|
|
@@ -711,7 +779,7 @@ module GraphQL
|
|
|
711
779
|
elsif inner_object.respond_to?(@method_sym)
|
|
712
780
|
method_to_call = @method_sym
|
|
713
781
|
method_receiver = obj.object
|
|
714
|
-
if ruby_kwargs.
|
|
782
|
+
if !ruby_kwargs.empty?
|
|
715
783
|
inner_object.public_send(@method_sym, **ruby_kwargs)
|
|
716
784
|
else
|
|
717
785
|
inner_object.public_send(@method_sym)
|
|
@@ -798,7 +866,7 @@ module GraphQL
|
|
|
798
866
|
unsatisfied_ruby_kwargs.clear
|
|
799
867
|
end
|
|
800
868
|
|
|
801
|
-
if unsatisfied_ruby_kwargs.
|
|
869
|
+
if !unsatisfied_ruby_kwargs.empty? || !unsatisfied_method_params.empty?
|
|
802
870
|
raise FieldImplementationFailed.new, <<-ERR
|
|
803
871
|
Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
|
|
804
872
|
|
|
@@ -857,6 +925,33 @@ ERR
|
|
|
857
925
|
end
|
|
858
926
|
end
|
|
859
927
|
|
|
928
|
+
public
|
|
929
|
+
|
|
930
|
+
def run_next_extensions_before_resolve(objs, args, ctx, extended, idx: 0, &block)
|
|
931
|
+
extension = @extensions[idx]
|
|
932
|
+
if extension
|
|
933
|
+
extension.resolve_next(objects: objs, arguments: args, context: ctx) do |extended_objs, extended_args, memo|
|
|
934
|
+
if memo
|
|
935
|
+
memos = extended.memos ||= {}
|
|
936
|
+
memos[idx] = memo
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
if (extras = extension.added_extras)
|
|
940
|
+
ae = extended.added_extras ||= []
|
|
941
|
+
ae.concat(extras)
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
extended.object = extended_objs
|
|
945
|
+
extended.arguments = extended_args
|
|
946
|
+
run_next_extensions_before_resolve(extended_objs, extended_args, ctx, extended, idx: idx + 1, &block)
|
|
947
|
+
end
|
|
948
|
+
else
|
|
949
|
+
yield(objs, args)
|
|
950
|
+
end
|
|
951
|
+
end
|
|
952
|
+
|
|
953
|
+
private
|
|
954
|
+
|
|
860
955
|
def run_extensions_before_resolve(obj, args, ctx, extended, idx: 0)
|
|
861
956
|
extension = @extensions[idx]
|
|
862
957
|
if extension
|
|
@@ -879,6 +974,38 @@ ERR
|
|
|
879
974
|
yield(obj, args)
|
|
880
975
|
end
|
|
881
976
|
end
|
|
977
|
+
|
|
978
|
+
def apply_own_complexity_to(child_complexity, query, nodes)
|
|
979
|
+
case (own_complexity = complexity)
|
|
980
|
+
when Numeric
|
|
981
|
+
own_complexity + child_complexity
|
|
982
|
+
when Proc
|
|
983
|
+
arguments = query.arguments_for(nodes.first, self)
|
|
984
|
+
if arguments.is_a?(GraphQL::ExecutionError)
|
|
985
|
+
return child_complexity
|
|
986
|
+
elsif arguments.respond_to?(:keyword_arguments)
|
|
987
|
+
arguments = arguments.keyword_arguments
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
own_complexity.call(query.context, arguments, child_complexity)
|
|
991
|
+
else
|
|
992
|
+
raise ArgumentError, "Invalid complexity for #{self.path}: #{own_complexity.inspect}"
|
|
993
|
+
end
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
def set_pagination_extensions(connection_extension:)
|
|
997
|
+
# This should run before connection extension,
|
|
998
|
+
# but should it run after the definition block?
|
|
999
|
+
if scoped?
|
|
1000
|
+
self.extension(ScopeExtension, call_after_define: false)
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
# The problem with putting this after the definition_block
|
|
1004
|
+
# is that it would override arguments
|
|
1005
|
+
if connection? && connection_extension
|
|
1006
|
+
self.extension(connection_extension, call_after_define: false)
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
882
1009
|
end
|
|
883
1010
|
end
|
|
884
1011
|
end
|
|
@@ -104,7 +104,7 @@ module GraphQL
|
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
106
|
end
|
|
107
|
-
if (extras = self.class.extras).
|
|
107
|
+
if !(extras = self.class.extras).empty?
|
|
108
108
|
@added_extras = extras - field.extras
|
|
109
109
|
field.extras(@added_extras)
|
|
110
110
|
else
|
|
@@ -134,6 +134,24 @@ module GraphQL
|
|
|
134
134
|
yield(object, arguments, nil)
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
+
# Called before batch-resolving {#field}. It should either:
|
|
138
|
+
#
|
|
139
|
+
# - `yield` values to continue execution; OR
|
|
140
|
+
# - return something else to shortcut field execution.
|
|
141
|
+
#
|
|
142
|
+
# Whatever this method returns will be used for execution.
|
|
143
|
+
#
|
|
144
|
+
# @param objects [Array<Object>] The objects the field is being resolved on
|
|
145
|
+
# @param arguments [Hash] Ruby keyword arguments for resolving this field
|
|
146
|
+
# @param context [Query::Context] the context for this query
|
|
147
|
+
# @yieldparam objects [Array<Object>] The objects to continue resolving the field on. Length must be the same as passed-in `objects:`
|
|
148
|
+
# @yieldparam arguments [Hash] The keyword arguments to continue resolving with
|
|
149
|
+
# @yieldparam memo [Object] Any extension-specific value which will be passed to {#after_resolve} later
|
|
150
|
+
# @return [Array<Object>] The return value for this field, length matching passed-in `objects:`.
|
|
151
|
+
def resolve_next(objects:, arguments:, context:)
|
|
152
|
+
yield(objects, arguments, nil)
|
|
153
|
+
end
|
|
154
|
+
|
|
137
155
|
# Called after {#field} was resolved, and after any lazy values (like `Promise`s) were synced,
|
|
138
156
|
# but before the value was added to the GraphQL response.
|
|
139
157
|
#
|
|
@@ -148,6 +166,21 @@ module GraphQL
|
|
|
148
166
|
def after_resolve(object:, arguments:, context:, value:, memo:)
|
|
149
167
|
value
|
|
150
168
|
end
|
|
169
|
+
|
|
170
|
+
# Called after {#field} was batch-resolved, and after any lazy values (like `Promise`s) were synced,
|
|
171
|
+
# but before the value was added to the GraphQL response.
|
|
172
|
+
#
|
|
173
|
+
# Whatever this hook returns will be used as the return value.
|
|
174
|
+
#
|
|
175
|
+
# @param objects [Array<Object>] The objects the field is being resolved on
|
|
176
|
+
# @param arguments [Hash] Ruby keyword arguments for resolving this field
|
|
177
|
+
# @param context [Query::Context] the context for this query
|
|
178
|
+
# @param values [Array<Object>] Whatever the field returned, one for each of `objects`
|
|
179
|
+
# @param memo [Object] The third value yielded by {#resolve}, or `nil` if there wasn't one
|
|
180
|
+
# @return [Array<Object>] The return values for this field, length matching `objects:`.
|
|
181
|
+
def after_resolve_next(objects:, arguments:, context:, values:, memo:)
|
|
182
|
+
values
|
|
183
|
+
end
|
|
151
184
|
end
|
|
152
185
|
end
|
|
153
186
|
end
|