graphql 1.12.16 → 1.13.2

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.

Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -1
  3. data/lib/generators/graphql/install_generator.rb +9 -2
  4. data/lib/generators/graphql/mutation_generator.rb +1 -1
  5. data/lib/generators/graphql/object_generator.rb +2 -1
  6. data/lib/generators/graphql/relay.rb +19 -11
  7. data/lib/generators/graphql/templates/schema.erb +14 -2
  8. data/lib/generators/graphql/type_generator.rb +0 -1
  9. data/lib/graphql/analysis/ast/field_usage.rb +3 -3
  10. data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
  11. data/lib/graphql/analysis/ast/visitor.rb +4 -4
  12. data/lib/graphql/backtrace/table.rb +1 -1
  13. data/lib/graphql/base_type.rb +4 -2
  14. data/lib/graphql/boolean_type.rb +1 -1
  15. data/lib/graphql/dataloader/source.rb +50 -2
  16. data/lib/graphql/dataloader.rb +93 -37
  17. data/lib/graphql/define/instance_definable.rb +1 -1
  18. data/lib/graphql/deprecated_dsl.rb +11 -3
  19. data/lib/graphql/deprecation.rb +1 -5
  20. data/lib/graphql/directive/deprecated_directive.rb +1 -1
  21. data/lib/graphql/directive/include_directive.rb +1 -1
  22. data/lib/graphql/directive/skip_directive.rb +1 -1
  23. data/lib/graphql/directive.rb +0 -4
  24. data/lib/graphql/enum_type.rb +5 -1
  25. data/lib/graphql/execution/errors.rb +1 -0
  26. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  27. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -2
  28. data/lib/graphql/execution/interpreter/runtime.rb +39 -23
  29. data/lib/graphql/execution/lookahead.rb +2 -2
  30. data/lib/graphql/execution/multiplex.rb +4 -1
  31. data/lib/graphql/float_type.rb +1 -1
  32. data/lib/graphql/id_type.rb +1 -1
  33. data/lib/graphql/int_type.rb +1 -1
  34. data/lib/graphql/integer_encoding_error.rb +18 -2
  35. data/lib/graphql/introspection/directive_type.rb +1 -1
  36. data/lib/graphql/introspection/entry_points.rb +2 -2
  37. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  38. data/lib/graphql/introspection/field_type.rb +2 -2
  39. data/lib/graphql/introspection/input_value_type.rb +10 -4
  40. data/lib/graphql/introspection/schema_type.rb +2 -2
  41. data/lib/graphql/introspection/type_type.rb +10 -10
  42. data/lib/graphql/language/block_string.rb +2 -6
  43. data/lib/graphql/language/document_from_schema_definition.rb +4 -2
  44. data/lib/graphql/language/lexer.rb +0 -3
  45. data/lib/graphql/language/lexer.rl +0 -4
  46. data/lib/graphql/language/nodes.rb +12 -2
  47. data/lib/graphql/language/parser.rb +442 -434
  48. data/lib/graphql/language/parser.y +5 -4
  49. data/lib/graphql/language/printer.rb +6 -1
  50. data/lib/graphql/language/sanitized_printer.rb +5 -5
  51. data/lib/graphql/language/token.rb +0 -4
  52. data/lib/graphql/name_validator.rb +0 -4
  53. data/lib/graphql/pagination/connections.rb +35 -16
  54. data/lib/graphql/query/arguments.rb +1 -1
  55. data/lib/graphql/query/arguments_cache.rb +1 -1
  56. data/lib/graphql/query/context.rb +15 -2
  57. data/lib/graphql/query/literal_input.rb +1 -1
  58. data/lib/graphql/query/null_context.rb +12 -7
  59. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  60. data/lib/graphql/query/validation_pipeline.rb +1 -1
  61. data/lib/graphql/query/variables.rb +5 -1
  62. data/lib/graphql/query.rb +4 -0
  63. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  64. data/lib/graphql/relay/global_id_resolve.rb +1 -1
  65. data/lib/graphql/relay/page_info.rb +1 -1
  66. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  67. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  68. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  69. data/lib/graphql/rubocop.rb +4 -0
  70. data/lib/graphql/schema/addition.rb +37 -28
  71. data/lib/graphql/schema/argument.rb +79 -34
  72. data/lib/graphql/schema/build_from_definition.rb +5 -5
  73. data/lib/graphql/schema/directive/feature.rb +1 -1
  74. data/lib/graphql/schema/directive/flagged.rb +2 -2
  75. data/lib/graphql/schema/directive/include.rb +1 -1
  76. data/lib/graphql/schema/directive/skip.rb +1 -1
  77. data/lib/graphql/schema/directive/transform.rb +1 -1
  78. data/lib/graphql/schema/directive.rb +7 -3
  79. data/lib/graphql/schema/enum.rb +60 -10
  80. data/lib/graphql/schema/enum_value.rb +6 -0
  81. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  82. data/lib/graphql/schema/field.rb +140 -42
  83. data/lib/graphql/schema/field_extension.rb +52 -2
  84. data/lib/graphql/schema/find_inherited_value.rb +1 -0
  85. data/lib/graphql/schema/finder.rb +5 -5
  86. data/lib/graphql/schema/input_object.rb +13 -14
  87. data/lib/graphql/schema/interface.rb +11 -20
  88. data/lib/graphql/schema/introspection_system.rb +1 -1
  89. data/lib/graphql/schema/list.rb +3 -1
  90. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  91. data/lib/graphql/schema/member/build_type.rb +0 -4
  92. data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
  93. data/lib/graphql/schema/member/has_arguments.rb +145 -57
  94. data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
  95. data/lib/graphql/schema/member/has_fields.rb +76 -18
  96. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  97. data/lib/graphql/schema/member.rb +1 -0
  98. data/lib/graphql/schema/non_null.rb +3 -1
  99. data/lib/graphql/schema/object.rb +10 -75
  100. data/lib/graphql/schema/printer.rb +1 -1
  101. data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
  102. data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
  103. data/lib/graphql/schema/resolver.rb +49 -64
  104. data/lib/graphql/schema/scalar.rb +2 -0
  105. data/lib/graphql/schema/subscription.rb +17 -9
  106. data/lib/graphql/schema/traversal.rb +1 -1
  107. data/lib/graphql/schema/type_expression.rb +1 -1
  108. data/lib/graphql/schema/type_membership.rb +18 -4
  109. data/lib/graphql/schema/union.rb +8 -1
  110. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  111. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  112. data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
  113. data/lib/graphql/schema/validator/format_validator.rb +4 -5
  114. data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
  115. data/lib/graphql/schema/validator/length_validator.rb +5 -3
  116. data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
  117. data/lib/graphql/schema/validator.rb +33 -25
  118. data/lib/graphql/schema/warden.rb +116 -52
  119. data/lib/graphql/schema.rb +124 -27
  120. data/lib/graphql/static_validation/base_visitor.rb +8 -5
  121. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  122. data/lib/graphql/static_validation/error.rb +3 -1
  123. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  124. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  125. data/lib/graphql/static_validation/rules/fields_will_merge.rb +52 -26
  126. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  127. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  128. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -1
  129. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
  130. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +7 -7
  131. data/lib/graphql/static_validation/validation_context.rb +8 -2
  132. data/lib/graphql/static_validation/validator.rb +15 -12
  133. data/lib/graphql/string_encoding_error.rb +13 -3
  134. data/lib/graphql/string_type.rb +1 -1
  135. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +15 -5
  136. data/lib/graphql/subscriptions/event.rb +66 -13
  137. data/lib/graphql/subscriptions/serialize.rb +1 -1
  138. data/lib/graphql/subscriptions.rb +17 -19
  139. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  140. data/lib/graphql/types/int.rb +1 -1
  141. data/lib/graphql/types/relay/connection_behaviors.rb +26 -9
  142. data/lib/graphql/types/relay/default_relay.rb +5 -1
  143. data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
  144. data/lib/graphql/types/relay/has_node_field.rb +1 -1
  145. data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
  146. data/lib/graphql/types/string.rb +1 -1
  147. data/lib/graphql/unauthorized_error.rb +1 -1
  148. data/lib/graphql/version.rb +1 -1
  149. data/lib/graphql.rb +10 -32
  150. data/readme.md +1 -1
  151. metadata +13 -6
