graphql 2.6.2 → 2.6.5
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/field_extractor.rb +17 -1
- data/lib/graphql/analysis/query_complexity.rb +31 -15
- data/lib/graphql/backtrace/table.rb +10 -1
- data/lib/graphql/current.rb +7 -1
- data/lib/graphql/dataloader/async_dataloader.rb +310 -60
- data/lib/graphql/dataloader/source.rb +18 -10
- data/lib/graphql/dataloader.rb +1 -1
- data/lib/graphql/execution/directive_checks.rb +2 -0
- data/lib/graphql/execution/field_resolve_step.rb +84 -18
- data/lib/graphql/execution/finalize.rb +10 -9
- data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -0
- data/lib/graphql/execution/interpreter/runtime.rb +0 -6
- data/lib/graphql/execution/load_argument_step.rb +6 -0
- data/lib/graphql/execution/prepare_object_step.rb +14 -4
- data/lib/graphql/execution/runner.rb +7 -1
- data/lib/graphql/execution/selections_step.rb +6 -2
- data/lib/graphql/execution_error.rb +4 -0
- data/lib/graphql/language.rb +8 -2
- data/lib/graphql/schema/argument.rb +1 -1
- data/lib/graphql/schema/interface.rb +1 -1
- data/lib/graphql/schema/introspection_system.rb +6 -21
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/validator/allow_blank_validator.rb +3 -3
- data/lib/graphql/schema/validator/allow_null_validator.rb +3 -3
- data/lib/graphql/schema/validator/exclusion_validator.rb +2 -2
- data/lib/graphql/schema/validator/format_validator.rb +3 -3
- data/lib/graphql/schema/validator/inclusion_validator.rb +2 -2
- data/lib/graphql/schema/validator/length_validator.rb +6 -6
- data/lib/graphql/schema/validator/numericality_validator.rb +19 -19
- data/lib/graphql/schema/validator/required_validator.rb +6 -4
- data/lib/graphql/schema/validator.rb +9 -0
- data/lib/graphql/schema/visibility/profile.rb +6 -4
- data/lib/graphql/schema/visibility.rb +30 -22
- data/lib/graphql/schema.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +2 -2
|
@@ -49,12 +49,16 @@ module GraphQL
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def value
|
|
52
|
+
return nil if @selections_step.killed
|
|
52
53
|
query = @selections_step.query
|
|
53
|
-
|
|
54
|
+
set_current_field
|
|
55
|
+
query.current_trace.begin_execute_field(@field_definition, @field_results, @arguments, query)
|
|
54
56
|
sync(@field_results)
|
|
55
|
-
query.current_trace.end_execute_field(@field_definition, @
|
|
57
|
+
query.current_trace.end_execute_field(@field_definition, @field_results, @arguments, query, @field_results)
|
|
56
58
|
@runner.add_step(self)
|
|
57
59
|
true
|
|
60
|
+
ensure
|
|
61
|
+
set_current_field(nil)
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
def sync(lazy)
|
|
@@ -76,6 +80,9 @@ module GraphQL
|
|
|
76
80
|
end
|
|
77
81
|
|
|
78
82
|
def call
|
|
83
|
+
return nil if @selections_step.killed
|
|
84
|
+
set_current_field if @field_definition
|
|
85
|
+
|
|
79
86
|
if @enqueued_authorization
|
|
80
87
|
enqueue_next_steps
|
|
81
88
|
elsif @finish_extension_idx
|
|
@@ -94,26 +101,68 @@ module GraphQL
|
|
|
94
101
|
else
|
|
95
102
|
raise
|
|
96
103
|
end
|
|
104
|
+
ensure
|
|
105
|
+
set_current_field(nil)
|
|
97
106
|
end
|
|
98
107
|
|
|
99
|
-
def add_graphql_error(err)
|
|
108
|
+
def add_graphql_error(result, key, err, return_type: @field_definition.type)
|
|
100
109
|
err.path = path
|
|
101
110
|
if err.ast_node.nil?
|
|
102
111
|
err.ast_nodes = ast_nodes
|
|
103
112
|
end
|
|
104
|
-
@selections_step.query
|
|
113
|
+
@runner.add_finalizer(@selections_step.query, result, key, err)
|
|
114
|
+
if !err.is_a?(GraphQL::Execution::Skip)
|
|
115
|
+
field_type = return_type
|
|
116
|
+
should_propagate_null = field_type.non_null?
|
|
117
|
+
while (should_propagate_null == false && field_type.kind.wraps?)
|
|
118
|
+
field_type = field_type.of_type
|
|
119
|
+
should_propagate_null = field_type.non_null?
|
|
120
|
+
end
|
|
121
|
+
if should_propagate_null
|
|
122
|
+
propagate_nulls
|
|
123
|
+
end
|
|
124
|
+
end
|
|
105
125
|
err
|
|
106
126
|
end
|
|
107
127
|
|
|
128
|
+
def propagate_nulls
|
|
129
|
+
propagating_null = true
|
|
130
|
+
highest_nulled_depth = path.size
|
|
131
|
+
highest_list_depth = nil
|
|
132
|
+
current_field_step = self
|
|
133
|
+
while current_field_step
|
|
134
|
+
return_type = current_field_step.field_definition.type
|
|
135
|
+
if propagating_null && return_type.non_null?
|
|
136
|
+
highest_nulled_depth = current_field_step.path.size
|
|
137
|
+
else
|
|
138
|
+
propagating_null = false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if return_type.list?
|
|
142
|
+
highest_list_depth = current_field_step.path.size
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
current_field_step = current_field_step.selections_step.field_resolve_step
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if highest_list_depth.nil? || highest_nulled_depth <= highest_list_depth
|
|
149
|
+
kill_field_step = self
|
|
150
|
+
while kill_field_step && highest_nulled_depth <= kill_field_step.path.size
|
|
151
|
+
kill_field_step.selections_step.killed = true
|
|
152
|
+
kill_field_step = kill_field_step.selections_step.field_resolve_step
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
108
157
|
def build_errors_result(errors, single_error)
|
|
109
158
|
first_error = errors.nil? ? single_error : errors.pop
|
|
110
|
-
@field_results =
|
|
159
|
+
@field_results = [first_error]
|
|
160
|
+
@results = [@selections_step.results.first]
|
|
111
161
|
if errors
|
|
112
162
|
errors.each do |e|
|
|
113
|
-
add_graphql_error(e)
|
|
163
|
+
add_graphql_error(@results.first, key, e)
|
|
114
164
|
end
|
|
115
165
|
end
|
|
116
|
-
@results ||= @selections_step.results
|
|
117
166
|
build_results
|
|
118
167
|
end
|
|
119
168
|
|
|
@@ -121,6 +170,7 @@ module GraphQL
|
|
|
121
170
|
query = @selections_step.query
|
|
122
171
|
field_name = @ast_node.name
|
|
123
172
|
@field_definition = query.types.field(@parent_type, field_name) || raise(GraphQL::Error, "No field definition found for #{@parent_type.to_type_signature}.#{ast_node.name} (at #{@ast_node.position})")
|
|
173
|
+
set_current_field
|
|
124
174
|
@arguments, errors = @runner.input_values[query].argument_values(@field_definition, @ast_node.arguments, self) # rubocop:disable Development/ContextIsPassedCop
|
|
125
175
|
if errors
|
|
126
176
|
build_errors_result(errors, nil)
|
|
@@ -131,6 +181,8 @@ module GraphQL
|
|
|
131
181
|
@field_results.nil? # Make sure the arguments flow didn't already call through
|
|
132
182
|
execute_field
|
|
133
183
|
end
|
|
184
|
+
ensure
|
|
185
|
+
set_current_field(nil)
|
|
134
186
|
end
|
|
135
187
|
|
|
136
188
|
# Used for compatibility in Schema::Subscription
|
|
@@ -217,7 +269,7 @@ module GraphQL
|
|
|
217
269
|
authorized_results << @results[i]
|
|
218
270
|
end
|
|
219
271
|
rescue GraphQL::ExecutionError => exec_err
|
|
220
|
-
add_graphql_error(exec_err)
|
|
272
|
+
add_graphql_error(@results[i], key, exec_err)
|
|
221
273
|
end
|
|
222
274
|
end
|
|
223
275
|
i += 1
|
|
@@ -235,7 +287,7 @@ module GraphQL
|
|
|
235
287
|
@was_scoped = true
|
|
236
288
|
end
|
|
237
289
|
|
|
238
|
-
query.current_trace.begin_execute_field(@field_definition, @arguments,
|
|
290
|
+
query.current_trace.begin_execute_field(@field_definition, authorized_objects, @arguments, query)
|
|
239
291
|
|
|
240
292
|
if @runner.uses_runtime_directives
|
|
241
293
|
if @ast_nodes.nil? || @ast_nodes.size == 1
|
|
@@ -310,7 +362,7 @@ module GraphQL
|
|
|
310
362
|
@field_results = resolve_batch(authorized_objects, ctx, @arguments)
|
|
311
363
|
end
|
|
312
364
|
|
|
313
|
-
query.current_trace.end_execute_field(@field_definition, @arguments,
|
|
365
|
+
query.current_trace.end_execute_field(@field_definition, authorized_objects, @arguments, query, @field_results)
|
|
314
366
|
|
|
315
367
|
if any_lazy_results?
|
|
316
368
|
@runner.dataloader.lazy_at_depth(path.size, self)
|
|
@@ -322,12 +374,12 @@ module GraphQL
|
|
|
322
374
|
end
|
|
323
375
|
end
|
|
324
376
|
rescue GraphQL::ExecutionError => err
|
|
325
|
-
|
|
377
|
+
build_errors_result(nil, err)
|
|
326
378
|
rescue StandardError => stderr
|
|
327
379
|
begin
|
|
328
380
|
@selections_step.query.handle_or_reraise(stderr, field: @field_definition, arguments: @arguments, object: nil)
|
|
329
381
|
rescue GraphQL::ExecutionError => err
|
|
330
|
-
add_graphql_error(err)
|
|
382
|
+
add_graphql_error(@results[0], key, err)
|
|
331
383
|
end
|
|
332
384
|
end
|
|
333
385
|
|
|
@@ -449,13 +501,13 @@ module GraphQL
|
|
|
449
501
|
end
|
|
450
502
|
|
|
451
503
|
def finish_leaf_result(result_h, key, field_result, return_type, ctx)
|
|
452
|
-
final_field_result = build_leaf_result(field_result, return_type, ctx, false)
|
|
504
|
+
final_field_result = build_leaf_result(result_h, key, field_result, return_type, ctx, false)
|
|
453
505
|
|
|
454
506
|
@directive_finalizers&.each { |f| @runner.add_finalizer(ctx.query, result_h, key, f) }
|
|
455
507
|
result_h[@key] = final_field_result
|
|
456
508
|
end
|
|
457
509
|
|
|
458
|
-
def build_leaf_result(field_result, return_type, ctx, is_from_array)
|
|
510
|
+
def build_leaf_result(result_h, result_key, field_result, return_type, ctx, is_from_array)
|
|
459
511
|
if field_result.nil?
|
|
460
512
|
if return_type.non_null?
|
|
461
513
|
add_non_null_error(is_from_array)
|
|
@@ -464,7 +516,7 @@ module GraphQL
|
|
|
464
516
|
end
|
|
465
517
|
elsif field_result.is_a?(Finalizer)
|
|
466
518
|
if field_result.is_a?(GraphQL::RuntimeError)
|
|
467
|
-
add_graphql_error(field_result)
|
|
519
|
+
add_graphql_error(result_h, result_key, field_result, return_type: return_type)
|
|
468
520
|
else
|
|
469
521
|
field_result.path = path
|
|
470
522
|
@runner.add_finalizer(ctx.query, result_h, key, field_result)
|
|
@@ -475,7 +527,11 @@ module GraphQL
|
|
|
475
527
|
end
|
|
476
528
|
|
|
477
529
|
inner_type = return_type.of_type
|
|
478
|
-
|
|
530
|
+
result_a = Array.new(field_result.size)
|
|
531
|
+
field_result.each_with_index do |item, idx|
|
|
532
|
+
result_a[idx] = build_leaf_result(result_a, idx, item, inner_type, ctx, true)
|
|
533
|
+
end
|
|
534
|
+
result_a
|
|
479
535
|
else
|
|
480
536
|
return_type.coerce_result(field_result, ctx)
|
|
481
537
|
end
|
|
@@ -517,6 +573,7 @@ module GraphQL
|
|
|
517
573
|
query.current_trace.objects(obj_type, next_objects, ctx)
|
|
518
574
|
@runner.add_step(SelectionsStep.new(
|
|
519
575
|
path: path,
|
|
576
|
+
field_resolve_step: self,
|
|
520
577
|
parent_type: obj_type,
|
|
521
578
|
selections: @next_selections,
|
|
522
579
|
objects: next_objects,
|
|
@@ -529,6 +586,7 @@ module GraphQL
|
|
|
529
586
|
query.current_trace.objects(@static_type, @all_next_objects, ctx)
|
|
530
587
|
@runner.add_step(SelectionsStep.new(
|
|
531
588
|
path: path,
|
|
589
|
+
field_resolve_step: self,
|
|
532
590
|
parent_type: @static_type,
|
|
533
591
|
selections: @next_selections,
|
|
534
592
|
objects: @all_next_objects,
|
|
@@ -549,7 +607,15 @@ module GraphQL
|
|
|
549
607
|
|
|
550
608
|
def add_non_null_error(is_from_array)
|
|
551
609
|
err = @parent_type::InvalidNullError.new(@parent_type, @field_definition, ast_nodes, is_from_array: is_from_array, path: path)
|
|
552
|
-
@runner.schema.type_error(err, @selections_step.query.context)
|
|
610
|
+
nn_result = @runner.schema.type_error(err, @selections_step.query.context)
|
|
611
|
+
if nn_result.nil?
|
|
612
|
+
propagate_nulls
|
|
613
|
+
end
|
|
614
|
+
nn_result
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def set_current_field(new_value = @field_definition)
|
|
618
|
+
Fiber[:__graphql_current_field] = new_value
|
|
553
619
|
end
|
|
554
620
|
|
|
555
621
|
private
|
|
@@ -563,7 +629,7 @@ module GraphQL
|
|
|
563
629
|
end
|
|
564
630
|
elsif field_result.is_a?(Finalizer)
|
|
565
631
|
graphql_result[key] = if field_result.is_a?(GraphQL::RuntimeError)
|
|
566
|
-
add_graphql_error(field_result)
|
|
632
|
+
add_graphql_error(graphql_result, key, field_result)
|
|
567
633
|
else
|
|
568
634
|
field_result.path = path
|
|
569
635
|
@runner.add_finalizer(@selections_step.query, graphql_result, key, field_result)
|
|
@@ -33,14 +33,15 @@ module GraphQL
|
|
|
33
33
|
|
|
34
34
|
targets.each_with_index do |target, idx|
|
|
35
35
|
if target.is_a?(Hash)
|
|
36
|
-
|
|
36
|
+
value_at_key = target[key]
|
|
37
|
+
if value_at_key.equal?(err)
|
|
37
38
|
tf = @finalizers[target] ||= {}.compare_by_identity
|
|
38
39
|
tf[key] = err
|
|
39
40
|
@finalizers_count += 1
|
|
40
|
-
elsif
|
|
41
|
-
|
|
41
|
+
elsif value_at_key.is_a?(Array)
|
|
42
|
+
value_at_key.each_with_index do |el, idx|
|
|
42
43
|
if el.equal?(err)
|
|
43
|
-
tf = @finalizers[
|
|
44
|
+
tf = @finalizers[value_at_key] ||= {}.compare_by_identity
|
|
44
45
|
tf[idx] = err
|
|
45
46
|
@finalizers_count += 1
|
|
46
47
|
end
|
|
@@ -117,7 +118,7 @@ module GraphQL
|
|
|
117
118
|
@current_exec_path << key
|
|
118
119
|
@current_result_path << key
|
|
119
120
|
|
|
120
|
-
field_defn = @query.context.types.field(parent_type, ast_selection.name) || raise("Invariant: No field found for #{
|
|
121
|
+
field_defn = @query.context.types.field(parent_type, ast_selection.name) || raise("Invariant: No field found for #{parent_type.to_type_signature}.#{ast_selection.name}")
|
|
121
122
|
result_type = field_defn.type
|
|
122
123
|
if (result_type_non_null = result_type.non_null?)
|
|
123
124
|
result_type = result_type.of_type
|
|
@@ -150,16 +151,18 @@ module GraphQL
|
|
|
150
151
|
when Language::Nodes::InlineFragment
|
|
151
152
|
static_type_at_result = @static_type_at[result_h]
|
|
152
153
|
if static_type_at_result && (
|
|
153
|
-
|
|
154
|
+
(t = ast_selection.type).nil? ||
|
|
154
155
|
@runner.type_condition_applies?(@query.context, static_type_at_result, t.name)
|
|
155
156
|
)
|
|
156
157
|
result_h = check_object_result(result_h, parent_type, ast_selection.selections)
|
|
158
|
+
return nil if result_h.nil?
|
|
157
159
|
end
|
|
158
160
|
when Language::Nodes::FragmentSpread
|
|
159
161
|
fragment_defn = @query.document.definitions.find { |defn| defn.is_a?(Language::Nodes::FragmentDefinition) && defn.name == ast_selection.name }
|
|
160
162
|
static_type_at_result = @static_type_at[result_h]
|
|
161
163
|
if static_type_at_result && @runner.type_condition_applies?(@query.context, static_type_at_result, fragment_defn.type.name)
|
|
162
164
|
result_h = check_object_result(result_h, parent_type, fragment_defn.selections)
|
|
165
|
+
return nil if result_h.nil?
|
|
163
166
|
end
|
|
164
167
|
end
|
|
165
168
|
end
|
|
@@ -168,9 +171,7 @@ module GraphQL
|
|
|
168
171
|
end
|
|
169
172
|
|
|
170
173
|
def check_list_result(result_arr, inner_type, ast_selections)
|
|
171
|
-
inner_type_non_null =
|
|
172
|
-
if inner_type.non_null?
|
|
173
|
-
inner_type_non_null = true
|
|
174
|
+
if (inner_type_non_null = inner_type.non_null?)
|
|
174
175
|
inner_type = inner_type.of_type
|
|
175
176
|
end
|
|
176
177
|
|
|
@@ -30,7 +30,10 @@ module GraphQL
|
|
|
30
30
|
@storage[argument_owner][parent_object][ast_node] = resolved_args
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
|
+
end
|
|
33
34
|
|
|
35
|
+
def cached_arguments_for(ast_node, argument_owner)
|
|
36
|
+
@storage[argument_owner][nil][ast_node]
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
# @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
|
|
@@ -492,12 +492,6 @@ module GraphQL
|
|
|
492
492
|
end
|
|
493
493
|
end
|
|
494
494
|
end
|
|
495
|
-
# If this field is a root mutation field, immediately resolve
|
|
496
|
-
# all of its child fields before moving on to the next root mutation field.
|
|
497
|
-
# (Subselections of this mutation will still be resolved level-by-level.)
|
|
498
|
-
if selection_result.graphql_is_eager
|
|
499
|
-
@dataloader.run
|
|
500
|
-
end
|
|
501
495
|
end
|
|
502
496
|
|
|
503
497
|
def set_result(selection_result, result_name, value, is_child_result, is_non_null)
|
|
@@ -14,6 +14,7 @@ module GraphQL
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def value
|
|
17
|
+
@field_resolve_step.set_current_field
|
|
17
18
|
schema = @field_resolve_step.runner.schema
|
|
18
19
|
@loaded_value = schema.sync_lazy(@loaded_value)
|
|
19
20
|
assign_value
|
|
@@ -34,9 +35,12 @@ module GraphQL
|
|
|
34
35
|
@loaded_value = ex_err
|
|
35
36
|
end
|
|
36
37
|
assign_value
|
|
38
|
+
ensure
|
|
39
|
+
@field_resolve_step.set_current_field(nil)
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
def call
|
|
43
|
+
@field_resolve_step.set_current_field
|
|
40
44
|
context = @field_resolve_step.selections_step.query.context
|
|
41
45
|
@loaded_value = begin
|
|
42
46
|
@load_receiver.load_and_authorize_application_object(@argument_definition, @argument_value, context)
|
|
@@ -64,6 +68,8 @@ module GraphQL
|
|
|
64
68
|
ex_err
|
|
65
69
|
end
|
|
66
70
|
assign_value
|
|
71
|
+
ensure
|
|
72
|
+
@field_resolve_step.set_current_field(nil)
|
|
67
73
|
end
|
|
68
74
|
|
|
69
75
|
private
|
|
@@ -19,6 +19,7 @@ module GraphQL
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def value
|
|
22
|
+
@field_resolve_step.set_current_field
|
|
22
23
|
if @authorized_value
|
|
23
24
|
query = @field_resolve_step.selections_step.query
|
|
24
25
|
query.current_trace.begin_authorized(@resolved_type, @object, query.context)
|
|
@@ -36,9 +37,12 @@ module GraphQL
|
|
|
36
37
|
ctx.query.current_trace.end_resolve_type(st, @object, ctx, @resolved_type)
|
|
37
38
|
end
|
|
38
39
|
@runner.add_step(self)
|
|
40
|
+
ensure
|
|
41
|
+
@field_resolve_step.set_current_field(nil)
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
def call
|
|
45
|
+
@field_resolve_step.set_current_field
|
|
42
46
|
case @next_step
|
|
43
47
|
when :resolve_type
|
|
44
48
|
static_type = @field_resolve_step.static_type
|
|
@@ -65,6 +69,12 @@ module GraphQL
|
|
|
65
69
|
else
|
|
66
70
|
raise ArgumentError, "This is a bug, unknown step: #{@next_step.inspect}"
|
|
67
71
|
end
|
|
72
|
+
ensure
|
|
73
|
+
@field_resolve_step.set_current_field(nil)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def add_field_error(err)
|
|
77
|
+
@field_resolve_step.add_graphql_error(@graphql_result, @key, err)
|
|
68
78
|
end
|
|
69
79
|
|
|
70
80
|
def authorize
|
|
@@ -90,13 +100,13 @@ module GraphQL
|
|
|
90
100
|
create_result
|
|
91
101
|
end
|
|
92
102
|
rescue GraphQL::RuntimeError => err
|
|
93
|
-
@graphql_result[@key] =
|
|
103
|
+
@graphql_result[@key] = add_field_error(err)
|
|
94
104
|
rescue StandardError => err
|
|
95
105
|
query ||= @field_resolve_step.selections_step.query
|
|
96
106
|
begin
|
|
97
107
|
query.handle_or_reraise(err, field: @field_resolve_step.field_definition, arguments: @field_resolve_step.arguments, object: @object) # rubocop:disable Development/ContextIsPassedCop
|
|
98
108
|
rescue GraphQL::RuntimeError => err
|
|
99
|
-
@graphql_result[@key] =
|
|
109
|
+
@graphql_result[@key] = add_field_error(err)
|
|
100
110
|
end
|
|
101
111
|
end
|
|
102
112
|
|
|
@@ -114,13 +124,13 @@ module GraphQL
|
|
|
114
124
|
elsif @is_non_null
|
|
115
125
|
@graphql_result[@key] = @field_resolve_step.add_non_null_error(@is_from_array)
|
|
116
126
|
else
|
|
117
|
-
@graphql_result[@key] =
|
|
127
|
+
@graphql_result[@key] = add_field_error(@authorization_error)
|
|
118
128
|
end
|
|
119
129
|
rescue GraphQL::RuntimeError => err
|
|
120
130
|
if @is_non_null
|
|
121
131
|
@graphql_result[@key] = @field_resolve_step.add_non_null_error(@is_from_array)
|
|
122
132
|
else
|
|
123
|
-
@graphql_result[@key] =
|
|
133
|
+
@graphql_result[@key] = add_field_error(err)
|
|
124
134
|
end
|
|
125
135
|
end
|
|
126
136
|
end
|
|
@@ -116,7 +116,7 @@ module GraphQL
|
|
|
116
116
|
query.context.add_error(err)
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
-
trace.execute_query_lazy(query: nil, multiplex: @multiplex) do
|
|
119
|
+
trace.execute_query_lazy(query: @multiplex.queries.size == 1 ? @multiplex.queries.first : nil, multiplex: @multiplex) do
|
|
120
120
|
while (next_isolated_steps = isolated_steps.shift)
|
|
121
121
|
next_isolated_steps.each do |step|
|
|
122
122
|
add_step(step)
|
|
@@ -298,6 +298,7 @@ module GraphQL
|
|
|
298
298
|
if query.query?
|
|
299
299
|
isolated_steps[0] << SelectionsStep.new(
|
|
300
300
|
parent_type: root_type,
|
|
301
|
+
field_resolve_step: nil,
|
|
301
302
|
selections: selected_operation.selections,
|
|
302
303
|
objects: objects,
|
|
303
304
|
results: [data],
|
|
@@ -317,6 +318,7 @@ module GraphQL
|
|
|
317
318
|
isolated_steps << [SelectionsStep.new(
|
|
318
319
|
clobber: false, # `data` is being shared among several selections steps
|
|
319
320
|
parent_type: root_type,
|
|
321
|
+
field_resolve_step: field_resolve_step,
|
|
320
322
|
selections: field_resolve_step.ast_nodes || Array(field_resolve_step.ast_node),
|
|
321
323
|
objects: objects,
|
|
322
324
|
results: [data],
|
|
@@ -332,6 +334,7 @@ module GraphQL
|
|
|
332
334
|
end
|
|
333
335
|
isolated_steps[0] << SelectionsStep.new(
|
|
334
336
|
parent_type: root_type,
|
|
337
|
+
field_resolve_step: nil,
|
|
335
338
|
selections: selected_operation.selections,
|
|
336
339
|
objects: objects,
|
|
337
340
|
results: [data],
|
|
@@ -355,6 +358,7 @@ module GraphQL
|
|
|
355
358
|
results << { "data" => data }
|
|
356
359
|
isolated_steps[0] << SelectionsStep.new(
|
|
357
360
|
parent_type: resolved_type,
|
|
361
|
+
field_resolve_step: nil,
|
|
358
362
|
selections: selected_operation.selections,
|
|
359
363
|
objects: objects,
|
|
360
364
|
results: [data],
|
|
@@ -372,6 +376,7 @@ module GraphQL
|
|
|
372
376
|
results << { "data" => list_result }
|
|
373
377
|
isolated_steps[0] << SelectionsStep.new(
|
|
374
378
|
parent_type: inner_type,
|
|
379
|
+
field_resolve_step: nil,
|
|
375
380
|
selections: selected_operation.selections,
|
|
376
381
|
objects: root_value,
|
|
377
382
|
results: list_result,
|
|
@@ -420,6 +425,7 @@ module GraphQL
|
|
|
420
425
|
selections = partial.ast_nodes
|
|
421
426
|
dummy_ss = SelectionsStep.new(
|
|
422
427
|
parent_type: nil,
|
|
428
|
+
field_resolve_step: nil,
|
|
423
429
|
selections: selections,
|
|
424
430
|
objects: nil,
|
|
425
431
|
results: nil,
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Execution
|
|
4
4
|
class SelectionsStep
|
|
5
|
-
def initialize(parent_type:, selections:, objects:, results:, runner:, query:, path:, clobber: true)
|
|
5
|
+
def initialize(parent_type:, field_resolve_step:, selections:, objects:, results:, runner:, query:, path:, clobber: true)
|
|
6
6
|
@path = path
|
|
7
|
+
@field_resolve_step = field_resolve_step
|
|
7
8
|
@parent_type = parent_type
|
|
8
9
|
@selections = selections
|
|
9
10
|
@runner = runner
|
|
@@ -12,10 +13,13 @@ module GraphQL
|
|
|
12
13
|
@query = query
|
|
13
14
|
@graphql_objects = nil
|
|
14
15
|
@all_selections = nil
|
|
16
|
+
@killed = false
|
|
15
17
|
@clobber = clobber
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
attr_reader :path, :query, :objects, :results
|
|
20
|
+
attr_reader :path, :query, :objects, :results, :field_resolve_step
|
|
21
|
+
|
|
22
|
+
attr_accessor :killed
|
|
19
23
|
|
|
20
24
|
def graphql_objects
|
|
21
25
|
@graphql_objects ||= @objects.map do |obj|
|
|
@@ -26,6 +26,10 @@ module GraphQL
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def finalize_graphql_result(query, result_data, key)
|
|
29
|
+
add_this_error = !query.context.errors.any? { |e| e.eql?(self) }
|
|
30
|
+
if add_this_error
|
|
31
|
+
query.context.add_error(self)
|
|
32
|
+
end
|
|
29
33
|
if ast_node.is_a?(GraphQL::Language::Nodes::Directive)
|
|
30
34
|
# This is for backwards compatibility ... what does the spec say?
|
|
31
35
|
result_data.delete(key)
|
data/lib/graphql/language.rb
CHANGED
|
@@ -47,13 +47,19 @@ module GraphQL
|
|
|
47
47
|
def self.escape_single_quoted_newlines(query_str)
|
|
48
48
|
scanner = StringScanner.new(query_str)
|
|
49
49
|
inside_single_quoted_string = false
|
|
50
|
+
inside_triple_quoted_string = false
|
|
50
51
|
new_query_str = nil
|
|
51
52
|
while !scanner.eos?
|
|
52
|
-
if scanner.skip(
|
|
53
|
+
if scanner.skip('"""')
|
|
54
|
+
inside_triple_quoted_string = !inside_triple_quoted_string
|
|
55
|
+
new_query_str && (new_query_str << scanner.matched)
|
|
56
|
+
elsif scanner.skip(/(?:\\"|[^"\n\r])+/m)
|
|
53
57
|
new_query_str && (new_query_str << scanner.matched)
|
|
54
58
|
elsif scanner.skip('"')
|
|
55
59
|
new_query_str && (new_query_str << '"')
|
|
56
|
-
|
|
60
|
+
if !inside_triple_quoted_string
|
|
61
|
+
inside_single_quoted_string = !inside_single_quoted_string
|
|
62
|
+
end
|
|
57
63
|
elsif scanner.skip("\n")
|
|
58
64
|
if inside_single_quoted_string
|
|
59
65
|
new_query_str ||= query_str[0, scanner.pos - 1]
|
|
@@ -101,7 +101,7 @@ module GraphQL
|
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
child_class.ancestors.reverse_each do |ancestor|
|
|
104
|
-
if ancestor.const_defined?(:ResolverMethods)
|
|
104
|
+
if ancestor != child_class && ancestor <= GraphQL::Schema::Interface && ancestor.const_defined?(:ResolverMethods, false)
|
|
105
105
|
child_class.extend(ancestor::ResolverMethods)
|
|
106
106
|
end
|
|
107
107
|
end
|
|
@@ -105,11 +105,13 @@ module GraphQL
|
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
def load_constant(class_name)
|
|
108
|
-
const =
|
|
108
|
+
const = begin
|
|
109
|
+
@custom_namespace.const_get(class_name)
|
|
110
|
+
rescue NameError
|
|
111
|
+
# Dup the built-in so that the cached fields aren't shared
|
|
112
|
+
@built_in_namespace.const_get(class_name)
|
|
113
|
+
end
|
|
109
114
|
dup_type_class(const)
|
|
110
|
-
rescue NameError
|
|
111
|
-
# Dup the built-in so that the cached fields aren't shared
|
|
112
|
-
dup_type_class(@built_in_namespace.const_get(class_name))
|
|
113
115
|
end
|
|
114
116
|
|
|
115
117
|
def get_fields_from_class(class_sym:)
|
|
@@ -133,23 +135,6 @@ module GraphQL
|
|
|
133
135
|
end
|
|
134
136
|
end
|
|
135
137
|
end
|
|
136
|
-
|
|
137
|
-
class PerFieldProxyResolve
|
|
138
|
-
def initialize(object_class:, inner_resolve:)
|
|
139
|
-
@object_class = object_class
|
|
140
|
-
@inner_resolve = inner_resolve
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def call(obj, args, ctx)
|
|
144
|
-
query_ctx = ctx.query.context
|
|
145
|
-
# Remove the QueryType wrapper
|
|
146
|
-
if obj.is_a?(GraphQL::Schema::Object)
|
|
147
|
-
obj = obj.object
|
|
148
|
-
end
|
|
149
|
-
wrapped_object = @object_class.wrap(obj, query_ctx)
|
|
150
|
-
@inner_resolve.call(wrapped_object, args, ctx)
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
138
|
end
|
|
154
139
|
end
|
|
155
140
|
end
|
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
|
8
8
|
# @example Require a non-empty string for an argument
|
|
9
9
|
# argument :name, String, required: true, validate: { allow_blank: false }
|
|
10
10
|
class AllowBlankValidator < Validator
|
|
11
|
-
def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
|
|
11
|
+
def initialize(allow_blank_positional = nil, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
|
|
12
12
|
@message = message
|
|
13
13
|
super(**default_options)
|
|
14
14
|
@allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
|
|
@@ -16,10 +16,10 @@ module GraphQL
|
|
|
16
16
|
|
|
17
17
|
def validate(_object, _context, value)
|
|
18
18
|
if value.respond_to?(:blank?) && value.blank?
|
|
19
|
-
if (value.nil? && @allow_null) || @allow_blank
|
|
19
|
+
if (value.nil? && validation_parameter(@allow_null)) || validation_parameter(@allow_blank)
|
|
20
20
|
# pass
|
|
21
21
|
else
|
|
22
|
-
@message
|
|
22
|
+
validation_parameter(@message)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -9,15 +9,15 @@ module GraphQL
|
|
|
9
9
|
# argument :name, String, required: false, validates: { allow_null: false }
|
|
10
10
|
class AllowNullValidator < Validator
|
|
11
11
|
MESSAGE = "%{validated} can't be null"
|
|
12
|
-
def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
|
|
12
|
+
def initialize(allow_null_positional = nil, allow_null: nil, message: MESSAGE, **default_options)
|
|
13
13
|
@message = message
|
|
14
14
|
super(**default_options)
|
|
15
15
|
@allow_null = allow_null.nil? ? allow_null_positional : allow_null
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def validate(_object, _context, value)
|
|
19
|
-
if value.nil? &&
|
|
20
|
-
@message
|
|
19
|
+
if value.nil? && !validation_parameter(@allow_null)
|
|
20
|
+
validation_parameter(@message)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -23,8 +23,8 @@ module GraphQL
|
|
|
23
23
|
def validate(_object, _context, value)
|
|
24
24
|
if permitted_empty_value?(value)
|
|
25
25
|
# pass
|
|
26
|
-
elsif @in_list.include?(value)
|
|
27
|
-
@message
|
|
26
|
+
elsif validation_parameter(@in_list).include?(value)
|
|
27
|
+
validation_parameter(@message)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|