graphql 2.3.0 → 2.3.1
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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/graphql/analysis/ast/field_usage.rb +7 -5
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/language/lexer.rb +19 -2
- data/lib/graphql/language/parser.rb +14 -4
- data/lib/graphql/language.rb +23 -0
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/schema/argument.rb +1 -0
- data/lib/graphql/schema/build_from_definition.rb +6 -0
- data/lib/graphql/schema/input_object.rb +1 -2
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/resolver.rb +10 -5
- data/lib/graphql/schema.rb +11 -0
- data/lib/graphql/testing/helpers.rb +24 -2
- data/lib/graphql/tracing/prometheus_trace.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +9 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 566d6d5c49b331b3f38e2f4d338c635bae02a86b14a004ff55f1eccccb973181
|
4
|
+
data.tar.gz: 0a8a048f8644e933252ca30459386e2049ac8c3093731709d344bf898f884731
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12136553e963ed98012887215d1f21efd31c2a3bacd40ada6836ca3884680cb4ac6a8c7a1fabaa7fc8699c0ba6db9f20418ae068a74694daef8db1d13e506933
|
7
|
+
data.tar.gz: 1faab9e89cf122660fb277df551ba026685cefeaa2fba9d83b590a5a18d4c4dc1202712ecf404c2998eb12c27a1219bd548944ef5f65daaad79371163ca66b43
|
@@ -26,6 +26,9 @@ class <%= schema_name %> < GraphQL::Schema
|
|
26
26
|
raise(GraphQL::RequiredImplementationMissingError)
|
27
27
|
end
|
28
28
|
|
29
|
+
# Limit the size of incoming queries:
|
30
|
+
max_query_string_tokens(5000)
|
31
|
+
|
29
32
|
# Stop validating when it encounters this many errors:
|
30
33
|
validate_max_errors(100)
|
31
34
|
end
|
@@ -41,7 +41,9 @@ module GraphQL
|
|
41
41
|
@used_deprecated_arguments << argument.definition.path
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
arg_val = argument.value
|
45
|
+
|
46
|
+
next if arg_val.nil?
|
45
47
|
|
46
48
|
argument_type = argument.definition.type
|
47
49
|
if argument_type.non_null?
|
@@ -49,18 +51,18 @@ module GraphQL
|
|
49
51
|
end
|
50
52
|
|
51
53
|
if argument_type.kind.input_object?
|
52
|
-
extract_deprecated_arguments(argument.
|
54
|
+
extract_deprecated_arguments(argument.original_value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
53
55
|
elsif argument_type.kind.enum?
|
54
|
-
extract_deprecated_enum_value(argument_type,
|
56
|
+
extract_deprecated_enum_value(argument_type, arg_val)
|
55
57
|
elsif argument_type.list?
|
56
58
|
inner_type = argument_type.unwrap
|
57
59
|
case inner_type.kind
|
58
60
|
when TypeKinds::INPUT_OBJECT
|
59
|
-
argument.
|
61
|
+
argument.original_value.each do |value|
|
60
62
|
extract_deprecated_arguments(value.arguments.argument_values) # rubocop:disable Development/ContextIsPassedCop -- runtime args instance
|
61
63
|
end
|
62
64
|
when TypeKinds::ENUM
|
63
|
-
|
65
|
+
arg_val.each do |value|
|
64
66
|
extract_deprecated_enum_value(inner_type, value)
|
65
67
|
end
|
66
68
|
else
|
@@ -6,15 +6,19 @@ module GraphQL
|
|
6
6
|
# A container for metadata regarding arguments present in a GraphQL query.
|
7
7
|
# @see Interpreter::Arguments#argument_values for a hash of these objects.
|
8
8
|
class ArgumentValue
|
9
|
-
def initialize(definition:, value:, default_used:)
|
9
|
+
def initialize(definition:, value:, original_value:, default_used:)
|
10
10
|
@definition = definition
|
11
11
|
@value = value
|
12
|
+
@original_value = original_value
|
12
13
|
@default_used = default_used
|
13
14
|
end
|
14
15
|
|
15
16
|
# @return [Object] The Ruby-ready value for this Argument
|
16
17
|
attr_reader :value
|
17
18
|
|
19
|
+
# @return [Object] The value of this argument _before_ `prepare` is applied.
|
20
|
+
attr_reader :original_value
|
21
|
+
|
18
22
|
# @return [GraphQL::Schema::Argument] The definition instance for this argument
|
19
23
|
attr_reader :definition
|
20
24
|
|
@@ -3,7 +3,7 @@ module GraphQL
|
|
3
3
|
module Language
|
4
4
|
|
5
5
|
class Lexer
|
6
|
-
def initialize(graphql_str, filename: nil)
|
6
|
+
def initialize(graphql_str, filename: nil, max_tokens: nil)
|
7
7
|
if !(graphql_str.encoding == Encoding::UTF_8 || graphql_str.ascii_only?)
|
8
8
|
graphql_str = graphql_str.dup.force_encoding(Encoding::UTF_8)
|
9
9
|
end
|
@@ -11,6 +11,8 @@ module GraphQL
|
|
11
11
|
@filename = filename
|
12
12
|
@scanner = StringScanner.new(graphql_str)
|
13
13
|
@pos = nil
|
14
|
+
@max_tokens = max_tokens || Float::INFINITY
|
15
|
+
@tokens_count = 0
|
14
16
|
end
|
15
17
|
|
16
18
|
def eos?
|
@@ -22,6 +24,10 @@ module GraphQL
|
|
22
24
|
def advance
|
23
25
|
@scanner.skip(IGNORE_REGEXP)
|
24
26
|
return false if @scanner.eos?
|
27
|
+
@tokens_count += 1
|
28
|
+
if @tokens_count > @max_tokens
|
29
|
+
raise_parse_error("This query is too large to execute.")
|
30
|
+
end
|
25
31
|
@pos = @scanner.pos
|
26
32
|
next_byte = @string.getbyte(@pos)
|
27
33
|
next_byte_is_for = FIRST_BYTES[next_byte]
|
@@ -52,6 +58,17 @@ module GraphQL
|
|
52
58
|
:IDENTIFIER
|
53
59
|
when ByteFor::NUMBER
|
54
60
|
@scanner.skip(NUMERIC_REGEXP)
|
61
|
+
|
62
|
+
if GraphQL.reject_numbers_followed_by_names
|
63
|
+
new_pos = @scanner.pos
|
64
|
+
peek_byte = @string.getbyte(new_pos)
|
65
|
+
next_first_byte = FIRST_BYTES[peek_byte]
|
66
|
+
if next_first_byte == ByteFor::NAME || next_first_byte == ByteFor::IDENTIFIER
|
67
|
+
number_part = token_value
|
68
|
+
name_part = @scanner.scan(IDENTIFIER_REGEXP)
|
69
|
+
raise_parse_error("Name after number is not allowed (in `#{number_part}#{name_part}`)")
|
70
|
+
end
|
71
|
+
end
|
55
72
|
# Check for a matched decimal:
|
56
73
|
@scanner[1] ? :FLOAT : :INT
|
57
74
|
when ByteFor::ELLIPSIS
|
@@ -156,6 +173,7 @@ module GraphQL
|
|
156
173
|
INT_REGEXP = /-?(?:[0]|[1-9][0-9]*)/
|
157
174
|
FLOAT_DECIMAL_REGEXP = /[.][0-9]+/
|
158
175
|
FLOAT_EXP_REGEXP = /[eE][+-]?[0-9]+/
|
176
|
+
# TODO: FLOAT_EXP_REGEXP should not be allowed to follow INT_REGEXP, integers are not allowed to have exponent parts.
|
159
177
|
NUMERIC_REGEXP = /#{INT_REGEXP}(#{FLOAT_DECIMAL_REGEXP}#{FLOAT_EXP_REGEXP}|#{FLOAT_DECIMAL_REGEXP}|#{FLOAT_EXP_REGEXP})?/
|
160
178
|
|
161
179
|
KEYWORDS = [
|
@@ -250,7 +268,6 @@ module GraphQL
|
|
250
268
|
FOUR_DIGIT_UNICODE = /#{UNICODE_DIGIT}{4}/
|
251
269
|
N_DIGIT_UNICODE = %r{#{Punctuation::LCURLY}#{UNICODE_DIGIT}{4,}#{Punctuation::RCURLY}}x
|
252
270
|
UNICODE_ESCAPE = %r{\\u(?:#{FOUR_DIGIT_UNICODE}|#{N_DIGIT_UNICODE})}
|
253
|
-
# # https://graphql.github.io/graphql-spec/June2018/#sec-String-Value
|
254
271
|
STRING_ESCAPE = %r{[\\][\\/bfnrt]}
|
255
272
|
BLOCK_QUOTE = '"""'
|
256
273
|
ESCAPED_QUOTE = /\\"/;
|
@@ -12,8 +12,8 @@ module GraphQL
|
|
12
12
|
class << self
|
13
13
|
attr_accessor :cache
|
14
14
|
|
15
|
-
def parse(graphql_str, filename: nil, trace: Tracing::NullTrace)
|
16
|
-
self.new(graphql_str, filename: filename, trace: trace).parse
|
15
|
+
def parse(graphql_str, filename: nil, trace: Tracing::NullTrace, max_tokens: nil)
|
16
|
+
self.new(graphql_str, filename: filename, trace: trace, max_tokens: max_tokens).parse
|
17
17
|
end
|
18
18
|
|
19
19
|
def parse_file(filename, trace: Tracing::NullTrace)
|
@@ -27,14 +27,15 @@ module GraphQL
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def initialize(graphql_str, filename: nil, trace: Tracing::NullTrace)
|
30
|
+
def initialize(graphql_str, filename: nil, trace: Tracing::NullTrace, max_tokens: nil)
|
31
31
|
if graphql_str.nil?
|
32
32
|
raise GraphQL::ParseError.new("No query string was present", nil, nil, nil)
|
33
33
|
end
|
34
|
-
@lexer = Lexer.new(graphql_str, filename: filename)
|
34
|
+
@lexer = Lexer.new(graphql_str, filename: filename, max_tokens: max_tokens)
|
35
35
|
@graphql_str = graphql_str
|
36
36
|
@filename = filename
|
37
37
|
@trace = trace
|
38
|
+
@dedup_identifiers = false
|
38
39
|
end
|
39
40
|
|
40
41
|
def parse
|
@@ -732,6 +733,9 @@ module GraphQL
|
|
732
733
|
# Only use when we care about the expected token's value
|
733
734
|
def expect_token_value(tok)
|
734
735
|
token_value = @lexer.token_value
|
736
|
+
if @dedup_identifiers
|
737
|
+
token_value = -token_value
|
738
|
+
end
|
735
739
|
expect_token(tok)
|
736
740
|
token_value
|
737
741
|
end
|
@@ -741,6 +745,12 @@ module GraphQL
|
|
741
745
|
def debug_token_value
|
742
746
|
@lexer.debug_token_value(token_name)
|
743
747
|
end
|
748
|
+
class SchemaParser < Parser
|
749
|
+
def initialize(*args, **kwargs)
|
750
|
+
super
|
751
|
+
@dedup_identifiers = true
|
752
|
+
end
|
753
|
+
end
|
744
754
|
end
|
745
755
|
end
|
746
756
|
end
|
data/lib/graphql/language.rb
CHANGED
@@ -33,6 +33,12 @@ module GraphQL
|
|
33
33
|
else
|
34
34
|
JSON.generate(value, quirks_mode: true)
|
35
35
|
end
|
36
|
+
rescue JSON::GeneratorError
|
37
|
+
if Float::INFINITY == value
|
38
|
+
"Infinity"
|
39
|
+
else
|
40
|
+
raise
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
# Returns a new string if any single-quoted newlines were escaped.
|
@@ -70,5 +76,22 @@ module GraphQL
|
|
70
76
|
end
|
71
77
|
new_query_str || query_str
|
72
78
|
end
|
79
|
+
|
80
|
+
INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP = %r{
|
81
|
+
(
|
82
|
+
((?<num>#{Lexer::INT_REGEXP}(#{Lexer::FLOAT_EXP_REGEXP})?)(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
|
83
|
+
|
|
84
|
+
((?<num>#{Lexer::INT_REGEXP}#{Lexer::FLOAT_DECIMAL_REGEXP}#{Lexer::FLOAT_EXP_REGEXP})(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
|
85
|
+
|
|
86
|
+
((?<num>#{Lexer::INT_REGEXP}#{Lexer::FLOAT_DECIMAL_REGEXP})(?<name>#{Lexer::IDENTIFIER_REGEXP})#{Lexer::IGNORE_REGEXP}:)
|
87
|
+
)}x
|
88
|
+
|
89
|
+
def self.add_space_between_numbers_and_names(query_str)
|
90
|
+
if query_str.match?(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP)
|
91
|
+
query_str.gsub(INVALID_NUMBER_FOLLOWED_BY_NAME_REGEXP, "\\k<num> \\k<name>:")
|
92
|
+
else
|
93
|
+
query_str
|
94
|
+
end
|
95
|
+
end
|
73
96
|
end
|
74
97
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -395,7 +395,7 @@ module GraphQL
|
|
395
395
|
parse_error = nil
|
396
396
|
@document ||= begin
|
397
397
|
if query_string
|
398
|
-
GraphQL.parse(query_string, trace: self.current_trace)
|
398
|
+
GraphQL.parse(query_string, trace: self.current_trace, max_tokens: @schema.max_query_string_tokens)
|
399
399
|
end
|
400
400
|
rescue GraphQL::ParseError => err
|
401
401
|
parse_error = err
|
@@ -290,6 +290,7 @@ module GraphQL
|
|
290
290
|
# TODO code smell to access such a deeply-nested constant in a distant module
|
291
291
|
argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
|
292
292
|
value: resolved_loaded_value,
|
293
|
+
original_value: resolved_coerced_value,
|
293
294
|
definition: self,
|
294
295
|
default_used: default_used,
|
295
296
|
)
|
@@ -7,10 +7,16 @@ module GraphQL
|
|
7
7
|
class << self
|
8
8
|
# @see {Schema.from_definition}
|
9
9
|
def from_definition(schema_superclass, definition_string, parser: GraphQL.default_parser, **kwargs)
|
10
|
+
if defined?(parser::SchemaParser)
|
11
|
+
parser = parser::SchemaParser
|
12
|
+
end
|
10
13
|
from_document(schema_superclass, parser.parse(definition_string), **kwargs)
|
11
14
|
end
|
12
15
|
|
13
16
|
def from_definition_path(schema_superclass, definition_path, parser: GraphQL.default_parser, **kwargs)
|
17
|
+
if defined?(parser::SchemaParser)
|
18
|
+
parser = parser::SchemaParser
|
19
|
+
end
|
14
20
|
from_document(schema_superclass, parser.parse_file(definition_path), **kwargs)
|
15
21
|
end
|
16
22
|
|
@@ -215,8 +215,7 @@ module GraphQL
|
|
215
215
|
if resolved_arguments.is_a?(GraphQL::Error)
|
216
216
|
raise resolved_arguments
|
217
217
|
else
|
218
|
-
|
219
|
-
input_obj_instance.prepare
|
218
|
+
self.new(resolved_arguments, ruby_kwargs: resolved_arguments.keyword_arguments, context: ctx, defaults_used: nil)
|
220
219
|
end
|
221
220
|
end
|
222
221
|
end
|
@@ -62,6 +62,13 @@ module GraphQL
|
|
62
62
|
extend GraphQL::Schema::Member::HasFields
|
63
63
|
extend GraphQL::Schema::Resolver::HasPayloadType
|
64
64
|
|
65
|
+
# @api private
|
66
|
+
def call_resolve(_args_hash)
|
67
|
+
# Clear any cached values from `loads` or authorization:
|
68
|
+
dataloader.clear_cache
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
65
72
|
class << self
|
66
73
|
def visible?(context)
|
67
74
|
true
|
@@ -103,11 +103,7 @@ module GraphQL
|
|
103
103
|
end
|
104
104
|
elsif authorized_val
|
105
105
|
# Finally, all the hooks have passed, so resolve it
|
106
|
-
|
107
|
-
public_send(self.class.resolve_method, **loaded_args)
|
108
|
-
else
|
109
|
-
public_send(self.class.resolve_method)
|
110
|
-
end
|
106
|
+
call_resolve(loaded_args)
|
111
107
|
else
|
112
108
|
raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
|
113
109
|
end
|
@@ -117,6 +113,15 @@ module GraphQL
|
|
117
113
|
end
|
118
114
|
end
|
119
115
|
|
116
|
+
# @api private {GraphQL::Schema::Mutation} uses this to clear the dataloader cache
|
117
|
+
def call_resolve(args_hash)
|
118
|
+
if args_hash.any?
|
119
|
+
public_send(self.class.resolve_method, **args_hash)
|
120
|
+
else
|
121
|
+
public_send(self.class.resolve_method)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
120
125
|
# Do the work. Everything happens here.
|
121
126
|
# @return [Object] An object corresponding to the return type
|
122
127
|
def resolve(**args)
|
data/lib/graphql/schema.rb
CHANGED
@@ -643,6 +643,17 @@ module GraphQL
|
|
643
643
|
end
|
644
644
|
end
|
645
645
|
|
646
|
+
# A limit on the number of tokens to accept on incoming query strings.
|
647
|
+
# Use this to prevent parsing maliciously-large query strings.
|
648
|
+
# @return [nil, Integer]
|
649
|
+
def max_query_string_tokens(new_max_tokens = NOT_CONFIGURED)
|
650
|
+
if NOT_CONFIGURED.equal?(new_max_tokens)
|
651
|
+
defined?(@max_query_string_tokens) ? @max_query_string_tokens : find_inherited_value(:max_query_string_tokens)
|
652
|
+
else
|
653
|
+
@max_query_string_tokens = new_max_tokens
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
646
657
|
def default_page_size(new_default_page_size = nil)
|
647
658
|
if new_default_page_size
|
648
659
|
@default_page_size = new_default_page_size
|
@@ -39,9 +39,9 @@ module GraphQL
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def run_graphql_field(schema, field_path, object, arguments: {}, context: {})
|
42
|
+
def run_graphql_field(schema, field_path, object, arguments: {}, context: {}, ast_node: nil, lookahead: nil)
|
43
43
|
type_name, *field_names = field_path.split(".")
|
44
|
-
dummy_query = GraphQL::Query.new(schema, context: context)
|
44
|
+
dummy_query = GraphQL::Query.new(schema, "{ __typename }", context: context)
|
45
45
|
query_context = dummy_query.context
|
46
46
|
object_type = dummy_query.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
|
47
47
|
if object_type
|
@@ -57,6 +57,28 @@ module GraphQL
|
|
57
57
|
dummy_query.context.dataloader.run_isolated {
|
58
58
|
field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
|
59
59
|
field_args = schema.sync_lazy(field_args)
|
60
|
+
if visible_field.extras.any?
|
61
|
+
extra_args = {}
|
62
|
+
visible_field.extras.each do |extra|
|
63
|
+
extra_args[extra] = case extra
|
64
|
+
when :ast_node
|
65
|
+
ast_node ||= GraphQL::Language::Nodes::Field.new(name: visible_field.graphql_name)
|
66
|
+
when :lookahead
|
67
|
+
lookahead ||= begin
|
68
|
+
ast_node ||= GraphQL::Language::Nodes::Field.new(name: visible_field.graphql_name)
|
69
|
+
Execution::Lookahead.new(
|
70
|
+
query: dummy_query,
|
71
|
+
ast_nodes: [ast_node],
|
72
|
+
field: visible_field,
|
73
|
+
)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
raise ArgumentError, "This extra isn't supported in `run_graphql_field` yet: `#{extra.inspect}`. Open an issue on GitHub to request it: https://github.com/rmosolgo/graphql-ruby/issues/new"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
field_args = field_args.merge_extras(extra_args)
|
81
|
+
end
|
60
82
|
graphql_result = visible_field.resolve(graphql_result, field_args.keyword_arguments, query_context)
|
61
83
|
graphql_result = schema.sync_lazy(graphql_result)
|
62
84
|
}
|
@@ -24,8 +24,8 @@ module GraphQL
|
|
24
24
|
'execute_query_lazy' => "graphql.execute",
|
25
25
|
}.each do |trace_method, platform_key|
|
26
26
|
module_eval <<-RUBY, __FILE__, __LINE__
|
27
|
-
def #{trace_method}(**data
|
28
|
-
instrument_execution("#{platform_key}", "#{trace_method}"
|
27
|
+
def #{trace_method}(**data)
|
28
|
+
instrument_execution("#{platform_key}", "#{trace_method}") { super }
|
29
29
|
end
|
30
30
|
RUBY
|
31
31
|
end
|
data/lib/graphql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -42,8 +42,8 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
|
|
42
42
|
# Turn a query string or schema definition into an AST
|
43
43
|
# @param graphql_string [String] a GraphQL query string or schema definition
|
44
44
|
# @return [GraphQL::Language::Nodes::Document]
|
45
|
-
def self.parse(graphql_string, trace: GraphQL::Tracing::NullTrace, filename: nil)
|
46
|
-
default_parser.parse(graphql_string, trace: trace, filename: filename)
|
45
|
+
def self.parse(graphql_string, trace: GraphQL::Tracing::NullTrace, filename: nil, max_tokens: nil)
|
46
|
+
default_parser.parse(graphql_string, trace: trace, filename: filename, max_tokens: max_tokens)
|
47
47
|
end
|
48
48
|
|
49
49
|
# Read the contents of `filename` and parse them as GraphQL
|
@@ -74,6 +74,13 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
|
|
74
74
|
EMPTY_HASH = {}.freeze
|
75
75
|
EMPTY_ARRAY = [].freeze
|
76
76
|
end
|
77
|
+
|
78
|
+
class << self
|
79
|
+
# If true, the parser should raise when an integer or float is followed immediately by an identifier (instead of a space or punctuation)
|
80
|
+
attr_accessor :reject_numbers_followed_by_names
|
81
|
+
end
|
82
|
+
|
83
|
+
self.reject_numbers_followed_by_names = false
|
77
84
|
end
|
78
85
|
|
79
86
|
# Order matters for these:
|
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: 2.3.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|