@@ -34,10 +34,14 @@ module GraphQL
34
34
  end
35
35
 
36
36
  # @return [Hash<String => EnumValue>] `{name => value}` pairs contained in this type
37
- def values
37
+ def values(_context = nil)
38
38
  @values_by_name
39
39
  end
40
40
 
41
+ def enum_values(_context = nil)
42
+ values.values
43
+ end
44
+
41
45
  def kind
42
46
  GraphQL::TypeKinds::ENUM
43
47
  end
@@ -111,6 +111,7 @@ module GraphQL
111
111
  runtime_info = ctx.namespace(:interpreter) || {}
112
112
  obj = runtime_info[:current_object]
113
113
  args = runtime_info[:current_arguments]
114
+ args = args && args.keyword_arguments
114
115
  field = runtime_info[:current_field]
115
116
  if obj.is_a?(GraphQL::Schema::Object)
116
117
  obj = obj.object
@@ -59,7 +59,7 @@ module GraphQL
59
59
  @empty
60
60
  end
61
61
 
62
- def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values
62
+ def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values, :size, :to_h
63
63
  def_delegators :argument_values, :each_value
64
64
 
65
65
  def inspect
@@ -71,11 +71,11 @@ module GraphQL
71
71
  when Array
72
72
  ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
73
73
  when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
