graphql 1.9.6 → 1.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/generators/graphql/install_generator.rb +2 -1
- data/lib/generators/graphql/templates/base_field.erb +7 -0
- data/lib/graphql/analysis/ast/visitor.rb +5 -2
- data/lib/graphql/execution/multiplex.rb +5 -1
- data/lib/graphql/query.rb +6 -1
- data/lib/graphql/relay/array_connection.rb +1 -1
- data/lib/graphql/schema.rb +15 -1
- data/lib/graphql/schema/argument.rb +5 -1
- data/lib/graphql/schema/input_object.rb +21 -12
- data/lib/graphql/schema/introspection_system.rb +6 -1
- data/lib/graphql/schema/member/has_arguments.rb +4 -2
- data/lib/graphql/schema/resolver.rb +8 -3
- data/lib/graphql/schema/subscription.rb +22 -0
- data/lib/graphql/schema/timeout.rb +109 -0
- data/lib/graphql/types/relay/base_edge.rb +0 -3
- data/lib/graphql/upgrader/member.rb +148 -111
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/fixtures/upgrader/mutation.original.rb +28 -0
- data/spec/fixtures/upgrader/mutation.transformed.rb +28 -0
- data/spec/graphql/analysis/ast_spec.rb +27 -0
- data/spec/graphql/execution/instrumentation_spec.rb +34 -6
- data/spec/graphql/execution/multiplex_spec.rb +11 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +6 -1
- data/spec/graphql/schema/input_object_spec.rb +56 -7
- data/spec/graphql/schema/introspection_system_spec.rb +24 -0
- data/spec/graphql/schema/subscription_spec.rb +65 -0
- data/spec/graphql/schema/timeout_spec.rb +206 -0
- data/spec/integration/mongoid/star_trek/schema.rb +1 -2
- data/spec/integration/rails/graphql/input_object_spec.rb +19 -0
- data/spec/integration/rails/graphql/relay/array_connection_spec.rb +47 -28
- data/spec/integration/rails/graphql/schema_spec.rb +18 -0
- data/spec/integration/tmp/app/graphql/types/date_type.rb +14 -0
- data/spec/integration/tmp/dummy/Gemfile +50 -0
- data/spec/integration/tmp/dummy/README.md +24 -0
- data/spec/integration/tmp/dummy/Rakefile +6 -0
- data/spec/integration/tmp/dummy/app/assets/config/manifest.js +3 -0
- data/spec/integration/tmp/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/integration/tmp/dummy/app/assets/javascripts/cable.js +13 -0
- data/spec/integration/tmp/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/integration/tmp/dummy/app/channels/application_cable/channel.rb +5 -0
- data/spec/integration/tmp/dummy/app/channels/application_cable/connection.rb +5 -0
- data/spec/integration/tmp/dummy/app/controllers/application_controller.rb +4 -0
- data/spec/integration/tmp/dummy/app/controllers/graphql_controller.rb +44 -0
- data/spec/integration/tmp/dummy/app/helpers/application_helper.rb +3 -0
- data/spec/integration/tmp/dummy/app/jobs/application_job.rb +3 -0
- data/spec/integration/tmp/dummy/app/mailers/application_mailer.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/dummy_schema.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/mutations/update_name.rb +15 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_enum.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_input_object.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_interface.rb +6 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_object.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_scalar.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/base_union.rb +5 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/mutation_type.rb +12 -0
- data/spec/integration/tmp/dummy/app/mydirectory/types/query_type.rb +14 -0
- data/spec/integration/tmp/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/integration/tmp/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/integration/tmp/dummy/bin/bundle +3 -0
- data/spec/integration/tmp/dummy/bin/rails +4 -0
- data/spec/integration/tmp/dummy/bin/rake +4 -0
- data/spec/integration/tmp/dummy/bin/setup +34 -0
- data/spec/integration/tmp/dummy/bin/update +29 -0
- data/spec/integration/tmp/dummy/config.ru +5 -0
- data/spec/integration/tmp/dummy/config/application.rb +26 -0
- data/spec/integration/tmp/dummy/config/boot.rb +4 -0
- data/spec/integration/tmp/dummy/config/cable.yml +9 -0
- data/spec/integration/tmp/dummy/config/environment.rb +6 -0
- data/spec/integration/tmp/dummy/config/environments/development.rb +52 -0
- data/spec/integration/tmp/dummy/config/environments/production.rb +84 -0
- data/spec/integration/tmp/dummy/config/environments/test.rb +43 -0
- data/spec/integration/tmp/dummy/config/initializers/application_controller_renderer.rb +9 -0
- data/spec/integration/tmp/dummy/config/initializers/assets.rb +12 -0
- data/spec/integration/tmp/dummy/config/initializers/backtrace_silencers.rb +8 -0
- data/spec/integration/tmp/dummy/config/initializers/cookies_serializer.rb +6 -0
- data/spec/integration/tmp/dummy/config/initializers/filter_parameter_logging.rb +5 -0
- data/spec/integration/tmp/dummy/config/initializers/inflections.rb +17 -0
- data/spec/integration/tmp/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/integration/tmp/dummy/config/initializers/new_framework_defaults.rb +24 -0
- data/spec/integration/tmp/dummy/config/initializers/session_store.rb +4 -0
- data/spec/integration/tmp/dummy/config/initializers/wrap_parameters.rb +10 -0
- data/spec/integration/tmp/dummy/config/locales/en.yml +23 -0
- data/spec/integration/tmp/dummy/config/puma.rb +48 -0
- data/spec/integration/tmp/dummy/config/routes.rb +9 -0
- data/spec/integration/tmp/dummy/config/secrets.yml +22 -0
- data/spec/integration/tmp/dummy/db/seeds.rb +8 -0
- data/spec/integration/tmp/dummy/log/test.log +0 -0
- data/spec/integration/tmp/dummy/public/404.html +67 -0
- data/spec/integration/tmp/dummy/public/422.html +67 -0
- data/spec/integration/tmp/dummy/public/500.html +66 -0
- data/spec/integration/tmp/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/integration/tmp/dummy/public/apple-touch-icon.png +0 -0
- data/spec/integration/tmp/dummy/public/favicon.ico +0 -0
- data/spec/integration/tmp/dummy/public/robots.txt +5 -0
- data/spec/integration/tmp/dummy/test/test_helper.rb +8 -0
- data/spec/support/jazz.rb +6 -0
- data/spec/support/star_wars/schema.rb +1 -2
- metadata +171 -6
- data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
@@ -32,9 +32,6 @@ module GraphQL
|
|
32
32
|
def node_type(node_type = nil, null: true)
|
33
33
|
if node_type
|
34
34
|
@node_type = node_type
|
35
|
-
wrapped_type_name = node_type.graphql_name
|
36
|
-
# Set this to be named like the node type, but suffixed with `Edge`
|
37
|
-
graphql_name("#{wrapped_type_name}Edge")
|
38
35
|
# Add a default `node` field
|
39
36
|
field :node, node_type, null: null, description: "The item at the end of the edge."
|
40
37
|
end
|
@@ -125,7 +125,7 @@ module GraphQL
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def apply(input_text)
|
128
|
-
input_text.
|
128
|
+
input_text.gsub(@find_pattern, @replace_pattern)
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
@@ -147,10 +147,10 @@ module GraphQL
|
|
147
147
|
name = matches[:overridden_name]
|
148
148
|
if type_name_without_the_type_part != name
|
149
149
|
# If the overridden name is still required, use `graphql_name` for it
|
150
|
-
transformable = transformable.
|
150
|
+
transformable = transformable.gsub(/ name (.*)/, ' graphql_name \1')
|
151
151
|
else
|
152
152
|
# Otherwise, remove it altogether
|
153
|
-
transformable = transformable.
|
153
|
+
transformable = transformable.gsub(/\s+name ('|").*('|")/, '')
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
@@ -285,43 +285,57 @@ module GraphQL
|
|
285
285
|
def apply(input_text)
|
286
286
|
if input_text =~ @proc_check_pattern
|
287
287
|
processor = apply_processor(input_text, NamedProcProcessor.new(@proc_name))
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
288
|
+
processor.proc_to_method_sections.reverse.each do |proc_to_method_section|
|
289
|
+
proc_body = input_text[proc_to_method_section.proc_body_start..proc_to_method_section.proc_body_end]
|
290
|
+
method_defn_indent = " " * proc_to_method_section.proc_defn_indent
|
291
|
+
method_defn = "def self.#{@proc_name}(#{proc_to_method_section.proc_arg_names.join(", ")})\n#{method_defn_indent} #{proc_body}\n#{method_defn_indent}end\n"
|
292
|
+
method_defn = trim_lines(method_defn)
|
293
|
+
# replace the proc with the new method
|
294
|
+
input_text[proc_to_method_section.proc_defn_start..proc_to_method_section.proc_defn_end] = method_defn
|
295
|
+
end
|
294
296
|
end
|
295
297
|
input_text
|
296
298
|
end
|
297
299
|
|
298
300
|
class NamedProcProcessor < Parser::AST::Processor
|
299
|
-
attr_reader :
|
301
|
+
attr_reader :proc_to_method_sections
|
300
302
|
def initialize(proc_name)
|
301
303
|
@proc_name_sym = proc_name.to_sym
|
302
|
-
@
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
304
|
+
@proc_to_method_sections = []
|
305
|
+
end
|
306
|
+
|
307
|
+
class ProcToMethodSection
|
308
|
+
attr_accessor :proc_arg_names, :proc_defn_start, :proc_defn_end, :proc_defn_indent, :proc_body_start, :proc_body_end, :inside_proc
|
309
|
+
|
310
|
+
def initialize
|
311
|
+
# @proc_name_sym = proc_name.to_sym
|
312
|
+
@proc_arg_names = nil
|
313
|
+
# Beginning of the `#{proc_name} -> {...}` call
|
314
|
+
@proc_defn_start = nil
|
315
|
+
# End of the last `end/}`
|
316
|
+
@proc_defn_end = nil
|
317
|
+
# Amount of whitespace to insert to the rewritten body
|
318
|
+
@proc_defn_indent = nil
|
319
|
+
# First statement of the proc
|
320
|
+
@proc_body_start = nil
|
321
|
+
# End of last statement in the proc
|
322
|
+
@proc_body_end = nil
|
323
|
+
# Used for identifying the proper block
|
324
|
+
@inside_proc = false
|
325
|
+
end
|
315
326
|
end
|
316
327
|
|
317
328
|
def on_send(node)
|
318
329
|
receiver, method_name, _args = *node
|
319
330
|
if method_name == @proc_name_sym && receiver.nil?
|
331
|
+
proc_section = ProcToMethodSection.new
|
320
332
|
source_exp = node.loc.expression
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
333
|
+
proc_section.proc_defn_start = source_exp.begin.begin_pos
|
334
|
+
proc_section.proc_defn_end = source_exp.end.end_pos
|
335
|
+
proc_section.proc_defn_indent = source_exp.column
|
336
|
+
proc_section.inside_proc = true
|
337
|
+
|
338
|
+
@proc_to_method_sections << proc_section
|
325
339
|
end
|
326
340
|
res = super(node)
|
327
341
|
@inside_proc = false
|
@@ -331,11 +345,14 @@ module GraphQL
|
|
331
345
|
def on_block(node)
|
332
346
|
send_node, args_node, body_node = node.children
|
333
347
|
_receiver, method_name, _send_args_node = *send_node
|
334
|
-
if method_name == :lambda && @inside_proc
|
348
|
+
if method_name == :lambda && !@proc_to_method_sections.empty? && @proc_to_method_sections[-1].inside_proc
|
349
|
+
proc_to_method_section = @proc_to_method_sections[-1]
|
350
|
+
|
335
351
|
source_exp = body_node.loc.expression
|
336
|
-
|
337
|
-
|
338
|
-
|
352
|
+
proc_to_method_section.proc_arg_names = args_node.children.map { |arg_node| arg_node.children[0].to_s }
|
353
|
+
proc_to_method_section.proc_body_start = source_exp.begin.begin_pos
|
354
|
+
proc_to_method_section.proc_body_end = source_exp.end.end_pos
|
355
|
+
proc_to_method_section.inside_proc = false
|
339
356
|
end
|
340
357
|
super(node)
|
341
358
|
end
|
@@ -353,30 +370,34 @@ module GraphQL
|
|
353
370
|
if input_text =~ /GraphQL::Relay::Mutation\.define/
|
354
371
|
named_proc_processor = apply_processor(input_text, ProcToClassMethodTransform::NamedProcProcessor.new(@proc_name))
|
355
372
|
resolve_proc_processor = apply_processor(input_text, ResolveProcToMethodTransform::ResolveProcProcessor.new)
|
356
|
-
proc_body = input_text[named_proc_processor.proc_body_start..named_proc_processor.proc_body_end]
|
357
|
-
method_defn_indent = " " * named_proc_processor.proc_defn_indent
|
358
|
-
|
359
|
-
obj_arg_name, args_arg_name, ctx_arg_name = resolve_proc_processor.proc_arg_names
|
360
|
-
# This is not good, it will hit false positives
|
361
|
-
# Should use AST to make this substitution
|
362
|
-
if obj_arg_name != "_"
|
363
|
-
proc_body.gsub!(/([^\w:.]|^)#{obj_arg_name}([^\w:]|$)/, '\1object\2')
|
364
|
-
end
|
365
|
-
if ctx_arg_name != "_"
|
366
|
-
proc_body.gsub!(/([^\w:.]|^)#{ctx_arg_name}([^\w:]|$)/, '\1context\2')
|
367
|
-
end
|
368
373
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
374
|
+
named_proc_processor.proc_to_method_sections.zip(resolve_proc_processor.resolve_proc_sections).reverse.each do |pair|
|
375
|
+
proc_to_method_section, resolve_proc_section = *pair
|
376
|
+
proc_body = input_text[proc_to_method_section.proc_body_start..proc_to_method_section.proc_body_end]
|
377
|
+
method_defn_indent = " " * proc_to_method_section.proc_defn_indent
|
378
|
+
|
379
|
+
obj_arg_name, args_arg_name, ctx_arg_name = resolve_proc_section.proc_arg_names
|
380
|
+
# This is not good, it will hit false positives
|
381
|
+
# Should use AST to make this substitution
|
382
|
+
if obj_arg_name != "_"
|
383
|
+
proc_body.gsub!(/([^\w:.]|^)#{obj_arg_name}([^\w:]|$)/, '\1object\2')
|
384
|
+
end
|
385
|
+
if ctx_arg_name != "_"
|
386
|
+
proc_body.gsub!(/([^\w:.]|^)#{ctx_arg_name}([^\w:]|$)/, '\1context\2')
|
387
|
+
end
|
388
|
+
|
389
|
+
method_defn = "def #{@proc_name}(**#{args_arg_name})\n#{method_defn_indent} #{proc_body}\n#{method_defn_indent}end\n"
|
390
|
+
method_defn = trim_lines(method_defn)
|
391
|
+
# Update usage of args keys
|
392
|
+
method_defn = method_defn.gsub(/#{args_arg_name}(?<method_begin>\.key\?\(?|\[)["':](?<arg_name>[a-zA-Z0-9_]+)["']?(?<method_end>\]|\))?/) do
|
393
|
+
method_begin = $~[:method_begin]
|
394
|
+
arg_name = underscorize($~[:arg_name])
|
395
|
+
method_end = $~[:method_end]
|
396
|
+
"#{args_arg_name}#{method_begin}:#{arg_name}#{method_end}"
|
397
|
+
end
|
398
|
+
# replace the proc with the new method
|
399
|
+
input_text[proc_to_method_section.proc_defn_start..proc_to_method_section.proc_defn_end] = method_defn
|
377
400
|
end
|
378
|
-
# replace the proc with the new method
|
379
|
-
input_text[named_proc_processor.proc_defn_start..named_proc_processor.proc_defn_end] = method_defn
|
380
401
|
end
|
381
402
|
input_text
|
382
403
|
end
|
@@ -512,74 +533,86 @@ module GraphQL
|
|
512
533
|
input_text.match(/(?<field_type>input_field|field|connection|argument) :(?<name>[a-zA-Z_0-9_]*)/)
|
513
534
|
field_name = $~[:name]
|
514
535
|
processor = apply_processor(input_text, ResolveProcProcessor.new)
|
515
|
-
proc_body = input_text[processor.proc_start..processor.proc_end]
|
516
|
-
obj_arg_name, args_arg_name, ctx_arg_name = processor.proc_arg_names
|
517
|
-
# This is not good, it will hit false positives
|
518
|
-
# Should use AST to make this substitution
|
519
|
-
if obj_arg_name != "_"
|
520
|
-
proc_body.gsub!(/([^\w:.]|^)#{obj_arg_name}([^\w:]|$)/, '\1object\2')
|
521
|
-
end
|
522
|
-
if ctx_arg_name != "_"
|
523
|
-
proc_body.gsub!(/([^\w:.]|^)#{ctx_arg_name}([^\w:]|$)/, '\1context\2')
|
524
|
-
end
|
525
536
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
537
|
+
processor.resolve_proc_sections.reverse.each do |resolve_proc_section|
|
538
|
+
proc_body = input_text[resolve_proc_section.proc_start..resolve_proc_section.proc_end]
|
539
|
+
obj_arg_name, args_arg_name, ctx_arg_name = resolve_proc_section.proc_arg_names
|
540
|
+
# This is not good, it will hit false positives
|
541
|
+
# Should use AST to make this substitution
|
542
|
+
if obj_arg_name != "_"
|
543
|
+
proc_body.gsub!(/([^\w:.]|^)#{obj_arg_name}([^\w:]|$)/, '\1object\2')
|
544
|
+
end
|
545
|
+
if ctx_arg_name != "_"
|
546
|
+
proc_body.gsub!(/([^\w:.]|^)#{ctx_arg_name}([^\w:]|$)/, '\1context\2')
|
547
|
+
end
|
548
|
+
|
549
|
+
method_def_indent = " " * (resolve_proc_section.resolve_indent - 2)
|
550
|
+
# Turn the proc body into a method body
|
551
|
+
method_body = reindent_lines(proc_body, from_indent: resolve_proc_section.resolve_indent + 2, to_indent: resolve_proc_section.resolve_indent)
|
552
|
+
# Add `def... end`
|
553
|
+
method_def = if input_text.include?("argument ")
|
554
|
+
# This field has arguments
|
555
|
+
"def #{field_name}(**#{args_arg_name})"
|
556
|
+
else
|
557
|
+
# No field arguments, so, no method arguments
|
558
|
+
"def #{field_name}"
|
559
|
+
end
|
560
|
+
# Wrap the body in def ... end
|
561
|
+
method_body = "\n#{method_def_indent}#{method_def}\n#{method_body}\n#{method_def_indent}end\n"
|
562
|
+
# Update Argument access to be underscore and symbols
|
563
|
+
# Update `args[...]` and `args.key?`
|
564
|
+
method_body = method_body.gsub(/#{args_arg_name}(?<method_begin>\.key\?\(?|\[)["':](?<arg_name>[a-zA-Z0-9_]+)["']?(?<method_end>\]|\))?/) do
|
565
|
+
method_begin = $~[:method_begin]
|
566
|
+
arg_name = underscorize($~[:arg_name])
|
567
|
+
method_end = $~[:method_end]
|
568
|
+
"#{args_arg_name}#{method_begin}:#{arg_name}#{method_end}"
|
569
|
+
end
|
547
570
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
571
|
+
# Replace the resolve proc with the method
|
572
|
+
input_text[resolve_proc_section.resolve_start..resolve_proc_section.resolve_end] = ""
|
573
|
+
# The replacement above might have left some preceeding whitespace,
|
574
|
+
# so remove it by deleting all whitespace chars before `resolve`:
|
575
|
+
preceeding_whitespace = resolve_proc_section.resolve_start - 1
|
576
|
+
while input_text[preceeding_whitespace] == " " && preceeding_whitespace > 0
|
577
|
+
input_text[preceeding_whitespace] = ""
|
578
|
+
preceeding_whitespace -= 1
|
579
|
+
end
|
580
|
+
input_text += method_body
|
581
|
+
input_text
|
556
582
|
end
|
557
|
-
input_text += method_body
|
558
|
-
input_text
|
559
|
-
else
|
560
|
-
# No resolve proc
|
561
|
-
input_text
|
562
583
|
end
|
584
|
+
|
585
|
+
input_text
|
563
586
|
end
|
564
587
|
|
565
588
|
class ResolveProcProcessor < Parser::AST::Processor
|
566
|
-
attr_reader :
|
589
|
+
attr_reader :resolve_proc_sections
|
567
590
|
def initialize
|
568
|
-
@
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
591
|
+
@resolve_proc_sections = []
|
592
|
+
end
|
593
|
+
|
594
|
+
class ResolveProcSection
|
595
|
+
attr_accessor :proc_start, :proc_end, :proc_arg_names, :resolve_start, :resolve_end, :resolve_indent
|
596
|
+
def initialize
|
597
|
+
@proc_arg_names = nil
|
598
|
+
@resolve_start = nil
|
599
|
+
@resolve_end = nil
|
600
|
+
@resolve_indent = nil
|
601
|
+
@proc_start = nil
|
602
|
+
@proc_end = nil
|
603
|
+
end
|
574
604
|
end
|
575
605
|
|
576
606
|
def on_send(node)
|
577
607
|
receiver, method_name, _args = *node
|
578
608
|
if method_name == :resolve && receiver.nil?
|
609
|
+
resolve_proc_section = ResolveProcSection.new
|
579
610
|
source_exp = node.loc.expression
|
580
|
-
|
581
|
-
|
582
|
-
|
611
|
+
resolve_proc_section.resolve_start = source_exp.begin.begin_pos
|
612
|
+
resolve_proc_section.resolve_end = source_exp.end.end_pos
|
613
|
+
resolve_proc_section.resolve_indent = source_exp.column
|
614
|
+
|
615
|
+
@resolve_proc_sections << resolve_proc_section
|
583
616
|
end
|
584
617
|
super(node)
|
585
618
|
end
|
@@ -588,11 +621,15 @@ module GraphQL
|
|
588
621
|
send_node, args_node, body_node = node.children
|
589
622
|
_receiver, method_name, _send_args_node = *send_node
|
590
623
|
# Assume that the first three-argument proc we enter is the resolve
|
591
|
-
if
|
624
|
+
if (
|
625
|
+
method_name == :lambda && args_node.children.size == 3 &&
|
626
|
+
!@resolve_proc_sections.empty? && @resolve_proc_sections[-1].proc_arg_names.nil?
|
627
|
+
)
|
628
|
+
resolve_proc_section = @resolve_proc_sections[-1]
|
592
629
|
source_exp = body_node.loc.expression
|
593
|
-
|
594
|
-
|
595
|
-
|
630
|
+
resolve_proc_section.proc_arg_names = args_node.children.map { |arg_node| arg_node.children[0].to_s }
|
631
|
+
resolve_proc_section.proc_start = source_exp.begin.begin_pos
|
632
|
+
resolve_proc_section.proc_end = source_exp.end.end_pos
|
596
633
|
end
|
597
634
|
super(node)
|
598
635
|
end
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
@@ -33,7 +33,7 @@ $ rails generate graphql:install
|
|
33
33
|
|
34
34
|
After this, you may need to run `bundle install` again, as by default graphiql-rails is added on installation.
|
35
35
|
|
36
|
-
Or, see ["Getting Started"](https://graphql-ruby.org/).
|
36
|
+
Or, see ["Getting Started"](https://graphql-ruby.org/getting_started.html).
|
37
37
|
|
38
38
|
## Upgrade
|
39
39
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Platform
|
3
|
+
module Mutations
|
4
|
+
Echo = GraphQL::Relay::Mutation.define do
|
5
|
+
name 'EchoMutation'
|
6
|
+
|
7
|
+
input_field :message, types.String
|
8
|
+
|
9
|
+
field :data, types.String
|
10
|
+
|
11
|
+
resolve ->(_obj, inputs, _ctx) {
|
12
|
+
{ data: inputs[:message] }
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
Repeat = GraphQL::Relay::Mutation.define do
|
17
|
+
name 'RepeatMutation'
|
18
|
+
|
19
|
+
input_field :message, types.String
|
20
|
+
|
21
|
+
field :data, types.String
|
22
|
+
|
23
|
+
resolve ->(_obj, inputs, _ctx) {
|
24
|
+
{ data: inputs[:message] }
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Platform
|
3
|
+
module Mutations
|
4
|
+
class Echo < Mutations::BaseMutation
|
5
|
+
graphql_name 'EchoMutation'
|
6
|
+
|
7
|
+
argument :message, String, required: false
|
8
|
+
|
9
|
+
field :data, String, null: true
|
10
|
+
|
11
|
+
def resolve(**inputs)
|
12
|
+
{ data: inputs[:message] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Repeat < Mutations::BaseMutation
|
17
|
+
graphql_name 'RepeatMutation'
|
18
|
+
|
19
|
+
argument :message, String, required: false
|
20
|
+
|
21
|
+
field :data, String, null: true
|
22
|
+
|
23
|
+
def resolve(**inputs)
|
24
|
+
{ data: inputs[:message] }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -71,6 +71,17 @@ describe GraphQL::Analysis::AST do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
class AstArguments < GraphQL::Analysis::AST::Analyzer
|
75
|
+
def on_enter_argument(node, parent, visitor)
|
76
|
+
@argument = visitor.argument_definition
|
77
|
+
@previous_argument = visitor.previous_argument_definition
|
78
|
+
end
|
79
|
+
|
80
|
+
def result
|
81
|
+
[@argument, @previous_argument]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
74
85
|
describe "using the AST analysis engine" do
|
75
86
|
let(:schema) do
|
76
87
|
query_type = Class.new(GraphQL::Schema::Object) do
|
@@ -179,6 +190,22 @@ describe GraphQL::Analysis::AST do
|
|
179
190
|
assert_equal "__Schema.types", prev_field.metadata[:type_class].path
|
180
191
|
end
|
181
192
|
end
|
193
|
+
|
194
|
+
describe "Visitor#argument_definition" do
|
195
|
+
let(:analyzers) { [AstArguments] }
|
196
|
+
let(:query) do
|
197
|
+
GraphQL::Query.new(
|
198
|
+
Dummy::Schema,
|
199
|
+
'{ searchDairy(product: [{ source: "SHEEP" }]) { ... on Cheese { id } } }'
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "it runs the analyzer" do
|
204
|
+
argument, prev_argument = reduce_result.first
|
205
|
+
assert_equal "DairyProductInput.source", argument.metadata[:type_class].path
|
206
|
+
assert_equal "Query.searchDairy.product", prev_argument.metadata[:type_class].path
|
207
|
+
end
|
208
|
+
end
|
182
209
|
end
|
183
210
|
|
184
211
|
it "calls the defined analyzers" do
|