graphql 1.9.6 → 1.9.7
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.
- 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
|