74
- if ast_arg_or_hash_or_value.arguments.empty?
74
+ if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
75
75
  return NO_ARGUMENTS
76
76
  end
77
77
  args_hash = {}
78
- ast_arg_or_hash_or_value.arguments.each do |arg|
78
+ ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
79
79
  v = prepare_args_hash(query, arg.value)
80
80
  if v != NO_VALUE_GIVEN
81
81
  args_hash[arg.name] = v
@@ -236,6 +236,7 @@ module GraphQL
236
236
  selections,
237
237
  selection_response,
238
238
  final_response,
239
+ nil,
239
240
  )
240
241
  end
241
242
  }
@@ -313,7 +314,7 @@ module GraphQL
313
314
  case node
314
315
  when GraphQL::Language::Nodes::InlineFragment
315
316
  if node.type
316
- type_defn = schema.get_type(node.type.name)
317
+ type_defn = schema.get_type(node.type.name, context)
317
318
 
318
319
  # Faster than .map{}.include?()
319
320
  query.warden.possible_types(type_defn).each do |t|
@@ -328,7 +329,7 @@ module GraphQL
328
329
  end
329
330
  when GraphQL::Language::Nodes::FragmentSpread
330
331
  fragment_def = query.fragments[node.name]
331
- type_defn = schema.get_type(fragment_def.type.name)
332
+ type_defn = query.get_type(fragment_def.type.name)
332
333
  possible_types = query.warden.possible_types(type_defn)
333
334
  possible_types.each do |t|
334
335
  if t == owner_type
@@ -347,7 +348,7 @@ module GraphQL
347
348
  NO_ARGS = {}.freeze
348
349
 
349
350
  # @return [void]
350
- def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result) # rubocop:disable Metrics/ParameterLists
351
+ def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object) # rubocop:disable Metrics/ParameterLists
351
352
  set_all_interpreter_context(owner_object, nil, nil, path)
352
353
 
353
354
  finished_jobs = 0
@@ -355,7 +356,7 @@ module GraphQL
355
356
  gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
356
357
  @dataloader.append_job {
357
358
  evaluate_selection(
358
- path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection, selections_result
359
+ path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection, selections_result, parent_object
359
360
  )
360
361
  finished_jobs += 1
361
362
  if target_result && finished_jobs == enqueued_jobs
@@ -370,7 +371,7 @@ module GraphQL
370
371
  attr_reader :progress_path
371
372
 
372
373
  # @return [void]
373
- def evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_field, selections_result) # rubocop:disable Metrics/ParameterLists
374
+ def evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_field, selections_result, parent_object) # rubocop:disable Metrics/ParameterLists
374
375
  return if dead_result?(selections_result)
