graphql 1.12.6 → 1.12.11

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +1 -1
  3. data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
  4. data/lib/graphql.rb +10 -10
  5. data/lib/graphql/backtrace/table.rb +14 -2
  6. data/lib/graphql/dataloader.rb +44 -15
  7. data/lib/graphql/execution/errors.rb +109 -11
  8. data/lib/graphql/execution/execute.rb +1 -1
  9. data/lib/graphql/execution/interpreter.rb +4 -8
  10. data/lib/graphql/execution/interpreter/runtime.rb +207 -188
  11. data/lib/graphql/introspection.rb +1 -1
  12. data/lib/graphql/introspection/directive_type.rb +7 -3
  13. data/lib/graphql/introspection/schema_type.rb +1 -1
  14. data/lib/graphql/pagination/active_record_relation_connection.rb +7 -0
  15. data/lib/graphql/pagination/connections.rb +1 -1
  16. data/lib/graphql/pagination/relation_connection.rb +8 -1
  17. data/lib/graphql/query.rb +1 -3
  18. data/lib/graphql/query/null_context.rb +7 -1
  19. data/lib/graphql/query/validation_pipeline.rb +1 -1
  20. data/lib/graphql/rake_task.rb +3 -0
  21. data/lib/graphql/schema.rb +49 -237
  22. data/lib/graphql/schema/addition.rb +238 -0
  23. data/lib/graphql/schema/argument.rb +55 -36
  24. data/lib/graphql/schema/directive/transform.rb +13 -1
  25. data/lib/graphql/schema/input_object.rb +2 -2
  26. data/lib/graphql/schema/loader.rb +8 -0
  27. data/lib/graphql/schema/member/base_dsl_methods.rb +3 -15
  28. data/lib/graphql/schema/object.rb +19 -5
  29. data/lib/graphql/schema/resolver.rb +46 -24
  30. data/lib/graphql/schema/scalar.rb +3 -1
  31. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +3 -1
  32. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
  33. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +2 -1
  34. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  35. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  36. data/lib/graphql/static_validation/rules/fields_will_merge.rb +17 -8
  37. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -1
  38. data/lib/graphql/static_validation/validator.rb +5 -0
  39. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +4 -3
  40. data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
  41. data/lib/graphql/subscriptions/serialize.rb +11 -1
  42. data/lib/graphql/types/relay/base_connection.rb +4 -0
  43. data/lib/graphql/types/relay/connection_behaviors.rb +21 -10
  44. data/lib/graphql/types/relay/edge_behaviors.rb +12 -1
  45. data/lib/graphql/version.rb +1 -1
  46. metadata +3 -3
  47. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
@@ -17,7 +17,7 @@ query IntrospectionQuery {
17
17
  name
18
18
  description
19
19
  locations
20
- args {
20
+ args#{include_deprecated_args ? '(includeDeprecated: true)' : ''} {
21
21
  ...InputValue
22
22
  }
23
23
  }
@@ -12,13 +12,17 @@ module GraphQL
12
12
  field :name, String, null: false, method: :graphql_name
13
13
  field :description, String, null: true
14
14
  field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
- field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false
15
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
16
+ argument :include_deprecated, Boolean, required: false, default_value: false
17
+ end
16
18
  field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
17
19
  field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment?
18
20
  field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field?
19
21
 
20
- def args
21
- @context.warden.arguments(@object)
22
+ def args(include_deprecated:)
23
+ args = @context.warden.arguments(@object)
24
+ args = args.reject(&:deprecation_reason) unless include_deprecated
25
+ args
22
26
  end
23
27
  end
24
28
  end
@@ -31,7 +31,7 @@ module GraphQL
31
31
  end
32
32
 
33
33
  def directives
34
- context.schema.directives.values
34
+ @context.warden.directives
35
35
  end
36
36
 
37
37
  private
@@ -5,6 +5,13 @@ module GraphQL
5
5
  module Pagination
6
6
  # Customizes `RelationConnection` to work with `ActiveRecord::Relation`s.
7
7
  class ActiveRecordRelationConnection < Pagination::RelationConnection
8
+ private
9
+
10
+ def relation_larger_than(relation, size)
11
+ initial_offset = relation.offset_value || 0
12
+ relation.offset(initial_offset + size).exists?
13
+ end
14
+
8
15
  def relation_count(relation)
9
16
  int_or_hash = if relation.respond_to?(:unscope)
10
17
  relation.unscope(:order).count(:all)
