graphql 1.10.0.pre1 → 1.10.0.pre2
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 +1 -0
- data/lib/generators/graphql/install_generator.rb +1 -0
- data/lib/generators/graphql/mutation_generator.rb +1 -1
- data/lib/generators/graphql/templates/base_field.erb +0 -4
- data/lib/generators/graphql/templates/base_mutation.erb +8 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +5 -0
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/schema.erb +1 -1
- data/lib/graphql.rb +4 -1
- data/lib/graphql/analysis/ast.rb +14 -13
- data/lib/graphql/analysis/ast/analyzer.rb +23 -4
- data/lib/graphql/analysis/ast/field_usage.rb +1 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
- data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
- data/lib/graphql/analysis/ast/query_complexity.rb +2 -2
- data/lib/graphql/analysis/ast/visitor.rb +3 -3
- data/lib/graphql/base_type.rb +1 -1
- data/lib/graphql/directive.rb +0 -1
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/execution/errors.rb +4 -8
- data/lib/graphql/execution/interpreter.rb +5 -11
- data/lib/graphql/execution/interpreter/runtime.rb +56 -48
- 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 +10 -0
- data/lib/graphql/function.rb +1 -1
- data/lib/graphql/input_object_type.rb +3 -2
- data/lib/graphql/interface_type.rb +1 -1
- 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 +6 -6
- data/lib/graphql/introspection/schema_type.rb +1 -6
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language.rb +1 -1
- data/lib/graphql/language/block_string.rb +2 -2
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +42 -42
- data/lib/graphql/language/lexer.rb +49 -48
- data/lib/graphql/language/lexer.rl +49 -48
- data/lib/graphql/language/nodes.rb +11 -8
- data/lib/graphql/language/parser.rb +4 -1
- data/lib/graphql/language/parser.y +4 -1
- data/lib/graphql/language/token.rb +1 -1
- data/lib/graphql/pagination/array_connection.rb +0 -1
- data/lib/graphql/pagination/connection.rb +31 -10
- data/lib/graphql/pagination/connections.rb +7 -2
- data/lib/graphql/pagination/relation_connection.rb +1 -7
- data/lib/graphql/query.rb +9 -4
- data/lib/graphql/query/arguments.rb +8 -1
- data/lib/graphql/query/literal_input.rb +2 -1
- data/lib/graphql/query/variables.rb +5 -1
- data/lib/graphql/relay/base_connection.rb +3 -3
- data/lib/graphql/relay/relation_connection.rb +9 -5
- data/lib/graphql/schema.rb +699 -153
- data/lib/graphql/schema/argument.rb +20 -4
- data/lib/graphql/schema/build_from_definition.rb +64 -31
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/directive.rb +16 -1
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/enum.rb +39 -3
- data/lib/graphql/schema/field.rb +39 -9
- data/lib/graphql/schema/field/connection_extension.rb +4 -4
- 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 +109 -1
- data/lib/graphql/schema/interface.rb +8 -7
- data/lib/graphql/schema/introspection_system.rb +104 -36
- data/lib/graphql/schema/late_bound_type.rb +1 -0
- data/lib/graphql/schema/list.rb +26 -0
- data/lib/graphql/schema/loader.rb +10 -4
- data/lib/graphql/schema/member.rb +3 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +23 -13
- data/lib/graphql/schema/member/build_type.rb +1 -1
- data/lib/graphql/schema/member/has_arguments.rb +2 -2
- data/lib/graphql/schema/member/has_fields.rb +15 -6
- data/lib/graphql/schema/member/instrumentation.rb +6 -1
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/non_null.rb +25 -0
- data/lib/graphql/schema/object.rb +14 -1
- data/lib/graphql/schema/printer.rb +4 -3
- data/lib/graphql/schema/relay_classic_mutation.rb +5 -1
- data/lib/graphql/schema/resolver.rb +20 -2
- data/lib/graphql/schema/scalar.rb +18 -3
- data/lib/graphql/schema/subscription.rb +1 -1
- data/lib/graphql/schema/timeout_middleware.rb +3 -2
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +22 -24
- data/lib/graphql/schema/validation.rb +17 -1
- data/lib/graphql/schema/warden.rb +46 -17
- data/lib/graphql/schema/wrapper.rb +1 -1
- data/lib/graphql/static_validation/base_visitor.rb +10 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +21 -12
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/subscriptions.rb +38 -13
- data/lib/graphql/subscriptions/event.rb +24 -7
- data/lib/graphql/subscriptions/instrumentation.rb +1 -1
- data/lib/graphql/subscriptions/subscription_root.rb +0 -1
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +10 -10
- data/lib/graphql/tracing/platform_tracing.rb +1 -2
- data/lib/graphql/tracing/skylight_tracing.rb +1 -0
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/upgrader/member.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b0dea1cf870243e0c1ca99c9aa276b3ab6dca48c94048d99033c7e868d6edb7
|
4
|
+
data.tar.gz: a9067feb798b969d50e6cd3b436432adba4216ad8b66d58cd8cde2d76f9d5589
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2effe2d2074b17026c7c6e3ddc71db82b1bd17ce8624dbdd9a88345ff39b2177ae48981deabdda227fb4bcf965469a5e874faeb76c0830d598fdb5501673c98
|
7
|
+
data.tar.gz: 810111555e1713e4d0d6afabba7102a03f458349d135d92f573236feedd116d81481ba7119c364d9533d39f1d98aa940ce32dc7d452008f6c00827796e5794ef
|
@@ -25,6 +25,7 @@ module Graphql
|
|
25
25
|
|
26
26
|
def create_mutation_root_type
|
27
27
|
create_dir("#{options[:directory]}/mutations")
|
28
|
+
template("base_mutation.erb", "#{options[:directory]}/mutations/base_mutation.rb", { skip: true })
|
28
29
|
template("mutation_type.erb", "#{options[:directory]}/types/mutation_type.rb", { skip: true })
|
29
30
|
insert_root_type('mutation', 'MutationType')
|
30
31
|
end
|
@@ -1,4 +1,9 @@
|
|
1
1
|
class GraphqlController < ApplicationController
|
2
|
+
# If accessing from outside this domain, nullify the session
|
3
|
+
# This allows for outside API access while preventing CSRF attacks,
|
4
|
+
# but you'll have to authenticate your user separately
|
5
|
+
# protect_from_forgery with: :null_session
|
6
|
+
|
2
7
|
def execute
|
3
8
|
variables = ensure_hash(params[:variables])
|
4
9
|
query = params[:query]
|
@@ -24,7 +24,7 @@ class <%= schema_name %> < GraphQL::Schema
|
|
24
24
|
def self.resolve_type(type, obj, ctx)
|
25
25
|
# TODO: Implement this function
|
26
26
|
# to return the correct type for `obj`
|
27
|
-
raise(
|
27
|
+
raise(GraphQL::RequiredImplementationMissingError)
|
28
28
|
end
|
29
29
|
<% end %><% if options[:batch] %>
|
30
30
|
# GraphQL::Batch setup:
|
data/lib/graphql.rb
CHANGED
@@ -10,6 +10,9 @@ module GraphQL
|
|
10
10
|
class Error < StandardError
|
11
11
|
end
|
12
12
|
|
13
|
+
class RequiredImplementationMissingError < Error
|
14
|
+
end
|
15
|
+
|
13
16
|
# Turn a query string or schema definition into an AST
|
14
17
|
# @param graphql_string [String] a GraphQL query string or schema definition
|
15
18
|
# @return [GraphQL::Language::Nodes::Document]
|
@@ -81,6 +84,7 @@ require "graphql/tracing"
|
|
81
84
|
require "graphql/execution"
|
82
85
|
require "graphql/dig"
|
83
86
|
require "graphql/schema"
|
87
|
+
require "graphql/query"
|
84
88
|
require "graphql/directive"
|
85
89
|
require "graphql/execution"
|
86
90
|
require "graphql/types"
|
@@ -104,7 +108,6 @@ require "graphql/invalid_name_error"
|
|
104
108
|
require "graphql/unresolved_type_error"
|
105
109
|
require "graphql/integer_encoding_error"
|
106
110
|
require "graphql/string_encoding_error"
|
107
|
-
require "graphql/query"
|
108
111
|
require "graphql/internal_representation"
|
109
112
|
require "graphql/static_validation"
|
110
113
|
require "graphql/version"
|
data/lib/graphql/analysis/ast.rb
CHANGED
@@ -12,9 +12,8 @@ module GraphQL
|
|
12
12
|
module AST
|
13
13
|
module_function
|
14
14
|
|
15
|
-
def use(
|
16
|
-
|
17
|
-
schema.analysis_engine = GraphQL::Analysis::AST
|
15
|
+
def use(schema_class)
|
16
|
+
schema_class.analysis_engine = GraphQL::Analysis::AST
|
18
17
|
end
|
19
18
|
|
20
19
|
# Analyze a multiplex, and all queries within.
|
@@ -23,7 +22,7 @@ module GraphQL
|
|
23
22
|
#
|
24
23
|
# @param multiplex [GraphQL::Execution::Multiplex]
|
25
24
|
# @param analyzers [Array<GraphQL::Analysis::AST::Analyzer>]
|
26
|
-
# @return [
|
25
|
+
# @return [Array<Any>] Results from multiplex analyzers
|
27
26
|
def analyze_multiplex(multiplex, analyzers)
|
28
27
|
multiplex_analyzers = analyzers.map { |analyzer| analyzer.new(multiplex) }
|
29
28
|
|
@@ -46,8 +45,8 @@ module GraphQL
|
|
46
45
|
multiplex.queries.each_with_index do |query, idx|
|
47
46
|
query.analysis_errors = multiplex_errors + analysis_errors(query_results[idx])
|
48
47
|
end
|
48
|
+
multiplex_results
|
49
49
|
end
|
50
|
-
nil
|
51
50
|
end
|
52
51
|
|
53
52
|
# @param query [GraphQL::Query]
|
@@ -60,16 +59,18 @@ module GraphQL
|
|
60
59
|
.select { |analyzer| analyzer.analyze? }
|
61
60
|
|
62
61
|
analyzers_to_run = query_analyzers + multiplex_analyzers
|
63
|
-
|
62
|
+
if analyzers_to_run.any?
|
63
|
+
visitor = GraphQL::Analysis::AST::Visitor.new(
|
64
|
+
query: query,
|
65
|
+
analyzers: analyzers_to_run
|
66
|
+
)
|
64
67
|
|
65
|
-
|
66
|
-
query: query,
|
67
|
-
analyzers: analyzers_to_run
|
68
|
-
)
|
68
|
+
visitor.visit
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
query_analyzers.map(&:result)
|
71
|
+
else
|
72
|
+
[]
|
73
|
+
end
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
@@ -5,10 +5,21 @@ module GraphQL
|
|
5
5
|
# Query analyzer for query ASTs. Query analyzers respond to visitor style methods
|
6
6
|
# but are prefixed by `enter` and `leave`.
|
7
7
|
#
|
8
|
-
#
|
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
|
9
12
|
class Analyzer
|
10
|
-
def initialize(
|
11
|
-
@
|
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
|
12
23
|
end
|
13
24
|
|
14
25
|
# Analyzer hook to decide at analysis time whether a query should
|
@@ -22,7 +33,7 @@ module GraphQL
|
|
22
33
|
# in a query error.
|
23
34
|
# @return [Any] The analyzer result
|
24
35
|
def result
|
25
|
-
raise
|
36
|
+
raise GraphQL::RequiredImplementationMissingError
|
26
37
|
end
|
27
38
|
|
28
39
|
class << self
|
@@ -58,7 +69,15 @@ module GraphQL
|
|
58
69
|
|
59
70
|
protected
|
60
71
|
|
72
|
+
# @return [GraphQL::Query, GraphQL::Execution::Multiplex] Whatever this analyzer is analyzing
|
73
|
+
attr_reader :subject
|
74
|
+
|
75
|
+
# @return [GraphQL::Query, nil] `nil` if this analyzer is visiting a multiplex
|
76
|
+
# (When this is `nil`, use `visitor.query` inside visit methods to get the current query)
|
61
77
|
attr_reader :query
|
78
|
+
|
79
|
+
# @return [GraphQL::Execution::Multiplex, nil] `nil` if this analyzer is visiting a query
|
80
|
+
attr_reader :multiplex
|
62
81
|
end
|
63
82
|
end
|
64
83
|
end
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
11
11
|
|
12
12
|
def on_leave_field(node, parent, visitor)
|
13
13
|
field_defn = visitor.field_definition
|
14
|
-
field = "#{visitor.parent_type_definition.
|
14
|
+
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
15
15
|
@used_fields << field
|
16
16
|
@used_deprecated_fields << field if field_defn.deprecation_reason
|
17
17
|
end
|
@@ -7,12 +7,12 @@ module GraphQL
|
|
7
7
|
# see {Schema#max_complexity} and {Query#max_complexity}
|
8
8
|
class MaxQueryComplexity < QueryComplexity
|
9
9
|
def result
|
10
|
-
return if
|
10
|
+
return if subject.max_complexity.nil?
|
11
11
|
|
12
12
|
total_complexity = max_possible_complexity
|
13
13
|
|
14
|
-
if total_complexity >
|
15
|
-
GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{
|
14
|
+
if total_complexity > subject.max_complexity
|
15
|
+
GraphQL::AnalysisError.new("Query has complexity of #{total_complexity}, which exceeds max complexity of #{subject.max_complexity}")
|
16
16
|
else
|
17
17
|
nil
|
18
18
|
end
|
@@ -4,10 +4,14 @@ module GraphQL
|
|
4
4
|
module AST
|
5
5
|
class MaxQueryDepth < QueryDepth
|
6
6
|
def result
|
7
|
-
|
7
|
+
configured_max_depth = if query
|
8
|
+
query.max_depth
|
9
|
+
else
|
10
|
+
multiplex.schema.max_depth
|
11
|
+
end
|
8
12
|
|
9
|
-
if @max_depth >
|
10
|
-
GraphQL::AnalysisError.new("Query has depth of #{@max_depth}, which exceeds max depth of #{
|
13
|
+
if configured_max_depth && @max_depth > configured_max_depth
|
14
|
+
GraphQL::AnalysisError.new("Query has depth of #{@max_depth}, which exceeds max depth of #{configured_max_depth}")
|
11
15
|
else
|
12
16
|
nil
|
13
17
|
end
|
@@ -42,7 +42,7 @@ module GraphQL
|
|
42
42
|
if @complexities_on_type.last.is_a?(AbstractTypeComplexity)
|
43
43
|
key = selection_key(visitor.response_path, visitor.query)
|
44
44
|
parent_type = visitor.parent_type_definition
|
45
|
-
query.possible_types(parent_type).each do |type|
|
45
|
+
visitor.query.possible_types(parent_type).each do |type|
|
46
46
|
@complexities_on_type.last.merge(type, key, own_complexity)
|
47
47
|
end
|
48
48
|
else
|
@@ -74,7 +74,7 @@ module GraphQL
|
|
74
74
|
|
75
75
|
case defined_complexity
|
76
76
|
when Proc
|
77
|
-
defined_complexity.call(query.context, arguments, child_complexity)
|
77
|
+
defined_complexity.call(visitor.query.context, arguments, child_complexity)
|
78
78
|
when Numeric
|
79
79
|
defined_complexity + (child_complexity || 0)
|
80
80
|
else
|
@@ -134,7 +134,7 @@ module GraphQL
|
|
134
134
|
argument_defn = if (arg = @argument_definitions.last)
|
135
135
|
arg_type = arg.type.unwrap
|
136
136
|
if arg_type.kind.input_object?
|
137
|
-
arg_type.
|
137
|
+
arg_type.arguments[node.name]
|
138
138
|
else
|
139
139
|
nil
|
140
140
|
end
|
@@ -214,7 +214,7 @@ module GraphQL
|
|
214
214
|
fragment_def = query.fragments[fragment_spread.name]
|
215
215
|
|
216
216
|
object_type = if fragment_def.type
|
217
|
-
query.
|
217
|
+
@query.warden.get_type(fragment_def.type.name)
|
218
218
|
else
|
219
219
|
object_types.last
|
220
220
|
end
|
@@ -245,7 +245,7 @@ module GraphQL
|
|
245
245
|
|
246
246
|
def on_fragment_with_type(node)
|
247
247
|
object_type = if node.type
|
248
|
-
@
|
248
|
+
@query.warden.get_type(node.type.name)
|
249
249
|
else
|
250
250
|
@object_types.last
|
251
251
|
end
|
data/lib/graphql/base_type.rb
CHANGED
data/lib/graphql/directive.rb
CHANGED
@@ -45,7 +45,6 @@ module GraphQL
|
|
45
45
|
INPUT_FIELD_DEFINITION = :INPUT_FIELD_DEFINITION,
|
46
46
|
]
|
47
47
|
|
48
|
-
DEFAULT_DEPRECATION_REASON = 'No longer supported'
|
49
48
|
LOCATION_DESCRIPTIONS = {
|
50
49
|
QUERY: 'Location adjacent to a query operation.',
|
51
50
|
MUTATION: 'Location adjacent to a mutation operation.',
|
@@ -1,13 +1,2 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
GraphQL::Directive::DeprecatedDirective = GraphQL::Directive.
|
3
|
-
name "deprecated"
|
4
|
-
description "Marks an element of a GraphQL schema as no longer supported."
|
5
|
-
locations([GraphQL::Directive::FIELD_DEFINITION, GraphQL::Directive::ENUM_VALUE])
|
6
|
-
|
7
|
-
reason_description = "Explains why this element was deprecated, usually also including a "\
|
8
|
-
"suggestion for how to access supported similar data. Formatted "\
|
9
|
-
"in [Markdown](https://daringfireball.net/projects/markdown/)."
|
10
|
-
|
11
|
-
argument :reason, GraphQL::STRING_TYPE, reason_description, default_value: GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
12
|
-
default_directive true
|
13
|
-
end
|
2
|
+
GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition
|
@@ -18,12 +18,7 @@ module GraphQL
|
|
18
18
|
#
|
19
19
|
class Errors
|
20
20
|
def self.use(schema)
|
21
|
-
|
22
|
-
schema.tracer(self.new(schema_class))
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize(schema)
|
26
|
-
@schema = schema
|
21
|
+
schema.tracer(self.new)
|
27
22
|
end
|
28
23
|
|
29
24
|
def trace(event, data)
|
@@ -40,12 +35,13 @@ module GraphQL
|
|
40
35
|
def with_error_handling(trace_data)
|
41
36
|
yield
|
42
37
|
rescue StandardError => err
|
43
|
-
|
38
|
+
ctx = trace_data[:query].context
|
39
|
+
schema = ctx.schema
|
40
|
+
rescues = schema.rescues
|
44
41
|
_err_class, handler = rescues.find { |err_class, handler| err.is_a?(err_class) }
|
45
42
|
if handler
|
46
43
|
obj = trace_data[:object]
|
47
44
|
args = trace_data[:arguments]
|
48
|
-
ctx = trace_data[:query].context
|
49
45
|
field = trace_data[:field]
|
50
46
|
if obj.is_a?(GraphQL::Schema::Object)
|
51
47
|
obj = obj.object
|
@@ -17,17 +17,11 @@ module GraphQL
|
|
17
17
|
runtime.final_value
|
18
18
|
end
|
19
19
|
|
20
|
-
def self.use(
|
21
|
-
|
22
|
-
|
23
|
-
schema_class
|
24
|
-
|
25
|
-
# we have to update both :(
|
26
|
-
[schema_class, schema_defn].each do |schema_config|
|
27
|
-
schema_config.query_execution_strategy(GraphQL::Execution::Interpreter)
|
28
|
-
schema_config.mutation_execution_strategy(GraphQL::Execution::Interpreter)
|
29
|
-
schema_config.subscription_execution_strategy(GraphQL::Execution::Interpreter)
|
30
|
-
end
|
20
|
+
def self.use(schema_class)
|
21
|
+
schema_class.interpreter = true
|
22
|
+
schema_class.query_execution_strategy(GraphQL::Execution::Interpreter)
|
23
|
+
schema_class.mutation_execution_strategy(GraphQL::Execution::Interpreter)
|
24
|
+
schema_class.subscription_execution_strategy(GraphQL::Execution::Interpreter)
|
31
25
|
end
|
32
26
|
|
33
27
|
def self.begin_multiplex(multiplex)
|
@@ -45,8 +45,7 @@ module GraphQL
|
|
45
45
|
def run_eager
|
46
46
|
root_operation = query.selected_operation
|
47
47
|
root_op_type = root_operation.operation_type || "query"
|
48
|
-
|
49
|
-
root_type = legacy_root_type.metadata[:type_class] || raise("Invariant: type must be class-based: #{legacy_root_type}")
|
48
|
+
root_type = schema.root_type_for_operation(root_op_type)
|
50
49
|
object_proxy = root_type.authorized_new(query.root_value, context)
|
51
50
|
object_proxy = schema.sync_lazy(object_proxy)
|
52
51
|
if object_proxy.nil?
|
@@ -86,11 +85,10 @@ module GraphQL
|
|
86
85
|
end
|
87
86
|
when GraphQL::Language::Nodes::InlineFragment
|
88
87
|
if node.type
|
89
|
-
type_defn = schema.
|
90
|
-
type_defn = type_defn.metadata[:type_class]
|
88
|
+
type_defn = schema.get_type(node.type.name)
|
91
89
|
# Faster than .map{}.include?()
|
92
90
|
query.warden.possible_types(type_defn).each do |t|
|
93
|
-
if t
|
91
|
+
if t == owner_type
|
94
92
|
gather_selections(owner_object, owner_type, node.selections, selections_by_name)
|
95
93
|
break
|
96
94
|
end
|
@@ -101,10 +99,9 @@ module GraphQL
|
|
101
99
|
end
|
102
100
|
when GraphQL::Language::Nodes::FragmentSpread
|
103
101
|
fragment_def = query.fragments[node.name]
|
104
|
-
type_defn = schema.
|
105
|
-
type_defn
|
106
|
-
|
107
|
-
if t.metadata[:type_class] == owner_type
|
102
|
+
type_defn = schema.get_type(fragment_def.type.name)
|
103
|
+
query.warden.possible_types(type_defn).each do |t|
|
104
|
+
if t == owner_type
|
108
105
|
gather_selections(owner_object, owner_type, fragment_def.selections, selections_by_name)
|
109
106
|
break
|
110
107
|
end
|
@@ -133,18 +130,18 @@ module GraphQL
|
|
133
130
|
field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name)
|
134
131
|
is_introspection = false
|
135
132
|
if field_defn.nil?
|
136
|
-
field_defn = if owner_type == schema.query
|
133
|
+
field_defn = if owner_type == schema.query && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
|
137
134
|
is_introspection = true
|
138
|
-
entry_point_field
|
135
|
+
entry_point_field
|
139
136
|
elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
|
140
137
|
is_introspection = true
|
141
|
-
dynamic_field
|
138
|
+
dynamic_field
|
142
139
|
else
|
143
140
|
raise "Invariant: no field for #{owner_type}.#{field_name}"
|
144
141
|
end
|
145
142
|
end
|
146
143
|
|
147
|
-
return_type =
|
144
|
+
return_type = field_defn.type
|
148
145
|
|
149
146
|
next_path = path.dup
|
150
147
|
next_path << result_name
|
@@ -296,7 +293,6 @@ module GraphQL
|
|
296
293
|
write_in_response(path, nil)
|
297
294
|
nil
|
298
295
|
else
|
299
|
-
resolved_type = resolved_type.metadata[:type_class]
|
300
296
|
continue_field(path, value, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments)
|
301
297
|
end
|
302
298
|
end
|
@@ -338,8 +334,6 @@ module GraphQL
|
|
338
334
|
response_list
|
339
335
|
when "NON_NULL"
|
340
336
|
inner_type = type.of_type
|
341
|
-
# For fields like `__schema: __Schema!`
|
342
|
-
inner_type = resolve_if_late_bound_type(inner_type)
|
343
337
|
# Don't `set_type_at_path` because we want the static type,
|
344
338
|
# we're going to use that to determine whether a `nil` should be propagated or not.
|
345
339
|
continue_field(path, value, field, inner_type, ast_node, next_selections, true, owner_object, arguments)
|
@@ -359,7 +353,7 @@ module GraphQL
|
|
359
353
|
else
|
360
354
|
dir_defn = schema.directives.fetch(dir_node.name)
|
361
355
|
if !dir_defn.is_a?(Class)
|
362
|
-
dir_defn = dir_defn.
|
356
|
+
dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
|
363
357
|
end
|
364
358
|
dir_args = arguments(nil, dir_defn, dir_node)
|
365
359
|
dir_defn.resolve(object, dir_args, context) do
|
@@ -371,7 +365,7 @@ module GraphQL
|
|
371
365
|
# Check {Schema::Directive.include?} for each directive that's present
|
372
366
|
def directives_include?(node, graphql_object, parent_type)
|
373
367
|
node.directives.each do |dir_node|
|
374
|
-
dir_defn = schema.directives.fetch(dir_node.name).
|
368
|
+
dir_defn = schema.directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
|
375
369
|
args = arguments(graphql_object, dir_defn, dir_node)
|
376
370
|
if !dir_defn.include?(graphql_object, args, context)
|
377
371
|
return false
|
@@ -380,14 +374,6 @@ module GraphQL
|
|
380
374
|
true
|
381
375
|
end
|
382
376
|
|
383
|
-
def resolve_if_late_bound_type(type)
|
384
|
-
if type.is_a?(GraphQL::Schema::LateBoundType)
|
385
|
-
query.warden.get_type(type.name).metadata[:type_class]
|
386
|
-
else
|
387
|
-
type
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
377
|
# @param obj [Object] Some user-returned value that may want to be batched
|
392
378
|
# @param path [Array<String>]
|
393
379
|
# @param field [GraphQL::Schema::Field]
|
@@ -448,7 +434,7 @@ module GraphQL
|
|
448
434
|
arg_defn = arg_defns[arg_name]
|
449
435
|
# Need to distinguish between client-provided `nil`
|
450
436
|
# and nothing-at-all
|
451
|
-
is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_value)
|
437
|
+
is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_value, already_arguments: false)
|
452
438
|
if is_present
|
453
439
|
# This doesn't apply to directives, which are legacy
|
454
440
|
# Can remove this when Skip and Include use classes or something.
|
@@ -460,50 +446,72 @@ module GraphQL
|
|
460
446
|
end
|
461
447
|
arg_defns.each do |name, arg_defn|
|
462
448
|
if arg_defn.default_value? && !kwarg_arguments.key?(arg_defn.keyword)
|
463
|
-
_is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_defn.default_value)
|
449
|
+
_is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_defn.default_value, already_arguments: false)
|
464
450
|
kwarg_arguments[arg_defn.keyword] = value
|
465
451
|
end
|
466
452
|
end
|
467
453
|
kwarg_arguments
|
468
454
|
end
|
469
455
|
|
456
|
+
# TODO CAN THIS USE `.coerce_input` ???
|
457
|
+
|
470
458
|
# Get a Ruby-ready value from a client query.
|
471
459
|
# @param graphql_object [Object] The owner of the field whose argument this is
|
472
460
|
# @param arg_type [Class, GraphQL::Schema::NonNull, GraphQL::Schema::List]
|
473
461
|
# @param ast_value [GraphQL::Language::Nodes::VariableIdentifier, String, Integer, Float, Boolean]
|
462
|
+
# @param already_arguments [Boolean] if true, don't re-coerce these with `arguments(...)`
|
474
463
|
# @return [Array(is_present, value)]
|
475
|
-
def arg_to_value(graphql_object, arg_type, ast_value)
|
464
|
+
def arg_to_value(graphql_object, arg_type, ast_value, already_arguments:)
|
476
465
|
if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
|
477
466
|
# If it's not here, it will get added later
|
478
467
|
if query.variables.key?(ast_value.name)
|
479
|
-
|
468
|
+
variable_value = query.variables[ast_value.name]
|
469
|
+
arg_to_value(graphql_object, arg_type, variable_value, already_arguments: true)
|
480
470
|
else
|
481
471
|
return false, nil
|
482
472
|
end
|
483
473
|
elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
|
484
474
|
return true, nil
|
485
475
|
elsif arg_type.is_a?(GraphQL::Schema::NonNull)
|
486
|
-
arg_to_value(graphql_object, arg_type.of_type, ast_value)
|
476
|
+
arg_to_value(graphql_object, arg_type.of_type, ast_value, already_arguments: already_arguments)
|
487
477
|
elsif arg_type.is_a?(GraphQL::Schema::List)
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
list
|
494
|
-
|
495
|
-
|
478
|
+
if ast_value.nil?
|
479
|
+
return true, nil
|
480
|
+
else
|
481
|
+
# Treat a single value like a list
|
482
|
+
arg_value = Array(ast_value)
|
483
|
+
list = []
|
484
|
+
arg_value.map do |inner_v|
|
485
|
+
_present, value = arg_to_value(graphql_object, arg_type.of_type, inner_v, already_arguments: already_arguments)
|
486
|
+
list << value
|
487
|
+
end
|
488
|
+
return true, list
|
489
|
+
end
|
496
490
|
elsif arg_type.is_a?(Class) && arg_type < GraphQL::Schema::InputObject
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
491
|
+
if already_arguments
|
492
|
+
# This came from a variable, already prepared.
|
493
|
+
# But replace `nil` with `{}` like we would for `arg_type`
|
494
|
+
if ast_value.nil?
|
495
|
+
return false, nil
|
496
|
+
else
|
497
|
+
return true, arg_type.new(ruby_kwargs: ast_value, context: context, defaults_used: nil)
|
498
|
+
end
|
499
|
+
else
|
500
|
+
# For these, `prepare` is applied during `#initialize`.
|
501
|
+
# Pass `nil` so it will be skipped in `#arguments`.
|
502
|
+
# What a mess.
|
503
|
+
args = arguments(nil, arg_type, ast_value)
|
504
|
+
return true, arg_type.new(ruby_kwargs: args, context: context, defaults_used: nil)
|
505
|
+
end
|
504
506
|
else
|
505
|
-
flat_value =
|
506
|
-
|
507
|
+
flat_value = if already_arguments
|
508
|
+
# It was coerced by variable handling
|
509
|
+
ast_value
|
510
|
+
else
|
511
|
+
v = flatten_ast_value(ast_value)
|
512
|
+
arg_type.coerce_input(v, context)
|
513
|
+
end
|
514
|
+
return true, flat_value
|
507
515
|
end
|
508
516
|
end
|
509
517
|
|