375
376
  # As a performance optimization, the hash key will be a `Node` if
376
377
  # there's only one selection of the field. But if there are multiple
@@ -383,7 +384,9 @@ module GraphQL
383
384
  ast_node = field_ast_nodes_or_ast_node
384
385
  end
385
386
  field_name = ast_node.name
386
- field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name)
387
+ # This can't use `query.get_field` because it gets confused on introspection below if `field_defn` isn't `nil`,
388
+ # because of how `is_introspection` is used to call `.authorized_new` later on.
389
+ field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name, @context)
387
390
  is_introspection = false
388
391
  if field_defn.nil?
389
392
  field_defn = if owner_type == schema.query && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
@@ -418,22 +421,22 @@ module GraphQL
418
421
  object = authorized_new(field_defn.owner, object, context)
419
422
  end
420
423
 
421
- total_args_count = field_defn.arguments.size
424
+ total_args_count = field_defn.arguments(context).size
422
425
  if total_args_count == 0
423
- kwarg_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
424
- evaluate_selection_with_args(kwarg_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result)
426
+ resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
427
+ evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
425
428
  else
426
429
  # TODO remove all arguments(...) usages?
427
430
  @query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
428
- evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result)
431
+ evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object)
429
432
  end
430
433
  end
431
434
  end
432
435
 
433
- def evaluate_selection_with_args(kwarg_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
436
+ def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object) # rubocop:disable Metrics/ParameterLists
434
437
  context.scoped_context = scoped_context
435
438
  return_type = field_defn.type
436
- after_lazy(kwarg_arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
439
+ after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
437
440
  if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
438
441
  continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
439
442
  next
@@ -472,6 +475,8 @@ module GraphQL
472
475
  # This is used by `__typename` in order to support the legacy runtime,
473
476
  # but it has no use here (and it's always `nil`).
474
477
  # Stop adding it here to avoid the overhead of `.merge_extras` below.
478
+ when :parent
479
+ extra_args[:parent] = parent_object
475
480
  else
476
481
  extra_args[extra] = field_defn.fetch_extra(extra, context)
477
482
  end
@@ -482,7 +487,7 @@ module GraphQL
482
487
  resolved_arguments.keyword_arguments
483
488
  end
484
489
 
485
- set_all_interpreter_context(nil, nil, kwarg_arguments, nil)
490
+ set_all_interpreter_context(nil, nil, resolved_arguments, nil)
486
491
 
487
492
  # Optimize for the case that field is selected only once
488
493
  if field_ast_nodes.nil? || field_ast_nodes.size == 1
@@ -508,10 +513,10 @@ module GraphQL
508
513
  rescue GraphQL::ExecutionError => err
509
514
  err
510
515
  end
511
- after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: kwarg_arguments, result_name: result_name, result: selection_result) do |inner_result|
516
+ after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
512
517
  continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
513
518
  if HALT != continue_value
514
- continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, kwarg_arguments, result_name, selection_result)
519
+ continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
515
520
  end
516
521
  end
517
522
  end
@@ -634,14 +639,20 @@ module GraphQL
634
639
  when Array
635
640
  # It's an array full of execution errors; add them all.
636
641
  if value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
642
+ list_type_at_all = (field && (field.type.list?))
637
643
  if selection_result.nil? || !dead_result?(selection_result)
638
644
  value.each_with_index do |error, index|
639
645
  error.ast_node ||= ast_node
640
- error.path ||= path + ((field && field.type.list?) ? [index] : [])
646
+ error.path ||= path + (list_type_at_all ? [index] : [])
641
647
  context.errors << error
642
648
  end
643
649
  if selection_result