@@ -79,7 +79,7 @@ module GraphQL
79
79
  context: context,
80
80
  parent: parent,
81
81
  field: field,
82
- max_page_size: field.max_page_size || context.schema.default_max_page_size,
82
+ max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
83
83
  first: arguments[:first],
84
84
  after: arguments[:after],
85
85
  last: arguments[:last],
@@ -35,7 +35,7 @@ module GraphQL
35
35
  if @nodes && @nodes.count < first
36
36
  false
37
37
  else
38
- relation_count(set_limit(sliced_nodes, first + 1)) == first + 1
38
+ relation_larger_than(sliced_nodes, first)
39
39
  end
40
40
  else
41
41
  false
@@ -53,6 +53,13 @@ module GraphQL
53
53
 
54
54
  private
55
55
 
56
+ # @param relation [Object] A database query object
57
+ # @param size [Integer] The value against which we check the relation size
58
+ # @return [Boolean] True if the number of items in this relation is larger than `size`
59
+ def relation_larger_than(relation, size)
60
+ relation_count(set_limit(relation, size + 1)) == size + 1
61
+ end
62
+
56
63
  # @param relation [Object] A database query object
57
64
  # @return [Integer, nil] The offset value, or nil if there isn't one
58
65
  def relation_offset(relation)
data/lib/graphql/query.rb CHANGED
@@ -195,9 +195,7 @@ module GraphQL
195
195
  # @return [Hash] A GraphQL response, with `"data"` and/or `"errors"` keys
196
196
  def result
197
197
  if !@executed
198
- with_prepared_ast {
199
- Execution::Multiplex.run_queries(@schema, [self], context: @context)
200
- }
198
+ Execution::Multiplex.run_queries(@schema, [self], context: @context)
201
199
  end
202
200
  @result ||= Query::Result.new(query: self, values: @result_values)
203
201
  end
@@ -9,10 +9,16 @@ module GraphQL
9
9
  def visible_type?(t); true; end
10
10
  end
11
11
 
12
+ class NullQuery
13
+ def with_error_handling
14
+ yield
15
+ end
16
+ end
17
+
12
18
  attr_reader :schema, :query, :warden, :dataloader
13
19
 
14
20
  def initialize
15
- @query = nil
21
+ @query = NullQuery.new
16
22
  @dataloader = GraphQL::Dataloader::NullDataloader.new
17
23
  @schema = GraphQL::Schema.new
