graphql 2.3.5 → 2.3.12
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +46 -0
- data/lib/graphql/analysis/analyzer.rb +89 -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 +183 -0
- data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
- data/lib/graphql/analysis/visitor.rb +283 -0
- data/lib/graphql/analysis.rb +92 -1
- data/lib/graphql/current.rb +52 -0
- data/lib/graphql/dataloader/async_dataloader.rb +2 -0
- data/lib/graphql/dataloader/source.rb +5 -2
- data/lib/graphql/dataloader.rb +4 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/runtime.rb +8 -14
- data/lib/graphql/execution/interpreter.rb +3 -1
- data/lib/graphql/execution/lookahead.rb +10 -10
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +6 -11
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language/document_from_schema_definition.rb +19 -26
- data/lib/graphql/language/lexer.rb +0 -3
- data/lib/graphql/language/nodes.rb +2 -2
- data/lib/graphql/language/parser.rb +9 -1
- data/lib/graphql/language/sanitized_printer.rb +1 -1
- data/lib/graphql/language.rb +0 -1
- data/lib/graphql/query/context.rb +7 -1
- data/lib/graphql/query/null_context.rb +2 -2
- data/lib/graphql/query/validation_pipeline.rb +2 -2
- data/lib/graphql/query.rb +26 -7
- data/lib/graphql/schema/always_visible.rb +1 -0
- data/lib/graphql/schema/argument.rb +19 -5
- data/lib/graphql/schema/build_from_definition.rb +8 -1
- data/lib/graphql/schema/directive/flagged.rb +1 -1
- data/lib/graphql/schema/directive.rb +2 -0
- data/lib/graphql/schema/enum.rb +9 -5
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +13 -1
- data/lib/graphql/schema/has_single_input_argument.rb +2 -1
- data/lib/graphql/schema/input_object.rb +8 -7
- data/lib/graphql/schema/interface.rb +20 -4
- data/lib/graphql/schema/introspection_system.rb +5 -16
- data/lib/graphql/schema/member/has_arguments.rb +14 -9
- data/lib/graphql/schema/member/has_fields.rb +6 -4
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/resolver.rb +5 -5
- data/lib/graphql/schema/subset.rb +510 -0
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/types_migration.rb +185 -0
- data/lib/graphql/schema/validator/all_validator.rb +60 -0
- data/lib/graphql/schema/validator.rb +2 -0
- data/lib/graphql/schema/warden.rb +89 -5
- data/lib/graphql/schema.rb +74 -37
- data/lib/graphql/static_validation/base_visitor.rb +6 -5
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +7 -7
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- 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/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validation_context.rb +2 -2
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/event.rb +1 -1
- data/lib/graphql/subscriptions.rb +3 -3
- data/lib/graphql/testing/helpers.rb +8 -5
- data/lib/graphql/types/relay/connection_behaviors.rb +10 -0
- data/lib/graphql/types/relay/edge_behaviors.rb +10 -0
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +2 -0
- metadata +28 -13
- data/lib/graphql/analysis/ast/analyzer.rb +0 -91
- data/lib/graphql/analysis/ast/field_usage.rb +0 -84
- 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 -185
- data/lib/graphql/analysis/ast/visitor.rb +0 -284
- data/lib/graphql/analysis/ast.rb +0 -94
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
|
@@ -16,11 +16,11 @@ module GraphQL
|
|
|
16
16
|
private
|
|
17
17
|
|
|
18
18
|
def assert_required_args(ast_node, defn)
|
|
19
|
-
args =
|
|
19
|
+
args = @context.query.types.arguments(defn)
|
|
20
20
|
return if args.empty?
|
|
21
21
|
present_argument_names = ast_node.arguments.map(&:name)
|
|
22
|
-
required_argument_names = context.
|
|
23
|
-
.select { |a| a.type.kind.non_null? && !a.default_value? && context.
|
|
22
|
+
required_argument_names = context.query.types.arguments(defn)
|
|
23
|
+
.select { |a| a.type.kind.non_null? && !a.default_value? && context.query.types.argument(defn, a.name) }
|
|
24
24
|
.map!(&:name)
|
|
25
25
|
|
|
26
26
|
missing_names = required_argument_names - present_argument_names
|
|
@@ -26,7 +26,7 @@ module GraphQL
|
|
|
26
26
|
context.directive_definition || context.field_definition
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
parent_type = context.
|
|
29
|
+
parent_type = context.types.argument(defn, parent_name(parent, defn))
|
|
30
30
|
parent_type ? parent_type.type.unwrap : nil
|
|
31
31
|
end
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ module GraphQL
|
|
|
34
34
|
parent_type = get_parent_type(context, parent)
|
|
35
35
|
return unless parent_type && parent_type.kind.input_object?
|
|
36
36
|
|
|
37
|
-
required_fields = context.
|
|
37
|
+
required_fields = context.types.arguments(parent_type)
|
|
38
38
|
.select{ |arg| arg.type.kind.non_null? && !arg.default_value? }
|
|
39
39
|
.map!(&:graphql_name)
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ module GraphQL
|
|
|
43
43
|
|
|
44
44
|
missing_fields.each do |missing_field|
|
|
45
45
|
path = [*context.path, missing_field]
|
|
46
|
-
missing_field_type = context.
|
|
46
|
+
missing_field_type = context.types.argument(parent_type, missing_field).type
|
|
47
47
|
add_error(RequiredInputObjectAttributesArePresentError.new(
|
|
48
48
|
"Argument '#{missing_field}' on InputObject '#{parent_type.to_type_signature}' is required. Expected type #{missing_field_type.to_type_signature}",
|
|
49
49
|
argument_name: missing_field,
|
|
@@ -3,7 +3,7 @@ module GraphQL
|
|
|
3
3
|
module StaticValidation
|
|
4
4
|
module SubscriptionRootExists
|
|
5
5
|
def on_operation_definition(node, _parent)
|
|
6
|
-
if node.operation_type == "subscription" && context.
|
|
6
|
+
if node.operation_type == "subscription" && context.types.subscription_root.nil?
|
|
7
7
|
add_error(GraphQL::StaticValidation::SubscriptionRootExistsError.new(
|
|
8
8
|
'Schema is not configured for subscriptions',
|
|
9
9
|
nodes: node
|
|
@@ -5,36 +5,27 @@ module GraphQL
|
|
|
5
5
|
def on_variable_definition(node, parent)
|
|
6
6
|
if !node.default_value.nil?
|
|
7
7
|
value = node.default_value
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
nodes: node,
|
|
12
|
-
name: node.name,
|
|
13
|
-
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
|
|
14
|
-
))
|
|
8
|
+
type = context.schema.type_from_ast(node.type, context: context)
|
|
9
|
+
if type.nil?
|
|
10
|
+
# This is handled by another validator
|
|
15
11
|
else
|
|
16
|
-
|
|
17
|
-
if type.nil?
|
|
18
|
-
# This is handled by another validator
|
|
19
|
-
else
|
|
20
|
-
validation_result = context.validate_literal(value, type)
|
|
12
|
+
validation_result = context.validate_literal(value, type)
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
|
30
|
-
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
|
31
|
-
error_message,
|
|
32
|
-
nodes: node,
|
|
33
|
-
name: node.name,
|
|
34
|
-
type: type.to_type_signature,
|
|
35
|
-
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
|
|
36
|
-
))
|
|
14
|
+
if !validation_result.valid?
|
|
15
|
+
problems = validation_result.problems
|
|
16
|
+
first_problem = problems && problems.first
|
|
17
|
+
if first_problem
|
|
18
|
+
error_message = first_problem["explanation"]
|
|
37
19
|
end
|
|
20
|
+
|
|
21
|
+
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
|
22
|
+
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
|
23
|
+
error_message,
|
|
24
|
+
nodes: node,
|
|
25
|
+
name: node.name,
|
|
26
|
+
type: type.to_type_signature,
|
|
27
|
+
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE],
|
|
28
|
+
))
|
|
38
29
|
end
|
|
39
30
|
end
|
|
40
31
|
end
|
|
@@ -65,7 +65,7 @@ module GraphQL
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
arg_defn =
|
|
68
|
+
arg_defn = @types.argument(argument_owner, arg_node.name)
|
|
69
69
|
arg_defn_type = arg_defn.type
|
|
70
70
|
|
|
71
71
|
# If the argument is non-null, but it was given a default value,
|
|
@@ -4,7 +4,7 @@ module GraphQL
|
|
|
4
4
|
module VariablesAreInputTypes
|
|
5
5
|
def on_variable_definition(node, parent)
|
|
6
6
|
type_name = get_type_name(node.type)
|
|
7
|
-
type = context.
|
|
7
|
+
type = context.query.types.type(type_name)
|
|
8
8
|
|
|
9
9
|
if type.nil?
|
|
10
10
|
add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
|
|
@@ -13,14 +13,14 @@ module GraphQL
|
|
|
13
13
|
|
|
14
14
|
attr_reader :query, :errors, :visitor,
|
|
15
15
|
:on_dependency_resolve_handlers,
|
|
16
|
-
:max_errors, :
|
|
16
|
+
:max_errors, :types, :schema
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def_delegators :@query, :document, :fragments, :operations
|
|
20
20
|
|
|
21
21
|
def initialize(query, visitor_class, max_errors)
|
|
22
22
|
@query = query
|
|
23
|
-
@
|
|
23
|
+
@types = query.types # TODO update migrated callers to use this accessor
|
|
24
24
|
@schema = query.schema
|
|
25
25
|
@literal_validator = LiteralValidator.new(context: query.context)
|
|
26
26
|
@errors = []
|
|
@@ -9,7 +9,7 @@ module GraphQL
|
|
|
9
9
|
# Assign the result to `context.namespace(:subscriptions)[:subscription_broadcastable]`
|
|
10
10
|
# @api private
|
|
11
11
|
# @see Subscriptions#broadcastable? for a public API
|
|
12
|
-
class BroadcastAnalyzer < GraphQL::Analysis::
|
|
12
|
+
class BroadcastAnalyzer < GraphQL::Analysis::Analyzer
|
|
13
13
|
def initialize(subject)
|
|
14
14
|
super
|
|
15
15
|
@default_broadcastable = subject.schema.subscriptions.default_broadcastable
|
|
@@ -28,9 +28,8 @@ module GraphQL
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
current_field = visitor.field_definition
|
|
31
|
-
apply_broadcastable(current_field)
|
|
32
|
-
|
|
33
31
|
current_type = visitor.parent_type_definition
|
|
32
|
+
apply_broadcastable(current_type, current_field)
|
|
34
33
|
if current_type.kind.interface?
|
|
35
34
|
pt = @query.possible_types(current_type)
|
|
36
35
|
pt.each do |object_type|
|
|
@@ -38,7 +37,7 @@ module GraphQL
|
|
|
38
37
|
# Inherited fields would be exactly the same object;
|
|
39
38
|
# only check fields that are overrides of the inherited one
|
|
40
39
|
if ot_field && ot_field != current_field
|
|
41
|
-
apply_broadcastable(ot_field)
|
|
40
|
+
apply_broadcastable(object_type, ot_field)
|
|
42
41
|
end
|
|
43
42
|
end
|
|
44
43
|
end
|
|
@@ -55,10 +54,16 @@ module GraphQL
|
|
|
55
54
|
private
|
|
56
55
|
|
|
57
56
|
# Modify `@subscription_broadcastable` based on `field_defn`'s configuration (and/or the default value)
|
|
58
|
-
def apply_broadcastable(field_defn)
|
|
57
|
+
def apply_broadcastable(owner_type, field_defn)
|
|
59
58
|
current_field_broadcastable = field_defn.introspection? || field_defn.broadcastable?
|
|
59
|
+
|
|
60
|
+
if current_field_broadcastable.nil? && owner_type.respond_to?(:default_broadcastable?)
|
|
61
|
+
current_field_broadcastable = owner_type.default_broadcastable?
|
|
62
|
+
end
|
|
63
|
+
|
|
60
64
|
case current_field_broadcastable
|
|
61
65
|
when nil
|
|
66
|
+
query.logger.debug { "`broadcastable: nil` for field: #{field_defn.path}" }
|
|
62
67
|
# If the value wasn't set, mix in the default value:
|
|
63
68
|
# - If the default is false and the current value is true, make it false
|
|
64
69
|
# - If the default is true and the current value is true, it stays true
|
|
@@ -66,6 +71,7 @@ module GraphQL
|
|
|
66
71
|
# - If the default is true and the current value is false, keep it false
|
|
67
72
|
@subscription_broadcastable = @subscription_broadcastable && @default_broadcastable
|
|
68
73
|
when false
|
|
74
|
+
query.logger.debug { "`broadcastable: false` for field: #{field_defn.path}" }
|
|
69
75
|
# One non-broadcastable field is enough to make the whole subscription non-broadcastable
|
|
70
76
|
@subscription_broadcastable = false
|
|
71
77
|
when true
|
|
@@ -137,7 +137,7 @@ module GraphQL
|
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def get_arg_definition(arg_owner, arg_name, context)
|
|
140
|
-
|
|
140
|
+
context.types.argument(arg_owner, arg_name) || context.types.arguments(arg_owner).find { |v| v.keyword.to_s == arg_name }
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
end
|
|
@@ -64,12 +64,12 @@ module GraphQL
|
|
|
64
64
|
event_name = event_name.to_s
|
|
65
65
|
|
|
66
66
|
# Try with the verbatim input first:
|
|
67
|
-
field =
|
|
67
|
+
field = dummy_query.types.field(@schema.subscription, event_name) # rubocop:disable Development/ContextIsPassedCop
|
|
68
68
|
|
|
69
69
|
if field.nil?
|
|
70
70
|
# And if it wasn't found, normalize it:
|
|
71
71
|
normalized_event_name = normalize_name(event_name)
|
|
72
|
-
field =
|
|
72
|
+
field = dummy_query.types.field(@schema.subscription, normalized_event_name) # rubocop:disable Development/ContextIsPassedCop
|
|
73
73
|
if field.nil?
|
|
74
74
|
raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
|
|
75
75
|
end
|
|
@@ -235,7 +235,7 @@ module GraphQL
|
|
|
235
235
|
if !query.valid?
|
|
236
236
|
raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
|
|
237
237
|
end
|
|
238
|
-
GraphQL::Analysis
|
|
238
|
+
GraphQL::Analysis.analyze_query(query, @schema.query_analyzers)
|
|
239
239
|
query.context.namespace(:subscriptions)[:subscription_broadcastable]
|
|
240
240
|
end
|
|
241
241
|
|
|
@@ -43,7 +43,7 @@ module GraphQL
|
|
|
43
43
|
type_name, *field_names = field_path.split(".")
|
|
44
44
|
dummy_query = GraphQL::Query.new(schema, "{ __typename }", context: context)
|
|
45
45
|
query_context = dummy_query.context
|
|
46
|
-
object_type = dummy_query.
|
|
46
|
+
object_type = dummy_query.types.type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
|
47
47
|
if object_type
|
|
48
48
|
graphql_result = object
|
|
49
49
|
field_names.each do |field_name|
|
|
@@ -52,7 +52,7 @@ module GraphQL
|
|
|
52
52
|
if graphql_result.nil?
|
|
53
53
|
return nil
|
|
54
54
|
end
|
|
55
|
-
visible_field = dummy_query.
|
|
55
|
+
visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
|
|
56
56
|
if visible_field
|
|
57
57
|
dummy_query.context.dataloader.run_isolated {
|
|
58
58
|
field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
|
|
@@ -90,10 +90,13 @@ module GraphQL
|
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
graphql_result
|
|
93
|
-
elsif schema.has_defined_type?(type_name)
|
|
94
|
-
raise TypeNotVisibleError.new(type_name: type_name)
|
|
95
93
|
else
|
|
96
|
-
|
|
94
|
+
unfiltered_type = Schema::Subset.pass_thru(schema: schema, context: context).type(type_name)
|
|
95
|
+
if unfiltered_type
|
|
96
|
+
raise TypeNotVisibleError.new(type_name: type_name)
|
|
97
|
+
else
|
|
98
|
+
raise TypeNotDefinedError.new(type_name: type_name)
|
|
99
|
+
end
|
|
97
100
|
end
|
|
98
101
|
end
|
|
99
102
|
|
|
@@ -18,6 +18,7 @@ module GraphQL
|
|
|
18
18
|
self.node_type = nil
|
|
19
19
|
self.edge_class = nil
|
|
20
20
|
}
|
|
21
|
+
child_class.default_broadcastable(nil)
|
|
21
22
|
add_page_info_field(child_class)
|
|
22
23
|
end
|
|
23
24
|
|
|
@@ -31,12 +32,21 @@ module GraphQL
|
|
|
31
32
|
child_class.edge_type = nil
|
|
32
33
|
child_class.node_type = nil
|
|
33
34
|
child_class.edge_class = nil
|
|
35
|
+
child_class.default_broadcastable(default_broadcastable?)
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
def default_relay?
|
|
37
39
|
true
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
def default_broadcastable?
|
|
43
|
+
@default_broadcastable
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def default_broadcastable(new_value)
|
|
47
|
+
@default_broadcastable = new_value
|
|
48
|
+
end
|
|
49
|
+
|
|
40
50
|
# @return [Class]
|
|
41
51
|
attr_reader :node_type
|
|
42
52
|
|
|
@@ -10,6 +10,7 @@ module GraphQL
|
|
|
10
10
|
child_class.extend(ClassMethods)
|
|
11
11
|
child_class.class_eval { self.node_type = nil }
|
|
12
12
|
child_class.node_nullable(true)
|
|
13
|
+
child_class.default_broadcastable(nil)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def node
|
|
@@ -24,12 +25,21 @@ module GraphQL
|
|
|
24
25
|
super
|
|
25
26
|
child_class.node_type = nil
|
|
26
27
|
child_class.node_nullable = nil
|
|
28
|
+
child_class.default_broadcastable(default_broadcastable?)
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def default_relay?
|
|
30
32
|
true
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
def default_broadcastable?
|
|
36
|
+
@default_broadcastable
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def default_broadcastable(new_value)
|
|
40
|
+
@default_broadcastable = new_value
|
|
41
|
+
end
|
|
42
|
+
|
|
33
43
|
# Get or set the Object type that this edge wraps.
|
|
34
44
|
#
|
|
35
45
|
# @param node_type [Class] A `Schema::Object` subclass
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "json"
|
|
|
4
4
|
require "set"
|
|
5
5
|
require "singleton"
|
|
6
6
|
require "forwardable"
|
|
7
|
+
require "fiber/storage"
|
|
7
8
|
|
|
8
9
|
module GraphQL
|
|
9
10
|
class Error < StandardError
|
|
@@ -121,3 +122,4 @@ require "graphql/unauthorized_error"
|
|
|
121
122
|
require "graphql/unauthorized_field_error"
|
|
122
123
|
require "graphql/load_application_object_failed_error"
|
|
123
124
|
require "graphql/testing"
|
|
125
|
+
require "graphql/current"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Mosolgo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-08-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: fiber-storage
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: benchmark-ips
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -306,14 +320,13 @@ files:
|
|
|
306
320
|
- lib/generators/graphql/union_generator.rb
|
|
307
321
|
- lib/graphql.rb
|
|
308
322
|
- lib/graphql/analysis.rb
|
|
309
|
-
- lib/graphql/analysis/
|
|
310
|
-
- lib/graphql/analysis/
|
|
311
|
-
- lib/graphql/analysis/
|
|
312
|
-
- lib/graphql/analysis/
|
|
313
|
-
- lib/graphql/analysis/
|
|
314
|
-
- lib/graphql/analysis/
|
|
315
|
-
- lib/graphql/analysis/
|
|
316
|
-
- lib/graphql/analysis/ast/visitor.rb
|
|
323
|
+
- lib/graphql/analysis/analyzer.rb
|
|
324
|
+
- lib/graphql/analysis/field_usage.rb
|
|
325
|
+
- lib/graphql/analysis/max_query_complexity.rb
|
|
326
|
+
- lib/graphql/analysis/max_query_depth.rb
|
|
327
|
+
- lib/graphql/analysis/query_complexity.rb
|
|
328
|
+
- lib/graphql/analysis/query_depth.rb
|
|
329
|
+
- lib/graphql/analysis/visitor.rb
|
|
317
330
|
- lib/graphql/analysis_error.rb
|
|
318
331
|
- lib/graphql/backtrace.rb
|
|
319
332
|
- lib/graphql/backtrace/inspect_result.rb
|
|
@@ -322,6 +335,7 @@ files:
|
|
|
322
335
|
- lib/graphql/backtrace/traced_error.rb
|
|
323
336
|
- lib/graphql/backtrace/tracer.rb
|
|
324
337
|
- lib/graphql/coercion_error.rb
|
|
338
|
+
- lib/graphql/current.rb
|
|
325
339
|
- lib/graphql/dataloader.rb
|
|
326
340
|
- lib/graphql/dataloader/async_dataloader.rb
|
|
327
341
|
- lib/graphql/dataloader/null_dataloader.rb
|
|
@@ -377,7 +391,6 @@ files:
|
|
|
377
391
|
- lib/graphql/language/printer.rb
|
|
378
392
|
- lib/graphql/language/sanitized_printer.rb
|
|
379
393
|
- lib/graphql/language/static_visitor.rb
|
|
380
|
-
- lib/graphql/language/token.rb
|
|
381
394
|
- lib/graphql/language/visitor.rb
|
|
382
395
|
- lib/graphql/load_application_object_failed_error.rb
|
|
383
396
|
- lib/graphql/name_validator.rb
|
|
@@ -440,7 +453,6 @@ files:
|
|
|
440
453
|
- lib/graphql/schema/input_object.rb
|
|
441
454
|
- lib/graphql/schema/interface.rb
|
|
442
455
|
- lib/graphql/schema/introspection_system.rb
|
|
443
|
-
- lib/graphql/schema/invalid_type_error.rb
|
|
444
456
|
- lib/graphql/schema/late_bound_type.rb
|
|
445
457
|
- lib/graphql/schema/list.rb
|
|
446
458
|
- lib/graphql/schema/loader.rb
|
|
@@ -471,12 +483,15 @@ files:
|
|
|
471
483
|
- lib/graphql/schema/resolver/has_payload_type.rb
|
|
472
484
|
- lib/graphql/schema/scalar.rb
|
|
473
485
|
- lib/graphql/schema/subscription.rb
|
|
486
|
+
- lib/graphql/schema/subset.rb
|
|
474
487
|
- lib/graphql/schema/timeout.rb
|
|
475
488
|
- lib/graphql/schema/type_expression.rb
|
|
476
489
|
- lib/graphql/schema/type_membership.rb
|
|
490
|
+
- lib/graphql/schema/types_migration.rb
|
|
477
491
|
- lib/graphql/schema/union.rb
|
|
478
492
|
- lib/graphql/schema/unique_within_type.rb
|
|
479
493
|
- lib/graphql/schema/validator.rb
|
|
494
|
+
- lib/graphql/schema/validator/all_validator.rb
|
|
480
495
|
- lib/graphql/schema/validator/allow_blank_validator.rb
|
|
481
496
|
- lib/graphql/schema/validator/allow_null_validator.rb
|
|
482
497
|
- lib/graphql/schema/validator/exclusion_validator.rb
|
|
@@ -645,7 +660,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
645
660
|
- !ruby/object:Gem::Version
|
|
646
661
|
version: '0'
|
|
647
662
|
requirements: []
|
|
648
|
-
rubygems_version: 3.
|
|
663
|
+
rubygems_version: 3.3.7
|
|
649
664
|
signing_key:
|
|
650
665
|
specification_version: 4
|
|
651
666
|
summary: A GraphQL language and runtime for Ruby
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
module GraphQL
|
|
3
|
-
module Analysis
|
|
4
|
-
module AST
|
|
5
|
-
# Query analyzer for query ASTs. Query analyzers respond to visitor style methods
|
|
6
|
-
# but are prefixed by `enter` and `leave`.
|
|
7
|
-
#
|
|
8
|
-
# When an analyzer is initialized with a Multiplex, you can always get the current query from
|
|
9
|
-
# `visitor.query` in the visit methods.
|
|
10
|
-
#
|
|
11
|
-
# @param [GraphQL::Query, GraphQL::Execution::Multiplex] The query or multiplex to analyze
|
|
12
|
-
class Analyzer
|
|
13
|
-
def initialize(subject)
|
|
14
|
-
@subject = subject
|
|
15
|
-
|
|
16
|
-
if subject.is_a?(GraphQL::Query)
|
|
17
|
-
@query = subject
|
|
18
|
-
@multiplex = nil
|
|
19
|
-
else
|
|
20
|
-
@multiplex = subject
|
|
21
|
-
@query = nil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Analyzer hook to decide at analysis time whether a query should
|
|
26
|
-
# be analyzed or not.
|
|
27
|
-
# @return [Boolean] If the query should be analyzed or not
|
|
28
|
-
def analyze?
|
|
29
|
-
true
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Analyzer hook to decide at analysis time whether analysis
|
|
33
|
-
# requires a visitor pass; can be disabled for precomputed results.
|
|
34
|
-
# @return [Boolean] If analysis requires visitation or not
|
|
35
|
-
def visit?
|
|
36
|
-
true
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# The result for this analyzer. Returning {GraphQL::AnalysisError} results
|
|
40
|
-
# in a query error.
|
|
41
|
-
# @return [Any] The analyzer result
|
|
42
|
-
def result
|
|
43
|
-
raise GraphQL::RequiredImplementationMissingError
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
class << self
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
def build_visitor_hooks(member_name)
|
|
50
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
51
|
-
def on_enter_#{member_name}(node, parent, visitor)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def on_leave_#{member_name}(node, parent, visitor)
|
|
55
|
-
end
|
|
56
|
-
EOS
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
build_visitor_hooks :argument
|
|
61
|
-
build_visitor_hooks :directive
|
|
62
|
-
build_visitor_hooks :document
|
|
63
|
-
build_visitor_hooks :enum
|
|
64
|
-
build_visitor_hooks :field
|
|
65
|
-
build_visitor_hooks :fragment_spread
|
|
66
|
-
build_visitor_hooks :inline_fragment
|
|
67
|
-
build_visitor_hooks :input_object
|
|
68
|
-
build_visitor_hooks :list_type
|
|
69
|
-
build_visitor_hooks :non_null_type
|
|
70
|
-
build_visitor_hooks :null_value
|
|
71
|
-
build_visitor_hooks :operation_definition
|
|
72
|
-
build_visitor_hooks :type_name
|
|
73
|
-
build_visitor_hooks :variable_definition
|
|
74
|
-
build_visitor_hooks :variable_identifier
|
|
75
|
-
build_visitor_hooks :abstract_node
|
|
76
|
-
|
|
77
|
-
protected
|
|
78
|
-
|
|
79
|
-
# @return [GraphQL::Query, GraphQL::Execution::Multiplex] Whatever this analyzer is analyzing
|
|
80
|
-
attr_reader :subject
|
|
81
|
-
|
|
82
|
-
# @return [GraphQL::Query, nil] `nil` if this analyzer is visiting a multiplex
|
|
83
|
-
# (When this is `nil`, use `visitor.query` inside visit methods to get the current query)
|
|
84
|
-
attr_reader :query
|
|
85
|
-
|
|
86
|
-
# @return [GraphQL::Execution::Multiplex, nil] `nil` if this analyzer is visiting a query
|
|
87
|
-
attr_reader :multiplex
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
module GraphQL
|
|
3
|
-
module Analysis
|
|
4
|
-
module AST
|
|
5
|
-
class FieldUsage < Analyzer
|
|
6
|
-
def initialize(query)
|
|
7
|
-
super
|
|
8
|
-
@used_fields = Set.new
|
|
9
|
-
@used_deprecated_fields = Set.new
|
|
10
|
-
@used_deprecated_arguments = Set.new
|
|
11
|
-
@used_deprecated_enum_values = Set.new
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def on_leave_field(node, parent, visitor)
|
|
15
|
-
field_defn = visitor.field_definition
|
|
16
|
-
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
|
17
|
-
@used_fields << field
|
|
18
|
-
@used_deprecated_fields << field if field_defn.deprecation_reason
|
|
19
|
-
arguments = visitor.query.arguments_for(node, field_defn)
|
|
20
|
-
# If there was an error when preparing this argument object,
|
|
21
|
-
# then this might be an error or something:
|
|
22
|
-
if arguments.respond_to?(:argument_values)
|
|
23
|
-
extract_deprecated_arguments(arguments.argument_values)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def result
|
|
28
|
-
{
|
|
29
|
-
used_fields: @used_fields.to_a,
|
|
30
|
-
used_deprecated_fields: @used_deprecated_fields.to_a,
|
|
31
|
-
used_deprecated_arguments: @used_deprecated_arguments.to_a,
|
|
32
|
-
used_deprecated_enum_values: @used_deprecated_enum_values.to_a,
|
|
33
|
-
}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def extract_deprecated_arguments(argument_values)
|
|
39
|
-
argument_values.each_pair do |_argument_name, argument|
|
|
40
|
-
if argument.definition.deprecation_reason
|
|
41
|
-
@used_deprecated_arguments << argument.definition.path
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
arg_val = argument.value
|
|
45
|
-
|
|
46
|
-
next if arg_val.nil?
|
|
47
|
-
|
|
48
|
-
argument_type = argument.definition.type
|
|
49
|
-
if argument_type.non_null?
|
|
50
|
-
argument_type = argument_type.of_type
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
if argument_type.kind.input_object?
|
|
54
|
-
extract_deprecated_arguments(argument.original_value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
|
55
|
-
elsif argument_type.kind.enum?
|
|
56
|
-
extract_deprecated_enum_value(argument_type, arg_val)
|
|
57
|
-
elsif argument_type.list?
|
|
58
|
-
inner_type = argument_type.unwrap
|
|
59
|
-
case inner_type.kind
|
|
60
|
-
when TypeKinds::INPUT_OBJECT
|
|
61
|
-
argument.original_value.each do |value|
|
|
62
|
-
extract_deprecated_arguments(value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
|
63
|
-
end
|
|
64
|
-
when TypeKinds::ENUM
|
|
65
|
-
arg_val.each do |value|
|
|
66
|
-
extract_deprecated_enum_value(inner_type, value)
|
|
67
|
-
end
|
|
68
|
-
else
|
|
69
|
-
# Not a kind of input that we track
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def extract_deprecated_enum_value(enum_type, value)
|
|
76
|
-
enum_value = @query.warden.enum_values(enum_type).find { |ev| ev.value == value }
|
|
77
|
-
if enum_value&.deprecation_reason
|
|
78
|
-
@used_deprecated_enum_values << enum_value.path
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
module GraphQL
|
|
3
|
-
module Analysis
|
|
4
|
-
module AST
|
|
5
|
-
# Used under the hood to implement complexity validation,
|
|
6
|
-
# see {Schema#max_complexity} and {Query#max_complexity}
|
|
7
|
-
class MaxQueryComplexity < QueryComplexity
|
|
8
|
-
def result
|
|
9
|
-
return if subject.max_complexity.nil?
|
|
10
|
-
|
|
11
|
-
total_complexity = max_possible_complexity
|
|
12
|
-
|
|
13
|
-
if total_complexity > subject.max_complexity
|
|
14
|
-
GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{subject.max_complexity}")
|
|
15
|
-
else
|
|
16
|
-
nil
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|