graphql 1.5.15 → 1.6.0
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/graphql.rb +4 -19
- data/lib/graphql/analysis/analyze_query.rb +27 -2
- data/lib/graphql/analysis/query_complexity.rb +10 -11
- data/lib/graphql/argument.rb +7 -6
- data/lib/graphql/backwards_compatibility.rb +47 -0
- data/lib/graphql/compatibility/execution_specification.rb +14 -0
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +6 -1
- data/lib/graphql/compatibility/lazy_execution_specification.rb +19 -0
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +15 -6
- data/lib/graphql/directive.rb +1 -6
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution/execute.rb +174 -160
- data/lib/graphql/execution/field_result.rb +5 -1
- data/lib/graphql/execution/lazy.rb +2 -2
- data/lib/graphql/execution/lazy/resolve.rb +8 -11
- data/lib/graphql/execution/multiplex.rb +134 -0
- data/lib/graphql/execution/selection_result.rb +5 -0
- data/lib/graphql/field.rb +1 -8
- data/lib/graphql/filter.rb +53 -0
- data/lib/graphql/internal_representation/node.rb +11 -6
- data/lib/graphql/internal_representation/rewrite.rb +3 -3
- data/lib/graphql/query.rb +160 -78
- data/lib/graphql/query/arguments.rb +14 -25
- data/lib/graphql/query/arguments_cache.rb +6 -13
- data/lib/graphql/query/context.rb +28 -10
- data/lib/graphql/query/executor.rb +1 -0
- data/lib/graphql/query/literal_input.rb +10 -4
- data/lib/graphql/query/null_context.rb +1 -1
- data/lib/graphql/query/serial_execution/field_resolution.rb +5 -1
- data/lib/graphql/query/validation_pipeline.rb +12 -7
- data/lib/graphql/query/variables.rb +1 -1
- data/lib/graphql/rake_task.rb +140 -0
- data/lib/graphql/relay/array_connection.rb +29 -48
- data/lib/graphql/relay/base_connection.rb +9 -7
- data/lib/graphql/relay/mutation.rb +0 -11
- data/lib/graphql/relay/mutation/instrumentation.rb +2 -2
- data/lib/graphql/relay/mutation/resolve.rb +7 -10
- data/lib/graphql/relay/relation_connection.rb +98 -61
- data/lib/graphql/scalar_type.rb +1 -15
- data/lib/graphql/schema.rb +90 -25
- data/lib/graphql/schema/build_from_definition.rb +22 -23
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +70 -0
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
- data/lib/graphql/schema/middleware_chain.rb +1 -1
- data/lib/graphql/schema/printer.rb +2 -1
- data/lib/graphql/schema/timeout_middleware.rb +6 -6
- data/lib/graphql/schema/type_map.rb +1 -1
- data/lib/graphql/schema/warden.rb +5 -9
- data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/analyze_query_spec.rb +2 -2
- data/spec/graphql/analysis/max_query_complexity_spec.rb +28 -0
- data/spec/graphql/argument_spec.rb +3 -3
- data/spec/graphql/execution/lazy_spec.rb +8 -114
- data/spec/graphql/execution/multiplex_spec.rb +131 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +10 -0
- data/spec/graphql/query/arguments_spec.rb +14 -16
- data/spec/graphql/query/context_spec.rb +14 -1
- data/spec/graphql/query/literal_input_spec.rb +19 -13
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +12 -1
- data/spec/graphql/rake_task_spec.rb +57 -0
- data/spec/graphql/relay/array_connection_spec.rb +24 -3
- data/spec/graphql/relay/connection_instrumentation_spec.rb +23 -0
- data/spec/graphql/relay/mutation_spec.rb +2 -10
- data/spec/graphql/relay/page_info_spec.rb +2 -2
- data/spec/graphql/relay/relation_connection_spec.rb +167 -3
- data/spec/graphql/schema/build_from_definition_spec.rb +93 -19
- data/spec/graphql/schema/warden_spec.rb +80 -0
- data/spec/graphql/schema_spec.rb +26 -2
- data/spec/spec_helper.rb +4 -2
- data/spec/support/lazy_helpers.rb +152 -0
- data/spec/support/star_wars/schema.rb +23 -0
- metadata +28 -3
- data/lib/graphql/schema/mask.rb +0 -55
@@ -26,14 +26,16 @@ module GraphQL
|
|
26
26
|
# @return [subclass of BaseConnection] a connection Class for wrapping `nodes`
|
27
27
|
def connection_for_nodes(nodes)
|
28
28
|
# Check for class _names_ because classes can be redefined in Rails development
|
29
|
-
nodes.class.ancestors.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
ancestor_names = nodes.class.ancestors.map(&:name)
|
30
|
+
implementation_class_name = ancestor_names.find do |ancestor_class_name|
|
31
|
+
CONNECTION_IMPLEMENTATIONS.include? ancestor_class_name
|
32
|
+
end
|
33
|
+
|
34
|
+
if implementation_class_name.nil?
|
35
|
+
raise("No connection implementation to wrap #{nodes.class} (#{nodes})")
|
36
|
+
else
|
37
|
+
CONNECTION_IMPLEMENTATIONS[implementation_class_name]
|
34
38
|
end
|
35
|
-
# Should have found a connection during the loop:
|
36
|
-
raise("No connection implementation to wrap #{nodes.class} (#{nodes})")
|
37
39
|
end
|
38
40
|
|
39
41
|
# Add `connection_class` as the connection wrapper for `nodes_class`
|
@@ -184,17 +184,6 @@ module GraphQL
|
|
184
184
|
def result_class
|
185
185
|
@result_class ||= Result.define_subclass(self)
|
186
186
|
end
|
187
|
-
|
188
|
-
private
|
189
|
-
|
190
|
-
def get_arity(callable)
|
191
|
-
case callable
|
192
|
-
when Proc
|
193
|
-
callable.arity
|
194
|
-
else
|
195
|
-
callable.method(:call).arity
|
196
|
-
end
|
197
|
-
end
|
198
187
|
end
|
199
188
|
end
|
200
189
|
end
|
@@ -11,8 +11,8 @@ module GraphQL
|
|
11
11
|
# giving users access to the original resolve function in earlier instrumentation.
|
12
12
|
def self.instrument(type, field)
|
13
13
|
if field.mutation
|
14
|
-
new_resolve = Mutation::Resolve.new(field.mutation, field.resolve_proc
|
15
|
-
new_lazy_resolve = Mutation::Resolve.new(field.mutation, field.lazy_resolve_proc
|
14
|
+
new_resolve = Mutation::Resolve.new(field.mutation, field.resolve_proc)
|
15
|
+
new_lazy_resolve = Mutation::Resolve.new(field.mutation, field.lazy_resolve_proc)
|
16
16
|
field.redefine(resolve: new_resolve, lazy_resolve: new_lazy_resolve)
|
17
17
|
else
|
18
18
|
field
|
@@ -7,38 +7,35 @@ module GraphQL
|
|
7
7
|
# Also, pass the `clientMutationId` to that result object.
|
8
8
|
# @api private
|
9
9
|
class Resolve
|
10
|
-
def initialize(mutation, resolve
|
10
|
+
def initialize(mutation, resolve)
|
11
11
|
@mutation = mutation
|
12
12
|
@resolve = resolve
|
13
13
|
@wrap_result = mutation.has_generated_return_type?
|
14
|
-
@eager = eager
|
15
14
|
end
|
16
15
|
|
17
16
|
def call(obj, args, ctx)
|
18
|
-
|
19
|
-
|
20
|
-
mutation_result = @resolve.call(obj, args[:input], ctx)
|
17
|
+
mutation_result = begin
|
18
|
+
@resolve.call(obj, args[:input], ctx)
|
21
19
|
rescue GraphQL::ExecutionError => err
|
22
|
-
|
23
|
-
error_raised = true
|
20
|
+
err
|
24
21
|
end
|
25
22
|
|
26
23
|
if ctx.schema.lazy?(mutation_result)
|
27
24
|
mutation_result
|
28
25
|
else
|
29
|
-
build_result(mutation_result, args, ctx
|
26
|
+
build_result(mutation_result, args, ctx)
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
30
|
private
|
34
31
|
|
35
|
-
def build_result(mutation_result, args, ctx
|
32
|
+
def build_result(mutation_result, args, ctx)
|
36
33
|
if mutation_result.is_a?(GraphQL::ExecutionError)
|
37
34
|
ctx.add_error(mutation_result)
|
38
35
|
mutation_result = nil
|
39
36
|
end
|
40
37
|
|
41
|
-
if
|
38
|
+
if mutation_result.nil?
|
42
39
|
nil
|
43
40
|
elsif @wrap_result
|
44
41
|
if mutation_result && !mutation_result.is_a?(Hash)
|
@@ -11,102 +11,139 @@ module GraphQL
|
|
11
11
|
if item_index.nil?
|
12
12
|
raise("Can't generate cursor, item not found in connection: #{item}")
|
13
13
|
else
|
14
|
-
offset =
|
14
|
+
offset = item_index + 1 + ((relation_offset(paged_nodes) || 0) - (relation_offset(sliced_nodes) || 0))
|
15
|
+
|
16
|
+
if after
|
17
|
+
offset += offset_from_cursor(after)
|
18
|
+
elsif before
|
19
|
+
offset += offset_from_cursor(before) - 1 - sliced_nodes_count
|
20
|
+
end
|
21
|
+
|
15
22
|
encode(offset.to_s)
|
16
23
|
end
|
17
24
|
end
|
18
25
|
|
19
26
|
def has_next_page
|
20
|
-
!!(first &&
|
27
|
+
!!(first && sliced_nodes_count > first)
|
21
28
|
end
|
22
29
|
|
23
30
|
def has_previous_page
|
24
|
-
!!(last &&
|
31
|
+
!!(last && sliced_nodes_count > last)
|
25
32
|
end
|
26
33
|
|
27
|
-
|
34
|
+
def first
|
35
|
+
return @first if defined? @first
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
count_or_hash.is_a?(Integer) ? count_or_hash : count_or_hash.length
|
37
|
+
@first = get_limited_arg(:first)
|
38
|
+
@first = max_page_size if @first && max_page_size && @first > max_page_size
|
39
|
+
@first
|
33
40
|
end
|
34
41
|
|
42
|
+
def last
|
43
|
+
return @last if defined? @last
|
44
|
+
|
45
|
+
@last = get_limited_arg(:last)
|
46
|
+
@last = max_page_size if @last && max_page_size && @last > max_page_size
|
47
|
+
@last
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
35
52
|
# apply first / last limit results
|
36
53
|
def paged_nodes
|
37
|
-
@paged_nodes
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
54
|
+
return @paged_nodes if defined? @paged_nodes
|
55
|
+
|
56
|
+
items = sliced_nodes
|
57
|
+
|
58
|
+
if first
|
59
|
+
if relation_limit(items).nil? || relation_limit(items) > first
|
60
|
+
items = items.limit(first)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
if last
|
65
|
+
if relation_limit(items)
|
66
|
+
if last <= relation_limit(items)
|
67
|
+
offset = (relation_offset(items) || 0) + (relation_limit(items) - last)
|
68
|
+
items = items.offset(offset).limit(last)
|
47
69
|
end
|
48
70
|
else
|
49
|
-
|
50
|
-
|
71
|
+
offset = (relation_offset(items) || 0) + relation_count(items) - last
|
72
|
+
items = items.offset(offset).limit(last)
|
51
73
|
end
|
52
74
|
end
|
53
|
-
end
|
54
75
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
76
|
+
if max_page_size && !first && !last
|
77
|
+
if relation_limit(items).nil? || relation_limit(items) > max_page_size
|
78
|
+
items = items.limit(max_page_size)
|
79
|
+
end
|
80
|
+
end
|
59
81
|
|
60
|
-
|
61
|
-
decode(cursor).to_i
|
82
|
+
@paged_nodes = items
|
62
83
|
end
|
63
84
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
else
|
71
|
-
previous_offset
|
72
|
-
end
|
85
|
+
def relation_offset(relation)
|
86
|
+
case relation
|
87
|
+
when ActiveRecord::Relation
|
88
|
+
relation.offset_value
|
89
|
+
when Sequel::Dataset
|
90
|
+
relation.opts[:offset]
|
73
91
|
end
|
74
92
|
end
|
75
93
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
prev_page_size = [max_page_size, last].compact.min || 0
|
83
|
-
offset_from_cursor(before) - prev_page_size - 1
|
84
|
-
else
|
85
|
-
0
|
94
|
+
def relation_limit(relation)
|
95
|
+
case relation
|
96
|
+
when ActiveRecord::Relation
|
97
|
+
relation.limit_value
|
98
|
+
when Sequel::Dataset
|
99
|
+
relation.opts[:limit]
|
86
100
|
end
|
87
101
|
end
|
88
102
|
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
# If a relation contains a `.group` clause, a `.count` will return a Hash.
|
104
|
+
def relation_count(relation)
|
105
|
+
count_or_hash = relation.count
|
106
|
+
count_or_hash.is_a?(Integer) ? count_or_hash : count_or_hash.length
|
107
|
+
end
|
108
|
+
|
109
|
+
# Apply cursors to edges
|
110
|
+
def sliced_nodes
|
111
|
+
return @sliced_nodes if defined? @sliced_nodes
|
112
|
+
|
113
|
+
@sliced_nodes = nodes
|
114
|
+
|
115
|
+
if after
|
116
|
+
offset = (relation_offset(@sliced_nodes) || 0) + offset_from_cursor(after)
|
117
|
+
@sliced_nodes = @sliced_nodes.offset(offset) if after
|
118
|
+
end
|
119
|
+
|
120
|
+
if before && after
|
121
|
+
if offset_from_cursor(after) < offset_from_cursor(before)
|
122
|
+
@sliced_nodes = @sliced_nodes.limit(offset_from_cursor(before) - offset_from_cursor(after) - 1)
|
97
123
|
else
|
98
|
-
|
99
|
-
previous_offset + (last ? last : 0)
|
100
|
-
else
|
101
|
-
last
|
102
|
-
end
|
124
|
+
@sliced_nodes = @sliced_nodes.limit(0)
|
103
125
|
end
|
104
|
-
|
126
|
+
elsif before
|
127
|
+
@sliced_nodes = @sliced_nodes.limit(offset_from_cursor(before) - 1)
|
105
128
|
end
|
129
|
+
|
130
|
+
@sliced_nodes
|
131
|
+
end
|
132
|
+
|
133
|
+
def sliced_nodes_count
|
134
|
+
return @sliced_nodes_count if defined? @sliced_nodes_count
|
135
|
+
|
136
|
+
# If a relation contains a `.group` clause, a `.count` will return a Hash.
|
137
|
+
@sliced_nodes_count = relation_count(sliced_nodes)
|
138
|
+
end
|
139
|
+
|
140
|
+
def offset_from_cursor(cursor)
|
141
|
+
decode(cursor).to_i
|
106
142
|
end
|
107
143
|
|
108
144
|
def paged_nodes_array
|
109
|
-
@paged_nodes_array
|
145
|
+
return @paged_nodes_array if defined?(@paged_nodes_array)
|
146
|
+
@paged_nodes_array = paged_nodes.to_a
|
110
147
|
end
|
111
148
|
end
|
112
149
|
|
data/lib/graphql/scalar_type.rb
CHANGED
@@ -80,22 +80,8 @@ module GraphQL
|
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
|
-
def get_arity(callable)
|
84
|
-
case callable
|
85
|
-
when Proc
|
86
|
-
callable.arity
|
87
|
-
else
|
88
|
-
callable.method(:call).arity
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
83
|
def ensure_two_arg(callable, method_name)
|
93
|
-
|
94
|
-
warn("Scalar coerce functions receive two values (`val` and `ctx`), one-argument functions are deprecated (see #{name}.#{method_name}).")
|
95
|
-
->(val, ctx) { callable.call(val) }
|
96
|
-
else
|
97
|
-
callable
|
98
|
-
end
|
84
|
+
GraphQL::BackwardsCompatibility.wrap_arity(callable, from: 1, to: 2, name: "#{name}.#{method_name}(val, ctx)")
|
99
85
|
end
|
100
86
|
|
101
87
|
def coerce_non_null_input(value, ctx)
|
data/lib/graphql/schema.rb
CHANGED
@@ -6,7 +6,6 @@ require "graphql/schema/default_type_error"
|
|
6
6
|
require "graphql/schema/invalid_type_error"
|
7
7
|
require "graphql/schema/instrumented_field_map"
|
8
8
|
require "graphql/schema/middleware_chain"
|
9
|
-
require "graphql/schema/mask"
|
10
9
|
require "graphql/schema/null_mask"
|
11
10
|
require "graphql/schema/possible_types"
|
12
11
|
require "graphql/schema/rescue_middleware"
|
@@ -63,8 +62,14 @@ module GraphQL
|
|
63
62
|
:default_mask,
|
64
63
|
:cursor_encoder,
|
65
64
|
directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.name] = d; m }},
|
66
|
-
instrument: ->(schema, type, instrumenter) {
|
65
|
+
instrument: ->(schema, type, instrumenter, after_built_ins: false) {
|
66
|
+
if type == :field && after_built_ins
|
67
|
+
type = :field_after_built_ins
|
68
|
+
end
|
69
|
+
schema.instrumenters[type] << instrumenter
|
70
|
+
},
|
67
71
|
query_analyzer: ->(schema, analyzer) { schema.query_analyzers << analyzer },
|
72
|
+
multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
|
68
73
|
middleware: ->(schema, middleware) { schema.middleware << middleware },
|
69
74
|
lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
|
70
75
|
rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block)}
|
@@ -74,7 +79,7 @@ module GraphQL
|
|
74
79
|
:query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
|
75
80
|
:max_depth, :max_complexity,
|
76
81
|
:orphan_types, :directives,
|
77
|
-
:query_analyzers, :instrumenters, :lazy_methods,
|
82
|
+
:query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
|
78
83
|
:cursor_encoder,
|
79
84
|
:raise_definition_error
|
80
85
|
|
@@ -89,6 +94,10 @@ module GraphQL
|
|
89
94
|
attr_accessor :default_execution_strategy
|
90
95
|
end
|
91
96
|
|
97
|
+
def default_filter
|
98
|
+
GraphQL::Filter.new(except: default_mask)
|
99
|
+
end
|
100
|
+
|
92
101
|
self.default_execution_strategy = GraphQL::Execution::Execute
|
93
102
|
|
94
103
|
BUILT_IN_TYPES = Hash[[INT_TYPE, STRING_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, ID_TYPE].map{ |type| [type.name, type] }]
|
@@ -104,6 +113,7 @@ module GraphQL
|
|
104
113
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
105
114
|
@middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
|
106
115
|
@query_analyzers = []
|
116
|
+
@multiplex_analyzers = []
|
107
117
|
@resolve_type_proc = nil
|
108
118
|
@object_from_id_proc = nil
|
109
119
|
@id_from_object_proc = nil
|
@@ -127,6 +137,7 @@ module GraphQL
|
|
127
137
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
128
138
|
@middleware = other.middleware.dup
|
129
139
|
@query_analyzers = other.query_analyzers.dup
|
140
|
+
@multiplex_analyzers = other.multiplex_analyzers.dup
|
130
141
|
|
131
142
|
@possible_types = GraphQL::Schema::PossibleTypes.new(self)
|
132
143
|
|
@@ -211,13 +222,36 @@ module GraphQL
|
|
211
222
|
# Execute a query on itself. Raises an error if the schema definition is invalid.
|
212
223
|
# @see {Query#initialize} for arguments.
|
213
224
|
# @return [Hash] query result, ready to be serialized as JSON
|
214
|
-
def execute(
|
215
|
-
if
|
216
|
-
|
217
|
-
else
|
218
|
-
query_obj = GraphQL::Query.new(self, *args)
|
219
|
-
query_obj.result
|
225
|
+
def execute(query_str = nil, **kwargs)
|
226
|
+
if query_str
|
227
|
+
kwargs[:query] = query_str
|
220
228
|
end
|
229
|
+
all_results = multiplex([kwargs])
|
230
|
+
all_results[0]
|
231
|
+
end
|
232
|
+
|
233
|
+
# Execute several queries on itself. Raises an error if the schema definition is invalid.
|
234
|
+
# @example Run several queries at once
|
235
|
+
# context = { ... }
|
236
|
+
# queries = [
|
237
|
+
# { query: params[:query_1], variables: params[:variables_1], context: context },
|
238
|
+
# { query: params[:query_2], variables: params[:variables_2], context: context },
|
239
|
+
# ]
|
240
|
+
# results = MySchema.multiplex(queries)
|
241
|
+
# render json: {
|
242
|
+
# result_1: results[0],
|
243
|
+
# result_2: results[1],
|
244
|
+
# }
|
245
|
+
#
|
246
|
+
# @see {Query#initialize} for query keyword arguments
|
247
|
+
# @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
|
248
|
+
# @param queries [Array<Hash>] Keyword arguments for each query
|
249
|
+
# @param context [Hash] Multiplex-level context
|
250
|
+
# @return [Array<Hash>] One result for each query in the input
|
251
|
+
def multiplex(*args)
|
252
|
+
with_definition_error_check {
|
253
|
+
GraphQL::Execution::Multiplex.run_all(self, *args)
|
254
|
+
}
|
221
255
|
end
|
222
256
|
|
223
257
|
# Resolve field named `field_name` for type `parent_type`.
|
@@ -225,17 +259,19 @@ module GraphQL
|
|
225
259
|
# @see [GraphQL::Schema::Warden] Restricted access to members of a schema
|
226
260
|
# @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
|
227
261
|
def get_field(parent_type, field_name)
|
228
|
-
|
229
|
-
|
230
|
-
defined_field
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
262
|
+
with_definition_error_check do
|
263
|
+
defined_field = @instrumented_field_map.get(parent_type.name, field_name)
|
264
|
+
if defined_field
|
265
|
+
defined_field
|
266
|
+
elsif field_name == "__typename"
|
267
|
+
GraphQL::Introspection::TypenameField
|
268
|
+
elsif field_name == "__schema" && parent_type == query
|
269
|
+
GraphQL::Introspection::SchemaField
|
270
|
+
elsif field_name == "__type" && parent_type == query
|
271
|
+
GraphQL::Introspection::TypeByNameField
|
272
|
+
else
|
273
|
+
nil
|
274
|
+
end
|
239
275
|
end
|
240
276
|
end
|
241
277
|
|
@@ -419,14 +455,31 @@ module GraphQL
|
|
419
455
|
!!lazy_method_name(obj)
|
420
456
|
end
|
421
457
|
|
422
|
-
# Return
|
458
|
+
# Return the GraphQL IDL for the schema
|
423
459
|
# @param context [Hash]
|
424
460
|
# @param only [<#call(member, ctx)>]
|
425
461
|
# @param except [<#call(member, ctx)>]
|
462
|
+
# @return [String]
|
426
463
|
def to_definition(only: nil, except: nil, context: {})
|
427
464
|
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
428
465
|
end
|
429
466
|
|
467
|
+
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
468
|
+
# @param context [Hash]
|
469
|
+
# @param only [<#call(member, ctx)>]
|
470
|
+
# @param except [<#call(member, ctx)>]
|
471
|
+
# @return [Hash] GraphQL result
|
472
|
+
def as_json(only: nil, except: nil, context: {})
|
473
|
+
execute(Introspection::INTROSPECTION_QUERY, only: only, except: except, context: context)
|
474
|
+
end
|
475
|
+
|
476
|
+
# Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
|
477
|
+
# @see {#as_json}
|
478
|
+
# @return [String]
|
479
|
+
def to_json(*args)
|
480
|
+
JSON.pretty_generate(as_json(*args))
|
481
|
+
end
|
482
|
+
|
430
483
|
protected
|
431
484
|
|
432
485
|
def rescues?
|
@@ -441,14 +494,18 @@ module GraphQL
|
|
441
494
|
|
442
495
|
private
|
443
496
|
|
497
|
+
# Wrap Relay-related objects in wrappers
|
498
|
+
# @api private
|
499
|
+
BUILT_IN_INSTRUMENTERS = [
|
500
|
+
GraphQL::Relay::ConnectionInstrumentation,
|
501
|
+
GraphQL::Relay::Mutation::Instrumentation,
|
502
|
+
]
|
503
|
+
|
444
504
|
# Apply instrumentation to fields. Relay instrumentation is applied last
|
445
505
|
# so that user-provided instrumentation can wrap user-provided resolve functions,
|
446
506
|
# _then_ Relay helpers can wrap the returned objects.
|
447
507
|
def build_instrumented_field_map
|
448
|
-
all_instrumenters = @instrumenters[:field] + [
|
449
|
-
GraphQL::Relay::ConnectionInstrumentation,
|
450
|
-
GraphQL::Relay::Mutation::Instrumentation,
|
451
|
-
]
|
508
|
+
all_instrumenters = @instrumenters[:field] + BUILT_IN_INSTRUMENTERS + @instrumenters[:field_after_built_ins]
|
452
509
|
@instrumented_field_map = InstrumentedFieldMap.new(self, all_instrumenters)
|
453
510
|
end
|
454
511
|
|
@@ -456,5 +513,13 @@ module GraphQL
|
|
456
513
|
all_types = orphan_types + [query, mutation, subscription, GraphQL::Introspection::SchemaType]
|
457
514
|
@types = GraphQL::Schema::ReduceTypes.reduce(all_types.compact)
|
458
515
|
end
|
516
|
+
|
517
|
+
def with_definition_error_check
|
518
|
+
if @definition_error
|
519
|
+
raise @definition_error
|
520
|
+
else
|
521
|
+
yield
|
522
|
+
end
|
523
|
+
end
|
459
524
|
end
|
460
525
|
end
|