graphql 2.2.14 → 2.3.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.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/visitor.rb +8 -0
- data/lib/graphql/backtrace/inspect_result.rb +0 -12
- data/lib/graphql/language/document_from_schema_definition.rb +1 -1
- data/lib/graphql/language/lexer.rb +27 -28
- data/lib/graphql/language.rb +37 -0
- data/lib/graphql/query/context.rb +30 -33
- data/lib/graphql/query.rb +1 -1
- data/lib/graphql/schema/build_from_definition.rb +3 -1
- data/lib/graphql/schema/loader.rb +2 -1
- data/lib/graphql/schema.rb +16 -1
- data/lib/graphql/tracing/platform_tracing.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- 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: 881a55a1017c82563e75cf9898d44be453c1329c849f60b9538fdbd0f0d4b630
|
4
|
+
data.tar.gz: e99efcbffe7cab713e9d5fa7156c1f3bb56752b10ae35f9c5b23e705a27f90da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c82107ac040dd40a8bfcf09f0abf23d5a4a40ef8ed68b3e6ff0918e3b4ff02c6ae7f9637fed578bbd78032bde8d61622b65ab8efeb3bd4e2538fc809e626a92a
|
7
|
+
data.tar.gz: e0eddc7d0562f9637ecb1707d690b7d4579373c6d8f030e09565a150a60c4272ebb4e5f06cefc5165f6babfde01e5fb8930b4f678d6c1e146df56999634cbc1f
|
@@ -118,8 +118,12 @@ module GraphQL
|
|
118
118
|
def on_inline_fragment(node, parent)
|
119
119
|
on_fragment_with_type(node) do
|
120
120
|
@path.push("...#{node.type ? " on #{node.type.name}" : ""}")
|
121
|
+
@skipping = @skip_stack.last || skip?(node)
|
122
|
+
@skip_stack << @skipping
|
123
|
+
|
121
124
|
call_on_enter_inline_fragment(node, parent)
|
122
125
|
super
|
126
|
+
@skipping = @skip_stack.pop
|
123
127
|
call_on_leave_inline_fragment(node, parent)
|
124
128
|
end
|
125
129
|
end
|
@@ -187,9 +191,13 @@ module GraphQL
|
|
187
191
|
|
188
192
|
def on_fragment_spread(node, parent)
|
189
193
|
@path.push("... #{node.name}")
|
194
|
+
@skipping = @skip_stack.last || skip?(node)
|
195
|
+
@skip_stack << @skipping
|
196
|
+
|
190
197
|
call_on_enter_fragment_spread(node, parent)
|
191
198
|
enter_fragment_spread_inline(node)
|
192
199
|
super
|
200
|
+
@skipping = @skip_stack.pop
|
193
201
|
leave_fragment_spread_inline(node)
|
194
202
|
call_on_leave_fragment_spread(node, parent)
|
195
203
|
@path.pop
|
@@ -16,12 +16,6 @@ module GraphQL
|
|
16
16
|
"[" +
|
17
17
|
obj.map { |v| inspect_truncated(v) }.join(", ") +
|
18
18
|
"]"
|
19
|
-
when Query::Context::SharedMethods
|
20
|
-
if obj.invalid_null?
|
21
|
-
"nil"
|
22
|
-
else
|
23
|
-
inspect_truncated(obj.value)
|
24
|
-
end
|
25
19
|
else
|
26
20
|
inspect_truncated(obj)
|
27
21
|
end
|
@@ -33,12 +27,6 @@ module GraphQL
|
|
33
27
|
"{...}"
|
34
28
|
when Array
|
35
29
|
"[...]"
|
36
|
-
when Query::Context::SharedMethods
|
37
|
-
if obj.invalid_null?
|
38
|
-
"nil"
|
39
|
-
else
|
40
|
-
inspect_truncated(obj.value)
|
41
|
-
end
|
42
30
|
when GraphQL::Execution::Lazy
|
43
31
|
"(unresolved)"
|
44
32
|
else
|
@@ -24,7 +24,7 @@ module GraphQL
|
|
24
24
|
@include_built_in_directives = include_built_in_directives
|
25
25
|
@include_one_of = false
|
26
26
|
|
27
|
-
schema_context = schema.context_class.new(query: nil,
|
27
|
+
schema_context = schema.context_class.new(query: nil, schema: schema, values: context)
|
28
28
|
|
29
29
|
|
30
30
|
@warden = @schema.warden_class.new(
|
@@ -109,29 +109,27 @@ module GraphQL
|
|
109
109
|
}
|
110
110
|
UTF_8 = /\\u(?:([\dAa-f]{4})|\{([\da-f]{4,})\})(?:\\u([\dAa-f]{4}))?/i
|
111
111
|
VALID_STRING = /\A(?:[^\\]|#{ESCAPES}|#{UTF_8})*\z/o
|
112
|
+
ESCAPED = /(?:#{ESCAPES}|#{UTF_8})/o
|
112
113
|
|
113
114
|
def string_value
|
114
115
|
str = token_value
|
115
116
|
is_block = str.start_with?('"""')
|
116
117
|
if is_block
|
117
118
|
str.gsub!(/\A"""|"""\z/, '')
|
119
|
+
return Language::BlockString.trim_whitespace(str)
|
118
120
|
else
|
119
121
|
str.gsub!(/\A"|"\z/, '')
|
120
|
-
end
|
121
|
-
|
122
|
-
if is_block
|
123
|
-
str = Language::BlockString.trim_whitespace(str)
|
124
|
-
end
|
125
|
-
|
126
|
-
if !str.valid_encoding? || !str.match?(VALID_STRING)
|
127
|
-
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
128
|
-
else
|
129
|
-
Lexer.replace_escaped_characters_in_place(str)
|
130
122
|
|
131
|
-
if !str.valid_encoding?
|
123
|
+
if !str.valid_encoding? || !str.match?(VALID_STRING)
|
132
124
|
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
133
125
|
else
|
134
|
-
str
|
126
|
+
Lexer.replace_escaped_characters_in_place(str)
|
127
|
+
|
128
|
+
if !str.valid_encoding?
|
129
|
+
raise_parse_error("Bad unicode escape in #{str.inspect}")
|
130
|
+
else
|
131
|
+
str
|
132
|
+
end
|
135
133
|
end
|
136
134
|
end
|
137
135
|
end
|
@@ -256,7 +254,7 @@ module GraphQL
|
|
256
254
|
STRING_ESCAPE = %r{[\\][\\/bfnrt]}
|
257
255
|
BLOCK_QUOTE = '"""'
|
258
256
|
ESCAPED_QUOTE = /\\"/;
|
259
|
-
STRING_CHAR = /#{ESCAPED_QUOTE}|[^"
|
257
|
+
STRING_CHAR = /#{ESCAPED_QUOTE}|[^"\\\n\r]|#{UNICODE_ESCAPE}|#{STRING_ESCAPE}/
|
260
258
|
QUOTED_STRING_REGEXP = %r{#{QUOTE} (?:#{STRING_CHAR})* #{QUOTE}}x
|
261
259
|
BLOCK_STRING_REGEXP = %r{
|
262
260
|
#{BLOCK_QUOTE}
|
@@ -301,24 +299,25 @@ module GraphQL
|
|
301
299
|
# Replace any escaped unicode or whitespace with the _actual_ characters
|
302
300
|
# To avoid allocating more strings, this modifies the string passed into it
|
303
301
|
def self.replace_escaped_characters_in_place(raw_string)
|
304
|
-
raw_string.gsub!(
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
(
|
313
|
-
|
314
|
-
|
315
|
-
|
302
|
+
raw_string.gsub!(ESCAPED) do |matched_str|
|
303
|
+
if (point_str_1 = $1 || $2)
|
304
|
+
codepoint_1 = point_str_1.to_i(16)
|
305
|
+
if (codepoint_2 = $3)
|
306
|
+
codepoint_2 = codepoint_2.to_i(16)
|
307
|
+
if (codepoint_1 >= 0xD800 && codepoint_1 <= 0xDBFF) && # leading surrogate
|
308
|
+
(codepoint_2 >= 0xDC00 && codepoint_2 <= 0xDFFF) # trailing surrogate
|
309
|
+
# A surrogate pair
|
310
|
+
combined = ((codepoint_1 - 0xD800) * 0x400) + (codepoint_2 - 0xDC00) + 0x10000
|
311
|
+
[combined].pack('U'.freeze)
|
312
|
+
else
|
313
|
+
# Two separate code points
|
314
|
+
[codepoint_1].pack('U'.freeze) + [codepoint_2].pack('U'.freeze)
|
315
|
+
end
|
316
316
|
else
|
317
|
-
|
318
|
-
[codepoint_1].pack('U'.freeze) + [codepoint_2].pack('U'.freeze)
|
317
|
+
[codepoint_1].pack('U'.freeze)
|
319
318
|
end
|
320
319
|
else
|
321
|
-
[
|
320
|
+
ESCAPES_REPLACE[matched_str]
|
322
321
|
end
|
323
322
|
end
|
324
323
|
nil
|
data/lib/graphql/language.rb
CHANGED
@@ -12,6 +12,7 @@ require "graphql/language/static_visitor"
|
|
12
12
|
require "graphql/language/token"
|
13
13
|
require "graphql/language/visitor"
|
14
14
|
require "graphql/language/definition_slice"
|
15
|
+
require "strscan"
|
15
16
|
|
16
17
|
module GraphQL
|
17
18
|
module Language
|
@@ -33,5 +34,41 @@ module GraphQL
|
|
33
34
|
JSON.generate(value, quirks_mode: true)
|
34
35
|
end
|
35
36
|
end
|
37
|
+
|
38
|
+
# Returns a new string if any single-quoted newlines were escaped.
|
39
|
+
# Otherwise, returns `query_str` unchanged.
|
40
|
+
# @return [String]
|
41
|
+
def self.escape_single_quoted_newlines(query_str)
|
42
|
+
scanner = StringScanner.new(query_str)
|
43
|
+
inside_single_quoted_string = false
|
44
|
+
new_query_str = nil
|
45
|
+
while !scanner.eos?
|
46
|
+
if (match = scanner.scan(/(?:\\"|[^"\n\r]|""")+/m)) && new_query_str
|
47
|
+
new_query_str << match
|
48
|
+
elsif scanner.scan('"')
|
49
|
+
new_query_str && (new_query_str << '"')
|
50
|
+
inside_single_quoted_string = !inside_single_quoted_string
|
51
|
+
elsif scanner.scan("\n")
|
52
|
+
if inside_single_quoted_string
|
53
|
+
new_query_str ||= query_str[0, scanner.pos - 1]
|
54
|
+
new_query_str << '\\n'
|
55
|
+
else
|
56
|
+
new_query_str && (new_query_str << "\n")
|
57
|
+
end
|
58
|
+
elsif scanner.scan("\r")
|
59
|
+
if inside_single_quoted_string
|
60
|
+
new_query_str ||= query_str[0, scanner.pos - 1]
|
61
|
+
new_query_str << '\\r'
|
62
|
+
else
|
63
|
+
new_query_str && (new_query_str << "\r")
|
64
|
+
end
|
65
|
+
elsif scanner.eos?
|
66
|
+
break
|
67
|
+
else
|
68
|
+
raise ArgumentError, "Unmatchable string scanner segment: #{scanner.rest.inspect}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
new_query_str || query_str
|
72
|
+
end
|
36
73
|
end
|
37
74
|
end
|
@@ -6,36 +6,6 @@ module GraphQL
|
|
6
6
|
# Expose some query-specific info to field resolve functions.
|
7
7
|
# It delegates `[]` to the hash that's passed to `GraphQL::Query#initialize`.
|
8
8
|
class Context
|
9
|
-
module SharedMethods
|
10
|
-
# Return this value to tell the runtime
|
11
|
-
# to exclude this field from the response altogether
|
12
|
-
def skip
|
13
|
-
GraphQL::Execution::SKIP
|
14
|
-
end
|
15
|
-
|
16
|
-
# Add error at query-level.
|
17
|
-
# @param error [GraphQL::ExecutionError] an execution error
|
18
|
-
# @return [void]
|
19
|
-
def add_error(error)
|
20
|
-
if !error.is_a?(ExecutionError)
|
21
|
-
raise TypeError, "expected error to be a ExecutionError, but was #{error.class}"
|
22
|
-
end
|
23
|
-
errors << error
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
|
27
|
-
# @example Print the GraphQL backtrace during field resolution
|
28
|
-
# puts ctx.backtrace
|
29
|
-
#
|
30
|
-
# @return [GraphQL::Backtrace] The backtrace for this point in query execution
|
31
|
-
def backtrace
|
32
|
-
GraphQL::Backtrace.new(self)
|
33
|
-
end
|
34
|
-
|
35
|
-
def execution_errors
|
36
|
-
@execution_errors ||= ExecutionErrors.new(self)
|
37
|
-
end
|
38
|
-
end
|
39
9
|
|
40
10
|
class ExecutionErrors
|
41
11
|
def initialize(ctx)
|
@@ -59,7 +29,6 @@ module GraphQL
|
|
59
29
|
alias :push :add
|
60
30
|
end
|
61
31
|
|
62
|
-
include SharedMethods
|
63
32
|
extend Forwardable
|
64
33
|
|
65
34
|
# @return [Array<GraphQL::ExecutionError>] errors returned during execution
|
@@ -77,11 +46,10 @@ module GraphQL
|
|
77
46
|
# Make a new context which delegates key lookup to `values`
|
78
47
|
# @param query [GraphQL::Query] the query who owns this context
|
79
48
|
# @param values [Hash] A hash of arbitrary values which will be accessible at query-time
|
80
|
-
def initialize(query:, schema: query.schema, values
|
49
|
+
def initialize(query:, schema: query.schema, values:)
|
81
50
|
@query = query
|
82
51
|
@schema = schema
|
83
52
|
@provided_values = values || {}
|
84
|
-
@object = object
|
85
53
|
# Namespaced storage, where user-provided values are in `nil` namespace:
|
86
54
|
@storage = Hash.new { |h, k| h[k] = {} }
|
87
55
|
@storage[nil] = @provided_values
|
@@ -140,6 +108,35 @@ module GraphQL
|
|
140
108
|
end
|
141
109
|
end
|
142
110
|
|
111
|
+
# Return this value to tell the runtime
|
112
|
+
# to exclude this field from the response altogether
|
113
|
+
def skip
|
114
|
+
GraphQL::Execution::SKIP
|
115
|
+
end
|
116
|
+
|
117
|
+
# Add error at query-level.
|
118
|
+
# @param error [GraphQL::ExecutionError] an execution error
|
119
|
+
# @return [void]
|
120
|
+
def add_error(error)
|
121
|
+
if !error.is_a?(ExecutionError)
|
122
|
+
raise TypeError, "expected error to be a ExecutionError, but was #{error.class}"
|
123
|
+
end
|
124
|
+
errors << error
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
# @example Print the GraphQL backtrace during field resolution
|
129
|
+
# puts ctx.backtrace
|
130
|
+
#
|
131
|
+
# @return [GraphQL::Backtrace] The backtrace for this point in query execution
|
132
|
+
def backtrace
|
133
|
+
GraphQL::Backtrace.new(self)
|
134
|
+
end
|
135
|
+
|
136
|
+
def execution_errors
|
137
|
+
@execution_errors ||= ExecutionErrors.new(self)
|
138
|
+
end
|
139
|
+
|
143
140
|
def current_path
|
144
141
|
current_runtime_state = Thread.current[:__graphql_runtime_info]
|
145
142
|
query_runtime_state = current_runtime_state && current_runtime_state[@query]
|
data/lib/graphql/query.rb
CHANGED
@@ -99,7 +99,7 @@ module GraphQL
|
|
99
99
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
100
100
|
variables ||= {}
|
101
101
|
@schema = schema
|
102
|
-
@context = schema.context_class.new(query: self,
|
102
|
+
@context = schema.context_class.new(query: self, values: context)
|
103
103
|
@warden = warden
|
104
104
|
@subscription_topic = subscription_topic
|
105
105
|
@root_value = root_value
|
@@ -120,10 +120,12 @@ module GraphQL
|
|
120
120
|
|
121
121
|
builder = self
|
122
122
|
|
123
|
+
found_types = types.values
|
123
124
|
schema_class = Class.new(schema_superclass) do
|
124
125
|
begin
|
125
126
|
# Add these first so that there's some chance of resolving late-bound types
|
126
|
-
|
127
|
+
add_type_and_traverse(found_types, root: false)
|
128
|
+
orphan_types(found_types.select { |t| t.respond_to?(:kind) && t.kind.object? })
|
127
129
|
query query_root_type
|
128
130
|
mutation mutation_root_type
|
129
131
|
subscription subscription_root_type
|
@@ -32,7 +32,8 @@ module GraphQL
|
|
32
32
|
end
|
33
33
|
|
34
34
|
Class.new(GraphQL::Schema) do
|
35
|
-
|
35
|
+
add_type_and_traverse(types.values, root: false)
|
36
|
+
orphan_types(types.values.select { |t| t.kind.object? })
|
36
37
|
directives(directives)
|
37
38
|
description(schema["description"])
|
38
39
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -861,6 +861,17 @@ module GraphQL
|
|
861
861
|
def orphan_types(*new_orphan_types)
|
862
862
|
if new_orphan_types.any?
|
863
863
|
new_orphan_types = new_orphan_types.flatten
|
864
|
+
non_object_types = new_orphan_types.reject { |ot| ot.is_a?(Class) && ot < GraphQL::Schema::Object }
|
865
|
+
if non_object_types.any?
|
866
|
+
raise ArgumentError, <<~ERR
|
867
|
+
Only object type classes should be added as `orphan_types(...)`.
|
868
|
+
|
869
|
+
- Remove these no-op types from `orphan_types`: #{non_object_types.map { |t| "#{t.inspect} (#{t.kind.name})"}.join(", ")}
|
870
|
+
- See https://graphql-ruby.org/type_definitions/interfaces.html#orphan-types
|
871
|
+
|
872
|
+
To add other types to your schema, you might want `extra_types`: https://graphql-ruby.org/schema/definition.html#extra-types
|
873
|
+
ERR
|
874
|
+
end
|
864
875
|
add_type_and_traverse(new_orphan_types, root: false)
|
865
876
|
own_orphan_types.concat(new_orphan_types.flatten)
|
866
877
|
end
|
@@ -1129,7 +1140,11 @@ module GraphQL
|
|
1129
1140
|
}.freeze
|
1130
1141
|
end
|
1131
1142
|
|
1132
|
-
def tracer(new_tracer)
|
1143
|
+
def tracer(new_tracer, silence_deprecation_warning: false)
|
1144
|
+
if !silence_deprecation_warning
|
1145
|
+
warn("`Schema.tracer(#{new_tracer.inspect})` is deprecated; use module-based `trace_with` instead. See: https://graphql-ruby.org/queries/tracing.html")
|
1146
|
+
warn " #{caller(1, 1).first}"
|
1147
|
+
end
|
1133
1148
|
default_trace = trace_class_for(:default, build: true)
|
1134
1149
|
if default_trace.nil? || !(default_trace < GraphQL::Tracing::CallLegacyTracers)
|
1135
1150
|
trace_with(GraphQL::Tracing::CallLegacyTracers)
|
@@ -86,7 +86,7 @@ module GraphQL
|
|
86
86
|
else
|
87
87
|
warn("`use(#{self.name})` and `Tracing::PlatformTracing` are deprecated. Use a `trace_with(...)` module instead. More info: https://graphql-ruby.org/queries/tracing.html. Please open an issue on the GraphQL-Ruby repo if you want to discuss further!")
|
88
88
|
tracer = self.new(**options)
|
89
|
-
|
89
|
+
schema_defn.tracer(tracer, silence_deprecation_warning: true)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
data/lib/graphql/version.rb
CHANGED
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.
|
4
|
+
version: 2.3.0
|
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-03-
|
11
|
+
date: 2024-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|