644
- set_result(selection_result, result_name, nil)
650
+ if list_type_at_all
651
+ result_without_errors = value.map { |v| v.is_a?(GraphQL::ExecutionError) ? nil : v }
652
+ set_result(selection_result, result_name, result_without_errors)
653
+ else
654
+ set_result(selection_result, result_name, nil)
655
+ end
645
656
  end
646
657
  end
647
658
  HALT
@@ -733,6 +744,7 @@ module GraphQL
733
744
  selections,
734
745
  this_result,
735
746
  final_result,
747
+ owner_object.object,
736
748
  )
737
749
  this_result
738
750
  end
@@ -858,16 +870,20 @@ module GraphQL
858
870
  # but don't wrap the continuation below
859
871
  inner_obj = begin
860
872
  query.with_error_handling do
861
- if trace
862
- query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
873
+ begin
874
+ if trace
875
+ query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
876
+ schema.sync_lazy(lazy_obj)
877
+ end
878
+ else
863
879
  schema.sync_lazy(lazy_obj)
864
880
  end
865
- else
866
- schema.sync_lazy(lazy_obj)
881
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
882
+ err
867
883
  end
868
884
  end
869
- rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
870
- err
885
+ rescue GraphQL::ExecutionError => ex_err
886
+ ex_err
871
887
  end
872
888
  yield(inner_obj)
873
889
  end
@@ -254,14 +254,14 @@ module GraphQL
254
254
  subselections_on_type = selections_on_type
255
255
  if (t = ast_selection.type)
256
256
  # Assuming this is valid, that `t` will be found.
257
- on_type = @query.schema.get_type(t.name).type_class
257
+ on_type = @query.get_type(t.name).type_class
258
258
  subselections_on_type = subselections_by_type[on_type] ||= {}
259
259
  end
260
260
  find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
261
261
  when GraphQL::Language::Nodes::FragmentSpread
262
262
  frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
263
263
  # Again, assuming a valid AST
264
- on_type = @query.schema.get_type(frag_defn.type.name).type_class
264
+ on_type = @query.get_type(frag_defn.type.name).type_class
265
265
  subselections_on_type = subselections_by_type[on_type] ||= {}
266
266
  find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
267
267
  else
@@ -35,7 +35,7 @@ module GraphQL
35
35
  @queries = queries
36
36
  @queries.each { |q| q.multiplex = self }
37
37
  @context = context
38
- @context[:dataloader] = @dataloader = @schema.dataloader_class.new
38
+ @dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
39
39
  @tracers = schema.tracers + (context[:tracers] || [])
40
40
  # Support `context: {backtrace: true}`
41
41
  if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
@@ -151,6 +151,9 @@ module GraphQL
151
151
 
152
152
  result
153
153
  end
154
+ if query.context.namespace?(:__query_result_extensions__)
155
+ query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
156
+ end
154
157
  end
155
158
 
156
159
  # use the old `query_execution_strategy` etc to run this query
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition
2
+ GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition(silence_deprecation_warning: true)
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition
2
+ GraphQL::ID_TYPE = GraphQL::Types::ID.graphql_definition(silence_deprecation_warning: true)
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition
2
+ GraphQL::INT_TYPE = GraphQL::Types::Int.graphql_definition(silence_deprecation_warning: true)
@@ -12,9 +12,25 @@ module GraphQL
12
12
  # The value which couldn't be encoded
13
13
  attr_reader :integer_value
14
14
 
15
- def initialize(value)
15
+ # @return [GraphQL::Schema::Field] The field that returned a too-big integer
16
+ attr_reader :field
17
+
18
+ # @return [Array<String, Integer>] Where the field appeared in the GraphQL response
19
+ attr_reader :path
20
+
21
+ def initialize(value, context:)
16
22
  @integer_value = value
17
- super("Integer out of bounds: #{value}. \nConsider using ID or GraphQL::Types::BigInt instead.")
23
+ @field = context[:current_field]
24
+ @path = context[:current_path]
25
+ message = "Integer out of bounds: #{value}".dup
26
+ if @path
27
+ message << " @ #{@path.join(".")}"
28
+ end
29
+ if @field
30
+ message << " (#{@field.path})"
31
+ end
32
+ message << ". Consider using ID or GraphQL::Types::BigInt instead."
33
+ super(message)
18
34
  end
