graphql 2.1.6 → 2.1.8
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/install_generator.rb +3 -0
- data/lib/generators/graphql/templates/base_resolver.erb +6 -0
- data/lib/graphql/backtrace/trace.rb +12 -15
- data/lib/graphql/dataloader.rb +80 -133
- data/lib/graphql/execution/interpreter.rb +1 -1
- data/lib/graphql/language/block_string.rb +6 -2
- data/lib/graphql/query/null_context.rb +2 -1
- data/lib/graphql/query.rb +0 -2
- data/lib/graphql/schema/argument.rb +6 -1
- data/lib/graphql/schema/input_object.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +1 -1
- data/lib/graphql/schema.rb +9 -1
- data/lib/graphql/subscriptions/event.rb +7 -1
- data/lib/graphql/subscriptions.rb +2 -2
- data/lib/graphql/types/relay/connection_behaviors.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5171a9a622fedcee350cbb3edff60fa524d000aa88e3bab802de59089d46d00f
|
4
|
+
data.tar.gz: 4d111262bacb8a687a1c2113de7f065af18b3e9153f19c87341d10cd14aeda34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23d10d5146a5ba2ef8092e75197d932e23a30f2763354bd0114c37b1c9fba25c757a3a78bd3ae789a47c9317c02b5e3654a47064bcb42dd750464228f29b97c5
|
7
|
+
data.tar.gz: 13863ed6840cf38f52cb81b6c90539bacc0a76f3aea96cc86f69aeed397306bee1aaa48c760f4c17e39074f9d3c588338aff7887450bd6c792b0d6911b3af59c
|
@@ -105,6 +105,9 @@ module Graphql
|
|
105
105
|
template("#{base_type}.erb", "#{options[:directory]}/types/#{base_type}.rb")
|
106
106
|
end
|
107
107
|
|
108
|
+
# All resolvers are defined as living in their own module, including this class.
|
109
|
+
template("base_resolver.erb", "#{options[:directory]}/resolvers/base.rb")
|
110
|
+
|
108
111
|
# Note: You can't have a schema without the query type, otherwise introspection breaks
|
109
112
|
template("query_type.erb", "#{options[:directory]}/types/query_type.rb")
|
110
113
|
insert_root_type('query', 'QueryType')
|
@@ -2,6 +2,12 @@
|
|
2
2
|
module GraphQL
|
3
3
|
class Backtrace
|
4
4
|
module Trace
|
5
|
+
def initialize(*args, **kwargs, &block)
|
6
|
+
@__backtrace_contexts = {}
|
7
|
+
@__backtrace_last_context = nil
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
5
11
|
def validate(query:, validate:)
|
6
12
|
if query.multiplex
|
7
13
|
push_query_backtrace_context(query)
|
@@ -42,36 +48,27 @@ module GraphQL
|
|
42
48
|
rescue StandardError => err
|
43
49
|
# This is an unhandled error from execution,
|
44
50
|
# Re-raise it with a GraphQL trace.
|
45
|
-
|
46
|
-
potential_context = multiplex_context[:last_graphql_backtrace_context]
|
47
|
-
|
51
|
+
potential_context = @__backtrace_last_context
|
48
52
|
if potential_context.is_a?(GraphQL::Query::Context) ||
|
49
53
|
potential_context.is_a?(Backtrace::Frame)
|
50
54
|
raise TracedError.new(err, potential_context)
|
51
55
|
else
|
52
56
|
raise
|
53
57
|
end
|
54
|
-
ensure
|
55
|
-
multiplex_context = multiplex.context
|
56
|
-
multiplex_context.delete(:graphql_backtrace_contexts)
|
57
|
-
multiplex_context.delete(:last_graphql_backtrace_context)
|
58
58
|
end
|
59
59
|
|
60
60
|
private
|
61
61
|
|
62
62
|
def push_query_backtrace_context(query)
|
63
63
|
push_data = query
|
64
|
-
multiplex = query.multiplex
|
65
64
|
push_key = []
|
66
|
-
|
67
|
-
|
68
|
-
multiplex.context[:last_graphql_backtrace_context] = push_data
|
65
|
+
@__backtrace_contexts[push_key] = push_data
|
66
|
+
@__backtrace_last_context = push_data
|
69
67
|
end
|
70
68
|
|
71
69
|
def push_field_backtrace_context(field, query, ast_node, arguments, object)
|
72
|
-
multiplex = query.multiplex
|
73
70
|
push_key = query.context[:current_path]
|
74
|
-
push_storage =
|
71
|
+
push_storage = @__backtrace_contexts
|
75
72
|
parent_frame = push_storage[push_key[0..-2]]
|
76
73
|
|
77
74
|
if parent_frame.is_a?(GraphQL::Query)
|
@@ -87,10 +84,10 @@ module GraphQL
|
|
87
84
|
arguments: arguments,
|
88
85
|
parent_frame: parent_frame,
|
89
86
|
)
|
90
|
-
|
91
87
|
push_storage[push_key] = push_data
|
92
|
-
|
88
|
+
@__backtrace_last_context = push_data
|
93
89
|
end
|
90
|
+
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -118,7 +118,12 @@ module GraphQL
|
|
118
118
|
#
|
119
119
|
# @return [void]
|
120
120
|
def yield
|
121
|
-
|
121
|
+
if use_fiber_resume?
|
122
|
+
Fiber.yield
|
123
|
+
else
|
124
|
+
parent_fiber = Thread.current[:parent_fiber]
|
125
|
+
parent_fiber.transfer
|
126
|
+
end
|
122
127
|
nil
|
123
128
|
end
|
124
129
|
|
@@ -167,120 +172,100 @@ module GraphQL
|
|
167
172
|
end
|
168
173
|
end
|
169
174
|
|
170
|
-
# @api private Move along, move along
|
171
175
|
def run
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
# At a high level, the algorithm is:
|
176
|
-
#
|
177
|
-
# A) Inside Fibers, run jobs from the queue one-by-one
|
178
|
-
# - When one of the jobs yields to the dataloader (`Fiber.yield`), then that fiber will pause
|
179
|
-
# - In that case, if there are still pending jobs, a new Fiber will be created to run jobs
|
180
|
-
# - Continue until all jobs have been _started_ by a Fiber. (Any number of those Fibers may be waiting to be resumed, after their data is loaded)
|
181
|
-
# B) Once all known jobs have been run until they are complete or paused for data, run all pending data sources.
|
182
|
-
# - Similarly, create a Fiber to consume pending sources and tell them to load their data.
|
183
|
-
# - If one of those Fibers pauses, then create a new Fiber to continue working through remaining pending sources.
|
184
|
-
# - When a source causes another source to become pending, run the newly-pending source _first_, since it's a dependency of the previous one.
|
185
|
-
# C) After all pending sources have been completely loaded (there are no more pending sources), resume any Fibers that were waiting for data.
|
186
|
-
# - Those Fibers assume that source caches will have been populated with the data they were waiting for.
|
187
|
-
# - Those Fibers may request data from a source again, in which case they will yeilded and be added to a new pending fiber list.
|
188
|
-
# D) Once all pending fibers have been resumed once, return to `A` above.
|
189
|
-
#
|
190
|
-
# For whatever reason, the best implementation I could find was to order the steps `[D, A, B, C]`, with a special case for skipping `D`
|
191
|
-
# on the first pass. I just couldn't find a better way to write the loops in a way that was DRY and easy to read.
|
192
|
-
#
|
193
|
-
pending_fibers = []
|
194
|
-
next_fibers = []
|
195
|
-
pending_source_fibers = []
|
176
|
+
job_fibers = []
|
177
|
+
next_job_fibers = []
|
178
|
+
source_fibers = []
|
196
179
|
next_source_fibers = []
|
197
180
|
first_pass = true
|
198
|
-
|
199
|
-
|
200
|
-
if first_pass
|
181
|
+
manager = spawn_fiber do
|
182
|
+
while first_pass || job_fibers.any?
|
201
183
|
first_pass = false
|
202
|
-
else
|
203
|
-
# These fibers were previously waiting for sources to load data,
|
204
|
-
# resume them. (They might wait again, in which case, re-enqueue them.)
|
205
|
-
resume(f)
|
206
|
-
if f.alive?
|
207
|
-
next_fibers << f
|
208
|
-
end
|
209
|
-
end
|
210
184
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
185
|
+
while (f = job_fibers.shift || spawn_job_fiber)
|
186
|
+
if f.alive?
|
187
|
+
finished = run_fiber(f)
|
188
|
+
if !finished
|
189
|
+
next_job_fibers << f
|
190
|
+
end
|
217
191
|
end
|
218
|
-
}
|
219
|
-
resume(f)
|
220
|
-
# In this case, the job yielded. Queue it up to run again after
|
221
|
-
# we load whatever it's waiting for.
|
222
|
-
if f.alive?
|
223
|
-
next_fibers << f
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
if pending_fibers.empty?
|
228
|
-
# Now, run all Sources which have become pending _before_ resuming GraphQL execution.
|
229
|
-
# Sources might queue up other Sources, which is fine -- those will also run before resuming execution.
|
230
|
-
#
|
231
|
-
# This is where an evented approach would be even better -- can we tell which
|
232
|
-
# fibers are ready to continue, and continue execution there?
|
233
|
-
#
|
234
|
-
if (first_source_fiber = create_source_fiber)
|
235
|
-
pending_source_fibers << first_source_fiber
|
236
192
|
end
|
193
|
+
join_queues(job_fibers, next_job_fibers)
|
237
194
|
|
238
|
-
while
|
239
|
-
while (
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
pending_source_fibers << next_source_fiber
|
195
|
+
while source_fibers.any? || @source_cache.each_value.any? { |group_sources| group_sources.each_value.any?(&:pending?) }
|
196
|
+
while (f = source_fibers.shift || spawn_source_fiber)
|
197
|
+
if f.alive?
|
198
|
+
finished = run_fiber(f)
|
199
|
+
if !finished
|
200
|
+
next_source_fibers << f
|
201
|
+
end
|
246
202
|
end
|
247
203
|
end
|
248
|
-
join_queues(
|
249
|
-
next_source_fibers.clear
|
204
|
+
join_queues(source_fibers, next_source_fibers)
|
250
205
|
end
|
251
|
-
|
252
|
-
# Clear out the list of next-round Fibers, so that
|
253
|
-
# any Fibers that pause can be put on it.
|
254
|
-
join_queues(pending_fibers, next_fibers)
|
255
|
-
next_fibers.clear
|
206
|
+
|
256
207
|
end
|
257
208
|
end
|
258
209
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
elsif next_fibers.any?
|
264
|
-
raise "Invariant: #{next_fibers.size} next fibers"
|
265
|
-
end
|
266
|
-
nil
|
210
|
+
run_fiber(manager)
|
211
|
+
|
212
|
+
rescue UncaughtThrowError => e
|
213
|
+
throw e.tag, e.value
|
267
214
|
end
|
268
215
|
|
269
|
-
def
|
270
|
-
if
|
271
|
-
|
272
|
-
|
216
|
+
def run_fiber(f)
|
217
|
+
if use_fiber_resume?
|
218
|
+
f.resume
|
219
|
+
else
|
220
|
+
f.transfer
|
273
221
|
end
|
274
|
-
|
222
|
+
end
|
223
|
+
|
224
|
+
def spawn_fiber
|
225
|
+
fiber_vars = get_fiber_variables
|
226
|
+
parent_fiber = use_fiber_resume? ? nil : Fiber.current
|
227
|
+
Fiber.new(blocking: !@nonblocking) {
|
228
|
+
set_fiber_variables(fiber_vars)
|
229
|
+
Thread.current[:parent_fiber] = parent_fiber
|
230
|
+
yield
|
231
|
+
# With `.transfer`, you have to explicitly pass back to the parent --
|
232
|
+
# if the fiber is allowed to terminate normally, control is passed to the main fiber instead.
|
233
|
+
if parent_fiber
|
234
|
+
parent_fiber.transfer(true)
|
235
|
+
else
|
236
|
+
true
|
237
|
+
end
|
238
|
+
}
|
275
239
|
end
|
276
240
|
|
277
241
|
private
|
278
242
|
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
243
|
+
def join_queues(prev_queue, new_queue)
|
244
|
+
@nonblocking && Fiber.scheduler.run
|
245
|
+
prev_queue.concat(new_queue)
|
246
|
+
new_queue.clear
|
247
|
+
end
|
248
|
+
|
249
|
+
def use_fiber_resume?
|
250
|
+
Fiber.respond_to?(:scheduler) &&
|
251
|
+
(
|
252
|
+
(defined?(::DummyScheduler) && Fiber.scheduler.is_a?(::DummyScheduler)) ||
|
253
|
+
(defined?(::Evt) && ::Evt::Scheduler.singleton_class::BACKENDS.any? { |be| Fiber.scheduler.is_a?(be) }) ||
|
254
|
+
(defined?(::Libev) && Fiber.scheduler.is_a?(::Libev::Scheduler))
|
255
|
+
)
|
256
|
+
end
|
257
|
+
|
258
|
+
def spawn_job_fiber
|
259
|
+
if @pending_jobs.any?
|
260
|
+
spawn_fiber do
|
261
|
+
while job = @pending_jobs.shift
|
262
|
+
job.call
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def spawn_source_fiber
|
284
269
|
pending_sources = nil
|
285
270
|
@source_cache.each_value do |source_by_batch_params|
|
286
271
|
source_by_batch_params.each_value do |source|
|
@@ -292,48 +277,10 @@ module GraphQL
|
|
292
277
|
end
|
293
278
|
|
294
279
|
if pending_sources
|
295
|
-
|
296
|
-
# For example, if you have sources `[a, b, c]`, and `a` is loaded, then `b` yields to wait for `d`, then
|
297
|
-
# the next fiber would be dispatched with `[c, d]`. It would fulfill `c`, then `d`, then eventually
|
298
|
-
# the previous fiber would start up again. `c` would no longer be pending, but it would still receive `.run_pending_keys`.
|
299
|
-
# That method is short-circuited since it isn't pending any more, but it's still a waste.
|
300
|
-
#
|
301
|
-
# This design could probably be improved by maintaining a `@pending_sources` queue which is shared by the fibers,
|
302
|
-
# similar to `@pending_jobs`. That way, when a fiber is resumed, it would never pick up work that was finished by a different fiber.
|
303
|
-
source_fiber = spawn_fiber do
|
280
|
+
spawn_fiber do
|
304
281
|
pending_sources.each(&:run_pending_keys)
|
305
282
|
end
|
306
283
|
end
|
307
|
-
|
308
|
-
source_fiber
|
309
|
-
end
|
310
|
-
|
311
|
-
def resume(fiber)
|
312
|
-
fiber.resume
|
313
|
-
rescue UncaughtThrowError => e
|
314
|
-
throw e.tag, e.value
|
315
|
-
end
|
316
|
-
|
317
|
-
# Copies the thread local vars into the fiber thread local vars. Many
|
318
|
-
# gems (such as RequestStore, MiniRacer, etc.) rely on thread local vars
|
319
|
-
# to keep track of execution context, and without this they do not
|
320
|
-
# behave as expected.
|
321
|
-
#
|
322
|
-
# @see https://github.com/rmosolgo/graphql-ruby/issues/3449
|
323
|
-
def spawn_fiber
|
324
|
-
fiber_vars = get_fiber_variables
|
325
|
-
|
326
|
-
if @nonblocking
|
327
|
-
Fiber.new(blocking: false) do
|
328
|
-
set_fiber_variables(fiber_vars)
|
329
|
-
yield
|
330
|
-
end
|
331
|
-
else
|
332
|
-
Fiber.new do
|
333
|
-
set_fiber_variables(fiber_vars)
|
334
|
-
yield
|
335
|
-
end
|
336
|
-
end
|
337
284
|
end
|
338
285
|
end
|
339
286
|
end
|
@@ -47,10 +47,10 @@ module GraphQL
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Remove leading & trailing blank lines
|
50
|
-
while lines.size > 0 && lines
|
50
|
+
while lines.size > 0 && contains_only_whitespace?(lines.first)
|
51
51
|
lines.shift
|
52
52
|
end
|
53
|
-
while lines.size > 0 && lines
|
53
|
+
while lines.size > 0 && contains_only_whitespace?(lines.last)
|
54
54
|
lines.pop
|
55
55
|
end
|
56
56
|
|
@@ -106,6 +106,10 @@ module GraphQL
|
|
106
106
|
|
107
107
|
nil
|
108
108
|
end
|
109
|
+
|
110
|
+
def self.contains_only_whitespace?(line)
|
111
|
+
line.match?(/^\s*$/)
|
112
|
+
end
|
109
113
|
end
|
110
114
|
end
|
111
115
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -115,8 +115,6 @@ module GraphQL
|
|
115
115
|
if schema.trace_class <= GraphQL::Tracing::CallLegacyTracers
|
116
116
|
context_tracers += [GraphQL::Backtrace::Tracer]
|
117
117
|
@tracers << GraphQL::Backtrace::Tracer
|
118
|
-
elsif !(current_trace.class <= GraphQL::Backtrace::Trace)
|
119
|
-
raise "Invariant: `backtrace: true` should have provided a trace class with Backtrace mixed in, but it didnt. (Found: #{current_trace.class.ancestors}). This is a bug in GraphQL-Ruby, please report it on GitHub."
|
120
118
|
end
|
121
119
|
end
|
122
120
|
|
@@ -221,8 +221,13 @@ module GraphQL
|
|
221
221
|
#
|
222
222
|
# This will have to be called later, when the runtime object _is_ available.
|
223
223
|
value
|
224
|
-
|
224
|
+
elsif obj.respond_to?(@prepare)
|
225
225
|
obj.public_send(@prepare, value)
|
226
|
+
elsif owner.respond_to?(@prepare)
|
227
|
+
owner.public_send(@prepare, value, context || obj.context)
|
228
|
+
else
|
229
|
+
raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}. "\
|
230
|
+
"Could not find prepare method #{@prepare} on #{obj.class} or #{owner}."
|
226
231
|
end
|
227
232
|
elsif @prepare.respond_to?(:call)
|
228
233
|
@prepare.call(value, context || obj.context)
|
@@ -145,7 +145,7 @@ module GraphQL
|
|
145
145
|
end
|
146
146
|
|
147
147
|
# @api private
|
148
|
-
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object
|
148
|
+
INVALID_OBJECT_MESSAGE = "Expected %{object} to be a key-value object."
|
149
149
|
|
150
150
|
def validate_non_null_input(input, ctx, max_errors: nil)
|
151
151
|
warden = ctx.warden
|
@@ -21,7 +21,7 @@ module GraphQL
|
|
21
21
|
if @reauthorize_scoped_objects != nil
|
22
22
|
@reauthorize_scoped_objects
|
23
23
|
else
|
24
|
-
find_inherited_value(:reauthorize_scoped_objects,
|
24
|
+
find_inherited_value(:reauthorize_scoped_objects, true)
|
25
25
|
end
|
26
26
|
else
|
27
27
|
@reauthorize_scoped_objects = new_value
|
data/lib/graphql/schema.rb
CHANGED
@@ -680,7 +680,7 @@ module GraphQL
|
|
680
680
|
else
|
681
681
|
string_or_document
|
682
682
|
end
|
683
|
-
query =
|
683
|
+
query = query_class.new(self, document: doc, context: context)
|
684
684
|
validator_opts = { schema: self }
|
685
685
|
rules && (validator_opts[:rules] = rules)
|
686
686
|
validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
|
@@ -688,6 +688,14 @@ module GraphQL
|
|
688
688
|
res[:errors]
|
689
689
|
end
|
690
690
|
|
691
|
+
def query_class(new_query_class = NOT_CONFIGURED)
|
692
|
+
if NOT_CONFIGURED.equal?(new_query_class)
|
693
|
+
@query_class || (superclass.respond_to?(:query_class) ? superclass.query_class : GraphQL::Query)
|
694
|
+
else
|
695
|
+
@query_class = new_query_class
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
691
699
|
attr_writer :validate_max_errors
|
692
700
|
|
693
701
|
def validate_max_errors(new_validate_max_errors = nil)
|
@@ -126,7 +126,13 @@ module GraphQL
|
|
126
126
|
when GraphQL::Schema::InputObject
|
127
127
|
stringify_args(arg_owner, args.to_h, context)
|
128
128
|
else
|
129
|
-
|
129
|
+
if arg_owner.is_a?(Class) && arg_owner < GraphQL::Schema::Enum
|
130
|
+
# `prepare:` may have made the value something other than
|
131
|
+
# a defined value of this enum -- use _that_ in this case.
|
132
|
+
arg_owner.coerce_isolated_input(args) || args
|
133
|
+
else
|
134
|
+
args
|
135
|
+
end
|
130
136
|
end
|
131
137
|
end
|
132
138
|
|
@@ -62,7 +62,7 @@ module GraphQL
|
|
62
62
|
# @return [void]
|
63
63
|
def trigger(event_name, args, object, scope: nil, context: {})
|
64
64
|
# Make something as context-like as possible, even though there isn't a current query:
|
65
|
-
dummy_query =
|
65
|
+
dummy_query = @schema.query_class.new(@schema, "{ __typename }", validate: false, context: context)
|
66
66
|
context = dummy_query.context
|
67
67
|
event_name = event_name.to_s
|
68
68
|
|
@@ -234,7 +234,7 @@ module GraphQL
|
|
234
234
|
|
235
235
|
# @return [Boolean] if true, then a query like this one would be broadcasted
|
236
236
|
def broadcastable?(query_str, **query_options)
|
237
|
-
query =
|
237
|
+
query = @schema.query_class.new(@schema, query_str, **query_options)
|
238
238
|
if !query.valid?
|
239
239
|
raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
|
240
240
|
end
|
@@ -87,6 +87,19 @@ module GraphQL
|
|
87
87
|
node_type.scope_items(items, context)
|
88
88
|
end
|
89
89
|
|
90
|
+
# The connection will skip auth on its nodes if the node_type is configured for that
|
91
|
+
def reauthorize_scoped_objects(new_value = nil)
|
92
|
+
if new_value.nil?
|
93
|
+
if @reauthorize_scoped_objects != nil
|
94
|
+
@reauthorize_scoped_objects
|
95
|
+
else
|
96
|
+
node_type.reauthorize_scoped_objects
|
97
|
+
end
|
98
|
+
else
|
99
|
+
@reauthorize_scoped_objects = new_value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
90
103
|
# Add the shortcut `nodes` field to this connection and its subclasses
|
91
104
|
def nodes_field(node_nullable: self.node_nullable, field_options: nil)
|
92
105
|
define_nodes_field(node_nullable, field_options: field_options)
|
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.1.
|
4
|
+
version: 2.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: racc
|
@@ -270,6 +270,7 @@ files:
|
|
270
270
|
- lib/generators/graphql/templates/base_input_object.erb
|
271
271
|
- lib/generators/graphql/templates/base_interface.erb
|
272
272
|
- lib/generators/graphql/templates/base_object.erb
|
273
|
+
- lib/generators/graphql/templates/base_resolver.erb
|
273
274
|
- lib/generators/graphql/templates/base_scalar.erb
|
274
275
|
- lib/generators/graphql/templates/base_union.erb
|
275
276
|
- lib/generators/graphql/templates/enum.erb
|