graphql 1.12.10 → 1.13.4
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/core.rb +3 -1
- data/lib/generators/graphql/install_generator.rb +9 -2
- data/lib/generators/graphql/mutation_generator.rb +1 -1
- data/lib/generators/graphql/object_generator.rb +2 -1
- data/lib/generators/graphql/relay.rb +19 -11
- data/lib/generators/graphql/templates/schema.erb +14 -2
- data/lib/generators/graphql/type_generator.rb +0 -1
- data/lib/graphql/analysis/ast/field_usage.rb +28 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +4 -4
- data/lib/graphql/backtrace/table.rb +15 -3
- data/lib/graphql/backtrace/tracer.rb +7 -4
- data/lib/graphql/base_type.rb +4 -2
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader/null_dataloader.rb +1 -0
- data/lib/graphql/dataloader/source.rb +50 -2
- data/lib/graphql/dataloader.rb +110 -41
- data/lib/graphql/define/instance_definable.rb +1 -1
- data/lib/graphql/deprecated_dsl.rb +11 -3
- data/lib/graphql/deprecation.rb +1 -5
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +0 -4
- data/lib/graphql/enum_type.rb +5 -1
- data/lib/graphql/execution/errors.rb +1 -0
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -4
- data/lib/graphql/execution/interpreter/resolve.rb +6 -2
- data/lib/graphql/execution/interpreter/runtime.rb +513 -213
- data/lib/graphql/execution/interpreter.rb +4 -8
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +4 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/integer_encoding_error.rb +18 -2
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +2 -2
- data/lib/graphql/introspection/input_value_type.rb +10 -4
- data/lib/graphql/introspection/schema_type.rb +3 -3
- data/lib/graphql/introspection/type_type.rb +10 -10
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/document_from_schema_definition.rb +10 -4
- data/lib/graphql/language/lexer.rb +0 -3
- data/lib/graphql/language/lexer.rl +0 -4
- data/lib/graphql/language/nodes.rb +13 -3
- data/lib/graphql/language/parser.rb +442 -434
- data/lib/graphql/language/parser.y +5 -4
- data/lib/graphql/language/printer.rb +6 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
- data/lib/graphql/pagination/connections.rb +40 -16
- data/lib/graphql/pagination/relation_connection.rb +57 -27
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +15 -2
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +12 -7
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +1 -1
- data/lib/graphql/query/variables.rb +5 -1
- data/lib/graphql/query.rb +5 -1
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -1
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/schema/addition.rb +247 -0
- data/lib/graphql/schema/argument.rb +103 -45
- data/lib/graphql/schema/build_from_definition.rb +13 -7
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +14 -2
- data/lib/graphql/schema/directive.rb +7 -3
- data/lib/graphql/schema/enum.rb +70 -11
- data/lib/graphql/schema/enum_value.rb +6 -0
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +243 -81
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +1 -0
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +39 -29
- data/lib/graphql/schema/interface.rb +11 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +3 -1
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/build_type.rb +1 -4
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +145 -57
- data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +76 -18
- data/lib/graphql/schema/member/has_interfaces.rb +90 -0
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/non_null.rb +7 -1
- data/lib/graphql/schema/object.rb +10 -75
- data/lib/graphql/schema/printer.rb +12 -17
- data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
- data/lib/graphql/schema/resolver.rb +75 -65
- data/lib/graphql/schema/scalar.rb +2 -0
- data/lib/graphql/schema/subscription.rb +36 -8
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
- data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
- data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/format_validator.rb +4 -5
- data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
- data/lib/graphql/schema/validator/length_validator.rb +5 -3
- data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +33 -25
- data/lib/graphql/schema/warden.rb +116 -52
- data/lib/graphql/schema.rb +162 -227
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +8 -5
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/error.rb +3 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +52 -26
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -1
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +8 -2
- data/lib/graphql/static_validation/validator.rb +15 -12
- data/lib/graphql/string_encoding_error.rb +13 -3
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +36 -6
- data/lib/graphql/subscriptions/event.rb +68 -31
- data/lib/graphql/subscriptions/serialize.rb +23 -3
- data/lib/graphql/subscriptions.rb +17 -19
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +26 -9
- data/lib/graphql/types/relay/default_relay.rb +5 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
- data/lib/graphql/types/relay/has_node_field.rb +2 -2
- data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
- data/lib/graphql/types/relay/node_field.rb +15 -4
- data/lib/graphql/types/relay/nodes_field.rb +14 -4
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/unauthorized_error.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +10 -28
- data/readme.md +1 -4
- metadata +17 -21
- data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
data/lib/graphql/schema.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require "graphql/schema/addition"
|
|
2
3
|
require "graphql/schema/base_64_encoder"
|
|
3
4
|
require "graphql/schema/catchall_middleware"
|
|
4
5
|
require "graphql/schema/default_parse_error"
|
|
@@ -91,6 +92,8 @@ module GraphQL
|
|
|
91
92
|
end
|
|
92
93
|
end
|
|
93
94
|
|
|
95
|
+
class DuplicateNamesError < GraphQL::Error; end
|
|
96
|
+
|
|
94
97
|
class UnresolvedLateBoundTypeError < GraphQL::Error
|
|
95
98
|
attr_reader :type
|
|
96
99
|
def initialize(type:)
|
|
@@ -160,7 +163,7 @@ module GraphQL
|
|
|
160
163
|
|
|
161
164
|
accepts_definitions \
|
|
162
165
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
|
163
|
-
:validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
|
|
166
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
|
164
167
|
:orphan_types, :resolve_type, :type_error, :parse_error,
|
|
165
168
|
:error_bubbling,
|
|
166
169
|
:raise_definition_error,
|
|
@@ -199,7 +202,7 @@ module GraphQL
|
|
|
199
202
|
attr_accessor \
|
|
200
203
|
:query, :mutation, :subscription,
|
|
201
204
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
|
202
|
-
:validate_timeout, :max_depth, :max_complexity, :default_max_page_size,
|
|
205
|
+
:validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
|
|
203
206
|
:orphan_types, :directives,
|
|
204
207
|
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
|
205
208
|
:cursor_encoder,
|
|
@@ -551,7 +554,7 @@ module GraphQL
|
|
|
551
554
|
end
|
|
552
555
|
end
|
|
553
556
|
|
|
554
|
-
# @see [GraphQL::Schema::Warden]
|
|
557
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
|
555
558
|
# @return [GraphQL::ObjectType, nil]
|
|
556
559
|
def root_type_for_operation(operation)
|
|
557
560
|
case operation
|
|
@@ -842,7 +845,7 @@ module GraphQL
|
|
|
842
845
|
# - Cause the Schema instance to be created, if it hasn't been created yet
|
|
843
846
|
# - Delegate to that instance
|
|
844
847
|
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
|
845
|
-
def_delegators :
|
|
848
|
+
def_delegators :deprecated_graphql_definition,
|
|
846
849
|
# Execution
|
|
847
850
|
:execution_strategy_for_operation,
|
|
848
851
|
# Configuration
|
|
@@ -851,6 +854,10 @@ module GraphQL
|
|
|
851
854
|
:id_from_object=, :object_from_id=,
|
|
852
855
|
:remove_handler
|
|
853
856
|
|
|
857
|
+
def deprecated_graphql_definition
|
|
858
|
+
graphql_definition(silence_deprecation_warning: true)
|
|
859
|
+
end
|
|
860
|
+
|
|
854
861
|
# @return [GraphQL::Subscriptions]
|
|
855
862
|
attr_accessor :subscriptions
|
|
856
863
|
|
|
@@ -893,8 +900,15 @@ module GraphQL
|
|
|
893
900
|
@find_cache[path] ||= @finder.find(path)
|
|
894
901
|
end
|
|
895
902
|
|
|
896
|
-
def graphql_definition
|
|
897
|
-
@graphql_definition ||=
|
|
903
|
+
def graphql_definition(silence_deprecation_warning: false)
|
|
904
|
+
@graphql_definition ||= begin
|
|
905
|
+
unless silence_deprecation_warning
|
|
906
|
+
message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Use a class-based definition instead."
|
|
907
|
+
caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
|
|
908
|
+
GraphQL::Deprecation.warn(message + caller_message)
|
|
909
|
+
end
|
|
910
|
+
to_graphql(silence_deprecation_warning: silence_deprecation_warning)
|
|
911
|
+
end
|
|
898
912
|
end
|
|
899
913
|
|
|
900
914
|
def default_filter
|
|
@@ -926,18 +940,20 @@ module GraphQL
|
|
|
926
940
|
find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
|
|
927
941
|
end
|
|
928
942
|
|
|
943
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
|
929
944
|
def to_graphql
|
|
930
945
|
schema_defn = self.new
|
|
931
946
|
schema_defn.raise_definition_error = true
|
|
932
|
-
schema_defn.query = query && query.graphql_definition
|
|
933
|
-
schema_defn.mutation = mutation && mutation.graphql_definition
|
|
934
|
-
schema_defn.subscription = subscription && subscription.graphql_definition
|
|
947
|
+
schema_defn.query = query && query.graphql_definition(silence_deprecation_warning: true)
|
|
948
|
+
schema_defn.mutation = mutation && mutation.graphql_definition(silence_deprecation_warning: true)
|
|
949
|
+
schema_defn.subscription = subscription && subscription.graphql_definition(silence_deprecation_warning: true)
|
|
935
950
|
schema_defn.validate_timeout = validate_timeout
|
|
951
|
+
schema_defn.validate_max_errors = validate_max_errors
|
|
936
952
|
schema_defn.max_complexity = max_complexity
|
|
937
953
|
schema_defn.error_bubbling = error_bubbling
|
|
938
954
|
schema_defn.max_depth = max_depth
|
|
939
955
|
schema_defn.default_max_page_size = default_max_page_size
|
|
940
|
-
schema_defn.orphan_types = orphan_types.map(
|
|
956
|
+
schema_defn.orphan_types = orphan_types.map { |t| t.graphql_definition(silence_deprecation_warning: true) }
|
|
941
957
|
schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
|
|
942
958
|
schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
|
|
943
959
|
schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
|
|
@@ -994,16 +1010,58 @@ module GraphQL
|
|
|
994
1010
|
# Build a map of `{ name => type }` and return it
|
|
995
1011
|
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
|
996
1012
|
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
|
997
|
-
def types
|
|
998
|
-
non_introspection_types.merge(introspection_system.types)
|
|
1013
|
+
def types(context = GraphQL::Query::NullContext)
|
|
1014
|
+
all_types = non_introspection_types.merge(introspection_system.types)
|
|
1015
|
+
visible_types = {}
|
|
1016
|
+
all_types.each do |k, v|
|
|
1017
|
+
visible_types[k] =if v.is_a?(Array)
|
|
1018
|
+
visible_t = nil
|
|
1019
|
+
v.each do |t|
|
|
1020
|
+
if t.visible?(context)
|
|
1021
|
+
if visible_t.nil?
|
|
1022
|
+
visible_t = t
|
|
1023
|
+
else
|
|
1024
|
+
raise DuplicateNamesError, "Found two visible type definitions for `#{k}`: #{visible_t.inspect}, #{t.inspect}"
|
|
1025
|
+
end
|
|
1026
|
+
end
|
|
1027
|
+
end
|
|
1028
|
+
visible_t
|
|
1029
|
+
else
|
|
1030
|
+
v
|
|
1031
|
+
end
|
|
1032
|
+
end
|
|
1033
|
+
visible_types
|
|
999
1034
|
end
|
|
1000
1035
|
|
|
1001
1036
|
# @param type_name [String]
|
|
1002
1037
|
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
|
1003
|
-
def get_type(type_name)
|
|
1004
|
-
own_types[type_name]
|
|
1005
|
-
|
|
1006
|
-
|
|
1038
|
+
def get_type(type_name, context = GraphQL::Query::NullContext)
|
|
1039
|
+
local_entry = own_types[type_name]
|
|
1040
|
+
type_defn = case local_entry
|
|
1041
|
+
when nil
|
|
1042
|
+
nil
|
|
1043
|
+
when Array
|
|
1044
|
+
visible_t = nil
|
|
1045
|
+
warden = Warden.from_context(context)
|
|
1046
|
+
local_entry.each do |t|
|
|
1047
|
+
if warden.visible_type?(t, context)
|
|
1048
|
+
if visible_t.nil?
|
|
1049
|
+
visible_t = t
|
|
1050
|
+
else
|
|
1051
|
+
raise DuplicateNamesError, "Found two visible type definitions for `#{type_name}`: #{visible_t.inspect}, #{t.inspect}"
|
|
1052
|
+
end
|
|
1053
|
+
end
|
|
1054
|
+
end
|
|
1055
|
+
visible_t
|
|
1056
|
+
when Module
|
|
1057
|
+
local_entry
|
|
1058
|
+
else
|
|
1059
|
+
raise "Invariant: unexpected own_types[#{type_name.inspect}]: #{local_entry.inspect}"
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
type_defn ||
|
|
1063
|
+
introspection_system.types[type_name] || # todo context-specific introspection?
|
|
1064
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
|
1007
1065
|
end
|
|
1008
1066
|
|
|
1009
1067
|
# @api private
|
|
@@ -1072,7 +1130,7 @@ module GraphQL
|
|
|
1072
1130
|
end
|
|
1073
1131
|
end
|
|
1074
1132
|
|
|
1075
|
-
# @see [GraphQL::Schema::Warden]
|
|
1133
|
+
# @see [GraphQL::Schema::Warden] Restricted access to root types
|
|
1076
1134
|
# @return [GraphQL::ObjectType, nil]
|
|
1077
1135
|
def root_type_for_operation(operation)
|
|
1078
1136
|
case operation
|
|
@@ -1180,19 +1238,23 @@ module GraphQL
|
|
|
1180
1238
|
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
|
1181
1239
|
end
|
|
1182
1240
|
|
|
1183
|
-
def get_field(type_or_name, field_name)
|
|
1241
|
+
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext)
|
|
1184
1242
|
parent_type = case type_or_name
|
|
1185
1243
|
when LateBoundType
|
|
1186
|
-
get_type(type_or_name.name)
|
|
1244
|
+
get_type(type_or_name.name, context)
|
|
1187
1245
|
when String
|
|
1188
|
-
get_type(type_or_name)
|
|
1246
|
+
get_type(type_or_name, context)
|
|
1189
1247
|
when Module
|
|
1190
1248
|
type_or_name
|
|
1191
1249
|
else
|
|
1192
|
-
raise ArgumentError,
|
|
1250
|
+
raise ArgumentError, <<-ERR
|
|
1251
|
+
Invariant: unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})
|
|
1252
|
+
|
|
1253
|
+
This is probably a bug in GraphQL-Ruby, please report this error on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new?template=bug_report.md
|
|
1254
|
+
ERR
|
|
1193
1255
|
end
|
|
1194
1256
|
|
|
1195
|
-
if parent_type.kind.fields? && (field = parent_type.get_field(field_name))
|
|
1257
|
+
if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
|
|
1196
1258
|
field
|
|
1197
1259
|
elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
|
|
1198
1260
|
entry_point_field
|
|
@@ -1203,8 +1265,8 @@ module GraphQL
|
|
|
1203
1265
|
end
|
|
1204
1266
|
end
|
|
1205
1267
|
|
|
1206
|
-
def get_fields(type)
|
|
1207
|
-
type.fields
|
|
1268
|
+
def get_fields(type, context = GraphQL::Query::NullContext)
|
|
1269
|
+
type.fields(context)
|
|
1208
1270
|
end
|
|
1209
1271
|
|
|
1210
1272
|
def introspection(new_introspection_namespace = nil)
|
|
@@ -1289,10 +1351,22 @@ module GraphQL
|
|
|
1289
1351
|
validator_opts = { schema: self }
|
|
1290
1352
|
rules && (validator_opts[:rules] = rules)
|
|
1291
1353
|
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
|
1292
|
-
res = validator.validate(query, timeout: validate_timeout)
|
|
1354
|
+
res = validator.validate(query, timeout: validate_timeout, max_errors: validate_max_errors)
|
|
1293
1355
|
res[:errors]
|
|
1294
1356
|
end
|
|
1295
1357
|
|
|
1358
|
+
attr_writer :validate_max_errors
|
|
1359
|
+
|
|
1360
|
+
def validate_max_errors(new_validate_max_errors = nil)
|
|
1361
|
+
if new_validate_max_errors
|
|
1362
|
+
@validate_max_errors = new_validate_max_errors
|
|
1363
|
+
elsif defined?(@validate_max_errors)
|
|
1364
|
+
@validate_max_errors
|
|
1365
|
+
else
|
|
1366
|
+
find_inherited_value(:validate_max_errors)
|
|
1367
|
+
end
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1296
1370
|
attr_writer :max_complexity
|
|
1297
1371
|
|
|
1298
1372
|
def max_complexity(max_complexity = nil)
|
|
@@ -1391,7 +1465,6 @@ module GraphQL
|
|
|
1391
1465
|
if new_orphan_types.any?
|
|
1392
1466
|
new_orphan_types = new_orphan_types.flatten
|
|
1393
1467
|
add_type_and_traverse(new_orphan_types, root: false)
|
|
1394
|
-
@orphan_types = new_orphan_types
|
|
1395
1468
|
own_orphan_types.concat(new_orphan_types.flatten)
|
|
1396
1469
|
end
|
|
1397
1470
|
|
|
@@ -1582,10 +1655,7 @@ module GraphQL
|
|
|
1582
1655
|
# @param new_directive [Class]
|
|
1583
1656
|
# @return void
|
|
1584
1657
|
def directive(new_directive)
|
|
1585
|
-
|
|
1586
|
-
add_type_and_traverse(new_directive, root: false)
|
|
1587
|
-
new_directive
|
|
1588
|
-
end
|
|
1658
|
+
add_type_and_traverse(new_directive, root: false)
|
|
1589
1659
|
end
|
|
1590
1660
|
|
|
1591
1661
|
def default_directives
|
|
@@ -1633,6 +1703,14 @@ module GraphQL
|
|
|
1633
1703
|
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
|
1634
1704
|
end
|
|
1635
1705
|
|
|
1706
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
|
1707
|
+
if new_sanitized_printer
|
|
1708
|
+
@own_sanitized_printer = new_sanitized_printer
|
|
1709
|
+
else
|
|
1710
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
|
1711
|
+
end
|
|
1712
|
+
end
|
|
1713
|
+
|
|
1636
1714
|
# Execute a query on itself.
|
|
1637
1715
|
# @see {Query#initialize} for arguments.
|
|
1638
1716
|
# @return [Hash] query result, ready to be serialized as JSON
|
|
@@ -1696,7 +1774,7 @@ module GraphQL
|
|
|
1696
1774
|
if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
|
|
1697
1775
|
GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
|
|
1698
1776
|
else
|
|
1699
|
-
subscription.
|
|
1777
|
+
subscription.all_field_definitions.each do |field|
|
|
1700
1778
|
field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
|
|
1701
1779
|
end
|
|
1702
1780
|
end
|
|
@@ -1709,6 +1787,59 @@ module GraphQL
|
|
|
1709
1787
|
|
|
1710
1788
|
private
|
|
1711
1789
|
|
|
1790
|
+
# @param t [Module, Array<Module>]
|
|
1791
|
+
# @return [void]
|
|
1792
|
+
def add_type_and_traverse(t, root:)
|
|
1793
|
+
if root
|
|
1794
|
+
@root_types ||= []
|
|
1795
|
+
@root_types << t
|
|
1796
|
+
end
|
|
1797
|
+
new_types = Array(t)
|
|
1798
|
+
addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
|
|
1799
|
+
addition.types.each do |name, types_entry| # rubocop:disable Development/ContextIsPassedCop -- build-time, not query-time
|
|
1800
|
+
if (prev_entry = own_types[name])
|
|
1801
|
+
prev_entries = case prev_entry
|
|
1802
|
+
when Array
|
|
1803
|
+
prev_entry
|
|
1804
|
+
when Module
|
|
1805
|
+
own_types[name] = [prev_entry]
|
|
1806
|
+
else
|
|
1807
|
+
raise "Invariant: unexpected prev_entry at #{name.inspect} when adding #{t.inspect}"
|
|
1808
|
+
end
|
|
1809
|
+
|
|
1810
|
+
case types_entry
|
|
1811
|
+
when Array
|
|
1812
|
+
prev_entries.concat(types_entry)
|
|
1813
|
+
prev_entries.uniq! # in case any are being re-visited
|
|
1814
|
+
when Module
|
|
1815
|
+
if !prev_entries.include?(types_entry)
|
|
1816
|
+
prev_entries << types_entry
|
|
1817
|
+
end
|
|
1818
|
+
else
|
|
1819
|
+
raise "Invariant: unexpected types_entry at #{name} when adding #{t.inspect}"
|
|
1820
|
+
end
|
|
1821
|
+
else
|
|
1822
|
+
if types_entry.is_a?(Array)
|
|
1823
|
+
types_entry.uniq!
|
|
1824
|
+
end
|
|
1825
|
+
own_types[name] = types_entry
|
|
1826
|
+
end
|
|
1827
|
+
end
|
|
1828
|
+
|
|
1829
|
+
own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
|
|
1830
|
+
own_union_memberships.merge!(addition.union_memberships)
|
|
1831
|
+
|
|
1832
|
+
addition.references.each { |thing, pointers|
|
|
1833
|
+
pointers.each { |pointer| references_to(thing, from: pointer) }
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
|
|
1837
|
+
|
|
1838
|
+
addition.arguments_with_default_values.each do |arg|
|
|
1839
|
+
arg.validate_default_value
|
|
1840
|
+
end
|
|
1841
|
+
end
|
|
1842
|
+
|
|
1712
1843
|
def lazy_methods
|
|
1713
1844
|
if !defined?(@lazy_methods)
|
|
1714
1845
|
if inherited_map = find_inherited_value(:lazy_methods)
|
|
@@ -1774,202 +1905,6 @@ module GraphQL
|
|
|
1774
1905
|
def own_multiplex_analyzers
|
|
1775
1906
|
@own_multiplex_analyzers ||= []
|
|
1776
1907
|
end
|
|
1777
|
-
|
|
1778
|
-
# @param t [Module, Array<Module>]
|
|
1779
|
-
# @return [void]
|
|
1780
|
-
def add_type_and_traverse(t, root:)
|
|
1781
|
-
if root
|
|
1782
|
-
@root_types ||= []
|
|
1783
|
-
@root_types << t
|
|
1784
|
-
end
|
|
1785
|
-
late_types = []
|
|
1786
|
-
new_types = Array(t)
|
|
1787
|
-
new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
|
|
1788
|
-
missed_late_types = 0
|
|
1789
|
-
while (late_type_vals = late_types.shift)
|
|
1790
|
-
type_owner, lt = late_type_vals
|
|
1791
|
-
if lt.is_a?(String)
|
|
1792
|
-
type = Member::BuildType.constantize(lt)
|
|
1793
|
-
# Reset the counter, since we might succeed next go-round
|
|
1794
|
-
missed_late_types = 0
|
|
1795
|
-
update_type_owner(type_owner, type)
|
|
1796
|
-
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
|
1797
|
-
elsif lt.is_a?(LateBoundType)
|
|
1798
|
-
if (type = get_type(lt.graphql_name))
|
|
1799
|
-
# Reset the counter, since we might succeed next go-round
|
|
1800
|
-
missed_late_types = 0
|
|
1801
|
-
update_type_owner(type_owner, type)
|
|
1802
|
-
add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
|
|
1803
|
-
else
|
|
1804
|
-
missed_late_types += 1
|
|
1805
|
-
# Add it back to the list, maybe we'll be able to resolve it later.
|
|
1806
|
-
late_types << [type_owner, lt]
|
|
1807
|
-
if missed_late_types == late_types.size
|
|
1808
|
-
# We've looked at all of them and haven't resolved one.
|
|
1809
|
-
raise UnresolvedLateBoundTypeError.new(type: lt)
|
|
1810
|
-
else
|
|
1811
|
-
# Try the next one
|
|
1812
|
-
end
|
|
1813
|
-
end
|
|
1814
|
-
else
|
|
1815
|
-
raise ArgumentError, "Unexpected late type: #{lt.inspect}"
|
|
1816
|
-
end
|
|
1817
|
-
end
|
|
1818
|
-
nil
|
|
1819
|
-
end
|
|
1820
|
-
|
|
1821
|
-
def update_type_owner(owner, type)
|
|
1822
|
-
case owner
|
|
1823
|
-
when Class
|
|
1824
|
-
if owner.kind.union?
|
|
1825
|
-
# It's a union with possible_types
|
|
1826
|
-
# Replace the item by class name
|
|
1827
|
-
owner.assign_type_membership_object_type(type)
|
|
1828
|
-
own_possible_types[owner.graphql_name] = owner.possible_types
|
|
1829
|
-
elsif type.kind.interface? && owner.kind.object?
|
|
1830
|
-
new_interfaces = []
|
|
1831
|
-
owner.interfaces.each do |int_t|
|
|
1832
|
-
if int_t.is_a?(String) && int_t == type.graphql_name
|
|
1833
|
-
new_interfaces << type
|
|
1834
|
-
elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
|
|
1835
|
-
new_interfaces << type
|
|
1836
|
-
else
|
|
1837
|
-
# Don't re-add proper interface definitions,
|
|
1838
|
-
# they were probably already added, maybe with options.
|
|
1839
|
-
end
|
|
1840
|
-
end
|
|
1841
|
-
owner.implements(*new_interfaces)
|
|
1842
|
-
new_interfaces.each do |int|
|
|
1843
|
-
pt = own_possible_types[int.graphql_name] ||= []
|
|
1844
|
-
if !pt.include?(owner)
|
|
1845
|
-
pt << owner
|
|
1846
|
-
end
|
|
1847
|
-
end
|
|
1848
|
-
end
|
|
1849
|
-
|
|
1850
|
-
when nil
|
|
1851
|
-
# It's a root type
|
|
1852
|
-
own_types[type.graphql_name] = type
|
|
1853
|
-
when GraphQL::Schema::Field, GraphQL::Schema::Argument
|
|
1854
|
-
orig_type = owner.type
|
|
1855
|
-
# Apply list/non-null wrapper as needed
|
|
1856
|
-
if orig_type.respond_to?(:of_type)
|
|
1857
|
-
transforms = []
|
|
1858
|
-
while (orig_type.respond_to?(:of_type))
|
|
1859
|
-
if orig_type.kind.non_null?
|
|
1860
|
-
transforms << :to_non_null_type
|
|
1861
|
-
elsif orig_type.kind.list?
|
|
1862
|
-
transforms << :to_list_type
|
|
1863
|
-
else
|
|
1864
|
-
raise "Invariant: :of_type isn't non-null or list"
|
|
1865
|
-
end
|
|
1866
|
-
orig_type = orig_type.of_type
|
|
1867
|
-
end
|
|
1868
|
-
transforms.reverse_each { |t| type = type.public_send(t) }
|
|
1869
|
-
end
|
|
1870
|
-
owner.type = type
|
|
1871
|
-
else
|
|
1872
|
-
raise "Unexpected update: #{owner.inspect} #{type.inspect}"
|
|
1873
|
-
end
|
|
1874
|
-
end
|
|
1875
|
-
|
|
1876
|
-
def add_type(type, owner:, late_types:, path:)
|
|
1877
|
-
if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
|
|
1878
|
-
type_class = type.metadata[:type_class]
|
|
1879
|
-
if type_class.nil?
|
|
1880
|
-
raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
|
|
1881
|
-
else
|
|
1882
|
-
type = type_class
|
|
1883
|
-
end
|
|
1884
|
-
elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
|
|
1885
|
-
late_types << [owner, type]
|
|
1886
|
-
return
|
|
1887
|
-
end
|
|
1888
|
-
|
|
1889
|
-
if owner.is_a?(Class) && owner < GraphQL::Schema::Union
|
|
1890
|
-
um = own_union_memberships[type.graphql_name] ||= []
|
|
1891
|
-
um << owner
|
|
1892
|
-
end
|
|
1893
|
-
|
|
1894
|
-
if (prev_type = own_types[type.graphql_name])
|
|
1895
|
-
if prev_type != type
|
|
1896
|
-
raise DuplicateTypeNamesError.new(
|
|
1897
|
-
type_name: type.graphql_name,
|
|
1898
|
-
first_definition: prev_type,
|
|
1899
|
-
second_definition: type,
|
|
1900
|
-
path: path,
|
|
1901
|
-
)
|
|
1902
|
-
else
|
|
1903
|
-
# This type was already added
|
|
1904
|
-
end
|
|
1905
|
-
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
|
1906
|
-
type.arguments.each do |name, arg|
|
|
1907
|
-
arg_type = arg.type.unwrap
|
|
1908
|
-
references_to(arg_type, from: arg)
|
|
1909
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
|
|
1910
|
-
end
|
|
1911
|
-
else
|
|
1912
|
-
own_types[type.graphql_name] = type
|
|
1913
|
-
add_directives_from(type)
|
|
1914
|
-
if type.kind.fields?
|
|
1915
|
-
type.fields.each do |name, field|
|
|
1916
|
-
field_type = field.type.unwrap
|
|
1917
|
-
references_to(field_type, from: field)
|
|
1918
|
-
field_path = path + [name]
|
|
1919
|
-
add_type(field_type, owner: field, late_types: late_types, path: field_path)
|
|
1920
|
-
add_directives_from(field)
|
|
1921
|
-
field.arguments.each do |arg_name, arg|
|
|
1922
|
-
add_directives_from(arg)
|
|
1923
|
-
arg_type = arg.type.unwrap
|
|
1924
|
-
references_to(arg_type, from: arg)
|
|
1925
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
|
|
1926
|
-
end
|
|
1927
|
-
end
|
|
1928
|
-
end
|
|
1929
|
-
if type.kind.input_object?
|
|
1930
|
-
type.arguments.each do |arg_name, arg|
|
|
1931
|
-
add_directives_from(arg)
|
|
1932
|
-
arg_type = arg.type.unwrap
|
|
1933
|
-
references_to(arg_type, from: arg)
|
|
1934
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
|
|
1935
|
-
end
|
|
1936
|
-
end
|
|
1937
|
-
if type.kind.union?
|
|
1938
|
-
own_possible_types[type.graphql_name] = type.possible_types
|
|
1939
|
-
type.possible_types.each do |t|
|
|
1940
|
-
add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
|
|
1941
|
-
end
|
|
1942
|
-
end
|
|
1943
|
-
if type.kind.interface?
|
|
1944
|
-
type.orphan_types.each do |t|
|
|
1945
|
-
add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
|
|
1946
|
-
end
|
|
1947
|
-
end
|
|
1948
|
-
if type.kind.object?
|
|
1949
|
-
own_possible_types[type.graphql_name] = [type]
|
|
1950
|
-
type.interface_type_memberships.each do |interface_type_membership|
|
|
1951
|
-
case interface_type_membership
|
|
1952
|
-
when Schema::TypeMembership
|
|
1953
|
-
interface_type = interface_type_membership.abstract_type
|
|
1954
|
-
# We can get these now; we'll have to get late-bound types later
|
|
1955
|
-
if interface_type.is_a?(Module)
|
|
1956
|
-
implementers = own_possible_types[interface_type.graphql_name] ||= []
|
|
1957
|
-
implementers << type
|
|
1958
|
-
end
|
|
1959
|
-
when String, Schema::LateBoundType
|
|
1960
|
-
interface_type = interface_type_membership
|
|
1961
|
-
else
|
|
1962
|
-
raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
|
|
1963
|
-
end
|
|
1964
|
-
add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
|
|
1965
|
-
end
|
|
1966
|
-
end
|
|
1967
|
-
end
|
|
1968
|
-
end
|
|
1969
|
-
|
|
1970
|
-
def add_directives_from(owner)
|
|
1971
|
-
owner.directives.each { |dir| directive(dir.class) }
|
|
1972
|
-
end
|
|
1973
1908
|
end
|
|
1974
1909
|
|
|
1975
1910
|
def dataloader_class
|
|
@@ -33,6 +33,7 @@ module GraphQL
|
|
|
33
33
|
GraphQL::StaticValidation::VariablesAreUsedAndDefined,
|
|
34
34
|
GraphQL::StaticValidation::VariableUsagesAreAllowed,
|
|
35
35
|
GraphQL::StaticValidation::MutationRootExists,
|
|
36
|
+
GraphQL::StaticValidation::QueryRootExists,
|
|
36
37
|
GraphQL::StaticValidation::SubscriptionRootExists,
|
|
37
38
|
GraphQL::StaticValidation::InputObjectNamesAreUnique,
|
|
38
39
|
]
|
|
@@ -94,7 +94,7 @@ module GraphQL
|
|
|
94
94
|
|
|
95
95
|
def on_field(node, parent)
|
|
96
96
|
parent_type = @object_types.last
|
|
97
|
-
field_definition = @schema.get_field(parent_type, node.name)
|
|
97
|
+
field_definition = @schema.get_field(parent_type, node.name, @context.query.context)
|
|
98
98
|
@field_definitions.push(field_definition)
|
|
99
99
|
if !field_definition.nil?
|
|
100
100
|
next_object_type = field_definition.type.unwrap
|
|
@@ -120,14 +120,14 @@ module GraphQL
|
|
|
120
120
|
argument_defn = if (arg = @argument_definitions.last)
|
|
121
121
|
arg_type = arg.type.unwrap
|
|
122
122
|
if arg_type.kind.input_object?
|
|
123
|
-
arg_type
|
|
123
|
+
@context.warden.get_argument(arg_type, node.name)
|
|
124
124
|
else
|
|
125
125
|
nil
|
|
126
126
|
end
|
|
127
127
|
elsif (directive_defn = @directive_definitions.last)
|
|
128
|
-
directive_defn
|
|
128
|
+
@context.warden.get_argument(directive_defn, node.name)
|
|
129
129
|
elsif (field_defn = @field_definitions.last)
|
|
130
|
-
field_defn
|
|
130
|
+
@context.warden.get_argument(field_defn, node.name)
|
|
131
131
|
else
|
|
132
132
|
nil
|
|
133
133
|
end
|
|
@@ -187,7 +187,7 @@ module GraphQL
|
|
|
187
187
|
|
|
188
188
|
def on_fragment_with_type(node)
|
|
189
189
|
object_type = if node.type
|
|
190
|
-
@
|
|
190
|
+
@context.warden.get_type(node.type.name)
|
|
191
191
|
else
|
|
192
192
|
@object_types.last
|
|
193
193
|
end
|
|
@@ -205,6 +205,9 @@ module GraphQL
|
|
|
205
205
|
private
|
|
206
206
|
|
|
207
207
|
def add_error(error, path: nil)
|
|
208
|
+
if @context.too_many_errors?
|
|
209
|
+
throw :too_many_validation_errors
|
|
210
|
+
end
|
|
208
211
|
error.path ||= (path || @path.dup)
|
|
209
212
|
context.errors << error
|
|
210
213
|
end
|
|
@@ -95,7 +95,7 @@ module GraphQL
|
|
|
95
95
|
def required_input_fields_are_present(type, ast_node)
|
|
96
96
|
# TODO - would be nice to use these to create an error message so the caller knows
|
|
97
97
|
# that required fields are missing
|
|
98
|
-
required_field_names =
|
|
98
|
+
required_field_names = @warden.arguments(type)
|
|
99
99
|
.select { |argument| argument.type.kind.non_null? && @warden.get_argument(type, argument.name) }
|
|
100
100
|
.map(&:name)
|
|
101
101
|
|
|
@@ -15,7 +15,7 @@ module GraphQL
|
|
|
15
15
|
if @context.schema.error_bubbling || context.errors.none? { |err| err.path.take(@path.size) == @path }
|
|
16
16
|
parent_defn = parent_definition(parent)
|
|
17
17
|
|
|
18
|
-
if parent_defn && (arg_defn = parent_defn
|
|
18
|
+
if parent_defn && (arg_defn = context.warden.get_argument(parent_defn, node.name))
|
|
19
19
|
validation_result = context.validate_literal(node.value, arg_defn.type)
|
|
20
20
|
if !validation_result.valid?
|
|
21
21
|
kind_of_node = node_type(parent)
|