graphql 2.0.31 → 2.5.18
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/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/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/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 +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 +161 -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 +51 -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 +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/dynamic_fields.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +11 -5
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +8 -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/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 +139 -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 +62 -119
- 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 +28 -1
- 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 +81 -144
- data/lib/graphql/query/null_context.rb +7 -16
- 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 +73 -14
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -66
- 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 +55 -3
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +11 -3
- data/lib/graphql/schema/field/connection_extension.rb +2 -16
- data/lib/graphql/schema/field/scope_extension.rb +8 -1
- data/lib/graphql/schema/field.rb +173 -119
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +123 -65
- 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 +17 -1
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- 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 +5 -5
- data/lib/graphql/schema/member/has_fields.rb +111 -16
- data/lib/graphql/schema/member/has_interfaces.rb +27 -13
- 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 +18 -5
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +33 -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 +45 -31
- 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 +924 -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 +11 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +32 -55
- 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 -158
- 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 +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 +184 -34
- 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_trace.rb +5 -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 +72 -68
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -55
- 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 -41
- 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 +43 -3
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -1
- 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/version.rb +1 -1
- data/lib/graphql.rb +68 -54
- data/readme.md +12 -2
- metadata +220 -40
- 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
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require "graphql/types/string"
|
|
3
2
|
|
|
4
3
|
module GraphQL
|
|
5
4
|
class Schema
|
|
@@ -21,6 +20,10 @@ module GraphQL
|
|
|
21
20
|
# @see {GraphQL::Schema::Mutation} for an example, it's basically the same.
|
|
22
21
|
#
|
|
23
22
|
class RelayClassicMutation < GraphQL::Schema::Mutation
|
|
23
|
+
include GraphQL::Schema::HasSingleInputArgument
|
|
24
|
+
|
|
25
|
+
argument :client_mutation_id, String, "A unique identifier for the client performing the mutation.", required: false
|
|
26
|
+
|
|
24
27
|
# The payload should always include this field
|
|
25
28
|
field(:client_mutation_id, String, "A unique identifier for the client performing the mutation.")
|
|
26
29
|
# Relay classic default:
|
|
@@ -31,34 +34,14 @@ module GraphQL
|
|
|
31
34
|
def resolve_with_support(**inputs)
|
|
32
35
|
input = inputs[:input].to_kwargs
|
|
33
36
|
|
|
34
|
-
new_extras = field ? field.extras : []
|
|
35
|
-
all_extras = self.class.extras + new_extras
|
|
36
|
-
|
|
37
|
-
# Transfer these from the top-level hash to the
|
|
38
|
-
# shortcutted `input:` object
|
|
39
|
-
all_extras.each do |ext|
|
|
40
|
-
# It's possible that the `extra` was not passed along by this point,
|
|
41
|
-
# don't re-add it if it wasn't given here.
|
|
42
|
-
if inputs.key?(ext)
|
|
43
|
-
input[ext] = inputs[ext]
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
37
|
if input
|
|
48
38
|
# This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
|
|
49
39
|
input_kwargs = input.to_h
|
|
50
40
|
client_mutation_id = input_kwargs.delete(:client_mutation_id)
|
|
51
|
-
|
|
52
|
-
# Relay Classic Mutations with no `argument`s
|
|
53
|
-
# don't require `input:`
|
|
54
|
-
input_kwargs = {}
|
|
41
|
+
inputs[:input] = input_kwargs
|
|
55
42
|
end
|
|
56
43
|
|
|
57
|
-
return_value =
|
|
58
|
-
super(**input_kwargs)
|
|
59
|
-
else
|
|
60
|
-
super()
|
|
61
|
-
end
|
|
44
|
+
return_value = super(**inputs)
|
|
62
45
|
|
|
63
46
|
context.query.after_lazy(return_value) do |return_hash|
|
|
64
47
|
# It might be an error
|
|
@@ -68,112 +51,6 @@ module GraphQL
|
|
|
68
51
|
return_hash
|
|
69
52
|
end
|
|
70
53
|
end
|
|
71
|
-
|
|
72
|
-
class << self
|
|
73
|
-
def dummy
|
|
74
|
-
@dummy ||= begin
|
|
75
|
-
d = Class.new(GraphQL::Schema::Resolver)
|
|
76
|
-
d.argument_class(self.argument_class)
|
|
77
|
-
# TODO make this lazier?
|
|
78
|
-
d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
|
|
79
|
-
d
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def field_arguments(context = GraphQL::Query::NullContext)
|
|
84
|
-
dummy.arguments(context)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def get_field_argument(name, context = GraphQL::Query::NullContext)
|
|
88
|
-
dummy.get_argument(name, context)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def own_field_arguments
|
|
92
|
-
dummy.own_arguments
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def all_field_argument_definitions
|
|
96
|
-
dummy.all_argument_definitions
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# Also apply this argument to the input type:
|
|
100
|
-
def argument(*args, own_argument: false, **kwargs, &block)
|
|
101
|
-
it = input_type # make sure any inherited arguments are already added to it
|
|
102
|
-
arg = super(*args, **kwargs, &block)
|
|
103
|
-
|
|
104
|
-
# This definition might be overriding something inherited;
|
|
105
|
-
# if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
|
|
106
|
-
prev_args = it.own_arguments[arg.graphql_name]
|
|
107
|
-
case prev_args
|
|
108
|
-
when GraphQL::Schema::Argument
|
|
109
|
-
if prev_args.owner != self
|
|
110
|
-
it.own_arguments.delete(arg.graphql_name)
|
|
111
|
-
end
|
|
112
|
-
when Array
|
|
113
|
-
prev_args.reject! { |a| a.owner != self }
|
|
114
|
-
if prev_args.empty?
|
|
115
|
-
it.own_arguments.delete(arg.graphql_name)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it.add_argument(arg)
|
|
120
|
-
arg
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# The base class for generated input object types
|
|
124
|
-
# @param new_class [Class] The base class to use for generating input object definitions
|
|
125
|
-
# @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
|
|
126
|
-
def input_object_class(new_class = nil)
|
|
127
|
-
if new_class
|
|
128
|
-
@input_object_class = new_class
|
|
129
|
-
end
|
|
130
|
-
@input_object_class || (superclass.respond_to?(:input_object_class) ? superclass.input_object_class : GraphQL::Schema::InputObject)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# @param new_input_type [Class, nil] If provided, it configures this mutation to accept `new_input_type` instead of generating an input type
|
|
134
|
-
# @return [Class] The generated {Schema::InputObject} class for this mutation's `input`
|
|
135
|
-
def input_type(new_input_type = nil)
|
|
136
|
-
if new_input_type
|
|
137
|
-
@input_type = new_input_type
|
|
138
|
-
end
|
|
139
|
-
@input_type ||= generate_input_type
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
private
|
|
143
|
-
|
|
144
|
-
# Generate the input type for the `input:` argument
|
|
145
|
-
# To customize how input objects are generated, override this method
|
|
146
|
-
# @return [Class] a subclass of {.input_object_class}
|
|
147
|
-
def generate_input_type
|
|
148
|
-
mutation_args = all_argument_definitions
|
|
149
|
-
mutation_class = self
|
|
150
|
-
Class.new(input_object_class) do
|
|
151
|
-
class << self
|
|
152
|
-
def default_graphql_name
|
|
153
|
-
"#{self.mutation.graphql_name}Input"
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def description(new_desc = nil)
|
|
157
|
-
super || "Autogenerated input type of #{self.mutation.graphql_name}"
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
mutation(mutation_class)
|
|
161
|
-
# these might be inherited:
|
|
162
|
-
mutation_args.each do |arg|
|
|
163
|
-
add_argument(arg)
|
|
164
|
-
end
|
|
165
|
-
argument :client_mutation_id, String, "A unique identifier for the client performing the mutation.", required: false
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
private
|
|
171
|
-
|
|
172
|
-
def authorize_arguments(args, values)
|
|
173
|
-
# remove the `input` wrapper to match values
|
|
174
|
-
input_args = args["input"].type.unwrap.arguments(context)
|
|
175
|
-
super(input_args, values)
|
|
176
|
-
end
|
|
177
54
|
end
|
|
178
55
|
end
|
|
179
56
|
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,19 +167,22 @@ 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
|
-
|
|
170
|
-
if
|
|
171
|
-
return
|
|
172
|
-
|
|
173
|
-
|
|
173
|
+
auth_result = argument.authorized?(self, arg_value, context)
|
|
174
|
+
if auth_result.is_a?(Array)
|
|
175
|
+
# only return this second value if the application returned a second value
|
|
176
|
+
arg_auth, err = auth_result
|
|
177
|
+
if !arg_auth
|
|
178
|
+
return arg_auth, err
|
|
179
|
+
end
|
|
180
|
+
elsif auth_result == false
|
|
181
|
+
return auth_result
|
|
174
182
|
end
|
|
175
|
-
else
|
|
176
|
-
true
|
|
177
183
|
end
|
|
178
184
|
end
|
|
185
|
+
true
|
|
179
186
|
end
|
|
180
187
|
|
|
181
188
|
def load_arguments(args)
|
|
@@ -198,23 +205,27 @@ module GraphQL
|
|
|
198
205
|
end
|
|
199
206
|
|
|
200
207
|
# Avoid returning a lazy if none are needed
|
|
201
|
-
if prepare_lazies.
|
|
208
|
+
if !prepare_lazies.empty?
|
|
202
209
|
GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
|
|
203
210
|
else
|
|
204
211
|
prepared_args
|
|
205
212
|
end
|
|
206
213
|
end
|
|
207
214
|
|
|
208
|
-
def get_argument(name, context = GraphQL::Query::NullContext)
|
|
215
|
+
def get_argument(name, context = GraphQL::Query::NullContext.instance)
|
|
209
216
|
self.class.get_argument(name, context)
|
|
210
217
|
end
|
|
211
218
|
|
|
212
219
|
class << self
|
|
213
|
-
def field_arguments(context = GraphQL::Query::NullContext)
|
|
220
|
+
def field_arguments(context = GraphQL::Query::NullContext.instance)
|
|
214
221
|
arguments(context)
|
|
215
222
|
end
|
|
216
223
|
|
|
217
|
-
def
|
|
224
|
+
def any_field_arguments?
|
|
225
|
+
any_arguments?
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def get_field_argument(name, context = GraphQL::Query::NullContext.instance)
|
|
218
229
|
get_argument(name, context)
|
|
219
230
|
end
|
|
220
231
|
|
|
@@ -380,7 +391,7 @@ module GraphQL
|
|
|
380
391
|
if superclass.respond_to?(:extensions)
|
|
381
392
|
s_exts = superclass.extensions
|
|
382
393
|
if own_exts
|
|
383
|
-
if s_exts.
|
|
394
|
+
if !s_exts.empty?
|
|
384
395
|
own_exts + s_exts
|
|
385
396
|
else
|
|
386
397
|
own_exts
|
|
@@ -393,11 +404,14 @@ module GraphQL
|
|
|
393
404
|
end
|
|
394
405
|
end
|
|
395
406
|
|
|
407
|
+
def inherited(child_class)
|
|
408
|
+
child_class.description(description)
|
|
409
|
+
super
|
|
410
|
+
end
|
|
411
|
+
|
|
396
412
|
private
|
|
397
413
|
|
|
398
|
-
|
|
399
|
-
@own_extensions
|
|
400
|
-
end
|
|
414
|
+
attr_reader :own_extensions
|
|
401
415
|
end
|
|
402
416
|
end
|
|
403
417
|
end
|
|
@@ -19,9 +19,9 @@ module GraphQL
|
|
|
19
19
|
|
|
20
20
|
def specified_by_url(new_url = nil)
|
|
21
21
|
if new_url
|
|
22
|
-
|
|
23
|
-
elsif
|
|
24
|
-
|
|
22
|
+
directive(GraphQL::Schema::Directive::SpecifiedBy, url: new_url)
|
|
23
|
+
elsif (directive = directives.find { |dir| dir.graphql_name == "specifiedBy" })
|
|
24
|
+
directive.arguments[:url] # rubocop:disable Development/ContextIsPassedCop
|
|
25
25
|
elsif superclass.respond_to?(:specified_by_url)
|
|
26
26
|
superclass.specified_by_url
|
|
27
27
|
else
|
|
@@ -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
|
|
@@ -19,29 +19,45 @@ module GraphQL
|
|
|
19
19
|
# propagate null.
|
|
20
20
|
null false
|
|
21
21
|
|
|
22
|
+
# @api private
|
|
22
23
|
def initialize(object:, context:, field:)
|
|
23
24
|
super
|
|
24
25
|
# Figure out whether this is an update or an initial subscription
|
|
25
26
|
@mode = context.query.subscription_update? ? :update : :subscribe
|
|
27
|
+
@subscription_written = false
|
|
28
|
+
@original_arguments = nil
|
|
29
|
+
if (subs_ns = context.namespace(:subscriptions)) &&
|
|
30
|
+
(sub_insts = subs_ns[:subscriptions])
|
|
31
|
+
sub_insts[context.current_path] = self
|
|
32
|
+
end
|
|
26
33
|
end
|
|
27
34
|
|
|
35
|
+
# @api private
|
|
28
36
|
def resolve_with_support(**args)
|
|
37
|
+
@original_arguments = args # before `loads:` have been run
|
|
29
38
|
result = nil
|
|
30
39
|
unsubscribed = true
|
|
31
|
-
catch :graphql_subscription_unsubscribed do
|
|
40
|
+
unsubscribed_result = catch :graphql_subscription_unsubscribed do
|
|
32
41
|
result = super
|
|
33
42
|
unsubscribed = false
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
|
|
37
46
|
if unsubscribed
|
|
38
|
-
|
|
47
|
+
if unsubscribed_result
|
|
48
|
+
context.namespace(:subscriptions)[:final_update] = true
|
|
49
|
+
unsubscribed_result
|
|
50
|
+
else
|
|
51
|
+
context.skip
|
|
52
|
+
end
|
|
39
53
|
else
|
|
40
54
|
result
|
|
41
55
|
end
|
|
42
56
|
end
|
|
43
57
|
|
|
44
|
-
# Implement the {Resolve} API
|
|
58
|
+
# Implement the {Resolve} API.
|
|
59
|
+
# You can implement this if you want code to run for _both_ the initial subscription
|
|
60
|
+
# and for later updates. Or, implement {#subscribe} and {#update}
|
|
45
61
|
def resolve(**args)
|
|
46
62
|
# Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
|
|
47
63
|
# have an unexpected `@mode`
|
|
@@ -49,8 +65,9 @@ module GraphQL
|
|
|
49
65
|
end
|
|
50
66
|
|
|
51
67
|
# Wrap the user-defined `#subscribe` hook
|
|
68
|
+
# @api private
|
|
52
69
|
def resolve_subscribe(**args)
|
|
53
|
-
ret_val = args.
|
|
70
|
+
ret_val = !args.empty? ? subscribe(**args) : subscribe
|
|
54
71
|
if ret_val == :no_response
|
|
55
72
|
context.skip
|
|
56
73
|
else
|
|
@@ -66,8 +83,9 @@ module GraphQL
|
|
|
66
83
|
end
|
|
67
84
|
|
|
68
85
|
# Wrap the user-provided `#update` hook
|
|
86
|
+
# @api private
|
|
69
87
|
def resolve_update(**args)
|
|
70
|
-
ret_val = args.
|
|
88
|
+
ret_val = !args.empty? ? update(**args) : update
|
|
71
89
|
if ret_val == NO_UPDATE
|
|
72
90
|
context.namespace(:subscriptions)[:no_update] = true
|
|
73
91
|
context.skip
|
|
@@ -94,19 +112,20 @@ module GraphQL
|
|
|
94
112
|
end
|
|
95
113
|
|
|
96
114
|
# Call this to halt execution and remove this subscription from the system
|
|
97
|
-
|
|
115
|
+
# @param update_value [Object] if present, deliver this update before unsubscribing
|
|
116
|
+
# @return [void]
|
|
117
|
+
def unsubscribe(update_value = nil)
|
|
98
118
|
context.namespace(:subscriptions)[:unsubscribed] = true
|
|
99
|
-
throw :graphql_subscription_unsubscribed
|
|
119
|
+
throw :graphql_subscription_unsubscribed, update_value
|
|
100
120
|
end
|
|
101
121
|
|
|
102
|
-
READING_SCOPE = ::Object.new
|
|
103
122
|
# Call this method to provide a new subscription_scope; OR
|
|
104
123
|
# call it without an argument to get the subscription_scope
|
|
105
124
|
# @param new_scope [Symbol]
|
|
106
125
|
# @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
|
|
107
126
|
# @return [Symbol]
|
|
108
|
-
def self.subscription_scope(new_scope =
|
|
109
|
-
if new_scope !=
|
|
127
|
+
def self.subscription_scope(new_scope = NOT_CONFIGURED, optional: false)
|
|
128
|
+
if new_scope != NOT_CONFIGURED
|
|
110
129
|
@subscription_scope = new_scope
|
|
111
130
|
@subscription_scope_optional = optional
|
|
112
131
|
elsif defined?(@subscription_scope)
|
|
@@ -143,6 +162,40 @@ module GraphQL
|
|
|
143
162
|
def self.topic_for(arguments:, field:, scope:)
|
|
144
163
|
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
|
145
164
|
end
|
|
165
|
+
|
|
166
|
+
# Calls through to `schema.subscriptions` to register this subscription with the backend.
|
|
167
|
+
# This is automatically called by GraphQL-Ruby after a query finishes successfully,
|
|
168
|
+
# but if you need to commit the subscription during `#subscribe`, you can call it there.
|
|
169
|
+
# (This method also sets a flag showing that this subscription was already written.)
|
|
170
|
+
#
|
|
171
|
+
# If you call this method yourself, you may also need to {#unsubscribe}
|
|
172
|
+
# or call `subscriptions.delete_subscription` to clean up the database if the query crashes with an error
|
|
173
|
+
# later in execution.
|
|
174
|
+
# @return [void]
|
|
175
|
+
def write_subscription
|
|
176
|
+
if subscription_written?
|
|
177
|
+
raise GraphQL::Error, "`write_subscription` was called but `#{self.class}#subscription_written?` is already true. Remove a call to `write subscription`."
|
|
178
|
+
else
|
|
179
|
+
@subscription_written = true
|
|
180
|
+
context.schema.subscriptions.write_subscription(context.query, [event])
|
|
181
|
+
end
|
|
182
|
+
nil
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# @return [Boolean] `true` if {#write_subscription} was called already
|
|
186
|
+
def subscription_written?
|
|
187
|
+
@subscription_written
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# @return [Subscriptions::Event] This object is used as a representation of this subscription for the backend
|
|
191
|
+
def event
|
|
192
|
+
@event ||= Subscriptions::Event.new(
|
|
193
|
+
name: field.name,
|
|
194
|
+
arguments: @original_arguments,
|
|
195
|
+
context: context,
|
|
196
|
+
field: field,
|
|
197
|
+
)
|
|
198
|
+
end
|
|
146
199
|
end
|
|
147
200
|
end
|
|
148
201
|
end
|
|
@@ -71,15 +71,23 @@ module GraphQL
|
|
|
71
71
|
def execute_field(query:, field:, **_rest)
|
|
72
72
|
timeout_state = query.context.namespace(@timeout).fetch(:state)
|
|
73
73
|
# If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
|
|
74
|
-
if timeout_state
|
|
74
|
+
if timeout_state == false
|
|
75
|
+
super
|
|
76
|
+
elsif Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
|
|
75
77
|
error = GraphQL::Schema::Timeout::TimeoutError.new(field)
|
|
76
78
|
# Only invoke the timeout callback for the first timeout
|
|
77
79
|
if !timeout_state[:timed_out]
|
|
78
80
|
timeout_state[:timed_out] = true
|
|
79
81
|
@timeout.handle_timeout(error, query)
|
|
82
|
+
timeout_state = query.context.namespace(@timeout).fetch(:state)
|
|
80
83
|
end
|
|
81
84
|
|
|
82
|
-
|
|
85
|
+
# `handle_timeout` may have set this to be `false`
|
|
86
|
+
if timeout_state != false
|
|
87
|
+
error
|
|
88
|
+
else
|
|
89
|
+
super
|
|
90
|
+
end
|
|
83
91
|
else
|
|
84
92
|
super
|
|
85
93
|
end
|
|
@@ -102,6 +110,15 @@ module GraphQL
|
|
|
102
110
|
# override to do something interesting
|
|
103
111
|
end
|
|
104
112
|
|
|
113
|
+
# Call this method (eg, from {#handle_timeout}) to disable timeout tracking
|
|
114
|
+
# for the given query.
|
|
115
|
+
# @param query [GraphQL::Query]
|
|
116
|
+
# @return [void]
|
|
117
|
+
def disable_timeout(query)
|
|
118
|
+
query.context.namespace(self)[:state] = false
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
105
122
|
# This error is raised when a query exceeds `max_seconds`.
|
|
106
123
|
# Since it's a child of {GraphQL::ExecutionError},
|
|
107
124
|
# its message will be added to the response's `errors` key.
|
|
@@ -5,13 +5,13 @@ module GraphQL
|
|
|
5
5
|
module TypeExpression
|
|
6
6
|
# Fetch a type from a type map by its AST specification.
|
|
7
7
|
# Return `nil` if not found.
|
|
8
|
-
# @param type_owner [#
|
|
8
|
+
# @param type_owner [#type] A thing for looking up types by name
|
|
9
9
|
# @param ast_node [GraphQL::Language::Nodes::AbstractNode]
|
|
10
10
|
# @return [Class, GraphQL::Schema::NonNull, GraphQL::Schema:List]
|
|
11
11
|
def self.build_type(type_owner, ast_node)
|
|
12
12
|
case ast_node
|
|
13
13
|
when GraphQL::Language::Nodes::TypeName
|
|
14
|
-
type_owner.
|
|
14
|
+
type_owner.type(ast_node.name) # rubocop:disable Development/ContextIsPassedCop -- this is a `context` or `warden`, it's already query-aware
|
|
15
15
|
when GraphQL::Language::Nodes::NonNullType
|
|
16
16
|
ast_inner_type = ast_node.of_type
|
|
17
17
|
inner_type = build_type(type_owner, ast_inner_type)
|
data/lib/graphql/schema/union.rb
CHANGED
|
@@ -10,8 +10,8 @@ module GraphQL
|
|
|
10
10
|
super
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def possible_types(*types, context: GraphQL::Query::NullContext, **options)
|
|
14
|
-
if types.
|
|
13
|
+
def possible_types(*types, context: GraphQL::Query::NullContext.instance, **options)
|
|
14
|
+
if !types.empty?
|
|
15
15
|
types.each do |t|
|
|
16
16
|
assert_valid_union_member(t)
|
|
17
17
|
type_memberships << type_membership_class.new(self, t, **options)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphQL
|
|
4
|
+
class Schema
|
|
5
|
+
class Validator
|
|
6
|
+
# Use this to validate each member of an array value.
|
|
7
|
+
#
|
|
8
|
+
# @example validate format of all strings in an array
|
|
9
|
+
#
|
|
10
|
+
# argument :handles, [String],
|
|
11
|
+
# validates: { all: { format: { with: /\A[a-z0-9_]+\Z/ } } }
|
|
12
|
+
#
|
|
13
|
+
# @example multiple validators can be combined
|
|
14
|
+
#
|
|
15
|
+
# argument :handles, [String],
|
|
16
|
+
# validates: { all: { format: { with: /\A[a-z0-9_]+\Z/ }, length: { maximum: 32 } } }
|
|
17
|
+
#
|
|
18
|
+
# @example any type can be used
|
|
19
|
+
#
|
|
20
|
+
# argument :choices, [Integer],
|
|
21
|
+
# validates: { all: { inclusion: { in: 1..12 } } }
|
|
22
|
+
#
|
|
23
|
+
class AllValidator < Validator
|
|
24
|
+
def initialize(validated:, allow_blank: false, allow_null: false, **validators)
|
|
25
|
+
super(validated: validated, allow_blank: allow_blank, allow_null: allow_null)
|
|
26
|
+
|
|
27
|
+
@validators = Validator.from_config(validated, validators)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validate(object, context, value)
|
|
31
|
+
return EMPTY_ARRAY if permitted_empty_value?(value)
|
|
32
|
+
|
|
33
|
+
all_errors = EMPTY_ARRAY
|
|
34
|
+
|
|
35
|
+
value.each do |subvalue|
|
|
36
|
+
@validators.each do |validator|
|
|
37
|
+
errors = validator.validate(object, context, subvalue)
|
|
38
|
+
if errors &&
|
|
39
|
+
(errors.is_a?(Array) && errors != EMPTY_ARRAY) ||
|
|
40
|
+
(errors.is_a?(String))
|
|
41
|
+
if all_errors.frozen? # It's empty
|
|
42
|
+
all_errors = []
|
|
43
|
+
end
|
|
44
|
+
if errors.is_a?(String)
|
|
45
|
+
all_errors << errors
|
|
46
|
+
else
|
|
47
|
+
all_errors.concat(errors)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
unless all_errors.frozen?
|
|
54
|
+
all_errors.uniq!
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
all_errors
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|