18
24
  @warden = NullWarden.new(
@@ -36,7 +36,7 @@ module GraphQL
36
36
  @valid
37
37
  end
38
38
 
39
- # @return [Array<GraphQL::StaticValidation::Error >] Static validation errors for the query string
39
+ # @return [Array<GraphQL::StaticValidation::Error, GraphQL::Query::VariableValidationError>] Static validation errors for the query string
40
40
  def validation_errors
41
41
  ensure_has_validated
42
42
  @validation_errors
@@ -98,6 +98,9 @@ module GraphQL
98
98
  result = schema.public_send(method_name, only: @only, except: @except, context: context)
99
99
  dir = File.dirname(file)
100
100
  FileUtils.mkdir_p(dir)
101
+ if !result.end_with?("\n")
102
+ result += "\n"
103
+ end
101
104
  File.write(file, result)
102
105
  end
103
106
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/schema/addition"
2
3
  require "graphql/schema/base_64_encoder"
3
4
  require "graphql/schema/catchall_middleware"
4
5
  require "graphql/schema/default_parse_error"
@@ -355,23 +356,6 @@ module GraphQL
355
356
  # For forwards-compatibility with Schema classes
356
357
  alias :graphql_definition :itself
357
358
 
358
- # Validate a query string according to this schema.
359
- # @param string_or_document [String, GraphQL::Language::Nodes::Document]
360
- # @return [Array<GraphQL::StaticValidation::Error >]
361
- def validate(string_or_document, rules: nil, context: nil)
362
- doc = if string_or_document.is_a?(String)
363
- GraphQL.parse(string_or_document)
364
- else
365
- string_or_document
366
- end
367
- query = GraphQL::Query.new(self, document: doc, context: context)
368
- validator_opts = { schema: self }
369
- rules && (validator_opts[:rules] = rules)
370
- validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
371
- res = validator.validate(query, timeout: validate_timeout)
372
- res[:errors]
373
- end
374
-
375
359
  def deprecated_define(**kwargs, &block)
376
360
  super
377
361
  ensure_defined
@@ -711,7 +695,8 @@ module GraphQL
711
695
  alias :_schema_class :class
712
696
  def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
713
697
  def_delegators :_schema_class, :directive
714
- def_delegators :_schema_class, :error_handler, :rescues
698
+ def_delegators :_schema_class, :error_handler
699
+ def_delegators :_schema_class, :validate
715
700
 
716
701
 
717
702
  # Given this schema member, find the class-based definition object
@@ -861,7 +846,6 @@ module GraphQL
861
846
  def_delegators :graphql_definition,
862
847
  # Execution
863
848
  :execution_strategy_for_operation,
864
- :validate,
865
849
  # Configuration
866
850
  :metadata, :redefine,
867
851
  :id_from_object_proc, :object_from_id_proc,
@@ -989,7 +973,7 @@ module GraphQL
989
973
  schema_defn.lazy_methods.set(lazy_class, value_method)
990
974
  end
991
975
 
992
- rescues.each do |err_class, handler|
976
+ error_handler.each_rescue do |err_class, handler|
993
977
  schema_defn.rescue_from(err_class, &handler)
994
978
  end
995
979
 
@@ -1293,6 +1277,23 @@ module GraphQL
1293
1277
  end
1294
1278
  end
1295
1279
 
1280
+ # Validate a query string according to this schema.
1281
+ # @param string_or_document [String, GraphQL::Language::Nodes::Document]
1282
+ # @return [Array<GraphQL::StaticValidation::Error >]
1283
+ def validate(string_or_document, rules: nil, context: nil)
1284
+ doc = if string_or_document.is_a?(String)
1285
+ GraphQL.parse(string_or_document)
1286
+ else
1287
+ string_or_document
1288
+ end
1289
+ query = GraphQL::Query.new(self, document: doc, context: context)
1290
+ validator_opts = { schema: self }
1291
+ rules && (validator_opts[:rules] = rules)
1292
+ validator = GraphQL::StaticValidation::Validator.new(**validator_opts)
1293
+ res = validator.validate(query, timeout: validate_timeout)
1294
+ res[:errors]
1295
+ end
1296
+
1296
1297
  attr_writer :max_complexity
1297
1298
 
1298
1299
  def max_complexity(max_complexity = nil)
@@ -1424,7 +1425,7 @@ module GraphQL
1424
1425
 
1425
1426
  def rescue_from(*err_classes, &handler_block)
1426
1427
  err_classes.each do |err_class|
1427
- own_rescues[err_class] = handler_block
1428
+ error_handler.rescue_from(err_class, handler_block)
1428
1429
  end
1429
1430
  end
1430
1431
 
@@ -1468,10 +1469,6 @@ module GraphQL
1468
1469
  super
1469
1470
  end
1470
1471
 
1471
- def rescues
1472
- find_inherited_value(:rescues, EMPTY_HASH).merge(own_rescues)
1473
- end
1474
-
1475
1472
  def object_from_id(node_id, ctx)
1476
1473
  raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(node_id, ctx) must be implemented to load by ID (tried to load from id `#{node_id}`)"
1477
1474
  end
@@ -1548,15 +1545,10 @@ module GraphQL
1548
1545
  def parse_error(parse_err, ctx)
1549
1546
  ctx.errors.push(parse_err)
1550
1547
  end
1551
- attr_writer :error_handler
1552
1548
 
1553
- # @return [GraphQL::Execution::Errors, Class<GraphQL::Execution::Errors::NullErrorHandler>]
1549
+ # @return [GraphQL::Execution::Errors]
1554
1550
  def error_handler
1555
- if defined?(@error_handler)
1556
- @error_handler
1557
- else
1558
- find_inherited_value(:error_handler, GraphQL::Execution::Errors::NullErrorHandler)
1559
- end
1551
+ @error_handler ||= GraphQL::Execution::Errors.new(self)
1560
1552
  end
1561
1553
 
1562
1554
  def lazy_resolve(lazy_class, value_method)
@@ -1591,10 +1583,7 @@ module GraphQL
1591
1583
  # @param new_directive [Class]
1592
1584
  # @return void
1593
1585
  def directive(new_directive)
1594
- own_directives[new_directive.graphql_name] ||= begin
1595
- add_type_and_traverse(new_directive, root: false)
1596
- new_directive
1597
- end
1586
+ add_type_and_traverse(new_directive, root: false)
1598
1587
  end
1599
1588
 
1600
1589
  def default_directives
@@ -1718,6 +1707,30 @@ module GraphQL
1718
1707
 
1719
1708
  private
1720
1709
 
1710
+ # @param t [Module, Array<Module>]
1711
+ # @return [void]
1712
+ def add_type_and_traverse(t, root:)
1713
+ if root
1714
+ @root_types ||= []
1715
+ @root_types << t
1716
+ end
1717
+ new_types = Array(t)
1718
+ addition = Schema::Addition.new(schema: self, own_types: own_types, new_types: new_types)
1719
+ own_types.merge!(addition.types)
1720
+ own_possible_types.merge!(addition.possible_types) { |key, old_val, new_val| old_val + new_val }
1721
+ own_union_memberships.merge!(addition.union_memberships)
1722
+
1723
+ addition.references.each { |thing, pointers|
1724
+ pointers.each { |pointer| references_to(thing, from: pointer) }
1725
+ }
1726
+
1727
+ addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
1728
+
1729
+ addition.arguments_with_default_values.each do |arg|
1730
+ arg.validate_default_value
1731
+ end
1732
+ end
1733
+
1721
1734
  def lazy_methods
1722
1735
  if !defined?(@lazy_methods)
1723
1736
  if inherited_map = find_inherited_value(:lazy_methods)
@@ -1744,10 +1757,6 @@ module GraphQL
1744
1757
  @own_plugins ||= []
1745
1758
  end
1746
1759
 
1747
- def own_rescues
1748
- @own_rescues ||= {}
1749
- end
1750
-
1751
1760
  def own_orphan_types
1752
1761
  @own_orphan_types ||= []
1753
1762
  end
@@ -1787,202 +1796,6 @@ module GraphQL
1787
1796
  def own_multiplex_analyzers
1788
1797
  @own_multiplex_analyzers ||= []
1789
1798
  end
1790
-
1791
- # @param t [Module, Array<Module>]
1792
- # @return [void]
1793
- def add_type_and_traverse(t, root:)
1794
- if root
1795
- @root_types ||= []
1796
- @root_types << t
1797
- end
1798
- late_types = []
1799
- new_types = Array(t)
1800
- new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
1801
- missed_late_types = 0
1802
- while (late_type_vals = late_types.shift)
1803
- type_owner, lt = late_type_vals
1804
- if lt.is_a?(String)
1805
- type = Member::BuildType.constantize(lt)
1806
- # Reset the counter, since we might succeed next go-round
1807
- missed_late_types = 0
1808
- update_type_owner(type_owner, type)
1809
- add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
1810
- elsif lt.is_a?(LateBoundType)
1811
- if (type = get_type(lt.graphql_name))
1812
- # Reset the counter, since we might succeed next go-round
1813
- missed_late_types = 0
1814
- update_type_owner(type_owner, type)
1815
- add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
1816
- else
1817
- missed_late_types += 1
1818
- # Add it back to the list, maybe we'll be able to resolve it later.
1819
- late_types << [type_owner, lt]
1820
- if missed_late_types == late_types.size
1821
- # We've looked at all of them and haven't resolved one.
1822
- raise UnresolvedLateBoundTypeError.new(type: lt)
1823
- else
1824
- # Try the next one
1825
- end
1826
- end
1827
- else
1828
- raise ArgumentError, "Unexpected late type: #{lt.inspect}"
1829
- end
1830
- end
1831
- nil
1832
- end
1833
-
1834
- def update_type_owner(owner, type)
1835
- case owner
1836
- when Class
1837
- if owner.kind.union?
1838
- # It's a union with possible_types
1839
- # Replace the item by class name
1840
- owner.assign_type_membership_object_type(type)
1841
- own_possible_types[owner.graphql_name] = owner.possible_types
1842
- elsif type.kind.interface? && owner.kind.object?
1843
- new_interfaces = []
1844
- owner.interfaces.each do |int_t|
1845
- if int_t.is_a?(String) && int_t == type.graphql_name
1846
- new_interfaces << type
1847
- elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
1848
- new_interfaces << type
1849
- else
1850
- # Don't re-add proper interface definitions,
1851
- # they were probably already added, maybe with options.
1852
- end
1853
- end
1854
- owner.implements(*new_interfaces)
1855
- new_interfaces.each do |int|
1856
- pt = own_possible_types[int.graphql_name] ||= []
1857
- if !pt.include?(owner)
1858
- pt << owner
1859
- end
1860
- end
1861
- end
1862
-
1863
- when nil
1864
- # It's a root type
1865
- own_types[type.graphql_name] = type
1866
- when GraphQL::Schema::Field, GraphQL::Schema::Argument
1867
- orig_type = owner.type
1868
- # Apply list/non-null wrapper as needed
1869
- if orig_type.respond_to?(:of_type)
1870
- transforms = []
1871
- while (orig_type.respond_to?(:of_type))
1872
- if orig_type.kind.non_null?
1873
- transforms << :to_non_null_type
1874
- elsif orig_type.kind.list?
1875
- transforms << :to_list_type
1876
- else
1877
- raise "Invariant: :of_type isn't non-null or list"
1878
- end
1879
- orig_type = orig_type.of_type
1880
- end
1881
- transforms.reverse_each { |t| type = type.public_send(t) }
1882
- end
1883
- owner.type = type
1884
- else
1885
- raise "Unexpected update: #{owner.inspect} #{type.inspect}"
1886
- end
1887
- end
1888
-
1889
- def add_type(type, owner:, late_types:, path:)
1890
- if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
1891
- type_class = type.metadata[:type_class]
1892
- if type_class.nil?
1893
- raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
1894
- else
1895
- type = type_class
1896
- end
1897
- elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
1898
- late_types << [owner, type]
1899
- return
1900
- end
1901
-
1902
- if owner.is_a?(Class) && owner < GraphQL::Schema::Union
1903
- um = own_union_memberships[type.graphql_name] ||= []
1904
- um << owner
1905
- end
1906
-
1907
- if (prev_type = own_types[type.graphql_name])
1908
- if prev_type != type
1909
- raise DuplicateTypeNamesError.new(
1910
- type_name: type.graphql_name,
1911
- first_definition: prev_type,
1912
- second_definition: type,
1913
- path: path,
1914
- )
1915
- else
1916
- # This type was already added
1917
- end
1918
- elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
1919
- type.arguments.each do |name, arg|
1920
- arg_type = arg.type.unwrap
1921
- references_to(arg_type, from: arg)
1922
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
1923
- end
1924
- else
1925
- own_types[type.graphql_name] = type
1926
- add_directives_from(type)
1927
- if type.kind.fields?
1928
- type.fields.each do |name, field|
1929
- field_type = field.type.unwrap
1930
- references_to(field_type, from: field)
1931
- field_path = path + [name]
1932
- add_type(field_type, owner: field, late_types: late_types, path: field_path)
1933
- add_directives_from(field)
1934
- field.arguments.each do |arg_name, arg|
1935
- add_directives_from(arg)
1936
- arg_type = arg.type.unwrap
1937
- references_to(arg_type, from: arg)
1938
- add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
1939
- end
1940
- end
1941
- end
1942
- if type.kind.input_object?
1943
- type.arguments.each do |arg_name, arg|
1944
- add_directives_from(arg)
1945
- arg_type = arg.type.unwrap
1946
- references_to(arg_type, from: arg)
1947
- add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
1948
- end
1949
- end
1950
- if type.kind.union?
1951
- own_possible_types[type.graphql_name] = type.possible_types
1952
- type.possible_types.each do |t|
1953
- add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
1954
- end
1955
- end
1956
- if type.kind.interface?
1957
- type.orphan_types.each do |t|
1958
- add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
1959
- end
1960
- end
1961
- if type.kind.object?
1962
- own_possible_types[type.graphql_name] = [type]
1963
- type.interface_type_memberships.each do |interface_type_membership|
1964
- case interface_type_membership
1965
- when Schema::TypeMembership
1966
- interface_type = interface_type_membership.abstract_type
1967
- # We can get these now; we'll have to get late-bound types later
1968
- if interface_type.is_a?(Module)
1969
- implementers = own_possible_types[interface_type.graphql_name] ||= []
1970
- implementers << type
1971
- end
1972
- when String, Schema::LateBoundType
1973
- interface_type = interface_type_membership
1974
- else
1975
- raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
1976
- end
1977
- add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
1978
- end
1979
- end
1980
- end
1981
- end
1982
-
1983
- def add_directives_from(owner)
1984
- owner.directives.each { |dir| directive(dir.class) }
1985
- end
1986
1799
  end
1987
1800
 
1988
1801
  def dataloader_class
@@ -1990,7 +1803,6 @@ module GraphQL
1990
1803
  end
1991
1804
 
1992
1805
  # Install these here so that subclasses will also install it.
1993
- use(GraphQL::Execution::Errors)
1994
1806
  use(GraphQL::Pagination::Connections)
1995
1807
 
1996
1808
  protected