19
35
  end
20
36
  end
@@ -10,7 +10,7 @@ module GraphQL
10
10
  "skipping a field. Directives provide this by describing additional information "\
11
11
  "to the executor."
12
12
  field :name, String, null: false, method: :graphql_name
13
- field :description, String, null: true
13
+ field :description, String
14
14
  field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
15
  field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
16
16
  argument :include_deprecated, Boolean, required: false, default_value: false
@@ -3,8 +3,8 @@ module GraphQL
3
3
  module Introspection
4
4
  class EntryPoints < Introspection::BaseObject
5
5
  field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false
6
- field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system", null: true do
7
- argument :name, String, required: true
6
+ field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system" do
7
+ argument :name, String
8
8
  end
9
9
 
10
10
  def __schema
@@ -7,9 +7,9 @@ module GraphQL
7
7
  "placeholder for a string or numeric value. However an Enum value is returned in "\
8
8
  "a JSON response as a string."
9
9
  field :name, String, null: false
10
- field :description, String, null: true
10
+ field :description, String
11
11
  field :is_deprecated, Boolean, null: false
12
- field :deprecation_reason, String, null: true
12
+ field :deprecation_reason, String
13
13
 
14
14
  def name
15
15
  object.graphql_name
@@ -6,13 +6,13 @@ module GraphQL
6
6
  description "Object and Interface types are described by a list of Fields, each of which has "\
7
7
  "a name, potentially a list of arguments, and a return type."
8
8
  field :name, String, null: false
9
- field :description, String, null: true
9
+ field :description, String
10
10
  field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
11
11
  argument :include_deprecated, Boolean, required: false, default_value: false
12
12
  end
13
13
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
14
14
  field :is_deprecated, Boolean, null: false
15
- field :deprecation_reason, String, null: true
15
+ field :deprecation_reason, String
16
16
 
17
17
  def is_deprecated
18
18
  !!@object.deprecation_reason
@@ -7,11 +7,11 @@ module GraphQL
7
7
  "InputObject are represented as Input Values which describe their type and "\
8
8
  "optionally a default value."
9
9
  field :name, String, null: false
10
- field :description, String, null: true
10
+ field :description, String
11
11
  field :type, GraphQL::Schema::LateBoundType.new("__Type"), null: false
12
- field :default_value, String, "A GraphQL-formatted string representing the default value for this input value.", null: true
12
+ field :default_value, String, "A GraphQL-formatted string representing the default value for this input value."
13
13
  field :is_deprecated, Boolean, null: false
14
- field :deprecation_reason, String, null: true
14
+ field :deprecation_reason, String
15
15
 
16
16
  def is_deprecated
17
17
  !!@object.deprecation_reason
@@ -23,6 +23,12 @@ module GraphQL
23
23
  if value.nil?
24
24
  'null'
25
25
  else
26
+ if (@object.type.kind.list? || (@object.type.kind.non_null? && @object.type.of_type.kind.list?)) && !value.respond_to?(:map)
27
+ # This is a bit odd -- we expect the default value to be an application-style value, so we use coerce result below.
28
+ # But coerce_result doesn't wrap single-item lists, which are valid inputs to list types.
29
+ # So, apply that wrapper here if needed.
30
+ value = [value]
31
+ end
26
32
  coerced_default_value = @object.type.coerce_result(value, @context)
27
33
  serialize_default_value(coerced_default_value, @object.type)
28
34
  end
@@ -48,7 +54,7 @@ module GraphQL
48
54
  elsif type.kind.input_object?
49
55
  "{" +
50
56
  value.map do |k, v|
51
- arg_defn = type.arguments[k]
57
+ arg_defn = type.get_argument(k, context)
52
58
  "#{k}: #{serialize_default_value(v, arg_defn.type)}"
53
59
  end.join(", ") +
54
60
  "}"
@@ -10,8 +10,8 @@ module GraphQL
10
10
 
