graphql 1.12.12 → 1.12.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/field_usage.rb +24 -1
- data/lib/graphql/backtrace/table.rb +1 -1
- data/lib/graphql/backtrace/tracer.rb +7 -4
- data/lib/graphql/execution/interpreter/resolve.rb +6 -2
- data/lib/graphql/execution/interpreter/runtime.rb +161 -41
- data/lib/graphql/execution/interpreter.rb +3 -3
- data/lib/graphql/execution/lazy.rb +5 -1
- data/lib/graphql/pagination/connections.rb +5 -0
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/schema/build_from_definition.rb +8 -2
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/enum.rb +10 -1
- data/lib/graphql/schema/input_object.rb +11 -15
- data/lib/graphql/schema/member/build_type.rb +1 -0
- data/lib/graphql/schema/printer.rb +11 -16
- data/lib/graphql/schema/resolver.rb +6 -1
- data/lib/graphql/schema/subscription.rb +20 -0
- data/lib/graphql/schema.rb +8 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -1
- data/lib/graphql/subscriptions/event.rb +4 -20
- data/lib/graphql/types/big_int.rb +5 -1
- data/lib/graphql/types/relay/has_node_field.rb +1 -1
- data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
- data/lib/graphql/types/relay/node_field.rb +2 -2
- data/lib/graphql/types/relay/nodes_field.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +15 -11
- data/readme.md +0 -3
- metadata +6 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03b30407d3081dad5d25f3a3f9a9e2781cd34db838688816b01c231aaa5a6dc5
|
4
|
+
data.tar.gz: a06092995f8e3ea0ed2c75485124b0123d41a23d77eedd773e15a1d00fad80ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3af391b8f7394985a42595af2d7b3735a6666310a4583ffd2a9ddce46cf868a6a8d7f2a9cb28ba6a1b85fb70cce8d7425074df847f8b113420e59599bd0379b5
|
7
|
+
data.tar.gz: ca7370709ff588ba437a2f5b277482f2a00543b057ee96e164198ea44f81ad1e470fafe4c7eb89a9e1e64c0aeeddcc128983a67458040c855115516c09adcfd0
|
@@ -7,6 +7,7 @@ module GraphQL
|
|
7
7
|
super
|
8
8
|
@used_fields = Set.new
|
9
9
|
@used_deprecated_fields = Set.new
|
10
|
+
@used_deprecated_arguments = Set.new
|
10
11
|
end
|
11
12
|
|
12
13
|
def on_leave_field(node, parent, visitor)
|
@@ -14,14 +15,36 @@ module GraphQL
|
|
14
15
|
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
15
16
|
@used_fields << field
|
16
17
|
@used_deprecated_fields << field if field_defn.deprecation_reason
|
18
|
+
|
19
|
+
extract_deprecated_arguments(visitor.query.arguments_for(node, visitor.field_definition).argument_values)
|
17
20
|
end
|
18
21
|
|
19
22
|
def result
|
20
23
|
{
|
21
24
|
used_fields: @used_fields.to_a,
|
22
|
-
used_deprecated_fields: @used_deprecated_fields.to_a
|
25
|
+
used_deprecated_fields: @used_deprecated_fields.to_a,
|
26
|
+
used_deprecated_arguments: @used_deprecated_arguments.to_a,
|
23
27
|
}
|
24
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def extract_deprecated_arguments(argument_values)
|
33
|
+
argument_values.each_pair do |_argument_name, argument|
|
34
|
+
if argument.definition.deprecation_reason
|
35
|
+
@used_deprecated_arguments << argument.definition.path
|
36
|
+
end
|
37
|
+
|
38
|
+
if argument.definition.type.kind.input_object?
|
39
|
+
extract_deprecated_arguments(argument.value.arguments.argument_values)
|
40
|
+
elsif argument.definition.type.list?
|
41
|
+
argument
|
42
|
+
.value
|
43
|
+
.select { |value| value.respond_to?(:arguments) }
|
44
|
+
.each { |value| extract_deprecated_arguments(value.arguments.argument_values) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|
@@ -15,14 +15,17 @@ module GraphQL
|
|
15
15
|
# No query context yet
|
16
16
|
nil
|
17
17
|
when "validate", "analyze_query", "execute_query", "execute_query_lazy"
|
18
|
-
query = metadata[:query] || metadata[:queries].first
|
19
18
|
push_key = []
|
20
|
-
|
21
|
-
|
19
|
+
if (query = metadata[:query]) || ((queries = metadata[:queries]) && (query = queries.first))
|
20
|
+
push_data = query
|
21
|
+
multiplex = query.multiplex
|
22
|
+
elsif (multiplex = metadata[:multiplex])
|
23
|
+
push_data = multiplex.queries.first
|
24
|
+
end
|
22
25
|
when "execute_field", "execute_field_lazy"
|
23
26
|
query = metadata[:query] || raise(ArgumentError, "Add `legacy: true` to use GraphQL::Backtrace without the interpreter runtime.")
|
24
27
|
multiplex = query.multiplex
|
25
|
-
push_key = metadata[:path]
|
28
|
+
push_key = metadata[:path]
|
26
29
|
parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]
|
27
30
|
|
28
31
|
if parent_frame.is_a?(GraphQL::Query)
|
@@ -34,7 +34,10 @@ module GraphQL
|
|
34
34
|
next_results = []
|
35
35
|
while results.any?
|
36
36
|
result_value = results.shift
|
37
|
-
if result_value.is_a?(Hash)
|
37
|
+
if result_value.is_a?(Runtime::GraphQLResultHash) || result_value.is_a?(Hash)
|
38
|
+
results.concat(result_value.values)
|
39
|
+
next
|
40
|
+
elsif result_value.is_a?(Runtime::GraphQLResultArray)
|
38
41
|
results.concat(result_value.values)
|
39
42
|
next
|
40
43
|
elsif result_value.is_a?(Array)
|
@@ -46,7 +49,8 @@ module GraphQL
|
|
46
49
|
# Since this field returned another lazy,
|
47
50
|
# add it to the same queue
|
48
51
|
results << loaded_value
|
49
|
-
elsif loaded_value.is_a?(
|
52
|
+
elsif loaded_value.is_a?(Runtime::GraphQLResultHash) || loaded_value.is_a?(Runtime::GraphQLResultArray) ||
|
53
|
+
loaded_value.is_a?(Hash) || loaded_value.is_a?(Array)
|
50
54
|
# Add these values in wholesale --
|
51
55
|
# they might be modified by later work in the dataloader.
|
52
56
|
next_results << loaded_value
|
@@ -10,9 +10,19 @@ module GraphQL
|
|
10
10
|
class Runtime
|
11
11
|
|
12
12
|
module GraphQLResult
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def initialize(result_name, parent_result)
|
14
|
+
@graphql_parent = parent_result
|
15
|
+
if parent_result && parent_result.graphql_dead
|
16
|
+
@graphql_dead = true
|
17
|
+
end
|
18
|
+
@graphql_result_name = result_name
|
19
|
+
# Jump through some hoops to avoid creating this duplicate storage if at all possible.
|
20
|
+
@graphql_metadata = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :graphql_dead
|
24
|
+
attr_reader :graphql_parent, :graphql_result_name
|
25
|
+
|
16
26
|
# Although these are used by only one of the Result classes,
|
17
27
|
# it's handy to have the methods implemented on both (even though they just return `nil`)
|
18
28
|
# because it makes it easy to check if anything is assigned.
|
@@ -20,9 +30,17 @@ module GraphQL
|
|
20
30
|
attr_accessor :graphql_non_null_field_names
|
21
31
|
# @return [nil, true]
|
22
32
|
attr_accessor :graphql_non_null_list_items
|
33
|
+
|
34
|
+
# @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
|
35
|
+
attr_accessor :graphql_result_data
|
23
36
|
end
|
24
37
|
|
25
|
-
class GraphQLResultHash
|
38
|
+
class GraphQLResultHash
|
39
|
+
def initialize(_result_name, _parent_result)
|
40
|
+
super
|
41
|
+
@graphql_result_data = {}
|
42
|
+
end
|
43
|
+
|
26
44
|
include GraphQLResult
|
27
45
|
|
28
46
|
attr_accessor :graphql_merged_into
|
@@ -39,12 +57,82 @@ module GraphQL
|
|
39
57
|
if (t = @graphql_merged_into)
|
40
58
|
t[key] = value
|
41
59
|
end
|
42
|
-
|
60
|
+
|
61
|
+
if value.respond_to?(:graphql_result_data)
|
62
|
+
@graphql_result_data[key] = value.graphql_result_data
|
63
|
+
# If we encounter some part of this response that requires metadata tracking,
|
64
|
+
# then create the metadata hash if necessary. It will be kept up-to-date after this.
|
65
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[key] = value
|
66
|
+
else
|
67
|
+
@graphql_result_data[key] = value
|
68
|
+
# keep this up-to-date if it's been initialized
|
69
|
+
@graphql_metadata && @graphql_metadata[key] = value
|
70
|
+
end
|
71
|
+
|
72
|
+
value
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete(key)
|
76
|
+
@graphql_metadata && @graphql_metadata.delete(key)
|
77
|
+
@graphql_result_data.delete(key)
|
78
|
+
end
|
79
|
+
|
80
|
+
def each
|
81
|
+
(@graphql_metadata || @graphql_result_data).each { |k, v| yield(k, v) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def values
|
85
|
+
(@graphql_metadata || @graphql_result_data).values
|
86
|
+
end
|
87
|
+
|
88
|
+
def key?(k)
|
89
|
+
@graphql_result_data.key?(k)
|
90
|
+
end
|
91
|
+
|
92
|
+
def [](k)
|
93
|
+
(@graphql_metadata || @graphql_result_data)[k]
|
43
94
|
end
|
44
95
|
end
|
45
96
|
|
46
|
-
class GraphQLResultArray
|
97
|
+
class GraphQLResultArray
|
47
98
|
include GraphQLResult
|
99
|
+
|
100
|
+
def initialize(_result_name, _parent_result)
|
101
|
+
super
|
102
|
+
@graphql_result_data = []
|
103
|
+
end
|
104
|
+
|
105
|
+
def graphql_skip_at(index)
|
106
|
+
# Mark this index as dead. It's tricky because some indices may already be storing
|
107
|
+
# `Lazy`s. So the runtime is still holding indexes _before_ skipping,
|
108
|
+
# this object has to coordinate incoming writes to account for any already-skipped indices.
|
109
|
+
@skip_indices ||= []
|
110
|
+
@skip_indices << index
|
111
|
+
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < index}
|
112
|
+
delete_at_index = index - offset_by
|
113
|
+
@graphql_metadata && @graphql_metadata.delete_at(delete_at_index)
|
114
|
+
@graphql_result_data.delete_at(delete_at_index)
|
115
|
+
end
|
116
|
+
|
117
|
+
def []=(idx, value)
|
118
|
+
if @skip_indices
|
119
|
+
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < idx }
|
120
|
+
idx -= offset_by
|
121
|
+
end
|
122
|
+
if value.respond_to?(:graphql_result_data)
|
123
|
+
@graphql_result_data[idx] = value.graphql_result_data
|
124
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[idx] = value
|
125
|
+
else
|
126
|
+
@graphql_result_data[idx] = value
|
127
|
+
@graphql_metadata && @graphql_metadata[idx] = value
|
128
|
+
end
|
129
|
+
|
130
|
+
value
|
131
|
+
end
|
132
|
+
|
133
|
+
def values
|
134
|
+
(@graphql_metadata || @graphql_result_data)
|
135
|
+
end
|
48
136
|
end
|
49
137
|
|
50
138
|
class GraphQLSelectionSet < Hash
|
@@ -60,9 +148,6 @@ module GraphQL
|
|
60
148
|
# @return [GraphQL::Query::Context]
|
61
149
|
attr_reader :context
|
62
150
|
|
63
|
-
# @return [Hash]
|
64
|
-
attr_reader :response
|
65
|
-
|
66
151
|
def initialize(query:)
|
67
152
|
@query = query
|
68
153
|
@dataloader = query.multiplex.dataloader
|
@@ -70,7 +155,7 @@ module GraphQL
|
|
70
155
|
@context = query.context
|
71
156
|
@multiplex_context = query.multiplex.context
|
72
157
|
@interpreter_context = @context.namespace(:interpreter)
|
73
|
-
@response = GraphQLResultHash.new
|
158
|
+
@response = GraphQLResultHash.new(nil, nil)
|
74
159
|
# Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
|
75
160
|
@runtime_directive_names = []
|
76
161
|
noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
|
@@ -87,6 +172,10 @@ module GraphQL
|
|
87
172
|
@lazy_cache = {}
|
88
173
|
end
|
89
174
|
|
175
|
+
def final_result
|
176
|
+
@response && @response.graphql_result_data
|
177
|
+
end
|
178
|
+
|
90
179
|
def inspect
|
91
180
|
"#<#{self.class.name} response=#{@response.inspect}>"
|
92
181
|
end
|
@@ -128,7 +217,7 @@ module GraphQL
|
|
128
217
|
# directly evaluated and the results can be written right into the main response hash.
|
129
218
|
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
130
219
|
if is_selection_array
|
131
|
-
selection_response = GraphQLResultHash.new
|
220
|
+
selection_response = GraphQLResultHash.new(nil, nil)
|
132
221
|
final_response = @response
|
133
222
|
else
|
134
223
|
selection_response = @response
|
@@ -167,7 +256,7 @@ module GraphQL
|
|
167
256
|
into_result[key] = value
|
168
257
|
else
|
169
258
|
case value
|
170
|
-
when
|
259
|
+
when GraphQLResultHash
|
171
260
|
deep_merge_selection_result(value, into_result[key])
|
172
261
|
else
|
173
262
|
# We have to assume that, since this passed the `fields_will_merge` selection,
|
@@ -282,6 +371,7 @@ module GraphQL
|
|
282
371
|
|
283
372
|
# @return [void]
|
284
373
|
def evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_field, selections_result) # rubocop:disable Metrics/ParameterLists
|
374
|
+
return if dead_result?(selections_result)
|
285
375
|
# As a performance optimization, the hash key will be a `Node` if
|
286
376
|
# there's only one selection of the field. But if there are multiple
|
287
377
|
# selections of the field, it will be an Array of nodes
|
@@ -439,15 +529,7 @@ module GraphQL
|
|
439
529
|
end
|
440
530
|
|
441
531
|
def dead_result?(selection_result)
|
442
|
-
|
443
|
-
while r
|
444
|
-
if r.graphql_dead
|
445
|
-
return true
|
446
|
-
else
|
447
|
-
r = r.graphql_parent
|
448
|
-
end
|
449
|
-
end
|
450
|
-
false
|
532
|
+
selection_result.graphql_dead || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
|
451
533
|
end
|
452
534
|
|
453
535
|
def set_result(selection_result, result_name, value)
|
@@ -471,9 +553,7 @@ module GraphQL
|
|
471
553
|
@response = nil
|
472
554
|
else
|
473
555
|
set_result(parent, name_in_parent, nil)
|
474
|
-
|
475
|
-
# a `nil`, it's marked dead. TODO: check the spec, is there a reason for this?
|
476
|
-
parent.graphql_dead = true
|
556
|
+
set_graphql_dead(selection_result)
|
477
557
|
end
|
478
558
|
else
|
479
559
|
selection_result[result_name] = value
|
@@ -481,6 +561,21 @@ module GraphQL
|
|
481
561
|
end
|
482
562
|
end
|
483
563
|
|
564
|
+
# Mark this node and any already-registered children as dead,
|
565
|
+
# so that it accepts no more writes.
|
566
|
+
def set_graphql_dead(selection_result)
|
567
|
+
case selection_result
|
568
|
+
when GraphQLResultArray
|
569
|
+
selection_result.graphql_dead = true
|
570
|
+
selection_result.values.each { |v| set_graphql_dead(v) }
|
571
|
+
when GraphQLResultHash
|
572
|
+
selection_result.graphql_dead = true
|
573
|
+
selection_result.each { |k, v| set_graphql_dead(v) }
|
574
|
+
else
|
575
|
+
# It's a scalar, no way to mark it dead.
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
484
579
|
HALT = Object.new
|
485
580
|
def continue_value(path, value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
|
486
581
|
case value
|
@@ -500,11 +595,13 @@ module GraphQL
|
|
500
595
|
# to avoid the overhead of checking three different classes
|
501
596
|
# every time.
|
502
597
|
if value.is_a?(GraphQL::ExecutionError)
|
503
|
-
if !dead_result?(selection_result)
|
598
|
+
if selection_result.nil? || !dead_result?(selection_result)
|
504
599
|
value.path ||= path
|
505
600
|
value.ast_node ||= ast_node
|
506
601
|
context.errors << value
|
507
|
-
|
602
|
+
if selection_result
|
603
|
+
set_result(selection_result, result_name, nil)
|
604
|
+
end
|
508
605
|
end
|
509
606
|
HALT
|
510
607
|
elsif value.is_a?(GraphQL::UnauthorizedError)
|
@@ -517,6 +614,17 @@ module GraphQL
|
|
517
614
|
end
|
518
615
|
continue_value(path, next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
|
519
616
|
elsif GraphQL::Execution::Execute::SKIP == value
|
617
|
+
# It's possible a lazy was already written here
|
618
|
+
case selection_result
|
619
|
+
when GraphQLResultHash
|
620
|
+
selection_result.delete(result_name)
|
621
|
+
when GraphQLResultArray
|
622
|
+
selection_result.graphql_skip_at(result_name)
|
623
|
+
when nil
|
624
|
+
# this can happen with directives
|
625
|
+
else
|
626
|
+
raise "Invariant: unexpected result class #{selection_result.class} (#{selection_result.inspect})"
|
627
|
+
end
|
520
628
|
HALT
|
521
629
|
else
|
522
630
|
# What could this actually _be_? Anyhow,
|
@@ -526,13 +634,15 @@ module GraphQL
|
|
526
634
|
when Array
|
527
635
|
# It's an array full of execution errors; add them all.
|
528
636
|
if value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
|
529
|
-
if !dead_result?(selection_result)
|
637
|
+
if selection_result.nil? || !dead_result?(selection_result)
|
530
638
|
value.each_with_index do |error, index|
|
531
639
|
error.ast_node ||= ast_node
|
532
|
-
error.path ||= path + (field.type.list? ? [index] : [])
|
640
|
+
error.path ||= path + ((field && field.type.list?) ? [index] : [])
|
533
641
|
context.errors << error
|
534
642
|
end
|
535
|
-
|
643
|
+
if selection_result
|
644
|
+
set_result(selection_result, result_name, nil)
|
645
|
+
end
|
536
646
|
end
|
537
647
|
HALT
|
538
648
|
else
|
@@ -593,9 +703,7 @@ module GraphQL
|
|
593
703
|
after_lazy(object_proxy, owner: current_type, path: path, ast_node: ast_node, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |inner_object|
|
594
704
|
continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
|
595
705
|
if HALT != continue_value
|
596
|
-
response_hash = GraphQLResultHash.new
|
597
|
-
response_hash.graphql_parent = selection_result
|
598
|
-
response_hash.graphql_result_name = result_name
|
706
|
+
response_hash = GraphQLResultHash.new(result_name, selection_result)
|
599
707
|
set_result(selection_result, result_name, response_hash)
|
600
708
|
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
601
709
|
# There are two possibilities for `gathered_selections`:
|
@@ -608,9 +716,7 @@ module GraphQL
|
|
608
716
|
# (Technically, it's possible that one of those entries _doesn't_ require isolation.)
|
609
717
|
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
610
718
|
if is_selection_array
|
611
|
-
this_result = GraphQLResultHash.new
|
612
|
-
this_result.graphql_parent = selection_result
|
613
|
-
this_result.graphql_result_name = result_name
|
719
|
+
this_result = GraphQLResultHash.new(result_name, selection_result)
|
614
720
|
final_result = response_hash
|
615
721
|
else
|
616
722
|
this_result = response_hash
|
@@ -635,16 +741,15 @@ module GraphQL
|
|
635
741
|
end
|
636
742
|
when "LIST"
|
637
743
|
inner_type = current_type.of_type
|
638
|
-
response_list = GraphQLResultArray.new
|
744
|
+
response_list = GraphQLResultArray.new(result_name, selection_result)
|
639
745
|
response_list.graphql_non_null_list_items = inner_type.non_null?
|
640
|
-
response_list.graphql_parent = selection_result
|
641
|
-
response_list.graphql_result_name = result_name
|
642
746
|
set_result(selection_result, result_name, response_list)
|
643
747
|
|
644
748
|
idx = 0
|
645
749
|
scoped_context = context.scoped_context
|
646
750
|
begin
|
647
751
|
value.each do |inner_value|
|
752
|
+
break if dead_result?(response_list)
|
648
753
|
next_path = path.dup
|
649
754
|
next_path << idx
|
650
755
|
this_idx = idx
|
@@ -689,9 +794,24 @@ module GraphQL
|
|
689
794
|
if !dir_defn.is_a?(Class)
|
690
795
|
dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
|
691
796
|
end
|
692
|
-
|
693
|
-
|
694
|
-
|
797
|
+
raw_dir_args = arguments(nil, dir_defn, dir_node)
|
798
|
+
dir_args = continue_value(
|
799
|
+
@context[:current_path], # path
|
800
|
+
raw_dir_args, # value
|
801
|
+
dir_defn, # parent_type
|
802
|
+
nil, # field
|
803
|
+
false, # is_non_null
|
804
|
+
dir_node, # ast_node
|
805
|
+
nil, # result_name
|
806
|
+
nil, # selection_result
|
807
|
+
)
|
808
|
+
|
809
|
+
if dir_args == HALT
|
810
|
+
nil
|
811
|
+
else
|
812
|
+
dir_defn.resolve(object, dir_args, context) do
|
813
|
+
run_directive(object, directives, idx + 1, &block)
|
814
|
+
end
|
695
815
|
end
|
696
816
|
end
|
697
817
|
end
|
@@ -18,7 +18,7 @@ module GraphQL
|
|
18
18
|
def execute(_operation, _root_type, query)
|
19
19
|
runtime = evaluate(query)
|
20
20
|
sync_lazies(query: query)
|
21
|
-
runtime.
|
21
|
+
runtime.final_result
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.use(schema_class)
|
@@ -56,7 +56,7 @@ module GraphQL
|
|
56
56
|
|
57
57
|
def self.finish_query(query, _multiplex)
|
58
58
|
{
|
59
|
-
"data" => query.context.namespace(:interpreter)[:runtime].
|
59
|
+
"data" => query.context.namespace(:interpreter)[:runtime].final_result
|
60
60
|
}
|
61
61
|
end
|
62
62
|
|
@@ -87,7 +87,7 @@ module GraphQL
|
|
87
87
|
final_values = queries.map do |query|
|
88
88
|
runtime = query.context.namespace(:interpreter)[:runtime]
|
89
89
|
# it might not be present if the query has an error
|
90
|
-
runtime ? runtime.
|
90
|
+
runtime ? runtime.final_result : nil
|
91
91
|
end
|
92
92
|
final_values.compact!
|
93
93
|
tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
|
@@ -48,7 +48,11 @@ module GraphQL
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
# `SKIP` was made into a subclass of `GraphQL::Error` to improve runtime performance
|
52
|
+
# (fewer clauses in a hot `case` block), but now it requires special handling here.
|
53
|
+
# I think it's still worth it for the performance win, but if the number of special
|
54
|
+
# cases grows, then maybe it's worth rethinking somehow.
|
55
|
+
if @value.is_a?(StandardError) && @value != GraphQL::Execution::Execute::SKIP
|
52
56
|
raise @value
|
53
57
|
else
|
54
58
|
@value
|
@@ -130,6 +130,11 @@ module GraphQL
|
|
130
130
|
if defined?(Mongoid::Association::Referenced::HasMany::Targets::Enumerable)
|
131
131
|
add(Mongoid::Association::Referenced::HasMany::Targets::Enumerable, Pagination::MongoidRelationConnection)
|
132
132
|
end
|
133
|
+
|
134
|
+
# Mongoid 7.3+
|
135
|
+
if defined?(Mongoid::Association::Referenced::HasMany::Enumerable)
|
136
|
+
add(Mongoid::Association::Referenced::HasMany::Enumerable, Pagination::MongoidRelationConnection)
|
137
|
+
end
|
133
138
|
end
|
134
139
|
end
|
135
140
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -270,7 +270,7 @@ module GraphQL
|
|
270
270
|
# @return [String, nil] Returns nil if the query is invalid.
|
271
271
|
def sanitized_query_string(inline_variables: true)
|
272
272
|
with_prepared_ast {
|
273
|
-
|
273
|
+
schema.sanitized_printer.new(self, inline_variables: inline_variables).sanitized_query_string
|
274
274
|
}
|
275
275
|
end
|
276
276
|
|
@@ -47,10 +47,16 @@ module GraphQL
|
|
47
47
|
# _while_ building the schema.
|
48
48
|
# It will dig for a type if it encounters a custom type. This could be a problem if there are cycles.
|
49
49
|
directive_type_resolver = nil
|
50
|
-
directive_type_resolver = build_resolve_type(
|
50
|
+
directive_type_resolver = build_resolve_type(types, directives, ->(type_name) {
|
51
51
|
types[type_name] ||= begin
|
52
52
|
defn = document.definitions.find { |d| d.respond_to?(:name) && d.name == type_name }
|
53
|
-
|
53
|
+
if defn
|
54
|
+
build_definition_from_node(defn, directive_type_resolver, default_resolve)
|
55
|
+
elsif (built_in_defn = GraphQL::Schema::BUILT_IN_TYPES[type_name])
|
56
|
+
built_in_defn
|
57
|
+
else
|
58
|
+
raise "No definition for #{type_name.inspect} found in schema document or built-in types. Add a definition for it or remove it."
|
59
|
+
end
|
54
60
|
end
|
55
61
|
})
|
56
62
|
|
@@ -39,7 +39,7 @@ module GraphQL
|
|
39
39
|
transform_name = arguments[:by]
|
40
40
|
if TRANSFORMS.include?(transform_name) && return_value.respond_to?(transform_name)
|
41
41
|
return_value = return_value.public_send(transform_name)
|
42
|
-
response = context.namespace(:interpreter)[:runtime].
|
42
|
+
response = context.namespace(:interpreter)[:runtime].final_result
|
43
43
|
*keys, last = path
|
44
44
|
keys.each do |key|
|
45
45
|
if response && (response = response[key])
|
data/lib/graphql/schema/enum.rb
CHANGED
@@ -24,6 +24,15 @@ module GraphQL
|
|
24
24
|
extend GraphQL::Schema::Member::ValidatesInput
|
25
25
|
|
26
26
|
class UnresolvedValueError < GraphQL::EnumType::UnresolvedValueError
|
27
|
+
def initialize(value:, enum:, context:)
|
28
|
+
fix_message = ", but this isn't a valid value for `#{enum.graphql_name}`. Update the field or resolver to return one of `#{enum.graphql_name}`'s values instead."
|
29
|
+
message = if (cp = context[:current_path]) && (cf = context[:current_field])
|
30
|
+
"`#{cf.path}` returned `#{value.inspect}` at `#{cp.join(".")}`#{fix_message}"
|
31
|
+
else
|
32
|
+
"`#{value.inspect}` was returned for `#{enum.graphql_name}`#{fix_message}"
|
33
|
+
end
|
34
|
+
super(message)
|
35
|
+
end
|
27
36
|
end
|
28
37
|
|
29
38
|
class << self
|
@@ -100,7 +109,7 @@ module GraphQL
|
|
100
109
|
if enum_value
|
101
110
|
enum_value.graphql_name
|
102
111
|
else
|
103
|
-
raise
|
112
|
+
raise self::UnresolvedValueError.new(enum: self, value: value, context: ctx)
|
104
113
|
end
|
105
114
|
end
|
106
115
|
|
@@ -11,6 +11,14 @@ module GraphQL
|
|
11
11
|
|
12
12
|
include GraphQL::Dig
|
13
13
|
|
14
|
+
# @return [GraphQL::Query::Context] The context for this query
|
15
|
+
attr_reader :context
|
16
|
+
# @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
17
|
+
attr_reader :arguments
|
18
|
+
|
19
|
+
# Ruby-like hash behaviors, read-only
|
20
|
+
def_delegators :@ruby_style_hash, :keys, :values, :each, :map, :any?, :empty?
|
21
|
+
|
14
22
|
def initialize(arguments = nil, ruby_kwargs: nil, context:, defaults_used:)
|
15
23
|
@context = context
|
16
24
|
if ruby_kwargs
|
@@ -54,19 +62,8 @@ module GraphQL
|
|
54
62
|
@maybe_lazies = maybe_lazies
|
55
63
|
end
|
56
64
|
|
57
|
-
# @return [GraphQL::Query::Context] The context for this query
|
58
|
-
attr_reader :context
|
59
|
-
|
60
|
-
# @return [GraphQL::Query::Arguments, GraphQL::Execution::Interpereter::Arguments] The underlying arguments instance
|
61
|
-
attr_reader :arguments
|
62
|
-
|
63
|
-
# Ruby-like hash behaviors, read-only
|
64
|
-
def_delegators :@ruby_style_hash, :keys, :values, :each, :map, :any?, :empty?
|
65
|
-
|
66
65
|
def to_h
|
67
|
-
@ruby_style_hash
|
68
|
-
h.merge(key => unwrap_value(value))
|
69
|
-
end
|
66
|
+
unwrap_value(@ruby_style_hash)
|
70
67
|
end
|
71
68
|
|
72
69
|
def to_hash
|
@@ -91,8 +88,8 @@ module GraphQL
|
|
91
88
|
when Array
|
92
89
|
value.map { |item| unwrap_value(item) }
|
93
90
|
when Hash
|
94
|
-
value.
|
95
|
-
h.merge(key => unwrap_value(value))
|
91
|
+
value.reduce({}) do |h, (key, value)|
|
92
|
+
h.merge!(key => unwrap_value(value))
|
96
93
|
end
|
97
94
|
when InputObject
|
98
95
|
value.to_h
|
@@ -162,7 +159,6 @@ module GraphQL
|
|
162
159
|
# @api private
|
163
160
|
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object responding to `to_h` or `to_unsafe_h`."
|
164
161
|
|
165
|
-
|
166
162
|
def validate_non_null_input(input, ctx)
|
167
163
|
result = GraphQL::Query::InputValidationResult.new
|
168
164
|
|
@@ -4,37 +4,32 @@ module GraphQL
|
|
4
4
|
# Used to convert your {GraphQL::Schema} to a GraphQL schema string
|
5
5
|
#
|
6
6
|
# @example print your schema to standard output (via helper)
|
7
|
-
# MySchema = GraphQL::Schema.define(query: QueryType)
|
8
7
|
# puts GraphQL::Schema::Printer.print_schema(MySchema)
|
9
8
|
#
|
10
9
|
# @example print your schema to standard output
|
11
|
-
# MySchema = GraphQL::Schema.define(query: QueryType)
|
12
10
|
# puts GraphQL::Schema::Printer.new(MySchema).print_schema
|
13
11
|
#
|
14
12
|
# @example print a single type to standard output
|
15
|
-
#
|
16
|
-
# name "Query"
|
13
|
+
# class Types::Query < GraphQL::Schema::Object
|
17
14
|
# description "The query root of this schema"
|
18
15
|
#
|
19
|
-
# field :post
|
20
|
-
# type post_type
|
21
|
-
# resolve ->(obj, args, ctx) { Post.find(args["id"]) }
|
22
|
-
# end
|
16
|
+
# field :post, Types::Post, null: true
|
23
17
|
# end
|
24
18
|
#
|
25
|
-
#
|
26
|
-
# name "Post"
|
19
|
+
# class Types::Post < GraphQL::Schema::Object
|
27
20
|
# description "A blog post"
|
28
21
|
#
|
29
|
-
# field :id,
|
30
|
-
# field :title,
|
31
|
-
# field :body,
|
22
|
+
# field :id, ID, null: false
|
23
|
+
# field :title, String, null: false
|
24
|
+
# field :body, String, null: false
|
32
25
|
# end
|
33
26
|
#
|
34
|
-
# MySchema
|
27
|
+
# class MySchema < GraphQL::Schema
|
28
|
+
# query(Types::Query)
|
29
|
+
# end
|
35
30
|
#
|
36
31
|
# printer = GraphQL::Schema::Printer.new(MySchema)
|
37
|
-
# puts printer.print_type(
|
32
|
+
# puts printer.print_type(Types::Post)
|
38
33
|
#
|
39
34
|
class Printer < GraphQL::Language::Printer
|
40
35
|
attr_reader :schema, :warden
|
@@ -87,7 +82,7 @@ module GraphQL
|
|
87
82
|
|
88
83
|
# Return a GraphQL schema string for the defined types in the schema
|
89
84
|
def print_schema
|
90
|
-
print(@document)
|
85
|
+
print(@document) + "\n"
|
91
86
|
end
|
92
87
|
|
93
88
|
def print_type(type)
|
@@ -307,10 +307,15 @@ module GraphQL
|
|
307
307
|
arguments: arguments,
|
308
308
|
null: null,
|
309
309
|
complexity: complexity,
|
310
|
-
extensions: extensions,
|
311
310
|
broadcastable: broadcastable?,
|
312
311
|
}
|
313
312
|
|
313
|
+
# If there aren't any, then the returned array is `[].freeze`,
|
314
|
+
# but passing that along breaks some user code.
|
315
|
+
if (exts = extensions).any?
|
316
|
+
field_opts[:extensions] = exts
|
317
|
+
end
|
318
|
+
|
314
319
|
if has_max_page_size?
|
315
320
|
field_opts[:max_page_size] = max_page_size
|
316
321
|
end
|
@@ -116,6 +116,26 @@ module GraphQL
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
+
# This is called during initial subscription to get a "name" for this subscription.
|
120
|
+
# Later, when `.trigger` is called, this will be called again to build another "name".
|
121
|
+
# Any subscribers with matching topic will begin the update flow.
|
122
|
+
#
|
123
|
+
# The default implementation creates a string using the field name, subscription scope, and argument keys and values.
|
124
|
+
# In that implementation, only `.trigger` calls with _exact matches_ result in updates to subscribers.
|
125
|
+
#
|
126
|
+
# To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope.
|
127
|
+
# Then, implement {#update} to compare its arguments to the current `object` and return `:no_update` when an
|
128
|
+
# update should be filtered out.
|
129
|
+
#
|
130
|
+
# @see {#update} for how to skip updates when an event comes with a matching topic.
|
131
|
+
# @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings)
|
132
|
+
# @param field [GraphQL::Schema::Field]
|
133
|
+
# @param scope [Object, nil] A value corresponding to `.trigger(... scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions).
|
134
|
+
# @return [String] An identifier corresponding to a stream of updates
|
135
|
+
def self.topic_for(arguments:, field:, scope:)
|
136
|
+
Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
|
137
|
+
end
|
138
|
+
|
119
139
|
# Overriding Resolver#field_options to include subscription_scope
|
120
140
|
def self.field_options
|
121
141
|
super.merge(
|
data/lib/graphql/schema.rb
CHANGED
@@ -1631,6 +1631,14 @@ module GraphQL
|
|
1631
1631
|
find_inherited_value(:multiplex_analyzers, EMPTY_ARRAY) + own_multiplex_analyzers
|
1632
1632
|
end
|
1633
1633
|
|
1634
|
+
def sanitized_printer(new_sanitized_printer = nil)
|
1635
|
+
if new_sanitized_printer
|
1636
|
+
@own_sanitized_printer = new_sanitized_printer
|
1637
|
+
else
|
1638
|
+
@own_sanitized_printer || GraphQL::Language::SanitizedPrinter
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
|
1634
1642
|
# Execute a query on itself.
|
1635
1643
|
# @see {Query#initialize} for arguments.
|
1636
1644
|
# @return [Hash] query result, ready to be serialized as JSON
|
@@ -95,6 +95,14 @@ module GraphQL
|
|
95
95
|
@action_cable = action_cable
|
96
96
|
@action_cable_coder = action_cable_coder
|
97
97
|
@serializer = serializer
|
98
|
+
@serialize_with_context = case @serializer.method(:load).arity
|
99
|
+
when 1
|
100
|
+
false
|
101
|
+
when 2
|
102
|
+
true
|
103
|
+
else
|
104
|
+
raise ArgumentError, "#{@serializer} must repond to `.load` accepting one or two arguments"
|
105
|
+
end
|
98
106
|
@transmit_ns = namespace
|
99
107
|
super
|
100
108
|
end
|
@@ -154,7 +162,7 @@ module GraphQL
|
|
154
162
|
# so just run it once, then deliver the result to every subscriber
|
155
163
|
first_event = events.first
|
156
164
|
first_subscription_id = first_event.context.fetch(:subscription_id)
|
157
|
-
object ||=
|
165
|
+
object ||= load_action_cable_message(message, first_event.context)
|
158
166
|
result = execute_update(first_subscription_id, first_event, object)
|
159
167
|
# Having calculated the result _once_, send the same payload to all subscribers
|
160
168
|
events.each do |event|
|
@@ -167,6 +175,18 @@ module GraphQL
|
|
167
175
|
end
|
168
176
|
end
|
169
177
|
|
178
|
+
# This is called to turn an ActionCable-broadcasted string (JSON)
|
179
|
+
# into a query-ready application object.
|
180
|
+
# @param message [String] n ActionCable-broadcasted string (JSON)
|
181
|
+
# @param context [GraphQL::Query::Context] the context of the first event for a given subscription fingerprint
|
182
|
+
def load_action_cable_message(message, context)
|
183
|
+
if @serialize_with_context
|
184
|
+
@serializer.load(message, context)
|
185
|
+
else
|
186
|
+
@serializer.load(message)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
170
190
|
# Return the query from "storage" (in memory)
|
171
191
|
def read_subscription(subscription_id)
|
172
192
|
query = @subscriptions[subscription_id]
|
@@ -29,26 +29,10 @@ module GraphQL
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# @return [String] an identifier for this unit of subscription
|
32
|
-
def self.serialize(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
when Hash
|
37
|
-
if field.is_a?(GraphQL::Schema::Field)
|
38
|
-
stringify_args(field, arguments)
|
39
|
-
else
|
40
|
-
GraphQL::Query::LiteralInput.from_arguments(
|
41
|
-
arguments,
|
42
|
-
field,
|
43
|
-
nil,
|
44
|
-
)
|
45
|
-
end
|
46
|
-
else
|
47
|
-
raise ArgumentError, "Unexpected arguments: #{arguments}, must be Hash or GraphQL::Arguments"
|
48
|
-
end
|
49
|
-
|
50
|
-
sorted_h = stringify_args(field, normalized_args.to_h)
|
51
|
-
Serialize.dump_recursive([scope, name, sorted_h])
|
32
|
+
def self.serialize(_name, arguments, field, scope:)
|
33
|
+
subscription = field.resolver || GraphQL::Schema::Subscription
|
34
|
+
normalized_args = stringify_args(field, arguments.to_h)
|
35
|
+
subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
|
52
36
|
end
|
53
37
|
|
54
38
|
# @return [String] a logical identifier for this event. (Stable when the query is broadcastable.)
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
description "Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string."
|
7
7
|
|
8
8
|
def self.coerce_input(value, _ctx)
|
9
|
-
value &&
|
9
|
+
value && parse_int(value)
|
10
10
|
rescue ArgumentError
|
11
11
|
nil
|
12
12
|
end
|
@@ -14,6 +14,10 @@ module GraphQL
|
|
14
14
|
def self.coerce_result(value, _ctx)
|
15
15
|
value.to_i.to_s
|
16
16
|
end
|
17
|
+
|
18
|
+
def self.parse_int(value)
|
19
|
+
value.is_a?(Numeric) ? value : Integer(value, 10)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module GraphQL
|
4
4
|
module Types
|
5
5
|
module Relay
|
6
|
+
# Include this module to your root Query type to get a Relay-compliant `node(id: ID!): Node` field that uses the schema's `object_from_id` hook.
|
6
7
|
module HasNodeField
|
7
8
|
def self.included(child_class)
|
8
9
|
child_class.field(**field_options, &field_block)
|
@@ -12,7 +13,6 @@ module GraphQL
|
|
12
13
|
def field_options
|
13
14
|
{
|
14
15
|
name: "node",
|
15
|
-
owner: nil,
|
16
16
|
type: GraphQL::Types::Relay::Node,
|
17
17
|
null: true,
|
18
18
|
description: "Fetches an object given its ID.",
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module GraphQL
|
4
4
|
module Types
|
5
5
|
module Relay
|
6
|
+
# Include this module to your root Query type to get a Relay-style `nodes(id: ID!): [Node]` field that uses the schema's `object_from_id` hook.
|
6
7
|
module HasNodesField
|
7
8
|
def self.included(child_class)
|
8
9
|
child_class.field(**field_options, &field_block)
|
@@ -12,7 +13,6 @@ module GraphQL
|
|
12
13
|
def field_options
|
13
14
|
{
|
14
15
|
name: "nodes",
|
15
|
-
owner: nil,
|
16
16
|
type: [GraphQL::Types::Relay::Node, null: true],
|
17
17
|
null: false,
|
18
18
|
description: "Fetches a list of objects given a list of IDs.",
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
# or use it for inspiration for your own field definition.
|
7
7
|
#
|
8
8
|
# @example Adding this field directly
|
9
|
-
#
|
9
|
+
# include GraphQL::Types::Relay::HasNodeField
|
10
10
|
#
|
11
11
|
# @example Implementing a similar field in your own Query root
|
12
12
|
#
|
@@ -19,7 +19,7 @@ module GraphQL
|
|
19
19
|
# context.schema.object_from_id(id, context)
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
NodeField = GraphQL::Schema::Field.new(**HasNodeField.field_options, &HasNodeField.field_block)
|
22
|
+
NodeField = GraphQL::Schema::Field.new(owner: nil, **HasNodeField.field_options, &HasNodeField.field_block)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -6,7 +6,7 @@ module GraphQL
|
|
6
6
|
# or use it for inspiration for your own field definition.
|
7
7
|
#
|
8
8
|
# @example Adding this field directly
|
9
|
-
#
|
9
|
+
# include GraphQL::Types::Relay::HasNodesField
|
10
10
|
#
|
11
11
|
# @example Implementing a similar field in your own Query root
|
12
12
|
#
|
@@ -21,7 +21,7 @@ module GraphQL
|
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
#
|
24
|
-
NodesField = GraphQL::Schema::Field.new(**HasNodesField.field_options, &HasNodesField.field_block)
|
24
|
+
NodesField = GraphQL::Schema::Field.new(owner: nil, **HasNodesField.field_options, &HasNodesField.field_block)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -57,22 +57,26 @@ module GraphQL
|
|
57
57
|
end
|
58
58
|
|
59
59
|
# Support Ruby 2.2 by implementing `-"str"`. If we drop 2.2 support, we can remove this backport.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
if !String.method_defined?(:-@)
|
61
|
+
module StringDedupBackport
|
62
|
+
refine String do
|
63
|
+
def -@
|
64
|
+
if frozen?
|
65
|
+
self
|
66
|
+
else
|
67
|
+
self.dup.freeze
|
68
|
+
end
|
67
69
|
end
|
68
70
|
end
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
if !String.method_defined?(:match?)
|
75
|
+
module StringMatchBackport
|
76
|
+
refine String do
|
77
|
+
def match?(pattern)
|
78
|
+
self =~ pattern
|
79
|
+
end
|
76
80
|
end
|
77
81
|
end
|
78
82
|
end
|
data/readme.md
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
[![CI Suite](https://github.com/rmosolgo/graphql-ruby/actions/workflows/ci.yaml/badge.svg)](https://github.com/rmosolgo/graphql-ruby/actions/workflows/ci.yaml)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/graphql.svg)](https://rubygems.org/gems/graphql)
|
5
|
-
[![Code Climate](https://codeclimate.com/github/rmosolgo/graphql-ruby/badges/gpa.svg)](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
6
|
-
[![Test Coverage](https://codeclimate.com/github/rmosolgo/graphql-ruby/badges/coverage.svg)](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
7
|
-
[![built with love](https://cloud.githubusercontent.com/assets/2231765/6766607/d07992c6-cfc9-11e4-813f-d9240714dd50.png)](https://rmosolgo.github.io/react-badges/)
|
8
5
|
|
9
6
|
A Ruby implementation of [GraphQL](https://graphql.org/).
|
10
7
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.12.
|
4
|
+
version: 1.12.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: codeclimate-test-reporter
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.4'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.4'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: concurrent-ruby
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,20 +136,6 @@ dependencies:
|
|
150
136
|
- - '='
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '0.68'
|
153
|
-
- !ruby/object:Gem::Dependency
|
154
|
-
name: stackprof
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
156
|
-
requirements:
|
157
|
-
- - ">="
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: '0'
|
160
|
-
type: :development
|
161
|
-
prerelease: false
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
163
|
-
requirements:
|
164
|
-
- - ">="
|
165
|
-
- !ruby/object:Gem::Version
|
166
|
-
version: '0'
|
167
139
|
- !ruby/object:Gem::Dependency
|
168
140
|
name: parser
|
169
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -713,7 +685,7 @@ metadata:
|
|
713
685
|
source_code_uri: https://github.com/rmosolgo/graphql-ruby
|
714
686
|
bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
|
715
687
|
mailing_list_uri: https://tinyletter.com/graphql-ruby
|
716
|
-
post_install_message:
|
688
|
+
post_install_message:
|
717
689
|
rdoc_options: []
|
718
690
|
require_paths:
|
719
691
|
- lib
|
@@ -728,8 +700,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
728
700
|
- !ruby/object:Gem::Version
|
729
701
|
version: '0'
|
730
702
|
requirements: []
|
731
|
-
rubygems_version: 3.
|
732
|
-
signing_key:
|
703
|
+
rubygems_version: 3.2.15
|
704
|
+
signing_key:
|
733
705
|
specification_version: 4
|
734
706
|
summary: A GraphQL language and runtime for Ruby
|
735
707
|
test_files: []
|