graphql 1.9.17 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/templates/schema.erb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +1 -1
- data/lib/graphql/analysis/ast/visitor.rb +3 -3
- data/lib/graphql/analysis/ast.rb +12 -11
- data/lib/graphql/argument.rb +7 -35
- data/lib/graphql/backtrace/table.rb +10 -2
- data/lib/graphql/base_type.rb +4 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/define/assign_enum_value.rb +1 -1
- data/lib/graphql/define/assign_object_field.rb +3 -3
- data/lib/graphql/define/defined_object_proxy.rb +8 -2
- data/lib/graphql/define/instance_definable.rb +10 -106
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/directive.rb +4 -1
- data/lib/graphql/enum_type.rb +5 -71
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +2 -3
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +106 -55
- data/lib/graphql/execution/interpreter.rb +5 -11
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lookahead.rb +5 -5
- data/lib/graphql/execution/multiplex.rb +13 -3
- data/lib/graphql/field.rb +9 -117
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/function.rb +1 -30
- data/lib/graphql/input_object_type.rb +2 -24
- data/lib/graphql/interface_type.rb +2 -23
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +7 -7
- data/lib/graphql/introspection/input_value_type.rb +27 -9
- data/lib/graphql/introspection/schema_type.rb +1 -6
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +50 -44
- data/lib/graphql/language/nodes.rb +3 -3
- data/lib/graphql/language/parser.rb +644 -646
- data/lib/graphql/language/parser.y +6 -4
- data/lib/graphql/language.rb +1 -1
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/object_type.rb +1 -21
- data/lib/graphql/pagination/active_record_relation_connection.rb +35 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +171 -0
- data/lib/graphql/pagination/connections.rb +108 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +151 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/query/arguments.rb +2 -1
- data/lib/graphql/query/context.rb +2 -5
- data/lib/graphql/query/literal_input.rb +30 -10
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +7 -3
- data/lib/graphql/query.rb +9 -5
- data/lib/graphql/relay/base_connection.rb +4 -0
- data/lib/graphql/relay/connection_type.rb +2 -1
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -86
- data/lib/graphql/relay/node.rb +2 -2
- data/lib/graphql/scalar_type.rb +1 -58
- data/lib/graphql/schema/argument.rb +51 -6
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +10 -4
- data/lib/graphql/schema/build_from_definition.rb +167 -178
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive.rb +28 -2
- data/lib/graphql/schema/enum.rb +40 -3
- data/lib/graphql/schema/enum_value.rb +5 -1
- data/lib/graphql/schema/field/connection_extension.rb +11 -1
- data/lib/graphql/schema/field.rb +59 -31
- data/lib/graphql/schema/find_inherited_value.rb +13 -0
- data/lib/graphql/schema/finder.rb +13 -11
- data/lib/graphql/schema/input_object.rb +107 -2
- data/lib/graphql/schema/interface.rb +10 -7
- data/lib/graphql/schema/introspection_system.rb +108 -37
- data/lib/graphql/schema/late_bound_type.rb +1 -0
- data/lib/graphql/schema/list.rb +41 -0
- data/lib/graphql/schema/loader.rb +16 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +21 -11
- data/lib/graphql/schema/member/build_type.rb +5 -1
- data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
- data/lib/graphql/schema/member/has_arguments.rb +2 -2
- data/lib/graphql/schema/member/has_ast_node.rb +17 -0
- data/lib/graphql/schema/member/has_fields.rb +4 -4
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +5 -0
- data/lib/graphql/schema/mutation.rb +1 -1
- data/lib/graphql/schema/non_null.rb +25 -0
- data/lib/graphql/schema/object.rb +15 -5
- data/lib/graphql/schema/printer.rb +1 -2
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +3 -15
- data/lib/graphql/schema/scalar.rb +19 -3
- data/lib/graphql/schema/subscription.rb +5 -5
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -3
- data/lib/graphql/schema/validation.rb +2 -2
- data/lib/graphql/schema/warden.rb +45 -20
- data/lib/graphql/schema.rb +764 -151
- data/lib/graphql/static_validation/base_visitor.rb +10 -6
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +9 -4
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +10 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +4 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -3
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -1
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -3
- data/lib/graphql/subscriptions/event.rb +7 -4
- data/lib/graphql/subscriptions/instrumentation.rb +10 -5
- data/lib/graphql/subscriptions/subscription_root.rb +0 -1
- data/lib/graphql/subscriptions.rb +34 -9
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +14 -10
- data/lib/graphql/tracing/appsignal_tracing.rb +8 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +8 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +8 -0
- data/lib/graphql/tracing/platform_tracing.rb +26 -6
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +8 -0
- data/lib/graphql/tracing/skylight_tracing.rb +8 -0
- data/lib/graphql/tracing.rb +7 -3
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/base_connection.rb +3 -1
- data/lib/graphql/union_type.rb +13 -28
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +2 -1
- metadata +15 -4
@@ -71,7 +71,7 @@ module GraphQL
|
|
71
71
|
module ContextMethods
|
72
72
|
def on_operation_definition(node, parent)
|
73
73
|
object_type = @schema.root_type_for_operation(node.operation_type)
|
74
|
-
|
74
|
+
push_type(object_type)
|
75
75
|
@path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
|
76
76
|
super
|
77
77
|
@object_types.pop
|
@@ -98,9 +98,9 @@ module GraphQL
|
|
98
98
|
@field_definitions.push(field_definition)
|
99
99
|
if !field_definition.nil?
|
100
100
|
next_object_type = field_definition.type.unwrap
|
101
|
-
|
101
|
+
push_type(next_object_type)
|
102
102
|
else
|
103
|
-
|
103
|
+
push_type(nil)
|
104
104
|
end
|
105
105
|
@path.push(node.alias || node.name)
|
106
106
|
super
|
@@ -120,7 +120,7 @@ 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
|
+
arg_type.arguments[node.name]
|
124
124
|
else
|
125
125
|
nil
|
126
126
|
end
|
@@ -187,15 +187,19 @@ module GraphQL
|
|
187
187
|
|
188
188
|
def on_fragment_with_type(node)
|
189
189
|
object_type = if node.type
|
190
|
-
@schema.
|
190
|
+
@schema.get_type(node.type.name)
|
191
191
|
else
|
192
192
|
@object_types.last
|
193
193
|
end
|
194
|
-
|
194
|
+
push_type(object_type)
|
195
195
|
yield(node)
|
196
196
|
@object_types.pop
|
197
197
|
@path.pop
|
198
198
|
end
|
199
|
+
|
200
|
+
def push_type(t)
|
201
|
+
@object_types.push(t)
|
202
|
+
end
|
199
203
|
end
|
200
204
|
|
201
205
|
private
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
nil
|
12
12
|
else
|
13
13
|
arg_ret_type = arg_defn.type.unwrap
|
14
|
-
if !arg_ret_type.
|
14
|
+
if !arg_ret_type.kind.input_object?
|
15
15
|
nil
|
16
16
|
else
|
17
17
|
arg_ret_type
|
@@ -54,7 +54,7 @@ module GraphQL
|
|
54
54
|
node.value.arguments.include?(err.ast_value)
|
55
55
|
else
|
56
56
|
# otherwise we just check equality
|
57
|
-
node.value ==
|
57
|
+
node.value == err.ast_value
|
58
58
|
end
|
59
59
|
if !matched
|
60
60
|
# This node isn't the node that caused the error,
|
@@ -67,9 +67,14 @@ module GraphQL
|
|
67
67
|
error ||= begin
|
68
68
|
kind_of_node = node_type(parent)
|
69
69
|
error_arg_name = parent_name(parent, parent_defn)
|
70
|
+
string_value = if node.value == Float::INFINITY
|
71
|
+
""
|
72
|
+
else
|
73
|
+
" (#{GraphQL::Language::Printer.new.print(node.value)})"
|
74
|
+
end
|
70
75
|
|
71
76
|
GraphQL::StaticValidation::ArgumentLiteralsAreCompatibleError.new(
|
72
|
-
"Argument '#{node.name}' on #{kind_of_node} '#{error_arg_name}' has an invalid value. Expected type '#{arg_defn.type}'.",
|
77
|
+
"Argument '#{node.name}' on #{kind_of_node} '#{error_arg_name}' has an invalid value#{string_value}. Expected type '#{arg_defn.type.to_type_signature}'.",
|
73
78
|
nodes: parent,
|
74
79
|
type: kind_of_node,
|
75
80
|
argument: node.name
|
@@ -92,7 +97,7 @@ module GraphQL
|
|
92
97
|
elsif parent.is_a?(GraphQL::Language::Nodes::InputObject)
|
93
98
|
type_defn.name
|
94
99
|
else
|
95
|
-
parent.
|
100
|
+
parent.graphql_name
|
96
101
|
end
|
97
102
|
end
|
98
103
|
|
@@ -10,10 +10,10 @@ module GraphQL
|
|
10
10
|
nil
|
11
11
|
else
|
12
12
|
arg_ret_type = arg_defn.type.unwrap
|
13
|
-
if
|
14
|
-
nil
|
15
|
-
else
|
13
|
+
if arg_ret_type.kind.input_object?
|
16
14
|
arg_ret_type
|
15
|
+
else
|
16
|
+
nil
|
17
17
|
end
|
18
18
|
end
|
19
19
|
when GraphQL::Language::Nodes::Directive
|
@@ -45,12 +45,15 @@ module GraphQL
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def parent_name(parent, type_defn)
|
48
|
-
|
48
|
+
case parent
|
49
|
+
when GraphQL::Language::Nodes::Field
|
49
50
|
parent.alias || parent.name
|
50
|
-
|
51
|
-
type_defn.
|
52
|
-
|
51
|
+
when GraphQL::Language::Nodes::InputObject
|
52
|
+
type_defn.graphql_name
|
53
|
+
when GraphQL::Language::Nodes::Argument, GraphQL::Language::Nodes::Directive
|
53
54
|
parent.name
|
55
|
+
else
|
56
|
+
raise "Invariant: Unexpected parent #{parent.inspect} (#{parent.class})"
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -56,7 +56,7 @@ module GraphQL
|
|
56
56
|
"'@#{directive_defn.graphql_name}' can't be applied to #{location_name} (allowed: #{allowed_location_names.join(", ")})",
|
57
57
|
nodes: directive_ast,
|
58
58
|
target: location_name,
|
59
|
-
name: directive_defn.
|
59
|
+
name: directive_defn.graphql_name
|
60
60
|
))
|
61
61
|
end
|
62
62
|
end
|
@@ -9,16 +9,16 @@ module GraphQL
|
|
9
9
|
if field.nil?
|
10
10
|
if parent_type.kind.union?
|
11
11
|
add_error(GraphQL::StaticValidation::FieldsHaveAppropriateSelectionsError.new(
|
12
|
-
"Selections can't be made directly on unions (see selections on #{parent_type.
|
12
|
+
"Selections can't be made directly on unions (see selections on #{parent_type.graphql_name})",
|
13
13
|
nodes: parent,
|
14
|
-
node_name: parent_type.
|
14
|
+
node_name: parent_type.graphql_name
|
15
15
|
))
|
16
16
|
else
|
17
17
|
add_error(GraphQL::StaticValidation::FieldsAreDefinedOnTypeError.new(
|
18
|
-
"Field '#{node.name}' doesn't exist on type '#{parent_type.
|
18
|
+
"Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'",
|
19
19
|
nodes: node,
|
20
20
|
field: node.name,
|
21
|
-
type: parent_type.
|
21
|
+
type: parent_type.graphql_name
|
22
22
|
))
|
23
23
|
end
|
24
24
|
else
|
@@ -27,12 +27,12 @@ module GraphQL
|
|
27
27
|
nil
|
28
28
|
elsif resolved_type.kind.scalar? && ast_node.selections.any?
|
29
29
|
if ast_node.selections.first.is_a?(GraphQL::Language::Nodes::InlineFragment)
|
30
|
-
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.
|
30
|
+
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has inline fragments [#{ast_node.selections.map(&:type).map(&:name).join(", ")}])"
|
31
31
|
else
|
32
|
-
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.
|
32
|
+
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{ast_node.selections.map(&:name).join(", ")}])"
|
33
33
|
end
|
34
34
|
elsif resolved_type.kind.fields? && ast_node.selections.empty?
|
35
|
-
"Field must have selections (%{node_name} returns #{resolved_type.
|
35
|
+
"Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
|
36
36
|
else
|
37
37
|
nil
|
38
38
|
end
|
@@ -55,13 +55,13 @@ module GraphQL
|
|
55
55
|
"name": node_name.to_s
|
56
56
|
}
|
57
57
|
unless resolved_type.nil?
|
58
|
-
extensions["type"] = resolved_type.
|
58
|
+
extensions["type"] = resolved_type.to_type_signature
|
59
59
|
end
|
60
60
|
add_error(GraphQL::StaticValidation::FieldsHaveAppropriateSelectionsError.new(
|
61
61
|
msg % { node_name: node_name },
|
62
62
|
nodes: ast_node,
|
63
63
|
node_name: node_name.to_s,
|
64
|
-
type: resolved_type.nil? ? nil : resolved_type.
|
64
|
+
type: resolved_type.nil? ? nil : resolved_type.graphql_name,
|
65
65
|
))
|
66
66
|
false
|
67
67
|
else
|
@@ -93,8 +93,8 @@ module GraphQL
|
|
93
93
|
|
94
94
|
return if fragment1.nil? || fragment2.nil?
|
95
95
|
|
96
|
-
fragment_type1 = context.
|
97
|
-
fragment_type2 = context.
|
96
|
+
fragment_type1 = context.warden.get_type(fragment1.type.name)
|
97
|
+
fragment_type2 = context.warden.get_type(fragment2.type.name)
|
98
98
|
|
99
99
|
return if fragment_type1.nil? || fragment_type2.nil?
|
100
100
|
|
@@ -146,7 +146,7 @@ module GraphQL
|
|
146
146
|
fragment = context.fragments[fragment_name]
|
147
147
|
return if fragment.nil?
|
148
148
|
|
149
|
-
fragment_type = context.
|
149
|
+
fragment_type = context.warden.get_type(fragment.type.name)
|
150
150
|
return if fragment_type.nil?
|
151
151
|
|
152
152
|
fragment_fields, fragment_spreads = fields_and_fragments_from_selection(fragment, owner_type: fragment_type, parents: [*fragment_spread.parents, fragment_type])
|
@@ -316,7 +316,7 @@ module GraphQL
|
|
316
316
|
definition = context.schema.get_field(owner_type, node.name)
|
317
317
|
fields << Field.new(node, definition, owner_type, parents)
|
318
318
|
when GraphQL::Language::Nodes::InlineFragment
|
319
|
-
fragment_type = node.type ? context.
|
319
|
+
fragment_type = node.type ? context.warden.get_type(node.type.name) : owner_type
|
320
320
|
find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: owner_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type
|
321
321
|
when GraphQL::Language::Nodes::FragmentSpread
|
322
322
|
fragment_spreads << FragmentSpread.new(node.name, parents)
|
@@ -50,12 +50,12 @@ module GraphQL
|
|
50
50
|
if child_types.none? { |c| parent_types.include?(c) }
|
51
51
|
name = node.respond_to?(:name) ? " #{node.name}" : ""
|
52
52
|
add_error(GraphQL::StaticValidation::FragmentSpreadsArePossibleError.new(
|
53
|
-
"Fragment#{name} on #{child_type.
|
53
|
+
"Fragment#{name} on #{child_type.graphql_name} can't be spread inside #{parent_type.graphql_name}",
|
54
54
|
nodes: node,
|
55
55
|
path: path,
|
56
56
|
fragment_name: name.empty? ? "unknown" : name,
|
57
|
-
type: child_type.
|
58
|
-
parent: parent_type.
|
57
|
+
type: child_type.graphql_name,
|
58
|
+
parent: parent_type.graphql_name
|
59
59
|
))
|
60
60
|
end
|
61
61
|
end
|
@@ -46,10 +46,10 @@ module GraphQL
|
|
46
46
|
path = [*context.path, missing_field]
|
47
47
|
missing_field_type = parent_type.arguments[missing_field].type
|
48
48
|
add_error(RequiredInputObjectAttributesArePresentError.new(
|
49
|
-
"Argument '#{missing_field}' on InputObject '#{parent_type}' is required. Expected type #{missing_field_type}",
|
49
|
+
"Argument '#{missing_field}' on InputObject '#{parent_type.to_type_signature}' is required. Expected type #{missing_field_type.to_type_signature}",
|
50
50
|
argument_name: missing_field,
|
51
|
-
argument_type: missing_field_type.
|
52
|
-
input_object_type: parent_type.
|
51
|
+
argument_type: missing_field_type.to_type_signature,
|
52
|
+
input_object_type: parent_type.to_type_signature,
|
53
53
|
path: path,
|
54
54
|
nodes: ast_node,
|
55
55
|
))
|
@@ -13,7 +13,7 @@ module GraphQL
|
|
13
13
|
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_ON_NON_NULL]
|
14
14
|
))
|
15
15
|
else
|
16
|
-
type = context.schema.type_from_ast(node.type)
|
16
|
+
type = context.schema.type_from_ast(node.type, context: context)
|
17
17
|
if type.nil?
|
18
18
|
# This is handled by another validator
|
19
19
|
else
|
@@ -26,13 +26,13 @@ module GraphQL
|
|
26
26
|
end
|
27
27
|
|
28
28
|
if !valid
|
29
|
-
error_message ||= "Default value for $#{node.name} doesn't match type #{type}"
|
29
|
+
error_message ||= "Default value for $#{node.name} doesn't match type #{type.to_type_signature}"
|
30
30
|
VariableDefaultValuesAreCorrectlyTypedError
|
31
31
|
add_error(GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTypedError.new(
|
32
32
|
error_message,
|
33
33
|
nodes: node,
|
34
34
|
name: node.name,
|
35
|
-
type: type.
|
35
|
+
type: type.to_type_signature,
|
36
36
|
error_type: VariableDefaultValuesAreCorrectlyTypedError::VIOLATIONS[:INVALID_TYPE]
|
37
37
|
))
|
38
38
|
end
|
@@ -52,17 +52,16 @@ module GraphQL
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def validate_usage(arguments, arg_node, ast_var)
|
55
|
-
var_type = context.schema.type_from_ast(ast_var.type)
|
55
|
+
var_type = context.schema.type_from_ast(ast_var.type, context: context)
|
56
56
|
if var_type.nil?
|
57
57
|
return
|
58
58
|
end
|
59
59
|
if !ast_var.default_value.nil?
|
60
|
-
unless var_type.
|
60
|
+
unless var_type.kind.non_null?
|
61
61
|
# If the value is required, but the argument is not,
|
62
62
|
# and yet there's a non-nil default, then we impliclty
|
63
63
|
# make the argument also a required type.
|
64
|
-
|
65
|
-
var_type = GraphQL::NonNullType.new(of_type: var_type)
|
64
|
+
var_type = var_type.to_non_null_type
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
@@ -85,10 +84,10 @@ module GraphQL
|
|
85
84
|
|
86
85
|
def create_error(error_message, var_type, ast_var, arg_defn, arg_node)
|
87
86
|
add_error(GraphQL::StaticValidation::VariableUsagesAreAllowedError.new(
|
88
|
-
"#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.
|
87
|
+
"#{error_message} on variable $#{ast_var.name} and argument #{arg_node.name} (#{var_type.to_type_signature} / #{arg_defn.type.to_type_signature})",
|
89
88
|
nodes: arg_node,
|
90
89
|
name: ast_var.name,
|
91
|
-
type: var_type.
|
90
|
+
type: var_type.to_type_signature,
|
92
91
|
argument: arg_node.name,
|
93
92
|
error: error_message
|
94
93
|
))
|
@@ -15,7 +15,7 @@ module GraphQL
|
|
15
15
|
))
|
16
16
|
elsif !type.kind.input?
|
17
17
|
add_error(GraphQL::StaticValidation::VariablesAreInputTypesError.new(
|
18
|
-
"#{type.
|
18
|
+
"#{type.graphql_name} isn't a valid input type (on $#{node.name})",
|
19
19
|
nodes: node,
|
20
20
|
name: node.name,
|
21
21
|
type: type_name
|
@@ -2,7 +2,7 @@
|
|
2
2
|
module GraphQL
|
3
3
|
module StaticValidation
|
4
4
|
# The problem is
|
5
|
-
# - Variable usage must be determined at the OperationDefinition level
|
5
|
+
# - Variable $usage must be determined at the OperationDefinition level
|
6
6
|
# - You can't tell how fragments use variables until you visit FragmentDefinitions (which may be at the end of the document)
|
7
7
|
#
|
8
8
|
# So, this validator includes some crazy logic to follow fragment spreads recursively, while avoiding infinite loops.
|
@@ -55,7 +55,7 @@ module GraphQL
|
|
55
55
|
module FragmentWithTypeStrategy
|
56
56
|
def push(stack, node)
|
57
57
|
object_type = if node.type
|
58
|
-
stack.schema.
|
58
|
+
stack.schema.get_type(node.type.name)
|
59
59
|
else
|
60
60
|
stack.object_types.last
|
61
61
|
end
|
@@ -148,7 +148,7 @@ module GraphQL
|
|
148
148
|
if stack.argument_definitions.last
|
149
149
|
arg_type = stack.argument_definitions.last.type.unwrap
|
150
150
|
if arg_type.kind.input_object?
|
151
|
-
argument_defn = arg_type.
|
151
|
+
argument_defn = arg_type.arguments[node.name]
|
152
152
|
else
|
153
153
|
argument_defn = nil
|
154
154
|
end
|
@@ -23,7 +23,7 @@ module GraphQL
|
|
23
23
|
# @return [Array<Hash>]
|
24
24
|
def validate(query, validate: true)
|
25
25
|
query.trace("validate", { validate: validate, query: query }) do
|
26
|
-
can_skip_rewrite = query.context.interpreter? && query.schema.using_ast_analysis?
|
26
|
+
can_skip_rewrite = query.context.interpreter? && query.schema.using_ast_analysis? && query.schema.is_a?(Class)
|
27
27
|
errors = if validate == false && can_skip_rewrite
|
28
28
|
[]
|
29
29
|
else
|
@@ -10,7 +10,7 @@ module GraphQL
|
|
10
10
|
# - Take care to reload context when re-delivering the subscription. (see {Query#subscription_update?})
|
11
11
|
#
|
12
12
|
# @example Adding ActionCableSubscriptions to your schema
|
13
|
-
# MySchema
|
13
|
+
# class MySchema < GraphQL::Schema
|
14
14
|
# # ...
|
15
15
|
# use GraphQL::Subscriptions::ActionCableSubscriptions
|
16
16
|
# end
|
@@ -26,7 +26,7 @@ module GraphQL
|
|
26
26
|
# variables = ensure_hash(data["variables"])
|
27
27
|
# operation_name = data["operationName"]
|
28
28
|
# context = {
|
29
|
-
# # Re-implement whatever context methods you need
|
29
|
+
# # Re-implement whatever context methods you need
|
30
30
|
# # in this channel or ApplicationCable::Channel
|
31
31
|
# # current_user: current_user,
|
32
32
|
# # Make sure the channel is in the context
|
@@ -41,7 +41,7 @@ module GraphQL
|
|
41
41
|
# })
|
42
42
|
#
|
43
43
|
# payload = {
|
44
|
-
# result: result.
|
44
|
+
# result: result.to_h,
|
45
45
|
# more: result.subscription?,
|
46
46
|
# }
|
47
47
|
#
|
@@ -49,7 +49,7 @@ module GraphQL
|
|
49
49
|
raise ArgumentError, "Unexpected arguments: #{arguments}, must be Hash or GraphQL::Arguments"
|
50
50
|
end
|
51
51
|
|
52
|
-
sorted_h = normalized_args.to_h
|
52
|
+
sorted_h = stringify_args(field, normalized_args.to_h)
|
53
53
|
Serialize.dump_recursive([scope, name, sorted_h])
|
54
54
|
end
|
55
55
|
|
@@ -71,18 +71,21 @@ module GraphQL
|
|
71
71
|
arg_defn = get_arg_definition(arg_owner, normalized_arg_name)
|
72
72
|
end
|
73
73
|
|
74
|
-
next_args[normalized_arg_name] = stringify_args(arg_defn
|
74
|
+
next_args[normalized_arg_name] = stringify_args(arg_defn.type, v)
|
75
75
|
end
|
76
|
-
|
76
|
+
# Make sure they're deeply sorted
|
77
|
+
next_args.sort.to_h
|
77
78
|
when Array
|
78
79
|
args.map { |a| stringify_args(arg_owner, a) }
|
80
|
+
when GraphQL::Schema::InputObject
|
81
|
+
stringify_args(arg_owner, args.to_h)
|
79
82
|
else
|
80
83
|
args
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
84
87
|
def get_arg_definition(arg_owner, arg_name)
|
85
|
-
arg_owner.arguments.find { |
|
88
|
+
arg_owner.arguments[arg_name] || arg_owner.arguments.each_value.find { |v| v.keyword.to_s == arg_name }
|
86
89
|
end
|
87
90
|
end
|
88
91
|
end
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def instrument(type, field)
|
14
|
-
if type == @schema.subscription
|
14
|
+
if type == @schema.subscription.graphql_definition
|
15
15
|
# This is a root field of `subscription`
|
16
16
|
subscribing_resolve_proc = SubscriptionRegistrationResolve.new(field.resolve_proc)
|
17
17
|
field.redefine(resolve: subscribing_resolve_proc)
|
@@ -44,7 +44,10 @@ module GraphQL
|
|
44
44
|
|
45
45
|
# Wrap the proc with subscription registration logic
|
46
46
|
def call(obj, args, ctx)
|
47
|
-
|
47
|
+
result = nil
|
48
|
+
if @inner_proc && !@inner_proc.is_a?(GraphQL::Field::Resolve::BuiltInResolve)
|
49
|
+
result = @inner_proc.call(obj, args, ctx)
|
50
|
+
end
|
48
51
|
|
49
52
|
events = ctx.namespace(:subscriptions)[:events]
|
50
53
|
|
@@ -56,10 +59,12 @@ module GraphQL
|
|
56
59
|
arguments: args,
|
57
60
|
context: ctx,
|
58
61
|
)
|
59
|
-
|
62
|
+
result
|
60
63
|
elsif ctx.irep_node.subscription_topic == ctx.query.subscription_topic
|
61
|
-
|
62
|
-
|
64
|
+
if !result.nil?
|
65
|
+
result
|
66
|
+
elsif obj.is_a?(GraphQL::Schema::Object)
|
67
|
+
# The root object is _already_ the subscription update:
|
63
68
|
obj.object
|
64
69
|
else
|
65
70
|
obj
|
@@ -18,12 +18,17 @@ module GraphQL
|
|
18
18
|
|
19
19
|
# @see {Subscriptions#initialize} for options, concrete implementations may add options.
|
20
20
|
def self.use(defn, options = {})
|
21
|
-
schema = defn.target
|
22
|
-
|
23
|
-
schema.subscriptions
|
21
|
+
schema = defn.is_a?(Class) ? defn : defn.target
|
22
|
+
|
23
|
+
if schema.subscriptions
|
24
|
+
raise ArgumentError, "Can't reinstall subscriptions. #{schema} is using #{schema.subscriptions}, can't also add #{self}"
|
25
|
+
end
|
26
|
+
|
24
27
|
instrumentation = Subscriptions::Instrumentation.new(schema: schema)
|
25
|
-
defn.instrument(:field, instrumentation)
|
26
28
|
defn.instrument(:query, instrumentation)
|
29
|
+
defn.instrument(:field, instrumentation)
|
30
|
+
options[:schema] = schema
|
31
|
+
schema.subscriptions = self.new(**options)
|
27
32
|
nil
|
28
33
|
end
|
29
34
|
|
@@ -90,7 +95,7 @@ module GraphQL
|
|
90
95
|
operation_name = query_data.fetch(:operation_name)
|
91
96
|
# Re-evaluate the saved query
|
92
97
|
result = @schema.execute(
|
93
|
-
{
|
98
|
+
**{
|
94
99
|
query: query_string,
|
95
100
|
context: context,
|
96
101
|
subscription_topic: event.topic,
|
@@ -188,7 +193,11 @@ module GraphQL
|
|
188
193
|
# @return [Any] normalized arguments value
|
189
194
|
def normalize_arguments(event_name, arg_owner, args)
|
190
195
|
case arg_owner
|
191
|
-
when GraphQL::Field, GraphQL::InputObjectType
|
196
|
+
when GraphQL::Field, GraphQL::InputObjectType, GraphQL::Schema::Field, Class
|
197
|
+
if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
|
198
|
+
# it's a type, but not an input object
|
199
|
+
return args
|
200
|
+
end
|
192
201
|
normalized_args = {}
|
193
202
|
missing_arg_names = []
|
194
203
|
args.each do |k, v|
|
@@ -202,16 +211,32 @@ module GraphQL
|
|
202
211
|
end
|
203
212
|
|
204
213
|
if arg_defn
|
205
|
-
|
214
|
+
if arg_defn.loads
|
215
|
+
normalized_arg_name = arg_defn.keyword.to_s
|
216
|
+
end
|
217
|
+
normalized = normalize_arguments(event_name, arg_defn.type, v)
|
218
|
+
normalized_args[normalized_arg_name] = normalized
|
206
219
|
else
|
207
220
|
# Couldn't find a matching argument definition
|
208
221
|
missing_arg_names << arg_name
|
209
222
|
end
|
210
223
|
end
|
211
224
|
|
225
|
+
# Backfill default values so that trigger arguments
|
226
|
+
# match query arguments.
|
227
|
+
arg_owner.arguments.each do |name, arg_defn|
|
228
|
+
if arg_defn.default_value? && !normalized_args.key?(arg_defn.name)
|
229
|
+
normalized_args[arg_defn.name] = arg_defn.default_value
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
212
233
|
if missing_arg_names.any?
|
213
234
|
arg_owner_name = if arg_owner.is_a?(GraphQL::Field)
|
214
235
|
"Subscription.#{arg_owner.name}"
|
236
|
+
elsif arg_owner.is_a?(GraphQL::Schema::Field)
|
237
|
+
arg_owner.path
|
238
|
+
elsif arg_owner.is_a?(Class)
|
239
|
+
arg_owner.graphql_name
|
215
240
|
else
|
216
241
|
arg_owner.to_s
|
217
242
|
end
|
@@ -219,9 +244,9 @@ module GraphQL
|
|
219
244
|
end
|
220
245
|
|
221
246
|
normalized_args
|
222
|
-
when GraphQL::ListType
|
247
|
+
when GraphQL::ListType, GraphQL::Schema::List
|
223
248
|
args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a) }
|
224
|
-
when GraphQL::NonNullType
|
249
|
+
when GraphQL::NonNullType, GraphQL::Schema::NonNull
|
225
250
|
normalize_arguments(event_name, arg_owner.of_type, args)
|
226
251
|
else
|
227
252
|
args
|
@@ -8,19 +8,23 @@ module GraphQL
|
|
8
8
|
module ActiveSupportNotificationsTracing
|
9
9
|
# A cache of frequently-used keys to avoid needless string allocations
|
10
10
|
KEYS = {
|
11
|
-
"lex" => "graphql
|
12
|
-
"parse" => "graphql
|
13
|
-
"validate" => "graphql
|
14
|
-
"analyze_multiplex" => "graphql
|
15
|
-
"analyze_query" => "graphql
|
16
|
-
"execute_query" => "graphql
|
17
|
-
"execute_query_lazy" => "graphql
|
18
|
-
"execute_field" => "graphql
|
19
|
-
"execute_field_lazy" => "graphql
|
11
|
+
"lex" => "lex.graphql",
|
12
|
+
"parse" => "parse.graphql",
|
13
|
+
"validate" => "validate.graphql",
|
14
|
+
"analyze_multiplex" => "analyze_multiplex.graphql",
|
15
|
+
"analyze_query" => "analyze_query.graphql",
|
16
|
+
"execute_query" => "execute_query.graphql",
|
17
|
+
"execute_query_lazy" => "execute_query_lazy.graphql",
|
18
|
+
"execute_field" => "execute_field.graphql",
|
19
|
+
"execute_field_lazy" => "execute_field_lazy.graphql",
|
20
|
+
"authorized" => "authorized.graphql",
|
21
|
+
"authorized_lazy" => "authorized_lazy.graphql",
|
22
|
+
"resolve_type" => "resolve_type.graphql",
|
23
|
+
"resolve_type_lazy" => "resolve_type.graphql",
|
20
24
|
}
|
21
25
|
|
22
26
|
def self.trace(key, metadata)
|
23
|
-
prefixed_key = KEYS[key] || "
|
27
|
+
prefixed_key = KEYS[key] || "#{key}.graphql"
|
24
28
|
ActiveSupport::Notifications.instrument(prefixed_key, metadata) do
|
25
29
|
yield
|
26
30
|
end
|
@@ -23,6 +23,14 @@ module GraphQL
|
|
23
23
|
def platform_field_key(type, field)
|
24
24
|
"#{type.graphql_name}.#{field.graphql_name}.graphql"
|
25
25
|
end
|
26
|
+
|
27
|
+
def platform_authorized_key(type)
|
28
|
+
"#{type.graphql_name}.authorized.graphql"
|
29
|
+
end
|
30
|
+
|
31
|
+
def platform_resolve_type_key(type)
|
32
|
+
"#{type.graphql_name}.resolve_type.graphql"
|
33
|
+
end
|
26
34
|
end
|
27
35
|
end
|
28
36
|
end
|
@@ -63,6 +63,14 @@ module GraphQL
|
|
63
63
|
def platform_field_key(type, field)
|
64
64
|
"#{type.graphql_name}.#{field.graphql_name}"
|
65
65
|
end
|
66
|
+
|
67
|
+
def platform_authorized_key(type)
|
68
|
+
"#{type.graphql_name}.authorized"
|
69
|
+
end
|
70
|
+
|
71
|
+
def platform_resolve_type_key(type)
|
72
|
+
"#{type.graphql_name}.resolve_type"
|
73
|
+
end
|
66
74
|
end
|
67
75
|
end
|
68
76
|
end
|
@@ -49,6 +49,14 @@ module GraphQL
|
|
49
49
|
def platform_field_key(type, field)
|
50
50
|
"GraphQL/#{type.graphql_name}/#{field.graphql_name}"
|
51
51
|
end
|
52
|
+
|
53
|
+
def platform_authorized_key(type)
|
54
|
+
"GraphQL/Authorize/#{type.graphql_name}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def platform_resolve_type_key(type)
|
58
|
+
"GraphQL/ResolveType/#{type.graphql_name}"
|
59
|
+
end
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|