11
11
  field :types, [GraphQL::Schema::LateBoundType.new("__Type")], "A list of all types supported by this server.", null: false
12
12
  field :query_type, GraphQL::Schema::LateBoundType.new("__Type"), "The type that query operations will be rooted at.", null: false
13
- field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at.", null: true
14
- field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at.", null: true
13
+ field :mutation_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server supports mutation, the type that mutation operations will be rooted at."
14
+ field :subscription_type, GraphQL::Schema::LateBoundType.new("__Type"), "If this server support subscription, the type that subscription operations will be rooted at."
15
15
  field :directives, [GraphQL::Schema::LateBoundType.new("__Directive")], "A list of all directives supported by this server.", null: false
16
16
 
17
17
  def types
@@ -12,20 +12,20 @@ module GraphQL
12
12
  "possible at runtime. List and NonNull types compose other types."
13
13
 
14
14
  field :kind, GraphQL::Schema::LateBoundType.new("__TypeKind"), null: false
15
- field :name, String, null: true
16
- field :description, String, null: true
17
- field :fields, [GraphQL::Schema::LateBoundType.new("__Field")], null: true do
15
+ field :name, String
16
+ field :description, String
17
+ field :fields, [GraphQL::Schema::LateBoundType.new("__Field")] do
18
18
  argument :include_deprecated, Boolean, required: false, default_value: false
19
19
  end
20
- field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")], null: true
21
- field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")], null: true
22
- field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")], null: true do
20
+ field :interfaces, [GraphQL::Schema::LateBoundType.new("__Type")]
21
+ field :possible_types, [GraphQL::Schema::LateBoundType.new("__Type")]
22
+ field :enum_values, [GraphQL::Schema::LateBoundType.new("__EnumValue")] do
23
23
  argument :include_deprecated, Boolean, required: false, default_value: false
24
24
  end
25
- field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: true do
25
+ field :input_fields, [GraphQL::Schema::LateBoundType.new("__InputValue")] do
26
26
  argument :include_deprecated, Boolean, required: false, default_value: false
27
27
  end
28
- field :of_type, GraphQL::Schema::LateBoundType.new("__Type"), null: true
28
+ field :of_type, GraphQL::Schema::LateBoundType.new("__Type")
29
29
 
30
30
  def name
31
31
  object.graphql_name
@@ -50,8 +50,8 @@ module GraphQL
50
50
  end
51
51
 
52
52
  def interfaces
53
- if @object.kind == GraphQL::TypeKinds::OBJECT
54
- @context.warden.interfaces(@object)
53
+ if @object.kind.object? || @object.kind.interface?
54
+ @context.warden.interfaces(@object).sort_by(&:graphql_name)
55
55
  else
56
56
  nil
57
57
  end
@@ -2,16 +2,12 @@
2
2
  module GraphQL
3
3
  module Language
4
4
  module BlockString
5
- if !String.method_defined?(:match?)
6
- using GraphQL::StringMatchBackport
7
- end
8
-
9
5
  # Remove leading and trailing whitespace from a block string.
10
6
  # See "Block Strings" in https://github.com/facebook/graphql/blob/master/spec/Section%202%20--%20Language.md
11
7
  def self.trim_whitespace(str)
12
8
  # Early return for the most common cases:
13
9
  if str == ""
14
- return ""
10
+ return "".dup
15
11
  elsif !(has_newline = str.include?("\n")) && !(str.start_with?(" "))
16
12
  return str
17
13
  end
@@ -59,7 +55,7 @@ module GraphQL
59
55
  end
60
56
 
61
57
  # Rebuild the string
62
- lines.size > 1 ? lines.join("\n") : (lines.first || "")
58
+ lines.size > 1 ? lines.join("\n") : (lines.first || "".dup)
63
59
  end
64
60
 
65
61
  def self.print(str, indent: '')
@@ -34,6 +34,7 @@ module GraphQL
34
34
  schema: @schema,
35
35
  context: schema_context,
36
36
  )
37
+ schema_context.warden = @warden
37
38
  end
38
39
 
39
40
  def document
@@ -87,6 +88,7 @@ module GraphQL
87
88
  def build_interface_type_node(interface_type)
88
89
  GraphQL::Language::Nodes::InterfaceTypeDefinition.new(
89
90
  name: interface_type.graphql_name,
91
+ interfaces: warden.interfaces(interface_type).sort_by(&:graphql_name).map { |type| build_type_name_node(type) },
90
92
  description: interface_type.description,
91
93
  fields: build_field_nodes(warden.fields(interface_type)),
92
94
  directives: directives(interface_type),
@@ -194,7 +196,7 @@ module GraphQL
194
196
  when "INPUT_OBJECT"
195
197
  GraphQL::Language::Nodes::InputObject.new(
196
198
  arguments: default_value.to_h.map do |arg_name, arg_value|
197
- arg_type = type.arguments.fetch(arg_name.to_s).type
199
+ arg_type = @warden.arguments(type).find { |a| a.graphql_name == arg_name.to_s }.type
198
200
  GraphQL::Language::Nodes::Argument.new(
199
201
  name: arg_name.to_s,
200
202
  value: build_default_value(arg_value, arg_type)
@@ -295,7 +297,7 @@ module GraphQL
295
297
  else
296
298
  member.directives.map do |dir|
297
299
  args = []
298
- dir.arguments.argument_values.each_value do |arg_value|
300
+ dir.arguments.argument_values.each_value do |arg_value| # rubocop:disable Development/ContextIsPassedCop -- directive instance method
299
301
  arg_defn = arg_value.definition
300
302
  if arg_defn.default_value? && arg_value.value == arg_defn.default_value
301
303
  next
@@ -3,9 +3,6 @@
3
3
  module GraphQL
4
4
  module Language
5
5
  module Lexer
6
- if !String.method_defined?(:match?)
7
- using GraphQL::StringMatchBackport
8
- end
9
6
 
10
7
  def self.tokenize(query_string)
11
8
  run_lexer(query_string)
@@ -121,10 +121,6 @@
121
121
  module GraphQL
122
122
  module Language
123
123
  module Lexer
124
- if !String.method_defined?(:match?)
125
- using GraphQL::StringMatchBackport
126
- end
127
-
128
124
  def self.tokenize(query_string)
129
125
  run_lexer(query_string)
130
126
  end
@@ -197,7 +197,16 @@ module GraphQL
197
197
  else
198
198
  module_eval <<-RUBY, __FILE__, __LINE__
199
199
  def children
200
- @children ||= (#{children_of_type.keys.map { |k| "@#{k}" }.join(" + ")}).freeze
200
+ @children ||= begin
201
+ if #{children_of_type.keys.map { |k| "@#{k}.any?" }.join(" || ")}
202
+ new_children = []
203
+ #{children_of_type.keys.map { |k| "new_children.concat(@#{k})" }.join("; ")}
204
+ new_children.freeze
205
+ new_children
206
+ else
207
+ NO_CHILDREN
208
+ end
209
+ end
201
210
  end
202
211
  RUBY
203
212
  end
@@ -467,7 +476,6 @@ module GraphQL
467
476
  end
468
477
  end
469
478
 
470
-
471
479
  # A list type definition, denoted with `[...]` (used for variable type definitions)
472
480
  class ListType < WrapperType
473
481
  end
@@ -618,6 +626,7 @@ module GraphQL
618
626
  attr_reader :description
619
627
  scalar_methods :name
620
628
  children_methods({
629
+ interfaces: GraphQL::Language::Nodes::TypeName,
621
630
  directives: GraphQL::Language::Nodes::Directive,
622
631
  fields: GraphQL::Language::Nodes::FieldDefinition,
623
632
  })
@@ -627,6 +636,7 @@ module GraphQL
627
636
  class InterfaceTypeExtension < AbstractNode
628
637
  scalar_methods :name
629
638
  children_methods({
639
+ interfaces: GraphQL::Language::Nodes::TypeName,
630
640
  directives: GraphQL::Language::Nodes::Directive,
631
641
  fields: GraphQL::Language::Nodes::FieldDefinition,
632
642
  })